1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 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. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* Equality engine manager for central equality engine architecture |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/ee_manager_central.h" |
17 |
|
|
18 |
|
#include "smt/env.h" |
19 |
|
#include "theory/quantifiers_engine.h" |
20 |
|
#include "theory/shared_solver.h" |
21 |
|
#include "theory/theory_engine.h" |
22 |
|
#include "theory/theory_state.h" |
23 |
|
|
24 |
|
namespace cvc5 { |
25 |
|
namespace theory { |
26 |
|
|
27 |
37 |
EqEngineManagerCentral::EqEngineManagerCentral(Env& env, |
28 |
|
TheoryEngine& te, |
29 |
37 |
SharedSolver& shs) |
30 |
|
: EqEngineManager(env, te, shs), |
31 |
|
d_masterEENotify(nullptr), |
32 |
|
d_masterEqualityEngine(nullptr), |
33 |
|
d_centralEENotify(*this), |
34 |
|
d_centralEqualityEngine( |
35 |
37 |
env, context(), d_centralEENotify, "central::ee", true) |
36 |
|
{ |
37 |
518 |
for (TheoryId theoryId = theory::THEORY_FIRST; |
38 |
518 |
theoryId != theory::THEORY_LAST; |
39 |
|
++theoryId) |
40 |
|
{ |
41 |
481 |
d_theoryNotify[theoryId] = nullptr; |
42 |
|
} |
43 |
37 |
if (env.isTheoryProofProducing()) |
44 |
|
{ |
45 |
8 |
d_centralPfee = |
46 |
16 |
std::make_unique<eq::ProofEqEngine>(env, d_centralEqualityEngine); |
47 |
8 |
d_centralEqualityEngine.setProofEqualityEngine(d_centralPfee.get()); |
48 |
|
} |
49 |
37 |
} |
50 |
|
|
51 |
74 |
EqEngineManagerCentral::~EqEngineManagerCentral() {} |
52 |
|
|
53 |
37 |
void EqEngineManagerCentral::initializeTheories() |
54 |
|
{ |
55 |
37 |
context::Context* c = context(); |
56 |
|
// initialize the shared solver |
57 |
74 |
EeSetupInfo esis; |
58 |
37 |
if (d_sharedSolver.needsEqualityEngine(esis)) |
59 |
|
{ |
60 |
|
// the shared solver uses central equality engine |
61 |
37 |
d_sharedSolver.setEqualityEngine(&d_centralEqualityEngine); |
62 |
|
} |
63 |
|
else |
64 |
|
{ |
65 |
|
Unreachable() << "Expected shared solver to use equality engine"; |
66 |
|
} |
67 |
|
// whether to use master equality engine as central |
68 |
37 |
bool masterEqToCentral = true; |
69 |
|
// setup info for each theory |
70 |
74 |
std::map<TheoryId, EeSetupInfo> esiMap; |
71 |
|
// set of theories that need equality engines |
72 |
74 |
std::unordered_set<TheoryId> eeTheories; |
73 |
37 |
const LogicInfo& logicInfo = d_te.getLogicInfo(); |
74 |
518 |
for (TheoryId theoryId = theory::THEORY_FIRST; |
75 |
518 |
theoryId != theory::THEORY_LAST; |
76 |
|
++theoryId) |
77 |
|
{ |
78 |
481 |
Theory* t = d_te.theoryOf(theoryId); |
79 |
481 |
if (t == nullptr) |
80 |
|
{ |
81 |
|
// theory not active, skip |
82 |
|
continue; |
83 |
|
} |
84 |
481 |
if (!t->needsEqualityEngine(esiMap[theoryId])) |
85 |
|
{ |
86 |
|
// theory said it doesn't need an equality engine, skip |
87 |
74 |
continue; |
88 |
|
} |
89 |
|
// otherwise add it to the set of equality engine theories |
90 |
407 |
eeTheories.insert(theoryId); |
91 |
|
// if the logic has a theory that does not use central equality engine, |
92 |
|
// we can't use the central equality engine for the master equality |
93 |
|
// engine |
94 |
1184 |
if (theoryId != THEORY_QUANTIFIERS && logicInfo.isTheoryEnabled(theoryId) |
95 |
777 |
&& !Theory::usesCentralEqualityEngine(theoryId)) |
96 |
|
{ |
97 |
|
Trace("ee-central") << "Must use separate master equality engine due to " |
98 |
|
<< theoryId << std::endl; |
99 |
|
masterEqToCentral = false; |
100 |
|
} |
101 |
|
} |
102 |
|
|
103 |
|
// initialize the master equality engine, which may be the central equality |
104 |
|
// engine |
105 |
37 |
if (logicInfo.isQuantified()) |
106 |
|
{ |
107 |
|
// construct the master equality engine |
108 |
37 |
Assert(d_masterEqualityEngine == nullptr); |
109 |
37 |
QuantifiersEngine* qe = d_te.getQuantifiersEngine(); |
110 |
37 |
Assert(qe != nullptr); |
111 |
37 |
d_masterEENotify.reset(new quantifiers::MasterNotifyClass(qe)); |
112 |
37 |
if (!masterEqToCentral) |
113 |
|
{ |
114 |
|
d_masterEqualityEngineAlloc = std::make_unique<eq::EqualityEngine>( |
115 |
|
d_env, c, *d_masterEENotify.get(), "master::ee", false); |
116 |
|
d_masterEqualityEngine = d_masterEqualityEngineAlloc.get(); |
117 |
|
} |
118 |
|
else |
119 |
|
{ |
120 |
74 |
Trace("ee-central") |
121 |
37 |
<< "Master equality engine is the central equality engine" |
122 |
37 |
<< std::endl; |
123 |
37 |
d_masterEqualityEngine = &d_centralEqualityEngine; |
124 |
37 |
d_centralEENotify.d_newClassNotify.push_back(d_masterEENotify.get()); |
125 |
|
} |
126 |
|
} |
127 |
|
|
128 |
|
// allocate equality engines per theory |
129 |
518 |
for (TheoryId theoryId = theory::THEORY_FIRST; |
130 |
518 |
theoryId != theory::THEORY_LAST; |
131 |
|
++theoryId) |
132 |
|
{ |
133 |
962 |
Trace("ee-central") << "Setup equality engine for " << theoryId |
134 |
481 |
<< std::endl; |
135 |
|
// always allocate an object in d_einfo here |
136 |
481 |
EeTheoryInfo& eet = d_einfo[theoryId]; |
137 |
555 |
if (eeTheories.find(theoryId) == eeTheories.end()) |
138 |
|
{ |
139 |
148 |
Trace("ee-central") << "..." << theoryId << " does not need ee" |
140 |
74 |
<< std::endl; |
141 |
555 |
continue; |
142 |
|
} |
143 |
407 |
Theory* t = d_te.theoryOf(theoryId); |
144 |
407 |
Assert(t != nullptr); |
145 |
407 |
Assert(esiMap.find(theoryId) != esiMap.end()); |
146 |
407 |
EeSetupInfo& esi = esiMap[theoryId]; |
147 |
444 |
if (esi.d_useMaster) |
148 |
|
{ |
149 |
37 |
Trace("ee-central") << "...uses master" << std::endl; |
150 |
|
// the theory said it wants to use the master equality engine |
151 |
37 |
eet.d_usedEe = d_masterEqualityEngine; |
152 |
37 |
continue; |
153 |
|
} |
154 |
|
// set the notify |
155 |
370 |
eq::EqualityEngineNotify* notify = esi.d_notify; |
156 |
370 |
d_theoryNotify[theoryId] = notify; |
157 |
|
// split on whether integrated, or whether asked for master |
158 |
740 |
if (t->usesCentralEqualityEngine()) |
159 |
|
{ |
160 |
370 |
Trace("ee-central") << "...uses central" << std::endl; |
161 |
|
// the theory uses the central equality engine |
162 |
370 |
eet.d_usedEe = &d_centralEqualityEngine; |
163 |
370 |
if (logicInfo.isTheoryEnabled(theoryId)) |
164 |
|
{ |
165 |
|
// add to vectors for the kinds of notifications |
166 |
370 |
if (esi.needsNotifyNewClass()) |
167 |
|
{ |
168 |
148 |
d_centralEENotify.d_newClassNotify.push_back(notify); |
169 |
|
} |
170 |
370 |
if (esi.needsNotifyMerge()) |
171 |
|
{ |
172 |
185 |
d_centralEENotify.d_mergeNotify.push_back(notify); |
173 |
|
} |
174 |
370 |
if (esi.needsNotifyDisequal()) |
175 |
|
{ |
176 |
74 |
d_centralEENotify.d_disequalNotify.push_back(notify); |
177 |
|
} |
178 |
|
} |
179 |
370 |
continue; |
180 |
|
} |
181 |
|
Trace("ee-central") << "...uses new" << std::endl; |
182 |
|
eet.d_allocEe.reset(allocateEqualityEngine(esi, c)); |
183 |
|
// the theory uses the equality engine |
184 |
|
eet.d_usedEe = eet.d_allocEe.get(); |
185 |
|
if (!masterEqToCentral) |
186 |
|
{ |
187 |
|
// set the master equality engine of the theory's equality engine |
188 |
|
eet.d_allocEe->setMasterEqualityEngine(d_masterEqualityEngine); |
189 |
|
} |
190 |
|
} |
191 |
|
|
192 |
|
// set the master equality engine of the theory's equality engine |
193 |
37 |
if (!masterEqToCentral) |
194 |
|
{ |
195 |
|
d_centralEqualityEngine.setMasterEqualityEngine(d_masterEqualityEngine); |
196 |
|
} |
197 |
37 |
} |
198 |
|
|
199 |
|
void EqEngineManagerCentral::notifyBuildingModel() {} |
200 |
|
|
201 |
37 |
EqEngineManagerCentral::CentralNotifyClass::CentralNotifyClass( |
202 |
37 |
EqEngineManagerCentral& eemc) |
203 |
37 |
: d_eemc(eemc), d_mNotify(nullptr), d_quantEngine(nullptr) |
204 |
|
{ |
205 |
37 |
} |
206 |
|
|
207 |
9690 |
bool EqEngineManagerCentral::CentralNotifyClass::eqNotifyTriggerPredicate( |
208 |
|
TNode predicate, bool value) |
209 |
|
{ |
210 |
19380 |
Trace("eem-central") << "eqNotifyTriggerPredicate: " << predicate |
211 |
9690 |
<< std::endl; |
212 |
9690 |
return d_eemc.eqNotifyTriggerPredicate(predicate, value); |
213 |
|
} |
214 |
|
|
215 |
12666 |
bool EqEngineManagerCentral::CentralNotifyClass::eqNotifyTriggerTermEquality( |
216 |
|
TheoryId tag, TNode t1, TNode t2, bool value) |
217 |
|
{ |
218 |
25332 |
Trace("eem-central") << "eqNotifyTriggerTermEquality: " << t1 << " " << t2 |
219 |
12666 |
<< value << ", tag = " << tag << std::endl; |
220 |
12666 |
return d_eemc.eqNotifyTriggerTermEquality(tag, t1, t2, value); |
221 |
|
} |
222 |
|
|
223 |
34 |
void EqEngineManagerCentral::CentralNotifyClass::eqNotifyConstantTermMerge( |
224 |
|
TNode t1, TNode t2) |
225 |
|
{ |
226 |
68 |
Trace("eem-central") << "eqNotifyConstantTermMerge: " << t1 << " " << t2 |
227 |
34 |
<< std::endl; |
228 |
34 |
d_eemc.eqNotifyConstantTermMerge(t1, t2); |
229 |
34 |
} |
230 |
|
|
231 |
7976 |
void EqEngineManagerCentral::CentralNotifyClass::eqNotifyNewClass(TNode t) |
232 |
|
{ |
233 |
7976 |
Trace("eem-central") << "...eqNotifyNewClass " << t << std::endl; |
234 |
|
// notify all theories that have new equivalence class notifications |
235 |
47856 |
for (eq::EqualityEngineNotify* notify : d_newClassNotify) |
236 |
|
{ |
237 |
39880 |
notify->eqNotifyNewClass(t); |
238 |
|
} |
239 |
7976 |
} |
240 |
|
|
241 |
17041 |
void EqEngineManagerCentral::CentralNotifyClass::eqNotifyMerge(TNode t1, |
242 |
|
TNode t2) |
243 |
|
{ |
244 |
17041 |
Trace("eem-central") << "...eqNotifyMerge " << t1 << ", " << t2 << std::endl; |
245 |
|
// notify all theories that have merge notifications |
246 |
102246 |
for (eq::EqualityEngineNotify* notify : d_mergeNotify) |
247 |
|
{ |
248 |
85205 |
notify->eqNotifyMerge(t1, t2); |
249 |
|
} |
250 |
17041 |
} |
251 |
|
|
252 |
476 |
void EqEngineManagerCentral::CentralNotifyClass::eqNotifyDisequal(TNode t1, |
253 |
|
TNode t2, |
254 |
|
TNode reason) |
255 |
|
{ |
256 |
952 |
Trace("eem-central") << "...eqNotifyDisequal " << t1 << ", " << t2 |
257 |
476 |
<< std::endl; |
258 |
|
// notify all theories that have disequal notifications |
259 |
1428 |
for (eq::EqualityEngineNotify* notify : d_disequalNotify) |
260 |
|
{ |
261 |
952 |
notify->eqNotifyDisequal(t1, t2, reason); |
262 |
|
} |
263 |
476 |
} |
264 |
|
|
265 |
9690 |
bool EqEngineManagerCentral::eqNotifyTriggerPredicate(TNode predicate, |
266 |
|
bool value) |
267 |
|
{ |
268 |
|
// always propagate with the shared solver |
269 |
19380 |
Trace("eem-central") << "...propagate " << predicate << ", " << value |
270 |
9690 |
<< " with shared solver" << std::endl; |
271 |
9690 |
return d_sharedSolver.propagateLit(predicate, value); |
272 |
|
} |
273 |
|
|
274 |
12666 |
bool EqEngineManagerCentral::eqNotifyTriggerTermEquality(TheoryId tag, |
275 |
|
TNode a, |
276 |
|
TNode b, |
277 |
|
bool value) |
278 |
|
{ |
279 |
|
// propagate to theory engine |
280 |
12666 |
bool ok = d_sharedSolver.propagateLit(a.eqNode(b), value); |
281 |
12666 |
if (!ok) |
282 |
|
{ |
283 |
78 |
return false; |
284 |
|
} |
285 |
|
// no need to propagate shared term equalities to the UF theory |
286 |
12588 |
if (tag == THEORY_UF) |
287 |
|
{ |
288 |
5483 |
return true; |
289 |
|
} |
290 |
|
// propagate shared equality |
291 |
7105 |
return d_sharedSolver.propagateSharedEquality(tag, a, b, value); |
292 |
|
} |
293 |
|
|
294 |
34 |
void EqEngineManagerCentral::eqNotifyConstantTermMerge(TNode t1, TNode t2) |
295 |
|
{ |
296 |
68 |
Node lit = t1.eqNode(t2); |
297 |
68 |
Node conflict = d_centralEqualityEngine.mkExplainLit(lit); |
298 |
68 |
Trace("eem-central") << "...explained conflict of " << lit << " ... " |
299 |
34 |
<< conflict << std::endl; |
300 |
34 |
d_sharedSolver.sendConflict(TrustNode::mkTrustConflict(conflict), |
301 |
|
InferenceId::EQ_CONSTANT_MERGE); |
302 |
68 |
return; |
303 |
|
} |
304 |
|
|
305 |
|
} // namespace theory |
306 |
31137 |
} // namespace cvc5 |