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