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
			
			
				main
			
			
		
				 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