1 /*********************                                                        */
2 /*! \file output_channel.h
3  ** \verbatim
4  ** Top contributors (to current version):
5  **   Morgan Deters, Tim King, Liana Hadarean
6  ** This file is part of the CVC4 project.
7  ** Copyright (c) 2009-2019 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.\endverbatim
11  **
12  ** \brief The theory output channel interface
13  **
14  ** The theory output channel interface.
15  **/
16 
17 #include "cvc4_private.h"
18 
19 #ifndef __CVC4__THEORY__OUTPUT_CHANNEL_H
20 #define __CVC4__THEORY__OUTPUT_CHANNEL_H
21 
22 #include <memory>
23 
24 #include "base/cvc4_assert.h"
25 #include "proof/proof_manager.h"
26 #include "smt/logic_exception.h"
27 #include "theory/interrupted.h"
28 #include "util/proof.h"
29 #include "util/resource_manager.h"
30 
31 namespace CVC4 {
32 namespace theory {
33 
34 class Theory;
35 
36 /**
37  * A LemmaStatus, returned from OutputChannel::lemma(), provides information
38  * about the lemma added.  In particular, it contains the T-rewritten lemma
39  * for inspection and the user-level at which the lemma will reside.
40  */
41 class LemmaStatus {
42  public:
LemmaStatus(TNode rewrittenLemma,unsigned level)43   LemmaStatus(TNode rewrittenLemma, unsigned level)
44       : d_rewrittenLemma(rewrittenLemma), d_level(level) {}
45 
46   /** Get the T-rewritten form of the lemma. */
getRewrittenLemma()47   TNode getRewrittenLemma() const { return d_rewrittenLemma; }
48   /**
49    * Get the user-level at which the lemma resides.  After this user level
50    * is popped, the lemma is un-asserted from the SAT layer.  This level
51    * will be 0 if the lemma didn't reach the SAT layer at all.
52    */
getLevel()53   unsigned getLevel() const { return d_level; }
54  private:
55   Node d_rewrittenLemma;
56   unsigned d_level;
57 }; /* class LemmaStatus */
58 
59 /**
60  * Generic "theory output channel" interface.
61  *
62  * All methods can throw unrecoverable CVC4::Exception's unless otherwise
63  * documented.
64  */
65 class OutputChannel {
66  public:
67   /** Construct an OutputChannel. */
OutputChannel()68   OutputChannel() {}
69 
70   /**
71    * Destructs an OutputChannel.  This implementation does nothing,
72    * but we need a virtual destructor for safety in case subclasses
73    * have a destructor.
74    */
~OutputChannel()75   virtual ~OutputChannel() {}
76 
77   OutputChannel(const OutputChannel&) = delete;
78   OutputChannel& operator=(const OutputChannel&) = delete;
79 
80   /**
81    * With safePoint(), the theory signals that it is at a safe point
82    * and can be interrupted.
83    *
84    * @throws Interrupted if the theory can be safely interrupted.
85    */
safePoint(uint64_t amount)86   virtual void safePoint(uint64_t amount) {}
87 
88   /**
89    * Indicate a theory conflict has arisen.
90    *
91    * @param n - a conflict at the current decision level.  This should
92    * be an AND-kinded node of literals that are TRUE in the current
93    * assignment and are in conflict (i.e., at least one must be
94    * assigned false), or else a literal by itself (in the case of a
95    * unit conflict) which is assigned TRUE (and T-conflicting) in the
96    * current assignment.
97    * @param pf - a proof of the conflict. This is only non-null if proofs
98    * are enabled.
99    */
100   virtual void conflict(TNode n, std::unique_ptr<Proof> pf = nullptr) = 0;
101 
102   /**
103    * Propagate a theory literal.
104    *
105    * @param n - a theory consequence at the current decision level
106    * @return false if an immediate conflict was encountered
107    */
108   virtual bool propagate(TNode n) = 0;
109 
110   /**
111    * Tell the core that a valid theory lemma at decision level 0 has
112    * been detected.  (This requests a split.)
113    *
114    * @param n - a theory lemma valid at decision level 0
115    * @param rule - the proof rule for this lemma
116    * @param removable - whether the lemma can be removed at any point
117    * @param preprocess - whether to apply more aggressive preprocessing
118    * @param sendAtoms - whether to ensure atoms are sent to the theory
119    * @return the "status" of the lemma, including user level at which
120    * the lemma resides; the lemma will be removed when this user level pops
121    */
122   virtual LemmaStatus lemma(TNode n, ProofRule rule, bool removable = false,
123                             bool preprocess = false,
124                             bool sendAtoms = false) = 0;
125 
126   /**
127    * Variant of the lemma function that does not require providing a proof rule.
128    */
129   virtual LemmaStatus lemma(TNode n, bool removable = false,
130                             bool preprocess = false, bool sendAtoms = false) {
131     return lemma(n, RULE_INVALID, removable, preprocess, sendAtoms);
132   }
133 
134   /**
135    * Request a split on a new theory atom.  This is equivalent to
136    * calling lemma({OR n (NOT n)}).
137    *
138    * @param n - a theory atom; must be of Boolean type
139    */
split(TNode n)140   LemmaStatus split(TNode n) { return splitLemma(n.orNode(n.notNode())); }
141 
142   virtual LemmaStatus splitLemma(TNode n, bool removable = false) = 0;
143 
144   /**
145    * If a decision is made on n, it must be in the phase specified.
146    * Note that this is enforced *globally*, i.e., it is completely
147    * context-INdependent.  If you ever requirePhase() on a literal,
148    * it is phase-locked forever and ever.  If it is to ever have the
149    * other phase as its assignment, it will be because it has been
150    * propagated that way (or it's a unit, at decision level 0).
151    *
152    * @param n - a theory atom with a SAT literal assigned; must have
153    * been pre-registered
154    * @param phase - the phase to decide on n
155    */
156   virtual void requirePhase(TNode n, bool phase) = 0;
157 
158   /**
159    * Notification from a theory that it realizes it is incomplete at
160    * this context level.  If SAT is later determined by the
161    * TheoryEngine, it should actually return an UNKNOWN result.
162    */
163   virtual void setIncomplete() = 0;
164 
165   /**
166    * "Spend" a "resource."  The meaning is specific to the context in
167    * which the theory is operating, and may even be ignored.  The
168    * intended meaning is that if the user has set a limit on the "units
169    * of resource" that can be expended in a search, and that limit is
170    * exceeded, then the search is terminated.  Note that the check for
171    * termination occurs in the main search loop, so while theories
172    * should call OutputChannel::spendResource() during particularly
173    * long-running operations, they cannot rely on resource() to break
174    * out of infinite or intractable computations.
175    */
spendResource(unsigned amount)176   virtual void spendResource(unsigned amount) {}
177 
178   /**
179    * Handle user attribute.
180    * Associates theory t with the attribute attr.  Theory t will be
181    * notified whenever an attribute of name attr is set on a node.
182    * This can happen through, for example, the SMT-LIBv2 language.
183    */
handleUserAttribute(const char * attr,Theory * t)184   virtual void handleUserAttribute(const char* attr, Theory* t) {}
185 
186   /** Demands that the search restart from sat search level 0.
187    * Using this leads to non-termination issues.
188    * It is appropriate for prototyping for theories.
189    */
demandRestart()190   virtual void demandRestart() {}
191 
192 }; /* class OutputChannel */
193 
194 }  // namespace theory
195 }  // namespace CVC4
196 
197 #endif /* __CVC4__THEORY__OUTPUT_CHANNEL_H */
198