Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
InternalSylvanDdManager.cpp
Go to the documentation of this file.
2
3#include <cmath>
4#include <iostream>
5
14
15namespace storm {
16namespace dd {
17
18#ifdef STORM_HAVE_SYLVAN
19#if defined(__clang__)
20#pragma clang diagnostic push
21#pragma clang diagnostic ignored "-Wzero-length-array"
22#pragma clang diagnostic ignored "-Wc99-extensions"
23#endif
24
25#ifndef NDEBUG
26VOID_TASK_0(gc_start) {
27 STORM_LOG_TRACE("Starting sylvan garbage collection...");
28}
29
30VOID_TASK_0(gc_end) {
31 STORM_LOG_TRACE("Sylvan garbage collection done.");
32}
33#endif
34
35VOID_TASK_2(execute_sylvan, std::function<void()> const*, f, std::exception_ptr*, e) {
36 try {
37 (*f)();
38 } catch (std::exception& exception) {
39 *e = std::current_exception();
40 }
41}
42
43#if defined(__clang__)
44#pragma clang diagnostic pop
45#endif
46
47uint_fast64_t InternalDdManager<DdType::Sylvan>::numberOfInstances = 0;
48bool InternalDdManager<DdType::Sylvan>::suspended = false;
49
50// It is important that the variable pairs start at an even offset, because sylvan assumes this to be true for
51// some operations.
52uint_fast64_t InternalDdManager<DdType::Sylvan>::nextFreeVariableIndex = 0;
53
54uint_fast64_t findLargestPowerOfTwoFitting(uint_fast64_t number) {
55 for (uint_fast64_t index = 0; index < 64; ++index) {
56 if ((number & (1ull << (63 - index))) != 0) {
57 return 63 - index;
58 }
59 }
60 return 0;
61}
62
63InternalDdManager<DdType::Sylvan>::InternalDdManager() {
64 if (numberOfInstances == 0) {
65 storm::settings::modules::SylvanSettings const& settings = storm::settings::getModule<storm::settings::modules::SylvanSettings>();
66 size_t const task_deque_size = 1024 * 1024;
67
68 lace_set_stacksize(1024 * 1024 * 16); // 16 MiB
69
70 lace_start(settings.getNumberOfThreads(), task_deque_size);
71
72 sylvan_set_limits(storm::settings::getModule<storm::settings::modules::SylvanSettings>().getMaximalMemory() * 1024 * 1024, 0, 0);
73 sylvan_init_package();
74
75 sylvan::Sylvan::initBdd();
76 sylvan::Sylvan::initMtbdd();
77 sylvan::Sylvan::initCustomMtbdd();
78
79#ifndef NDEBUG
80 sylvan_gc_hook_pregc(TASK(gc_start));
81 sylvan_gc_hook_postgc(TASK(gc_end));
82#endif
83 // TODO: uncomment these to disable lace threads whenever they are not used. This requires that *all* DD code is run through execute
84 // lace_suspend();
85 // suspended = true;
86 }
87 ++numberOfInstances;
88}
89
90InternalDdManager<DdType::Sylvan>::~InternalDdManager() {
91 --numberOfInstances;
92 if (numberOfInstances == 0) {
93 // Enable this to print the sylvan statistics to a file.
94 // FILE* filePointer = fopen("sylvan.stats", "w");
95 // sylvan_stats_report(filePointer, 0);
96 // fclose(filePointer);
97
98 sylvan::Sylvan::quitPackage();
99 lace_stop();
100 }
101}
102
103InternalBdd<DdType::Sylvan> InternalDdManager<DdType::Sylvan>::getBddOne() const {
104 return InternalBdd<DdType::Sylvan>(this, sylvan::Bdd::bddOne());
105}
106
107template<>
108InternalAdd<DdType::Sylvan, double> InternalDdManager<DdType::Sylvan>::getAddOne() const {
109 return InternalAdd<DdType::Sylvan, double>(this, sylvan::Mtbdd::doubleTerminal(storm::utility::one<double>()));
110}
111
112template<>
113InternalAdd<DdType::Sylvan, uint_fast64_t> InternalDdManager<DdType::Sylvan>::getAddOne() const {
114 return InternalAdd<DdType::Sylvan, uint_fast64_t>(this, sylvan::Mtbdd::int64Terminal(storm::utility::one<uint_fast64_t>()));
115}
116
117template<>
118InternalAdd<DdType::Sylvan, storm::RationalNumber> InternalDdManager<DdType::Sylvan>::getAddOne() const {
119 return InternalAdd<DdType::Sylvan, storm::RationalNumber>(this, sylvan::Mtbdd::stormRationalNumberTerminal(storm::utility::one<storm::RationalNumber>()));
120}
121
122template<>
123InternalAdd<DdType::Sylvan, storm::RationalFunction> InternalDdManager<DdType::Sylvan>::getAddOne() const {
124 return InternalAdd<DdType::Sylvan, storm::RationalFunction>(this,
125 sylvan::Mtbdd::stormRationalFunctionTerminal(storm::utility::one<storm::RationalFunction>()));
126}
127
128InternalBdd<DdType::Sylvan> InternalDdManager<DdType::Sylvan>::getBddZero() const {
129 return InternalBdd<DdType::Sylvan>(this, sylvan::Bdd::bddZero());
130}
131
132InternalBdd<DdType::Sylvan> InternalDdManager<DdType::Sylvan>::getBddEncodingLessOrEqualThan(uint64_t bound, InternalBdd<DdType::Sylvan> const& cube,
133 uint64_t numberOfDdVariables) const {
134 return InternalBdd<DdType::Sylvan>(this, sylvan::Bdd(this->getBddEncodingLessOrEqualThanRec(0, (1ull << numberOfDdVariables) - 1, bound,
135 cube.getSylvanBdd().GetBDD(), numberOfDdVariables)));
136}
137
138BDD InternalDdManager<DdType::Sylvan>::getBddEncodingLessOrEqualThanRec(uint64_t minimalValue, uint64_t maximalValue, uint64_t bound, BDD cube,
139 uint64_t remainingDdVariables) const {
140 if (maximalValue <= bound) {
141 return sylvan_true;
142 } else if (minimalValue > bound) {
143 return sylvan_false;
144 }
145
146 STORM_LOG_ASSERT(remainingDdVariables > 0, "Expected more remaining DD variables.");
147 uint64_t newRemainingDdVariables = remainingDdVariables - 1;
148 BDD elseResult =
149 getBddEncodingLessOrEqualThanRec(minimalValue, maximalValue & ~(1ull << newRemainingDdVariables), bound, sylvan_high(cube), newRemainingDdVariables);
150 bdd_refs_push(elseResult);
151 BDD thenResult =
152 getBddEncodingLessOrEqualThanRec(minimalValue | (1ull << newRemainingDdVariables), maximalValue, bound, sylvan_high(cube), newRemainingDdVariables);
153 bdd_refs_push(elseResult);
154 BDD result = sylvan_makenode(sylvan_var(cube), elseResult, thenResult);
155 bdd_refs_pop(2);
156 return result;
157}
158
159template<>
160InternalAdd<DdType::Sylvan, double> InternalDdManager<DdType::Sylvan>::getAddZero() const {
161 return InternalAdd<DdType::Sylvan, double>(this, sylvan::Mtbdd::doubleTerminal(storm::utility::zero<double>()));
162}
163
164template<>
165InternalAdd<DdType::Sylvan, uint_fast64_t> InternalDdManager<DdType::Sylvan>::getAddZero() const {
166 return InternalAdd<DdType::Sylvan, uint_fast64_t>(this, sylvan::Mtbdd::int64Terminal(storm::utility::zero<uint_fast64_t>()));
167}
168
169template<>
170InternalAdd<DdType::Sylvan, storm::RationalNumber> InternalDdManager<DdType::Sylvan>::getAddZero() const {
171 return InternalAdd<DdType::Sylvan, storm::RationalNumber>(this, sylvan::Mtbdd::stormRationalNumberTerminal(storm::utility::zero<storm::RationalNumber>()));
172}
173
174template<>
175InternalAdd<DdType::Sylvan, storm::RationalFunction> InternalDdManager<DdType::Sylvan>::getAddZero() const {
176 return InternalAdd<DdType::Sylvan, storm::RationalFunction>(this,
177 sylvan::Mtbdd::stormRationalFunctionTerminal(storm::utility::zero<storm::RationalFunction>()));
178}
179
180template<typename ValueType>
181InternalAdd<DdType::Sylvan, ValueType> InternalDdManager<DdType::Sylvan>::getAddUndefined() const {
182 return InternalAdd<DdType::Sylvan, ValueType>(this, sylvan::Mtbdd(sylvan::Bdd::bddZero()));
183}
184
185template<>
186InternalAdd<DdType::Sylvan, double> InternalDdManager<DdType::Sylvan>::getConstant(double const& value) const {
187 return InternalAdd<DdType::Sylvan, double>(this, sylvan::Mtbdd::doubleTerminal(value));
188}
189
190template<>
191InternalAdd<DdType::Sylvan, uint_fast64_t> InternalDdManager<DdType::Sylvan>::getConstant(uint_fast64_t const& value) const {
192 return InternalAdd<DdType::Sylvan, uint_fast64_t>(this, sylvan::Mtbdd::int64Terminal(value));
193}
194
195template<>
196InternalAdd<DdType::Sylvan, storm::RationalNumber> InternalDdManager<DdType::Sylvan>::getConstant(storm::RationalNumber const& value) const {
197 return InternalAdd<DdType::Sylvan, storm::RationalNumber>(this, sylvan::Mtbdd::stormRationalNumberTerminal(value));
198}
199
200template<>
201InternalAdd<DdType::Sylvan, storm::RationalFunction> InternalDdManager<DdType::Sylvan>::getConstant(storm::RationalFunction const& value) const {
202 return InternalAdd<DdType::Sylvan, storm::RationalFunction>(this, sylvan::Mtbdd::stormRationalFunctionTerminal(value));
203}
204
205std::vector<InternalBdd<DdType::Sylvan>> InternalDdManager<DdType::Sylvan>::createDdVariables(uint64_t numberOfLayers,
206 boost::optional<uint_fast64_t> const& position) {
207 STORM_LOG_THROW(!position, storm::exceptions::NotSupportedException, "The manager does not support ordered insertion.");
208
209 std::vector<InternalBdd<DdType::Sylvan>> result;
210
211 for (uint64_t layer = 0; layer < numberOfLayers; ++layer) {
212 result.emplace_back(InternalBdd<DdType::Sylvan>(this, sylvan::Bdd::bddVar(nextFreeVariableIndex)));
213 ++nextFreeVariableIndex;
214 }
215
216 return result;
217}
218
219bool InternalDdManager<DdType::Sylvan>::supportsOrderedInsertion() const {
220 return false;
221}
222
223void InternalDdManager<DdType::Sylvan>::allowDynamicReordering(bool) {
224 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan.");
225}
226
227bool InternalDdManager<DdType::Sylvan>::isDynamicReorderingAllowed() const {
228 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan.");
229}
230
231void InternalDdManager<DdType::Sylvan>::triggerReordering() {
232 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan.");
233}
234
235void InternalDdManager<DdType::Sylvan>::debugCheck() const {
236 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan.");
237}
238
239void InternalDdManager<DdType::Sylvan>::execute(std::function<void()> const& f) const {
240 // Only wake up the sylvan (i.e. lace) threads when they are suspended.
241 std::exception_ptr e = nullptr; // propagate exception
242 if (suspended) {
243 lace_resume();
244 suspended = false;
245 RUN(execute_sylvan, &f, &e);
246 lace_suspend();
247 suspended = true;
248 } else {
249 // The sylvan threads are already running, don't suspend afterwards.
250 RUN(execute_sylvan, &f, &e);
251 }
252 if (e) {
253 std::rethrow_exception(e);
254 }
255}
256
257uint_fast64_t InternalDdManager<DdType::Sylvan>::getNumberOfDdVariables() const {
258 return nextFreeVariableIndex;
259}
260#else
262 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
263 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
264 "version of Storm with Sylvan support.");
265}
266
268
270 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
271 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
272 "version of Storm with Sylvan support.");
273}
274
275template<typename ValueType>
277 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
278 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
279 "version of Storm with Sylvan support.");
280}
281
283 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
284 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
285 "version of Storm with Sylvan support.");
286}
287
289 uint64_t numberOfDdVariables) const {
290 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
291 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
292 "version of Storm with Sylvan support.");
293}
294
295template<typename ValueType>
297 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
298 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
299 "version of Storm with Sylvan support.");
300}
301
302template<typename ValueType>
304 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
305 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
306 "version of Storm with Sylvan support.");
307}
308
309template<typename ValueType>
311 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
312 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
313 "version of Storm with Sylvan support.");
314}
315
316std::vector<InternalBdd<DdType::Sylvan>> InternalDdManager<DdType::Sylvan>::createDdVariables(uint64_t numberOfLayers,
317 boost::optional<uint_fast64_t> const& position) {
318 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
319 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
320 "version of Storm with Sylvan support.");
321}
322
324 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
325 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
326 "version of Storm with Sylvan support.");
327}
328
330 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
331 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
332 "version of Storm with Sylvan support.");
333}
334
336 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
337 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
338 "version of Storm with Sylvan support.");
339}
340
342 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
343 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
344 "version of Storm with Sylvan support.");
345}
346
348 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
349 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
350 "version of Storm with Sylvan support.");
351}
352
353void InternalDdManager<DdType::Sylvan>::execute(std::function<void()> const& f) const {
354 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
355 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
356 "version of Storm with Sylvan support.");
357}
358
360 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
361 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
362 "version of Storm with Sylvan support.");
363}
364#endif
365
366#ifndef STORM_HAVE_SYLVAN
367// There is already an explicit template instantiations if Sylvan is available
380#endif
385
386} // namespace dd
387} // namespace storm
This class represents the settings for Sylvan.
uint64_t getNumberOfThreads() const
Retrieves the amount of threads available to Sylvan.
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30