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