1 /********************* */
4 ** Top contributors (to current version):
5 ** Tim King, Andrew Reynolds, Dejan Jovanovic
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2018 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 Base for theory interface.
14 ** Base for theory interface.
17 #include "theory/theory.h"
24 #include "base/cvc4_assert.h"
25 #include "expr/node_algorithm.h"
26 #include "smt/smt_statistics_registry.h"
27 #include "theory/ext_theory.h"
28 #include "theory/quantifiers_engine.h"
29 #include "theory/substitutions.h"
36 /** Default value for the uninterpreted sorts is the UF theory */
37 TheoryId
Theory::s_uninterpretedSortOwner
= THEORY_UF
;
39 std::ostream
& operator<<(std::ostream
& os
, Theory::Effort level
){
41 case Theory::EFFORT_STANDARD
:
42 os
<< "EFFORT_STANDARD"; break;
43 case Theory::EFFORT_FULL
:
44 os
<< "EFFORT_FULL"; break;
45 case Theory::EFFORT_COMBINATION
:
46 os
<< "EFFORT_COMBINATION"; break;
47 case Theory::EFFORT_LAST_CALL
:
48 os
<< "EFFORT_LAST_CALL"; break;
53 }/* ostream& operator<<(ostream&, Theory::Effort) */
55 Theory::Theory(TheoryId id
,
56 context::Context
* satContext
,
57 context::UserContext
* userContext
,
60 const LogicInfo
& logicInfo
,
64 d_satContext(satContext
),
65 d_userContext(userContext
),
66 d_logicInfo(logicInfo
),
68 d_factsHead(satContext
, 0),
69 d_sharedTermsIndex(satContext
, 0),
72 d_decManager(nullptr),
74 d_checkTime(getStatsPrefix(id
) + name
+ "::checkTime"),
75 d_computeCareGraphTime(getStatsPrefix(id
) + name
76 + "::computeCareGraphTime"),
77 d_sharedTerms(satContext
),
79 d_valuation(valuation
),
80 d_proofsEnabled(false)
82 smtStatisticsRegistry()->registerStat(&d_checkTime
);
83 smtStatisticsRegistry()->registerStat(&d_computeCareGraphTime
);
87 smtStatisticsRegistry()->unregisterStat(&d_checkTime
);
88 smtStatisticsRegistry()->unregisterStat(&d_computeCareGraphTime
);
93 TheoryId
Theory::theoryOf(TheoryOfMode mode
, TNode node
) {
94 TheoryId tid
= THEORY_BUILTIN
;
96 case THEORY_OF_TYPE_BASED
:
97 // Constants, variables, 0-ary constructors
99 if( node
.getKind() == kind::BOOLEAN_TERM_VARIABLE
){
102 tid
= Theory::theoryOf(node
.getType());
104 }else if (node
.isConst()) {
105 tid
= Theory::theoryOf(node
.getType());
106 } else if (node
.getKind() == kind::EQUAL
) {
107 // Equality is owned by the theory that owns the domain
108 tid
= Theory::theoryOf(node
[0].getType());
110 // Regular nodes are owned by the kind
111 tid
= kindToTheoryId(node
.getKind());
114 case THEORY_OF_TERM_BASED
:
117 if (Theory::theoryOf(node
.getType()) != theory::THEORY_BOOL
) {
118 // We treat the variables as uninterpreted
119 tid
= s_uninterpretedSortOwner
;
121 if( node
.getKind() == kind::BOOLEAN_TERM_VARIABLE
){
122 //Boolean vars go to UF
125 // Except for the Boolean ones
129 } else if (node
.isConst()) {
130 // Constants go to the theory of the type
131 tid
= Theory::theoryOf(node
.getType());
132 } else if (node
.getKind() == kind::EQUAL
) { // Equality
133 // If one of them is an ITE, it's irelevant, since they will get replaced out anyhow
134 if (node
[0].getKind() == kind::ITE
) {
135 tid
= Theory::theoryOf(node
[0].getType());
136 } else if (node
[1].getKind() == kind::ITE
) {
137 tid
= Theory::theoryOf(node
[1].getType());
141 TypeNode ltype
= l
.getType();
142 TypeNode rtype
= r
.getType();
143 if( ltype
!= rtype
){
144 tid
= Theory::theoryOf(l
.getType());
146 // If both sides belong to the same theory the choice is easy
147 TheoryId T1
= Theory::theoryOf(l
);
148 TheoryId T2
= Theory::theoryOf(r
);
152 TheoryId T3
= Theory::theoryOf(ltype
);
154 // * x*y = f(z) -> UF
156 // * f(x) = read(a, y) -> either UF or ARRAY
157 // at least one of the theories has to be parametric, i.e. theory of the type is different
158 // from the theory of the term
161 } else if (T2
== T3
) {
164 // If both are parametric, we take the smaller one (arbitrary)
165 tid
= T1
< T2
? T1
: T2
;
171 // Regular nodes are owned by the kind
172 tid
= kindToTheoryId(node
.getKind());
178 Trace("theory::internal") << "theoryOf(" << mode
<< ", " << node
<< ") -> " << tid
<< std::endl
;
182 void Theory::addSharedTermInternal(TNode n
) {
183 Debug("sharing") << "Theory::addSharedTerm<" << getId() << ">(" << n
<< ")" << endl
;
184 Debug("theory::assertions") << "Theory::addSharedTerm<" << getId() << ">(" << n
<< ")" << endl
;
185 d_sharedTerms
.push_back(n
);
189 void Theory::computeCareGraph() {
190 Debug("sharing") << "Theory::computeCareGraph<" << getId() << ">()" << endl
;
191 for (unsigned i
= 0; i
< d_sharedTerms
.size(); ++ i
) {
192 TNode a
= d_sharedTerms
[i
];
193 TypeNode aType
= a
.getType();
194 for (unsigned j
= i
+ 1; j
< d_sharedTerms
.size(); ++ j
) {
195 TNode b
= d_sharedTerms
[j
];
196 if (b
.getType() != aType
) {
197 // We don't care about the terms of different types
200 switch (d_valuation
.getEqualityStatus(a
, b
)) {
201 case EQUALITY_TRUE_AND_PROPAGATED
:
202 case EQUALITY_FALSE_AND_PROPAGATED
:
203 // If we know about it, we should have propagated it, so we can skip
214 void Theory::printFacts(std::ostream
& os
) const {
215 unsigned i
, n
= d_facts
.size();
216 for(i
= 0; i
< n
; i
++){
217 const Assertion
& a_i
= d_facts
[i
];
218 Node assertion
= a_i
;
219 os
<< d_id
<< '[' << i
<< ']' << " " << assertion
<< endl
;
223 void Theory::debugPrintFacts() const{
224 DebugChannel
.getStream() << "Theory::debugPrintFacts()" << endl
;
225 printFacts(DebugChannel
.getStream());
228 std::unordered_set
<TNode
, TNodeHashFunction
> Theory::currentlySharedTerms() const{
229 std::unordered_set
<TNode
, TNodeHashFunction
> currentlyShared
;
230 for (shared_terms_iterator i
= shared_terms_begin(),
231 i_end
= shared_terms_end(); i
!= i_end
; ++i
) {
232 currentlyShared
.insert (*i
);
234 return currentlyShared
;
237 void Theory::collectTerms(TNode n
,
239 set
<Node
>& termSet
) const
241 if (termSet
.find(n
) != termSet
.end()) {
244 Kind nk
= n
.getKind();
245 if (irrKinds
.find(nk
) == irrKinds
.end())
247 Trace("theory::collectTerms")
248 << "Theory::collectTerms: adding " << n
<< endl
;
251 if (nk
== kind::NOT
|| nk
== kind::EQUAL
|| !isLeaf(n
))
253 for(TNode::iterator child_it
= n
.begin(); child_it
!= n
.end(); ++child_it
) {
254 collectTerms(*child_it
, irrKinds
, termSet
);
260 void Theory::computeRelevantTerms(set
<Node
>& termSet
, bool includeShared
) const
263 computeRelevantTerms(termSet
, irrKinds
, includeShared
);
266 void Theory::computeRelevantTerms(set
<Node
>& termSet
,
268 bool includeShared
) const
270 // Collect all terms appearing in assertions
271 irrKinds
.insert(kind::EQUAL
);
272 irrKinds
.insert(kind::NOT
);
273 context::CDList
<Assertion
>::const_iterator assert_it
= facts_begin(), assert_it_end
= facts_end();
274 for (; assert_it
!= assert_it_end
; ++assert_it
) {
275 collectTerms(*assert_it
, irrKinds
, termSet
);
278 if (!includeShared
) return;
280 // Add terms that are shared terms
282 context::CDList
<TNode
>::const_iterator shared_it
= shared_terms_begin(), shared_it_end
= shared_terms_end();
283 for (; shared_it
!= shared_it_end
; ++shared_it
) {
284 collectTerms(*shared_it
, kempty
, termSet
);
288 Theory::PPAssertStatus
Theory::ppAssert(TNode in
,
289 SubstitutionMap
& outSubstitutions
)
291 if (in
.getKind() == kind::EQUAL
)
293 // (and (= x t) phi) can be replaced by phi[x/t] if
294 // 1) x is a variable
295 // 2) x is not in the term t
296 // 3) x : T and t : S, then S <: T
297 if (in
[0].isVar() && !expr::hasSubterm(in
[1], in
[0])
298 && (in
[1].getType()).isSubtypeOf(in
[0].getType()))
300 outSubstitutions
.addSubstitution(in
[0], in
[1]);
301 return PP_ASSERT_STATUS_SOLVED
;
303 if (in
[1].isVar() && !expr::hasSubterm(in
[0], in
[1])
304 && (in
[0].getType()).isSubtypeOf(in
[1].getType()))
306 outSubstitutions
.addSubstitution(in
[1], in
[0]);
307 return PP_ASSERT_STATUS_SOLVED
;
309 if (in
[0].isConst() && in
[1].isConst())
313 return PP_ASSERT_STATUS_CONFLICT
;
318 return PP_ASSERT_STATUS_UNSOLVED
;
321 std::pair
<bool, Node
> Theory::entailmentCheck(
323 const EntailmentCheckParameters
* params
,
324 EntailmentCheckSideEffects
* out
) {
325 return make_pair(false, Node::null());
328 ExtTheory
* Theory::getExtTheory() {
329 Assert(d_extTheory
!= NULL
);
333 void Theory::addCarePair(TNode t1
, TNode t2
) {
335 d_careGraph
->insert(CarePair(t1
, t2
, d_id
));
339 void Theory::getCareGraph(CareGraph
* careGraph
) {
340 Assert(careGraph
!= NULL
);
342 Trace("sharing") << "Theory<" << getId() << ">::getCareGraph()" << std::endl
;
343 TimerStat::CodeTimer
computeCareGraphTime(d_computeCareGraphTime
);
344 d_careGraph
= careGraph
;
349 void Theory::setQuantifiersEngine(QuantifiersEngine
* qe
) {
350 Assert(d_quantEngine
== NULL
);
355 void Theory::setDecisionManager(DecisionManager
* dm
)
357 Assert(d_decManager
== nullptr);
358 Assert(dm
!= nullptr);
362 void Theory::setupExtTheory() {
363 Assert(d_extTheory
== NULL
);
364 d_extTheory
= new ExtTheory(this);
368 EntailmentCheckParameters::EntailmentCheckParameters(TheoryId tid
)
372 EntailmentCheckParameters::~EntailmentCheckParameters(){}
374 TheoryId
EntailmentCheckParameters::getTheoryId() const {
378 EntailmentCheckSideEffects::EntailmentCheckSideEffects(TheoryId tid
)
382 TheoryId
EntailmentCheckSideEffects::getTheoryId() const {
386 EntailmentCheckSideEffects::~EntailmentCheckSideEffects() {
389 }/* CVC4::theory namespace */
390 }/* CVC4 namespace */