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