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