#pragma once #include #include "storm/storage/BitVector.h" #include "storm/storage/SparseMatrix.h" #include "storm/modelchecker/multiobjective/Objective.h" #include "storm/models/sparse/Mdp.h" #include "storm/utility/vector.h" #include "storm/storage/memorystructure/MemoryStructure.h" #include "storm/storage/memorystructure/SparseModelMemoryProduct.h" #include "storm/transformer/EndComponentEliminator.h" #include "storm/utility/Stopwatch.h" namespace storm { namespace modelchecker { namespace multiobjective { template class MultiDimensionalRewardUnfolding { public: typedef uint64_t Epoch; // The number of reward steps that are "left" for each dimension typedef typename std::conditional>::type SolutionType; struct EpochModel { storm::storage::SparseMatrix epochMatrix; storm::storage::BitVector stepChoices; std::vector stepSolutions; std::vector> objectiveRewards; std::vector objectiveRewardFilter; storm::storage::BitVector epochInStates; std::vector inStateSolutions; }; /* * * @param model The (preprocessed) model * @param objectives The (preprocessed) objectives * @param possibleECActions Overapproximation of the actions that are part of an EC * @param allowedBottomStates The states which are allowed to become a bottom state under a considered scheduler * */ MultiDimensionalRewardUnfolding(storm::models::sparse::Mdp const& model, std::vector> const& objectives, storm::storage::BitVector const& possibleECActions, storm::storage::BitVector const& allowedBottomStates); ~MultiDimensionalRewardUnfolding() { std::cout << "Unfolding statistics: " << std::endl; std::cout << " init: " << swInit << " seconds." << std::endl; std::cout << " setEpoch: " << swSetEpoch << " seconds." << std::endl; std::cout << " setEpochClass: " << swSetEpochClass << " seconds." << std::endl; std::cout << " findSolutions: " << swFindSol << " seconds." << std::endl; std::cout << " insertSolutions: " << swInsertSol << " seconds." << std::endl; std::cout << " aux1StopWatch: " << swAux1 << " seconds." << std::endl; std::cout << " aux2StopWatch: " << swAux2 << " seconds." << std::endl; std::cout << " aux3StopWatch: " << swAux3 << " seconds." << std::endl; std::cout << " aux4StopWatch: " << swAux4 << " seconds." << std::endl; std::cout << "---------------------------------------------" << std::endl; std::cout << " Product size: " << memoryProduct.getProduct().getNumberOfStates() << std::endl; std::cout << " Epoch model sizes: "; for (auto const& i : epochModelSizes) { std::cout << i << " "; } std::cout << std::endl; std::cout << "---------------------------------------------" << std::endl; std::cout << std::endl; } Epoch getStartEpoch(); std::vector getEpochComputationOrder(Epoch const& startEpoch); EpochModel& setCurrentEpoch(Epoch const& epoch); void setSolutionForCurrentEpoch(); SolutionType const& getInitialStateResult(Epoch const& epoch); private: class MemoryProduct { public: MemoryProduct() = default; MemoryProduct(storm::models::sparse::Mdp const& model, storm::storage::MemoryStructure const& memory, std::vector&& memoryStateMap, std::vector const& originalModelSteps, std::vector const& objectiveDimensions); storm::models::sparse::Mdp const& getProduct() const; std::vector const& getSteps() const; bool productStateExists(uint64_t const& modelState, uint64_t const& memoryState) const; uint64_t getProductState(uint64_t const& modelState, uint64_t const& memoryState) const; uint64_t getModelState(uint64_t const& productState) const; uint64_t getMemoryState(uint64_t const& productState) const; uint64_t convertMemoryState(storm::storage::BitVector const& memoryState) const; storm::storage::BitVector const& convertMemoryState(uint64_t const& memoryState) const; uint64_t getProductStateFromChoice(uint64_t const& productChoice) const; private: void setReachableStates(storm::storage::SparseModelMemoryProduct& productBuilder, std::vector const& originalModelSteps, std::vector const& objectiveDimensions) const; std::shared_ptr> product; std::vector steps; std::vector modelMemoryToProductStateMap; std::vector productToModelStateMap; std::vector productToMemoryStateMap; std::vector choiceToStateMap; std::vector memoryStateMap; }; void setCurrentEpochClass(Epoch const& epoch); storm::storage::BitVector computeProductInStatesForEpochClass(Epoch const& epoch); void initialize(); void initializeObjectives(std::vector& epochSteps); void initializeMemoryProduct(std::vector const& epochSteps); storm::storage::MemoryStructure computeMemoryStructure() const; std::vector computeMemoryStateMap(storm::storage::MemoryStructure const& memory) const; std::vector> computeObjectiveRewardsForProduct(Epoch const& epoch) const; bool sameEpochClass(Epoch const& epoch1, Epoch const& epoch2) const; Epoch getSuccessorEpoch(Epoch const& epoch, Epoch const& step) const; bool isZeroEpoch(Epoch const& epoch) const; bool isValidDimensionValue(uint64_t const& value) const; void setBottomDimension(Epoch& epoch, uint64_t const& dimension) const; void setDimensionOfEpoch(Epoch& epoch, uint64_t const& dimension, uint64_t const& value) const; // assumes that the value is small enough bool isBottomDimension(Epoch const& epoch, uint64_t const& dimension) const; uint64_t getDimensionOfEpoch(Epoch const& epoch, uint64_t const& dimension) const; // assumes that the dimension is not bottom std::string epochToString(Epoch const& epoch) const; template::type = 0> SolutionType getScaledSolution(SolutionType const& solution, ValueType const& scalingFactor) const; template::type = 0> SolutionType getScaledSolution(SolutionType const& solution, ValueType const& scalingFactor) const; template::type = 0> void addScaledSolution(SolutionType& solution, SolutionType const& solutionToAdd, ValueType const& scalingFactor) const; template::type = 0> void addScaledSolution(SolutionType& solution, SolutionType const& solutionToAdd, ValueType const& scalingFactor) const; template::type = 0> std::string solutionToString(SolutionType const& solution) const; template::type = 0> std::string solutionToString(SolutionType const& solution) const; void setSolutionForCurrentEpoch(uint64_t const& productState, SolutionType const& solution); SolutionType const& getStateSolution(Epoch const& epoch, uint64_t const& productState); storm::models::sparse::Mdp const& model; std::vector> const& objectives; storm::storage::BitVector possibleECActions; storm::storage::BitVector allowedBottomStates; MemoryProduct memoryProduct; typename storm::transformer::EndComponentEliminator::EndComponentEliminatorReturnType ecElimResult; std::set possibleEpochSteps; EpochModel epochModel; boost::optional currentEpoch; uint64_t dimensionCount; uint64_t bitsPerDimension; uint64_t dimensionBitMask; std::vector objectiveDimensions; std::vector, uint64_t>> subObjectives; std::vector> memoryLabels; std::vector scalingFactors; std::map, SolutionType> solutions; storm::utility::Stopwatch swInit, swFindSol, swInsertSol, swSetEpoch, swSetEpochClass, swAux1, swAux2, swAux3, swAux4; std::vector epochModelSizes; }; } } }