1 /******************************************************************************
2 * Top contributors (to current version):
3 * Andrew Reynolds, Gereon Kremer, Mathias Preiner
5 * This file is part of the cvc5 project.
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 * ****************************************************************************
13 * An inference manager for Theory.
16 #include "cvc5_private.h"
18 #ifndef CVC5__THEORY__THEORY_INFERENCE_MANAGER_H
19 #define CVC5__THEORY__THEORY_INFERENCE_MANAGER_H
23 #include "context/cdhashset.h"
24 #include "expr/node.h"
25 #include "expr/proof_rule.h"
26 #include "theory/inference_id.h"
27 #include "theory/output_channel.h"
28 #include "theory/trust_node.h"
29 #include "util/statistics_stats.h"
33 class ProofNodeManager
;
39 class DecisionManager
;
46 * The base class for inference manager. An inference manager is a wrapper
47 * around the output channel and the official equality engine of a Theory.
48 * It is used for ensuring that the equality engine and output channel
49 * are used properly. This includes the following invariants:
51 * (1) The state tracks conflicts.
52 * In particular, TheoryState::isInConflict returns true whenever we have
53 * called OutputChannel::conflict in the current context, which we enforce
54 * by always setting d_state.notifyInConflict at the same time we send
55 * conflicts on the output channel.
57 * (2) The theory is notified of (internal) facts.
58 * In particular, Theory::preNotifyFact and Theory::notifyFact are called
59 * (with isInternal = true) whenever we assert internal facts using
60 * assertFactInernal below, mirroring what is done for facts from the fact
61 * queue (where isInternal = false).
63 * (3) The proof equality engine is used whenever proofs are enabled (when
64 * the proof node manager provided to this class is non-null). Notice this
65 * class automatically will construct a proof equality engine during
66 * setEqualityEngine, and use it for handling variants of assertInternalFact
67 * below that involve proofs.
69 class TheoryInferenceManager
71 typedef context::CDHashSet
<Node
, NodeHashFunction
> NodeSet
;
75 * Constructor, note that state should be the official state of theory t.
77 * @param t The theory this inference manager is for
78 * @param state The state of the theory
79 * @param pnm The proof node manager, which if non-null, enables proofs for
80 * this inference manager
81 * @param statsName The name of the inference manager, which is used for
82 * giving unique names for statistics,
83 * @param cacheLemmas Whether all lemmas sent using this theory inference
84 * manager are added to a user-context dependent cache. This means that
85 * only lemmas that are unique after rewriting are sent to the theory engine
86 * from this inference manager.
88 TheoryInferenceManager(Theory
& t
,
90 ProofNodeManager
* pnm
,
91 const std::string
& statsName
,
92 bool cacheLemmas
= true);
93 virtual ~TheoryInferenceManager();
94 //--------------------------------------- initialization
96 * Set equality engine, ee is a pointer to the official equality engine
99 void setEqualityEngine(eq::EqualityEngine
* ee
);
100 /** Set the decision manager */
101 void setDecisionManager(DecisionManager
* dm
);
102 //--------------------------------------- end initialization
104 * Are proofs enabled in this inference manager? Returns true if the proof
105 * node manager pnm provided to the constructor of this class was non-null.
107 bool isProofEnabled() const;
108 /** Get the underlying proof equality engine */
109 eq::ProofEqEngine
* getProofEqEngine();
111 * Reset, which resets counters regarding the number of added lemmas and
112 * internal facts. This method should be manually called by the theory at
113 * the appropriate time for the purpose of tracking the usage of this
116 * For example, some theories implement an internal checking loop that
117 * repeats while new facts are added. The theory should call reset at the
118 * beginning of this loop and repeat its strategy while hasAddedFact is true.
122 * Returns true if we are in conflict, or if we have sent a lemma or fact
123 * since the last call to reset.
125 bool hasSent() const;
126 //--------------------------------------- propagations
128 * T-propagate literal lit, possibly encountered by equality engine,
129 * returns false if we are in conflict.
131 * Note that this is the preferred method to call on
132 * EqualityEngineNotify::eqNotifyTriggerPredicate and
133 * EqualityEngineNotify::eqNotifyTriggerTermEquality.
135 bool propagateLit(TNode lit
);
137 * Return an explanation for the literal represented by parameter lit
138 * (which was previously propagated by this theory). By default, this
139 * returns the explanation given by the official equality engine of the
140 * Theory, if it exists.
142 virtual TrustNode
explainLit(TNode lit
);
143 //--------------------------------------- conflicts
145 * Raise conflict, called when constants a and b merge. Sends the conflict
146 * on the output channel corresponding to the equality engine's explanation
147 * of (= a b). The proof equality engine (if it exists) will be used as the
150 * Note that this is the preferred method to call on
151 * EqualityEngineNotify::eqNotifyConstantTermMerge.
153 void conflictEqConstantMerge(TNode a
, TNode b
);
155 * Raise conflict conf (of any form), without proofs. This method should
156 * only be called if there is not yet proof support in the given theory.
158 void conflict(TNode conf
, InferenceId id
);
160 * Raise trusted conflict tconf (of any form) where a proof generator has
161 * been provided (as part of the trust node) in a custom way.
163 void trustedConflict(TrustNode tconf
, InferenceId id
);
165 * Explain and send conflict from contradictory facts. This method is called
166 * when the proof rule id with premises exp and arguments args concludes
167 * false. This method sends a trusted conflict corresponding to the official
168 * equality engine's explanation of literals in exp, with the proof equality
169 * engine as the proof generator (if it exists).
171 void conflictExp(InferenceId id
,
173 const std::vector
<Node
>& exp
,
174 const std::vector
<Node
>& args
);
176 * Make the trust node corresponding to the conflict of the above form. It is
177 * the responsibility of the caller to subsequently call trustedConflict with
178 * the returned trust node.
180 TrustNode
mkConflictExp(PfRule pfr
,
181 const std::vector
<Node
>& exp
,
182 const std::vector
<Node
>& args
);
184 * Explain and send conflict from contradictory facts. This method is called
185 * when proof generator pg has a proof of false from free assumptions exp.
186 * This method sends a trusted conflict corresponding to the official
187 * equality engine's explanation of literals in exp, with the proof equality
188 * engine as the proof generator (if it exists), where pg provides the
189 * final step(s) of this proof during this call.
191 void conflictExp(InferenceId id
,
192 const std::vector
<Node
>& exp
,
195 * Make the trust node corresponding to the conflict of the above form. It is
196 * the responsibility of the caller to subsequently call trustedConflict with
197 * the returned trust node.
199 TrustNode
mkConflictExp(const std::vector
<Node
>& exp
, ProofGenerator
* pg
);
200 //--------------------------------------- lemmas
202 * Send (trusted) lemma lem with property p on the output channel.
204 * @param tlem The trust node containing the lemma and its proof generator.
205 * @param p The property of the lemma
206 * @return true if the lemma was sent on the output channel.
208 bool trustedLemma(const TrustNode
& tlem
,
210 LemmaProperty p
= LemmaProperty::NONE
);
212 * Send lemma lem with property p on the output channel. Same as above, with
213 * a node instead of a trust node.
215 bool lemma(TNode lem
, InferenceId id
, LemmaProperty p
= LemmaProperty::NONE
);
217 * Explained lemma. This should be called when
219 * is a valid theory lemma. This method adds a lemma where part of exp
220 * is replaced by its explanation according to the official equality engine
223 * In particular, this method adds a lemma on the output channel of the form
224 * ( ^_{e in exp \ noExplain} EXPLAIN(e) ^ noExplain ) => conc
225 * where EXPLAIN(e) returns the explanation of literal e according to the
226 * official equality engine of the theory. Note that noExplain is the *subset*
227 * of exp that should not be explained.
229 * @param conc The conclusion of the lemma
230 * @param id The proof rule concluding conc
231 * @param exp The set of (all) literals that imply conc
232 * @param noExplain The subset of exp that should not be explained by the
234 * @param args The arguments to the proof step concluding conc
235 * @param p The property of the lemma
236 * @return true if the lemma was sent on the output channel.
238 bool lemmaExp(Node conc
,
241 const std::vector
<Node
>& exp
,
242 const std::vector
<Node
>& noExplain
,
243 const std::vector
<Node
>& args
,
244 LemmaProperty p
= LemmaProperty::NONE
);
246 * Make the trust node for the above method. It is responsibility of the
247 * caller to subsequently call trustedLemma with the returned trust node.
249 TrustNode
mkLemmaExp(Node conc
,
251 const std::vector
<Node
>& exp
,
252 const std::vector
<Node
>& noExplain
,
253 const std::vector
<Node
>& args
);
255 * Same as above, but where pg can provide a proof of conc from free
256 * assumptions in exp. This sends a trusted lemma on the output channel where
257 * the proof equality engine is the proof generator. The generator pg
258 * is asked to provide the final step(s) of this proof during this call.
260 * @param conc The conclusion of the lemma
261 * @param exp The set of (all) literals that imply conc
262 * @param noExplain The subset of exp that should not be explained by the
264 * @param pg If non-null, the proof generator who can provide a proof of conc.
265 * @param p The property of the lemma
266 * @return true if the lemma was sent on the output channel.
268 bool lemmaExp(Node conc
,
270 const std::vector
<Node
>& exp
,
271 const std::vector
<Node
>& noExplain
,
272 ProofGenerator
* pg
= nullptr,
273 LemmaProperty p
= LemmaProperty::NONE
);
275 * Make the trust node for the above method. It is responsibility of the
276 * caller to subsequently call trustedLemma with the returned trust node.
278 TrustNode
mkLemmaExp(Node conc
,
279 const std::vector
<Node
>& exp
,
280 const std::vector
<Node
>& noExplain
,
281 ProofGenerator
* pg
= nullptr);
283 * Has this inference manager cached and sent the given lemma (in this user
284 * context)? This method can be overridden by the particular manager. If not,
285 * this returns true if lem is in the cache d_lemmasSent maintained by this
286 * class. Notice that the default cache in this base class is not dependent
287 * on the lemma property.
289 virtual bool hasCachedLemma(TNode lem
, LemmaProperty p
);
290 /** The number of lemmas we have sent since the last call to reset */
291 uint32_t numSentLemmas() const;
292 /** Have we added a lemma since the last call to reset? */
293 bool hasSentLemma() const;
294 //--------------------------------------- internal facts
296 * Assert internal fact. This is recommended method for asserting "internal"
297 * facts into the equality engine of the theory. In particular, this method
298 * should be used for anything the theory infers that is not sent on the
299 * output channel as a propagation or lemma. This method ensures that the
300 * Theory's preNotifyFact and notifyFact method have been called with
303 * @param atom The atom of the fact to assert
304 * @param pol Its polarity
305 * @param exp Its explanation, i.e. ( exp => (~) atom ) is valid.
306 * @return true if the fact was processed, i.e. it was asserted to the
307 * equality engine or preNotifyFact returned true.
309 bool assertInternalFact(TNode atom
, bool pol
, InferenceId id
, TNode exp
);
311 * Assert internal fact, with a proof step justification. Notice that if
312 * proofs are not enabled in this inference manager, then this asserts
313 * a fact to the equality engine in the normal way.
315 * @param atom The atom of the fact to assert
316 * @param pol Its polarity
317 * @param id The proof rule identifier of the proof step
318 * @param exp Its explanation, interpreted as a conjunction
319 * @param args The arguments of the proof step
320 * @return true if the fact was processed, i.e. it was asserted to the
321 * equality engine or preNotifyFact returned true.
323 bool assertInternalFact(TNode atom
,
327 const std::vector
<Node
>& exp
,
328 const std::vector
<Node
>& args
);
330 * Assert internal fact, with a proof generator justification. Same as above,
331 * but with a proof generator instead of an explicit step.
333 * @param atom The atom of the fact to assert
334 * @param pol Its polarity
335 * @param exp Its explanation, interpreted as a conjunction
336 * @param pg The proof generator for this step. If non-null, pg must be able
337 * to provide a proof concluding (~) atom from free asumptions in exp in
338 * the remainder of the current SAT context.
339 * @return true if the fact was processed, i.e. it was asserted to the
340 * equality engine or preNotifyFact returned true.
342 bool assertInternalFact(TNode atom
,
345 const std::vector
<Node
>& exp
,
347 /** The number of internal facts we have added since the last call to reset */
348 uint32_t numSentFacts() const;
349 /** Have we added a internal fact since the last call to reset? */
350 bool hasSentFact() const;
351 //--------------------------------------- phase requirements
352 /** Get the decision manager, which manages decision strategies. */
353 DecisionManager
* getDecisionManager();
355 * Set that literal n has SAT phase requirement pol, that is, it should be
356 * decided with polarity pol, for details see OutputChannel::requirePhase.
358 void requirePhase(TNode n
, bool pol
);
361 * Forward to OutputChannel::spendResource() to spend resources.
363 void spendResource(Resource r
);
366 * Forward to OutputChannel::safePoint() to spend resources.
368 void safePoint(Resource r
);
370 * Notification from a theory that it realizes it is incomplete at
371 * this context level.
373 void setIncomplete(IncompleteId id
);
377 * Process internal fact. This is a common helper method for the
378 * assertInternalFact variants above. Returns true if the fact was processed.
380 bool processInternalFact(TNode atom
,
384 const std::vector
<Node
>& exp
,
385 const std::vector
<Node
>& args
,
388 * Explain conflict from constants merging in the equality engine. This
389 * method is called by conflictEqConstantMerge. By default, it returns
390 * the explanation of the official equality engine of the theory, if it
393 virtual TrustNode
explainConflictEqConstantMerge(TNode a
, TNode b
);
395 * Explain formula n (which is possibly a conjunction with no nested
396 * conjunctions), add its explanation to assumptions.
398 void explain(TNode n
, std::vector
<TNode
>& assumptions
);
400 * Explain formula n (which is possibly a conjunction with no nested
401 * conjunctions), return the explanation as a conjunction.
403 Node
mkExplain(TNode n
);
405 * Explain the set of formulas in exp using the official equality engine of
406 * the theory. We ask the equality engine to explain literals in exp
407 * that do not occur in noExplain, and return unchanged those that occur in
408 * noExplain. Note the vector noExplain should be a subset of exp.
410 Node
mkExplainPartial(const std::vector
<Node
>& exp
,
411 const std::vector
<Node
>& noExplain
);
413 * Cache that lemma lem is being sent with property p. Return true if it
414 * did not already exist in the cache maintained by this class. If this
415 * method is not overridden, then we use the d_lemmasSent cache maintained
416 * by this class, which notice is not dependent on lemma property. If
417 * the lemma property should be taken into account, the manager should
418 * override this method to take the lemma property into account as needed.
420 virtual bool cacheLemma(TNode lem
, LemmaProperty p
);
421 /** The theory object */
423 /** Reference to the state of theory */
424 TheoryState
& d_theoryState
;
425 /** Reference to the output channel of the theory */
426 OutputChannel
& d_out
;
427 /** Pointer to equality engine of the theory. */
428 eq::EqualityEngine
* d_ee
;
429 /** Pointer to the decision manager */
430 DecisionManager
* d_decManager
;
431 /** A proof equality engine */
432 std::unique_ptr
<eq::ProofEqEngine
> d_pfee
;
433 /** The proof node manager of the theory */
434 ProofNodeManager
* d_pnm
;
435 /** Whether this manager caches lemmas */
438 * The keep set of this class. This set is maintained to ensure that
439 * facts and their explanations are ref-counted. Since facts and their
440 * explanations are SAT-context-dependent, this set is also
441 * SAT-context-dependent.
445 * A cache of all lemmas sent, which is a user-context-dependent set of
446 * nodes. Notice that this cache does not depedent on lemma property.
448 NodeSet d_lemmasSent
;
449 /** The number of conflicts sent since the last call to reset. */
450 uint32_t d_numConflicts
;
451 /** The number of lemmas sent since the last call to reset. */
452 uint32_t d_numCurrentLemmas
;
453 /** The number of internal facts added since the last call to reset. */
454 uint32_t d_numCurrentFacts
;
455 /** Statistics for conflicts sent via this inference manager. */
456 HistogramStat
<InferenceId
> d_conflictIdStats
;
457 /** Statistics for facts sent via this inference manager. */
458 HistogramStat
<InferenceId
> d_factIdStats
;
459 /** Statistics for lemmas sent via this inference manager. */
460 HistogramStat
<InferenceId
> d_lemmaIdStats
;
463 } // namespace theory
466 #endif /* CVC5__THEORY__THEORY_INFERENCE_MANAGER_H */