Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
TransitionToActionRewardTransformerTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
4#include <optional>
5
12#include "storm/api/storm.h"
22
23namespace {
24template<typename TransitionValueType, typename RewardValueType>
25std::shared_ptr<storm::models::sparse::Dtmc<TransitionValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>> buildDtmcWithTransitionRewards(
26 RewardValueType const& firstReward, RewardValueType const& secondReward) {
28 transitionBuilder.addNextValue(0, 2, storm::utility::one<TransitionValueType>());
29 transitionBuilder.addNextValue(1, 2, storm::utility::one<TransitionValueType>());
30 transitionBuilder.addNextValue(2, 2, storm::utility::one<TransitionValueType>());
31
33 rewardBuilder.addNextValue(0, 2, firstReward);
34 rewardBuilder.addNextValue(1, 2, secondReward);
35
37 labeling.addLabel("init");
38 labeling.addLabelToState("init", 0);
40 transitionBuilder.build(), std::move(labeling));
41 std::optional<storm::storage::SparseMatrix<RewardValueType>> transitionRewards(rewardBuilder.build());
42 components.rewardModels.emplace("rew",
43 storm::models::sparse::StandardRewardModel<RewardValueType>(std::nullopt, std::nullopt, std::move(transitionRewards)));
44 return std::make_shared<storm::models::sparse::Dtmc<TransitionValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>>(
45 std::move(components));
46}
47
48template<typename TransitionValueType, typename RewardValueType>
50 TransitionValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> const& transformed,
51 RewardValueType const& firstReward, RewardValueType const& secondReward) {
52 ASSERT_EQ(5ull, transformed.model->getNumberOfStates());
53 EXPECT_EQ((std::vector<uint64_t>{0, 1, 4}), transformed.originalToNewStateIndices);
54
55 auto const& transitionMatrix = transformed.model->getTransitionMatrix();
56 auto checkTransition = [&transitionMatrix](uint64_t row, uint64_t column) {
57 auto const rowEntries = transitionMatrix.getRow(row);
58 ASSERT_EQ(1ull, rowEntries.getNumberOfEntries());
59 auto const& entry = *rowEntries.begin();
60 EXPECT_EQ(column, entry.getColumn());
61 EXPECT_EQ(storm::utility::one<TransitionValueType>(), entry.getValue());
62 };
63 checkTransition(0, 2);
64 checkTransition(1, 3);
65 checkTransition(2, 4);
66 checkTransition(3, 4);
67 checkTransition(4, 4);
68
69 auto const& rewardModel = transformed.model->getRewardModel("rew");
70 ASSERT_TRUE(rewardModel.hasStateActionRewards());
71 ASSERT_FALSE(rewardModel.hasTransitionRewards());
72 auto const& actionRewards = rewardModel.getStateActionRewardVector();
73 ASSERT_EQ(5ull, actionRewards.size());
74 EXPECT_EQ(firstReward, actionRewards[2]);
75 EXPECT_EQ(secondReward, actionRewards[3]);
76}
77
78double computeInitialReward(std::shared_ptr<storm::models::sparse::Model<double>> const& model, std::string const& formulaString) {
79 auto const formula = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)).front();
80 auto const result = storm::api::verifyWithSparseEngine(model, storm::api::createTask<double>(formula, true));
81 return result->asExplicitQuantitativeCheckResult<double>()[*model->getInitialStates().begin()];
82}
83
84TEST(TransitionToActionRewardTransformerTest, DtmcDie) {
85 auto const model = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/dtmc/die.tra", STORM_TEST_RESOURCES_DIR "/dtmc/die.lab", "",
86 STORM_TEST_RESOURCES_DIR "/rew/die.coin_flips.trans.rew");
87
88 auto const transformed = storm::transformer::transformTransitionToActionRewards<double>(model, {""});
89
90 EXPECT_EQ(25ull, transformed.model->getNumberOfStates());
91 EXPECT_EQ(32ull, transformed.model->getNumberOfTransitions());
92 EXPECT_EQ((std::vector<uint64_t>{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24}), transformed.originalToNewStateIndices);
93 EXPECT_TRUE(transformed.model->getRewardModel("").hasStateActionRewards());
94 EXPECT_FALSE(transformed.model->getRewardModel("").hasTransitionRewards());
95
96 EXPECT_NEAR(11.0 / 3.0, computeInitialReward(transformed.model, "R=? [F \"done\"]"), 1e-6);
97}
98
99TEST(TransitionToActionRewardTransformerTest, CtmcDie) {
100 auto const model = std::make_shared<storm::models::sparse::Ctmc<double>>(storm::parser::DeterministicModelParser<>::parseCtmc(
101 STORM_TEST_RESOURCES_DIR "/tra/die.tra", STORM_TEST_RESOURCES_DIR "/lab/die.lab", "", STORM_TEST_RESOURCES_DIR "/rew/die.coin_flips.trans.rew"));
102
103 auto const transformed = storm::transformer::transformTransitionToActionRewards<double>(model, {""});
104
105 EXPECT_EQ(storm::models::ModelType::Ctmc, transformed.model->getType());
106 EXPECT_EQ(25ull, transformed.model->getNumberOfStates());
107 EXPECT_EQ(32ull, transformed.model->getNumberOfTransitions());
108 EXPECT_TRUE(transformed.model->getRewardModel("").hasStateActionRewards());
109 EXPECT_FALSE(transformed.model->getRewardModel("").hasTransitionRewards());
110
111 EXPECT_NEAR(11.0 / 3.0, computeInitialReward(transformed.model, "R=? [F \"done\"]"), 1e-6);
112}
113
114TEST(TransitionToActionRewardTransformerTest, MdpTwoDice) {
115 auto const model = storm::parser::AutoParser<>::parseModel(STORM_TEST_RESOURCES_DIR "/tra/two_dice.tra", STORM_TEST_RESOURCES_DIR "/lab/two_dice.lab", "",
116 STORM_TEST_RESOURCES_DIR "/rew/two_dice.flip.trans.rew");
117
118 auto const transformed = storm::transformer::transformTransitionToActionRewards<double>(model, {""});
119
120 EXPECT_EQ(storm::models::ModelType::Mdp, transformed.model->getType());
121 EXPECT_EQ(337ull, transformed.model->getNumberOfStates());
122 EXPECT_EQ(604ull, transformed.model->getNumberOfTransitions());
123 ASSERT_EQ(169ull, transformed.originalToNewStateIndices.size());
124 for (uint64_t state = 0; state < transformed.originalToNewStateIndices.size(); ++state) {
125 EXPECT_EQ(2 * state, transformed.originalToNewStateIndices[state]);
126 }
127 EXPECT_TRUE(transformed.model->getRewardModel("").hasStateActionRewards());
128 EXPECT_FALSE(transformed.model->getRewardModel("").hasTransitionRewards());
129
130 EXPECT_NEAR(22.0 / 3.0, computeInitialReward(transformed.model, "Rmin=? [F \"done\"]"), 1e-6);
131}
132
133TEST(TransitionToActionRewardTransformerTest, MarkovAutomatonGeneral) {
134 auto const model = std::make_shared<storm::models::sparse::MarkovAutomaton<double>>(storm::parser::MarkovAutomatonParser<>::parseMarkovAutomaton(
135 STORM_TEST_RESOURCES_DIR "/tra/ma_general.tra", STORM_TEST_RESOURCES_DIR "/lab/ma_general.lab", STORM_TEST_RESOURCES_DIR "/rew/ma_general.state.rew"));
136 auto transitionRewards = model->getTransitionMatrix();
137 for (auto& entry : transitionRewards) {
138 entry.setValue(1.0);
139 }
140 auto const stateRewards = model->getRewardModel("").getOptionalStateRewardVector();
141 model->getRewardModel("") = storm::models::sparse::StandardRewardModel<double>(std::move(stateRewards), std::nullopt, std::move(transitionRewards));
142
143 auto const transformed = storm::transformer::transformTransitionToActionRewards<double>(model, {""});
144
145 EXPECT_EQ(storm::models::ModelType::MarkovAutomaton, transformed.model->getType());
146 EXPECT_EQ(12ull, transformed.model->getNumberOfStates());
147 EXPECT_EQ(18ull, transformed.model->getNumberOfTransitions());
148 EXPECT_EQ((std::vector<uint64_t>{1, 3, 5, 7, 9, 11}), transformed.originalToNewStateIndices);
149 EXPECT_TRUE(transformed.model->getRewardModel("").hasStateActionRewards());
150 EXPECT_FALSE(transformed.model->getRewardModel("").hasTransitionRewards());
151
152 auto transformedMa = transformed.model->as<storm::models::sparse::MarkovAutomaton<double>>();
153 EXPECT_EQ(2ull, transformedMa->getMarkovianStates().getNumberOfSetBits());
154 EXPECT_TRUE(transformedMa->isMarkovianState(1));
155 EXPECT_EQ(2.0, transformedMa->getExitRate(1));
156 EXPECT_TRUE(transformedMa->isMarkovianState(5));
157 EXPECT_EQ(15.0, transformedMa->getExitRate(5));
158 for (uint64_t state = 0; state < transformedMa->getNumberOfStates(); state += 2) {
159 EXPECT_TRUE(transformedMa->isProbabilisticState(state));
160 }
161}
162
163TEST(TransitionToActionRewardTransformerTest, OverlappingIntervalRewardsAreNotMerged) {
164 storm::Interval const firstReward(1.0, 3.0);
165 storm::Interval const secondReward(2.0, 4.0);
166 auto const model = buildDtmcWithTransitionRewards<storm::Interval>(firstReward, secondReward);
167
169
170 checkTransformedDtmc(transformed, firstReward, secondReward);
171}
172
173TEST(TransitionToActionRewardTransformerTest, OverlappingRationalIntervalRewardsAreNotMerged) {
174 storm::RationalInterval const firstReward(storm::RationalNumber(1), storm::RationalNumber(3));
175 storm::RationalInterval const secondReward(storm::RationalNumber(2), storm::RationalNumber(4));
176 auto const model = buildDtmcWithTransitionRewards<storm::RationalInterval>(firstReward, secondReward);
177
179
180 checkTransformedDtmc(transformed, firstReward, secondReward);
181}
182
183TEST(TransitionToActionRewardTransformerTest, DoubleOverlappingIntervalRewardsAreNotMerged) {
184 storm::Interval const firstReward(1.0, 3.0);
185 storm::Interval const secondReward(2.0, 4.0);
186 auto const model = buildDtmcWithTransitionRewards<double>(firstReward, secondReward);
187
188 auto const transformed =
190
191 checkTransformedDtmc(transformed, firstReward, secondReward);
192}
193
194TEST(TransitionToActionRewardTransformerTest, RationalOverlappingRationalIntervalRewardsAreNotMerged) {
195 storm::RationalInterval const firstReward(storm::RationalNumber(1), storm::RationalNumber(3));
196 storm::RationalInterval const secondReward(storm::RationalNumber(2), storm::RationalNumber(4));
197 auto const model = buildDtmcWithTransitionRewards<storm::RationalNumber>(firstReward, secondReward);
198
199 auto const transformed =
201 model, {"rew"});
202
203 checkTransformedDtmc(transformed, firstReward, secondReward);
204}
205
206} // namespace
TEST(RegionConstraintCheckerTest, AffineConstraintHoldsThroughout)
This class represents a Markov automaton.
Base class for all sparse models.
Definition Model.h:34
This class manages the labeling of the state space with a number of (atomic) labels.
static std::shared_ptr< storm::models::sparse::Model< ValueType, storm::models::sparse::StandardRewardModel< RewardValueType > > > parseModel(std::string const &transitionsFilename, std::string const &labelingFilename, std::string const &stateRewardFilename="", std::string const &transitionRewardFilename="", std::string const &choiceLabelingFilename="", ExplicitModelParserOptions const &options=ExplicitModelParserOptions())
Checks the given files and parses the model within these files.
static storm::models::sparse::Ctmc< ValueType, storm::models::sparse::StandardRewardModel< RewardValueType > > parseCtmc(std::string const &transitionsFilename, std::string const &labelingFilename, std::string const &stateRewardFilename="", std::string const &transitionRewardFilename="", std::string const &choiceLabelingFilename="", ExplicitModelParserOptions const &options=ExplicitModelParserOptions())
Parse a Ctmc.
static storm::models::sparse::MarkovAutomaton< ValueType, storm::models::sparse::StandardRewardModel< RewardValueType > > parseMarkovAutomaton(std::string const &transitionsFilename, std::string const &labelingFilename, std::string const &stateRewardFilename="", std::string const &transitionRewardFilename="", std::string const &choiceLabelingFilename="", ExplicitModelParserOptions const &options=ExplicitModelParserOptions())
Parses the given Markov automaton and returns an object representing the automaton.
A class that can be used to build a sparse matrix by adding value by value.
storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > createTask(std::shared_ptr< const storm::logic::Formula > const &formula, bool onlyInitialStatesRelevant=false)
std::vector< std::shared_ptr< storm::logic::Formula const > > extractFormulasFromProperties(std::vector< storm::jani::Property > const &properties)
std::vector< storm::jani::Property > parseProperties(storm::parser::FormulaParser &formulaParser, std::string const &inputString, boost::optional< std::set< std::string > > const &propertyFilter)
std::unique_ptr< storm::modelchecker::CheckResult > verifyWithSparseEngine(storm::Environment const &env, std::shared_ptr< storm::models::sparse::Dtmc< ValueType > > const &dtmc, storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > const &task, bool preferEliminationChecker=false)
TransitionToActionRewardTransformerReturnType< ValueType, RewardModelType > transformTransitionToActionRewards(std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > originalModel, std::vector< std::string > const &relevantRewardModelNames)
Replaces transition branch rewards from all given reward models and replaces them by equivalent state...
ValueType one()
Definition constants.cpp:21
carl::Interval< storm::RationalNumber > RationalInterval
carl::Interval< double > Interval
Interval type.