Browse Source
Added ODD-concept to easily convert between DD-based and explicit formats.
Added ODD-concept to easily convert between DD-based and explicit formats.
Former-commit-id: f2a2a002b7
tempestpy_adaptions
dehnert
11 years ago
8 changed files with 351 additions and 2 deletions
-
50src/storage/dd/CuddDd.cpp
-
48src/storage/dd/CuddDd.h
-
1src/storage/dd/CuddDdManager.h
-
4src/storage/dd/CuddDdMetaVariable.h
-
97src/storage/dd/CuddOdd.cpp
-
123src/storage/dd/CuddOdd.h
-
13src/storage/dd/Odd.h
-
17test/functional/storage/CuddDdTest.cpp
@ -0,0 +1,97 @@ |
|||
#include "src/storage/dd/CuddOdd.h"
|
|||
|
|||
#include <algorithm>
|
|||
|
|||
#include "src/storage/dd/CuddDdManager.h"
|
|||
#include "src/storage/dd/CuddDdMetaVariable.h"
|
|||
|
|||
namespace storm { |
|||
namespace dd { |
|||
Odd<DdType::CUDD>::Odd(Dd<DdType::CUDD> const& dd) { |
|||
std::shared_ptr<DdManager<DdType::CUDD>> manager = dd.getDdManager(); |
|||
|
|||
// First, we need to determine the involved DD variables indices.
|
|||
std::vector<uint_fast64_t> ddVariableIndices = dd.getSortedVariableIndices(); |
|||
|
|||
// Prepare a unique table for each level that keeps the constructed ODD nodes unique.
|
|||
std::vector<std::map<DdNode*, std::shared_ptr<Odd<DdType::CUDD>>>> uniqueTableForLevels(ddVariableIndices.size() + 1); |
|||
|
|||
// Now construct the ODD structure.
|
|||
std::shared_ptr<Odd<DdType::CUDD>> rootOdd = buildOddRec(dd.getCuddAdd().getNode(), manager->getCuddManager(), 0, ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels); |
|||
|
|||
// Finally, move the children of the root ODD into this ODD.
|
|||
this->dd = rootOdd->dd; |
|||
this->elseNode = std::move(rootOdd->elseNode); |
|||
this->thenNode = std::move(rootOdd->thenNode); |
|||
this->elseOffset = rootOdd->elseOffset; |
|||
this->thenOffset = rootOdd->thenOffset; |
|||
} |
|||
|
|||
Odd<DdType::CUDD>::Odd(ADD dd, std::shared_ptr<Odd<DdType::CUDD>>&& elseNode, uint_fast64_t elseOffset, std::shared_ptr<Odd<DdType::CUDD>>&& thenNode, uint_fast64_t thenOffset) : dd(dd), elseNode(elseNode), thenNode(thenNode), elseOffset(elseOffset), thenOffset(thenOffset) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
Odd<DdType::CUDD> const& Odd<DdType::CUDD>::getThenSuccessor() const { |
|||
return *this->thenNode; |
|||
} |
|||
|
|||
Odd<DdType::CUDD> const& Odd<DdType::CUDD>::getElseSuccessor() const { |
|||
return *this->elseNode; |
|||
} |
|||
|
|||
uint_fast64_t Odd<DdType::CUDD>::getElseOffset() const { |
|||
return this->elseOffset; |
|||
} |
|||
|
|||
void Odd<DdType::CUDD>::setElseOffset(uint_fast64_t newOffset) { |
|||
this->elseOffset = newOffset; |
|||
} |
|||
|
|||
uint_fast64_t Odd<DdType::CUDD>::getThenOffset() const { |
|||
return this->thenOffset; |
|||
} |
|||
|
|||
void Odd<DdType::CUDD>::setThenOffset(uint_fast64_t newOffset) { |
|||
this->thenOffset = newOffset; |
|||
} |
|||
|
|||
uint_fast64_t Odd<DdType::CUDD>::getTotalOffset() const { |
|||
return this->elseOffset + this->thenOffset; |
|||
} |
|||
|
|||
std::shared_ptr<Odd<DdType::CUDD>> Odd<DdType::CUDD>::buildOddRec(DdNode* dd, Cudd const& manager, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<std::map<DdNode*, std::shared_ptr<Odd<DdType::CUDD>>>>& uniqueTableForLevels) { |
|||
// Check whether the ODD for this node has already been computed (for this level) and if so, return this instead.
|
|||
auto const& iterator = uniqueTableForLevels[currentLevel].find(dd); |
|||
if (iterator != uniqueTableForLevels[currentLevel].end()) { |
|||
return iterator->second; |
|||
} else { |
|||
// Otherwise, we need to recursively compute the ODD.
|
|||
|
|||
// If we are already past the maximal level that is to be considered, we can simply create a Odd without
|
|||
// successors
|
|||
if (currentLevel == maxLevel) { |
|||
uint_fast64_t elseOffset = 0; |
|||
uint_fast64_t thenOffset = 0; |
|||
|
|||
// If the DD is not the zero leaf, then the then-offset is 1.
|
|||
if (dd != Cudd_ReadZero(manager.getManager())) { |
|||
thenOffset = 1; |
|||
} |
|||
|
|||
return std::shared_ptr<Odd<DdType::CUDD>>(new Odd<DdType::CUDD>(ADD(manager, dd), nullptr, elseOffset, nullptr, thenOffset)); |
|||
} else if (ddVariableIndices[currentLevel] < static_cast<uint_fast64_t>(dd->index)) { |
|||
// If we skipped the level in the DD, we compute the ODD just for the else-successor and use the same
|
|||
// node for the then-successor as well.
|
|||
std::shared_ptr<Odd<DdType::CUDD>> elseNode = buildOddRec(dd, manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels); |
|||
std::shared_ptr<Odd<DdType::CUDD>> thenNode = elseNode; |
|||
return std::shared_ptr<Odd<DdType::CUDD>>(new Odd<DdType::CUDD>(ADD(manager, dd), std::move(elseNode), elseNode->getElseOffset() + elseNode->getThenOffset(), std::move(thenNode), thenNode->getElseOffset() + thenNode->getThenOffset())); |
|||
} else { |
|||
// Otherwise, we compute the ODDs for both the then- and else successors.
|
|||
std::shared_ptr<Odd<DdType::CUDD>> elseNode = buildOddRec(Cudd_E(dd), manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels); |
|||
std::shared_ptr<Odd<DdType::CUDD>> thenNode = buildOddRec(Cudd_T(dd), manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels); |
|||
return std::shared_ptr<Odd<DdType::CUDD>>(new Odd<DdType::CUDD>(ADD(manager, dd), std::move(elseNode), elseNode->getElseOffset() + elseNode->getThenOffset(), std::move(thenNode), thenNode->getElseOffset() + thenNode->getThenOffset())); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,123 @@ |
|||
#ifndef STORM_STORAGE_DD_CUDDODD_H_ |
|||
#define STORM_STORAGE_DD_CUDDODD_H_ |
|||
|
|||
#include <memory> |
|||
|
|||
#include "src/storage/dd/Odd.h" |
|||
#include "src/storage/dd/CuddDd.h" |
|||
#include "src/utility/OsDetection.h" |
|||
|
|||
// Include the C++-interface of CUDD. |
|||
#include "cuddObj.hh" |
|||
|
|||
namespace storm { |
|||
namespace dd { |
|||
template<> |
|||
class Odd<DdType::CUDD> { |
|||
public: |
|||
/*! |
|||
* Constructs an offset-labeled DD from the given DD. |
|||
* |
|||
* @param dd The DD for which to build the offset-labeled DD. |
|||
*/ |
|||
Odd(Dd<DdType::CUDD> const& dd); |
|||
|
|||
// Instantiate all copy/move constructors/assignments with the default implementation. |
|||
Odd() = default; |
|||
Odd(Odd<DdType::CUDD> const& other) = default; |
|||
Odd& operator=(Odd<DdType::CUDD> const& other) = default; |
|||
#ifndef WINDOWS |
|||
Odd(Odd<DdType::CUDD>&& other) = default; |
|||
Odd& operator=(Odd<DdType::CUDD>&& other) = default; |
|||
#endif |
|||
|
|||
/*! |
|||
* Retrieves the then-successor of this ODD node. |
|||
* |
|||
* @return The then-successor of this ODD node. |
|||
*/ |
|||
Odd<DdType::CUDD> const& getThenSuccessor() const; |
|||
|
|||
/*! |
|||
* Retrieves the else-successor of this ODD node. |
|||
* |
|||
* @return The else-successor of this ODD node. |
|||
*/ |
|||
Odd<DdType::CUDD> const& getElseSuccessor() const; |
|||
|
|||
/*! |
|||
* Retrieves the else-offset of this ODD node. |
|||
* |
|||
* @return The else-offset of this ODD node. |
|||
*/ |
|||
uint_fast64_t getElseOffset() const; |
|||
|
|||
/*! |
|||
* Sets the else-offset of this ODD node. |
|||
* |
|||
* @param newOffset The new else-offset of this ODD node. |
|||
*/ |
|||
void setElseOffset(uint_fast64_t newOffset); |
|||
|
|||
/*! |
|||
* Retrieves the then-offset of this ODD node. |
|||
* |
|||
* @return The then-offset of this ODD node. |
|||
*/ |
|||
uint_fast64_t getThenOffset() const; |
|||
|
|||
/*! |
|||
* Sets the then-offset of this ODD node. |
|||
* |
|||
* @param newOffset The new then-offset of this ODD node. |
|||
*/ |
|||
void setThenOffset(uint_fast64_t newOffset); |
|||
|
|||
/*! |
|||
* Retrieves the total offset, i.e., the sum of the then- and else-offset. |
|||
* |
|||
* @return The total offset of this ODD. |
|||
*/ |
|||
uint_fast64_t getTotalOffset() const; |
|||
|
|||
private: |
|||
/*! |
|||
* Constructs an offset-labeled DD with the given topmost DD node, else- and then-successor. |
|||
* |
|||
* @param dd The DD associated with this ODD node. |
|||
* @param elseNode The else-successor of thie ODD node. |
|||
* @param elseOffset The offset of the else-successor. |
|||
* @param thenNode The then-successor of thie ODD node. |
|||
* @param thenOffset The offset of the then-successor. |
|||
*/ |
|||
Odd(ADD dd, std::shared_ptr<Odd<DdType::CUDD>>&& elseNode, uint_fast64_t elseOffset, std::shared_ptr<Odd<DdType::CUDD>>&& thenNode, uint_fast64_t thenOffset); |
|||
|
|||
/*! |
|||
* Recursively builds the ODD. |
|||
* |
|||
* @param dd The DD for which to build the ODD. |
|||
* @param manager The manager responsible for the DD. |
|||
* @param currentLevel The currently considered level in the DD. |
|||
* @param maxLevel The number of levels that need to be considered. |
|||
* @param ddVariableIndices The (sorted) indices of all DD variables that need to be considered. |
|||
* @param uniqueTableForLevels A vector of unique tables, one for each level to be considered, that keeps |
|||
* ODD nodes for the same DD and level unique. |
|||
* @return A pointer to the constructed ODD for the given arguments. |
|||
*/ |
|||
static std::shared_ptr<Odd<DdType::CUDD>> buildOddRec(DdNode* dd, Cudd const& manager, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<std::map<DdNode*, std::shared_ptr<Odd<DdType::CUDD>>>>& uniqueTableForLevels); |
|||
|
|||
// The DD associated with this ODD node. |
|||
ADD dd; |
|||
|
|||
// The then- and else-nodes. |
|||
std::shared_ptr<Odd<DdType::CUDD>> elseNode; |
|||
std::shared_ptr<Odd<DdType::CUDD>> thenNode; |
|||
|
|||
// The offsets that need to be added if the then- or else-successor is taken, respectively. |
|||
uint_fast64_t elseOffset; |
|||
uint_fast64_t thenOffset; |
|||
}; |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_STORAGE_DD_CUDDODD_H_ */ |
@ -0,0 +1,13 @@ |
|||
#ifndef STORM_STORAGE_DD_ODD_H_ |
|||
#define STORM_STORAGE_DD_ODD_H_ |
|||
|
|||
#include "src/storage/dd/DdType.h" |
|||
|
|||
namespace storm { |
|||
namespace dd { |
|||
// Declare Odd class so we can then specialize it for the different DD types. |
|||
template<DdType Type> class Odd; |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_STORAGE_DD_ODD_H_ */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue