Merge remote-tracking branch 'upstream/master' into sets
[cvc5.git] / src / theory / logic_info.h
1 /********************* */
2 /*! \file logic_info.h
3 ** \verbatim
4 ** Original author: Morgan Deters
5 ** Major contributors: none
6 ** Minor contributors (to current version): Dejan Jovanovic
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2013 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
11 **
12 ** \brief A class giving information about a logic (group a theory modules
13 ** and configuration information)
14 **
15 ** A class giving information about a logic (group of theory modules and
16 ** configuration information).
17 **/
18
19 #include "cvc4_public.h"
20
21 #ifndef __CVC4__LOGIC_INFO_H
22 #define __CVC4__LOGIC_INFO_H
23
24 #include <string>
25 #include <vector>
26 #include "expr/kind.h"
27
28 namespace CVC4 {
29
30 /**
31 * A LogicInfo instance describes a collection of theory modules and some
32 * basic configuration about them. Conceptually, it provides a background
33 * context for all operations in CVC4. Typically, when CVC4's SmtEngine
34 * is created, it is issued a setLogic() command indicating features of the
35 * assertions and queries to follow---for example, whether quantifiers are
36 * used, whether integers or reals (or both) will be used, etc.
37 *
38 * Most places in CVC4 will only ever need to access a const reference to an
39 * instance of this class. Such an instance is generally set by the SmtEngine
40 * when setLogic() is called. However, mutating member functions are also
41 * provided by this class so that it can be used as a more general mechanism
42 * (e.g., for communicating to the SmtEngine which theories should be used,
43 * rather than having to provide an SMT-LIB string).
44 */
45 class CVC4_PUBLIC LogicInfo {
46 mutable std::string d_logicString; /**< an SMT-LIB-like logic string */
47 std::vector<bool> d_theories; /**< set of active theories */
48 size_t d_sharingTheories; /**< count of theories that need sharing */
49
50 // for arithmetic
51 bool d_integers; /**< are integers used in this logic? */
52 bool d_reals; /**< are reals used in this logic? */
53 bool d_linear; /**< linear-only arithmetic in this logic? */
54 bool d_differenceLogic; /**< difference-only arithmetic in this logic? */
55 bool d_cardinalityConstraints; /**< cardinality constraints in this logic? */
56
57 bool d_locked; /**< is this LogicInfo instance locked (and thus immutable)? */
58
59 /**
60 * Returns true iff this is a "true" theory (one that must be worried
61 * about for sharing
62 */
63 static inline bool isTrueTheory(theory::TheoryId theory) {
64 switch(theory) {
65 case theory::THEORY_BUILTIN:
66 case theory::THEORY_BOOL:
67 case theory::THEORY_QUANTIFIERS:
68 return false;
69 default:
70 return true;
71 }
72 }
73
74 public:
75
76 /**
77 * Constructs a LogicInfo for the most general logic (quantifiers, all
78 * background theory modules, ...).
79 */
80 LogicInfo();
81
82 /**
83 * Construct a LogicInfo from an SMT-LIB-like logic string.
84 * Throws an IllegalArgumentException if the logic string cannot
85 * be interpreted.
86 */
87 LogicInfo(std::string logicString) throw(IllegalArgumentException);
88
89 /**
90 * Construct a LogicInfo from an SMT-LIB-like logic string.
91 * Throws an IllegalArgumentException if the logic string cannot
92 * be interpreted.
93 */
94 LogicInfo(const char* logicString) throw(IllegalArgumentException);
95
96 // ACCESSORS
97
98 /**
99 * Get an SMT-LIB-like logic string. These are only guaranteed to
100 * be SMT-LIB-compliant if an SMT-LIB-compliant string was used in
101 * the constructor and no mutating functions were called.
102 */
103 std::string getLogicString() const;
104
105 /** Is sharing enabled for this logic? */
106 bool isSharingEnabled() const {
107 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
108 return d_sharingTheories > 1;
109 }
110
111 /** Is the given theory module active in this logic? */
112 bool isTheoryEnabled(theory::TheoryId theory) const {
113 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
114 return d_theories[theory];
115 }
116
117 /** Is this a quantified logic? */
118 bool isQuantified() const {
119 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
120 return isTheoryEnabled(theory::THEORY_QUANTIFIERS);
121 }
122
123 /** Is this the all-inclusive logic? */
124 bool hasEverything() const {
125 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
126 LogicInfo everything;
127 everything.lock();
128 return *this == everything;
129 }
130
131 /** Is this the all-exclusive logic? (Here, that means propositional logic) */
132 bool hasNothing() const {
133 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
134 LogicInfo nothing("");
135 nothing.lock();
136 return *this == nothing;
137 }
138
139 /**
140 * Is this a pure logic (only one "true" background theory). Quantifiers
141 * can exist in such logics though; to test for quantifier-free purity,
142 * use "isPure(theory) && !isQuantified()".
143 */
144 bool isPure(theory::TheoryId theory) const {
145 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
146 // the third and fourth conjucts are really just to rule out the misleading
147 // case where you ask isPure(THEORY_BOOL) and get true even in e.g. QF_LIA
148 return isTheoryEnabled(theory) && !isSharingEnabled() &&
149 ( !isTrueTheory(theory) || d_sharingTheories == 1 ) &&
150 ( isTrueTheory(theory) || d_sharingTheories == 0 );
151 }
152
153 // these are for arithmetic
154
155 /** Are integers in this logic? */
156 bool areIntegersUsed() const {
157 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
158 CheckArgument(isTheoryEnabled(theory::THEORY_ARITH), *this, "Arithmetic not used in this LogicInfo; cannot ask whether integers are used");
159 return d_integers;
160 }
161 /** Are reals in this logic? */
162 bool areRealsUsed() const {
163 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
164 CheckArgument(isTheoryEnabled(theory::THEORY_ARITH), *this, "Arithmetic not used in this LogicInfo; cannot ask whether reals are used");
165 return d_reals;
166 }
167 /** Does this logic only linear arithmetic? */
168 bool isLinear() const {
169 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
170 CheckArgument(isTheoryEnabled(theory::THEORY_ARITH), *this, "Arithmetic not used in this LogicInfo; cannot ask whether it's linear");
171 return d_linear || d_differenceLogic;
172 }
173 /** Does this logic only permit difference reasoning? (implies linear) */
174 bool isDifferenceLogic() const {
175 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
176 CheckArgument(isTheoryEnabled(theory::THEORY_ARITH), *this, "Arithmetic not used in this LogicInfo; cannot ask whether it's difference logic");
177 return d_differenceLogic;
178 }
179 /** Does this logic allow cardinality constraints? */
180 bool hasCardinalityConstraints() const {
181 CheckArgument(d_locked, *this, "This LogicInfo isn't locked yet, and cannot be queried");
182 return d_cardinalityConstraints;
183 }
184
185 // MUTATORS
186
187 /**
188 * Initialize the LogicInfo with an SMT-LIB-like logic string.
189 * Throws an IllegalArgumentException if the string can't be
190 * interpreted.
191 */
192 void setLogicString(std::string logicString) throw(IllegalArgumentException);
193
194 /**
195 * Enable all functionality. All theories, plus quantifiers, will be
196 * enabled.
197 */
198 void enableEverything();
199
200 /**
201 * Disable all functionality. The result will be a LogicInfo with
202 * the BUILTIN and BOOLEAN theories enabled only ("QF_SAT").
203 */
204 void disableEverything();
205
206 /**
207 * Enable the given theory module.
208 */
209 void enableTheory(theory::TheoryId theory);
210
211 /**
212 * Disable the given theory module. THEORY_BUILTIN and THEORY_BOOL cannot
213 * be disabled (and if given here, the request will be silently ignored).
214 */
215 void disableTheory(theory::TheoryId theory);
216
217 /**
218 * Quantifiers are a special case, since two theory modules handle them.
219 */
220 void enableQuantifiers() {
221 enableTheory(theory::THEORY_QUANTIFIERS);
222 }
223
224 /**
225 * Quantifiers are a special case, since two theory modules handle them.
226 */
227 void disableQuantifiers() {
228 disableTheory(theory::THEORY_QUANTIFIERS);
229 }
230
231 // these are for arithmetic
232
233 /** Enable the use of integers in this logic. */
234 void enableIntegers();
235 /** Disable the use of integers in this logic. */
236 void disableIntegers();
237 /** Enable the use of reals in this logic. */
238 void enableReals();
239 /** Disable the use of reals in this logic. */
240 void disableReals();
241 /** Only permit difference arithmetic in this logic. */
242 void arithOnlyDifference();
243 /** Only permit linear arithmetic in this logic. */
244 void arithOnlyLinear();
245 /** Permit nonlinear arithmetic in this logic. */
246 void arithNonLinear();
247
248 // LOCKING FUNCTIONALITY
249
250 /** Lock this LogicInfo, disabling further mutation and allowing queries */
251 void lock() { d_locked = true; }
252 /** Check whether this LogicInfo is locked, disallowing further mutation */
253 bool isLocked() const { return d_locked; }
254 /** Get a copy of this LogicInfo that is identical, but unlocked */
255 LogicInfo getUnlockedCopy() const;
256
257 // COMPARISON
258
259 /** Are these two LogicInfos equal? */
260 bool operator==(const LogicInfo& other) const {
261 CheckArgument(isLocked() && other.isLocked(), *this, "This LogicInfo isn't locked yet, and cannot be queried");
262 for(theory::TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
263 if(d_theories[id] != other.d_theories[id]) {
264 return false;
265 }
266 }
267 CheckArgument(d_sharingTheories == other.d_sharingTheories, *this, "LogicInfo internal inconsistency");
268 if(isTheoryEnabled(theory::THEORY_ARITH)) {
269 return
270 d_integers == other.d_integers &&
271 d_reals == other.d_reals &&
272 d_linear == other.d_linear &&
273 d_differenceLogic == other.d_differenceLogic;
274 } else {
275 return true;
276 }
277 }
278 /** Are these two LogicInfos disequal? */
279 bool operator!=(const LogicInfo& other) const {
280 return !(*this == other);
281 }
282 /** Is this LogicInfo "greater than" (does it contain everything and more) the other? */
283 bool operator>(const LogicInfo& other) const {
284 return *this >= other && *this != other;
285 }
286 /** Is this LogicInfo "less than" (does it contain strictly less) the other? */
287 bool operator<(const LogicInfo& other) const {
288 return *this <= other && *this != other;
289 }
290 /** Is this LogicInfo "less than or equal" the other? */
291 bool operator<=(const LogicInfo& other) const {
292 CheckArgument(isLocked() && other.isLocked(), *this, "This LogicInfo isn't locked yet, and cannot be queried");
293 for(theory::TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
294 if(d_theories[id] && !other.d_theories[id]) {
295 return false;
296 }
297 }
298 CheckArgument(d_sharingTheories <= other.d_sharingTheories, *this, "LogicInfo internal inconsistency");
299 if(isTheoryEnabled(theory::THEORY_ARITH) && other.isTheoryEnabled(theory::THEORY_ARITH)) {
300 return
301 (!d_integers || other.d_integers) &&
302 (!d_reals || other.d_reals) &&
303 (d_linear || !other.d_linear) &&
304 (d_differenceLogic || !other.d_differenceLogic);
305 } else {
306 return true;
307 }
308 }
309 /** Is this LogicInfo "greater than or equal" the other? */
310 bool operator>=(const LogicInfo& other) const {
311 CheckArgument(isLocked() && other.isLocked(), *this, "This LogicInfo isn't locked yet, and cannot be queried");
312 for(theory::TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
313 if(!d_theories[id] && other.d_theories[id]) {
314 return false;
315 }
316 }
317 CheckArgument(d_sharingTheories >= other.d_sharingTheories, *this, "LogicInfo internal inconsistency");
318 if(isTheoryEnabled(theory::THEORY_ARITH) && other.isTheoryEnabled(theory::THEORY_ARITH)) {
319 return
320 (d_integers || !other.d_integers) &&
321 (d_reals || !other.d_reals) &&
322 (!d_linear || other.d_linear) &&
323 (!d_differenceLogic || other.d_differenceLogic);
324 } else {
325 return true;
326 }
327 }
328
329 /** Are two LogicInfos comparable? That is, is one of <= or > true? */
330 bool isComparableTo(const LogicInfo& other) const {
331 return *this <= other || *this >= other;
332 }
333
334 };/* class LogicInfo */
335
336 std::ostream& operator<<(std::ostream& out, const LogicInfo& logic) CVC4_PUBLIC;
337
338 }/* CVC4 namespace */
339
340 #endif /* __CVC4__LOGIC_INFO_H */
341