3#include <boost/functional/hash.hpp>
21 std::vector<uint_fast64_t>
const& sortedDdVariableIndices,
22 std::function<
bool(uint64_t)>
const& filter) {
23 uint_fast64_t offset = 0;
25 ddManager, cudd::BDD(ddManager->getCuddManager(), fromVectorRec(ddManager->getCuddManager().getManager(), offset, 0, sortedDdVariableIndices.size(),
26 odd, sortedDdVariableIndices, filter)));
30 return this->getCuddBdd() == other.getCuddBdd();
34 return !(*
this == other);
41 for (
auto const& variable : rowVariables) {
46 result = result.swapVariables(rowVariables, columnVariables);
54 for (
auto const& variable : columnVariables) {
65 return this->inverseRelationalProduct(relation, rowVariables, columnVariables);
72template<
typename ValueType>
85 this->cuddBdd = this->getCuddBdd() | other.getCuddBdd();
96 this->cuddBdd = this->getCuddBdd() & other.getCuddBdd();
109 return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().Ite(other.getCuddBdd(), ddManager->getBddOne().getCuddBdd()));
119 this->cuddBdd = ~this->getCuddBdd();
149 std::vector<cudd::BDD> fromBdd;
150 std::vector<cudd::BDD> toBdd;
151 for (
auto it1 = from.begin(), ite1 = from.end(), it2 = to.begin(); it1 != ite1; ++it1, ++it2) {
152 fromBdd.push_back(it1->getCuddBdd());
153 toBdd.push_back(it2->getCuddBdd());
165 if (numberOfDdVariables == 0) {
168 return static_cast<uint_fast64_t
>(this->getCuddBdd().CountMinterm(
static_cast<int>(numberOfDdVariables)));
172 return static_cast<uint_fast64_t
>(this->getCuddBdd().CountLeaves());
176 return static_cast<uint_fast64_t
>(this->getCuddBdd().nodeCount());
180 return this->getCuddBdd().IsOne();
184 return this->getCuddBdd().IsZero();
188 return static_cast<uint_fast64_t
>(this->getCuddBdd().NodeReadIndex());
192 return static_cast<uint_fast64_t
>(ddManager->getCuddManager().ReadPerm(this->getIndex()));
196 bool showVariablesIfPossible)
const {
198 std::vector<char*> ddNames;
199 std::string ddName(
"f");
200 ddNames.push_back(
new char[ddName.size() + 1]);
201 std::copy(ddName.c_str(), ddName.c_str() + 2, ddNames.back());
204 std::vector<char*> ddVariableNames;
205 for (
auto const& element : ddVariableNamesAsStrings) {
206 ddVariableNames.push_back(
new char[element.size() + 1]);
207 std::copy(element.c_str(), element.c_str() + element.size() + 1, ddVariableNames.back());
211 std::vector<cudd::BDD> cuddBddVector = {this->getCuddBdd()};
212 FILE* filePointer = fopen(filename.c_str(),
"a+");
213 if (showVariablesIfPossible) {
214 ddManager->getCuddManager().DumpDot(cuddBddVector, ddVariableNames.data(), &ddNames[0], filePointer);
216 ddManager->getCuddManager().DumpDot(cuddBddVector,
nullptr, &ddNames[0], filePointer);
221 for (
char* element : ddNames) {
224 for (
char* element : ddVariableNames) {
230 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"Operation not supported");
234 return this->cuddBdd;
238 return this->getCuddBdd().getNode();
241template<
typename ValueType>
247 Odd const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
248 std::function<
bool(uint64_t)>
const& filter) {
249 if (currentLevel == maxLevel) {
254 if (filter(currentOffset++)) {
255 return Cudd_ReadOne(manager);
257 return Cudd_ReadLogicZero(manager);
260 return Cudd_ReadZero(manager);
265 return Cudd_ReadZero(manager);
269 DdNode* elseSuccessor =
nullptr;
271 elseSuccessor = fromVectorRec(manager, currentOffset, currentLevel + 1, maxLevel, odd.
getElseSuccessor(), ddVariableIndices, filter);
273 elseSuccessor = Cudd_ReadLogicZero(manager);
275 Cudd_Ref(elseSuccessor);
278 DdNode* thenSuccessor =
nullptr;
280 thenSuccessor = fromVectorRec(manager, currentOffset, currentLevel + 1, maxLevel, odd.
getThenSuccessor(), ddVariableIndices, filter);
282 thenSuccessor = Cudd_ReadLogicZero(manager);
284 Cudd_Ref(thenSuccessor);
287 DdNode* currentVar = Cudd_bddIthVar(manager,
static_cast<int>(ddVariableIndices[currentLevel]));
288 Cudd_Ref(currentVar);
289 DdNode* result = Cudd_bddIte(manager, currentVar, thenSuccessor, elseSuccessor);
293 Cudd_RecursiveDeref(manager, currentVar);
294 Cudd_RecursiveDeref(manager, thenSuccessor);
295 Cudd_RecursiveDeref(manager, elseSuccessor);
306 this->toVectorRec(Cudd_Regular(this->getCuddDdNode()), ddManager->getCuddManager(), result, rowOdd, Cudd_IsComplement(this->getCuddDdNode()), 0,
307 ddVariableIndices.size(), 0, ddVariableIndices);
312 uint_fast64_t currentRowLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset,
313 std::vector<uint_fast64_t>
const& ddRowVariableIndices)
const {
315 if (dd == Cudd_ReadLogicZero(manager.getManager()) && !complement) {
317 }
else if (dd == Cudd_ReadOne(manager.getManager()) && complement) {
322 if (currentRowLevel == maxLevel) {
323 result.
set(currentRowOffset,
true);
324 }
else if (ddRowVariableIndices[currentRowLevel] < Cudd_NodeReadIndex(dd)) {
325 toVectorRec(dd, manager, result, rowOdd.
getElseSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset, ddRowVariableIndices);
326 toVectorRec(dd, manager, result, rowOdd.
getThenSuccessor(), complement, currentRowLevel + 1, maxLevel, currentRowOffset + rowOdd.
getElseOffset(),
327 ddRowVariableIndices);
330 DdNode
const* elseDdNode = Cudd_E_const(dd);
331 DdNode
const* thenDdNode = Cudd_T_const(dd);
334 bool elseComplemented = Cudd_IsComplement(elseDdNode) ^ complement;
335 bool thenComplemented = Cudd_IsComplement(thenDdNode) ^ complement;
337 toVectorRec(Cudd_Regular(elseDdNode), manager, result, rowOdd.
getElseSuccessor(), elseComplemented, currentRowLevel + 1, maxLevel, currentRowOffset,
338 ddRowVariableIndices);
339 toVectorRec(Cudd_Regular(thenDdNode), manager, result, rowOdd.
getThenSuccessor(), thenComplemented, currentRowLevel + 1, maxLevel,
340 currentRowOffset + rowOdd.
getElseOffset(), ddRowVariableIndices);
346 std::vector<std::unordered_map<DdNode const*, std::shared_ptr<Odd>>> uniqueTableForLevels(ddVariableIndices.size() + 1);
349 std::shared_ptr<Odd> rootOdd =
350 createOddRec(this->getCuddDdNode(), ddManager->getCuddManager(), 0, ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels);
353 return Odd(*rootOdd);
357 std::size_t result = 0;
358 boost::hash_combine(result, key.first);
359 boost::hash_combine(result, key.second);
363std::shared_ptr<Odd> InternalBdd<DdType::CUDD>::createOddRec(DdNode
const* dd, cudd::Cudd
const& manager, uint_fast64_t currentLevel, uint_fast64_t maxLevel,
364 std::vector<uint_fast64_t>
const& ddVariableIndices,
365 std::vector<std::unordered_map<DdNode
const*, std::shared_ptr<Odd>>>& uniqueTableForLevels) {
367 auto it = uniqueTableForLevels[currentLevel].find(dd);
368 if (it != uniqueTableForLevels[currentLevel].end()) {
375 if (currentLevel == maxLevel) {
376 auto oddNode = std::make_shared<Odd>(
nullptr, 0,
nullptr, dd != Cudd_ReadLogicZero(manager.getManager()) ? 1 : 0);
377 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
379 }
else if (ddVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
382 std::shared_ptr<Odd> elseNode = createOddRec(dd, manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
383 std::shared_ptr<Odd> thenNode = elseNode;
385 auto oddNode = std::make_shared<Odd>(elseNode, elseNode->getTotalOffset(), thenNode, elseNode->getTotalOffset());
386 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
390 DdNode
const* thenDdNode = Cudd_T_const(dd);
391 DdNode
const* elseDdNode = Cudd_E_const(dd);
393 if (Cudd_IsComplement(dd)) {
394 thenDdNode = Cudd_Not(thenDdNode);
395 elseDdNode = Cudd_Not(elseDdNode);
398 std::shared_ptr<Odd> elseNode = createOddRec(elseDdNode, manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
399 std::shared_ptr<Odd> thenNode = createOddRec(thenDdNode, manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
401 auto oddNode = std::make_shared<Odd>(elseNode, elseNode->getTotalOffset(), thenNode, thenNode->getTotalOffset());
402 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
408template<
typename ValueType>
410 std::vector<ValueType>
const& sourceValues, std::vector<ValueType>& targetValues)
const {
411 uint_fast64_t currentIndex = 0;
412 filterExplicitVectorRec(Cudd_Regular(this->getCuddDdNode()), ddManager->getCuddManager(), 0, Cudd_IsComplement(this->getCuddDdNode()),
413 ddVariableIndices.size(), ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
416template<
typename ValueType>
418 uint_fast64_t maxLevel, std::vector<uint_fast64_t>
const& ddVariableIndices,
419 uint_fast64_t currentOffset,
storm::dd::Odd const& odd, std::vector<ValueType>& result,
420 uint_fast64_t& currentIndex, std::vector<ValueType>
const& values) {
422 if (dd == Cudd_ReadLogicZero(manager.getManager()) && !complement) {
424 }
else if (dd == Cudd_ReadOne(manager.getManager()) && complement) {
428 if (currentLevel == maxLevel) {
429 result[currentIndex++] = values[currentOffset];
430 }
else if (ddVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
433 filterExplicitVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(), result,
434 currentIndex, values);
435 filterExplicitVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(),
439 DdNode
const* thenDdNode = Cudd_T_const(dd);
440 DdNode
const* elseDdNode = Cudd_E_const(dd);
443 bool elseComplemented = Cudd_IsComplement(elseDdNode) ^ complement;
444 bool thenComplemented = Cudd_IsComplement(thenDdNode) ^ complement;
446 filterExplicitVectorRec(Cudd_Regular(elseDdNode), manager, currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset,
448 filterExplicitVectorRec(Cudd_Regular(thenDdNode), manager, currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices,
454 std::vector<InternalBdd<DdType::CUDD>> result;
455 splitIntoGroupsRec(Cudd_Regular(this->getCuddDdNode()), Cudd_IsComplement(this->getCuddDdNode()), result, ddGroupVariableIndices, 0,
456 ddGroupVariableIndices.size());
461 std::vector<uint_fast64_t>
const& ddGroupVariableIndices, uint_fast64_t currentLevel,
462 uint_fast64_t maxLevel)
const {
464 if (negated && dd == Cudd_ReadOne(ddManager->getCuddManager().getManager())) {
468 if (currentLevel == maxLevel) {
469 groups.push_back(InternalBdd<DdType::CUDD>(ddManager, cudd::BDD(ddManager->getCuddManager(), negated ? Cudd_Complement(dd) : dd)));
470 }
else if (ddGroupVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
471 splitIntoGroupsRec(dd, negated, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
472 splitIntoGroupsRec(dd, negated, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
474 DdNode* elseNode = Cudd_E(dd);
475 DdNode* thenNode = Cudd_T(dd);
477 splitIntoGroupsRec(elseNode, negated ^ Cudd_IsComplement(elseNode), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
478 splitIntoGroupsRec(thenNode, negated ^ Cudd_IsComplement(thenNode), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
484 uint_fast64_t currentIndex = 0;
485 filterExplicitVectorRec(Cudd_Regular(this->getCuddDdNode()), ddManager->getCuddManager(), 0, Cudd_IsComplement(this->getCuddDdNode()),
486 ddVariableIndices.size(), ddVariableIndices, 0, odd, targetValues, currentIndex, sourceValues);
490 uint_fast64_t maxLevel, std::vector<uint_fast64_t>
const& ddVariableIndices,
494 if (dd == Cudd_ReadLogicZero(manager.getManager()) && !complement) {
496 }
else if (dd == Cudd_ReadOne(manager.getManager()) && complement) {
500 if (currentLevel == maxLevel) {
501 result.
set(currentIndex++, values.
get(currentOffset));
502 }
else if (ddVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
505 filterExplicitVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.
getElseSuccessor(), result,
506 currentIndex, values);
507 filterExplicitVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.
getElseOffset(),
511 DdNode
const* thenDdNode = Cudd_T_const(dd);
512 DdNode
const* elseDdNode = Cudd_E_const(dd);
515 bool elseComplemented = Cudd_IsComplement(elseDdNode) ^ complement;
516 bool thenComplemented = Cudd_IsComplement(thenDdNode) ^ complement;
518 filterExplicitVectorRec(Cudd_Regular(elseDdNode), manager, currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset,
520 filterExplicitVectorRec(Cudd_Regular(thenDdNode), manager, currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices,
527 std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<uint_fast64_t, storm::expressions::Variable>> result;
531 std::unordered_map<DdNode const*, uint_fast64_t> nodeToCounterMap;
532 std::vector<uint_fast64_t> nextCounterForIndex(ddManager->getNumberOfDdVariables(), 0);
535 bool negated = Cudd_Regular(this->getCuddDdNode()) != this->getCuddDdNode();
538 storm::expressions::Variable topVariable = this->toExpressionRec(Cudd_Regular(this->getCuddDdNode()), ddManager->getCuddManager(), manager, result.first,
539 result.second, 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<DdNode const*, 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, Cudd_NodeReadIndex(dd)));
563 STORM_LOG_ASSERT(variableIt != countIndexToVariablePair.end(),
"Unable to find node.");
564 return variableIt->second;
571 if (!Cudd_IsConstant_const(dd)) {
573 nodeToCounterMap[dd] = nextCounterForIndex[Cudd_NodeReadIndex(dd)];
574 countIndexToVariablePair[std::make_pair(nextCounterForIndex[Cudd_NodeReadIndex(dd)], Cudd_NodeReadIndex(dd))] = newNodeVariable;
575 ++nextCounterForIndex[Cudd_NodeReadIndex(dd)];
578 nodeToCounterMap[dd] = 0;
579 countIndexToVariablePair[std::make_pair(0, Cudd_NodeReadIndex(dd))] = newNodeVariable;
583 if (dd == Cudd_ReadOne(ddManager.getManager())) {
588 DdNode
const* t = Cudd_T_const(dd);
589 DdNode
const* e = Cudd_E_const(dd);
590 DdNode
const* T = Cudd_Regular(t);
591 DdNode
const* E = Cudd_Regular(e);
593 toExpressionRec(T, ddManager, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
595 toExpressionRec(E, ddManager, manager, expressions, indexToVariableMap, countIndexToVariablePair, nodeToCounterMap, nextCounterForIndex);
598 auto indexVariable = indexToVariableMap.find(Cudd_NodeReadIndex(dd));
600 if (indexVariable == indexToVariableMap.end()) {
601 levelVariable =
manager.declareFreshBooleanVariable();
602 indexToVariableMap[Cudd_NodeReadIndex(dd)] = levelVariable;
604 levelVariable = indexVariable->second;
607 newNodeVariable,
storm::expressions::ite(levelVariable, t == T ? thenVariable : !thenVariable, e == E ? elseVariable : !elseVariable)));
611 return newNodeVariable;
614template InternalAdd<DdType::CUDD, double> InternalBdd<DdType::CUDD>::toAdd()
const;
615template InternalAdd<DdType::CUDD, uint_fast64_t> InternalBdd<DdType::CUDD>::toAdd()
const;
616#ifdef STORM_HAVE_CARL
617template InternalAdd<DdType::CUDD, storm::RationalNumber> InternalBdd<DdType::CUDD>::toAdd()
const;
620template void InternalBdd<DdType::CUDD>::filterExplicitVectorRec<double>(DdNode
const* dd, cudd::Cudd
const& manager, uint_fast64_t currentLevel,
621 bool complement, uint_fast64_t maxLevel,
622 std::vector<uint_fast64_t>
const& ddVariableIndices, uint_fast64_t currentOffset,
623 storm::dd::Odd const& odd, std::vector<double>& result, uint_fast64_t& currentIndex,
624 std::vector<double>
const& values);
625template void InternalBdd<DdType::CUDD>::filterExplicitVectorRec<uint_fast64_t>(DdNode
const* dd, cudd::Cudd
const& manager, uint_fast64_t currentLevel,
626 bool complement, uint_fast64_t maxLevel,
627 std::vector<uint_fast64_t>
const& ddVariableIndices,
629 std::vector<uint_fast64_t>& result, uint_fast64_t& currentIndex,
630 std::vector<uint_fast64_t>
const& values);
632template void InternalBdd<DdType::CUDD>::filterExplicitVector(Odd
const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
633 std::vector<double>
const& sourceValues, std::vector<double>& targetValues)
const;
634template void InternalBdd<DdType::CUDD>::filterExplicitVector(Odd
const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
635 std::vector<uint_fast64_t>
const& sourceValues, std::vector<uint_fast64_t>& targetValues)
const;
637template InternalAdd<DdType::CUDD, double> InternalBdd<DdType::CUDD>::ite(InternalAdd<DdType::CUDD, double>
const& thenAdd,
638 InternalAdd<DdType::CUDD, double>
const& elseAdd)
const;
639template InternalAdd<DdType::CUDD, uint_fast64_t> InternalBdd<DdType::CUDD>::ite(InternalAdd<DdType::CUDD, uint_fast64_t>
const& thenAdd,
640 InternalAdd<DdType::CUDD, uint_fast64_t>
const& elseAdd)
const;
641template InternalAdd<DdType::CUDD, storm::RationalNumber> InternalBdd<DdType::CUDD>::ite(InternalAdd<DdType::CUDD, storm::RationalNumber>
const& thenAdd,
642 InternalAdd<DdType::CUDD, storm::RationalNumber>
const& elseAdd)
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.
uint_fast64_t getThenOffset() const
Retrieves the then-offset 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(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
#define STORM_LOG_ASSERT(cond, message)
#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.