1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Dejan Jovanovic, Morgan Deters |
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 |
|
* The theory engine. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
#ifndef CVC5__THEORY_ENGINE_H |
19 |
|
#define CVC5__THEORY_ENGINE_H |
20 |
|
|
21 |
|
#include <memory> |
22 |
|
#include <vector> |
23 |
|
|
24 |
|
#include "base/check.h" |
25 |
|
#include "context/cdhashmap.h" |
26 |
|
#include "expr/node.h" |
27 |
|
#include "options/theory_options.h" |
28 |
|
#include "theory/atom_requests.h" |
29 |
|
#include "theory/engine_output_channel.h" |
30 |
|
#include "theory/interrupted.h" |
31 |
|
#include "theory/rewriter.h" |
32 |
|
#include "theory/sort_inference.h" |
33 |
|
#include "theory/theory.h" |
34 |
|
#include "theory/theory_preprocessor.h" |
35 |
|
#include "theory/trust_node.h" |
36 |
|
#include "theory/trust_substitutions.h" |
37 |
|
#include "theory/uf/equality_engine.h" |
38 |
|
#include "theory/valuation.h" |
39 |
|
#include "util/hash.h" |
40 |
|
#include "util/statistics_stats.h" |
41 |
|
#include "util/unsafe_interrupt_exception.h" |
42 |
|
|
43 |
|
namespace cvc5 { |
44 |
|
|
45 |
|
class Env; |
46 |
|
class ResourceManager; |
47 |
|
class OutputManager; |
48 |
|
class TheoryEngineProofGenerator; |
49 |
|
class ProofChecker; |
50 |
|
|
51 |
|
/** |
52 |
|
* A pair of a theory and a node. This is used to mark the flow of |
53 |
|
* propagations between theories. |
54 |
|
*/ |
55 |
381623343 |
struct NodeTheoryPair { |
56 |
|
Node d_node; |
57 |
|
theory::TheoryId d_theory; |
58 |
|
size_t d_timestamp; |
59 |
55268643 |
NodeTheoryPair(TNode n, theory::TheoryId t, size_t ts = 0) |
60 |
55268643 |
: d_node(n), d_theory(t), d_timestamp(ts) |
61 |
|
{ |
62 |
55268643 |
} |
63 |
37650960 |
NodeTheoryPair() : d_theory(theory::THEORY_LAST), d_timestamp() {} |
64 |
|
// Comparison doesn't take into account the timestamp |
65 |
66258393 |
bool operator == (const NodeTheoryPair& pair) const { |
66 |
66258393 |
return d_node == pair.d_node && d_theory == pair.d_theory; |
67 |
|
} |
68 |
|
};/* struct NodeTheoryPair */ |
69 |
|
|
70 |
|
struct NodeTheoryPairHashFunction { |
71 |
|
std::hash<Node> hashFunction; |
72 |
|
// Hash doesn't take into account the timestamp |
73 |
122848420 |
size_t operator()(const NodeTheoryPair& pair) const { |
74 |
122848420 |
uint64_t hash = fnv1a::fnv1a_64(std::hash<Node>()(pair.d_node)); |
75 |
122848420 |
return static_cast<size_t>(fnv1a::fnv1a_64(pair.d_theory, hash)); |
76 |
|
} |
77 |
|
};/* struct NodeTheoryPairHashFunction */ |
78 |
|
|
79 |
|
|
80 |
|
/* Forward declarations */ |
81 |
|
namespace theory { |
82 |
|
class TheoryModel; |
83 |
|
class CombinationEngine; |
84 |
|
class SharedSolver; |
85 |
|
class DecisionManager; |
86 |
|
class RelevanceManager; |
87 |
|
|
88 |
|
} // namespace theory |
89 |
|
|
90 |
|
namespace prop { |
91 |
|
class PropEngine; |
92 |
|
} |
93 |
|
|
94 |
|
/** |
95 |
|
* This is essentially an abstraction for a collection of theories. A |
96 |
|
* TheoryEngine provides services to a PropEngine, making various |
97 |
|
* T-solvers look like a single unit to the propositional part of |
98 |
|
* cvc5. |
99 |
|
*/ |
100 |
|
class TheoryEngine { |
101 |
|
|
102 |
|
/** Shared terms database can use the internals notify the theories */ |
103 |
|
friend class SharedTermsDatabase; |
104 |
|
friend class theory::EngineOutputChannel; |
105 |
|
friend class theory::CombinationEngine; |
106 |
|
friend class theory::SharedSolver; |
107 |
|
|
108 |
|
/** Associated PropEngine engine */ |
109 |
|
prop::PropEngine* d_propEngine; |
110 |
|
|
111 |
|
/** |
112 |
|
* Reference to the environment. |
113 |
|
*/ |
114 |
|
Env& d_env; |
115 |
|
|
116 |
|
/** |
117 |
|
* A table of from theory IDs to theory pointers. Never use this table |
118 |
|
* directly, use theoryOf() instead. |
119 |
|
*/ |
120 |
|
theory::Theory* d_theoryTable[theory::THEORY_LAST]; |
121 |
|
|
122 |
|
/** |
123 |
|
* A collection of theories that are "active" for the current run. |
124 |
|
* This set is provided by the user (as a logic string, say, in SMT-LIBv2 |
125 |
|
* format input), or else by default it's all-inclusive. This is important |
126 |
|
* because we can optimize for single-theory runs (no sharing), can reduce |
127 |
|
* the cost of walking the DAG on registration, etc. |
128 |
|
*/ |
129 |
|
const LogicInfo& d_logicInfo; |
130 |
|
|
131 |
|
/** The separation logic location and data types */ |
132 |
|
TypeNode d_sepLocType; |
133 |
|
TypeNode d_sepDataType; |
134 |
|
|
135 |
|
/** Reference to the output manager of the smt engine */ |
136 |
|
OutputManager& d_outMgr; |
137 |
|
|
138 |
|
//--------------------------------- new proofs |
139 |
|
/** Proof node manager used by this theory engine, if proofs are enabled */ |
140 |
|
ProofNodeManager* d_pnm; |
141 |
|
/** The lazy proof object |
142 |
|
* |
143 |
|
* This stores instructions for how to construct proofs for all theory lemmas. |
144 |
|
*/ |
145 |
|
std::shared_ptr<LazyCDProof> d_lazyProof; |
146 |
|
/** The proof generator */ |
147 |
|
std::shared_ptr<TheoryEngineProofGenerator> d_tepg; |
148 |
|
//--------------------------------- end new proofs |
149 |
|
/** The combination manager we are using */ |
150 |
|
std::unique_ptr<theory::CombinationEngine> d_tc; |
151 |
|
/** The shared solver of the above combination engine. */ |
152 |
|
theory::SharedSolver* d_sharedSolver; |
153 |
|
/** The quantifiers engine, which is owned by the quantifiers theory */ |
154 |
|
theory::QuantifiersEngine* d_quantEngine; |
155 |
|
/** |
156 |
|
* The decision manager |
157 |
|
*/ |
158 |
|
std::unique_ptr<theory::DecisionManager> d_decManager; |
159 |
|
/** The relevance manager */ |
160 |
|
std::unique_ptr<theory::RelevanceManager> d_relManager; |
161 |
|
/** |
162 |
|
* An empty set of relevant assertions, which is returned as a dummy value for |
163 |
|
* getRelevantAssertions when relevance is disabled. |
164 |
|
*/ |
165 |
|
std::unordered_set<TNode> d_emptyRelevantSet; |
166 |
|
|
167 |
|
/** are we in eager model building mode? (see setEagerModelBuilding). */ |
168 |
|
bool d_eager_model_building; |
169 |
|
|
170 |
|
/** |
171 |
|
* Output channels for individual theories. |
172 |
|
*/ |
173 |
|
theory::EngineOutputChannel* d_theoryOut[theory::THEORY_LAST]; |
174 |
|
|
175 |
|
/** |
176 |
|
* Are we in conflict. |
177 |
|
*/ |
178 |
|
context::CDO<bool> d_inConflict; |
179 |
|
|
180 |
|
/** |
181 |
|
* Are we in "SAT mode"? In this state, the user can query for the model. |
182 |
|
* This corresponds to the state in Figure 4.1, page 52 of the SMT-LIB |
183 |
|
* standard, version 2.6. |
184 |
|
*/ |
185 |
|
bool d_inSatMode; |
186 |
|
|
187 |
|
/** |
188 |
|
* Called by the theories to notify of a conflict. |
189 |
|
* |
190 |
|
* @param conflict The trust node containing the conflict and its proof |
191 |
|
* generator (if it exists), |
192 |
|
* @param theoryId The theory that sent the conflict |
193 |
|
*/ |
194 |
|
void conflict(theory::TrustNode conflict, theory::TheoryId theoryId); |
195 |
|
|
196 |
|
/** |
197 |
|
* Debugging flag to ensure that shutdown() is called before the |
198 |
|
* destructor. |
199 |
|
*/ |
200 |
|
bool d_hasShutDown; |
201 |
|
|
202 |
|
/** |
203 |
|
* True if a theory has notified us of incompleteness (at this |
204 |
|
* context level or below). |
205 |
|
*/ |
206 |
|
context::CDO<bool> d_incomplete; |
207 |
|
/** The theory and identifier that (most recently) set incomplete */ |
208 |
|
context::CDO<theory::TheoryId> d_incompleteTheory; |
209 |
|
context::CDO<theory::IncompleteId> d_incompleteId; |
210 |
|
|
211 |
|
/** |
212 |
|
* Called by the theories to notify that the current branch is incomplete. |
213 |
|
*/ |
214 |
|
void setIncomplete(theory::TheoryId theory, theory::IncompleteId id); |
215 |
|
|
216 |
|
/** |
217 |
|
* Mapping of propagations from recievers to senders. |
218 |
|
*/ |
219 |
|
typedef context::CDHashMap<NodeTheoryPair, NodeTheoryPair, NodeTheoryPairHashFunction> PropagationMap; |
220 |
|
PropagationMap d_propagationMap; |
221 |
|
|
222 |
|
/** |
223 |
|
* Timestamp of propagations |
224 |
|
*/ |
225 |
|
context::CDO<size_t> d_propagationMapTimestamp; |
226 |
|
|
227 |
|
/** |
228 |
|
* Literals that are propagated by the theory. Note that these are TNodes. |
229 |
|
* The theory can only propagate nodes that have an assigned literal in the |
230 |
|
* SAT solver and are hence referenced in the SAT solver. |
231 |
|
*/ |
232 |
|
context::CDList<TNode> d_propagatedLiterals; |
233 |
|
|
234 |
|
/** |
235 |
|
* The index of the next literal to be propagated by a theory. |
236 |
|
*/ |
237 |
|
context::CDO<unsigned> d_propagatedLiteralsIndex; |
238 |
|
|
239 |
|
/** |
240 |
|
* Called by the output channel to propagate literals and facts |
241 |
|
* @return false if immediate conflict |
242 |
|
*/ |
243 |
|
bool propagate(TNode literal, theory::TheoryId theory); |
244 |
|
|
245 |
|
/** |
246 |
|
* Internal method to call the propagation routines and collect the |
247 |
|
* propagated literals. |
248 |
|
*/ |
249 |
|
void propagate(theory::Theory::Effort effort); |
250 |
|
|
251 |
|
/** |
252 |
|
* A variable to mark if we added any lemmas. |
253 |
|
*/ |
254 |
|
bool d_lemmasAdded; |
255 |
|
|
256 |
|
/** |
257 |
|
* A variable to mark if the OutputChannel was "used" by any theory |
258 |
|
* since the start of the last check. If it has been, we require |
259 |
|
* a FULL_EFFORT check before exiting and reporting SAT. |
260 |
|
* |
261 |
|
* See the documentation for the needCheck() function, below. |
262 |
|
*/ |
263 |
|
bool d_outputChannelUsed; |
264 |
|
|
265 |
|
/** Atom requests from lemmas */ |
266 |
|
AtomRequests d_atomRequests; |
267 |
|
|
268 |
|
/** |
269 |
|
* Adds a new lemma, returning its status. |
270 |
|
* @param node the lemma |
271 |
|
* @param p the properties of the lemma. |
272 |
|
* @param atomsTo the theory that atoms of the lemma should be sent to |
273 |
|
* @param from the theory that sent the lemma |
274 |
|
*/ |
275 |
|
void lemma(theory::TrustNode node, |
276 |
|
theory::LemmaProperty p, |
277 |
|
theory::TheoryId atomsTo = theory::THEORY_LAST, |
278 |
|
theory::TheoryId from = theory::THEORY_LAST); |
279 |
|
|
280 |
|
/** Enusre that the given atoms are send to the given theory */ |
281 |
|
void ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId theory); |
282 |
|
|
283 |
|
/** sort inference module */ |
284 |
|
std::unique_ptr<theory::SortInference> d_sortInfer; |
285 |
|
|
286 |
|
/** Time spent in theory combination */ |
287 |
|
TimerStat d_combineTheoriesTime; |
288 |
|
|
289 |
|
Node d_true; |
290 |
|
Node d_false; |
291 |
|
|
292 |
|
/** Whether we were just interrupted (or not) */ |
293 |
|
bool d_interrupted; |
294 |
|
|
295 |
|
public: |
296 |
|
/** Constructs a theory engine */ |
297 |
|
TheoryEngine(Env& env, OutputManager& outMgr, ProofNodeManager* pnm); |
298 |
|
|
299 |
|
/** Destroys a theory engine */ |
300 |
|
~TheoryEngine(); |
301 |
|
|
302 |
|
void interrupt(); |
303 |
|
|
304 |
|
/** "Spend" a resource during a search or preprocessing.*/ |
305 |
|
void spendResource(Resource r); |
306 |
|
|
307 |
|
/** |
308 |
|
* Adds a theory. Only one theory per TheoryId can be present, so if |
309 |
|
* there is another theory it will be deleted. |
310 |
|
*/ |
311 |
|
template <class TheoryClass> |
312 |
123003 |
inline void addTheory(theory::TheoryId theoryId) |
313 |
|
{ |
314 |
123003 |
Assert(d_theoryTable[theoryId] == NULL && d_theoryOut[theoryId] == NULL); |
315 |
123003 |
d_theoryOut[theoryId] = new theory::EngineOutputChannel(this, theoryId); |
316 |
369009 |
d_theoryTable[theoryId] = new TheoryClass(getSatContext(), |
317 |
123003 |
getUserContext(), |
318 |
123003 |
*d_theoryOut[theoryId], |
319 |
|
theory::Valuation(this), |
320 |
|
d_logicInfo, |
321 |
|
d_pnm); |
322 |
369009 |
theory::Rewriter::registerTheoryRewriter( |
323 |
369009 |
theoryId, d_theoryTable[theoryId]->getTheoryRewriter()); |
324 |
123003 |
} |
325 |
|
|
326 |
|
/** Register theory proof rule checkers to the given proof checker */ |
327 |
|
void initializeProofChecker(ProofChecker* pc); |
328 |
|
|
329 |
9494 |
void setPropEngine(prop::PropEngine* propEngine) |
330 |
|
{ |
331 |
9494 |
d_propEngine = propEngine; |
332 |
9494 |
} |
333 |
|
|
334 |
|
/** |
335 |
|
* Called when all initialization of options/logic is done, after theory |
336 |
|
* objects have been created. |
337 |
|
* |
338 |
|
* This initializes the quantifiers engine, the "official" equality engines |
339 |
|
* of each theory as required, and the model and model builder utilities. |
340 |
|
*/ |
341 |
|
void finishInit(); |
342 |
|
|
343 |
|
/** |
344 |
|
* Get a pointer to the underlying propositional engine. |
345 |
|
*/ |
346 |
3090550 |
inline prop::PropEngine* getPropEngine() const { |
347 |
3090550 |
return d_propEngine; |
348 |
|
} |
349 |
|
|
350 |
|
/** Get the proof node manager */ |
351 |
|
ProofNodeManager* getProofNodeManager() const; |
352 |
|
|
353 |
|
/** |
354 |
|
* Get a pointer to the underlying sat context. |
355 |
|
*/ |
356 |
|
context::Context* getSatContext() const; |
357 |
|
|
358 |
|
/** |
359 |
|
* Get a pointer to the underlying user context. |
360 |
|
*/ |
361 |
|
context::UserContext* getUserContext() const; |
362 |
|
|
363 |
|
/** |
364 |
|
* Get a pointer to the underlying quantifiers engine. |
365 |
|
*/ |
366 |
13226 |
theory::QuantifiersEngine* getQuantifiersEngine() const { |
367 |
13226 |
return d_quantEngine; |
368 |
|
} |
369 |
|
/** |
370 |
|
* Get a pointer to the underlying decision manager. |
371 |
|
*/ |
372 |
|
theory::DecisionManager* getDecisionManager() const |
373 |
|
{ |
374 |
|
return d_decManager.get(); |
375 |
|
} |
376 |
|
|
377 |
|
private: |
378 |
|
/** |
379 |
|
* Queue of nodes for pre-registration. |
380 |
|
*/ |
381 |
|
std::queue<TNode> d_preregisterQueue; |
382 |
|
|
383 |
|
/** |
384 |
|
* Boolean flag denoting we are in pre-registration. |
385 |
|
*/ |
386 |
|
bool d_inPreregister; |
387 |
|
|
388 |
|
/** |
389 |
|
* Did the theories get any new facts since the last time we called |
390 |
|
* check() |
391 |
|
*/ |
392 |
|
context::CDO<bool> d_factsAsserted; |
393 |
|
|
394 |
|
/** |
395 |
|
* Assert the formula to the given theory. |
396 |
|
* @param assertion the assertion to send (not necesserily normalized) |
397 |
|
* @param original the assertion as it was sent in from the propagating theory |
398 |
|
* @param toTheoryId the theory to assert to |
399 |
|
* @param fromTheoryId the theory that sent it |
400 |
|
*/ |
401 |
|
void assertToTheory(TNode assertion, TNode originalAssertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId); |
402 |
|
|
403 |
|
/** |
404 |
|
* Marks a theory propagation from a theory to a theory where a |
405 |
|
* theory could be the THEORY_SAT_SOLVER for literals coming from |
406 |
|
* or being propagated to the SAT solver. If the receiving theory |
407 |
|
* already recieved the literal, the method returns false, otherwise |
408 |
|
* it returns true. |
409 |
|
* |
410 |
|
* @param assertion the normalized assertion being sent |
411 |
|
* @param originalAssertion the actual assertion that was sent |
412 |
|
* @param toTheoryId the theory that is on the receiving end |
413 |
|
* @param fromTheoryId the theory that sent the assertion |
414 |
|
* @return true if a new assertion, false if theory already got it |
415 |
|
*/ |
416 |
|
bool markPropagation(TNode assertion, TNode originalAssertions, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId); |
417 |
|
|
418 |
|
/** |
419 |
|
* Computes the explanation by traversing the propagation graph and |
420 |
|
* asking relevant theories to explain the propagations. Initially |
421 |
|
* the explanation vector should contain only the element (node, theory) |
422 |
|
* where the node is the one to be explained, and the theory is the |
423 |
|
* theory that sent the literal. |
424 |
|
*/ |
425 |
|
theory::TrustNode getExplanation( |
426 |
|
std::vector<NodeTheoryPair>& explanationVector); |
427 |
|
|
428 |
|
/** Are proofs enabled? */ |
429 |
|
bool isProofEnabled() const; |
430 |
|
|
431 |
|
public: |
432 |
|
/** |
433 |
|
* Preprocess rewrite equality, called by the preprocessor to rewrite |
434 |
|
* equalities appearing in the input. |
435 |
|
*/ |
436 |
|
theory::TrustNode ppRewriteEquality(TNode eq); |
437 |
|
/** Notify (preprocessed) assertions. */ |
438 |
|
void notifyPreprocessedAssertions(const std::vector<Node>& assertions); |
439 |
|
|
440 |
|
/** Return whether or not we are incomplete (in the current context). */ |
441 |
6993 |
inline bool isIncomplete() const { return d_incomplete; } |
442 |
|
|
443 |
|
/** |
444 |
|
* Returns true if we need another round of checking. If this |
445 |
|
* returns true, check(FULL_EFFORT) _must_ be called by the |
446 |
|
* propositional layer before reporting SAT. |
447 |
|
* |
448 |
|
* This is especially necessary for incomplete theories that lazily |
449 |
|
* output some lemmas on FULL_EFFORT check (e.g. quantifier reasoning |
450 |
|
* outputing quantifier instantiations). In such a case, a lemma can |
451 |
|
* be asserted that is simplified away (perhaps it's already true). |
452 |
|
* However, we must maintain the invariant that, if a theory uses the |
453 |
|
* OutputChannel, it implicitly requests that another check(FULL_EFFORT) |
454 |
|
* be performed before exit, even if no new facts are on its fact queue, |
455 |
|
* as it might decide to further instantiate some lemmas, precluding |
456 |
|
* a SAT response. |
457 |
|
*/ |
458 |
3537589 |
inline bool needCheck() const { |
459 |
3537589 |
return d_outputChannelUsed || d_lemmasAdded; |
460 |
|
} |
461 |
|
/** |
462 |
|
* Is the literal lit (possibly) critical for satisfying the input formula in |
463 |
|
* the current context? This call is applicable only during collectModelInfo |
464 |
|
* or during LAST_CALL effort. |
465 |
|
*/ |
466 |
|
bool isRelevant(Node lit) const; |
467 |
|
/** |
468 |
|
* This is called at shutdown time by the SmtEngine, just before |
469 |
|
* destruction. It is important because there are destruction |
470 |
|
* ordering issues between PropEngine and Theory. |
471 |
|
*/ |
472 |
|
void shutdown(); |
473 |
|
|
474 |
|
/** |
475 |
|
* Solve the given literal with a theory that owns it. The proof of tliteral |
476 |
|
* is carried in the trust node. The proof added to substitutionOut should |
477 |
|
* take this proof into account (when proofs are enabled). |
478 |
|
*/ |
479 |
|
theory::Theory::PPAssertStatus solve( |
480 |
|
theory::TrustNode tliteral, |
481 |
|
theory::TrustSubstitutionMap& substitutionOut); |
482 |
|
|
483 |
|
/** |
484 |
|
* Preregister a Theory atom with the responsible theory (or |
485 |
|
* theories). |
486 |
|
*/ |
487 |
|
void preRegister(TNode preprocessed); |
488 |
|
|
489 |
|
/** |
490 |
|
* Assert the formula to the appropriate theory. |
491 |
|
* @param node the assertion |
492 |
|
*/ |
493 |
|
void assertFact(TNode node); |
494 |
|
|
495 |
|
/** |
496 |
|
* Check all (currently-active) theories for conflicts. |
497 |
|
* @param effort the effort level to use |
498 |
|
*/ |
499 |
|
void check(theory::Theory::Effort effort); |
500 |
|
|
501 |
|
/** |
502 |
|
* Calls ppStaticLearn() on all theories, accumulating their |
503 |
|
* combined contributions in the "learned" builder. |
504 |
|
*/ |
505 |
|
void ppStaticLearn(TNode in, NodeBuilder& learned); |
506 |
|
|
507 |
|
/** |
508 |
|
* Calls presolve() on all theories and returns true |
509 |
|
* if one of the theories discovers a conflict. |
510 |
|
*/ |
511 |
|
bool presolve(); |
512 |
|
|
513 |
|
/** |
514 |
|
* Calls postsolve() on all theories. |
515 |
|
*/ |
516 |
|
void postsolve(); |
517 |
|
|
518 |
|
/** |
519 |
|
* Calls notifyRestart() on all active theories. |
520 |
|
*/ |
521 |
|
void notifyRestart(); |
522 |
|
|
523 |
9447136 |
void getPropagatedLiterals(std::vector<TNode>& literals) { |
524 |
15818528 |
for (; d_propagatedLiteralsIndex < d_propagatedLiterals.size(); d_propagatedLiteralsIndex = d_propagatedLiteralsIndex + 1) { |
525 |
6371392 |
Debug("getPropagatedLiterals") << "TheoryEngine::getPropagatedLiterals: propagating: " << d_propagatedLiterals[d_propagatedLiteralsIndex] << std::endl; |
526 |
6371392 |
literals.push_back(d_propagatedLiterals[d_propagatedLiteralsIndex]); |
527 |
|
} |
528 |
3075744 |
} |
529 |
|
|
530 |
|
/** |
531 |
|
* Returns the next decision request, or null if none exist. The next |
532 |
|
* decision request is a literal that this theory engine prefers the SAT |
533 |
|
* solver to make as its next decision. Decision requests are managed by |
534 |
|
* the decision manager d_decManager. |
535 |
|
*/ |
536 |
|
Node getNextDecisionRequest(); |
537 |
|
|
538 |
|
bool properConflict(TNode conflict) const; |
539 |
|
|
540 |
|
/** |
541 |
|
* Returns an explanation of the node propagated to the SAT solver. |
542 |
|
*/ |
543 |
|
theory::TrustNode getExplanation(TNode node); |
544 |
|
|
545 |
|
/** |
546 |
|
* Get the pointer to the model object used by this theory engine. |
547 |
|
*/ |
548 |
|
theory::TheoryModel* getModel(); |
549 |
|
/** |
550 |
|
* Get the current model for the current set of assertions. This method |
551 |
|
* should only be called immediately after a satisfiable or unknown |
552 |
|
* response to a check-sat call, and only if produceModels is true. |
553 |
|
* |
554 |
|
* If the model is not already built, this will cause this theory engine |
555 |
|
* to build the model. |
556 |
|
* |
557 |
|
* If the model is not available (for instance, if the last call to check-sat |
558 |
|
* was interrupted), then this returns the null pointer. |
559 |
|
*/ |
560 |
|
theory::TheoryModel* getBuiltModel(); |
561 |
|
/** |
562 |
|
* This forces the model maintained by the combination engine to be built |
563 |
|
* if it has not been done so already. This should be called only during a |
564 |
|
* last call effort check after theory combination is run. |
565 |
|
* |
566 |
|
* @return true if the model was successfully built (possibly prior to this |
567 |
|
* call). |
568 |
|
*/ |
569 |
|
bool buildModel(); |
570 |
|
/** set eager model building |
571 |
|
* |
572 |
|
* If this method is called, then this TheoryEngine will henceforth build |
573 |
|
* its model immediately after every satisfiability check that results |
574 |
|
* in a satisfiable or unknown result. The motivation for this mode is to |
575 |
|
* accomodate API users that get the model object from the TheoryEngine, |
576 |
|
* where we want to ensure that this model is always valid. |
577 |
|
* TODO (#2648): revisit this. |
578 |
|
*/ |
579 |
25 |
void setEagerModelBuilding() { d_eager_model_building = true; } |
580 |
|
|
581 |
|
/** |
582 |
|
* Get the theory associated to a given Node. |
583 |
|
* |
584 |
|
* @returns the theory, or NULL if the TNode is |
585 |
|
* of built-in type. |
586 |
|
*/ |
587 |
2217850 |
inline theory::Theory* theoryOf(TNode node) const { |
588 |
2217850 |
return d_theoryTable[theory::Theory::theoryOf(node)]; |
589 |
|
} |
590 |
|
|
591 |
|
/** |
592 |
|
* Get the theory associated to a the given theory id. |
593 |
|
* |
594 |
|
* @returns the theory |
595 |
|
*/ |
596 |
32652802 |
inline theory::Theory* theoryOf(theory::TheoryId theoryId) const { |
597 |
32652802 |
Assert(theoryId < theory::THEORY_LAST); |
598 |
32652802 |
return d_theoryTable[theoryId]; |
599 |
|
} |
600 |
|
|
601 |
1695512 |
inline bool isTheoryEnabled(theory::TheoryId theoryId) const { |
602 |
1695512 |
return d_logicInfo.isTheoryEnabled(theoryId); |
603 |
|
} |
604 |
|
/** get the logic info used by this theory engine */ |
605 |
|
const LogicInfo& getLogicInfo() const; |
606 |
|
/** get the separation logic heap types */ |
607 |
|
bool getSepHeapTypes(TypeNode& locType, TypeNode& dataType) const; |
608 |
|
|
609 |
|
/** |
610 |
|
* Declare heap. This is used for separation logics to set the location |
611 |
|
* and data types. It should be called only once, and before any separation |
612 |
|
* logic constraints are asserted to this theory engine. |
613 |
|
*/ |
614 |
|
void declareSepHeap(TypeNode locT, TypeNode dataT); |
615 |
|
|
616 |
|
/** |
617 |
|
* Returns the equality status of the two terms, from the theory |
618 |
|
* that owns the domain type. The types of a and b must be the same. |
619 |
|
*/ |
620 |
|
theory::EqualityStatus getEqualityStatus(TNode a, TNode b); |
621 |
|
|
622 |
|
/** |
623 |
|
* Returns the value that a theory that owns the type of var currently |
624 |
|
* has (or null if none); |
625 |
|
*/ |
626 |
|
Node getModelValue(TNode var); |
627 |
|
|
628 |
|
/** |
629 |
|
* Get relevant assertions. This returns a set of assertions that are |
630 |
|
* currently asserted to this TheoryEngine that propositionally entail the |
631 |
|
* (preprocessed) input formula and all theory lemmas that have been marked |
632 |
|
* NEEDS_JUSTIFY. For more details on this, see relevance_manager.h. |
633 |
|
* |
634 |
|
* This method updates success to false if the set of relevant assertions |
635 |
|
* is not available. This may occur if we are not in SAT mode, if the |
636 |
|
* relevance manager is disabled (see option::relevanceFilter) or if the |
637 |
|
* relevance manager failed to compute relevant assertions due to an internal |
638 |
|
* error. |
639 |
|
*/ |
640 |
|
const std::unordered_set<TNode>& getRelevantAssertions(bool& success); |
641 |
|
|
642 |
|
/** |
643 |
|
* Forwards an entailment check according to the given theoryOfMode. |
644 |
|
* See theory.h for documentation on entailmentCheck(). |
645 |
|
*/ |
646 |
|
std::pair<bool, Node> entailmentCheck(options::TheoryOfMode mode, TNode lit); |
647 |
|
|
648 |
|
//---------------------- information about cardinality of types |
649 |
|
/** |
650 |
|
* Is the cardinality of type tn finite? This method depends on whether |
651 |
|
* finite model finding is enabled. If finite model finding is enabled, then |
652 |
|
* we assume that all uninterpreted sorts have finite cardinality. |
653 |
|
* |
654 |
|
* Notice that if finite model finding is enabled, this method returns true |
655 |
|
* if tn is an uninterpreted sort. It also returns true for the sort |
656 |
|
* (Array Int U) where U is an uninterpreted sort. This type |
657 |
|
* is finite if and only if U has cardinality one; for cases like this, |
658 |
|
* we conservatively return that tn has finite cardinality. |
659 |
|
* |
660 |
|
* This method does *not* depend on the state of the theory engine, e.g. |
661 |
|
* if U in the above example currently is entailed to have cardinality >1 |
662 |
|
* based on the assertions. |
663 |
|
*/ |
664 |
|
bool isFiniteType(TypeNode tn) const; |
665 |
|
//---------------------- end information about cardinality of types |
666 |
|
private: |
667 |
|
|
668 |
|
/** Dump the assertions to the dump */ |
669 |
|
void dumpAssertions(const char* tag); |
670 |
|
|
671 |
|
/** For preprocessing pass lifting bit-vectors of size 1 to booleans */ |
672 |
|
public: |
673 |
5241 |
theory::SortInference* getSortInference() { return d_sortInfer.get(); } |
674 |
|
|
675 |
|
/** Prints the assertions to the debug stream */ |
676 |
|
void printAssertions(const char* tag); |
677 |
|
|
678 |
|
private: |
679 |
|
|
680 |
|
std::map< std::string, std::vector< theory::Theory* > > d_attr_handle; |
681 |
|
|
682 |
|
public: |
683 |
|
/** Set user attribute. |
684 |
|
* |
685 |
|
* This function is called when an attribute is set by a user. In SMT-LIBv2 |
686 |
|
* this is done via the syntax (! n :attr) |
687 |
|
*/ |
688 |
|
void setUserAttribute(const std::string& attr, |
689 |
|
Node n, |
690 |
|
const std::vector<Node>& node_values, |
691 |
|
const std::string& str_value); |
692 |
|
|
693 |
|
/** Handle user attribute. |
694 |
|
* |
695 |
|
* Associates theory t with the attribute attr. Theory t will be |
696 |
|
* notified whenever an attribute of name attr is set. |
697 |
|
*/ |
698 |
|
void handleUserAttribute(const char* attr, theory::Theory* t); |
699 |
|
|
700 |
|
/** |
701 |
|
* Check that the theory assertions are satisfied in the model. |
702 |
|
* This function is called from the smt engine's checkModel routine. |
703 |
|
*/ |
704 |
|
void checkTheoryAssertionsWithModel(bool hardFailure); |
705 |
|
};/* class TheoryEngine */ |
706 |
|
|
707 |
|
} // namespace cvc5 |
708 |
|
|
709 |
|
#endif /* CVC5__THEORY_ENGINE_H */ |