3#include <boost/functional/hash.hpp>
18#ifdef STORM_HAVE_SYLVAN
19InternalBdd<DdType::Sylvan>::InternalBdd() : ddManager(nullptr), sylvanBdd() {
23InternalBdd<DdType::Sylvan>::InternalBdd(InternalDdManager<DdType::Sylvan>
const* ddManager, sylvan::Bdd
const& sylvanBdd)
24 : ddManager(ddManager), sylvanBdd(sylvanBdd) {
28InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::fromVector(InternalDdManager<DdType::Sylvan>
const* ddManager, Odd
const& odd,
29 std::vector<uint_fast64_t>
const& sortedDdVariableIndices,
30 std::function<
bool(uint64_t)>
const& filter) {
31 uint_fast64_t offset = 0;
32 return InternalBdd<DdType::Sylvan>(ddManager, sylvan::Bdd(fromVectorRec(offset, 0, sortedDdVariableIndices.size(), odd, sortedDdVariableIndices, filter)));
35BDD InternalBdd<DdType::Sylvan>::fromVectorRec(uint_fast64_t& currentOffset, uint_fast64_t currentLevel, uint_fast64_t maxLevel, Odd
const& odd,
36 std::vector<uint_fast64_t>
const& ddVariableIndices, std::function<
bool(uint64_t)>
const& filter) {
37 if (currentLevel == maxLevel) {
41 if (odd.getThenOffset() > 0) {
42 if (
filter(currentOffset++)) {
52 if (odd.getThenOffset() + odd.getElseOffset() == 0) {
58 if (odd.getElseOffset() > 0) {
59 elseSuccessor = fromVectorRec(currentOffset, currentLevel + 1, maxLevel, odd.getElseSuccessor(), ddVariableIndices, filter);
61 elseSuccessor = sylvan_false;
63 bdd_refs_push(elseSuccessor);
67 if (odd.getThenOffset() > 0) {
68 thenSuccessor = fromVectorRec(currentOffset, currentLevel + 1, maxLevel, odd.getThenSuccessor(), ddVariableIndices, filter);
70 thenSuccessor = sylvan_false;
72 bdd_refs_push(thenSuccessor);
75 BDD currentVar = sylvan_ithvar(
static_cast<BDDVAR
>(ddVariableIndices[currentLevel]));
76 bdd_refs_push(currentVar);
78 BDD result = sylvan_ite(currentVar, thenSuccessor, elseSuccessor);
87bool InternalBdd<DdType::Sylvan>::operator==(InternalBdd<DdType::Sylvan>
const& other)
const {
88 return sylvanBdd == other.sylvanBdd;
91bool InternalBdd<DdType::Sylvan>::operator!=(InternalBdd<DdType::Sylvan>
const& other)
const {
92 return sylvanBdd != other.sylvanBdd;
95InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::relationalProduct(InternalBdd<DdType::Sylvan>
const& relation,
96 std::vector<InternalBdd<DdType::Sylvan>>
const&,
97 std::vector<InternalBdd<DdType::Sylvan>>
const&)
const {
98 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.RelNext(relation.sylvanBdd, sylvan::Bdd(sylvan_false)));
101InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::inverseRelationalProduct(InternalBdd<DdType::Sylvan>
const& relation,
102 std::vector<InternalBdd<DdType::Sylvan>>
const&,
103 std::vector<InternalBdd<DdType::Sylvan>>
const&)
const {
104 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.RelPrev(relation.sylvanBdd, sylvan::Bdd(sylvan_false)));
107InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::inverseRelationalProductWithExtendedRelation(
108 InternalBdd<DdType::Sylvan>
const& relation, std::vector<InternalBdd<DdType::Sylvan>>
const& rowVariables,
109 std::vector<InternalBdd<DdType::Sylvan>>
const& columnVariables)
const {
112 InternalBdd<DdType::Sylvan> columnCube = ddManager->getBddOne();
113 for (
auto const& variable : columnVariables) {
114 columnCube &= variable;
117 return this->swapVariables(rowVariables, columnVariables).andExists(relation, columnCube);
120InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::ite(InternalBdd<DdType::Sylvan>
const& thenDd, InternalBdd<DdType::Sylvan>
const& elseDd)
const {
121 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Ite(thenDd.sylvanBdd, elseDd.sylvanBdd));
124template<
typename ValueType>
125InternalAdd<DdType::Sylvan, ValueType> InternalBdd<DdType::Sylvan>::ite(InternalAdd<DdType::Sylvan, ValueType>
const& thenAdd,
126 InternalAdd<DdType::Sylvan, ValueType>
const& elseAdd)
const {
127 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.Ite(thenAdd.getSylvanMtbdd(), elseAdd.getSylvanMtbdd()));
130InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator||(InternalBdd<DdType::Sylvan>
const& other)
const {
131 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd | other.sylvanBdd);
134InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::operator|=(InternalBdd<DdType::Sylvan>
const& other) {
135 this->sylvanBdd |= other.sylvanBdd;
139InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator&&(InternalBdd<DdType::Sylvan>
const& other)
const {
140 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd & other.sylvanBdd);
143InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::operator&=(InternalBdd<DdType::Sylvan>
const& other) {
144 this->sylvanBdd &= other.sylvanBdd;
148InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::iff(InternalBdd<DdType::Sylvan>
const& other)
const {
149 return InternalBdd<DdType::Sylvan>(ddManager, !(this->sylvanBdd ^ other.sylvanBdd));
152InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::exclusiveOr(InternalBdd<DdType::Sylvan>
const& other)
const {
153 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd ^ other.sylvanBdd);
156InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::implies(InternalBdd<DdType::Sylvan>
const& other)
const {
157 return InternalBdd<DdType::Sylvan>(ddManager, (!this->sylvanBdd) | other.sylvanBdd);
160InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator!()
const {
161 return InternalBdd<DdType::Sylvan>(ddManager, !this->sylvanBdd);
164InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::complement() {
165 this->sylvanBdd = !this->sylvanBdd;
169InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::existsAbstract(InternalBdd<DdType::Sylvan>
const& cube)
const {
170 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.ExistAbstract(cube.sylvanBdd));
173InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::existsAbstractRepresentative(InternalBdd<DdType::Sylvan>
const& cube)
const {
174 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.ExistAbstractRepresentative(cube.sylvanBdd));
177InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::universalAbstract(InternalBdd<DdType::Sylvan>
const& cube)
const {
178 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.UnivAbstract(cube.sylvanBdd));
181InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::andExists(InternalBdd<DdType::Sylvan>
const& other, InternalBdd<DdType::Sylvan>
const& cube)
const {
182 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.AndAbstract(other.sylvanBdd, cube.sylvanBdd));
185InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::constrain(InternalBdd<DdType::Sylvan>
const& constraint)
const {
186 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Constrain(constraint.sylvanBdd));
189InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::restrict(InternalBdd<DdType::Sylvan>
const& constraint)
const {
190 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Restrict(constraint.sylvanBdd));
193InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::swapVariables(std::vector<InternalBdd<DdType::Sylvan>>
const& from,
194 std::vector<InternalBdd<DdType::Sylvan>>
const& to)
const {
195 std::vector<uint32_t> fromIndices;
196 std::vector<uint32_t> toIndices;
197 for (
auto it1 = from.begin(), ite1 = from.end(), it2 = to.begin(); it1 != ite1; ++it1, ++it2) {
198 fromIndices.push_back(it1->getIndex());
199 fromIndices.push_back(it2->getIndex());
200 toIndices.push_back(it2->getIndex());
201 toIndices.push_back(it1->getIndex());
203 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Permute(fromIndices, toIndices));
206InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::getSupport()
const {
207 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Support());
210uint_fast64_t InternalBdd<DdType::Sylvan>::getNonZeroCount(uint_fast64_t numberOfDdVariables)
const {
211 if (numberOfDdVariables == 0) {
214 return static_cast<uint_fast64_t
>(this->sylvanBdd.SatCount(numberOfDdVariables));
217uint_fast64_t InternalBdd<DdType::Sylvan>::getLeafCount()
const {
223uint_fast64_t InternalBdd<DdType::Sylvan>::getNodeCount()
const {
225 return static_cast<uint_fast64_t
>(this->sylvanBdd.NodeCount());
228bool InternalBdd<DdType::Sylvan>::isOne()
const {
229 return this->sylvanBdd.isOne();
232bool InternalBdd<DdType::Sylvan>::isZero()
const {
233 return this->sylvanBdd.isZero();
236uint_fast64_t InternalBdd<DdType::Sylvan>::getIndex()
const {
237 return static_cast<uint_fast64_t
>(this->sylvanBdd.TopVar());
240uint_fast64_t InternalBdd<DdType::Sylvan>::getLevel()
const {
241 return this->getIndex();
244void InternalBdd<DdType::Sylvan>::exportToDot(std::string
const& filename, std::vector<std::string>
const&,
bool)
const {
245 FILE* filePointer = fopen(filename.c_str(),
"a+");
247 if (filePointer ==
nullptr) {
250 this->sylvanBdd.PrintDot(filePointer);
255void InternalBdd<DdType::Sylvan>::exportToText(std::string
const& filename)
const {
256 FILE* filePointer = fopen(filename.c_str(),
"a+");
258 if (filePointer ==
nullptr) {
261 this->sylvanBdd.PrintText(filePointer);
266sylvan::Bdd& InternalBdd<DdType::Sylvan>::getSylvanBdd() {
270sylvan::Bdd
const& InternalBdd<DdType::Sylvan>::getSylvanBdd()
const {
274template<
typename ValueType>
275InternalAdd<DdType::Sylvan, ValueType> InternalBdd<DdType::Sylvan>::toAdd()
const {
276 if (std::is_same<ValueType, double>::value) {
277 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toDoubleMtbdd());
278 }
else if (std::is_same<ValueType, uint_fast64_t>::value) {
279 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toInt64Mtbdd());
280 }
else if (std::is_same<ValueType, storm::RationalNumber>::value) {
281 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toStormRationalNumberMtbdd());
282 }
else if (std::is_same<ValueType, storm::RationalFunction>::value) {
283 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toStormRationalFunctionMtbdd());
285 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Illegal ADD type.");
291 this->toVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), result, rowOdd, bdd_isnegated(this->getSylvanBdd().GetBDD()), 0, ddVariableIndices.size(), 0,
296void InternalBdd<DdType::Sylvan>::toVectorRec(BDD dd,
storm::storage::BitVector& result, Odd
const& rowOdd,
bool complement, uint_fast64_t currentRowLevel,
297 uint_fast64_t maxLevel, uint_fast64_t currentRowOffset,
298 std::vector<uint_fast64_t>
const& ddRowVariableIndices)
const {
300 if (dd == sylvan_false && !complement) {
302 }
else if (dd == sylvan_true && complement) {
307 if (currentRowLevel == maxLevel) {
308 result.
set(currentRowOffset,
true);
309 }
else if (bdd_isterminal(dd) || ddRowVariableIndices[currentRowLevel] < sylvan_var(dd)) {
310 toVectorRec(dd, result, rowOdd.getElseSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset, ddRowVariableIndices);
311 toVectorRec(dd, result, rowOdd.getThenSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset + rowOdd.getElseOffset(),
312 ddRowVariableIndices);
315 BDD elseDdNode = sylvan_low(dd);
316 BDD thenDdNode = sylvan_high(dd);
319 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
320 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
322 toVectorRec(bdd_regular(elseDdNode), result, rowOdd.getElseSuccessor(), elseComplemented, currentRowLevel + 1, maxLevel, currentRowOffset,
323 ddRowVariableIndices);
324 toVectorRec(bdd_regular(thenDdNode), result, rowOdd.getThenSuccessor(), thenComplemented, currentRowLevel + 1, maxLevel,
325 currentRowOffset + rowOdd.getElseOffset(), ddRowVariableIndices);
329Odd InternalBdd<DdType::Sylvan>::createOdd(std::vector<uint_fast64_t>
const& ddVariableIndices)
const {
331 std::vector<std::unordered_map<std::pair<BDD, bool>, std::shared_ptr<Odd>, HashFunctor>> uniqueTableForLevels(ddVariableIndices.size() + 1);
334 std::shared_ptr<Odd> rootOdd = createOddRec(bdd_regular(this->getSylvanBdd().GetBDD()), bdd_isnegated(this->getSylvanBdd().GetBDD()), 0,
335 ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels);
338 return Odd(*rootOdd);
341std::size_t InternalBdd<DdType::Sylvan>::HashFunctor::operator()(std::pair<BDD, bool>
const& key)
const {
342 std::size_t result = 0;
343 boost::hash_combine(result, key.first);
344 boost::hash_combine(result, key.second);
348std::shared_ptr<Odd> InternalBdd<DdType::Sylvan>::createOddRec(
349 BDD dd,
bool complement, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t>
const& ddVariableIndices,
350 std::vector<std::unordered_map<std::pair<BDD, bool>, std::shared_ptr<Odd>, HashFunctor>>& uniqueTableForLevels) {
352 auto const& iterator = uniqueTableForLevels[currentLevel].find(std::make_pair(dd, complement));
353 if (iterator != uniqueTableForLevels[currentLevel].end()) {
354 return iterator->second;
360 if (currentLevel == maxLevel) {
361 uint_fast64_t elseOffset = 0;
362 uint_fast64_t thenOffset = 0;
365 if (dd != mtbdd_false) {
371 thenOffset = 1 - thenOffset;
374 auto oddNode = std::make_shared<Odd>(
nullptr, elseOffset,
nullptr, thenOffset);
375 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
377 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
380 std::shared_ptr<Odd> elseNode = createOddRec(dd, complement, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
381 std::shared_ptr<Odd> thenNode = elseNode;
382 uint_fast64_t totalOffset = elseNode->getElseOffset() + elseNode->getThenOffset();
383 auto oddNode = std::make_shared<Odd>(elseNode, totalOffset, thenNode, totalOffset);
384 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
388 BDD thenDdNode = sylvan_high(dd);
389 BDD elseDdNode = sylvan_low(dd);
392 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
393 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
395 std::shared_ptr<Odd> elseNode =
396 createOddRec(bdd_regular(elseDdNode), elseComplemented, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
397 std::shared_ptr<Odd> thenNode =
398 createOddRec(bdd_regular(thenDdNode), thenComplemented, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
400 auto oddNode = std::make_shared<Odd>(elseNode, elseNode->getElseOffset() + elseNode->getThenOffset(), thenNode,
401 thenNode->getElseOffset() + thenNode->getThenOffset());
402 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
408template<
typename ValueType>
409void InternalBdd<DdType::Sylvan>::filterExplicitVector(Odd
const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
410 std::vector<ValueType>
const& sourceValues, std::vector<ValueType>& targetValues)
const {
411 uint_fast64_t currentIndex = 0;
412 filterExplicitVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), 0, bdd_isnegated(this->getSylvanBdd().GetBDD()), ddVariableIndices.size(),
413 ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
416template<
typename ValueType>
417void InternalBdd<DdType::Sylvan>::filterExplicitVectorRec(BDD dd, uint_fast64_t currentLevel,
bool complement, uint_fast64_t maxLevel,
418 std::vector<uint_fast64_t>
const& ddVariableIndices, uint_fast64_t currentOffset,
419 storm::dd::Odd const& odd, std::vector<ValueType>& result, uint_fast64_t& currentIndex,
420 std::vector<ValueType>
const& values) {
422 if (dd == sylvan_false && !complement) {
424 }
else if (dd == sylvan_true && complement) {
428 if (currentLevel == maxLevel) {
429 result[currentIndex++] = values[currentOffset];
430 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
433 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(), result, currentIndex,
435 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(), odd.
getThenSuccessor(),
436 result, currentIndex, values);
439 BDD thenDdNode = sylvan_high(dd);
440 BDD elseDdNode = sylvan_low(dd);
443 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
444 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
446 filterExplicitVectorRec(bdd_regular(elseDdNode), currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(),
447 result, currentIndex, values);
448 filterExplicitVectorRec(bdd_regular(thenDdNode), currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(),
453void InternalBdd<DdType::Sylvan>::filterExplicitVector(Odd
const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
455 uint_fast64_t currentIndex = 0;
456 filterExplicitVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), 0, bdd_isnegated(this->getSylvanBdd().GetBDD()), ddVariableIndices.size(),
457 ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
460void InternalBdd<DdType::Sylvan>::filterExplicitVectorRec(BDD dd, uint_fast64_t currentLevel,
bool complement, uint_fast64_t maxLevel,
461 std::vector<uint_fast64_t>
const& ddVariableIndices, uint_fast64_t currentOffset,
465 if (dd == sylvan_false && !complement) {
467 }
else if (dd == sylvan_true && complement) {
471 if (currentLevel == maxLevel) {
472 result.
set(currentIndex++, values.
get(currentOffset));
473 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
476 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(), result, currentIndex,
478 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(), odd.
getThenSuccessor(),
479 result, currentIndex, values);
482 BDD thenDdNode = sylvan_high(dd);
483 BDD elseDdNode = sylvan_low(dd);
486 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
487 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
489 filterExplicitVectorRec(bdd_regular(elseDdNode), currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(),
490 result, currentIndex, values);
491 filterExplicitVectorRec(bdd_regular(thenDdNode), currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(),
496std::vector<InternalBdd<DdType::Sylvan>> InternalBdd<DdType::Sylvan>::splitIntoGroups(std::vector<uint_fast64_t>
const& ddGroupVariableIndices)
const {
497 std::vector<InternalBdd<DdType::Sylvan>> result;
498 splitIntoGroupsRec(this->getSylvanBdd().GetBDD(), result, ddGroupVariableIndices, 0, ddGroupVariableIndices.size());
502void InternalBdd<DdType::Sylvan>::splitIntoGroupsRec(BDD dd, std::vector<InternalBdd<DdType::Sylvan>>& groups,
503 std::vector<uint_fast64_t>
const& ddGroupVariableIndices, uint_fast64_t currentLevel,
504 uint_fast64_t maxLevel)
const {
506 if (dd == sylvan_false) {
510 if (currentLevel == maxLevel) {
511 groups.push_back(InternalBdd<DdType::Sylvan>(ddManager, sylvan::Bdd(dd)));
512 }
else if (bdd_isterminal(dd) || ddGroupVariableIndices[currentLevel] < sylvan_var(dd)) {
513 splitIntoGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
514 splitIntoGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
517 BDD thenDdNode = sylvan_high(dd);
518 BDD elseDdNode = sylvan_low(dd);
520 splitIntoGroupsRec(elseDdNode, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
521 splitIntoGroupsRec(thenDdNode, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
525std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>>
527 std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> result;
531 std::unordered_map<BDD, uint_fast64_t> nodeToCounterMap;
532 std::vector<uint_fast64_t> nextCounterForIndex(ddManager->getNumberOfDdVariables(), 0);
535 bool negated = bdd_isnegated(this->getSylvanBdd().GetBDD());
538 storm::expressions::Variable topVariable = this->toExpressionRec(bdd_regular(this->getSylvanBdd().GetBDD()), manager, result.first, result.second,
539 countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
543 result.first.push_back(!topVariable);
545 result.first.push_back(topVariable);
553 std::unordered_map<uint_fast64_t, storm::expressions::Variable>& indexToVariableMap,
555 std::unordered_map<BDD, uint_fast64_t>& nodeToCounterMap, std::vector<uint_fast64_t>& nextCounterForIndex) {
559 auto nodeCounterIt = nodeToCounterMap.find(dd);
560 if (nodeCounterIt != nodeToCounterMap.end()) {
562 auto variableIt = countIndexToVariablePair.find(std::make_pair(nodeCounterIt->second, sylvan_var(dd)));
563 STORM_LOG_ASSERT(variableIt != countIndexToVariablePair.end(),
"Unable to find node.");
564 return variableIt->second;
571 if (!bdd_isterminal(dd)) {
573 nodeToCounterMap[dd] = nextCounterForIndex[sylvan_var(dd)];
574 countIndexToVariablePair[std::make_pair(nextCounterForIndex[sylvan_var(dd)], sylvan_var(dd))] = newNodeVariable;
575 ++nextCounterForIndex[sylvan_var(dd)];
578 nodeToCounterMap[dd] = 0;
579 countIndexToVariablePair[std::make_pair(0, sylvan_var(dd))] = newNodeVariable;
583 if (bdd_isterminal(dd)) {
584 if (dd == sylvan_true) {
591 BDD t = sylvan_high(dd);
592 BDD e = sylvan_low(dd);
593 BDD T = bdd_regular(t);
594 BDD E = bdd_regular(e);
596 toExpressionRec(T, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
598 toExpressionRec(E, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
602 auto indexVariable = indexToVariableMap.find(sylvan_var(dd));
604 if (indexVariable == indexToVariableMap.end()) {
605 levelVariable =
manager.declareFreshBooleanVariable();
606 indexToVariableMap[sylvan_var(dd)] = levelVariable;
608 levelVariable = indexVariable->second;
611 newNodeVariable,
storm::expressions::ite(levelVariable, t == T ? thenVariable : !thenVariable, e == E ? elseVariable : !elseVariable)));
615 return newNodeVariable;
620 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
621 "version of Storm with Sylvan support.");
625 std::vector<uint_fast64_t>
const& sortedDdVariableIndices,
626 std::function<
bool(uint64_t)>
const& filter) {
628 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
629 "version of Storm with Sylvan support.");
634 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
635 "version of Storm with Sylvan support.");
640 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
641 "version of Storm with Sylvan support.");
648 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
649 "version of Storm with Sylvan support.");
656 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
657 "version of Storm with Sylvan support.");
664 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
665 "version of Storm with Sylvan support.");
670 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
671 "version of Storm with Sylvan support.");
674template<
typename ValueType>
678 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
679 "version of Storm with Sylvan support.");
684 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
685 "version of Storm with Sylvan support.");
690 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
691 "version of Storm with Sylvan support.");
696 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
697 "version of Storm with Sylvan support.");
702 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
703 "version of Storm with Sylvan support.");
708 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
709 "version of Storm with Sylvan support.");
714 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
715 "version of Storm with Sylvan support.");
720 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
721 "version of Storm with Sylvan support.");
726 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
727 "version of Storm with Sylvan support.");
732 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
733 "version of Storm with Sylvan support.");
738 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
739 "version of Storm with Sylvan support.");
744 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
745 "version of Storm with Sylvan support.");
750 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
751 "version of Storm with Sylvan support.");
756 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
757 "version of Storm with Sylvan support.");
762 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
763 "version of Storm with Sylvan support.");
768 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
769 "version of Storm with Sylvan support.");
775 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
776 "version of Storm with Sylvan support.");
781 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
782 "version of Storm with Sylvan support.");
787 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
788 "version of Storm with Sylvan support.");
793 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
794 "version of Storm with Sylvan support.");
799 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
800 "version of Storm with Sylvan support.");
805 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
806 "version of Storm with Sylvan support.");
811 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
812 "version of Storm with Sylvan support.");
817 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
818 "version of Storm with Sylvan support.");
823 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
824 "version of Storm with Sylvan support.");
829 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
830 "version of Storm with Sylvan support.");
835 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
836 "version of Storm with Sylvan support.");
839template<
typename ValueType>
842 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
843 "version of Storm with Sylvan support.");
848 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
849 "version of Storm with Sylvan support.");
854 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
855 "version of Storm with Sylvan support.");
858template<
typename ValueType>
860 std::vector<ValueType>
const& sourceValues, std::vector<ValueType>& targetValues)
const {
862 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
863 "version of Storm with Sylvan support.");
869 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
870 "version of Storm with Sylvan support.");
875 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
876 "version of Storm with Sylvan support.");
879std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>>
882 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
883 "version of Storm with Sylvan support.");
893 std::vector<double>
const& sourceValues, std::vector<double>& targetValues)
const;
895 std::vector<uint_fast64_t>
const& sourceValues, std::vector<uint_fast64_t>& targetValues)
const;
897 std::vector<storm::RationalNumber>
const& sourceValues,
898 std::vector<storm::RationalNumber>& targetValues)
const;
900 std::vector<storm::RationalFunction>
const& sourceValues,
901 std::vector<storm::RationalFunction>& targetValues)
const;
Odd const & getThenSuccessor() const
Retrieves the then-successor of this ODD node.
uint_fast64_t getTotalOffset() const
Retrieves the total offset, i.e., the sum of the then- and else-offset.
uint_fast64_t getElseOffset() const
Retrieves the else-offset of this ODD node.
Odd const & getElseSuccessor() const
Retrieves the else-successor of this ODD node.
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.
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_ERROR(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
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...