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