Storm
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
8
13
16
17#include "storm-config.h"
18
19namespace storm {
20namespace dd {
21
22#if defined(__clang__)
23#pragma clang diagnostic push
24#pragma clang diagnostic ignored "-Wzero-length-array"
25#pragma clang diagnostic ignored "-Wc99-extensions"
26#endif
27
28#ifndef NDEBUG
29VOID_TASK_0(gc_start) {
30 STORM_LOG_TRACE("Starting sylvan garbage collection...");
31}
32
33VOID_TASK_0(gc_end) {
34 STORM_LOG_TRACE("Sylvan garbage collection done.");
35}
36#endif
37
38VOID_TASK_2(execute_sylvan, std::function<void()> const*, f, std::exception_ptr*, e) {
39 try {
40 (*f)();
41 } catch (std::exception& exception) {
42 *e = std::current_exception();
43 }
44}
45
46#if defined(__clang__)
47#pragma clang diagnostic pop
48#endif
49
50uint_fast64_t InternalDdManager<DdType::Sylvan>::numberOfInstances = 0;
51bool InternalDdManager<DdType::Sylvan>::suspended = false;
52
53// It is important that the variable pairs start at an even offset, because sylvan assumes this to be true for
54// some operations.
55uint_fast64_t InternalDdManager<DdType::Sylvan>::nextFreeVariableIndex = 0;
56
57uint_fast64_t findLargestPowerOfTwoFitting(uint_fast64_t number) {
58 for (uint_fast64_t index = 0; index < 64; ++index) {
59 if ((number & (1ull << (63 - index))) != 0) {
60 return 63 - index;
61 }
62 }
63 return 0;
64}
65
67 if (numberOfInstances == 0) {
69 size_t const task_deque_size = 1024 * 1024;
70
71 lace_set_stacksize(1024 * 1024 * 16); // 16 MiB
72
73 lace_start(settings.getNumberOfThreads(), task_deque_size);
74
75 sylvan_set_limits(storm::settings::getModule<storm::settings::modules::SylvanSettings>().getMaximalMemory() * 1024 * 1024, 0, 0);
76 sylvan_init_package();
77
78 sylvan::Sylvan::initBdd();
79 sylvan::Sylvan::initMtbdd();
80 sylvan::Sylvan::initCustomMtbdd();
81
82#ifndef NDEBUG
83 sylvan_gc_hook_pregc(TASK(gc_start));
84 sylvan_gc_hook_postgc(TASK(gc_end));
85#endif
86 // TODO: uncomment these to disable lace threads whenever they are not used. This requires that *all* DD code is run through execute
87 // lace_suspend();
88 // suspended = true;
89 }
90 ++numberOfInstances;
91}
92
94 --numberOfInstances;
95 if (numberOfInstances == 0) {
96 // Enable this to print the sylvan statistics to a file.
97 // FILE* filePointer = fopen("sylvan.stats", "w");
98 // sylvan_stats_report(filePointer, 0);
99 // fclose(filePointer);
100
101 sylvan::Sylvan::quitPackage();
102 lace_stop();
103 }
104}
105
109
110template<>
112 return InternalAdd<DdType::Sylvan, double>(this, sylvan::Mtbdd::doubleTerminal(storm::utility::one<double>()));
113}
114
115template<>
117 return InternalAdd<DdType::Sylvan, uint_fast64_t>(this, sylvan::Mtbdd::int64Terminal(storm::utility::one<uint_fast64_t>()));
118}
119
120template<>
122 return InternalAdd<DdType::Sylvan, storm::RationalNumber>(this, sylvan::Mtbdd::stormRationalNumberTerminal(storm::utility::one<storm::RationalNumber>()));
123}
124
125#ifdef STORM_HAVE_CARL
126template<>
129 sylvan::Mtbdd::stormRationalFunctionTerminal(storm::utility::one<storm::RationalFunction>()));
130}
131#endif
132
136
138 uint64_t numberOfDdVariables) const {
139 return InternalBdd<DdType::Sylvan>(this, sylvan::Bdd(this->getBddEncodingLessOrEqualThanRec(0, (1ull << numberOfDdVariables) - 1, bound,
140 cube.getSylvanBdd().GetBDD(), numberOfDdVariables)));
141}
142
143BDD InternalDdManager<DdType::Sylvan>::getBddEncodingLessOrEqualThanRec(uint64_t minimalValue, uint64_t maximalValue, uint64_t bound, BDD cube,
144 uint64_t remainingDdVariables) const {
145 if (maximalValue <= bound) {
146 return sylvan_true;
147 } else if (minimalValue > bound) {
148 return sylvan_false;
149 }
150
151 STORM_LOG_ASSERT(remainingDdVariables > 0, "Expected more remaining DD variables.");
152 uint64_t newRemainingDdVariables = remainingDdVariables - 1;
153 BDD elseResult =
154 getBddEncodingLessOrEqualThanRec(minimalValue, maximalValue & ~(1ull << newRemainingDdVariables), bound, sylvan_high(cube), newRemainingDdVariables);
155 bdd_refs_push(elseResult);
156 BDD thenResult =
157 getBddEncodingLessOrEqualThanRec(minimalValue | (1ull << newRemainingDdVariables), maximalValue, bound, sylvan_high(cube), newRemainingDdVariables);
158 bdd_refs_push(elseResult);
159 BDD result = sylvan_makenode(sylvan_var(cube), elseResult, thenResult);
160 bdd_refs_pop(2);
161 return result;
162}
163
164template<>
166 return InternalAdd<DdType::Sylvan, double>(this, sylvan::Mtbdd::doubleTerminal(storm::utility::zero<double>()));
167}
168
169template<>
171 return InternalAdd<DdType::Sylvan, uint_fast64_t>(this, sylvan::Mtbdd::int64Terminal(storm::utility::zero<uint_fast64_t>()));
172}
173
174template<>
176 return InternalAdd<DdType::Sylvan, storm::RationalNumber>(this, sylvan::Mtbdd::stormRationalNumberTerminal(storm::utility::zero<storm::RationalNumber>()));
177}
178
179#ifdef STORM_HAVE_CARL
180template<>
183 sylvan::Mtbdd::stormRationalFunctionTerminal(storm::utility::zero<storm::RationalFunction>()));
184}
185#endif
186
187template<typename ValueType>
191
192template<>
194 return InternalAdd<DdType::Sylvan, double>(this, sylvan::Mtbdd::doubleTerminal(value));
195}
196
197template<>
199 return InternalAdd<DdType::Sylvan, uint_fast64_t>(this, sylvan::Mtbdd::int64Terminal(value));
200}
201
202template<>
204 return InternalAdd<DdType::Sylvan, storm::RationalNumber>(this, sylvan::Mtbdd::stormRationalNumberTerminal(value));
205}
206
207#ifdef STORM_HAVE_CARL
208template<>
210 return InternalAdd<DdType::Sylvan, storm::RationalFunction>(this, sylvan::Mtbdd::stormRationalFunctionTerminal(value));
211}
212#endif
213
214std::vector<InternalBdd<DdType::Sylvan>> InternalDdManager<DdType::Sylvan>::createDdVariables(uint64_t numberOfLayers,
215 boost::optional<uint_fast64_t> const& position) {
216 STORM_LOG_THROW(!position, storm::exceptions::NotSupportedException, "The manager does not support ordered insertion.");
217
218 std::vector<InternalBdd<DdType::Sylvan>> result;
219
220 for (uint64_t layer = 0; layer < numberOfLayers; ++layer) {
221 result.emplace_back(InternalBdd<DdType::Sylvan>(this, sylvan::Bdd::bddVar(nextFreeVariableIndex)));
222 ++nextFreeVariableIndex;
223 }
224
225 return result;
226}
227
231
233 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan.");
234}
235
237 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan.");
238}
239
241 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan.");
242}
243
245 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan.");
246}
247
248void InternalDdManager<DdType::Sylvan>::execute(std::function<void()> const& f) const {
249 // Only wake up the sylvan (i.e. lace) threads when they are suspended.
250 std::exception_ptr e = nullptr; // propagate exception
251 if (suspended) {
252 lace_resume();
253 suspended = false;
254 RUN(execute_sylvan, &f, &e);
255 lace_suspend();
256 suspended = true;
257 } else {
258 // The sylvan threads are already running, don't suspend afterwards.
259 RUN(execute_sylvan, &f, &e);
260 }
261 if (e) {
262 std::rethrow_exception(e);
263 }
264}
265
267 return nextFreeVariableIndex;
268}
269
272
274
275#ifdef STORM_HAVE_CARL
277#endif
278} // namespace dd
279} // namespace storm
This class represents the settings for Sylvan.
uint_fast64_t getNumberOfThreads() const
Retrieves the amount of threads available to Sylvan.
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
VOID_TASK_2(execute_sylvan, std::function< void()> const *, f, std::exception_ptr *, e)
uint_fast64_t findLargestPowerOfTwoFitting(uint_fast64_t number)
SettingsType const & getModule()
Get module.
LabParser.cpp.
Definition cli.cpp:18