Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
InternalCuddBdd.cpp
Go to the documentation of this file.
2
3#include <boost/functional/hash.hpp>
4
12
13namespace storm {
14namespace dd {
15
16#ifdef STORM_HAVE_CUDD
17InternalBdd<DdType::CUDD>::InternalBdd(InternalDdManager<DdType::CUDD> const* ddManager, cudd::BDD cuddBdd) : ddManager(ddManager), cuddBdd(cuddBdd) {
18 // Intentionally left empty.
19}
20
21InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::fromVector(InternalDdManager<DdType::CUDD> const* ddManager, Odd const& odd,
22 std::vector<uint_fast64_t> const& sortedDdVariableIndices,
23 std::function<bool(uint64_t)> const& filter) {
24 uint_fast64_t offset = 0;
25 return InternalBdd<DdType::CUDD>(
26 ddManager, cudd::BDD(ddManager->getCuddManager(), fromVectorRec(ddManager->getCuddManager().getManager(), offset, 0, sortedDdVariableIndices.size(),
27 odd, sortedDdVariableIndices, filter)));
28}
29
30bool InternalBdd<DdType::CUDD>::operator==(InternalBdd<DdType::CUDD> const& other) const {
31 return this->getCuddBdd() == other.getCuddBdd();
32}
33
34bool InternalBdd<DdType::CUDD>::operator!=(InternalBdd<DdType::CUDD> const& other) const {
35 return !(*this == other);
36}
37
38InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::relationalProduct(InternalBdd<DdType::CUDD> const& relation,
39 std::vector<InternalBdd<DdType::CUDD>> const& rowVariables,
40 std::vector<InternalBdd<DdType::CUDD>> const& columnVariables) const {
41 InternalBdd<DdType::CUDD> cube = ddManager->getBddOne();
42 for (auto const& variable : rowVariables) {
43 cube &= variable;
44 }
45
46 InternalBdd<DdType::CUDD> result = this->andExists(relation, cube);
47 result = result.swapVariables(rowVariables, columnVariables);
48 return result;
49}
50
51InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::inverseRelationalProduct(InternalBdd<DdType::CUDD> const& relation,
52 std::vector<InternalBdd<DdType::CUDD>> const& rowVariables,
53 std::vector<InternalBdd<DdType::CUDD>> const& columnVariables) const {
54 InternalBdd<DdType::CUDD> cube = ddManager->getBddOne();
55 for (auto const& variable : columnVariables) {
56 cube &= variable;
57 }
58
59 InternalBdd<DdType::CUDD> result = this->swapVariables(rowVariables, columnVariables).andExists(relation, cube);
60 return result;
61}
62
63InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::inverseRelationalProductWithExtendedRelation(
64 InternalBdd<DdType::CUDD> const& relation, std::vector<InternalBdd<DdType::CUDD>> const& rowVariables,
65 std::vector<InternalBdd<DdType::CUDD>> const& columnVariables) const {
66 return this->inverseRelationalProduct(relation, rowVariables, columnVariables);
67}
68
69InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::ite(InternalBdd<DdType::CUDD> const& thenDd, InternalBdd<DdType::CUDD> const& elseDd) const {
70 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().Ite(thenDd.getCuddBdd(), elseDd.getCuddBdd()));
71}
72
73template<typename ValueType>
74InternalAdd<DdType::CUDD, ValueType> InternalBdd<DdType::CUDD>::ite(InternalAdd<DdType::CUDD, ValueType> const& thenAdd,
75 InternalAdd<DdType::CUDD, ValueType> const& elseAdd) const {
76 return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddBdd().Add().Ite(thenAdd.getCuddAdd(), elseAdd.getCuddAdd()));
77}
78
79InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::operator||(InternalBdd<DdType::CUDD> const& other) const {
80 InternalBdd<DdType::CUDD> result(*this);
81 result |= other;
82 return result;
83}
84
85InternalBdd<DdType::CUDD>& InternalBdd<DdType::CUDD>::operator|=(InternalBdd<DdType::CUDD> const& other) {
86 this->cuddBdd = this->getCuddBdd() | other.getCuddBdd();
87 return *this;
88}
89
90InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::operator&&(InternalBdd<DdType::CUDD> const& other) const {
91 InternalBdd<DdType::CUDD> result(*this);
92 result &= other;
93 return result;
94}
95
96InternalBdd<DdType::CUDD>& InternalBdd<DdType::CUDD>::operator&=(InternalBdd<DdType::CUDD> const& other) {
97 this->cuddBdd = this->getCuddBdd() & other.getCuddBdd();
98 return *this;
99}
100
101InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::iff(InternalBdd<DdType::CUDD> const& other) const {
102 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().Xnor(other.getCuddBdd()));
103}
104
105InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::exclusiveOr(InternalBdd<DdType::CUDD> const& other) const {
106 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().Xor(other.getCuddBdd()));
107}
108
109InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::implies(InternalBdd<DdType::CUDD> const& other) const {
110 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().Ite(other.getCuddBdd(), ddManager->getBddOne().getCuddBdd()));
111}
112
113InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::operator!() const {
114 InternalBdd<DdType::CUDD> result(*this);
115 result.complement();
116 return result;
117}
118
119InternalBdd<DdType::CUDD>& InternalBdd<DdType::CUDD>::complement() {
120 this->cuddBdd = ~this->getCuddBdd();
121 return *this;
122}
123
124InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::existsAbstract(InternalBdd<DdType::CUDD> const& cube) const {
125 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().ExistAbstract(cube.getCuddBdd()));
126}
127
128InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::existsAbstractRepresentative(InternalBdd<DdType::CUDD> const& cube) const {
129 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().ExistAbstractRepresentative(cube.getCuddBdd()));
130}
131
132InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::universalAbstract(InternalBdd<DdType::CUDD> const& cube) const {
133 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().UnivAbstract(cube.getCuddBdd()));
134}
135
136InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::andExists(InternalBdd<DdType::CUDD> const& other, InternalBdd<DdType::CUDD> const& cube) const {
137 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().AndAbstract(other.getCuddBdd(), cube.getCuddBdd()));
138}
139
140InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::constrain(InternalBdd<DdType::CUDD> const& constraint) const {
141 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().Constrain(constraint.getCuddBdd()));
142}
143
144InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::restrict(InternalBdd<DdType::CUDD> const& constraint) const {
145 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().Restrict(constraint.getCuddBdd()));
146}
147
148InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::swapVariables(std::vector<InternalBdd<DdType::CUDD>> const& from,
149 std::vector<InternalBdd<DdType::CUDD>> const& to) const {
150 std::vector<cudd::BDD> fromBdd;
151 std::vector<cudd::BDD> toBdd;
152 for (auto it1 = from.begin(), ite1 = from.end(), it2 = to.begin(); it1 != ite1; ++it1, ++it2) {
153 fromBdd.push_back(it1->getCuddBdd());
154 toBdd.push_back(it2->getCuddBdd());
155 }
156 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().SwapVariables(fromBdd, toBdd));
157}
158
159InternalBdd<DdType::CUDD> InternalBdd<DdType::CUDD>::getSupport() const {
160 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().Support());
161}
162
163uint_fast64_t InternalBdd<DdType::CUDD>::getNonZeroCount(uint_fast64_t numberOfDdVariables) const {
164 // If the number of DD variables is zero, CUDD returns a number greater 0 for constant nodes different from
165 // zero, which is not the behaviour we expect.
166 if (numberOfDdVariables == 0) {
167 return 0;
168 }
169 return static_cast<uint_fast64_t>(this->getCuddBdd().CountMinterm(static_cast<int>(numberOfDdVariables)));
170}
171
172uint_fast64_t InternalBdd<DdType::CUDD>::getLeafCount() const {
173 return static_cast<uint_fast64_t>(this->getCuddBdd().CountLeaves());
174}
175
176uint_fast64_t InternalBdd<DdType::CUDD>::getNodeCount() const {
177 return static_cast<uint_fast64_t>(this->getCuddBdd().nodeCount());
178}
179
180bool InternalBdd<DdType::CUDD>::isOne() const {
181 return this->getCuddBdd().IsOne();
182}
183
184bool InternalBdd<DdType::CUDD>::isZero() const {
185 return this->getCuddBdd().IsZero();
186}
187
188uint_fast64_t InternalBdd<DdType::CUDD>::getIndex() const {
189 return static_cast<uint_fast64_t>(this->getCuddBdd().NodeReadIndex());
190}
191
192uint_fast64_t InternalBdd<DdType::CUDD>::getLevel() const {
193 return static_cast<uint_fast64_t>(ddManager->getCuddManager().ReadPerm(this->getIndex()));
194}
195
196void InternalBdd<DdType::CUDD>::exportToDot(std::string const& filename, std::vector<std::string> const& ddVariableNamesAsStrings,
197 bool showVariablesIfPossible) const {
198 // Build the name input of the DD.
199 std::vector<char*> ddNames;
200 std::string ddName("f");
201 ddNames.push_back(new char[ddName.size() + 1]);
202 std::copy(ddName.c_str(), ddName.c_str() + 2, ddNames.back());
203
204 // Now build the variables names.
205 std::vector<char*> ddVariableNames;
206 for (auto const& element : ddVariableNamesAsStrings) {
207 ddVariableNames.push_back(new char[element.size() + 1]);
208 std::copy(element.c_str(), element.c_str() + element.size() + 1, ddVariableNames.back());
209 }
210
211 // Open the file, dump the DD and close it again.
212 std::vector<cudd::BDD> cuddBddVector = {this->getCuddBdd()};
213 FILE* filePointer = fopen(filename.c_str(), "a+");
214 if (showVariablesIfPossible) {
215 ddManager->getCuddManager().DumpDot(cuddBddVector, ddVariableNames.data(), &ddNames[0], filePointer);
216 } else {
217 ddManager->getCuddManager().DumpDot(cuddBddVector, nullptr, &ddNames[0], filePointer);
218 }
219 fclose(filePointer);
220
221 // Finally, delete the names.
222 for (char* element : ddNames) {
223 delete element;
224 }
225 for (char* element : ddVariableNames) {
226 delete element;
227 }
228}
229
230void InternalBdd<DdType::CUDD>::exportToText(std::string const&) const {
231 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation not supported.");
232}
233
234cudd::BDD InternalBdd<DdType::CUDD>::getCuddBdd() const {
235 return this->cuddBdd;
236}
237
238DdNode* InternalBdd<DdType::CUDD>::getCuddDdNode() const {
239 return this->getCuddBdd().getNode();
240}
241
242template<typename ValueType>
243InternalAdd<DdType::CUDD, ValueType> InternalBdd<DdType::CUDD>::toAdd() const {
244 return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddBdd().Add());
245}
246
247DdNode* InternalBdd<DdType::CUDD>::fromVectorRec(::DdManager* manager, uint_fast64_t& currentOffset, uint_fast64_t currentLevel, uint_fast64_t maxLevel,
248 Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices,
249 std::function<bool(uint64_t)> const& filter) {
250 if (currentLevel == maxLevel) {
251 // If we are in a terminal node of the ODD, we need to check whether the then-offset of the ODD is one
252 // (meaning the encoding is a valid one) or zero (meaning the encoding is not valid). Consequently, we
253 // need to copy the next value of the vector iff the then-offset is greater than zero.
254 if (odd.getThenOffset() > 0) {
255 if (filter(currentOffset++)) {
256 return Cudd_ReadOne(manager);
257 } else {
258 return Cudd_ReadLogicZero(manager);
259 }
260 } else {
261 return Cudd_ReadZero(manager);
262 }
263 } else {
264 // If the total offset is zero, we can just return the constant zero DD.
265 if (odd.getThenOffset() + odd.getElseOffset() == 0) {
266 return Cudd_ReadZero(manager);
267 }
268
269 // Determine the new else-successor.
270 DdNode* elseSuccessor = nullptr;
271 if (odd.getElseOffset() > 0) {
272 elseSuccessor = fromVectorRec(manager, currentOffset, currentLevel + 1, maxLevel, odd.getElseSuccessor(), ddVariableIndices, filter);
273 } else {
274 elseSuccessor = Cudd_ReadLogicZero(manager);
275 }
276 Cudd_Ref(elseSuccessor);
277
278 // Determine the new then-successor.
279 DdNode* thenSuccessor = nullptr;
280 if (odd.getThenOffset() > 0) {
281 thenSuccessor = fromVectorRec(manager, currentOffset, currentLevel + 1, maxLevel, odd.getThenSuccessor(), ddVariableIndices, filter);
282 } else {
283 thenSuccessor = Cudd_ReadLogicZero(manager);
284 }
285 Cudd_Ref(thenSuccessor);
286
287 // Create a node representing ITE(currentVar, thenSuccessor, elseSuccessor);
288 DdNode* currentVar = Cudd_bddIthVar(manager, static_cast<int>(ddVariableIndices[currentLevel]));
289 Cudd_Ref(currentVar);
290 DdNode* result = Cudd_bddIte(manager, currentVar, thenSuccessor, elseSuccessor);
291 Cudd_Ref(result);
292
293 // Dispose of the intermediate results
294 Cudd_RecursiveDeref(manager, currentVar);
295 Cudd_RecursiveDeref(manager, thenSuccessor);
296 Cudd_RecursiveDeref(manager, elseSuccessor);
297
298 // Before returning, we remove the protection imposed by the previous call to Cudd_Ref.
299 Cudd_Deref(result);
300
301 return result;
302 }
303}
304
305storm::storage::BitVector InternalBdd<DdType::CUDD>::toVector(storm::dd::Odd const& rowOdd, std::vector<uint_fast64_t> const& ddVariableIndices) const {
307 this->toVectorRec(Cudd_Regular(this->getCuddDdNode()), ddManager->getCuddManager(), result, rowOdd, Cudd_IsComplement(this->getCuddDdNode()), 0,
308 ddVariableIndices.size(), 0, ddVariableIndices);
309 return result;
310}
311
312void InternalBdd<DdType::CUDD>::toVectorRec(DdNode const* dd, cudd::Cudd const& manager, storm::storage::BitVector& result, Odd const& rowOdd, bool complement,
313 uint_fast64_t currentRowLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset,
314 std::vector<uint_fast64_t> const& ddRowVariableIndices) const {
315 // If there are no more values to select, we can directly return.
316 if (dd == Cudd_ReadLogicZero(manager.getManager()) && !complement) {
317 return;
318 } else if (dd == Cudd_ReadOne(manager.getManager()) && complement) {
319 return;
320 }
321
322 // If we are at the maximal level, the value to be set is stored as a constant in the DD.
323 if (currentRowLevel == maxLevel) {
324 result.set(currentRowOffset, true);
325 } else if (ddRowVariableIndices[currentRowLevel] < Cudd_NodeReadIndex(dd)) {
326 toVectorRec(dd, manager, result, rowOdd.getElseSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset, ddRowVariableIndices);
327 toVectorRec(dd, manager, result, rowOdd.getThenSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset + rowOdd.getElseOffset(),
328 ddRowVariableIndices);
329 } else {
330 // Otherwise, we compute the ODDs for both the then- and else successors.
331 DdNode const* elseDdNode = Cudd_E_const(dd);
332 DdNode const* thenDdNode = Cudd_T_const(dd);
333
334 // Determine whether we have to evaluate the successors as if they were complemented.
335 bool elseComplemented = Cudd_IsComplement(elseDdNode) ^ complement;
336 bool thenComplemented = Cudd_IsComplement(thenDdNode) ^ complement;
337
338 toVectorRec(Cudd_Regular(elseDdNode), manager, result, rowOdd.getElseSuccessor(), elseComplemented, currentRowLevel + 1, maxLevel, currentRowOffset,
339 ddRowVariableIndices);
340 toVectorRec(Cudd_Regular(thenDdNode), manager, result, rowOdd.getThenSuccessor(), thenComplemented, currentRowLevel + 1, maxLevel,
341 currentRowOffset + rowOdd.getElseOffset(), ddRowVariableIndices);
342 }
343}
344
345Odd InternalBdd<DdType::CUDD>::createOdd(std::vector<uint_fast64_t> const& ddVariableIndices) const {
346 // Prepare a unique table for each level that keeps the constructed ODD nodes unique.
347 std::vector<std::unordered_map<DdNode const*, std::shared_ptr<Odd>>> uniqueTableForLevels(ddVariableIndices.size() + 1);
348
349 // Now construct the ODD structure from the BDD.
350 std::shared_ptr<Odd> rootOdd =
351 createOddRec(this->getCuddDdNode(), ddManager->getCuddManager(), 0, ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels);
352
353 // Return a copy of the root node to remove the shared_ptr encapsulation.
354 return Odd(*rootOdd);
355}
356
357std::size_t InternalBdd<DdType::CUDD>::HashFunctor::operator()(std::pair<DdNode const*, bool> const& key) const {
358 std::size_t result = 0;
359 boost::hash_combine(result, key.first);
360 boost::hash_combine(result, key.second);
361 return result;
362}
363
364std::shared_ptr<Odd> InternalBdd<DdType::CUDD>::createOddRec(DdNode const* dd, cudd::Cudd const& manager, uint_fast64_t currentLevel, uint_fast64_t maxLevel,
365 std::vector<uint_fast64_t> const& ddVariableIndices,
366 std::vector<std::unordered_map<DdNode const*, std::shared_ptr<Odd>>>& uniqueTableForLevels) {
367 // Check whether the ODD for this node has already been computed (for this level) and if so, return this instead.
368 auto it = uniqueTableForLevels[currentLevel].find(dd);
369 if (it != uniqueTableForLevels[currentLevel].end()) {
370 return it->second;
371 } else {
372 // Otherwise, we need to recursively compute the ODD.
373
374 // If we are already at the maximal level that is to be considered, we can simply create an Odd without
375 // successors
376 if (currentLevel == maxLevel) {
377 auto oddNode = std::make_shared<Odd>(nullptr, 0, nullptr, dd != Cudd_ReadLogicZero(manager.getManager()) ? 1 : 0);
378 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
379 return oddNode;
380 } else if (ddVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
381 // If we skipped the level in the DD, we compute the ODD just for the else-successor and use the same
382 // node for the then-successor as well.
383 std::shared_ptr<Odd> elseNode = createOddRec(dd, manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
384 std::shared_ptr<Odd> thenNode = elseNode;
385
386 auto oddNode = std::make_shared<Odd>(elseNode, elseNode->getTotalOffset(), thenNode, elseNode->getTotalOffset());
387 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
388 return oddNode;
389 } else {
390 // Otherwise, we compute the ODDs for both the then- and else successors.
391 DdNode const* thenDdNode = Cudd_T_const(dd);
392 DdNode const* elseDdNode = Cudd_E_const(dd);
393
394 if (Cudd_IsComplement(dd)) {
395 thenDdNode = Cudd_Not(thenDdNode);
396 elseDdNode = Cudd_Not(elseDdNode);
397 }
398
399 std::shared_ptr<Odd> elseNode = createOddRec(elseDdNode, manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
400 std::shared_ptr<Odd> thenNode = createOddRec(thenDdNode, manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
401
402 auto oddNode = std::make_shared<Odd>(elseNode, elseNode->getTotalOffset(), thenNode, thenNode->getTotalOffset());
403 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
404 return oddNode;
405 }
406 }
407}
408
409template<typename ValueType>
410void InternalBdd<DdType::CUDD>::filterExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices,
411 std::vector<ValueType> const& sourceValues, std::vector<ValueType>& targetValues) const {
412 uint_fast64_t currentIndex = 0;
413 filterExplicitVectorRec(Cudd_Regular(this->getCuddDdNode()), ddManager->getCuddManager(), 0, Cudd_IsComplement(this->getCuddDdNode()),
414 ddVariableIndices.size(), ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
415}
416
417template<typename ValueType>
418void InternalBdd<DdType::CUDD>::filterExplicitVectorRec(DdNode const* dd, cudd::Cudd const& manager, uint_fast64_t currentLevel, bool complement,
419 uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices,
420 uint_fast64_t currentOffset, storm::dd::Odd const& odd, std::vector<ValueType>& result,
421 uint_fast64_t& currentIndex, std::vector<ValueType> const& values) {
422 // If there are no more values to select, we can directly return.
423 if (dd == Cudd_ReadLogicZero(manager.getManager()) && !complement) {
424 return;
425 } else if (dd == Cudd_ReadOne(manager.getManager()) && complement) {
426 return;
427 }
428
429 if (currentLevel == maxLevel) {
430 result[currentIndex++] = values[currentOffset];
431 } else if (ddVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
432 // If we skipped a level, we need to enumerate the explicit entries for the case in which the bit is set
433 // and for the one in which it is not set.
434 filterExplicitVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.getElseSuccessor(), result,
435 currentIndex, values);
436 filterExplicitVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.getElseOffset(),
437 odd.getThenSuccessor(), result, currentIndex, values);
438 } else {
439 // Otherwise, we compute the ODDs for both the then- and else successors.
440 DdNode const* thenDdNode = Cudd_T_const(dd);
441 DdNode const* elseDdNode = Cudd_E_const(dd);
442
443 // Determine whether we have to evaluate the successors as if they were complemented.
444 bool elseComplemented = Cudd_IsComplement(elseDdNode) ^ complement;
445 bool thenComplemented = Cudd_IsComplement(thenDdNode) ^ complement;
446
447 filterExplicitVectorRec(Cudd_Regular(elseDdNode), manager, currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset,
448 odd.getElseSuccessor(), result, currentIndex, values);
449 filterExplicitVectorRec(Cudd_Regular(thenDdNode), manager, currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices,
450 currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), result, currentIndex, values);
451 }
452}
453
454std::vector<InternalBdd<DdType::CUDD>> InternalBdd<DdType::CUDD>::splitIntoGroups(std::vector<uint_fast64_t> const& ddGroupVariableIndices) const {
455 std::vector<InternalBdd<DdType::CUDD>> result;
456 splitIntoGroupsRec(Cudd_Regular(this->getCuddDdNode()), Cudd_IsComplement(this->getCuddDdNode()), result, ddGroupVariableIndices, 0,
457 ddGroupVariableIndices.size());
458 return result;
459}
460
461void InternalBdd<DdType::CUDD>::splitIntoGroupsRec(DdNode* dd, bool negated, std::vector<InternalBdd<DdType::CUDD>>& groups,
462 std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel,
463 uint_fast64_t maxLevel) const {
464 // For the empty DD, we do not need to create a group.
465 if (negated && dd == Cudd_ReadOne(ddManager->getCuddManager().getManager())) {
466 return;
467 }
468
469 if (currentLevel == maxLevel) {
470 groups.push_back(InternalBdd<DdType::CUDD>(ddManager, cudd::BDD(ddManager->getCuddManager(), negated ? Cudd_Complement(dd) : dd)));
471 } else if (ddGroupVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
472 splitIntoGroupsRec(dd, negated, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
473 splitIntoGroupsRec(dd, negated, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
474 } else {
475 DdNode* elseNode = Cudd_E(dd);
476 DdNode* thenNode = Cudd_T(dd);
477
478 splitIntoGroupsRec(elseNode, negated ^ Cudd_IsComplement(elseNode), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
479 splitIntoGroupsRec(thenNode, negated ^ Cudd_IsComplement(thenNode), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
480 }
481}
482
483void InternalBdd<DdType::CUDD>::filterExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices,
484 storm::storage::BitVector const& sourceValues, storm::storage::BitVector& targetValues) const {
485 uint_fast64_t currentIndex = 0;
486 filterExplicitVectorRec(Cudd_Regular(this->getCuddDdNode()), ddManager->getCuddManager(), 0, Cudd_IsComplement(this->getCuddDdNode()),
487 ddVariableIndices.size(), ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
488}
489
490void InternalBdd<DdType::CUDD>::filterExplicitVectorRec(DdNode const* dd, cudd::Cudd const& manager, uint_fast64_t currentLevel, bool complement,
491 uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices,
492 uint_fast64_t currentOffset, storm::dd::Odd const& odd, storm::storage::BitVector& result,
493 uint_fast64_t& currentIndex, storm::storage::BitVector const& values) {
494 // If there are no more values to select, we can directly return.
495 if (dd == Cudd_ReadLogicZero(manager.getManager()) && !complement) {
496 return;
497 } else if (dd == Cudd_ReadOne(manager.getManager()) && complement) {
498 return;
499 }
500
501 if (currentLevel == maxLevel) {
502 result.set(currentIndex++, values.get(currentOffset));
503 } else if (ddVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
504 // If we skipped a level, we need to enumerate the explicit entries for the case in which the bit is set
505 // and for the one in which it is not set.
506 filterExplicitVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.getElseSuccessor(), result,
507 currentIndex, values);
508 filterExplicitVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.getElseOffset(),
509 odd.getThenSuccessor(), result, currentIndex, values);
510 } else {
511 // Otherwise, we compute the ODDs for both the then- and else successors.
512 DdNode const* thenDdNode = Cudd_T_const(dd);
513 DdNode const* elseDdNode = Cudd_E_const(dd);
514
515 // Determine whether we have to evaluate the successors as if they were complemented.
516 bool elseComplemented = Cudd_IsComplement(elseDdNode) ^ complement;
517 bool thenComplemented = Cudd_IsComplement(thenDdNode) ^ complement;
518
519 filterExplicitVectorRec(Cudd_Regular(elseDdNode), manager, currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset,
520 odd.getElseSuccessor(), result, currentIndex, values);
521 filterExplicitVectorRec(Cudd_Regular(thenDdNode), manager, currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices,
522 currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), result, currentIndex, values);
523 }
524}
525
526std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> InternalBdd<DdType::CUDD>::toExpression(
528 std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> result;
529
530 // Create (and maintain) a mapping from the DD nodes to a counter that says the how-many-th node (within the
531 // nodes of equal index) the node was.
532 std::unordered_map<DdNode const*, uint_fast64_t> nodeToCounterMap;
533 std::vector<uint_fast64_t> nextCounterForIndex(ddManager->getNumberOfDdVariables(), 0);
534 std::unordered_map<std::pair<uint_fast64_t, uint_fast64_t>, storm::expressions::Variable> countIndexToVariablePair;
535
536 bool negated = Cudd_Regular(this->getCuddDdNode()) != this->getCuddDdNode();
537
538 // Translate from the top node downwards.
540 Cudd_Regular(this->getCuddDdNode()), ddManager->getCuddManager(), manager, result.first, result.second, countIndexToVariablePair, nodeToCounterMap,
541 nextCounterForIndex);
542
543 // Create the final expression.
544 if (negated) {
545 result.first.push_back(!topVariable);
546 } else {
547 result.first.push_back(topVariable);
548 }
549
550 return result;
551}
552
553storm::expressions::Variable InternalBdd<DdType::CUDD>::toExpressionRec(
554 DdNode const* dd, cudd::Cudd const& ddManager, storm::expressions::ExpressionManager& manager, std::vector<storm::expressions::Expression>& expressions,
555 std::unordered_map<uint_fast64_t, storm::expressions::Variable>& indexToVariableMap,
556 std::unordered_map<std::pair<uint_fast64_t, uint_fast64_t>, storm::expressions::Variable>& countIndexToVariablePair,
557 std::unordered_map<DdNode const*, uint_fast64_t>& nodeToCounterMap, std::vector<uint_fast64_t>& nextCounterForIndex) {
558 STORM_LOG_ASSERT(dd == Cudd_Regular(dd), "Expected non-negated BDD node.");
559
560 // First, try to look up the current node if it's not a terminal node.
561 auto nodeCounterIt = nodeToCounterMap.find(dd);
562 if (nodeCounterIt != nodeToCounterMap.end()) {
563 // If we have found the node, this means we can look up the counter-index pair and get the corresponding variable.
564 auto variableIt = countIndexToVariablePair.find(std::make_pair(nodeCounterIt->second, Cudd_NodeReadIndex(dd)));
565 STORM_LOG_ASSERT(variableIt != countIndexToVariablePair.end(), "Unable to find node.");
566 return variableIt->second;
567 }
568
569 // If the node was not yet encountered, we create a variable and associate it with the appropriate expression.
570 storm::expressions::Variable newNodeVariable = manager.declareFreshBooleanVariable();
571
572 // Since we want to reuse the variable whenever possible, we insert the appropriate entries in the hash table.
573 if (!Cudd_IsConstant_const(dd)) {
574 // If we are dealing with a non-terminal node, we count it as a new node with this index.
575 nodeToCounterMap[dd] = nextCounterForIndex[Cudd_NodeReadIndex(dd)];
576 countIndexToVariablePair[std::make_pair(nextCounterForIndex[Cudd_NodeReadIndex(dd)], Cudd_NodeReadIndex(dd))] = newNodeVariable;
577 ++nextCounterForIndex[Cudd_NodeReadIndex(dd)];
578 } else {
579 // If it's a terminal node, it is the one leaf and there's no need to keep track of a counter for this level.
580 nodeToCounterMap[dd] = 0;
581 countIndexToVariablePair[std::make_pair(0, Cudd_NodeReadIndex(dd))] = newNodeVariable;
582 }
583
584 // In the terminal case, we can only have a one since we are considering non-negated nodes only.
585 if (dd == Cudd_ReadOne(ddManager.getManager())) {
586 // Push the expression that enforces that the new variable is true.
587 expressions.push_back(storm::expressions::iff(manager.boolean(true), newNodeVariable));
588 } else {
589 // In the non-terminal case, we recursively translate the children nodes and then construct and appropriate ite-expression.
590 DdNode const* t = Cudd_T_const(dd);
591 DdNode const* e = Cudd_E_const(dd);
592 DdNode const* T = Cudd_Regular(t);
593 DdNode const* E = Cudd_Regular(e);
594 storm::expressions::Variable thenVariable =
595 toExpressionRec(T, ddManager, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
596 storm::expressions::Variable elseVariable =
597 toExpressionRec(E, ddManager, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
598
599 // Create the appropriate expression.
600 auto indexVariable = indexToVariableMap.find(Cudd_NodeReadIndex(dd));
601 storm::expressions::Variable levelVariable;
602 if (indexVariable == indexToVariableMap.end()) {
603 levelVariable = manager.declareFreshBooleanVariable();
604 indexToVariableMap[Cudd_NodeReadIndex(dd)] = levelVariable;
605 } else {
606 levelVariable = indexVariable->second;
607 }
608 expressions.push_back(storm::expressions::iff(
609 newNodeVariable, storm::expressions::ite(levelVariable, t == T ? thenVariable : !thenVariable, e == E ? elseVariable : !elseVariable)));
610 }
611
612 // Return the variable for this node.
613 return newNodeVariable;
614}
615#else
617 std::vector<uint_fast64_t> const& sortedDdVariableIndices,
618 std::function<bool(uint64_t)> const& filter) {
619 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
620 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
621 "of Storm with CUDD support.");
622}
623
625 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
626 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
627 "of Storm with CUDD support.");
628}
629
631 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
632 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
633 "of Storm with CUDD support.");
634}
635
637 std::vector<InternalBdd<DdType::CUDD>> const& rowVariables,
638 std::vector<InternalBdd<DdType::CUDD>> const& columnVariables) const {
639 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
640 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
641 "of Storm with CUDD support.");
642}
643
645 std::vector<InternalBdd<DdType::CUDD>> const& rowVariables,
646 std::vector<InternalBdd<DdType::CUDD>> const& columnVariables) const {
647 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
648 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
649 "of Storm with CUDD support.");
650}
651
653 InternalBdd<DdType::CUDD> const& relation, std::vector<InternalBdd<DdType::CUDD>> const& rowVariables,
654 std::vector<InternalBdd<DdType::CUDD>> const& columnVariables) const {
655 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
656 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
657 "of Storm with CUDD support.");
658}
659
661 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
662 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
663 "of Storm with CUDD support.");
664}
665
666template<typename ValueType>
668 InternalAdd<DdType::CUDD, ValueType> const& elseAdd) const {
669 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
670 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
671 "of Storm with CUDD support.");
672}
673
675 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
676 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
677 "of Storm with CUDD support.");
678}
679
681 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
682 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
683 "of Storm with CUDD support.");
684}
685
687 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
688 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
689 "of Storm with CUDD support.");
690}
691
693 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
694 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
695 "of Storm with CUDD support.");
696}
697
699 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
700 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
701 "of Storm with CUDD support.");
702}
703
705 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
706 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
707 "of Storm with CUDD support.");
708}
709
711 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
712 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
713 "of Storm with CUDD support.");
714}
715
717 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
718 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
719 "of Storm with CUDD support.");
720}
721
723 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
724 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
725 "of Storm with CUDD support.");
726}
727
729 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
730 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
731 "of Storm with CUDD support.");
732}
733
735 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
736 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
737 "of Storm with CUDD support.");
738}
739
741 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
742 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
743 "of Storm with CUDD support.");
744}
745
747 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
748 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
749 "of Storm with CUDD support.");
750}
751
753 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
754 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
755 "of Storm with CUDD support.");
756}
757
759 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
760 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
761 "of Storm with CUDD support.");
762}
763
765 std::vector<InternalBdd<DdType::CUDD>> const& to) const {
766 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
767 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
768 "of Storm with CUDD support.");
769}
770
772 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
773 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
774 "of Storm with CUDD support.");
775}
776
777uint_fast64_t InternalBdd<DdType::CUDD>::getNonZeroCount(uint_fast64_t numberOfDdVariables) const {
778 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
779 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
780 "of Storm with CUDD support.");
781}
782
784 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
785 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
786 "of Storm with CUDD support.");
787}
788
790 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
791 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
792 "of Storm with CUDD support.");
793}
794
796 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
797 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
798 "of Storm with CUDD support.");
799}
800
802 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
803 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
804 "of Storm with CUDD support.");
805}
806
808 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
809 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
810 "of Storm with CUDD support.");
811}
812
814 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
815 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
816 "of Storm with CUDD support.");
817}
818
819void InternalBdd<DdType::CUDD>::exportToDot(std::string const& filename, std::vector<std::string> const& ddVariableNamesAsStrings,
820 bool showVariablesIfPossible) const {
821 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
822 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
823 "of Storm with CUDD support.");
824}
825
826void InternalBdd<DdType::CUDD>::exportToText(std::string const&) const {
827 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
828 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
829 "of Storm with CUDD support.");
830}
831
832template<typename ValueType>
834 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
835 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
836 "of Storm with CUDD support.");
837}
838
839storm::storage::BitVector InternalBdd<DdType::CUDD>::toVector(storm::dd::Odd const& rowOdd, std::vector<uint_fast64_t> const& ddVariableIndices) const {
840 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
841 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
842 "of Storm with CUDD support.");
843}
844
845Odd InternalBdd<DdType::CUDD>::createOdd(std::vector<uint_fast64_t> const& ddVariableIndices) const {
846 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
847 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
848 "of Storm with CUDD support.");
849}
850
851template<typename ValueType>
852void InternalBdd<DdType::CUDD>::filterExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices,
853 std::vector<ValueType> const& sourceValues, std::vector<ValueType>& targetValues) const {
854 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
855 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
856 "of Storm with CUDD support.");
857}
858
859std::vector<InternalBdd<DdType::CUDD>> InternalBdd<DdType::CUDD>::splitIntoGroups(std::vector<uint_fast64_t> const& ddGroupVariableIndices) const {
860 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
861 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
862 "of Storm with CUDD support.");
863}
864
865void InternalBdd<DdType::CUDD>::filterExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices,
866 storm::storage::BitVector const& sourceValues, storm::storage::BitVector& targetValues) const {
867 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
868 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
869 "of Storm with CUDD support.");
870}
871
872std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> InternalBdd<DdType::CUDD>::toExpression(
874 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
875 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
876 "of Storm with CUDD support.");
877}
878
879#endif
880
884
885#ifdef STORM_HAVE_CUDD
886template void InternalBdd<DdType::CUDD>::filterExplicitVectorRec<double>(DdNode const* dd, cudd::Cudd const& manager, uint_fast64_t currentLevel,
887 bool complement, uint_fast64_t maxLevel,
888 std::vector<uint_fast64_t> const& ddVariableIndices, uint_fast64_t currentOffset,
889 storm::dd::Odd const& odd, std::vector<double>& result, uint_fast64_t& currentIndex,
890 std::vector<double> const& values);
891template void InternalBdd<DdType::CUDD>::filterExplicitVectorRec<uint_fast64_t>(DdNode const* dd, cudd::Cudd const& manager, uint_fast64_t currentLevel,
892 bool complement, uint_fast64_t maxLevel,
893 std::vector<uint_fast64_t> const& ddVariableIndices,
894 uint_fast64_t currentOffset, storm::dd::Odd const& odd,
895 std::vector<uint_fast64_t>& result, uint_fast64_t& currentIndex,
896 std::vector<uint_fast64_t> const& values);
897#endif
898
899template void InternalBdd<DdType::CUDD>::filterExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices,
900 std::vector<double> const& sourceValues, std::vector<double>& targetValues) const;
901template void InternalBdd<DdType::CUDD>::filterExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices,
902 std::vector<uint_fast64_t> const& sourceValues, std::vector<uint_fast64_t>& targetValues) const;
903
905 InternalAdd<DdType::CUDD, double> const& elseAdd) const;
907 InternalAdd<DdType::CUDD, uint_fast64_t> const& elseAdd) const;
910} // namespace dd
911} // namespace storm
Odd const & getThenSuccessor() const
Retrieves the then-successor of this ODD node.
Definition Odd.cpp:20
uint_fast64_t getTotalOffset() const
Retrieves the total offset, i.e., the sum of the then- and else-offset.
Definition Odd.cpp:44
uint_fast64_t getElseOffset() const
Retrieves the else-offset of this ODD node.
Definition Odd.cpp:28
Odd const & getElseSuccessor() const
Retrieves the else-successor of this ODD node.
Definition Odd.cpp:24
This class is responsible for managing a set of typed variables and all expressions using these varia...
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:28
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
Expression iff(Expression const &first, Expression const &second)
SettingsManager const & manager()
Retrieves the settings manager.
storm::storage::BitVector filter(std::vector< T > const &values, std::function< bool(T const &value)> const &function)
Retrieves a bit vector containing all the indices for which the value at this position makes the give...
Definition vector.h:486