3#include <boost/functional/hash.hpp>
17#ifdef STORM_HAVE_SYLVAN
18InternalBdd<DdType::Sylvan>::InternalBdd() : ddManager(nullptr), sylvanBdd() {
22InternalBdd<DdType::Sylvan>::InternalBdd(InternalDdManager<DdType::Sylvan>
const* ddManager, sylvan::Bdd
const& sylvanBdd)
23 : ddManager(ddManager), sylvanBdd(sylvanBdd) {
27InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::fromVector(InternalDdManager<DdType::Sylvan>
const* ddManager, Odd
const& odd,
28 std::vector<uint_fast64_t>
const& sortedDdVariableIndices,
29 std::function<
bool(uint64_t)>
const& filter) {
30 uint_fast64_t offset = 0;
31 return InternalBdd<DdType::Sylvan>(ddManager, sylvan::Bdd(fromVectorRec(offset, 0, sortedDdVariableIndices.size(), odd, sortedDdVariableIndices, filter)));
34BDD InternalBdd<DdType::Sylvan>::fromVectorRec(uint_fast64_t& currentOffset, uint_fast64_t currentLevel, uint_fast64_t maxLevel, Odd
const& odd,
35 std::vector<uint_fast64_t>
const& ddVariableIndices, std::function<
bool(uint64_t)>
const& filter) {
36 if (currentLevel == maxLevel) {
40 if (odd.getThenOffset() > 0) {
41 if (
filter(currentOffset++)) {
51 if (odd.getThenOffset() + odd.getElseOffset() == 0) {
57 if (odd.getElseOffset() > 0) {
58 elseSuccessor = fromVectorRec(currentOffset, currentLevel + 1, maxLevel, odd.getElseSuccessor(), ddVariableIndices, filter);
60 elseSuccessor = sylvan_false;
62 bdd_refs_push(elseSuccessor);
66 if (odd.getThenOffset() > 0) {
67 thenSuccessor = fromVectorRec(currentOffset, currentLevel + 1, maxLevel, odd.getThenSuccessor(), ddVariableIndices, filter);
69 thenSuccessor = sylvan_false;
71 bdd_refs_push(thenSuccessor);
74 BDD currentVar = sylvan_ithvar(
static_cast<BDDVAR
>(ddVariableIndices[currentLevel]));
75 bdd_refs_push(currentVar);
77 BDD result = sylvan_ite(currentVar, thenSuccessor, elseSuccessor);
86bool InternalBdd<DdType::Sylvan>::operator==(InternalBdd<DdType::Sylvan>
const& other)
const {
87 return sylvanBdd == other.sylvanBdd;
90bool InternalBdd<DdType::Sylvan>::operator!=(InternalBdd<DdType::Sylvan>
const& other)
const {
91 return sylvanBdd != other.sylvanBdd;
94InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::relationalProduct(InternalBdd<DdType::Sylvan>
const& relation,
95 std::vector<InternalBdd<DdType::Sylvan>>
const&,
96 std::vector<InternalBdd<DdType::Sylvan>>
const&)
const {
97 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.RelNext(relation.sylvanBdd, sylvan::Bdd(sylvan_false)));
100InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::inverseRelationalProduct(InternalBdd<DdType::Sylvan>
const& relation,
101 std::vector<InternalBdd<DdType::Sylvan>>
const&,
102 std::vector<InternalBdd<DdType::Sylvan>>
const&)
const {
103 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.RelPrev(relation.sylvanBdd, sylvan::Bdd(sylvan_false)));
106InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::inverseRelationalProductWithExtendedRelation(
107 InternalBdd<DdType::Sylvan>
const& relation, std::vector<InternalBdd<DdType::Sylvan>>
const& rowVariables,
108 std::vector<InternalBdd<DdType::Sylvan>>
const& columnVariables)
const {
111 InternalBdd<DdType::Sylvan> columnCube = ddManager->getBddOne();
112 for (
auto const& variable : columnVariables) {
113 columnCube &= variable;
116 return this->swapVariables(rowVariables, columnVariables).andExists(relation, columnCube);
119InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::ite(InternalBdd<DdType::Sylvan>
const& thenDd, InternalBdd<DdType::Sylvan>
const& elseDd)
const {
120 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Ite(thenDd.sylvanBdd, elseDd.sylvanBdd));
123template<
typename ValueType>
124InternalAdd<DdType::Sylvan, ValueType> InternalBdd<DdType::Sylvan>::ite(InternalAdd<DdType::Sylvan, ValueType>
const& thenAdd,
125 InternalAdd<DdType::Sylvan, ValueType>
const& elseAdd)
const {
126 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.Ite(thenAdd.getSylvanMtbdd(), elseAdd.getSylvanMtbdd()));
129InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator||(InternalBdd<DdType::Sylvan>
const& other)
const {
130 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd | other.sylvanBdd);
133InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::operator|=(InternalBdd<DdType::Sylvan>
const& other) {
134 this->sylvanBdd |= other.sylvanBdd;
138InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator&&(InternalBdd<DdType::Sylvan>
const& other)
const {
139 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd & other.sylvanBdd);
142InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::operator&=(InternalBdd<DdType::Sylvan>
const& other) {
143 this->sylvanBdd &= other.sylvanBdd;
147InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::iff(InternalBdd<DdType::Sylvan>
const& other)
const {
148 return InternalBdd<DdType::Sylvan>(ddManager, !(this->sylvanBdd ^ other.sylvanBdd));
151InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::exclusiveOr(InternalBdd<DdType::Sylvan>
const& other)
const {
152 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd ^ other.sylvanBdd);
155InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::implies(InternalBdd<DdType::Sylvan>
const& other)
const {
156 return InternalBdd<DdType::Sylvan>(ddManager, (!this->sylvanBdd) | other.sylvanBdd);
159InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator!()
const {
160 return InternalBdd<DdType::Sylvan>(ddManager, !this->sylvanBdd);
163InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::complement() {
164 this->sylvanBdd = !this->sylvanBdd;
168InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::existsAbstract(InternalBdd<DdType::Sylvan>
const& cube)
const {
169 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.ExistAbstract(cube.sylvanBdd));
172InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::existsAbstractRepresentative(InternalBdd<DdType::Sylvan>
const& cube)
const {
173 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.ExistAbstractRepresentative(cube.sylvanBdd));
176InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::universalAbstract(InternalBdd<DdType::Sylvan>
const& cube)
const {
177 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.UnivAbstract(cube.sylvanBdd));
180InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::andExists(InternalBdd<DdType::Sylvan>
const& other, InternalBdd<DdType::Sylvan>
const& cube)
const {
181 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.AndAbstract(other.sylvanBdd, cube.sylvanBdd));
184InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::constrain(InternalBdd<DdType::Sylvan>
const& constraint)
const {
185 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Constrain(constraint.sylvanBdd));
188InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::restrict(InternalBdd<DdType::Sylvan>
const& constraint)
const {
189 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Restrict(constraint.sylvanBdd));
192InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::swapVariables(std::vector<InternalBdd<DdType::Sylvan>>
const& from,
193 std::vector<InternalBdd<DdType::Sylvan>>
const& to)
const {
194 std::vector<uint32_t> fromIndices;
195 std::vector<uint32_t> toIndices;
196 for (
auto it1 = from.begin(), ite1 = from.end(), it2 = to.begin(); it1 != ite1; ++it1, ++it2) {
197 fromIndices.push_back(it1->getIndex());
198 fromIndices.push_back(it2->getIndex());
199 toIndices.push_back(it2->getIndex());
200 toIndices.push_back(it1->getIndex());
202 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Permute(fromIndices, toIndices));
205InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::getSupport()
const {
206 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Support());
209uint_fast64_t InternalBdd<DdType::Sylvan>::getNonZeroCount(uint_fast64_t numberOfDdVariables)
const {
210 if (numberOfDdVariables == 0) {
213 return static_cast<uint_fast64_t
>(this->sylvanBdd.SatCount(numberOfDdVariables));
216uint_fast64_t InternalBdd<DdType::Sylvan>::getLeafCount()
const {
222uint_fast64_t InternalBdd<DdType::Sylvan>::getNodeCount()
const {
224 return static_cast<uint_fast64_t
>(this->sylvanBdd.NodeCount());
227bool InternalBdd<DdType::Sylvan>::isOne()
const {
228 return this->sylvanBdd.isOne();
231bool InternalBdd<DdType::Sylvan>::isZero()
const {
232 return this->sylvanBdd.isZero();
235uint_fast64_t InternalBdd<DdType::Sylvan>::getIndex()
const {
236 return static_cast<uint_fast64_t
>(this->sylvanBdd.TopVar());
239uint_fast64_t InternalBdd<DdType::Sylvan>::getLevel()
const {
240 return this->getIndex();
243void InternalBdd<DdType::Sylvan>::exportToDot(std::string
const& filename, std::vector<std::string>
const&,
bool)
const {
244 FILE* filePointer = fopen(filename.c_str(),
"a+");
246 if (filePointer ==
nullptr) {
249 this->sylvanBdd.PrintDot(filePointer);
254void InternalBdd<DdType::Sylvan>::exportToText(std::string
const& filename)
const {
255 FILE* filePointer = fopen(filename.c_str(),
"a+");
257 if (filePointer ==
nullptr) {
260 this->sylvanBdd.PrintText(filePointer);
265sylvan::Bdd& InternalBdd<DdType::Sylvan>::getSylvanBdd() {
269sylvan::Bdd
const& InternalBdd<DdType::Sylvan>::getSylvanBdd()
const {
273template<
typename ValueType>
274InternalAdd<DdType::Sylvan, ValueType> InternalBdd<DdType::Sylvan>::toAdd()
const {
275 if (std::is_same<ValueType, double>::value) {
276 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toDoubleMtbdd());
277 }
else if (std::is_same<ValueType, uint_fast64_t>::value) {
278 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toInt64Mtbdd());
279 }
else if (std::is_same<ValueType, storm::RationalNumber>::value) {
280 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toStormRationalNumberMtbdd());
281 }
else if (std::is_same<ValueType, storm::RationalFunction>::value) {
282 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toStormRationalFunctionMtbdd());
284 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Illegal ADD type.");
290 this->toVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), result, rowOdd, bdd_isnegated(this->getSylvanBdd().GetBDD()), 0, ddVariableIndices.size(), 0,
295void InternalBdd<DdType::Sylvan>::toVectorRec(BDD dd,
storm::storage::BitVector& result, Odd
const& rowOdd,
bool complement, uint_fast64_t currentRowLevel,
296 uint_fast64_t maxLevel, uint_fast64_t currentRowOffset,
297 std::vector<uint_fast64_t>
const& ddRowVariableIndices)
const {
299 if (dd == sylvan_false && !complement) {
301 }
else if (dd == sylvan_true && complement) {
306 if (currentRowLevel == maxLevel) {
307 result.
set(currentRowOffset,
true);
308 }
else if (bdd_isterminal(dd) || ddRowVariableIndices[currentRowLevel] < sylvan_var(dd)) {
309 toVectorRec(dd, result, rowOdd.getElseSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset, ddRowVariableIndices);
310 toVectorRec(dd, result, rowOdd.getThenSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset + rowOdd.getElseOffset(),
311 ddRowVariableIndices);
314 BDD elseDdNode = sylvan_low(dd);
315 BDD thenDdNode = sylvan_high(dd);
318 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
319 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
321 toVectorRec(bdd_regular(elseDdNode), result, rowOdd.getElseSuccessor(), elseComplemented, currentRowLevel + 1, maxLevel, currentRowOffset,
322 ddRowVariableIndices);
323 toVectorRec(bdd_regular(thenDdNode), result, rowOdd.getThenSuccessor(), thenComplemented, currentRowLevel + 1, maxLevel,
324 currentRowOffset + rowOdd.getElseOffset(), ddRowVariableIndices);
328Odd InternalBdd<DdType::Sylvan>::createOdd(std::vector<uint_fast64_t>
const& ddVariableIndices)
const {
330 std::vector<std::unordered_map<std::pair<BDD, bool>, std::shared_ptr<Odd>, HashFunctor>> uniqueTableForLevels(ddVariableIndices.size() + 1);
333 std::shared_ptr<Odd> rootOdd = createOddRec(bdd_regular(this->getSylvanBdd().GetBDD()), bdd_isnegated(this->getSylvanBdd().GetBDD()), 0,
334 ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels);
337 return Odd(*rootOdd);
340std::size_t InternalBdd<DdType::Sylvan>::HashFunctor::operator()(std::pair<BDD, bool>
const& key)
const {
341 std::size_t result = 0;
342 boost::hash_combine(result, key.first);
343 boost::hash_combine(result, key.second);
347std::shared_ptr<Odd> InternalBdd<DdType::Sylvan>::createOddRec(
348 BDD dd,
bool complement, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t>
const& ddVariableIndices,
349 std::vector<std::unordered_map<std::pair<BDD, bool>, std::shared_ptr<Odd>, HashFunctor>>& uniqueTableForLevels) {
351 auto const& iterator = uniqueTableForLevels[currentLevel].find(std::make_pair(dd, complement));
352 if (iterator != uniqueTableForLevels[currentLevel].end()) {
353 return iterator->second;
359 if (currentLevel == maxLevel) {
360 uint_fast64_t elseOffset = 0;
361 uint_fast64_t thenOffset = 0;
364 if (dd != mtbdd_false) {
370 thenOffset = 1 - thenOffset;
373 auto oddNode = std::make_shared<Odd>(
nullptr, elseOffset,
nullptr, thenOffset);
374 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
376 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
379 std::shared_ptr<Odd> elseNode = createOddRec(dd, complement, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
380 std::shared_ptr<Odd> thenNode = elseNode;
381 uint_fast64_t totalOffset = elseNode->getElseOffset() + elseNode->getThenOffset();
382 auto oddNode = std::make_shared<Odd>(elseNode, totalOffset, thenNode, totalOffset);
383 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
387 BDD thenDdNode = sylvan_high(dd);
388 BDD elseDdNode = sylvan_low(dd);
391 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
392 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
394 std::shared_ptr<Odd> elseNode =
395 createOddRec(bdd_regular(elseDdNode), elseComplemented, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
396 std::shared_ptr<Odd> thenNode =
397 createOddRec(bdd_regular(thenDdNode), thenComplemented, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
399 auto oddNode = std::make_shared<Odd>(elseNode, elseNode->getElseOffset() + elseNode->getThenOffset(), thenNode,
400 thenNode->getElseOffset() + thenNode->getThenOffset());
401 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
407template<
typename ValueType>
408void InternalBdd<DdType::Sylvan>::filterExplicitVector(Odd
const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
409 std::vector<ValueType>
const& sourceValues, std::vector<ValueType>& targetValues)
const {
410 uint_fast64_t currentIndex = 0;
411 filterExplicitVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), 0, bdd_isnegated(this->getSylvanBdd().GetBDD()), ddVariableIndices.size(),
412 ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
415template<
typename ValueType>
416void InternalBdd<DdType::Sylvan>::filterExplicitVectorRec(BDD dd, uint_fast64_t currentLevel,
bool complement, uint_fast64_t maxLevel,
417 std::vector<uint_fast64_t>
const& ddVariableIndices, uint_fast64_t currentOffset,
418 storm::dd::Odd const& odd, std::vector<ValueType>& result, uint_fast64_t& currentIndex,
419 std::vector<ValueType>
const& values) {
421 if (dd == sylvan_false && !complement) {
423 }
else if (dd == sylvan_true && complement) {
427 if (currentLevel == maxLevel) {
428 result[currentIndex++] = values[currentOffset];
429 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
432 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(), result, currentIndex,
434 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(), odd.
getThenSuccessor(),
435 result, currentIndex, values);
438 BDD thenDdNode = sylvan_high(dd);
439 BDD elseDdNode = sylvan_low(dd);
442 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
443 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
445 filterExplicitVectorRec(bdd_regular(elseDdNode), currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(),
446 result, currentIndex, values);
447 filterExplicitVectorRec(bdd_regular(thenDdNode), currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(),
452void InternalBdd<DdType::Sylvan>::filterExplicitVector(Odd
const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
454 uint_fast64_t currentIndex = 0;
455 filterExplicitVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), 0, bdd_isnegated(this->getSylvanBdd().GetBDD()), ddVariableIndices.size(),
456 ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
459void InternalBdd<DdType::Sylvan>::filterExplicitVectorRec(BDD dd, uint_fast64_t currentLevel,
bool complement, uint_fast64_t maxLevel,
460 std::vector<uint_fast64_t>
const& ddVariableIndices, uint_fast64_t currentOffset,
464 if (dd == sylvan_false && !complement) {
466 }
else if (dd == sylvan_true && complement) {
470 if (currentLevel == maxLevel) {
471 result.
set(currentIndex++, values.
get(currentOffset));
472 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
475 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(), result, currentIndex,
477 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(), odd.
getThenSuccessor(),
478 result, currentIndex, values);
481 BDD thenDdNode = sylvan_high(dd);
482 BDD elseDdNode = sylvan_low(dd);
485 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
486 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
488 filterExplicitVectorRec(bdd_regular(elseDdNode), currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(),
489 result, currentIndex, values);
490 filterExplicitVectorRec(bdd_regular(thenDdNode), currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(),
495std::vector<InternalBdd<DdType::Sylvan>> InternalBdd<DdType::Sylvan>::splitIntoGroups(std::vector<uint_fast64_t>
const& ddGroupVariableIndices)
const {
496 std::vector<InternalBdd<DdType::Sylvan>> result;
497 splitIntoGroupsRec(this->getSylvanBdd().GetBDD(), result, ddGroupVariableIndices, 0, ddGroupVariableIndices.size());
501void InternalBdd<DdType::Sylvan>::splitIntoGroupsRec(BDD dd, std::vector<InternalBdd<DdType::Sylvan>>& groups,
502 std::vector<uint_fast64_t>
const& ddGroupVariableIndices, uint_fast64_t currentLevel,
503 uint_fast64_t maxLevel)
const {
505 if (dd == sylvan_false) {
509 if (currentLevel == maxLevel) {
510 groups.push_back(InternalBdd<DdType::Sylvan>(ddManager, sylvan::Bdd(dd)));
511 }
else if (bdd_isterminal(dd) || ddGroupVariableIndices[currentLevel] < sylvan_var(dd)) {
512 splitIntoGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
513 splitIntoGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
516 BDD thenDdNode = sylvan_high(dd);
517 BDD elseDdNode = sylvan_low(dd);
519 splitIntoGroupsRec(elseDdNode, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
520 splitIntoGroupsRec(thenDdNode, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
524std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>>
526 std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> result;
530 std::unordered_map<BDD, uint_fast64_t> nodeToCounterMap;
531 std::vector<uint_fast64_t> nextCounterForIndex(ddManager->getNumberOfDdVariables(), 0);
534 bool negated = bdd_isnegated(this->getSylvanBdd().GetBDD());
537 storm::expressions::Variable topVariable = this->toExpressionRec(bdd_regular(this->getSylvanBdd().GetBDD()), manager, result.first, result.second,
538 countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
542 result.first.push_back(!topVariable);
544 result.first.push_back(topVariable);
552 std::unordered_map<uint_fast64_t, storm::expressions::Variable>& indexToVariableMap,
554 std::unordered_map<BDD, uint_fast64_t>& nodeToCounterMap, std::vector<uint_fast64_t>& nextCounterForIndex) {
558 auto nodeCounterIt = nodeToCounterMap.find(dd);
559 if (nodeCounterIt != nodeToCounterMap.end()) {
561 auto variableIt = countIndexToVariablePair.find(std::make_pair(nodeCounterIt->second, sylvan_var(dd)));
562 STORM_LOG_ASSERT(variableIt != countIndexToVariablePair.end(),
"Unable to find node.");
563 return variableIt->second;
570 if (!bdd_isterminal(dd)) {
572 nodeToCounterMap[dd] = nextCounterForIndex[sylvan_var(dd)];
573 countIndexToVariablePair[std::make_pair(nextCounterForIndex[sylvan_var(dd)], sylvan_var(dd))] = newNodeVariable;
574 ++nextCounterForIndex[sylvan_var(dd)];
577 nodeToCounterMap[dd] = 0;
578 countIndexToVariablePair[std::make_pair(0, sylvan_var(dd))] = newNodeVariable;
582 if (bdd_isterminal(dd)) {
583 if (dd == sylvan_true) {
590 BDD t = sylvan_high(dd);
591 BDD e = sylvan_low(dd);
592 BDD T = bdd_regular(t);
593 BDD E = bdd_regular(e);
595 toExpressionRec(T, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
597 toExpressionRec(E, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
601 auto indexVariable = indexToVariableMap.find(sylvan_var(dd));
603 if (indexVariable == indexToVariableMap.end()) {
604 levelVariable =
manager.declareFreshBooleanVariable();
605 indexToVariableMap[sylvan_var(dd)] = levelVariable;
607 levelVariable = indexVariable->second;
610 newNodeVariable,
storm::expressions::ite(levelVariable, t == T ? thenVariable : !thenVariable, e == E ? elseVariable : !elseVariable)));
614 return newNodeVariable;
619 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
620 "version of Storm with Sylvan support.");
624 std::vector<uint_fast64_t>
const& sortedDdVariableIndices,
625 std::function<
bool(uint64_t)>
const& filter) {
627 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
628 "version of Storm with Sylvan support.");
633 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
634 "version of Storm with Sylvan support.");
639 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
640 "version of Storm with Sylvan support.");
647 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
648 "version of Storm with Sylvan support.");
655 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
656 "version of Storm with Sylvan support.");
663 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
664 "version of Storm with Sylvan support.");
669 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
670 "version of Storm with Sylvan support.");
673template<
typename ValueType>
677 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
678 "version of Storm with Sylvan support.");
683 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
684 "version of Storm with Sylvan support.");
689 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
690 "version of Storm with Sylvan support.");
695 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
696 "version of Storm with Sylvan support.");
701 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
702 "version of Storm with Sylvan support.");
707 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
708 "version of Storm with Sylvan support.");
713 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
714 "version of Storm with Sylvan support.");
719 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
720 "version of Storm with Sylvan support.");
725 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
726 "version of Storm with Sylvan support.");
731 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
732 "version of Storm with Sylvan support.");
737 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
738 "version of Storm with Sylvan support.");
743 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
744 "version of Storm with Sylvan support.");
749 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
750 "version of Storm with Sylvan support.");
755 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
756 "version of Storm with Sylvan support.");
761 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
762 "version of Storm with Sylvan support.");
767 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
768 "version of Storm with Sylvan support.");
774 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
775 "version of Storm with Sylvan support.");
780 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
781 "version of Storm with Sylvan support.");
786 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
787 "version of Storm with Sylvan support.");
792 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
793 "version of Storm with Sylvan support.");
798 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
799 "version of Storm with Sylvan support.");
804 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
805 "version of Storm with Sylvan support.");
810 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
811 "version of Storm with Sylvan support.");
816 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
817 "version of Storm with Sylvan support.");
822 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
823 "version of Storm with Sylvan support.");
828 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
829 "version of Storm with Sylvan support.");
834 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
835 "version of Storm with Sylvan support.");
838template<
typename ValueType>
841 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
842 "version of Storm with Sylvan support.");
847 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
848 "version of Storm with Sylvan support.");
853 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
854 "version of Storm with Sylvan support.");
857template<
typename ValueType>
859 std::vector<ValueType>
const& sourceValues, std::vector<ValueType>& targetValues)
const {
861 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
862 "version of Storm with Sylvan support.");
868 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
869 "version of Storm with Sylvan support.");
874 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
875 "version of Storm with Sylvan support.");
878std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>>
881 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
882 "version of Storm with Sylvan support.");
892 std::vector<double>
const& sourceValues, std::vector<double>& targetValues)
const;
894 std::vector<uint_fast64_t>
const& sourceValues, std::vector<uint_fast64_t>& targetValues)
const;
896 std::vector<storm::RationalNumber>
const& sourceValues,
897 std::vector<storm::RationalNumber>& targetValues)
const;
899 std::vector<storm::RationalFunction>
const& sourceValues,
900 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...