Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ConditionalMdpPrctlModelCheckerTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
6#include "storm/api/builder.h"
12
13namespace {
14
15class SparseDoubleRestartEnvironment {
16 public:
17 static const bool isExact = false;
18 typedef double ValueType;
20 static storm::Environment createEnvironment() {
23 env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); // restart algorithm requires a higher precision
24 return env;
25 }
26};
27
28class SparseDoubleBisectionEnvironment {
29 public:
30 static const bool isExact = false;
31 typedef double ValueType;
33 static storm::Environment createEnvironment() {
36 return env;
37 }
38};
39
40class SparseDoubleBisectionAdvancedEnvironment {
41 public:
42 static const bool isExact = false;
43 typedef double ValueType;
45 static storm::Environment createEnvironment() {
48 return env;
49 }
50};
51
52class SparseDoublePiEnvironment {
53 public:
54 static const bool isExact = false;
55 typedef double ValueType;
57 static storm::Environment createEnvironment() {
60 return env;
61 }
62};
63
64class SparseRationalNumberRestartEnvironment {
65 public:
66 static const bool isExact = true;
67 typedef storm::RationalNumber ValueType;
69 static storm::Environment createEnvironment() {
72 env.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(1e-10)); // restart algorithm requires a higher precision
73 return env;
74 }
75};
76
77class SparseRationalNumberBisectionEnvironment {
78 public:
79 static const bool isExact = true;
80 typedef storm::RationalNumber ValueType;
82 static storm::Environment createEnvironment() {
85 return env;
86 }
87};
88
89class SparseRationalNumberBisectionAdvancedEnvironment {
90 public:
91 static const bool isExact = true;
92 typedef storm::RationalNumber ValueType;
94 static storm::Environment createEnvironment() {
97 return env;
98 }
99};
100
101class SparseRationalNumberPiEnvironment {
102 public:
103 static const bool isExact = true;
104 typedef storm::RationalNumber ValueType;
106 static storm::Environment createEnvironment() {
109 return env;
110 }
111};
112
113template<typename TestType>
114class ConditionalMdpPrctlModelCheckerTest : public ::testing::Test {
115 public:
116 typedef typename TestType::ValueType ValueType;
117 typedef typename storm::models::sparse::Mdp<ValueType> SparseModelType;
118
119 ConditionalMdpPrctlModelCheckerTest() : _environment(TestType::createEnvironment()) {}
120
121 void SetUp() override {
122#ifndef STORM_HAVE_Z3
123 GTEST_SKIP() << "Z3 not available.";
124#endif
125 }
126
127 storm::Environment const& env() const {
128 return _environment;
129 }
130 ValueType parseNumber(std::string const& input) const {
131 return storm::utility::convertNumber<ValueType>(input);
132 }
133 ValueType precision() const {
134 return TestType::isExact ? parseNumber("0") : parseNumber("1e-6");
135 }
136 bool isSparseModel() const {
137 return std::is_same<typename TestType::ModelType, SparseModelType>::value;
138 }
139
140 std::pair<std::shared_ptr<SparseModelType>, std::vector<std::shared_ptr<storm::logic::Formula const>>> buildModelFormulas(
141 storm::prism::Program const& inputProgram, std::string const& formulasAsString, std::string const& constantDefinitionString = "") const {
142 std::pair<std::shared_ptr<SparseModelType>, std::vector<std::shared_ptr<storm::logic::Formula const>>> result;
143 auto program = storm::utility::prism::preprocess(inputProgram, constantDefinitionString);
145 result.first = storm::api::buildSparseModel<ValueType>(program, result.second)->template as<SparseModelType>();
146 return result;
147 }
148
149 std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> getTasks(
150 std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) const {
151 std::vector<storm::modelchecker::CheckTask<storm::logic::Formula, ValueType>> result;
152 for (auto const& f : formulas) {
153 result.emplace_back(*f, true); // Set onlyInitialStatesRelevant to true for conditional tasks
154 }
155 return result;
156 }
157
158 private:
159 storm::Environment _environment;
160};
161
162typedef ::testing::Types<SparseDoubleRestartEnvironment, SparseDoubleBisectionEnvironment, SparseDoubleBisectionAdvancedEnvironment, SparseDoublePiEnvironment,
163 SparseRationalNumberRestartEnvironment, SparseRationalNumberBisectionEnvironment, SparseRationalNumberBisectionAdvancedEnvironment,
164 SparseRationalNumberPiEnvironment>
166
167TYPED_TEST_SUITE(ConditionalMdpPrctlModelCheckerTest, TestingTypes, );
168
169TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, two_dice) {
170 typedef typename TestFixture::ValueType ValueType;
171
172 std::string const formulasString =
173 "Pmax=? [F \"twelve\" || F d1=6];"
174 "Pmin=? [F \"twelve\" || F d1=6];"
175 "Pmax=? [F \"seven\" || F d2=4];"
176 "Pmin=? [F \"seven\" || F d2=4];"
177 "Pmax=? [F \"two\" || F d2=2];"
178 "Pmin=? [F \"two\" || F d2=2];"
179 "Pmax=? [F d1=6 || F \"twelve\"];"
180 "Pmin=? [F d1=6 || F \"twelve\"];";
181
182 auto program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/mdp/two_dice.nm");
183 auto modelFormulas = this->buildModelFormulas(program, formulasString);
184 auto model = std::move(modelFormulas.first);
185 auto tasks = this->getTasks(modelFormulas.second);
186 EXPECT_EQ(169ul, model->getNumberOfStates());
187 EXPECT_EQ(436ul, model->getNumberOfTransitions());
188 ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
189 auto mdp = model->template as<storm::models::sparse::Mdp<ValueType>>();
191
192 auto result = checker.check(this->env(), tasks[0])->template asExplicitQuantitativeCheckResult<ValueType>();
193 EXPECT_NEAR(this->parseNumber("1/6"), result[*mdp->getInitialStates().begin()], this->precision());
194 result = checker.check(this->env(), tasks[1])->template asExplicitQuantitativeCheckResult<ValueType>();
195 EXPECT_NEAR(this->parseNumber("1/6"), result[*mdp->getInitialStates().begin()], this->precision());
196 result = checker.check(this->env(), tasks[2])->template asExplicitQuantitativeCheckResult<ValueType>();
197 EXPECT_NEAR(this->parseNumber("1/6"), result[*mdp->getInitialStates().begin()], this->precision());
198 result = checker.check(this->env(), tasks[3])->template asExplicitQuantitativeCheckResult<ValueType>();
199 EXPECT_NEAR(this->parseNumber("1/6"), result[*mdp->getInitialStates().begin()], this->precision());
200 result = checker.check(this->env(), tasks[4])->template asExplicitQuantitativeCheckResult<ValueType>();
201 EXPECT_NEAR(this->parseNumber("0"), result[*mdp->getInitialStates().begin()], this->precision());
202 result = checker.check(this->env(), tasks[5])->template asExplicitQuantitativeCheckResult<ValueType>();
203 EXPECT_NEAR(this->parseNumber("0"), result[*mdp->getInitialStates().begin()], this->precision());
204 result = checker.check(this->env(), tasks[6])->template asExplicitQuantitativeCheckResult<ValueType>();
205 EXPECT_NEAR(this->parseNumber("1"), result[*mdp->getInitialStates().begin()], this->precision());
206 result = checker.check(this->env(), tasks[7])->template asExplicitQuantitativeCheckResult<ValueType>();
207 EXPECT_NEAR(this->parseNumber("1"), result[*mdp->getInitialStates().begin()], this->precision());
208}
209
210TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, consensus) {
211 typedef typename TestFixture::ValueType ValueType;
212
213 std::string const formulasString =
214 "Pmax=? [F \"all_coins_equal_0\" & \"finished\" || F \"agree\" & \"finished\"];"
215 "Pmin=? [F \"all_coins_equal_0\" & \"finished\" || F \"agree\" & \"finished\"];"
216 "Pmax=? [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];"
217 "Pmin=? [F \"all_coins_equal_1\" & \"finished\" || F \"agree\" & \"finished\"];";
218
219 auto program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm");
220 auto modelFormulas = this->buildModelFormulas(program, formulasString);
221 auto model = std::move(modelFormulas.first);
222 auto tasks = this->getTasks(modelFormulas.second);
223 EXPECT_EQ(272ul, model->getNumberOfStates());
224 EXPECT_EQ(492ul, model->getNumberOfTransitions());
225 ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
226 auto mdp = model->template as<storm::models::sparse::Mdp<ValueType>>();
228
229 auto result = checker.check(this->env(), tasks[0])->template asExplicitQuantitativeCheckResult<ValueType>();
230 EXPECT_NEAR(this->parseNumber("561/953"), result[*mdp->getInitialStates().begin()], this->precision());
231 result = checker.check(this->env(), tasks[1])->template asExplicitQuantitativeCheckResult<ValueType>();
232 EXPECT_NEAR(this->parseNumber("392/953"), result[*mdp->getInitialStates().begin()], this->precision());
233 result = checker.check(this->env(), tasks[2])->template asExplicitQuantitativeCheckResult<ValueType>();
234 EXPECT_NEAR(this->parseNumber("561/953"), result[*mdp->getInitialStates().begin()], this->precision());
235 result = checker.check(this->env(), tasks[3])->template asExplicitQuantitativeCheckResult<ValueType>();
236 EXPECT_NEAR(this->parseNumber("392/953"), result[*mdp->getInitialStates().begin()], this->precision());
237}
238
239TYPED_TEST(ConditionalMdpPrctlModelCheckerTest, simple) {
240 typedef typename TestFixture::ValueType ValueType;
241
242 std::string const programAsString = R"(mdp
243module main
244 x : [0..2];
245 [] x=0 -> 0.7 : (x'=1) + 0.3 : (x'=2);
246 [] x=1 -> 1 : (x'=1);
247 [] x=2 -> 1 : (x'=1);
248endmodule
249)";
250
251 std::string const formulasString =
252 "Pmin=? [F x=2 || F x=1];"
253 "Pmax=? [F x=2 || F x=1];";
254
255 auto program = storm::parser::PrismParser::parseFromString(programAsString, "<no filename>");
256 auto modelFormulas = this->buildModelFormulas(program, formulasString);
257 auto model = std::move(modelFormulas.first);
258 auto tasks = this->getTasks(modelFormulas.second);
259 EXPECT_EQ(3ul, model->getNumberOfStates());
260 EXPECT_EQ(4ul, model->getNumberOfTransitions());
261 ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
262 auto mdp = model->template as<storm::models::sparse::Mdp<ValueType>>();
264
265 auto result = checker.check(this->env(), tasks[0])->template asExplicitQuantitativeCheckResult<ValueType>();
266 EXPECT_NEAR(this->parseNumber("3/10"), result[*mdp->getInitialStates().begin()], this->precision());
267 result = checker.check(this->env(), tasks[1])->template asExplicitQuantitativeCheckResult<ValueType>();
268 EXPECT_NEAR(this->parseNumber("3/10"), result[*mdp->getInitialStates().begin()], this->precision());
269}
270
271} // namespace
SolverEnvironment & solver()
ModelCheckerEnvironment & modelchecker()
void setPrecision(storm::RationalNumber value)
void setConditionalAlgorithmSetting(ConditionalAlgorithmSetting value)
MinMaxSolverEnvironment & minMax()
This class represents a (discrete-time) Markov decision process.
Definition Mdp.h:13
static storm::prism::Program parseFromString(std::string const &input, std::string const &filename, bool prismCompatability=false)
Parses the given input stream into the PRISM storage classes assuming it complies with the PRISM synt...
static storm::prism::Program parse(std::string const &filename, bool prismCompatability=false)
Parses the given file into the PRISM storage classes assuming it complies with the PRISM syntax.
std::vector< storm::jani::Property > parsePropertiesForPrismProgram(std::string const &inputString, storm::prism::Program const &program, boost::optional< std::set< std::string > > const &propertyFilter)
std::vector< std::shared_ptr< storm::logic::Formula const > > extractFormulasFromProperties(std::vector< storm::jani::Property > const &properties)
SFTBDDChecker::ValueType ValueType
NumberType parseNumber(std::string const &value)
Parse number from string.
storm::prism::Program preprocess(storm::prism::Program const &program, std::map< storm::expressions::Variable, storm::expressions::Expression > const &constantDefinitions)
Definition prism.cpp:19
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
Definition GraphTest.cpp:62
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes
Definition GraphTest.cpp:59