Browse Source
			
			
			restructured ODD to be independent of the DD library being used
			
				
		restructured ODD to be independent of the DD library being used
	
		
	
			
				Former-commit-id: 83f08ba203
			
			
				main
			
			
		
				 25 changed files with 680 additions and 935 deletions
			
			
		- 
					19src/modelchecker/csl/helper/HybridCtmcCslHelper.cpp
 - 
					4src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp
 - 
					2src/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp
 - 
					12src/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp
 - 
					12src/modelchecker/prctl/helper/HybridMdpPrctlHelper.cpp
 - 
					10src/modelchecker/prctl/helper/SymbolicDtmcPrctlHelper.cpp
 - 
					1src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp
 - 
					10src/modelchecker/results/HybridQuantitativeCheckResult.cpp
 - 
					8src/modelchecker/results/HybridQuantitativeCheckResult.h
 - 
					29src/storage/dd/Add.cpp
 - 
					30src/storage/dd/Add.h
 - 
					27src/storage/dd/Bdd.cpp
 - 
					26src/storage/dd/Bdd.h
 - 
					4src/storage/dd/Dd.h
 - 
					4src/storage/dd/DdManager.h
 - 
					144src/storage/dd/Odd.cpp
 - 
					145src/storage/dd/Odd.h
 - 
					332src/storage/dd/cudd/CuddOdd.cpp
 - 
					235src/storage/dd/cudd/CuddOdd.h
 - 
					291src/storage/dd/cudd/InternalCuddAdd.cpp
 - 
					48src/storage/dd/cudd/InternalCuddAdd.h
 - 
					133src/storage/dd/cudd/InternalCuddBdd.cpp
 - 
					59src/storage/dd/cudd/InternalCuddBdd.h
 - 
					4src/storage/dd/cudd/InternalCuddDdManager.h
 - 
					26test/functional/storage/CuddDdTest.cpp
 
@ -1 +1,143 @@ | 
				
			|||
#include "src/storage/dd/Odd.h"
 | 
				
			|||
#include "src/storage/dd/Odd.h"
 | 
				
			|||
 | 
				
			|||
#include <set>
 | 
				
			|||
#include <fstream>
 | 
				
			|||
#include <boost/algorithm/string/join.hpp>
 | 
				
			|||
 | 
				
			|||
#include "src/utility/macros.h"
 | 
				
			|||
#include "src/exceptions/InvalidArgumentException.h"
 | 
				
			|||
 | 
				
			|||
namespace storm { | 
				
			|||
    namespace dd { | 
				
