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-2020 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"
25 #include "base/check.h"
26 #include "base/configuration.h"
27 #include "expr/kind.h"
30 using namespace CVC4::theory
;
34 LogicInfo::LogicInfo()
36 d_theories(THEORY_LAST
, false),
40 d_transcendentals(true),
42 d_differenceLogic(false),
43 d_cardinalityConstraints(false),
47 for (TheoryId id
= THEORY_FIRST
; id
< THEORY_LAST
; ++id
)
49 if (id
== THEORY_FP
&& !Configuration::isBuiltWithSymFPU())
57 LogicInfo::LogicInfo(std::string logicString
)
59 d_theories(THEORY_LAST
, false),
63 d_transcendentals(false),
65 d_differenceLogic(false),
66 d_cardinalityConstraints(false),
70 setLogicString(logicString
);
74 LogicInfo::LogicInfo(const char* logicString
)
76 d_theories(THEORY_LAST
, false),
80 d_transcendentals(false),
82 d_differenceLogic(false),
83 d_cardinalityConstraints(false),
87 setLogicString(logicString
);
91 /** Is sharing enabled for this logic? */
92 bool LogicInfo::isSharingEnabled() const {
93 PrettyCheckArgument(d_locked
, *this,
94 "This LogicInfo isn't locked yet, and cannot be queried");
95 return d_sharingTheories
> 1;
99 /** Is the given theory module active in this logic? */
100 bool LogicInfo::isTheoryEnabled(theory::TheoryId theory
) const {
101 PrettyCheckArgument(d_locked
, *this,
102 "This LogicInfo isn't locked yet, and cannot be queried");
103 return d_theories
[theory
];
106 /** Is this a quantified logic? */
107 bool LogicInfo::isQuantified() const {
108 PrettyCheckArgument(d_locked
, *this,
109 "This LogicInfo isn't locked yet, and cannot be queried");
110 return isTheoryEnabled(theory::THEORY_QUANTIFIERS
);
113 /** Is this a higher-order logic? */
114 bool LogicInfo::isHigherOrder() const
116 PrettyCheckArgument(d_locked
,
118 "This LogicInfo isn't locked yet, and cannot be queried");
119 return d_higherOrder
;
122 /** Is this the all-inclusive logic? */
123 bool LogicInfo::hasEverything() const {
124 PrettyCheckArgument(d_locked
, *this,
125 "This LogicInfo isn't locked yet, and cannot be queried");
126 LogicInfo everything
;
128 return *this == everything
;
131 /** Is this the all-exclusive logic? (Here, that means propositional logic) */
132 bool LogicInfo::hasNothing() const {
133 PrettyCheckArgument(d_locked
, *this,
134 "This LogicInfo isn't locked yet, and cannot be queried");
135 LogicInfo
nothing("");
137 return *this == nothing
;
140 bool LogicInfo::isPure(theory::TheoryId theory
) const {
141 PrettyCheckArgument(d_locked
, *this,
142 "This LogicInfo isn't locked yet, and cannot be queried");
143 // the third and fourth conjucts are really just to rule out the misleading
144 // case where you ask isPure(THEORY_BOOL) and get true even in e.g. QF_LIA
145 return isTheoryEnabled(theory
) && !isSharingEnabled() &&
146 ( !isTrueTheory(theory
) || d_sharingTheories
== 1 ) &&
147 ( isTrueTheory(theory
) || d_sharingTheories
== 0 );
150 bool LogicInfo::areIntegersUsed() const {
151 PrettyCheckArgument(d_locked
, *this,
152 "This LogicInfo isn't locked yet, and cannot be queried");
154 isTheoryEnabled(theory::THEORY_ARITH
), *this,
155 "Arithmetic not used in this LogicInfo; cannot ask whether integers are used");
159 bool LogicInfo::areRealsUsed() const {
160 PrettyCheckArgument(d_locked
, *this,
161 "This LogicInfo isn't locked yet, and cannot be queried");
163 isTheoryEnabled(theory::THEORY_ARITH
), *this,
164 "Arithmetic not used in this LogicInfo; cannot ask whether reals are used");
168 bool LogicInfo::areTranscendentalsUsed() const
170 PrettyCheckArgument(d_locked
,
172 "This LogicInfo isn't locked yet, and cannot be queried");
173 PrettyCheckArgument(isTheoryEnabled(theory::THEORY_ARITH
),
175 "Arithmetic not used in this LogicInfo; cannot ask "
176 "whether transcendentals are used");
177 return d_transcendentals
;
180 bool LogicInfo::isLinear() const {
181 PrettyCheckArgument(d_locked
, *this,
182 "This LogicInfo isn't locked yet, and cannot be queried");
184 isTheoryEnabled(theory::THEORY_ARITH
), *this,
185 "Arithmetic not used in this LogicInfo; cannot ask whether it's linear");
186 return d_linear
|| d_differenceLogic
;
189 bool LogicInfo::isDifferenceLogic() const {
190 PrettyCheckArgument(d_locked
, *this,
191 "This LogicInfo isn't locked yet, and cannot be queried");
193 isTheoryEnabled(theory::THEORY_ARITH
), *this,
194 "Arithmetic not used in this LogicInfo; cannot ask whether it's difference logic");
195 return d_differenceLogic
;
198 bool LogicInfo::hasCardinalityConstraints() const {
199 PrettyCheckArgument(d_locked
, *this,
200 "This LogicInfo isn't locked yet, and cannot be queried");
201 return d_cardinalityConstraints
;
205 bool LogicInfo::operator==(const LogicInfo
& other
) const {
206 PrettyCheckArgument(isLocked() && other
.isLocked(), *this,
207 "This LogicInfo isn't locked yet, and cannot be queried");
208 for(theory::TheoryId id
= theory::THEORY_FIRST
; id
< theory::THEORY_LAST
; ++id
) {
209 if(d_theories
[id
] != other
.d_theories
[id
]) {
214 PrettyCheckArgument(d_sharingTheories
== other
.d_sharingTheories
, *this,
215 "LogicInfo internal inconsistency");
216 bool res
= d_cardinalityConstraints
== other
.d_cardinalityConstraints
217 && d_higherOrder
== other
.d_higherOrder
;
218 if(isTheoryEnabled(theory::THEORY_ARITH
)) {
219 return d_integers
== other
.d_integers
&& d_reals
== other
.d_reals
220 && d_transcendentals
== other
.d_transcendentals
221 && d_linear
== other
.d_linear
222 && d_differenceLogic
== other
.d_differenceLogic
&& res
;
228 bool LogicInfo::operator<=(const LogicInfo
& other
) const {
229 PrettyCheckArgument(isLocked() && other
.isLocked(), *this,
230 "This LogicInfo isn't locked yet, and cannot be queried");
231 for(theory::TheoryId id
= theory::THEORY_FIRST
; id
< theory::THEORY_LAST
; ++id
) {
232 if(d_theories
[id
] && !other
.d_theories
[id
]) {
236 PrettyCheckArgument(d_sharingTheories
<= other
.d_sharingTheories
, *this,
237 "LogicInfo internal inconsistency");
238 bool res
= (!d_cardinalityConstraints
|| other
.d_cardinalityConstraints
)
239 && (!d_higherOrder
|| other
.d_higherOrder
);
240 if(isTheoryEnabled(theory::THEORY_ARITH
) && other
.isTheoryEnabled(theory::THEORY_ARITH
)) {
241 return (!d_integers
|| other
.d_integers
) && (!d_reals
|| other
.d_reals
)
242 && (!d_transcendentals
|| other
.d_transcendentals
)
243 && (d_linear
|| !other
.d_linear
)
244 && (d_differenceLogic
|| !other
.d_differenceLogic
) && res
;
250 bool LogicInfo::operator>=(const LogicInfo
& other
) const {
251 PrettyCheckArgument(isLocked() && other
.isLocked(), *this,
252 "This LogicInfo isn't locked yet, and cannot be queried");
253 for(theory::TheoryId id
= theory::THEORY_FIRST
; id
< theory::THEORY_LAST
; ++id
) {
254 if(!d_theories
[id
] && other
.d_theories
[id
]) {
258 PrettyCheckArgument(d_sharingTheories
>= other
.d_sharingTheories
, *this,
259 "LogicInfo internal inconsistency");
260 bool res
= (d_cardinalityConstraints
|| !other
.d_cardinalityConstraints
)
261 && (d_higherOrder
|| !other
.d_higherOrder
);
262 if(isTheoryEnabled(theory::THEORY_ARITH
) && other
.isTheoryEnabled(theory::THEORY_ARITH
)) {
263 return (d_integers
|| !other
.d_integers
) && (d_reals
|| !other
.d_reals
)
264 && (d_transcendentals
|| !other
.d_transcendentals
)
265 && (!d_linear
|| other
.d_linear
)
266 && (!d_differenceLogic
|| other
.d_differenceLogic
) && res
;
272 std::string
LogicInfo::getLogicString() const {
275 "This LogicInfo isn't locked yet, and cannot be queried");
276 if(d_logicString
== "") {
277 LogicInfo qf_all_supported
;
278 qf_all_supported
.disableQuantifiers();
279 qf_all_supported
.lock();
280 if(hasEverything()) {
281 d_logicString
= "ALL";
282 } else if(*this == qf_all_supported
) {
283 d_logicString
= "QF_ALL";
285 size_t seen
= 0; // make sure we support all the active theories
288 if(!isQuantified()) {
291 if (d_theories
[THEORY_SEP
])
296 if(d_theories
[THEORY_ARRAYS
]) {
297 ss
<< (d_sharingTheories
== 1 ? "AX" : "A");
300 if(d_theories
[THEORY_UF
]) {
304 if( d_cardinalityConstraints
){
307 if(d_theories
[THEORY_BV
]) {
311 if(d_theories
[THEORY_FP
]) {
315 if(d_theories
[THEORY_DATATYPES
]) {
319 if(d_theories
[THEORY_STRINGS
]) {
323 if(d_theories
[THEORY_ARITH
]) {
324 if(isDifferenceLogic()) {
325 ss
<< (areIntegersUsed() ? "I" : "");
326 ss
<< (areRealsUsed() ? "R" : "");
329 ss
<< (isLinear() ? "L" : "N");
330 ss
<< (areIntegersUsed() ? "I" : "");
331 ss
<< (areRealsUsed() ? "R" : "");
333 ss
<< (areTranscendentalsUsed() ? "T" : "");
337 if(d_theories
[THEORY_SETS
]) {
341 if (d_theories
[THEORY_BAGS
])
346 if(seen
!= d_sharingTheories
) {
348 << "can't extract a logic string from LogicInfo; at least one "
349 "active theory is unknown to LogicInfo::getLogicString() !";
356 d_logicString
= ss
.str();
359 return d_logicString
;
362 void LogicInfo::setLogicString(std::string logicString
)
364 PrettyCheckArgument(!d_locked
, *this,
365 "This LogicInfo is locked, and cannot be modified");
366 for(TheoryId id
= THEORY_FIRST
; id
< THEORY_LAST
; ++id
) {
367 d_theories
[id
] = false;// ensure it's cleared
369 d_sharingTheories
= 0;
371 // Below, ONLY use enableTheory()/disableTheory() rather than
372 // accessing d_theories[] directly. This makes sure to set up
375 enableTheory(THEORY_BUILTIN
);
376 enableTheory(THEORY_BOOL
);
378 const char* p
= logicString
.c_str();
380 // propositional logic only; we're done.
381 } else if(!strcmp(p
, "QF_SAT")) {
382 // propositional logic only; we're done.
384 } else if(!strcmp(p
, "SAT")) {
385 // quantified Boolean formulas only; we're done.
388 } else if(!strcmp(p
, "QF_ALL_SUPPORTED")) {
389 // the "all theories included" logic, no quantifiers
391 disableQuantifiers();
394 } else if(!strcmp(p
, "QF_ALL")) {
395 // the "all theories included" logic, no quantifiers
397 disableQuantifiers();
400 } else if(!strcmp(p
, "ALL_SUPPORTED")) {
401 // the "all theories included" logic, with quantifiers
406 } else if(!strcmp(p
, "ALL")) {
407 // the "all theories included" logic, with quantifiers
413 else if (!strcmp(p
, "HORN"))
421 if(!strncmp(p
, "QF_", 3)) {
422 disableQuantifiers();
427 if (!strncmp(p
, "SEP_", 4))
429 enableSeparationLogic();
432 if(!strncmp(p
, "AX", 2)) {
433 enableTheory(THEORY_ARRAYS
);
437 enableTheory(THEORY_ARRAYS
);
440 if(!strncmp(p
, "UF", 2)) {
441 enableTheory(THEORY_UF
);
444 if(!strncmp(p
, "C", 1 )) {
445 d_cardinalityConstraints
= true;
448 // allow BV or DT in either order
449 if(!strncmp(p
, "BV", 2)) {
450 enableTheory(THEORY_BV
);
453 if(!strncmp(p
, "FP", 2)) {
454 enableTheory(THEORY_FP
);
457 if(!strncmp(p
, "DT", 2)) {
458 enableTheory(THEORY_DATATYPES
);
461 if(!d_theories
[THEORY_BV
] && !strncmp(p
, "BV", 2)) {
462 enableTheory(THEORY_BV
);
466 enableTheory(THEORY_STRINGS
);
469 if(!strncmp(p
, "IDL", 3)) {
472 arithOnlyDifference();
474 } else if(!strncmp(p
, "RDL", 3)) {
477 arithOnlyDifference();
479 } else if(!strncmp(p
, "IRDL", 4)) {
480 // "IRDL" ?! --not very useful, but getLogicString() can produce
481 // that string, so we really had better be able to read it back in.
484 arithOnlyDifference();
486 } else if(!strncmp(p
, "LIA", 3)) {
491 } else if(!strncmp(p
, "LRA", 3)) {
496 } else if(!strncmp(p
, "LIRA", 4)) {
501 } else if(!strncmp(p
, "NIA", 3)) {
506 } else if(!strncmp(p
, "NRA", 3)) {
513 arithTranscendentals();
516 } else if(!strncmp(p
, "NIRA", 4)) {
523 arithTranscendentals();
527 if(!strncmp(p
, "FS", 2)) {
528 enableTheory(THEORY_SETS
);
534 if (d_theories
[THEORY_FP
])
536 // THEORY_BV is needed for bit-blasting.
537 // We have to set this here rather than in expandDefinition as it
538 // is possible to create variables without any theory specific
539 // operations, so expandDefinition won't be called.
540 enableTheory(THEORY_BV
);
545 err
<< "LogicInfo::setLogicString(): ";
546 if(p
== logicString
) {
547 err
<< "cannot parse logic string: " << logicString
;
549 err
<< "junk (\"" << p
<< "\") at end of logic string: " << logicString
;
551 IllegalArgument(logicString
, err
.str().c_str());
554 // ensure a getLogic() returns the same thing as was set
555 d_logicString
= logicString
;
558 void LogicInfo::enableEverything() {
559 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
563 void LogicInfo::disableEverything() {
564 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
565 *this = LogicInfo("");
568 void LogicInfo::enableTheory(theory::TheoryId theory
) {
569 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
570 if(!d_theories
[theory
]) {
571 if(isTrueTheory(theory
)) {
575 d_theories
[theory
] = true;
579 void LogicInfo::disableTheory(theory::TheoryId theory
) {
580 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
581 if(d_theories
[theory
]) {
582 if(isTrueTheory(theory
)) {
583 Assert(d_sharingTheories
> 0);
586 if(theory
== THEORY_BUILTIN
||
587 theory
== THEORY_BOOL
) {
591 d_theories
[theory
] = false;
595 void LogicInfo::enableSygus()
598 enableTheory(THEORY_UF
);
599 enableTheory(THEORY_DATATYPES
);
604 void LogicInfo::enableSeparationLogic()
606 enableTheory(THEORY_SEP
);
607 enableTheory(THEORY_UF
);
608 enableTheory(THEORY_SETS
);
611 void LogicInfo::enableIntegers() {
612 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
614 enableTheory(THEORY_ARITH
);
618 void LogicInfo::disableIntegers() {
619 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
623 disableTheory(THEORY_ARITH
);
627 void LogicInfo::enableReals() {
628 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
630 enableTheory(THEORY_ARITH
);
634 void LogicInfo::disableReals() {
635 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
639 disableTheory(THEORY_ARITH
);
643 void LogicInfo::arithTranscendentals()
646 !d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
648 d_transcendentals
= true;
659 void LogicInfo::arithOnlyDifference() {
660 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
663 d_differenceLogic
= true;
664 d_transcendentals
= false;
667 void LogicInfo::arithOnlyLinear() {
668 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
671 d_differenceLogic
= false;
672 d_transcendentals
= false;
675 void LogicInfo::arithNonLinear() {
676 PrettyCheckArgument(!d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
679 d_differenceLogic
= false;
682 void LogicInfo::enableCardinalityConstraints()
685 !d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
687 d_cardinalityConstraints
= true;
690 void LogicInfo::disableCardinalityConstraints()
693 !d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
695 d_cardinalityConstraints
= false;
698 void LogicInfo::enableHigherOrder()
701 !d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
703 d_higherOrder
= true;
706 void LogicInfo::disableHigherOrder()
709 !d_locked
, *this, "This LogicInfo is locked, and cannot be modified");
711 d_higherOrder
= false;
714 LogicInfo
LogicInfo::getUnlockedCopy() const {
716 LogicInfo info
= *this;
717 info
.d_locked
= false;
724 std::ostream
& operator<<(std::ostream
& out
, const LogicInfo
& logic
) {
725 return out
<< logic
.getLogicString();
728 }/* CVC4 namespace */