From 6af15f3a0d32f17dd624a7486989e52d9557a98a Mon Sep 17 00:00:00 2001 From: TimQu Date: Tue, 18 Jul 2017 11:29:34 +0200 Subject: [PATCH] Memory Structure Product with custom reward model type --- .../memorystructure/MemoryStructure.cpp | 8 +- .../storage/memorystructure/MemoryStructure.h | 7 +- .../MemoryStructureBuilder.cpp | 1 + .../SparseModelMemoryProduct.cpp | 88 ++++++++++--------- .../SparseModelMemoryProduct.h | 12 +-- 5 files changed, 62 insertions(+), 54 deletions(-) diff --git a/src/storm/storage/memorystructure/MemoryStructure.cpp b/src/storm/storage/memorystructure/MemoryStructure.cpp index 3d9348c44..499bc4db6 100644 --- a/src/storm/storage/memorystructure/MemoryStructure.cpp +++ b/src/storm/storage/memorystructure/MemoryStructure.cpp @@ -106,9 +106,9 @@ namespace storm { return MemoryStructure(std::move(resultTransitions), std::move(resultLabeling), std::move(resultInitialMemoryStates)); } - template - SparseModelMemoryProduct MemoryStructure::product(storm::models::sparse::Model const& sparseModel) const { - return SparseModelMemoryProduct(sparseModel, *this); + template + SparseModelMemoryProduct MemoryStructure::product(storm::models::sparse::Model const& sparseModel) const { + return SparseModelMemoryProduct(sparseModel, *this); } std::string MemoryStructure::toString() const { @@ -143,7 +143,9 @@ namespace storm { } template SparseModelMemoryProduct MemoryStructure::product(storm::models::sparse::Model const& sparseModel) const; + template SparseModelMemoryProduct> MemoryStructure::product(storm::models::sparse::Model> const& sparseModel) const; template SparseModelMemoryProduct MemoryStructure::product(storm::models::sparse::Model const& sparseModel) const; + template SparseModelMemoryProduct MemoryStructure::product(storm::models::sparse::Model const& sparseModel) const; } } diff --git a/src/storm/storage/memorystructure/MemoryStructure.h b/src/storm/storage/memorystructure/MemoryStructure.h index 9df320fd3..64bd7aaa9 100644 --- a/src/storm/storage/memorystructure/MemoryStructure.h +++ b/src/storm/storage/memorystructure/MemoryStructure.h @@ -6,11 +6,12 @@ #include "storm/logic/Formula.h" #include "storm/models/sparse/StateLabeling.h" #include "storm/models/sparse/Model.h" +#include "storm/models/sparse/StandardRewardModel.h" namespace storm { namespace storage { - template + template class SparseModelMemoryProduct; /*! @@ -53,8 +54,8 @@ namespace storm { * Builds the product of this memory structure and the given sparse model. * An exception is thrown if the state labelings of this memory structure and the given model are not disjoint. */ - template - SparseModelMemoryProduct product(storm::models::sparse::Model const& sparseModel) const; + template > + SparseModelMemoryProduct product(storm::models::sparse::Model const& sparseModel) const; std::string toString() const; diff --git a/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp b/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp index 696e9662a..148cbf2ca 100644 --- a/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp +++ b/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp @@ -91,6 +91,7 @@ namespace storm { } template class MemoryStructureBuilder; + template class MemoryStructureBuilder>; template class MemoryStructureBuilder; template class MemoryStructureBuilder; diff --git a/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp b/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp index 97e601f52..58f773cfe 100644 --- a/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp +++ b/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp @@ -17,24 +17,24 @@ namespace storm { namespace storage { - template - SparseModelMemoryProduct::SparseModelMemoryProduct(storm::models::sparse::Model const& sparseModel, storm::storage::MemoryStructure const& memoryStructure) : model(sparseModel), memory(memoryStructure) { + template + SparseModelMemoryProduct::SparseModelMemoryProduct(storm::models::sparse::Model const& sparseModel, storm::storage::MemoryStructure const& memoryStructure) : model(sparseModel), memory(memoryStructure) { reachableStates = storm::storage::BitVector(model.getNumberOfStates() * memory.getNumberOfStates(), false); } - template - void SparseModelMemoryProduct::addReachableState(uint64_t const& modelState, uint64_t const& memoryState) { + template + void SparseModelMemoryProduct::addReachableState(uint64_t const& modelState, uint64_t const& memoryState) { reachableStates.set(modelState * memory.getNumberOfStates() + memoryState, true); } - template - void SparseModelMemoryProduct::setBuildFullProduct() { + template + void SparseModelMemoryProduct::setBuildFullProduct() { reachableStates.clear(); reachableStates.complement(); } - template - std::shared_ptr> SparseModelMemoryProduct::build(boost::optional> const& scheduler) { + template + std::shared_ptr> SparseModelMemoryProduct::build(boost::optional> const& scheduler) { uint64_t modelStateCount = model.getNumberOfStates(); uint64_t memoryStateCount = memory.getNumberOfStates(); @@ -70,7 +70,7 @@ namespace storm { transitionMatrix = buildNondeterministicTransitionMatrix(memorySuccessors); } storm::models::sparse::StateLabeling labeling = buildStateLabeling(transitionMatrix); - std::unordered_map> rewardModels = buildRewardModels(transitionMatrix, memorySuccessors, scheduler); + std::unordered_map rewardModels = buildRewardModels(transitionMatrix, memorySuccessors, scheduler); // Add the label for the initial states. We need to translate the state indices w.r.t. the set of reachable states. labeling.addLabel("init", initialStates % reachableStates); @@ -80,13 +80,13 @@ namespace storm { } - template - uint64_t const& SparseModelMemoryProduct::getResultState(uint64_t const& modelState, uint64_t const& memoryState) const { + template + uint64_t const& SparseModelMemoryProduct::getResultState(uint64_t const& modelState, uint64_t const& memoryState) const { return toResultStateMapping[modelState * memory.getNumberOfStates() + memoryState]; } - template - std::vector SparseModelMemoryProduct::computeMemorySuccessors() const { + template + std::vector SparseModelMemoryProduct::computeMemorySuccessors() const { uint64_t modelTransitionCount = model.getTransitionMatrix().getEntryCount(); uint64_t memoryStateCount = memory.getNumberOfStates(); std::vector result(modelTransitionCount * memoryStateCount, std::numeric_limits::max()); @@ -104,8 +104,8 @@ namespace storm { return result; } - template - void SparseModelMemoryProduct::computeReachableStates(std::vector const& memorySuccessors, storm::storage::BitVector const& initialStates, boost::optional> const& scheduler) { + template + void SparseModelMemoryProduct::computeReachableStates(std::vector const& memorySuccessors, storm::storage::BitVector const& initialStates, boost::optional> const& scheduler) { uint64_t memoryStateCount = memory.getNumberOfStates(); // Explore the reachable states via DFS. // A state s on the stack corresponds to the model state (s / memoryStateCount) and memory state (s % memoryStateCount) @@ -156,8 +156,8 @@ namespace storm { } } - template - storm::storage::SparseMatrix SparseModelMemoryProduct::buildDeterministicTransitionMatrix(std::vector const& memorySuccessors) const { + template + storm::storage::SparseMatrix SparseModelMemoryProduct::buildDeterministicTransitionMatrix(std::vector const& memorySuccessors) const { uint64_t memoryStateCount = memory.getNumberOfStates(); uint64_t numResStates = reachableStates.getNumberOfSetBits(); uint64_t numResTransitions = 0; @@ -182,8 +182,8 @@ namespace storm { return builder.build(); } - template - storm::storage::SparseMatrix SparseModelMemoryProduct::buildNondeterministicTransitionMatrix(std::vector const& memorySuccessors) const { + template + storm::storage::SparseMatrix SparseModelMemoryProduct::buildNondeterministicTransitionMatrix(std::vector const& memorySuccessors) const { uint64_t memoryStateCount = memory.getNumberOfStates(); uint64_t numResStates = reachableStates.getNumberOfSetBits(); uint64_t numResChoices = 0; @@ -216,8 +216,8 @@ namespace storm { return builder.build(); } - template - storm::storage::SparseMatrix SparseModelMemoryProduct::buildTransitionMatrixForScheduler(std::vector const& memorySuccessors, storm::storage::Scheduler const& scheduler) const { + template + storm::storage::SparseMatrix SparseModelMemoryProduct::buildTransitionMatrixForScheduler(std::vector const& memorySuccessors, storm::storage::Scheduler const& scheduler) const { uint64_t memoryStateCount = memory.getNumberOfStates(); uint64_t numResStates = reachableStates.getNumberOfSetBits(); uint64_t numResChoices = 0; @@ -311,8 +311,8 @@ namespace storm { return builder.build(); } - template - storm::models::sparse::StateLabeling SparseModelMemoryProduct::buildStateLabeling(storm::storage::SparseMatrix const& resultTransitionMatrix) const { + template + storm::models::sparse::StateLabeling SparseModelMemoryProduct::buildStateLabeling(storm::storage::SparseMatrix const& resultTransitionMatrix) const { uint64_t modelStateCount = model.getNumberOfStates(); uint64_t memoryStateCount = memory.getNumberOfStates(); @@ -351,16 +351,19 @@ namespace storm { return resultLabeling; } - template - std::unordered_map> SparseModelMemoryProduct::buildRewardModels(storm::storage::SparseMatrix const& resultTransitionMatrix, std::vector const& memorySuccessors, boost::optional> const& scheduler) const { - std::unordered_map> result; + template + std::unordered_map SparseModelMemoryProduct::buildRewardModels(storm::storage::SparseMatrix const& resultTransitionMatrix, std::vector const& memorySuccessors, boost::optional> const& scheduler) const { + + typedef typename RewardModelType::ValueType RewardValueType; + + std::unordered_map result; uint64_t memoryStateCount = memory.getNumberOfStates(); uint64_t numResStates = resultTransitionMatrix.getRowGroupCount(); for (auto const& rewardModel : model.getRewardModels()) { - boost::optional> stateRewards; + boost::optional> stateRewards; if (rewardModel.second.hasStateRewards()) { - stateRewards = std::vector(numResStates, storm::utility::zero()); + stateRewards = std::vector(numResStates, storm::utility::zero()); uint64_t modelState = 0; for (auto const& modelStateReward : rewardModel.second.getStateRewardVector()) { if (!storm::utility::isZero(modelStateReward)) { @@ -375,9 +378,9 @@ namespace storm { ++modelState; } } - boost::optional> stateActionRewards; + boost::optional> stateActionRewards; if (rewardModel.second.hasStateActionRewards()) { - stateActionRewards = std::vector(resultTransitionMatrix.getRowCount(), storm::utility::zero()); + stateActionRewards = std::vector(resultTransitionMatrix.getRowCount(), storm::utility::zero()); uint64_t modelState = 0; uint64_t modelRow = 0; for (auto const& modelStateActionReward : rewardModel.second.getStateActionRewardVector()) { @@ -402,9 +405,9 @@ namespace storm { ++modelRow; } } - boost::optional> transitionRewards; + boost::optional> transitionRewards; if (rewardModel.second.hasTransitionRewards()) { - storm::storage::SparseMatrixBuilder builder(resultTransitionMatrix.getRowCount(), resultTransitionMatrix.getColumnCount()); + storm::storage::SparseMatrixBuilder builder(resultTransitionMatrix.getRowCount(), resultTransitionMatrix.getColumnCount()); uint64_t stateIndex = 0; for (auto const& resState : toResultStateMapping) { if (resState < numResStates) { @@ -412,7 +415,7 @@ namespace storm { uint64_t memoryState = stateIndex % memoryStateCount; uint64_t rowGroupSize = resultTransitionMatrix.getRowGroupSize(resState); if (scheduler && scheduler->getChoice(modelState, memoryState).isDefined()) { - std::map rewards; + std::map rewards; for (uint64_t rowOffset = 0; rowOffset < rowGroupSize; ++rowOffset) { uint64_t modelRowIndex = model.getTransitionMatrix().getRowGroupIndices()[modelState] + rowOffset; auto transitionEntryIt = model.getTransitionMatrix().getRow(modelRowIndex).begin(); @@ -454,14 +457,14 @@ namespace storm { } transitionRewards = builder.build(); } - result.insert(std::make_pair(rewardModel.first, storm::models::sparse::StandardRewardModel(std::move(stateRewards), std::move(stateActionRewards), std::move(transitionRewards)))); + result.insert(std::make_pair(rewardModel.first, RewardModelType(std::move(stateRewards), std::move(stateActionRewards), std::move(transitionRewards)))); } return result; } - template - std::shared_ptr> SparseModelMemoryProduct::buildResult(storm::storage::SparseMatrix&& matrix, storm::models::sparse::StateLabeling&& labeling, std::unordered_map>&& rewardModels, boost::optional> const& scheduler) const { - storm::storage::sparse::ModelComponents> components (std::move(matrix), std::move(labeling), std::move(rewardModels)); + template + std::shared_ptr> SparseModelMemoryProduct::buildResult(storm::storage::SparseMatrix&& matrix, storm::models::sparse::StateLabeling&& labeling, std::unordered_map&& rewardModels, boost::optional> const& scheduler) const { + storm::storage::sparse::ModelComponents components (std::move(matrix), std::move(labeling), std::move(rewardModels)); if (model.isOfType(storm::models::ModelType::Ctmc)) { components.rateTransitions = true; @@ -472,8 +475,8 @@ namespace storm { std::vector resultExitRates; resultExitRates.reserve(components.transitionMatrix.getRowGroupCount()); storm::storage::BitVector resultMarkovianStates(numResStates, false); - auto const& modelExitRates = dynamic_cast const&>(model).getExitRates(); - auto const& modelMarkovianStates = dynamic_cast const&>(model).getMarkovianStates(); + auto const& modelExitRates = dynamic_cast const&>(model).getExitRates(); + auto const& modelMarkovianStates = dynamic_cast const&>(model).getMarkovianStates(); uint64_t stateIndex = 0; for (auto const& resState : toResultStateMapping) { @@ -502,9 +505,10 @@ namespace storm { return storm::utility::builder::buildModelFromComponents(resultType, std::move(components)); } - template class SparseModelMemoryProduct; - template class SparseModelMemoryProduct; - template class SparseModelMemoryProduct; + template class SparseModelMemoryProduct; + template class SparseModelMemoryProduct>; + template class SparseModelMemoryProduct; + template class SparseModelMemoryProduct; } } diff --git a/src/storm/storage/memorystructure/SparseModelMemoryProduct.h b/src/storm/storage/memorystructure/SparseModelMemoryProduct.h index b37527542..fb959daa5 100644 --- a/src/storm/storage/memorystructure/SparseModelMemoryProduct.h +++ b/src/storm/storage/memorystructure/SparseModelMemoryProduct.h @@ -21,11 +21,11 @@ namespace storm { * memory structure. * An exception is thrown if the state labelings are not disjoint. */ - template + template > class SparseModelMemoryProduct { public: - SparseModelMemoryProduct(storm::models::sparse::Model const& sparseModel, storm::storage::MemoryStructure const& memoryStructure); + SparseModelMemoryProduct(storm::models::sparse::Model const& sparseModel, storm::storage::MemoryStructure const& memoryStructure); // Enforces that the given model and memory state as well as the successor(s) are considered reachable -- even if they are not reachable from an initial state. void addReachableState(uint64_t const& modelState, uint64_t const& memoryState); @@ -34,7 +34,7 @@ namespace storm { void setBuildFullProduct(); // Invokes the building of the product under the specified scheduler (if given). - std::shared_ptr> build(boost::optional> const& scheduler = boost::none); + std::shared_ptr> build(boost::optional> const& scheduler = boost::none); // Retrieves the state of the resulting model that represents the given memory and model state. // Should only be called AFTER calling build(); @@ -60,10 +60,10 @@ namespace storm { // State labeling. Note: DOES NOT ADD A LABEL FOR THE INITIAL STATES storm::models::sparse::StateLabeling buildStateLabeling(storm::storage::SparseMatrix const& resultTransitionMatrix) const; // Reward models - std::unordered_map> buildRewardModels(storm::storage::SparseMatrix const& resultTransitionMatrix, std::vector const& memorySuccessors, boost::optional> const& scheduler) const; + std::unordered_map buildRewardModels(storm::storage::SparseMatrix const& resultTransitionMatrix, std::vector const& memorySuccessors, boost::optional> const& scheduler) const; // Builds the resulting model - std::shared_ptr> buildResult(storm::storage::SparseMatrix&& matrix, storm::models::sparse::StateLabeling&& labeling, std::unordered_map>&& rewardModels, boost::optional> const& scheduler) const; + std::shared_ptr> buildResult(storm::storage::SparseMatrix&& matrix, storm::models::sparse::StateLabeling&& labeling, std::unordered_map&& rewardModels, boost::optional> const& scheduler) const; // Maps (modelState * memoryStateCount) + memoryState to the state in the result that represents (memoryState,modelState) @@ -72,7 +72,7 @@ namespace storm { // Indicates which states are considered reachable. (s, m) is reachable if this BitVector is true at (s * memoryStateCount) + m storm::storage::BitVector reachableStates; - storm::models::sparse::Model const& model; + storm::models::sparse::Model const& model; storm::storage::MemoryStructure const& memory; };