1 /********************* */
2 /*! \file logic_info.cpp
4 ** Top contributors (to current version):
5 ** Morgan Deters, Tim King, Andrew Reynolds
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2016 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
12 ** \brief A class giving information about a logic (group a theory modules
13 ** and configuration information)
15 ** A class giving information about a logic (group of theory modules and
16 ** configuration information).
18 #include "theory/logic_info.h"
24 #include "base/cvc4_assert.h"
25 #include "expr/kind.h"
29 using namespace CVC4::theory
;
33 LogicInfo::LogicInfo() :
35 d_theories(THEORY_LAST
, false),
39 d_linear(true),// for now, "everything enabled" doesn't include non-linear arith
40 d_differenceLogic(false),
41 d_cardinalityConstraints(false),
44 for(TheoryId id
= THEORY_FIRST
; id
< THEORY_LAST
; ++id
) {
49 LogicInfo::LogicInfo(std::string logicString
) throw(IllegalArgumentException
) :
51 d_theories(THEORY_LAST
, false),
56 d_differenceLogic(false),
57 d_cardinalityConstraints(false),
60 setLogicString(logicString
);
64 LogicInfo::LogicInfo(const char* logicString
) throw(IllegalArgumentException
) :
66 d_theories(THEORY_LAST
, false),
71 d_differenceLogic(false),
72 d_cardinalityConstraints(false),
75 setLogicString(logicString
);
79 /** Is sharing enabled for this logic? */
80 bool LogicInfo::isSharingEnabled() const {
81 PrettyCheckArgument(d_locked
, *this,
82 "This LogicInfo isn't locked yet, and cannot be queried");
83 return d_sharingTheories
> 1;
87 /** Is the given theory module active in this logic? */
88 bool LogicInfo::isTheoryEnabled(theory::TheoryId theory
) const {
89 PrettyCheckArgument(d_locked
, *this,
90 "This LogicInfo isn't locked yet, and cannot be queried");
91 return d_theories
[theory
];
94 /** Is this a quantified logic? */
95 bool LogicInfo::isQuantified() const {
96 PrettyCheckArgument(d_locked
, *this,
97 "This LogicInfo isn't locked yet, and cannot be queried");
98 return isTheoryEnabled(theory::THEORY_QUANTIFIERS
);
101 /** Is this the all-inclusive logic? */
102 bool LogicInfo::hasEverything() const {
103 PrettyCheckArgument(d_locked
, *this,
104 "This LogicInfo isn't locked yet, and cannot be queried");
105 LogicInfo everything
;
107 return *this == everything
;
110 /** Is this the all-exclusive logic? (Here, that means propositional logic) */
111 bool LogicInfo::hasNothing() const {
112 PrettyCheckArgument(d_locked
, *this,
113 "This LogicInfo isn't locked yet, and cannot be queried");
114 LogicInfo
nothing("");
116 return *this == nothing
;
119 bool LogicInfo::isPure(theory::TheoryId theory
) const {
120 PrettyCheckArgument(d_locked
, *this,
121 "This LogicInfo isn't locked yet, and cannot be queried");
122 // the third and fourth conjucts are really just to rule out the misleading
123 // case where you ask isPure(THEORY_BOOL) and get true even in e.g. QF_LIA
124 return isTheoryEnabled(theory
) && !isSharingEnabled() &&
125 ( !isTrueTheory(theory
) || d_sharingTheories
== 1 ) &&
126 ( isTrueTheory(theory
) || d_sharingTheories
== 0 );
129 bool LogicInfo::areIntegersUsed() const {
130 PrettyCheckArgument(d_locked
, *this,
131 "This LogicInfo isn't locked yet, and cannot be queried");
133 isTheoryEnabled(theory::THEORY_ARITH
), *this,
134 "Arithmetic not used in this LogicInfo; cannot ask whether integers are used");
138 bool LogicInfo::areRealsUsed() const {
139 PrettyCheckArgument(d_locked
, *this,
140 "This LogicInfo isn't locked yet, and cannot be queried");
142 isTheoryEnabled(theory::THEORY_ARITH
), *this,
143 "Arithmetic not used in this LogicInfo; cannot ask whether reals are used");
147 bool LogicInfo::isLinear() const {
148 PrettyCheckArgument(d_locked
, *this,
149 "This LogicInfo isn't locked yet, and cannot be queried");
151 isTheoryEnabled(theory::THEORY_ARITH
), *this,
152 "Arithmetic not used in this LogicInfo; cannot ask whether it's linear");
153 return d_linear
|| d_differenceLogic
;
156 bool LogicInfo::isDifferenceLogic() const {
157 PrettyCheckArgument(d_locked
, *this,
158 "This LogicInfo isn't locked yet, and cannot be queried");
160 isTheoryEnabled(theory::THEORY_ARITH
), *this,
161 "Arithmetic not used in this LogicInfo; cannot ask whether it's difference logic");
162 return d_differenceLogic
;
165 bool LogicInfo::hasCardinalityConstraints() const {
166 PrettyCheckArgument(d_locked
, *this,
167 "This LogicInfo isn't locked yet, and cannot be queried");
168 return d_cardinalityConstraints
;
172 bool LogicInfo::operator==(const LogicInfo
& other
) const {
173 PrettyCheckArgument(isLocked() && other
.isLocked(), *this,
174 "This LogicInfo isn't locked yet, and cannot be queried");
175 for(theory::TheoryId id
= theory::THEORY_FIRST
; id
< theory::THEORY_LAST
; ++id
) {
176 if(d_theories
[id
] != other
.d_theories
[id
]) {
181 PrettyCheckArgument(d_sharingTheories
== other
.d_sharingTheories
, *this,
182 "LogicInfo internal inconsistency");
183 if(isTheoryEnabled(theory::THEORY_ARITH
)) {
185 d_integers
== other
.d_integers
&&
186 d_reals
== other
.d_reals
&&
187 d_linear
== other
.d_linear
&&
188 d_differenceLogic
== other
.d_differenceLogic
;
194 bool LogicInfo::operator<=(const LogicInfo
& other
) const {
195 PrettyCheckArgument(isLocked() && other
.isLocked(), *this,
196 "This LogicInfo isn't locked yet, and cannot be queried");
197 for(theory::TheoryId id
= theory::THEORY_FIRST
; id
< theory::THEORY_LAST
; ++id
) {
198 if(d_theories
[id
] && !other
.d_theories
[id
]) {
202 PrettyCheckArgument(d_sharingTheories
<= other
.d_sharingTheories
, *this,
203 "LogicInfo internal inconsistency");
204 if(isTheoryEnabled(theory::THEORY_ARITH
) && other
.isTheoryEnabled(theory::THEORY_ARITH
)) {
206 (!d_integers
|| other
.d_integers
) &&
207 (!d_reals
|| other
.d_reals
) &&
208 (d_linear
|| !other
.d_linear
) &&
209 (d_differenceLogic
|| !other
.d_differenceLogic
);
215 bool LogicInfo::operator>=(const LogicInfo
& other
) const {
216 PrettyCheckArgument(isLocked() && other
.isLocked(), *this,
217 "This LogicInfo isn't locked yet, and cannot be queried");
218 for(theory::TheoryId id
= theory::THEORY_FIRST
; id
< theory::THEORY_LAST
; ++id
) {
219 if(!d_theories
[id
] && other
.d_theories
[id
]) {
223 PrettyCheckArgument(d_sharingTheories
>= other
.d_sharingTheories
, *this,
224 "LogicInfo internal inconsistency");
225 if(isTheoryEnabled(theory::THEORY_ARITH
) && other
.isTheoryEnabled(theory::THEORY_ARITH
)) {
227 (d_integers
|| !other
.d_integers
) &&
228 (d_reals
|| !other
.d_reals
) &&
229 (!d_linear
|| other
.d_linear
) &&
230 (!d_differenceLogic
|| other
.d_differenceLogic
);
236 std::string
LogicInfo::getLogicString() const {
239 "This LogicInfo isn't locked yet, and cannot be queried");
240 if(d_logicString
== "") {
241 LogicInfo qf_all_supported
;
242 qf_all_supported
.disableQuantifiers();
243 qf_all_supported
.lock();
244 if(hasEverything()) {
245 d_logicString
= "ALL";
246 } else if(*this == qf_all_supported
) {
247 d_logicString
= "QF_ALL";
249 size_t seen
= 0; // make sure we support all the active theories
252 if(!isQuantified()) {
255 if(d_theories
[THEORY_ARRAY
]) {
256 ss
<< (d_sharingTheories
== 1 ? "AX" : "A");
259 if(d_theories
[THEORY_UF
]) {
263 if( d_cardinalityConstraints
){
266 if(d_theories
[THEORY_BV
]) {
270 if(d_theories
[THEORY_FP
]) {
274 if(d_theories
[THEORY_DATATYPES
]) {
278 if(d_theories
[THEORY_STRINGS
]) {
282 if(d_theories
[THEORY_ARITH
]) {
283 if(isDifferenceLogic()) {
284 ss
<< (areIntegersUsed() ? "I" : "");
285 ss
<< (areRealsUsed() ? "R" : "");
288 ss
<< (isLinear() ? "L" : "N");
289 ss
<< (areIntegersUsed() ? "I" : "");
290 ss
<< (areRealsUsed() ? "R" : "");
295 if(d_theories
[THEORY_SETS
]) {
299 if(d_theories
[THEORY_SEP
]) {
303 if(seen
!= d_sharingTheories
) {
304 Unhandled("can't extract a logic string from LogicInfo; at least one "
305 "active theory is unknown to LogicInfo::getLogicString() !");
312 d_logicString
= ss
.str();
315 return d_logicString
;
318 void LogicInfo::setLogicString(std::string logicString
) throw(IllegalArgumentException
) {
319 PrettyCheckArgument(!d_locked
, *this,
320 "This LogicInfo is locked, and cannot be modified");
321 for(TheoryId id
= THEORY_FIRST
; id
< THEORY_LAST
; ++id
) {
322 d_theories
[id
] = false;// ensure it's cleared
324 d_sharingTheories
= 0;
326 // Below, ONLY use enableTheory()/disableTheory() rather than
327 // accessing d_theories[] directly. This makes sure to set up
330 enableTheory(THEORY_BUILTIN
);
331 enableTheory(THEORY_BOOL
);
333 const char* p
= logicString
.c_str();
335 // propositional logic only; we're done.
336 } else if(!strcmp(p
, "QF_SAT")) {
337 // propositional logic only; we're done.
339 } else if(!strcmp(p
, "QF_ALL_SUPPORTED")) {
340 // the "all theories included" logic, no quantifiers
342 disableQuantifiers();
344 } else if(!strcmp(p
, "QF_ALL")) {
345 // the "all theories included" logic, no quantifiers
347 disableQuantifiers();
349 } else if(!strcmp(p
, "ALL_SUPPORTED")) {
350 // the "all theories included" logic, with quantifiers
354 } else if(!strcmp(p
, "ALL")) {
355 // the "all theories included" logic, with quantifiers
360 if(!strncmp(p
, "QF_", 3)) {
361 disableQuantifiers();
366 if(!strncmp(p
, "AX", 2)) {
367 enableTheory(THEORY_ARRAY
);
371 enableTheory(THEORY_ARRAY
);
374 if(!strncmp(p
, "UF", 2)) {
375 enableTheory(THEORY_UF
);
378 if(!strncmp(p
, "C", 1 )) {
379 d_cardinalityConstraints
= true;
382 // allow BV or DT in either order
383 if(!strncmp(p
, "BV", 2)) {
384 enableTheory(THEORY_BV
);
387 if(!strncmp(p
, "FP", 2)) {
388 enableTheory(THEORY_FP
);
391 if(!strncmp(p
, "DT", 2)) {
392 enableTheory(THEORY_DATATYPES
);
395 if(!d_theories
[THEORY_BV
] && !strncmp(p
, "BV", 2)) {
396 enableTheory(THEORY_BV
);
400 enableTheory(THEORY_STRINGS
);
403 if(!strncmp(p
, "IDL", 3)) {
406 arithOnlyDifference();
408 } else if(!strncmp(p
, "RDL", 3)) {
411 arithOnlyDifference();
413 } else if(!strncmp(p
, "IRDL", 4)) {
414 // "IRDL" ?! --not very useful, but getLogicString() can produce
415 // that string, so we really had better be able to read it back in.
418 arithOnlyDifference();
420 } else if(!strncmp(p
, "LIA", 3)) {
425 } else if(!strncmp(p
, "LRA", 3)) {
430 } else if(!strncmp(p
, "LIRA", 4)) {
435 } else if(!strncmp(p
, "NIA", 3)) {
440 } else if(!strncmp(p
, "NRA", 3)) {
445 } else if(!strncmp(p
, "NIRA", 4)) {
451 if(!strncmp(p
, "FS", 2)) {
452 enableTheory(THEORY_SETS
);
455 if(!strncmp(p
, "SEP", 3)) {
456 enableTheory(THEORY_SEP
);
463 err
<< "LogicInfo::setLogicString(): ";
464 if(p
== logicString
) {
465 err
<< "cannot parse logic string: " << logicString
;
467 err
<< "junk (\"" << p
<< "\") at end of logic string: " << logicString
;
469 IllegalArgument(logicString
, err
.str().c_str());
472 // ensure a getLogic() returns the same thing as was set
473 d_logicString
= logicString
;
476 void LogicInfo::enableEverything() {
477 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
481 void LogicInfo::disableEverything() {
482 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
483 *this = LogicInfo("");
486 void LogicInfo::enableTheory(theory::TheoryId theory
) {
487 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
488 if(!d_theories
[theory
]) {
489 if(isTrueTheory(theory
)) {
493 d_theories
[theory
] = true;
497 void LogicInfo::disableTheory(theory::TheoryId theory
) {
498 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
499 if(d_theories
[theory
]) {
500 if(isTrueTheory(theory
)) {
501 Assert(d_sharingTheories
> 0);
504 if(theory
== THEORY_BUILTIN
||
505 theory
== THEORY_BOOL
) {
509 d_theories
[theory
] = false;
513 void LogicInfo::enableIntegers() {
514 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
516 enableTheory(THEORY_ARITH
);
520 void LogicInfo::disableIntegers() {
521 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
525 disableTheory(THEORY_ARITH
);
529 void LogicInfo::enableReals() {
530 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
532 enableTheory(THEORY_ARITH
);
536 void LogicInfo::disableReals() {
537 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
541 disableTheory(THEORY_ARITH
);
545 void LogicInfo::arithOnlyDifference() {
546 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
549 d_differenceLogic
= true;
552 void LogicInfo::arithOnlyLinear() {
553 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
556 d_differenceLogic
= false;
559 void LogicInfo::arithNonLinear() {
560 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
563 d_differenceLogic
= false;
566 LogicInfo
LogicInfo::getUnlockedCopy() const {
568 LogicInfo info
= *this;
569 info
.d_locked
= false;
576 std::ostream
& operator<<(std::ostream
& out
, const LogicInfo
& logic
) {
577 return out
<< logic
.getLogicString();
580 }/* CVC4 namespace */