3#include <boost/functional/hash.hpp>
17#ifdef STORM_HAVE_SYLVAN
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#pragma clang diagnostic push
78#pragma clang diagnostic ignored "-Wused-but-marked-unused"
79 BDD result = sylvan_ite(currentVar, thenSuccessor, elseSuccessor);
80#pragma clang diagnostic pop
89bool InternalBdd<DdType::Sylvan>::operator==(InternalBdd<DdType::Sylvan>
const& other)
const {
90 return sylvanBdd == other.sylvanBdd;
93bool InternalBdd<DdType::Sylvan>::operator!=(InternalBdd<DdType::Sylvan>
const& other)
const {
94 return sylvanBdd != other.sylvanBdd;
97InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::relationalProduct(InternalBdd<DdType::Sylvan>
const& relation,
98 std::vector<InternalBdd<DdType::Sylvan>>
const&,
99 std::vector<InternalBdd<DdType::Sylvan>>
const&)
const {
100 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.RelNext(relation.sylvanBdd, sylvan::Bdd(sylvan_false)));
103InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::inverseRelationalProduct(InternalBdd<DdType::Sylvan>
const& relation,
104 std::vector<InternalBdd<DdType::Sylvan>>
const&,
105 std::vector<InternalBdd<DdType::Sylvan>>
const&)
const {
106 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.RelPrev(relation.sylvanBdd, sylvan::Bdd(sylvan_false)));
109InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::inverseRelationalProductWithExtendedRelation(
110 InternalBdd<DdType::Sylvan>
const& relation, std::vector<InternalBdd<DdType::Sylvan>>
const& rowVariables,
111 std::vector<InternalBdd<DdType::Sylvan>>
const& columnVariables)
const {
114 InternalBdd<DdType::Sylvan> columnCube = ddManager->getBddOne();
115 for (
auto const& variable : columnVariables) {
116 columnCube &= variable;
119 return this->swapVariables(rowVariables, columnVariables).andExists(relation, columnCube);
122InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::ite(InternalBdd<DdType::Sylvan>
const& thenDd, InternalBdd<DdType::Sylvan>
const& elseDd)
const {
123 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Ite(thenDd.sylvanBdd, elseDd.sylvanBdd));
126template<
typename ValueType>
127InternalAdd<DdType::Sylvan, ValueType> InternalBdd<DdType::Sylvan>::ite(InternalAdd<DdType::Sylvan, ValueType>
const& thenAdd,
128 InternalAdd<DdType::Sylvan, ValueType>
const& elseAdd)
const {
129 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.Ite(thenAdd.getSylvanMtbdd(), elseAdd.getSylvanMtbdd()));
132InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator||(InternalBdd<DdType::Sylvan>
const& other)
const {
133 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd | other.sylvanBdd);
136InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::operator|=(InternalBdd<DdType::Sylvan>
const& other) {
137 this->sylvanBdd |= other.sylvanBdd;
141InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator&&(InternalBdd<DdType::Sylvan>
const& other)
const {
142 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd & other.sylvanBdd);
145InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::operator&=(InternalBdd<DdType::Sylvan>
const& other) {
146 this->sylvanBdd &= other.sylvanBdd;
150InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::iff(InternalBdd<DdType::Sylvan>
const& other)
const {
151 return InternalBdd<DdType::Sylvan>(ddManager, !(this->sylvanBdd ^ other.sylvanBdd));
154InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::exclusiveOr(InternalBdd<DdType::Sylvan>
const& other)
const {
155 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd ^ other.sylvanBdd);
158InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::implies(InternalBdd<DdType::Sylvan>
const& other)
const {
159 return InternalBdd<DdType::Sylvan>(ddManager, (!this->sylvanBdd) | other.sylvanBdd);
162InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::operator!()
const {
163 return InternalBdd<DdType::Sylvan>(ddManager, !this->sylvanBdd);
166InternalBdd<DdType::Sylvan>& InternalBdd<DdType::Sylvan>::complement() {
167 this->sylvanBdd = !this->sylvanBdd;
171InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::existsAbstract(InternalBdd<DdType::Sylvan>
const& cube)
const {
172 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.ExistAbstract(cube.sylvanBdd));
175InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::existsAbstractRepresentative(InternalBdd<DdType::Sylvan>
const& cube)
const {
176 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.ExistAbstractRepresentative(cube.sylvanBdd));
179InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::universalAbstract(InternalBdd<DdType::Sylvan>
const& cube)
const {
180 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.UnivAbstract(cube.sylvanBdd));
183InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::andExists(InternalBdd<DdType::Sylvan>
const& other, InternalBdd<DdType::Sylvan>
const& cube)
const {
184 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.AndAbstract(other.sylvanBdd, cube.sylvanBdd));
187InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::constrain(InternalBdd<DdType::Sylvan>
const& constraint)
const {
188 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Constrain(constraint.sylvanBdd));
191InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::restrict(InternalBdd<DdType::Sylvan>
const& constraint)
const {
192 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Restrict(constraint.sylvanBdd));
195InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::swapVariables(std::vector<InternalBdd<DdType::Sylvan>>
const& from,
196 std::vector<InternalBdd<DdType::Sylvan>>
const& to)
const {
197 std::vector<uint32_t> fromIndices;
198 std::vector<uint32_t> toIndices;
199 for (
auto it1 = from.begin(), ite1 = from.end(), it2 = to.begin(); it1 != ite1; ++it1, ++it2) {
200 fromIndices.push_back(it1->getIndex());
201 fromIndices.push_back(it2->getIndex());
202 toIndices.push_back(it2->getIndex());
203 toIndices.push_back(it1->getIndex());
205 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Permute(fromIndices, toIndices));
208InternalBdd<DdType::Sylvan> InternalBdd<DdType::Sylvan>::getSupport()
const {
209 return InternalBdd<DdType::Sylvan>(ddManager, this->sylvanBdd.Support());
212uint_fast64_t InternalBdd<DdType::Sylvan>::getNonZeroCount(uint_fast64_t numberOfDdVariables)
const {
213 if (numberOfDdVariables == 0) {
216 return static_cast<uint_fast64_t
>(this->sylvanBdd.SatCount(numberOfDdVariables));
219uint_fast64_t InternalBdd<DdType::Sylvan>::getLeafCount()
const {
225uint_fast64_t InternalBdd<DdType::Sylvan>::getNodeCount()
const {
227 return static_cast<uint_fast64_t
>(this->sylvanBdd.NodeCount());
230bool InternalBdd<DdType::Sylvan>::isOne()
const {
231 return this->sylvanBdd.isOne();
234bool InternalBdd<DdType::Sylvan>::isZero()
const {
235 return this->sylvanBdd.isZero();
238uint_fast64_t InternalBdd<DdType::Sylvan>::getIndex()
const {
239 return static_cast<uint_fast64_t
>(this->sylvanBdd.TopVar());
242uint_fast64_t InternalBdd<DdType::Sylvan>::getLevel()
const {
243 return this->getIndex();
246void InternalBdd<DdType::Sylvan>::exportToDot(std::string
const& filename, std::vector<std::string>
const&,
bool)
const {
247 FILE* filePointer = fopen(filename.c_str(),
"a+");
249 if (filePointer ==
nullptr) {
252 this->sylvanBdd.PrintDot(filePointer);
257void InternalBdd<DdType::Sylvan>::exportToText(std::string
const& filename)
const {
258 FILE* filePointer = fopen(filename.c_str(),
"a+");
260 if (filePointer ==
nullptr) {
263 this->sylvanBdd.PrintText(filePointer);
268sylvan::Bdd& InternalBdd<DdType::Sylvan>::getSylvanBdd() {
272sylvan::Bdd
const& InternalBdd<DdType::Sylvan>::getSylvanBdd()
const {
276template<
typename ValueType>
277InternalAdd<DdType::Sylvan, ValueType> InternalBdd<DdType::Sylvan>::toAdd()
const {
278 if (std::is_same<ValueType, double>::value) {
279 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toDoubleMtbdd());
280 }
else if (std::is_same<ValueType, uint_fast64_t>::value) {
281 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toInt64Mtbdd());
282 }
else if (std::is_same<ValueType, storm::RationalNumber>::value) {
283 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toStormRationalNumberMtbdd());
284 }
else if (std::is_same<ValueType, storm::RationalFunction>::value) {
285 return InternalAdd<DdType::Sylvan, ValueType>(ddManager, this->sylvanBdd.toStormRationalFunctionMtbdd());
287 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Illegal ADD type.");
293 this->toVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), result, rowOdd, bdd_isnegated(this->getSylvanBdd().GetBDD()), 0, ddVariableIndices.size(), 0,
298void InternalBdd<DdType::Sylvan>::toVectorRec(BDD dd,
storm::storage::BitVector& result, Odd
const& rowOdd,
bool complement, uint_fast64_t currentRowLevel,
299 uint_fast64_t maxLevel, uint_fast64_t currentRowOffset,
300 std::vector<uint_fast64_t>
const& ddRowVariableIndices)
const {
302 if (dd == sylvan_false && !complement) {
304 }
else if (dd == sylvan_true && complement) {
309 if (currentRowLevel == maxLevel) {
310 result.
set(currentRowOffset,
true);
311 }
else if (bdd_isterminal(dd) || ddRowVariableIndices[currentRowLevel] < sylvan_var(dd)) {
312 toVectorRec(dd, result, rowOdd.getElseSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset, ddRowVariableIndices);
313 toVectorRec(dd, result, rowOdd.getThenSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset + rowOdd.getElseOffset(),
314 ddRowVariableIndices);
317 BDD elseDdNode = sylvan_low(dd);
318 BDD thenDdNode = sylvan_high(dd);
321 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
322 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
324 toVectorRec(bdd_regular(elseDdNode), result, rowOdd.getElseSuccessor(), elseComplemented, currentRowLevel + 1, maxLevel, currentRowOffset,
325 ddRowVariableIndices);
326 toVectorRec(bdd_regular(thenDdNode), result, rowOdd.getThenSuccessor(), thenComplemented, currentRowLevel + 1, maxLevel,
327 currentRowOffset + rowOdd.getElseOffset(), ddRowVariableIndices);
331Odd InternalBdd<DdType::Sylvan>::createOdd(std::vector<uint_fast64_t>
const& ddVariableIndices)
const {
333 std::vector<std::unordered_map<std::pair<BDD, bool>, std::shared_ptr<Odd>, HashFunctor>> uniqueTableForLevels(ddVariableIndices.size() + 1);
336 std::shared_ptr<Odd> rootOdd = createOddRec(bdd_regular(this->getSylvanBdd().GetBDD()), bdd_isnegated(this->getSylvanBdd().GetBDD()), 0,
337 ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels);
340 return Odd(*rootOdd);
343std::size_t InternalBdd<DdType::Sylvan>::HashFunctor::operator()(std::pair<BDD, bool>
const& key)
const {
344 std::size_t result = 0;
345 boost::hash_combine(result, key.first);
346 boost::hash_combine(result, key.second);
350std::shared_ptr<Odd> InternalBdd<DdType::Sylvan>::createOddRec(
351 BDD dd,
bool complement, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t>
const& ddVariableIndices,
352 std::vector<std::unordered_map<std::pair<BDD, bool>, std::shared_ptr<Odd>, HashFunctor>>& uniqueTableForLevels) {
354 auto const& iterator = uniqueTableForLevels[currentLevel].find(std::make_pair(dd, complement));
355 if (iterator != uniqueTableForLevels[currentLevel].end()) {
356 return iterator->second;
362 if (currentLevel == maxLevel) {
363 uint_fast64_t elseOffset = 0;
364 uint_fast64_t thenOffset = 0;
367 if (dd != mtbdd_false) {
373 thenOffset = 1 - thenOffset;
376 auto oddNode = std::make_shared<Odd>(
nullptr, elseOffset,
nullptr, thenOffset);
377 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
379 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
382 std::shared_ptr<Odd> elseNode = createOddRec(dd, complement, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
383 std::shared_ptr<Odd> thenNode = elseNode;
384 uint_fast64_t totalOffset = elseNode->getElseOffset() + elseNode->getThenOffset();
385 auto oddNode = std::make_shared<Odd>(elseNode, totalOffset, thenNode, totalOffset);
386 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
390 BDD thenDdNode = sylvan_high(dd);
391 BDD elseDdNode = sylvan_low(dd);
394 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
395 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
397 std::shared_ptr<Odd> elseNode =
398 createOddRec(bdd_regular(elseDdNode), elseComplemented, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
399 std::shared_ptr<Odd> thenNode =
400 createOddRec(bdd_regular(thenDdNode), thenComplemented, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
402 auto oddNode = std::make_shared<Odd>(elseNode, elseNode->getElseOffset() + elseNode->getThenOffset(), thenNode,
403 thenNode->getElseOffset() + thenNode->getThenOffset());
404 uniqueTableForLevels[currentLevel].emplace(std::make_pair(dd, complement), oddNode);
410template<
typename ValueType>
411void InternalBdd<DdType::Sylvan>::filterExplicitVector(Odd
const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
412 std::vector<ValueType>
const& sourceValues, std::vector<ValueType>& targetValues)
const {
413 uint_fast64_t currentIndex = 0;
414 filterExplicitVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), 0, bdd_isnegated(this->getSylvanBdd().GetBDD()), ddVariableIndices.size(),
415 ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
418template<
typename ValueType>
419void InternalBdd<DdType::Sylvan>::filterExplicitVectorRec(BDD dd, uint_fast64_t currentLevel,
bool complement, uint_fast64_t maxLevel,
420 std::vector<uint_fast64_t>
const& ddVariableIndices, uint_fast64_t currentOffset,
421 storm::dd::Odd const& odd, std::vector<ValueType>& result, uint_fast64_t& currentIndex,
422 std::vector<ValueType>
const& values) {
424 if (dd == sylvan_false && !complement) {
426 }
else if (dd == sylvan_true && complement) {
430 if (currentLevel == maxLevel) {
431 result[currentIndex++] = values[currentOffset];
432 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
435 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(), result, currentIndex,
437 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(), odd.
getThenSuccessor(),
438 result, currentIndex, values);
441 BDD thenDdNode = sylvan_high(dd);
442 BDD elseDdNode = sylvan_low(dd);
445 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
446 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
448 filterExplicitVectorRec(bdd_regular(elseDdNode), currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(),
449 result, currentIndex, values);
450 filterExplicitVectorRec(bdd_regular(thenDdNode), currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(),
455void InternalBdd<DdType::Sylvan>::filterExplicitVector(Odd
const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
457 uint_fast64_t currentIndex = 0;
458 filterExplicitVectorRec(bdd_regular(this->getSylvanBdd().GetBDD()), 0, bdd_isnegated(this->getSylvanBdd().GetBDD()), ddVariableIndices.size(),
459 ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
462void InternalBdd<DdType::Sylvan>::filterExplicitVectorRec(BDD dd, uint_fast64_t currentLevel,
bool complement, uint_fast64_t maxLevel,
463 std::vector<uint_fast64_t>
const& ddVariableIndices, uint_fast64_t currentOffset,
467 if (dd == sylvan_false && !complement) {
469 }
else if (dd == sylvan_true && complement) {
473 if (currentLevel == maxLevel) {
474 result.
set(currentIndex++, values.
get(currentOffset));
475 }
else if (bdd_isterminal(dd) || ddVariableIndices[currentLevel] < sylvan_var(dd)) {
478 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(), result, currentIndex,
480 filterExplicitVectorRec(dd, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(), odd.
getThenSuccessor(),
481 result, currentIndex, values);
484 BDD thenDdNode = sylvan_high(dd);
485 BDD elseDdNode = sylvan_low(dd);
488 bool elseComplemented = bdd_isnegated(elseDdNode) ^ complement;
489 bool thenComplemented = bdd_isnegated(thenDdNode) ^ complement;
491 filterExplicitVectorRec(bdd_regular(elseDdNode), currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(),
492 result, currentIndex, values);
493 filterExplicitVectorRec(bdd_regular(thenDdNode), currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(),
498std::vector<InternalBdd<DdType::Sylvan>> InternalBdd<DdType::Sylvan>::splitIntoGroups(std::vector<uint_fast64_t>
const& ddGroupVariableIndices)
const {
499 std::vector<InternalBdd<DdType::Sylvan>> result;
500 splitIntoGroupsRec(this->getSylvanBdd().GetBDD(), result, ddGroupVariableIndices, 0, ddGroupVariableIndices.size());
504void InternalBdd<DdType::Sylvan>::splitIntoGroupsRec(BDD dd, std::vector<InternalBdd<DdType::Sylvan>>& groups,
505 std::vector<uint_fast64_t>
const& ddGroupVariableIndices, uint_fast64_t currentLevel,
506 uint_fast64_t maxLevel)
const {
508 if (dd == sylvan_false) {
512 if (currentLevel == maxLevel) {
513 groups.push_back(InternalBdd<DdType::Sylvan>(ddManager, sylvan::Bdd(dd)));
514 }
else if (bdd_isterminal(dd) || ddGroupVariableIndices[currentLevel] < sylvan_var(dd)) {
515 splitIntoGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
516 splitIntoGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
519 BDD thenDdNode = sylvan_high(dd);
520 BDD elseDdNode = sylvan_low(dd);
522 splitIntoGroupsRec(elseDdNode, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
523 splitIntoGroupsRec(thenDdNode, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
527std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>>
529 std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> result;
533 std::unordered_map<BDD, uint_fast64_t> nodeToCounterMap;
534 std::vector<uint_fast64_t> nextCounterForIndex(ddManager->getNumberOfDdVariables(), 0);
537 bool negated = bdd_isnegated(this->getSylvanBdd().GetBDD());
541 bdd_regular(this->getSylvanBdd().GetBDD()), manager, result.first, result.second, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
545 result.first.push_back(!topVariable);
547 result.first.push_back(topVariable);
555 std::unordered_map<uint_fast64_t, storm::expressions::Variable>& indexToVariableMap,
557 std::unordered_map<BDD, uint_fast64_t>& nodeToCounterMap, std::vector<uint_fast64_t>& nextCounterForIndex) {
561 auto nodeCounterIt = nodeToCounterMap.find(dd);
562 if (nodeCounterIt != nodeToCounterMap.end()) {
564 auto variableIt = countIndexToVariablePair.find(std::make_pair(nodeCounterIt->second, sylvan_var(dd)));
565 STORM_LOG_ASSERT(variableIt != countIndexToVariablePair.end(),
"Unable to find node.");
566 return variableIt->second;
573 if (!bdd_isterminal(dd)) {
575 nodeToCounterMap[dd] = nextCounterForIndex[sylvan_var(dd)];
576 countIndexToVariablePair[std::make_pair(nextCounterForIndex[sylvan_var(dd)], sylvan_var(dd))] = newNodeVariable;
577 ++nextCounterForIndex[sylvan_var(dd)];
580 nodeToCounterMap[dd] = 0;
581 countIndexToVariablePair[std::make_pair(0, sylvan_var(dd))] = newNodeVariable;
585 if (bdd_isterminal(dd)) {
586 if (dd == sylvan_true) {
593 BDD t = sylvan_high(dd);
594 BDD e = sylvan_low(dd);
595 BDD T = bdd_regular(t);
596 BDD E = bdd_regular(e);
598 toExpressionRec(T, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
600 toExpressionRec(E, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
604 auto indexVariable = indexToVariableMap.find(sylvan_var(dd));
606 if (indexVariable == indexToVariableMap.end()) {
607 levelVariable =
manager.declareFreshBooleanVariable();
608 indexToVariableMap[sylvan_var(dd)] = levelVariable;
610 levelVariable = indexVariable->second;
613 newNodeVariable,
storm::expressions::ite(levelVariable, t == T ? thenVariable : !thenVariable, e == E ? elseVariable : !elseVariable)));
617 return newNodeVariable;
622 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
623 "version of Storm with Sylvan support.");
627 std::vector<uint_fast64_t>
const& sortedDdVariableIndices,
628 std::function<
bool(uint64_t)>
const& filter) {
630 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
631 "version of Storm with Sylvan support.");
636 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
637 "version of Storm with Sylvan support.");
642 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
643 "version of Storm with Sylvan support.");
650 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
651 "version of Storm with Sylvan support.");
658 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
659 "version of Storm with Sylvan support.");
666 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
667 "version of Storm with Sylvan support.");
672 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
673 "version of Storm with Sylvan support.");
676template<
typename ValueType>
680 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
681 "version of Storm with Sylvan support.");
686 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
687 "version of Storm with Sylvan support.");
692 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
693 "version of Storm with Sylvan support.");
698 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
699 "version of Storm with Sylvan support.");
704 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
705 "version of Storm with Sylvan support.");
710 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
711 "version of Storm with Sylvan support.");
716 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
717 "version of Storm with Sylvan support.");
722 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
723 "version of Storm with Sylvan support.");
728 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
729 "version of Storm with Sylvan support.");
734 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
735 "version of Storm with Sylvan support.");
740 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
741 "version of Storm with Sylvan support.");
746 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
747 "version of Storm with Sylvan support.");
752 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
753 "version of Storm with Sylvan support.");
758 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
759 "version of Storm with Sylvan support.");
764 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
765 "version of Storm with Sylvan support.");
770 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
771 "version of Storm with Sylvan support.");
777 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
778 "version of Storm with Sylvan support.");
783 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
784 "version of Storm with Sylvan support.");
789 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
790 "version of Storm with Sylvan support.");
795 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
796 "version of Storm with Sylvan support.");
801 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
802 "version of Storm with Sylvan support.");
807 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
808 "version of Storm with Sylvan support.");
813 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
814 "version of Storm with Sylvan support.");
819 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
820 "version of Storm with Sylvan support.");
825 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
826 "version of Storm with Sylvan support.");
831 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
832 "version of Storm with Sylvan support.");
837 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
838 "version of Storm with Sylvan support.");
841template<
typename ValueType>
844 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
845 "version of Storm with Sylvan support.");
850 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
851 "version of Storm with Sylvan support.");
856 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
857 "version of Storm with Sylvan support.");
860template<
typename ValueType>
862 std::vector<ValueType>
const& sourceValues, std::vector<ValueType>& targetValues)
const {
864 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
865 "version of Storm with Sylvan support.");
871 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
872 "version of Storm with Sylvan support.");
877 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
878 "version of Storm with Sylvan support.");
881std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>>
884 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
885 "version of Storm with Sylvan support.");
895 std::vector<double>
const& sourceValues, std::vector<double>& targetValues)
const;
897 std::vector<uint_fast64_t>
const& sourceValues, std::vector<uint_fast64_t>& targetValues)
const;
899 std::vector<storm::RationalNumber>
const& sourceValues,
900 std::vector<storm::RationalNumber>& targetValues)
const;
902 std::vector<storm::RationalFunction>
const& sourceValues,
903 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...