Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
MultiObjectiveSchedRestModelCheckerTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
5#include "storm/api/storm.h"
15
16#ifdef STORM_HAVE_Z3_OPTIMIZE
17
18namespace {
19
20class FlowBigMEnvironment {
21 public:
22 static storm::Environment getEnv() {
26 env.modelchecker().multi().setUseBsccOrderEncoding(false); // not relevant for Flow
27 env.modelchecker().multi().setUseRedundantBsccConstraints(false); // not relevant for Flow
28 return env;
29 }
30};
31
32class FlowIndicatorEnvironment {
33 public:
34 static storm::Environment getEnv() {
38 env.modelchecker().multi().setUseBsccOrderEncoding(false); // not relevant for Flow
39 env.modelchecker().multi().setUseRedundantBsccConstraints(false); // not relevant for Flow
40 return env;
41 }
42};
43
44class BigMEnvironment {
45 public:
46 static storm::Environment getEnv() {
52 return env;
53 }
54};
55
56class IndicatorEnvironment {
57 public:
58 static storm::Environment getEnv() {
64 return env;
65 }
66};
67
68class BigMOrderEnvironment {
69 public:
70 static storm::Environment getEnv() {
76 return env;
77 }
78};
79
80class IndicatorOrderEnvironment {
81 public:
82 static storm::Environment getEnv() {
88 return env;
89 }
90};
91
92class RedundantEnvironment {
93 public:
94 static storm::Environment getEnv() {
100 return env;
101 }
102};
103
104class RedundantOrderEnvironment {
105 public:
106 static storm::Environment getEnv() {
112 return env;
113 }
114};
115
116template<typename TestType>
117class MultiObjectiveSchedRestModelCheckerTest : public ::testing::Test {
118 public:
119 typedef storm::RationalNumber ValueType;
120
121 bool isFlowEncoding() const {
122 return TestType::getEnv().modelchecker().multi().getEncodingType() == storm::MultiObjectiveModelCheckerEnvironment::EncodingType::Flow;
123 }
124
125 storm::Environment getPositionalDeterministicEnvironment() {
126 auto env = TestType::getEnv();
127 env.modelchecker().multi().setSchedulerRestriction(storm::storage::SchedulerClass().setPositional().setIsDeterministic());
128 return env;
129 }
130
131 storm::Environment getGoalDeterministicEnvironment() {
132 auto env = TestType::getEnv();
135 return env;
136 }
137
138 typedef std::vector<storm::RationalNumber> Point;
139
140 ValueType parseNumber(std::string const& input) const {
141 return storm::utility::convertNumber<ValueType>(input);
142 }
143
144 std::vector<Point> parsePoints(std::vector<std::string> const& input) {
145 std::vector<Point> result;
146 for (auto const& i : input) {
147 Point currPoint;
148 std::size_t pos1 = 0;
149 std::size_t pos2 = i.find(",");
150 while (pos2 != std::string::npos) {
151 currPoint.push_back(parseNumber(i.substr(pos1, pos2 - pos1)));
152 pos1 = pos2 + 1;
153 pos2 = i.find(",", pos1);
154 }
155 currPoint.push_back(parseNumber(i.substr(pos1)));
156 result.push_back(currPoint);
157 }
158 return result;
159 }
160
161 std::set<Point> setMinus(std::vector<Point> const& lhs, std::vector<Point> const& rhs) {
162 std::set<Point> result(lhs.begin(), lhs.end());
163 for (auto const& r : rhs) {
164 for (auto lIt = result.begin(); lIt != result.end(); ++lIt) {
165 if (*lIt == r) {
166 result.erase(lIt);
167 break;
168 }
169 }
170 }
171 return result;
172 }
173
174 std::string toString(Point point, bool asDouble) {
175 std::stringstream s;
176 s << "[";
177 bool first = true;
178 for (auto const& pi : point) {
179 if (first) {
180 first = false;
181 } else {
182 s << ", ";
183 }
184 if (asDouble) {
185 s << storm::utility::convertNumber<double>(pi);
186 } else {
187 s << pi;
188 }
189 }
190 s << "]";
191 return s.str();
192 }
193
194 std::string getDiffString(std::vector<Point> const& expected, std::vector<Point> const& actual) {
195 std::stringstream stream;
196 stream << "Unexpected set of Points:\n";
197 stream << " Expected | Actual | Point\n";
198 for (auto const& p : expected) {
199 if (std::find(actual.begin(), actual.end(), p) != actual.end()) {
200 stream << " yes | yes | " << toString(p, true) << "\n";
201 } else {
202 stream << " --> yes | no | " << toString(p, true) << "\n";
203 }
204 }
205 for (auto const& p : actual) {
206 if (std::find(expected.begin(), expected.end(), p) == expected.end()) {
207 stream << " --> no | yes | " << toString(p, true) << "\n";
208 }
209 }
210 return stream.str();
211 }
212
213 bool isSame(std::vector<Point> const& expected, std::vector<Point> const& actual, std::string& diffString) {
214 if (expected.size() != actual.size()) {
215 diffString = getDiffString(expected, actual);
216 return false;
217 }
218 for (auto const& p : expected) {
219 if (std::find(actual.begin(), actual.end(), p) == actual.end()) {
220 diffString = getDiffString(expected, actual);
221 return false;
222 }
223 }
224 diffString = "";
225 return true;
226 }
227
228 template<typename SparseModelType>
229 bool testParetoFormula(storm::Environment const& env, SparseModelType const& model, storm::logic::Formula const& formula,
230 std::vector<Point> const& expected, std::string& errorString) {
232 if (!result->isParetoCurveCheckResult()) {
233 errorString = "Not a ParetoCurveCheckResult";
234 return false;
235 }
236 return isSame(expected, result->template asExplicitParetoCurveCheckResult<ValueType>().getPoints(), errorString);
237 }
238};
239
240typedef ::testing::Types<FlowBigMEnvironment, FlowIndicatorEnvironment, BigMEnvironment, IndicatorEnvironment, BigMOrderEnvironment, IndicatorOrderEnvironment,
241 RedundantEnvironment, RedundantOrderEnvironment>
243
244TYPED_TEST_SUITE(MultiObjectiveSchedRestModelCheckerTest, TestingTypes, );
245
246TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) {
247 typedef typename TestFixture::ValueType ValueType;
248
249 std::string programFile = STORM_TEST_RESOURCES_DIR "/mdp/multiobj_stairs.nm";
250 std::string constantsString = "N=3";
251 std::string formulasAsString = "multi(Pmax=? [ F y=1], Pmax=? [ F y=2 ]);";
252 formulasAsString += "multi(P>=0.375 [ F y=1], Pmax>=0.5 [ F y=2 ]);";
253 formulasAsString += "multi(P>=0.4 [ F y=1], Pmax>=0.4 [ F y=2 ]);";
254 formulasAsString += "multi(Pmax=? [ F y=1], Pmax>=0.4 [ F y=2 ]);";
255 formulasAsString += "multi(Pmax=? [ F y=1], Pmax>=0.9 [ F y=2 ]);";
256
257 // programm, model, formula
258 storm::prism::Program program = storm::api::parseProgram(programFile);
259 program = storm::utility::prism::preprocess(program, constantsString);
260 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas =
262 std::shared_ptr<storm::models::sparse::Mdp<ValueType>> mdp =
263 storm::api::buildSparseModel<ValueType>(program, formulas)->template as<storm::models::sparse::Mdp<ValueType>>();
264 std::string errorString; // storage for error reporting
265
266 storm::Environment env = this->getPositionalDeterministicEnvironment();
267 uint64_t formulaIndex = 0;
268 {
269 auto expected = this->parsePoints({"0.875,0", "0,0.875", "0.125,0.75", "0.25,0.625", "0.375,0.5", "0.5,0.375", "0.625,0.25", "0.75,0.125"});
270 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
271 }
272 ++formulaIndex;
273 {
274 auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula());
275 ASSERT_TRUE(result->isExplicitQualitativeCheckResult());
276 EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]);
277 }
278 ++formulaIndex;
279 {
280 auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula());
281 ASSERT_TRUE(result->isExplicitQualitativeCheckResult());
282 EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]);
283 }
284 ++formulaIndex;
285 {
286 auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula());
287 ASSERT_TRUE(result->isExplicitQuantitativeCheckResult());
288 auto expected = storm::utility::convertNumber<ValueType, std::string>("0.375");
289 EXPECT_EQ(result->template asExplicitQuantitativeCheckResult<ValueType>()[*mdp->getInitialStates().begin()], expected);
290 }
291 ++formulaIndex;
292 {
293 auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula());
294 ASSERT_TRUE(result->isExplicitQualitativeCheckResult());
295 EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]);
296 }
297}
298
299TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) {
300 typedef typename TestFixture::ValueType ValueType;
301 typedef typename TestFixture::Point Point;
302 std::string programFile = STORM_TEST_RESOURCES_DIR "/mdp/multiobj_mecs.nm";
303 std::string constantsString = "";
304 std::string formulasAsString = "multi(Pmin=? [ F x=3], Pmax=? [ F x=4 ]);";
305 formulasAsString += "\nmulti(R{\"test\"}min=? [C], Pmin=? [F \"t1\"]);";
306 formulasAsString += "\nmulti(R{\"test\"}min=? [C], Pmin=? [F \"t2\"]);";
307 formulasAsString += "\nmulti(R{\"test\"}min=? [C], Pmin=? [F \"t2\"], Pmax=? [F \"t1\"]);";
308 formulasAsString += "\nmulti(R{\"test\"}<=0 [C], P<=1 [F \"t2\"], P>=0 [F \"t1\"]);";
309 formulasAsString += "\nmulti(R{\"test\"}<=1 [C], P<=1 [F \"t2\"], P>=0.1 [F \"t1\"]);";
310 // programm, model, formula
311 storm::prism::Program program = storm::api::parseProgram(programFile);
312 program = storm::utility::prism::preprocess(program, constantsString);
313 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas =
315 std::shared_ptr<storm::models::sparse::Mdp<ValueType>> mdp =
316 storm::api::buildSparseModel<ValueType>(program, formulas)->template as<storm::models::sparse::Mdp<ValueType>>();
317 std::string errorString; // storage for error reporting
318 std::vector<Point> expected;
319
320 storm::Environment env = this->getPositionalDeterministicEnvironment();
321
322 uint64_t formulaIndex = 0;
323 expected = this->parsePoints({"0.5,0.5", "1,1"});
324 if (this->isFlowEncoding()) {
325 STORM_SILENT_EXPECT_THROW(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString),
326 storm::exceptions::InvalidOperationException);
327 } else {
328 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
329 }
330
331 ++formulaIndex;
332 expected = this->parsePoints({"0,0"});
333 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
334
335 ++formulaIndex;
336 expected = this->parsePoints({"0,1"});
337 if (this->isFlowEncoding()) {
338 STORM_SILENT_EXPECT_THROW(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString),
339 storm::exceptions::InvalidOperationException);
340 } else {
341 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
342 }
343
344 ++formulaIndex;
345 expected = this->parsePoints({"0,1,0", "2,1,1"});
346 if (this->isFlowEncoding()) {
347 STORM_SILENT_EXPECT_THROW(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString),
348 storm::exceptions::InvalidOperationException);
349 } else {
350 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
351 }
352 ++formulaIndex;
353 {
354 if (this->isFlowEncoding()) {
356 storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()),
357 storm::exceptions::InvalidOperationException);
358 } else {
359 auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula());
360 ASSERT_TRUE(result->isExplicitQualitativeCheckResult());
361 EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]);
362 }
363 }
364 ++formulaIndex;
365 {
366 if (this->isFlowEncoding()) {
368 storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()),
369 storm::exceptions::InvalidOperationException);
370 } else {
371 auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula());
372 ASSERT_TRUE(result->isExplicitQualitativeCheckResult());
373 EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]);
374 }
375 }
376}
377
378TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, compromise) {
379 typedef typename TestFixture::ValueType ValueType;
380 typedef typename TestFixture::Point Point;
381 std::string programFile = STORM_TEST_RESOURCES_DIR "/mdp/multiobj_compromise.nm";
382 std::string constantsString = "";
383 std::string formulasAsString = "multi(Pmax=? [ F x=1], Pmax=? [ F x=2 ]);";
384 formulasAsString += "\nmulti(R{\"test\"}min=? [F x=1], Pmax=? [F x=1 ]);";
385 formulasAsString += "\nmulti(Pmax=? [F x=1], Pmax=? [F x=2 ], Pmax=? [F x=3 ]);";
386 formulasAsString += "\nmulti(R{\"test\"}min=? [C], Pmin=? [F x=2 ], Pmin=? [F x=3]);";
387 // programm, model, formula
388 storm::prism::Program program = storm::api::parseProgram(programFile);
389 program = storm::utility::prism::preprocess(program, constantsString);
390 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas =
392 std::shared_ptr<storm::models::sparse::Mdp<ValueType>> mdp =
393 storm::api::buildSparseModel<ValueType>(program, formulas)->template as<storm::models::sparse::Mdp<ValueType>>();
394 std::string errorString; // storage for error reporting
395 std::vector<Point> expected;
396
397 storm::Environment env = this->getPositionalDeterministicEnvironment();
398
399 uint64_t formulaIndex = 0;
400 expected = this->parsePoints({"1,0", "0,1", "0.3,3/7"});
401 if (this->isFlowEncoding()) {
402 STORM_SILENT_EXPECT_THROW(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString),
403 storm::exceptions::InvalidOperationException);
404 } else {
405 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
406 }
407
408 ++formulaIndex;
409 expected = this->parsePoints({"0,0.3", "2,1"});
410 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
411
412 ++formulaIndex;
413 expected = this->parsePoints({"1,0,0", "0,1,0", "0.3,3/7,4/7"});
414 if (this->isFlowEncoding()) {
415 STORM_SILENT_EXPECT_THROW(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString),
416 storm::exceptions::InvalidOperationException);
417 } else {
418 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
419 }
420
421 ++formulaIndex;
422 expected = this->parsePoints({"0,1,0", "0,3/7,4/7"});
423 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
424
425 env = this->getGoalDeterministicEnvironment();
426
427 formulaIndex = 0;
428 expected = this->parsePoints({"1,1"});
429 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
430
431 ++formulaIndex;
432 expected = this->parsePoints({"0,0.3", "2,1"});
433 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
434
435 ++formulaIndex;
436 expected = this->parsePoints({"1,1,0", "1,3/7,4/7"});
437 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
438
439 ++formulaIndex;
440 expected = this->parsePoints({"0,1,0", "0,3/7,4/7"});
441 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
442}
443
444TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, infrew) {
445 typedef typename TestFixture::ValueType ValueType;
446 typedef typename TestFixture::Point Point;
447 std::string programFile = STORM_TEST_RESOURCES_DIR "/mdp/multiobj_infrew.nm";
448 std::string constantsString = "";
449 std::string formulasAsString = "multi(R{\"one\"}min=? [ F x=2], R{\"two\"}min=? [ C ]);";
450 // programm, model, formula
451 storm::prism::Program program = storm::api::parseProgram(programFile);
452 program = storm::utility::prism::preprocess(program, constantsString);
453 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas =
455 std::shared_ptr<storm::models::sparse::Mdp<ValueType>> mdp =
456 storm::api::buildSparseModel<ValueType>(program, formulas)->template as<storm::models::sparse::Mdp<ValueType>>();
457 std::string errorString; // storage for error reporting
458 std::vector<Point> expected;
459
460 storm::Environment env = this->getPositionalDeterministicEnvironment();
461
462 uint64_t formulaIndex = 0;
463 expected = this->parsePoints({"10,1"});
464 if (this->isFlowEncoding()) {
465 STORM_SILENT_EXPECT_THROW(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString),
466 storm::exceptions::InvalidOperationException);
467 } else {
468 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
469 }
470
471 env = this->getGoalDeterministicEnvironment();
472
473 formulaIndex = 0;
474 expected = this->parsePoints({"0,1"});
475 EXPECT_TRUE(this->testParetoFormula(env, mdp, *formulas[formulaIndex], expected, errorString)) << errorString;
476}
477
478} // namespace
479
480#endif /* defined STORM_HAVE_Z3_OPTIMIZE */
ModelCheckerEnvironment & modelchecker()
MultiObjectiveModelCheckerEnvironment & multi()
void setSchedulerRestriction(storm::storage::SchedulerClass const &value)
MultiObjectiveFormula & asMultiObjectiveFormula()
Definition Formula.cpp:237
std::vector< storm::jani::Property > parsePropertiesForPrismProgram(std::string const &inputString, storm::prism::Program const &program, boost::optional< std::set< std::string > > const &propertyFilter)
storm::prism::Program parseProgram(std::string const &filename, bool prismCompatibility, bool simplify)
std::vector< std::shared_ptr< storm::logic::Formula const > > extractFormulasFromProperties(std::vector< storm::jani::Property > const &properties)
SFTBDDChecker::ValueType ValueType
std::string toString(DFTElementType const &type)
std::unique_ptr< CheckResult > performMultiObjectiveModelChecking(Environment const &env, SparseModelType const &model, storm::logic::MultiObjectiveFormula const &formula, bool produceScheduler)
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:13
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
Definition GraphTest.cpp:62
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes
Definition GraphTest.cpp:59
#define STORM_SILENT_EXPECT_THROW(statement, expected_exception)
Definition storm_gtest.h:31