1 /********************* */
2 /*! \file shared_terms_database.cpp
4 ** Top contributors (to current version):
5 ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters
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 ** [[ Add lengthier description here ]]
13 ** \todo document this file
16 #include "theory/shared_terms_database.h"
18 #include "smt/smt_statistics_registry.h"
19 #include "theory/theory_engine.h"
22 using namespace CVC4::theory
;
26 SharedTermsDatabase::SharedTermsDatabase(TheoryEngine
* theoryEngine
,
27 context::Context
* context
,
28 context::UserContext
* userContext
,
29 ProofNodeManager
* pnm
)
30 : ContextNotifyObj(context
),
31 d_statSharedTerms("theory::shared_terms", 0),
32 d_addedSharedTermsSize(context
, 0),
33 d_termsToTheories(context
),
34 d_alreadyNotifiedMap(context
),
35 d_registeredEqualities(context
),
37 d_theoryEngine(theoryEngine
),
38 d_inConflict(context
, false),
40 d_satContext(context
),
41 d_userContext(userContext
),
42 d_equalityEngine(nullptr),
46 smtStatisticsRegistry()->registerStat(&d_statSharedTerms
);
49 SharedTermsDatabase::~SharedTermsDatabase()
51 smtStatisticsRegistry()->unregisterStat(&d_statSharedTerms
);
54 void SharedTermsDatabase::setEqualityEngine(eq::EqualityEngine
* ee
)
56 Assert(ee
!= nullptr);
57 d_equalityEngine
= ee
;
58 // if proofs are enabled, make the proof equality engine
62 new eq::ProofEqEngine(d_satContext
, d_userContext
, *ee
, d_pnm
));
66 bool SharedTermsDatabase::needsEqualityEngine(EeSetupInfo
& esi
)
68 esi
.d_notify
= &d_EENotify
;
69 esi
.d_name
= "SharedTermsDatabase";
73 void SharedTermsDatabase::addEqualityToPropagate(TNode equality
) {
74 Assert(d_equalityEngine
!= nullptr);
75 d_registeredEqualities
.insert(equality
);
76 d_equalityEngine
->addTriggerPredicate(equality
);
80 void SharedTermsDatabase::addSharedTerm(TNode atom
,
84 Debug("register") << "SharedTermsDatabase::addSharedTerm(" << atom
<< ", "
85 << term
<< ", " << TheoryIdSetUtil::setToString(theories
)
88 std::pair
<TNode
, TNode
> search_pair(atom
, term
);
89 SharedTermsTheoriesMap::iterator find
= d_termsToTheories
.find(search_pair
);
90 if (find
== d_termsToTheories
.end()) {
91 // First time for this term and this atom
92 d_atomsToTerms
[atom
].push_back(term
);
93 d_addedSharedTerms
.push_back(atom
);
94 d_addedSharedTermsSize
= d_addedSharedTermsSize
+ 1;
95 d_termsToTheories
[search_pair
] = theories
;
97 Assert(theories
!= (*find
).second
);
98 d_termsToTheories
[search_pair
] =
99 TheoryIdSetUtil::setUnion(theories
, (*find
).second
);
103 SharedTermsDatabase::shared_terms_iterator
SharedTermsDatabase::begin(TNode atom
) const {
104 Assert(hasSharedTerms(atom
));
105 return d_atomsToTerms
.find(atom
)->second
.begin();
108 SharedTermsDatabase::shared_terms_iterator
SharedTermsDatabase::end(TNode atom
) const {
109 Assert(hasSharedTerms(atom
));
110 return d_atomsToTerms
.find(atom
)->second
.end();
113 bool SharedTermsDatabase::hasSharedTerms(TNode atom
) const {
114 return d_atomsToTerms
.find(atom
) != d_atomsToTerms
.end();
117 void SharedTermsDatabase::backtrack() {
118 for (int i
= d_addedSharedTerms
.size() - 1, i_end
= (int)d_addedSharedTermsSize
; i
>= i_end
; -- i
) {
119 TNode atom
= d_addedSharedTerms
[i
];
120 shared_terms_list
& list
= d_atomsToTerms
[atom
];
123 d_atomsToTerms
.erase(atom
);
126 d_addedSharedTerms
.resize(d_addedSharedTermsSize
);
129 TheoryIdSet
SharedTermsDatabase::getTheoriesToNotify(TNode atom
,
132 // Get the theories that share this term from this atom
133 std::pair
<TNode
, TNode
> search_pair(atom
, term
);
134 SharedTermsTheoriesMap::iterator find
= d_termsToTheories
.find(search_pair
);
135 Assert(find
!= d_termsToTheories
.end());
137 // Get the theories that were already notified
138 TheoryIdSet alreadyNotified
= 0;
139 AlreadyNotifiedMap::iterator theoriesFind
= d_alreadyNotifiedMap
.find(term
);
140 if (theoriesFind
!= d_alreadyNotifiedMap
.end()) {
141 alreadyNotified
= (*theoriesFind
).second
;
144 // Return the ones that haven't been notified yet
145 return TheoryIdSetUtil::setDifference((*find
).second
, alreadyNotified
);
148 TheoryIdSet
SharedTermsDatabase::getNotifiedTheories(TNode term
) const
150 // Get the theories that were already notified
151 AlreadyNotifiedMap::iterator theoriesFind
= d_alreadyNotifiedMap
.find(term
);
152 if (theoriesFind
!= d_alreadyNotifiedMap
.end()) {
153 return (*theoriesFind
).second
;
159 bool SharedTermsDatabase::propagateSharedEquality(TheoryId theory
, TNode a
, TNode b
, bool value
)
161 Debug("shared-terms-database") << "SharedTermsDatabase::newEquality(" << theory
<< "," << a
<< "," << b
<< ", " << (value
? "true" : "false") << ")" << endl
;
168 Node equality
= a
.eqNode(b
);
170 d_theoryEngine
->assertToTheory(equality
, equality
, theory
, THEORY_BUILTIN
);
172 d_theoryEngine
->assertToTheory(equality
.notNode(), equality
.notNode(), theory
, THEORY_BUILTIN
);
179 void SharedTermsDatabase::markNotified(TNode term
, TheoryIdSet theories
)
181 // Find out if there are any new theories that were notified about this term
182 TheoryIdSet alreadyNotified
= 0;
183 AlreadyNotifiedMap::iterator theoriesFind
= d_alreadyNotifiedMap
.find(term
);
184 if (theoriesFind
!= d_alreadyNotifiedMap
.end()) {
185 alreadyNotified
= (*theoriesFind
).second
;
187 TheoryIdSet newlyNotified
=
188 TheoryIdSetUtil::setDifference(theories
, alreadyNotified
);
190 // If no new theories were notified, we are done
191 if (newlyNotified
== 0) {
195 Debug("shared-terms-database") << "SharedTermsDatabase::markNotified(" << term
<< ")" << endl
;
197 // First update the set of notified theories for this term
198 d_alreadyNotifiedMap
[term
] =
199 TheoryIdSetUtil::setUnion(newlyNotified
, alreadyNotified
);
201 if (d_equalityEngine
== nullptr)
203 // if we are not assigned an equality engine, there is nothing to do
207 // Mark the shared terms in the equality engine
208 theory::TheoryId currentTheory
;
209 while ((currentTheory
= TheoryIdSetUtil::setPop(newlyNotified
))
212 d_equalityEngine
->addTriggerTerm(term
, currentTheory
);
215 // Check for any conflits
219 bool SharedTermsDatabase::areEqual(TNode a
, TNode b
) const {
220 Assert(d_equalityEngine
!= nullptr);
221 if (d_equalityEngine
->hasTerm(a
) && d_equalityEngine
->hasTerm(b
))
223 return d_equalityEngine
->areEqual(a
, b
);
225 Assert(d_equalityEngine
->hasTerm(a
) || a
.isConst());
226 Assert(d_equalityEngine
->hasTerm(b
) || b
.isConst());
227 // since one (or both) of them is a constant, and the other is in the equality engine, they are not same
232 bool SharedTermsDatabase::areDisequal(TNode a
, TNode b
) const {
233 Assert(d_equalityEngine
!= nullptr);
234 if (d_equalityEngine
->hasTerm(a
) && d_equalityEngine
->hasTerm(b
))
236 return d_equalityEngine
->areDisequal(a
, b
, false);
238 Assert(d_equalityEngine
->hasTerm(a
) || a
.isConst());
239 Assert(d_equalityEngine
->hasTerm(b
) || b
.isConst());
240 // one (or both) are in the equality engine
245 theory::eq::EqualityEngine
* SharedTermsDatabase::getEqualityEngine()
247 return d_equalityEngine
;
250 void SharedTermsDatabase::assertEquality(TNode equality
, bool polarity
, TNode reason
)
252 Assert(d_equalityEngine
!= nullptr);
253 Debug("shared-terms-database::assert") << "SharedTermsDatabase::assertEquality(" << equality
<< ", " << (polarity
? "true" : "false") << ", " << reason
<< ")" << endl
;
254 // Add it to the equality engine
255 d_equalityEngine
->assertEquality(equality
, polarity
, reason
);
256 // Check for conflict
260 bool SharedTermsDatabase::propagateEquality(TNode equality
, bool polarity
) {
262 d_theoryEngine
->propagate(equality
, THEORY_BUILTIN
);
264 d_theoryEngine
->propagate(equality
.notNode(), THEORY_BUILTIN
);
269 void SharedTermsDatabase::checkForConflict()
275 d_inConflict
= false;
277 if (d_pfee
!= nullptr)
279 Node conflict
= d_conflictLHS
.eqNode(d_conflictRHS
);
280 conflict
= d_conflictPolarity
? conflict
: conflict
.notNode();
281 trnc
= d_pfee
->assertConflict(conflict
);
286 std::vector
<TNode
> assumptions
;
287 d_equalityEngine
->explainEquality(
288 d_conflictLHS
, d_conflictRHS
, d_conflictPolarity
, assumptions
);
289 Node conflictNode
= NodeManager::currentNM()->mkAnd(assumptions
);
290 trnc
= TrustNode::mkTrustConflict(conflictNode
, nullptr);
292 d_theoryEngine
->conflict(trnc
, THEORY_BUILTIN
);
293 d_conflictLHS
= d_conflictRHS
= Node::null();
296 bool SharedTermsDatabase::isKnown(TNode literal
) const {
297 Assert(d_equalityEngine
!= nullptr);
298 bool polarity
= literal
.getKind() != kind::NOT
;
299 TNode equality
= polarity
? literal
: literal
[0];
301 return d_equalityEngine
->areEqual(equality
[0], equality
[1]);
303 return d_equalityEngine
->areDisequal(equality
[0], equality
[1], false);
307 theory::TrustNode
SharedTermsDatabase::explain(TNode literal
) const
309 if (d_pfee
!= nullptr)
311 // use the proof equality engine if it exists
312 return d_pfee
->explain(literal
);
314 // otherwise, explain without proofs
315 Node exp
= d_equalityEngine
->mkExplainLit(literal
);
316 // no proof generator
317 return TrustNode::mkTrustPropExp(literal
, exp
, nullptr);
320 } /* namespace CVC4 */