Browse Source

more StateDuplicator

Former-commit-id: d98234a00e
tempestpy_adaptions
TimQu 9 years ago
parent
commit
dbac45d9be
  1. 4
      src/CMakeLists.txt
  2. 33
      src/modelchecker/multiobjective/helper/SparseMdpMultiObjectivePreprocessingHelper.cpp
  3. 24
      src/modelchecker/multiobjective/helper/SparseMultiObjectiveModelCheckerInformation.h
  4. 146
      src/transformer/StateDuplicator.h
  5. 100
      test/functional/transformer/StateDuplicatorTest.cpp

4
src/CMakeLists.txt

@ -32,7 +32,7 @@ file(GLOB_RECURSE STORM_PERMISSIVESCHEDULER_FILES ${PROJECT_SOURCE_DIR}/src/perm
file(GLOB STORM_MODELS_FILES ${PROJECT_SOURCE_DIR}/src/models/*.h ${PROJECT_SOURCE_DIR}/src/models/*.cpp)
file(GLOB_RECURSE STORM_MODELS_SPARSE_FILES ${PROJECT_SOURCE_DIR}/src/models/sparse/*.h ${PROJECT_SOURCE_DIR}/src/models/sparse/*.cpp)
file(GLOB_RECURSE STORM_MODELS_SYMBOLIC_FILES ${PROJECT_SOURCE_DIR}/src/models/symbolic/*.h ${PROJECT_SOURCE_DIR}/src/models/symbolic/*.cpp)
file(GLOB_RECURSE STORM_MODELTRANSFORMER_FILES ${PROJECT_SOURCE_DIR}/src/modeltransformer/*.h ${PROJECT_SOURCE_DIR}/src/modeltransformer/*.cpp)
file(GLOB_RECURSE STORM_TRANSFORMER_FILES ${PROJECT_SOURCE_DIR}/src/transformer/*.h ${PROJECT_SOURCE_DIR}/src/transformer/*.cpp)
file(GLOB STORM_PARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/*.h ${PROJECT_SOURCE_DIR}/src/parser/*.cpp)
file(GLOB_RECURSE STORM_PARSER_PRISMPARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/prismparser/*.h ${PROJECT_SOURCE_DIR}/src/parser/prismparser/*.cpp)
file(GLOB STORM_SETTINGS_FILES ${PROJECT_SOURCE_DIR}/src/settings/*.h ${PROJECT_SOURCE_DIR}/src/settings/*.cpp)
@ -89,7 +89,7 @@ source_group(permissiveschedulers FILES ${STORM_PERMISSIVESCHEDULER_FILES})
source_group(models FILES ${STORM_MODELS_FILES})
source_group(models\\sparse FILES ${STORM_MODELS_SPARSE_FILES})
source_group(models\\symbolic FILES ${STORM_MODELS_SYMBOLIC_FILES})
source_group(modeltransformer FILES ${STORM_MODELTRANSFORMER_FILES})
source_group(transformer FILES ${STORM_TRANSFORMER_FILES})
source_group(parser FILES ${STORM_PARSER_FILES})
source_group(parser\\prismparser FILES ${STORM_PARSER_PRISMPARSER_FILES})
source_group(settings FILES ${STORM_SETTINGS_FILES})

33
src/modelchecker/multiobjective/helper/SparseMdpMultiObjectivePreprocessingHelper.cpp

@ -6,6 +6,8 @@
#include "src/modelchecker/propositional/SparsePropositionalModelChecker.h"
#include "src/modelchecker/results/ExplicitQualitativeCheckResult.h"
#include "src/transformer/StateDuplicator.h"
#include "src/storage/BitVector.h"
#include "src/utility/macros.h"
@ -24,10 +26,7 @@ namespace storm {
Information info(std::move(originalModel));
//Initialize the state mapping.
info.getNewToOldStateMapping().reserve(info.getModel().getNumberOfStates());
for(uint_fast64_t state = 0; state < info.getModel().getNumberOfStates(); ++state){
info.getNewToOldStateMapping().push_back(state);
}
info.setNewToOldStateIndexMapping(storm::utility::vector::buildVectorForRange(0, info.getModel().getNumberOfStates()));
//Gather information regarding the individual objectives
if(!gatherObjectiveInformation(originalFormula, info)){
@ -201,13 +200,27 @@ namespace storm {
storm::storage::BitVector phiStates = mc.check(phiTask)->asExplicitQualitativeCheckResult().getTruthValuesVector();
storm::storage::BitVector psiStates = mc.check(psiTask)->asExplicitQualitativeCheckResult().getTruthValuesVector();
// modelUnfolder(info.model, (~phiStates) | psiStates)
// info.model = modelUnfolder.info()
// build info.stateMapping from modelUnfolder.stateMapping
// build stateaction reward vector
// insert it in the model information
auto duplicatorResult = storm::transformer::StateDuplicator<SparseMdpModelType>::transform(info.getModel(), ~phiStates | psiStates);
// duplicatorResult.newToOldStateIndexMapping now reffers to the indices of the model we had before preprocessing this formula.
// This might not be the actual original model.
for(auto & originalModelStateIndex : duplicatorResult.newToOldStateIndexMapping){
originalModelStateIndex = info.getNewToOldStateIndexMapping()[originalModelStateIndex];
}
info.setNewToOldStateIndexMapping(duplicatorResult.newToOldStateIndexMapping);
// build stateAction reward vector that gives (one*transitionProbability) reward whenever a transition leads from the firstCopy to a psiState
storm::storage::BitVector newPsiStates(duplicatorResult.model->getNumberOfStates(), false);
for(auto const& oldPsiState : psiStates){
//note that psiStates are always located in the second copy
newPsiStates.set(duplicatorResult.secondCopyOldToNewStateIndexMapping[oldPsiState], true);
}
std::vector<ValueType> objectiveRewards = duplicatorResult.model->getTransitionMatrix().getConstrainedRowGroupSumVector(duplicatorResult.firstCopy, newPsiStates);
if(info.areNegativeRewardsConsidered()){
storm::utility::vector::scaleVectorInPlace(objectiveRewards, -storm::utility::one<ValueType>());
}
// TODO
duplicatorResult.model->getRewardModels().insert(std::make_pair(currentObjective.rewardModelName, RewardModelType(boost::none, objectiveRewards)));
info.setModel(std::move(*duplicatorResult.model));
return success;
}

24
src/modelchecker/multiobjective/helper/SparseMultiObjectiveModelCheckerInformation.h

@ -36,18 +36,28 @@ namespace storm {
//Intentionally left empty
}
SparseModelType& getModel(){
return model;
void setModel(SparseModelType&& newModel){
model = newModel;
}
void setModel(SparseModelType const& newModel){
model = newModel;
}
SparseModelType const& getModel() const {
return model;
}
std::vector<uint_fast64_t>& getNewToOldStateMapping(){
return newToOldStateMapping;
void setNewToOldStateIndexMapping(std::vector<uint_fast64_t> const& newMapping){
newToOldStateIndexMapping = newMapping;
}
std::vector<uint_fast64_t>const& getNewToOldStateMapping() const{
return newToOldStateMapping;
void setNewToOldStateIndexMapping(std::vector<uint_fast64_t>&& newMapping){
newToOldStateIndexMapping = newMapping;
}
std::vector<uint_fast64_t>const& getNewToOldStateIndexMapping() const{
return newToOldStateIndexMapping;
}
bool areNegativeRewardsConsidered() {
@ -68,7 +78,7 @@ namespace storm {
private:
SparseModelType model;
std::vector<uint_fast64_t> newToOldStateMapping;
std::vector<uint_fast64_t> newToOldStateIndexMapping;
bool negativeRewardsConsidered;
std::vector<ObjectiveInformation> objectives;

146
src/modeltransformers/StateDuplicator.h → src/transformer/StateDuplicator.h

@ -1,36 +1,20 @@
#ifndef STORM_MDPTRIVIALSTATEELIMINATOR_H
#define STORM_MDPTRIVIALSTATEELIMINATOR_H
#ifndef STORM_TRANSFORMER_STATEDUPLICATOR_H
#define STORM_TRANSFORMER_STATEDUPLICATOR_H
#include "../utility/macros.h"
#include <chrono>
#include <memory>
#include <boost/optional.hpp>
#include "src/adapters/CarlAdapter.h"
#include "src/logic/Formulas.h"
#include "src/modelchecker/results/ExplicitQualitativeCheckResult.h"
#include "src/modelchecker/region/RegionCheckResult.h"
#include "src/modelchecker/propositional/SparsePropositionalModelChecker.h"
#include "src/models/sparse/StandardRewardModel.h"
#include "src/settings/SettingsManager.h"
#include "src/settings/modules/RegionSettings.h"
#include "src/solver/OptimizationDirection.h"
#include "src/storage/sparse/StateType.h"
#include "src/storage/FlexibleSparseMatrix.h"
#include "src/utility/constants.h"
#include "src/utility/graph.h"
#include "src/utility/macros.h"
#include "src/utility/vector.h"
#include "src/models/sparse/Dtmc.h"
#include "src/models/sparse/Mdp.h"
#include "src/models/sparse/Ctmc.h"
#include "src/models/sparse/MarkovAutomaton.h"
#include "src/exceptions/InvalidArgumentException.h"
#include "src/exceptions/InvalidPropertyException.h"
#include "src/exceptions/InvalidStateException.h"
#include "src/exceptions/InvalidSettingsException.h"
#include "src/exceptions/NotImplementedException.h"
#include "src/exceptions/UnexpectedException.h"
#include "src/exceptions/NotSupportedException.h"
#include "src/logic/FragmentSpecification.h"
namespace storm {
namespace transformer {
@ -39,14 +23,12 @@ namespace storm {
* Duplicates the state space of the given model and redirects the incoming transitions of gateStates of the first copy to the gateStates of the second copy.
* Only states reachable from the initial states are kept.
*/
<template ModelType>
template <typename SparseModelType>
class StateDuplicator {
public:
typedef typename SparseMdpModelType::ValueType ValueType;
typedef typename SparseMdpModelType::RewardModelType RewardModelType;
struct StateDuplicatorReturnType {
ModelType model; // The resulting model
std::shared_ptr<SparseModelType> model; // The resulting model
storm::storage::BitVector firstCopy; // The states of the resulting model that correspond to the first copy
storm::storage::BitVector secondCopy; // The states of the resulting model that correspond to the second copy
storm::storage::BitVector gateStates; // The gate states of the resulting model
@ -67,25 +49,42 @@ namespace storm {
* @param originalModel The model to be duplicated
* @param gateStates The states for which the incoming transitions are redirected
*/
static StateDuplicatorReturnType transform(ModelType const& originalModel, storm::storage::BitVector const& gateStates) {
static StateDuplicatorReturnType transform(SparseModelType const& originalModel, storm::storage::BitVector const& gateStates) {
STORM_LOG_DEBUG("Invoked state duplicator on model with " << originalModel.getNumberOfStates() << " states.");
StateDuplicatorReturnType result;
// Collect some data for the result
initializeTransformation(originalModel, gateStates, result);
// Transform the ingedients of the model
storm::storage::SparseMatrix<typename SparseModelType::ValueType> matrix = transformMatrix(originalModel.getTransitionMatrix(), result);
storm::models::sparse::StateLabeling labeling(matrix.getRowGroupCount());
for(auto const& label : originalModel.getStateLabeling().getLabels()){
storm::storage::BitVector newBitVectorForLabel = transformStateBitVector(originalModel.getStateLabeling().getStates(label), result);
if(label=="init"){
newBitVectorForLabel &=result.firstCopy;
}
labeling.addLabel(label, std::move(newBitVectorForLabel));
}
std::unordered_map<std::string, typename SparseModelType::RewardModelType> rewardModels;
for(auto const& rewardModel : originalModel.getRewardModels()){
rewardModels.insert(std::make_pair(rewardModel.first, transformRewardModel(rewardModel.second, originalModel.getTransitionMatrix().getRowGroupIndices(), result)));
}
boost::optional<std::vector<storm::models::sparse::LabelSet>> choiceLabeling;
if(originalModel.hasChoiceLabeling()){
choiceLabeling = transformActionValueVector<storm::models::sparse::LabelSet>(originalModel.getChoiceLabeling(), originalModel.getTransitionMatrix().getRowGroupIndices(), result);
}
storm::storage::SparseMatrix<ValueType> matrix = transformMatrix(originalModel.getTransitionMatrix(), originalModel, gateStates, result);
//TODO
result.model = std::make_shared<SparseModelType>(createTransformedModel(originalModel, result, matrix, labeling, rewardModels, choiceLabeling));
STORM_LOG_DEBUG("State duplicator is done. Resulting model has " << result.model->getNumberOfStates() << " states, where " << result.firstCopy.getNumberOfSetBits() << " are in the first copy.");
return result;
}
private:
static void initializeTransformation(ModelType const& originalModel, storm::storage::BitVector const& gateStates, StateDuplicatorReturnType& result) {
static void initializeTransformation(SparseModelType const& originalModel, storm::storage::BitVector const& gateStates, StateDuplicatorReturnType& result) {
storm::storage::BitVector noStates(originalModel.getNumberOfStates(), false)
storm::storage::BitVector noStates(originalModel.getNumberOfStates(), false);
// Get the states that are reachable without visiting a gateState
storm::storage::BitVector statesForFirstCopy = storm::utility::graph::getReachableStates(originalModel.getTransitionMatrix(), originalModel.getInitialStates(), ~gateStates, noStates);
@ -96,13 +95,13 @@ namespace storm {
result.reachableStates = statesForFirstCopy | statesForSecondCopy;
uint_fast64_t numStates = statesForFirstCopy.getNumberOfSetBits() + statesForSecondCopy.getNumberOfSetBits();
result.firstCopy = statesForFirstCopy % reachableStates; // only consider reachable states
result.firstCopy = statesForFirstCopy % result.reachableStates; // only consider reachable states
result.firstCopy.resize(numStates, false); // the new states do NOT belong to the first copy
result.secondCopy = (statesForSecondCopy & (~statesForFirstCopy)) % reachableStates; // only consider reachable states
result.secondCopy = (statesForSecondCopy & (~statesForFirstCopy)) % result.reachableStates; // only consider reachable states
result.secondCopy.resize(numStates, true); // the new states DO belong to the second copy
result.gateStates = gateStates;
gateStates.resize(numStates, false); // there are no duplicated gateStates
STORM_LOG_ASSERT((result.firstCopy^result.secondCopy).full()), "firstCopy and secondCopy do not partition the state space.");
result.gateStates.resize(numStates, false); // there are no duplicated gateStates
STORM_LOG_ASSERT((result.firstCopy^result.secondCopy).full(), "firstCopy and secondCopy do not partition the state space.");
// Get the state mappings.
// We initialize them with illegal values to assert that we don't get a valid
@ -111,7 +110,7 @@ namespace storm {
result.firstCopyOldToNewStateIndexMapping = std::vector<uint_fast64_t>(originalModel.getNumberOfStates(), std::numeric_limits<uint_fast64_t>::max());
result.secondCopyOldToNewStateIndexMapping = std::vector<uint_fast64_t>(originalModel.getNumberOfStates(), std::numeric_limits<uint_fast64_t>::max());
uint_fast64_t newState = 0;
for(auto const& oldState : reachableStates){
for(auto const& oldState : result.reachableStates){
result.newToOldStateIndexMapping[newState] = oldState;
if(statesForFirstCopy.get(oldState)){
result.firstCopyOldToNewStateIndexMapping[oldState] = newState;
@ -125,11 +124,30 @@ namespace storm {
for(auto const& oldState : result.duplicatedStates) {
result.newToOldStateIndexMapping[newState] = oldState;
result.secondCopyOldToNewStateIndexMapping[oldState] = newState;
++newState
++newState;
}
STORM_LOG_ASSERT(newState == numStates, "Unexpected state Indices");
}
template<typename ValueType = typename SparseModelType::ValueType, typename RewardModelType = typename SparseModelType::RewardModelType>
static typename std::enable_if<std::is_same<RewardModelType, storm::models::sparse::StandardRewardModel<ValueType>>::value, RewardModelType>::type
transformRewardModel(RewardModelType const& originalRewardModel, std::vector<uint_fast64_t> const& originalRowGroupIndices, StateDuplicatorReturnType const& result) {
boost::optional<std::vector<ValueType>> stateRewardVector;
boost::optional<std::vector<ValueType>> stateActionRewardVector;
boost::optional<storm::storage::SparseMatrix<ValueType>> transitionRewardMatrix;
if(originalRewardModel.hasStateRewards()){
stateRewardVector = transformStateValueVector(originalRewardModel.getStateRewardVector(), result);
}
if(originalRewardModel.hasStateActionRewards()){
stateActionRewardVector = transformActionValueVector(originalRewardModel.getStateActionRewardVector(), originalRowGroupIndices, result);
}
if(originalRewardModel.hasTransitionRewards()){
transitionRewardMatrix = transformMatrix(originalRewardModel.getTransitionRewardMatrix(), result);
}
return RewardModelType(std::move(stateRewardVector), std::move(stateActionRewardVector), std::move(transitionRewardMatrix));
}
template<typename ValueType = typename SparseModelType::ValueType>
static storm::storage::SparseMatrix<ValueType> transformMatrix(storm::storage::SparseMatrix<ValueType> const& originalMatrix, StateDuplicatorReturnType const& result) {
// Build the builder
uint_fast64_t numStates = result.newToOldStateIndexMapping.size();
@ -137,7 +155,7 @@ namespace storm {
uint_fast64_t numEntries = 0;
for(auto const& oldState : result.newToOldStateIndexMapping){
numRows += originalMatrix.getRowGroupSize(oldState);
numEntries += stateOccurrences * originalMatrix.getRowGroupEntryCount(oldState);
numEntries += originalMatrix.getRowGroupEntryCount(oldState);
}
storm::storage::SparseMatrixBuilder<ValueType> builder(numRows, numStates, numEntries, true, !originalMatrix.hasTrivialRowGrouping(), originalMatrix.hasTrivialRowGrouping() ? 0 : numStates);
@ -148,10 +166,14 @@ namespace storm {
builder.newRowGroup(newRow);
}
uint_fast64_t oldState = result.newToOldStateIndexMapping[newState];
const& correctOldToNewMapping = result.firstCopy.get(newState) ? result.firstCopyOldToNewStateIndexMapping : result.secondCopyOldToNewStateIndexMapping;
for (uint_fast64_t oldRow = originalMatrix.getRowGroupIndices()[oldState]; oldRow < originalMatrix.getRowGroupIndices()[oldState+1]; ++oldRow){
for(auto const& entry : originalMatrix.getRow(oldRow)){
builder.addNextValue(newRow, correctOldToNewMapping[entry.getColumn()], entry.getValue());
if(result.firstCopy.get(newState) && !result.gateStates.get(entry.getColumn())){
builder.addNextValue(newRow, result.firstCopyOldToNewStateIndexMapping[entry.getColumn()], entry.getValue());
} else {
builder.addNextValue(newRow, result.secondCopyOldToNewStateIndexMapping[entry.getColumn()], entry.getValue());
}
}
++newRow;
}
@ -160,6 +182,8 @@ namespace storm {
return builder.build();
}
template<typename ValueType = typename SparseModelType::ValueType>
static std::vector<ValueType> transformActionValueVector(std::vector<ValueType>const& originalVector, std::vector<uint_fast64_t> const& originalRowGroupIndices, StateDuplicatorReturnType const& result) {
uint_fast64_t numActions = 0;
for(auto const& oldState : result.newToOldStateIndexMapping){
@ -168,7 +192,7 @@ namespace storm {
std::vector<ValueType> v;
v.reserve(numActions);
for(auto const& oldState : result.newToOldStateIndexMapping){
for (uint_fast64_t oldAction = originalRowGroupIndices()[oldState]; oldAction < originaRowGroupIndices()[oldState+1]; ++oldAction){
for (uint_fast64_t oldAction = originalRowGroupIndices[oldState]; oldAction < originalRowGroupIndices[oldState+1]; ++oldAction){
v.push_back(originalVector[oldAction]);
}
}
@ -176,14 +200,15 @@ namespace storm {
return v;
}
template<typename ValueType = typename SparseModelType::ValueType>
static std::vector<ValueType> transformStateValueVector(std::vector<ValueType> const& originalVector, StateDuplicatorReturnType const& result) {
uint_fast64_t numStates = result.newToOldStateIndexMapping.size();
std::vector<ValueType> v;
result.reserve(numStates);
v.reserve(numStates);
for(auto const& oldState : result.newToOldStateIndexMapping){
v.push_back(originalVector[oldState]);
}
STORM_LOG_ASSERT(result.size() == numStates, "Unexpected vector size.");
STORM_LOG_ASSERT(v.size() == numStates, "Unexpected vector size.");
return v;
}
@ -198,7 +223,40 @@ namespace storm {
}
template<typename MT = SparseModelType>
static typename std::enable_if<
std::is_same<MT,storm::models::sparse::Dtmc<typename SparseModelType::ValueType>>::value ||
std::is_same<MT,storm::models::sparse::Mdp<typename SparseModelType::ValueType>>::value ||
std::is_same<MT,storm::models::sparse::Ctmc<typename SparseModelType::ValueType>>::value,
MT>::type
createTransformedModel(MT const& originalModel,
StateDuplicatorReturnType& result,
storm::storage::SparseMatrix<typename MT::ValueType>& matrix,
storm::models::sparse::StateLabeling& stateLabeling,
std::unordered_map<std::string,
typename MT::RewardModelType>& rewardModels,
boost::optional<std::vector<typename storm::models::sparse::LabelSet>>& choiceLabeling ) {
return MT(std::move(matrix), std::move(stateLabeling), std::move(rewardModels), std::move(choiceLabeling));
}
template<typename MT = SparseModelType>
static typename std::enable_if<
std::is_same<MT,storm::models::sparse::MarkovAutomaton<typename SparseModelType::ValueType>>::value,
MT>::type
createTransformedModel(MT const& originalModel,
StateDuplicatorReturnType& result,
storm::storage::SparseMatrix<typename MT::ValueType>& matrix,
storm::models::sparse::StateLabeling& stateLabeling,
std::unordered_map<std::string,
typename MT::RewardModelType>& rewardModels,
boost::optional<std::vector<typename storm::models::sparse::LabelSet>>& choiceLabeling ) {
storm::storage::BitVector markovianStates = transformStateBitVector(originalModel.getMarkovianStates(), result);
std::vector<typename MT::ValueType> exitRates = transformStateValueVector(originalModel.getExitRates(), result);
return MT(std::move(matrix), std::move(stateLabeling), std::move(markovianStates), std::move(exitRates), true, std::move(rewardModels), std::move(choiceLabeling));
}
};
}
}
#endif // STORM_TRANSFORMER_STATEDUPLICATOR_H

100
test/functional/transformer/StateDuplicatorTest.cpp

@ -0,0 +1,100 @@
#include "gtest/gtest.h"
#include "src/transformer/StateDuplicator.h"
TEST(StateDuplicator, SimpleModelTest) {
storm::storage::SparseMatrix<double> matrix;
storm::storage::SparseMatrixBuilder<double> builder(6, 4, 7, true, true, 4);
ASSERT_NO_THROW(builder.newRowGroup(0));
ASSERT_NO_THROW(builder.addNextValue(0, 0, 0.3));
ASSERT_NO_THROW(builder.addNextValue(0, 1, 0.7));
ASSERT_NO_THROW(builder.addNextValue(1, 3, 1.0));
ASSERT_NO_THROW(builder.newRowGroup(2));
ASSERT_NO_THROW(builder.addNextValue(2, 1, 1.0));
ASSERT_NO_THROW(builder.newRowGroup(3));
ASSERT_NO_THROW(builder.addNextValue(3, 0, 1.0));
ASSERT_NO_THROW(builder.newRowGroup(4));
ASSERT_NO_THROW(builder.addNextValue(4, 0, 1.0));
ASSERT_NO_THROW(builder.addNextValue(5, 3, 1.0));
ASSERT_NO_THROW(matrix = builder.build());
storm::models::sparse::StateLabeling labeling(4);
storm::storage::BitVector initStates(4);
initStates.set(0);
labeling.addLabel("init", initStates);
storm::storage::BitVector gateStates(4);
gateStates.set(3);
labeling.addLabel("gate", gateStates);
storm::storage::BitVector aStates(4);
aStates.set(0);
aStates.set(2);
labeling.addLabel("a", aStates);
storm::storage::BitVector bStates(4);
bStates.set(1);
bStates.set(3);
labeling.addLabel("b", bStates);
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<double>> rewardModels;
std::vector<double> stateReward = {1.0, 2.0, 3.0, 4.0};
std::vector<double> stateActionReward = {1.1, 1.2, 2.1, 3.1, 4.1, 4.2};
rewardModels.insert(std::make_pair("rewards", storm::models::sparse::StandardRewardModel<double>(stateReward, stateActionReward)));
storm::models::sparse::Mdp<double> model(matrix, labeling, rewardModels);
auto res = storm::transformer::StateDuplicator<storm::models::sparse::Mdp<double>>::transform(model, gateStates);
storm::storage::SparseMatrixBuilder<double> expectedBuilder(8, 5, 10, true, true, 5);
ASSERT_NO_THROW(expectedBuilder.newRowGroup(0));
ASSERT_NO_THROW(expectedBuilder.addNextValue(0, 0, 0.3));
ASSERT_NO_THROW(expectedBuilder.addNextValue(0, 1, 0.7));
ASSERT_NO_THROW(expectedBuilder.addNextValue(1, 2, 1.0));
ASSERT_NO_THROW(expectedBuilder.newRowGroup(2));
ASSERT_NO_THROW(expectedBuilder.addNextValue(2, 1, 1.0));
ASSERT_NO_THROW(expectedBuilder.newRowGroup(3));
ASSERT_NO_THROW(expectedBuilder.addNextValue(3, 3, 1.0));
ASSERT_NO_THROW(expectedBuilder.addNextValue(4, 2, 1.0));
ASSERT_NO_THROW(expectedBuilder.newRowGroup(5));
ASSERT_NO_THROW(expectedBuilder.addNextValue(5, 3, 0.3));
ASSERT_NO_THROW(expectedBuilder.addNextValue(5, 4, 0.7));
ASSERT_NO_THROW(expectedBuilder.addNextValue(6, 2, 1.0));
ASSERT_NO_THROW(expectedBuilder.newRowGroup(7));
ASSERT_NO_THROW(expectedBuilder.addNextValue(7, 4, 1.0));
ASSERT_NO_THROW(matrix = expectedBuilder.build());
EXPECT_EQ(matrix, res.model->getTransitionMatrix());
initStates.resize(5);
EXPECT_EQ(initStates, res.model->getInitialStates());
gateStates=storm::storage::BitVector(5);
gateStates.set(2);
EXPECT_EQ(gateStates, res.model->getStates("gate"));
aStates = initStates;
aStates.set(3);
EXPECT_EQ(aStates, res.model->getStates("a"));
bStates = ~aStates;
EXPECT_EQ(bStates, res.model->getStates("b"));
EXPECT_TRUE(res.model->hasRewardModel("rewards"));
EXPECT_TRUE(res.model->getRewardModel("rewards").hasStateRewards());
stateReward = {1.0, 2.0, 4.0, 1.0, 2.0};
EXPECT_EQ(stateReward, res.model->getRewardModel("rewards").getStateRewardVector());
EXPECT_TRUE(res.model->getRewardModel("rewards").hasStateActionRewards());
stateActionReward = {1.1, 1.2, 2.1, 4.1, 4.2, 1.1, 1.2, 2.1};
EXPECT_EQ(stateActionReward, res.model->getRewardModel("rewards").getStateActionRewardVector());
storm::storage::BitVector firstCopy(5);
firstCopy.set(0);
firstCopy.set(1);
EXPECT_EQ(firstCopy, res.firstCopy);
EXPECT_EQ(~firstCopy, res.secondCopy);
std::vector<uint_fast64_t> mapping = {0,1,3,0,1};
EXPECT_EQ(mapping, res.newToOldStateIndexMapping);
uint_fast64_t max = std::numeric_limits<uint_fast64_t>::max();
mapping = {0, 1, max, max};
EXPECT_EQ(mapping, res.firstCopyOldToNewStateIndexMapping);
mapping = {3, 4, max, 2};
EXPECT_EQ(mapping, res.secondCopyOldToNewStateIndexMapping);
}
Loading…
Cancel
Save