			|||
        Odd::Odd(std::shared_ptr<Odd> elseNode, uint_fast64_t elseOffset, std::shared_ptr<Odd> thenNode, uint_fast64_t thenOffset) : elseNode(elseNode), thenNode(thenNode), elseOffset(elseOffset), thenOffset(thenOffset) { | 
				
			|||
            // Intentionally left empty.
 | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        Odd const& Odd::getThenSuccessor() const { | 
				
			|||
            return *this->thenNode; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        Odd const& Odd::getElseSuccessor() const { | 
				
			|||
            return *this->elseNode; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint_fast64_t Odd::getElseOffset() const { | 
				
			|||
            return this->elseOffset; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd::setElseOffset(uint_fast64_t newOffset) { | 
				
			|||
            this->elseOffset = newOffset; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint_fast64_t Odd::getThenOffset() const { | 
				
			|||
            return this->thenOffset; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd::setThenOffset(uint_fast64_t newOffset) { | 
				
			|||
            this->thenOffset = newOffset; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint_fast64_t Odd::getTotalOffset() const { | 
				
			|||
            return this->elseOffset + this->thenOffset; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint_fast64_t Odd::getNodeCount() const { | 
				
			|||
            // If the ODD contains a constant (and thus has no children), the size is 1.
 | 
				
			|||
            if (this->elseNode == nullptr && this->thenNode == nullptr) { | 
				
			|||
                return 1; | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            // If the two successors are actually the same, we need to count the subnodes only once.
 | 
				
			|||
            if (this->elseNode == this->thenNode) { | 
				
			|||
                return this->elseNode->getNodeCount(); | 
				
			|||
            } else { | 
				
			|||
                return this->elseNode->getNodeCount() + this->thenNode->getNodeCount(); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint_fast64_t Odd::getHeight() const { | 
				
			|||
            if (this->isTerminalNode()) { | 
				
			|||
                return 1; | 
				
			|||
            } else { | 
				
			|||
                return 1 + this->getElseSuccessor().getHeight(); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        bool Odd::isTerminalNode() const { | 
				
			|||
            return this->elseNode == nullptr && this->thenNode == nullptr; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd::expandExplicitVector(storm::dd::Odd const& newOdd, std::vector<double> const& oldValues, std::vector<double>& newValues) const { | 
				
			|||
            expandValuesToVectorRec(0, *this, oldValues, 0, newOdd, newValues); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd::expandValuesToVectorRec(uint_fast64_t oldOffset, storm::dd::Odd const& oldOdd, std::vector<double> const& oldValues, uint_fast64_t newOffset, storm::dd::Odd const& newOdd, std::vector<double>& newValues) { | 
				
			|||
            if (oldOdd.isTerminalNode()) { | 
				
			|||
                STORM_LOG_THROW(newOdd.isTerminalNode(), storm::exceptions::InvalidArgumentException, "The ODDs for the translation must have the same height."); | 
				
			|||
                if (oldOdd.getThenOffset() != 0) { | 
				
			|||
                    newValues[newOffset] += oldValues[oldOffset]; | 
				
			|||
                } | 
				
			|||
            } else { | 
				
			|||
                expandValuesToVectorRec(oldOffset, oldOdd.getElseSuccessor(), oldValues, newOffset, newOdd.getElseSuccessor(), newValues); | 
				
			|||
                expandValuesToVectorRec(oldOffset + oldOdd.getElseOffset(), oldOdd.getThenSuccessor(), oldValues, newOffset + newOdd.getElseOffset(), newOdd.getThenSuccessor(), newValues); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd::exportToDot(std::string const& filename) const { | 
				
			|||
            std::ofstream dotFile; | 
				
			|||
            dotFile.open (filename); | 
				
			|||
             | 
				
			|||
            // Print header.
 | 
				
			|||
            dotFile << "digraph \"ODD\" {" << std::endl << "center=true;" << std::endl << "edge [dir = none];" << std::endl; | 
				
			|||
             | 
				
			|||
            // Print levels as ranks.
 | 
				
			|||
            dotFile << "{ node [shape = plaintext];" << std::endl << "edge [style = invis];" << std::endl; | 
				
			|||
            std::vector<std::string> levelNames; | 
				
			|||
            for (uint_fast64_t level = 0; level < this->getHeight(); ++level) { | 
				
			|||
                levelNames.push_back("\"" + std::to_string(level) + "\""); | 
				
			|||
            } | 
				
			|||
            dotFile << boost::join(levelNames, " -> ") << ";"; | 
				
			|||
            dotFile << "}" << std::endl; | 
				
			|||
             | 
				
			|||
            std::map<uint_fast64_t, std::vector<std::reference_wrapper<storm::dd::Odd const>>> levelToOddNodesMap; | 
				
			|||
            this->addToLevelToOddNodesMap(levelToOddNodesMap); | 
				
			|||
             | 
				
			|||
            for (auto const& levelNodes : levelToOddNodesMap) { | 
				
			|||
                dotFile << "{ rank = same; \"" << levelNodes.first << "\"" << std::endl;; | 
				
			|||
                for (auto const& node : levelNodes.second) { | 
				
			|||
                    dotFile << "\"" << &node.get() << "\";" << std::endl; | 
				
			|||
                } | 
				
			|||
                dotFile << "}" << std::endl; | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            std::set<storm::dd::Odd const*> printedNodes; | 
				
			|||
            for (auto const& levelNodes : levelToOddNodesMap) { | 
				
			|||
                for (auto const& node : levelNodes.second) { | 
				
			|||
                    if (printedNodes.find(&node.get()) != printedNodes.end()) { | 
				
			|||
                        continue; | 
				
			|||
                    } else { | 
				
			|||
                        printedNodes.insert(&node.get()); | 
				
			|||
                    } | 
				
			|||
                     | 
				
			|||
                    dotFile << "\"" << &node.get() << "\" [label=\"" << levelNodes.first << "\"];" << std::endl; | 
				
			|||
                    if (!node.get().isTerminalNode()) { | 
				
			|||
                        dotFile << "\"" << &node.get() << "\" -> \"" << &node.get().getElseSuccessor() << "\" [style=dashed, label=\"0\"];" << std::endl; | 
				
			|||
                        dotFile << "\"" << &node.get() << "\" -> \"" << &node.get().getThenSuccessor() << "\" [style=solid, label=\"" << node.get().getElseOffset() << "\"];" << std::endl; | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            dotFile << "}" << std::endl; | 
				
			|||
             | 
				
			|||
            dotFile.close(); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd::addToLevelToOddNodesMap(std::map<uint_fast64_t, std::vector<std::reference_wrapper<storm::dd::Odd const>>>& levelToOddNodesMap, uint_fast64_t level) const { | 
				
			|||
            levelToOddNodesMap[level].push_back(*this); | 
				
			|||
            if (!this->isTerminalNode()) { | 
				
			|||
                this->getElseSuccessor().addToLevelToOddNodesMap(levelToOddNodesMap, level + 1); | 
				
			|||
                this->getThenSuccessor().addToLevelToOddNodesMap(levelToOddNodesMap, level + 1); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -1,12 +1,151 @@ | 
				
			|||
#ifndef STORM_STORAGE_DD_ODD_H_ | 
				
			|||
#define STORM_STORAGE_DD_ODD_H_ | 
				
			|||
 | 
				
			|||
#include "src/storage/dd/DdType.h" | 
				
			|||
#include <vector> | 
				
			|||
#include <map> | 
				
			|||
 | 
				
			|||
namespace storm { | 
				
			|||
    namespace dd { | 
				
			|||
        template<DdType Type> | 
				
			|||
        class Odd; | 
				
			|||
        class Odd { | 
				
			|||
        public: | 
				
			|||
            /*! | 
				
			|||
             * Constructs an offset-labeled DD with the given topmost DD node, else- and then-successor. | 
				
			|||
             * | 
				
			|||
             * @param dd The DD node 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(std::shared_ptr<Odd> elseNode, uint_fast64_t elseOffset, std::shared_ptr<Odd> thenNode, uint_fast64_t thenOffset); | 
				
			|||
             | 
				
			|||
            // Instantiate all copy/move constructors/assignments with the default implementation. | 
				
			|||
            Odd() = default; | 
				
			|||
            Odd(Odd const& other) = default; | 
				
			|||
            Odd& operator=(Odd const& other) = default; | 
				
			|||
#ifndef WINDOWS | 
				
			|||
            Odd(Odd&& other) = default; | 
				
			|||
            Odd& operator=(Odd&& other) = default; | 
				
			|||
#endif | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Retrieves the then-successor of this ODD node. | 
				
			|||
             * | 
				
			|||
             * @return The then-successor of this ODD node. | 
				
			|||
             */ | 
				
			|||
            Odd const& getThenSuccessor() const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Retrieves the else-successor of this ODD node. | 
				
			|||
             * | 
				
			|||
             * @return The else-successor of this ODD node. | 
				
			|||
             */ | 
				
			|||
            Odd 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; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Retrieves the size of the ODD. Note: the size is computed by a traversal, so this may be costlier than | 
				
			|||
             * expected. | 
				
			|||
             * | 
				
			|||
             * @return The size (in nodes) of this ODD. | 
				
			|||
             */ | 
				
			|||
            uint_fast64_t getNodeCount() const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Retrieves the height of the ODD. | 
				
			|||
             * | 
				
			|||
             * @return The height of the ODD. | 
				
			|||
             */ | 
				
			|||
            uint_fast64_t getHeight() const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Checks whether the given ODD node is a terminal node, i.e. has no successors. | 
				
			|||
             * | 
				
			|||
             * @return True iff the node is terminal. | 
				
			|||
             */ | 
				
			|||
            bool isTerminalNode() const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Adds the old values to the new values. It does so by writing the old values at their correct positions | 
				
			|||
             * wrt. to the new ODD. | 
				
			|||
             * | 
				
			|||
             * @param newOdd The new ODD to use. | 
				
			|||
             * @param oldValues The old vector of values (which is being read). | 
				
			|||
             * @param newValues The new vector of values (which is being written). | 
				
			|||
             */ | 
				
			|||
            void expandExplicitVector(storm::dd::Odd const& newOdd, std::vector<double> const& oldValues, std::vector<double>& newValues) const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Exports the ODD in the dot format to the given file. | 
				
			|||
             * | 
				
			|||
             * @param filename The name of the file to which to write the dot output. | 
				
			|||
             */ | 
				
			|||
            void exportToDot(std::string const& filename) const; | 
				
			|||
             | 
				
			|||
        private: | 
				
			|||
            /*! | 
				
			|||
             * Adds all nodes below the current one to the given mapping. | 
				
			|||
             * | 
				
			|||
             * @param levelToOddNodesMap A mapping of the level to the ODD node. | 
				
			|||
             * @param The level of the current node. | 
				
			|||
             */ | 
				
			|||
            void addToLevelToOddNodesMap(std::map<uint_fast64_t, std::vector<std::reference_wrapper<storm::dd::Odd const>>>& levelToOddNodesMap, uint_fast64_t level = 0) const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Adds the values of the old explicit values to the new explicit values where the positions in the old vector | 
				
			|||
             * are given by the current old ODD and the positions in the new vector are given by the new ODD. | 
				
			|||
             * | 
				
			|||
             * @param oldOffset The offset in the old explicit values. | 
				
			|||
             * @param oldOdd The ODD to use for the old explicit values. | 
				
			|||
             * @param oldValues The vector of old values. | 
				
			|||
             * @param newOffset The offset in the new explicit values. | 
				
			|||
             * @param newOdd The ODD to use for the new explicit values. | 
				
			|||
             * @param newValues The vector of new values. | 
				
			|||
             */ | 
				
			|||
            static void expandValuesToVectorRec(uint_fast64_t oldOffset, storm::dd::Odd const& oldOdd, std::vector<double> const& oldValues, uint_fast64_t newOffset, storm::dd::Odd const& newOdd, std::vector<double>& newValues); | 
				
			|||
             | 
				
			|||
            // The then- and else-nodes. | 
				
			|||
            std::shared_ptr<Odd> elseNode; | 
				
			|||
            std::shared_ptr<Odd> 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; | 
				
			|||
        }; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
@ -1,332 +0,0 @@ | 
				
			|||
#include "src/storage/dd/cudd/CuddOdd.h"
 | 
				
			|||
 | 
				
			|||
#include <fstream>
 | 
				
			|||
#include <algorithm>
 | 
				
			|||
#include <boost/functional/hash.hpp>
 | 
				
			|||
#include <boost/algorithm/string/join.hpp>
 | 
				
			|||
 | 
				
			|||
#include "src/exceptions/InvalidArgumentException.h"
 | 
				
			|||
#include "src/utility/macros.h"
 | 
				
			|||
 | 
				
			|||
#include "src/storage/dd/DdManager.h"
 | 
				
			|||
#include "src/storage/dd/DdMetaVariable.h"
 | 
				
			|||
 | 
				
			|||
namespace storm { | 
				
			|||
    namespace dd { | 
				
			|||
        template<typename ValueType> | 
				
			|||
        Odd<DdType::CUDD>::Odd(Add<DdType::CUDD, ValueType> const& add) { | 
				
			|||
            std::shared_ptr<DdManager<DdType::CUDD> const> manager = add.getDdManager(); | 
				
			|||
             | 
				
			|||
            // First, we need to determine the involved DD variables indices.
 | 
				
			|||
            std::vector<uint_fast64_t> ddVariableIndices = add.getSortedVariableIndices(); | 
				
			|||
             | 
				
			|||
            // Prepare a unique table for each level that keeps the constructed ODD nodes unique.
 | 
				
			|||
            std::vector<std::unordered_map<DdNode*, std::shared_ptr<Odd<DdType::CUDD>>>> uniqueTableForLevels(ddVariableIndices.size() + 1); | 
				
			|||
             | 
				
			|||
            // Now construct the ODD structure from the ADD.
 | 
				
			|||
            std::shared_ptr<Odd<DdType::CUDD>> rootOdd = buildOddFromAddRec(add.internalAdd.getCuddDdNode(), manager->internalDdManager.getCuddManager(), 0, ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels); | 
				
			|||
             | 
				
			|||
            // Finally, move the children of the root ODD into this ODD.
 | 
				
			|||
            this->elseNode = std::move(rootOdd->elseNode); | 
				
			|||
            this->thenNode = std::move(rootOdd->thenNode); | 
				
			|||
            this->elseOffset = rootOdd->elseOffset; | 
				
			|||
            this->thenOffset = rootOdd->thenOffset; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        Odd<DdType::CUDD>::Odd(Bdd<DdType::CUDD> const& bdd) { | 
				
			|||
            std::shared_ptr<DdManager<DdType::CUDD> const> manager = bdd.getDdManager(); | 
				
			|||
             | 
				
			|||
            // First, we need to determine the involved DD variables indices.
 | 
				
			|||
            std::vector<uint_fast64_t> ddVariableIndices = bdd.getSortedVariableIndices(); | 
				
			|||
 | 
				
			|||
            // Prepare a unique table for each level that keeps the constructed ODD nodes unique.
 | 
				
			|||
            std::vector<std::unordered_map<std::pair<DdNode*, bool>, std::shared_ptr<Odd<DdType::CUDD>>, HashFunctor>> uniqueTableForLevels(ddVariableIndices.size() + 1); | 
				
			|||
             | 
				
			|||
            // Now construct the ODD structure from the BDD.
 | 
				
			|||
            std::shared_ptr<Odd<DdType::CUDD>> rootOdd = buildOddFromBddRec(Cudd_Regular(bdd.internalBdd.getCuddDdNode()), manager->internalDdManager.getCuddManager(), 0, Cudd_IsComplement(bdd.internalBdd.getCuddDdNode()), ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels); | 
				
			|||
             | 
				
			|||
            // Finally, move the children of the root ODD into this ODD.
 | 
				
			|||
            this->elseNode = std::move(rootOdd->elseNode); | 
				
			|||
            this->thenNode = std::move(rootOdd->thenNode); | 
				
			|||
            this->elseOffset = rootOdd->elseOffset; | 
				
			|||
            this->thenOffset = rootOdd->thenOffset; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        Odd<DdType::CUDD>::Odd(std::shared_ptr<Odd<DdType::CUDD>> elseNode, uint_fast64_t elseOffset, std::shared_ptr<Odd<DdType::CUDD>> thenNode, uint_fast64_t thenOffset) : 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; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint_fast64_t Odd<DdType::CUDD>::getNodeCount() const { | 
				
			|||
            // If the ODD contains a constant (and thus has no children), the size is 1.
 | 
				
			|||
            if (this->elseNode == nullptr && this->thenNode == nullptr) { | 
				
			|||
                return 1; | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            // If the two successors are actually the same, we need to count the subnodes only once.
 | 
				
			|||
            if (this->elseNode == this->thenNode) { | 
				
			|||
                return this->elseNode->getNodeCount(); | 
				
			|||
            } else { | 
				
			|||
                return this->elseNode->getNodeCount() + this->thenNode->getNodeCount(); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint_fast64_t Odd<DdType::CUDD>::getHeight() const { | 
				
			|||
            if (this->isTerminalNode()) { | 
				
			|||
                return 1; | 
				
			|||
            } else { | 
				
			|||
                return 1 + this->getElseSuccessor().getHeight(); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        bool Odd<DdType::CUDD>::isTerminalNode() const { | 
				
			|||
            return this->elseNode == nullptr && this->thenNode == nullptr; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::vector<double> Odd<DdType::CUDD>::filterExplicitVector(storm::dd::Bdd<DdType::CUDD> const& selectedValues, std::vector<double> const& values) const { | 
				
			|||
            std::vector<double> result(selectedValues.getNonZeroCount()); | 
				
			|||
             | 
				
			|||
            // First, we need to determine the involved DD variables indices.
 | 
				
			|||
            std::vector<uint_fast64_t> ddVariableIndices = selectedValues.getSortedVariableIndices(); | 
				
			|||
             | 
				
			|||
            uint_fast64_t currentIndex = 0; | 
				
			|||
            addSelectedValuesToVectorRec(selectedValues.internalBdd.getCuddDdNode(), selectedValues.getDdManager()->internalDdManager.getCuddManager(), 0, Cudd_IsComplement(selectedValues.internalBdd.getCuddDdNode()), ddVariableIndices.size(), ddVariableIndices, 0, *this, result, currentIndex, values); | 
				
			|||
            return result; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd<DdType::CUDD>::expandExplicitVector(storm::dd::Odd<DdType::CUDD> const& newOdd, std::vector<double> const& oldValues, std::vector<double>& newValues) const { | 
				
			|||
            expandValuesToVectorRec(0, *this, oldValues, 0, newOdd, newValues); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd<DdType::CUDD>::expandValuesToVectorRec(uint_fast64_t oldOffset, storm::dd::Odd<DdType::CUDD> const& oldOdd, std::vector<double> const& oldValues, uint_fast64_t newOffset, storm::dd::Odd<DdType::CUDD> const& newOdd, std::vector<double>& newValues) { | 
				
			|||
            if (oldOdd.isTerminalNode()) { | 
				
			|||
                STORM_LOG_THROW(newOdd.isTerminalNode(), storm::exceptions::InvalidArgumentException, "The ODDs for the translation must have the same height."); | 
				
			|||
                if (oldOdd.getThenOffset() != 0) { | 
				
			|||
                    newValues[newOffset] += oldValues[oldOffset]; | 
				
			|||
                } | 
				
			|||
            } else { | 
				
			|||
                expandValuesToVectorRec(oldOffset, oldOdd.getElseSuccessor(), oldValues, newOffset, newOdd.getElseSuccessor(), newValues); | 
				
			|||
                expandValuesToVectorRec(oldOffset + oldOdd.getElseOffset(), oldOdd.getThenSuccessor(), oldValues, newOffset + newOdd.getElseOffset(), newOdd.getThenSuccessor(), newValues); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd<DdType::CUDD>::addSelectedValuesToVectorRec(DdNode* dd, Cudd const& manager, uint_fast64_t currentLevel, bool complement, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, uint_fast64_t currentOffset, storm::dd::Odd<DdType::CUDD> const& odd, std::vector<double>& result, uint_fast64_t& currentIndex, std::vector<double> const& values) { | 
				
			|||
            // If there are no more values to select, we can directly return.
 | 
				
			|||
            if (dd == Cudd_ReadLogicZero(manager.getManager()) && !complement) { | 
				
			|||
                return; | 
				
			|||
            } else if (dd == Cudd_ReadOne(manager.getManager()) && complement) { | 
				
			|||
                return; | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            if (currentLevel == maxLevel) { | 
				
			|||
                // If the DD is not the zero leaf, then the then-offset is 1.
 | 
				
			|||
                bool selected = false; | 
				
			|||
                if (dd != Cudd_ReadLogicZero(manager.getManager())) { | 
				
			|||
                    selected = !complement; | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                if (selected) { | 
				
			|||
                    result[currentIndex++] = values[currentOffset]; | 
				
			|||
                } | 
				
			|||
            } else if (ddVariableIndices[currentLevel] < dd->index) { | 
				
			|||
                // If we skipped a level, we need to enumerate the explicit entries for the case in which the bit is set
 | 
				
			|||
                // and for the one in which it is not set.
 | 
				
			|||
                addSelectedValuesToVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset, odd.getElseSuccessor(), result, currentIndex, values); | 
				
			|||
                addSelectedValuesToVectorRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), result, currentIndex, values); | 
				
			|||
            } else { | 
				
			|||
                // Otherwise, we compute the ODDs for both the then- and else successors.
 | 
				
			|||
                DdNode* thenDdNode = Cudd_T(dd); | 
				
			|||
                DdNode* elseDdNode = Cudd_E(dd); | 
				
			|||
                 | 
				
			|||
                // Determine whether we have to evaluate the successors as if they were complemented.
 | 
				
			|||
                bool elseComplemented = Cudd_IsComplement(elseDdNode) ^ complement; | 
				
			|||
                bool thenComplemented = Cudd_IsComplement(thenDdNode) ^ complement; | 
				
			|||
                 | 
				
			|||
                addSelectedValuesToVectorRec(Cudd_Regular(elseDdNode), manager, currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, currentOffset, odd.getElseSuccessor(), result, currentIndex, values); | 
				
			|||
                addSelectedValuesToVectorRec(Cudd_Regular(thenDdNode), manager, currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), result, currentIndex, values); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd<DdType::CUDD>::exportToDot(std::string const& filename) const { | 
				
			|||
            std::ofstream dotFile; | 
				
			|||
            dotFile.open (filename); | 
				
			|||
             | 
				
			|||
            // Print header.
 | 
				
			|||
            dotFile << "digraph \"ODD\" {" << std::endl << "center=true;" << std::endl << "edge [dir = none];" << std::endl; | 
				
			|||
 | 
				
			|||
            // Print levels as ranks.
 | 
				
			|||
            dotFile << "{ node [shape = plaintext];" << std::endl << "edge [style = invis];" << std::endl; | 
				
			|||
            std::vector<std::string> levelNames; | 
				
			|||
            for (uint_fast64_t level = 0; level < this->getHeight(); ++level) { | 
				
			|||
                levelNames.push_back("\"" + std::to_string(level) + "\""); | 
				
			|||
            } | 
				
			|||
            dotFile << boost::join(levelNames, " -> ") << ";"; | 
				
			|||
            dotFile << "}" << std::endl; | 
				
			|||
             | 
				
			|||
            std::map<uint_fast64_t, std::vector<std::reference_wrapper<storm::dd::Odd<DdType::CUDD> const>>> levelToOddNodesMap; | 
				
			|||
            this->addToLevelToOddNodesMap(levelToOddNodesMap); | 
				
			|||
             | 
				
			|||
            for (auto const& levelNodes : levelToOddNodesMap) { | 
				
			|||
                dotFile << "{ rank = same; \"" << levelNodes.first << "\"" << std::endl;; | 
				
			|||
                for (auto const& node : levelNodes.second) { | 
				
			|||
                    dotFile << "\"" << &node.get() << "\";" << std::endl; | 
				
			|||
                } | 
				
			|||
                dotFile << "}" << std::endl; | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            std::set<storm::dd::Odd<DdType::CUDD> const*> printedNodes; | 
				
			|||
            for (auto const& levelNodes : levelToOddNodesMap) { | 
				
			|||
                for (auto const& node : levelNodes.second) { | 
				
			|||
                    if (printedNodes.find(&node.get()) != printedNodes.end()) { | 
				
			|||
                        continue; | 
				
			|||
                    } else { | 
				
			|||
                        printedNodes.insert(&node.get()); | 
				
			|||
                    } | 
				
			|||
                     | 
				
			|||
                    dotFile << "\"" << &node.get() << "\" [label=\"" << levelNodes.first << "\"];" << std::endl; | 
				
			|||
                    if (!node.get().isTerminalNode()) { | 
				
			|||
                        dotFile << "\"" << &node.get() << "\" -> \"" << &node.get().getElseSuccessor() << "\" [style=dashed, label=\"0\"];" << std::endl; | 
				
			|||
                        dotFile << "\"" << &node.get() << "\" -> \"" << &node.get().getThenSuccessor() << "\" [style=solid, label=\"" << node.get().getElseOffset() << "\"];" << std::endl; | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            dotFile << "}" << std::endl; | 
				
			|||
             | 
				
			|||
            dotFile.close(); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void Odd<DdType::CUDD>::addToLevelToOddNodesMap(std::map<uint_fast64_t, std::vector<std::reference_wrapper<storm::dd::Odd<DdType::CUDD> const>>>& levelToOddNodesMap, uint_fast64_t level) const { | 
				
			|||
            levelToOddNodesMap[level].push_back(*this); | 
				
			|||
            if (!this->isTerminalNode()) { | 
				
			|||
                this->getElseSuccessor().addToLevelToOddNodesMap(levelToOddNodesMap, level + 1); | 
				
			|||
                this->getThenSuccessor().addToLevelToOddNodesMap(levelToOddNodesMap, level + 1); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::shared_ptr<Odd<DdType::CUDD>> Odd<DdType::CUDD>::buildOddFromAddRec(DdNode* dd, Cudd const& manager, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<std::unordered_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 an 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>(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 = buildOddFromAddRec(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>(elseNode, elseNode->getElseOffset() + elseNode->getThenOffset(), thenNode, thenNode->getElseOffset() + thenNode->getThenOffset())); | 
				
			|||
                } else { | 
				
			|||
                    // Otherwise, we compute the ODDs for both the then- and else successors.
 | 
				
			|||
                    bool elseComplemented = Cudd_IsComplement(Cudd_E(dd)); | 
				
			|||
                    bool thenComplemented = Cudd_IsComplement(Cudd_T(dd)); | 
				
			|||
                    std::shared_ptr<Odd<DdType::CUDD>> elseNode = buildOddFromAddRec(Cudd_E(dd), manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels); | 
				
			|||
                    std::shared_ptr<Odd<DdType::CUDD>> thenNode = buildOddFromAddRec(Cudd_T(dd), manager, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels); | 
				
			|||
                    uint_fast64_t totalElseOffset = elseNode->getElseOffset() + elseNode->getThenOffset(); | 
				
			|||
                    uint_fast64_t totalThenOffset = thenNode->getElseOffset() + thenNode->getThenOffset(); | 
				
			|||
                    return std::shared_ptr<Odd<DdType::CUDD>>(new Odd<DdType::CUDD>(elseNode, elseComplemented ? (1ull << (maxLevel - currentLevel - 1)) - totalElseOffset : totalElseOffset, thenNode, thenComplemented ? (1ull << (maxLevel - currentLevel - 1)) - totalThenOffset : totalThenOffset)); | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::size_t Odd<DdType::CUDD>::HashFunctor::operator()(std::pair<DdNode*, bool> const& key) const { | 
				
			|||
            std::size_t result = 0; | 
				
			|||
            boost::hash_combine(result, key.first); | 
				
			|||
            boost::hash_combine(result, key.second); | 
				
			|||
            return result; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::shared_ptr<Odd<DdType::CUDD>> Odd<DdType::CUDD>::buildOddFromBddRec(DdNode* dd, Cudd const& manager, uint_fast64_t currentLevel, bool complement, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<std::unordered_map<std::pair<DdNode*, bool>, std::shared_ptr<Odd<DdType::CUDD>>, HashFunctor>>& 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(std::make_pair(dd, complement)); | 
				
			|||
            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 an 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; | 
				
			|||
                    } | 
				
			|||
                     | 
				
			|||
                    // If we need to complement the 'terminal' node, we need to negate its offset.
 | 
				
			|||
                    if (complement) { | 
				
			|||
                        thenOffset = 1 - thenOffset; | 
				
			|||
                    } | 
				
			|||
                     | 
				
			|||
                    return std::shared_ptr<Odd<DdType::CUDD>>(new Odd<DdType::CUDD>(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 = buildOddFromBddRec(dd, manager, currentLevel + 1, complement, maxLevel, ddVariableIndices, uniqueTableForLevels); | 
				
			|||
                    std::shared_ptr<Odd<DdType::CUDD>> thenNode = elseNode; | 
				
			|||
                    uint_fast64_t totalOffset = elseNode->getElseOffset() + elseNode->getThenOffset(); | 
				
			|||
                    return std::shared_ptr<Odd<DdType::CUDD>>(new Odd<DdType::CUDD>(elseNode, totalOffset, thenNode, totalOffset)); | 
				
			|||
                } else { | 
				
			|||
                    // Otherwise, we compute the ODDs for both the then- and else successors.
 | 
				
			|||
                    DdNode* thenDdNode = Cudd_T(dd); | 
				
			|||
                    DdNode* elseDdNode = Cudd_E(dd); | 
				
			|||
                     | 
				
			|||
                    // Determine whether we have to evaluate the successors as if they were complemented.
 | 
				
			|||
                    bool elseComplemented = Cudd_IsComplement(elseDdNode) ^ complement; | 
				
			|||
                    bool thenComplemented = Cudd_IsComplement(thenDdNode) ^ complement; | 
				
			|||
                     | 
				
			|||
                    std::shared_ptr<Odd<DdType::CUDD>> elseNode = buildOddFromBddRec(Cudd_Regular(elseDdNode), manager, currentLevel + 1, elseComplemented, maxLevel, ddVariableIndices, uniqueTableForLevels); | 
				
			|||
                    std::shared_ptr<Odd<DdType::CUDD>> thenNode = buildOddFromBddRec(Cudd_Regular(thenDdNode), manager, currentLevel + 1, thenComplemented, maxLevel, ddVariableIndices, uniqueTableForLevels); | 
				
			|||
                     | 
				
			|||
                    return std::shared_ptr<Odd<DdType::CUDD>>(new Odd<DdType::CUDD>(elseNode, elseNode->getElseOffset() + elseNode->getThenOffset(), thenNode, thenNode->getElseOffset() + thenNode->getThenOffset())); | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        template Odd<DdType::CUDD>::Odd(Add<DdType::CUDD, double> const& add); | 
				
			|||
        template Odd<DdType::CUDD>::Odd(Add<DdType::CUDD, uint_fast64_t> const& add); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -1,235 +0,0 @@ | 
				
			|||
#ifndef STORM_STORAGE_DD_CUDDODD_H_ | 
				
			|||
#define STORM_STORAGE_DD_CUDDODD_H_ | 
				
			|||
 | 
				
			|||
#include <memory> | 
				
			|||
#include <unordered_map> | 
				
			|||
 | 
				
			|||
#include "src/storage/dd/Odd.h" | 
				
			|||
#include "src/storage/dd/Add.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 ADD. | 
				
			|||
             * | 
				
			|||
             * @param add The ADD for which to build the offset-labeled ADD. | 
				
			|||
             */ | 
				
			|||
            template<typename ValueType> | 
				
			|||
            Odd(Add<DdType::CUDD, ValueType> const& add); | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Constructs an offset-labeled DD from the given BDD. | 
				
			|||
             * | 
				
			|||
             * @param bdd The BDD for which to build the offset-labeled ADD. | 
				
			|||
             */ | 
				
			|||
            Odd(Bdd<DdType::CUDD> const& bdd); | 
				
			|||
             | 
				
			|||
            // 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; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Retrieves the size of the ODD. Note: the size is computed by a traversal, so this may be costlier than | 
				
			|||
             * expected. | 
				
			|||
             * | 
				
			|||
             * @return The size (in nodes) of this ODD. | 
				
			|||
             */ | 
				
			|||
            uint_fast64_t getNodeCount() const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Retrieves the height of the ODD. | 
				
			|||
             * | 
				
			|||
             * @return The height of the ODD. | 
				
			|||
             */ | 
				
			|||
            uint_fast64_t getHeight() const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Checks whether the given ODD node is a terminal node, i.e. has no successors. | 
				
			|||
             * | 
				
			|||
             * @return True iff the node is terminal. | 
				
			|||
             */ | 
				
			|||
            bool isTerminalNode() const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Filters the given explicit vector using the symbolic representation of which values to select. | 
				
			|||
             * | 
				
			|||
             * @param selectedValues A symbolic representation of which values to select. | 
				
			|||
             * @param values The value vector from which to select the values. | 
				
			|||
             * @return The resulting vector. | 
				
			|||
             */ | 
				
			|||
            std::vector<double> filterExplicitVector(storm::dd::Bdd<DdType::CUDD> const& selectedValues, std::vector<double> const& values) const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Adds the old values to the new values. It does so by writing the old values at their correct positions | 
				
			|||
             * wrt. to the new ODD. | 
				
			|||
             * | 
				
			|||
             * @param newOdd The new ODD to use. | 
				
			|||
             * @param oldValues The old vector of values (which is being read). | 
				
			|||
             * @param newValues The new vector of values (which is being written). | 
				
			|||
             */ | 
				
			|||
            void expandExplicitVector(storm::dd::Odd<DdType::CUDD> const& newOdd, std::vector<double> const& oldValues, std::vector<double>& newValues) const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Exports the ODD in the dot format to the given file. | 
				
			|||
             * | 
				
			|||
             * @param filename The name of the file to which to write the dot output. | 
				
			|||
             */ | 
				
			|||
            void exportToDot(std::string const& filename) const; | 
				
			|||
             | 
				
			|||
        private: | 
				
			|||
            // Declare a hash functor that is used for the unique tables in the construction process. | 
				
			|||
            class HashFunctor { | 
				
			|||
            public: | 
				
			|||
                std::size_t operator()(std::pair<DdNode*, bool> const& key) const; | 
				
			|||
            }; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Adds all nodes below the current one to the given mapping. | 
				
			|||
             * | 
				
			|||
             * @param levelToOddNodesMap A mapping of the level to the ODD node. | 
				
			|||
             * @param The level of the current node. | 
				
			|||
             */ | 
				
			|||
            void addToLevelToOddNodesMap(std::map<uint_fast64_t, std::vector<std::reference_wrapper<storm::dd::Odd<DdType::CUDD> const>>>& levelToOddNodesMap, uint_fast64_t level = 0) const; | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Constructs an offset-labeled DD with the given topmost DD node, else- and then-successor. | 
				
			|||
             * | 
				
			|||
             * @param dd The DD node 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(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 from an ADD (that has no complement edges). | 
				
			|||
             * | 
				
			|||
             * @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>> buildOddFromAddRec(DdNode* dd, Cudd const& manager, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<std::unordered_map<DdNode*, std::shared_ptr<Odd<DdType::CUDD>>>>& uniqueTableForLevels); | 
				
			|||
 | 
				
			|||
            /*! | 
				
			|||
             * Recursively builds the ODD from a BDD (that potentially has complement edges). | 
				
			|||
             * | 
				
			|||
             * @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 complement A flag indicating whether or not the given node is to be considered as complemented. | 
				
			|||
             * @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>> buildOddFromBddRec(DdNode* dd, Cudd const& manager, uint_fast64_t currentLevel, bool complement, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<std::unordered_map<std::pair<DdNode*, bool>, std::shared_ptr<Odd<DdType::CUDD>>, HashFunctor>>& uniqueTableForLevels); | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Adds the selected values the target vector. | 
				
			|||
             * | 
				
			|||
             * @param dd The current node of the DD representing the selected values. | 
				
			|||
             * @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 list of variable indices to use. | 
				
			|||
             * @param currentOffset The offset along the path taken in the DD representing the selected values. | 
				
			|||
             * @param odd The current ODD node. | 
				
			|||
             * @param result The target vector to which to write the values. | 
				
			|||
             * @param currentIndex The index at which the next element is to be written. | 
				
			|||
             * @param values The value vector from which to select the values. | 
				
			|||
             */ | 
				
			|||
            static void addSelectedValuesToVectorRec(DdNode* dd, Cudd const& manager, uint_fast64_t currentLevel, bool complement, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, uint_fast64_t currentOffset, storm::dd::Odd<DdType::CUDD> const& odd, std::vector<double>& result, uint_fast64_t& currentIndex, std::vector<double> const& values); | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Adds the values of the old explicit values to the new explicit values where the positions in the old vector | 
				
			|||
             * are given by the current old ODD and the positions in the new vector are given by the new ODD. | 
				
			|||
             * | 
				
			|||
             * @param oldOffset The offset in the old explicit values. | 
				
			|||
             * @param oldOdd The ODD to use for the old explicit values. | 
				
			|||
             * @param oldValues The vector of old values. | 
				
			|||
             * @param newOffset The offset in the new explicit values. | 
				
			|||
             * @param newOdd The ODD to use for the new explicit values. | 
				
			|||
             * @param newValues The vector of new values. | 
				
			|||
             */ | 
				
			|||
            static void expandValuesToVectorRec(uint_fast64_t oldOffset, storm::dd::Odd<DdType::CUDD> const& oldOdd, std::vector<double> const& oldValues, uint_fast64_t newOffset, storm::dd::Odd<DdType::CUDD> const& newOdd, std::vector<double>& newValues); | 
				
			|||
             | 
				
			|||
            // 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_ */ | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue