Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DftModelCheckerTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
5#include "storm-dft/api/io.h"
10
11namespace {
12
13// Configurations for DFT analysis
14struct DftAnalysisConfig {
15 bool useSR;
16 bool useMod;
17 bool useDC;
18};
19
20class NoOptimizationsConfig {
21 public:
22 typedef double ValueType;
23
24 static DftAnalysisConfig createConfig() {
25 return DftAnalysisConfig{false, false, false};
26 }
27};
28
29class DontCareOnlyConfig {
30 public:
31 typedef double ValueType;
32
33 static DftAnalysisConfig createConfig() {
34 return DftAnalysisConfig{false, false, true};
35 }
36};
37
38class ModularisationOnlyConfig {
39 public:
40 typedef double ValueType;
41
42 static DftAnalysisConfig createConfig() {
43 return DftAnalysisConfig{false, true, false};
44 }
45};
46
47class SymmetryReductionOnlyConfig {
48 public:
49 typedef double ValueType;
50
51 static DftAnalysisConfig createConfig() {
52 return DftAnalysisConfig{true, false, false};
53 }
54};
55
56class ModularisationConfig {
57 public:
58 typedef double ValueType;
59
60 static DftAnalysisConfig createConfig() {
61 return DftAnalysisConfig{false, true, true};
62 }
63};
64
65class SymmetryReductionConfig {
66 public:
67 typedef double ValueType;
68
69 static DftAnalysisConfig createConfig() {
70 return DftAnalysisConfig{true, false, true};
71 }
72};
73
74class AllOptimizationsConfig {
75 public:
76 typedef double ValueType;
77
78 static DftAnalysisConfig createConfig() {
79 return DftAnalysisConfig{true, true, true};
80 }
81};
82
83// General base class for testing of DFT model checking
84template<typename TestType>
85class DftModelCheckerTest : public ::testing::Test {
86 public:
87 typedef typename TestType::ValueType ValueType;
88
89 DftModelCheckerTest() : config(TestType::createConfig()) {}
90
91 DftAnalysisConfig const& getConfig() const {
92 return config;
93 }
94
95 double analyze(std::string const& file, std::string const& property) const {
96 // Load, build and prepare DFT
97 std::shared_ptr<storm::dft::storage::DFT<double>> dft =
99 EXPECT_TRUE(storm::dft::api::isWellFormed(*dft).first);
100
101 // Create property
102 std::vector<std::shared_ptr<storm::logic::Formula const>> properties = storm::api::extractFormulasFromProperties(storm::api::parseProperties(property));
103
104 // Create relevant names
105 std::vector<std::string> relevantNames;
106 if (!config.useDC) {
107 relevantNames.push_back("all");
108 }
109 storm::dft::utility::RelevantEvents relevantEvents = storm::dft::api::computeRelevantEvents(properties, relevantNames);
110
111 // Perform model checking
113 storm::dft::api::analyzeDFT<double>(*dft, properties, config.useSR, config.useMod, relevantEvents, false);
114 return boost::get<double>(results[0]);
115 }
116
117 double analyzeMTTF(std::string const& file) const {
118 std::string property = "Tmin=? [F \"failed\"]";
119 return analyze(file, property);
120 }
121
122 double analyzeReliability(std::string const& file, double bound) const {
123 std::string property = "Pmin=? [F<=" + std::to_string(bound) + " \"failed\"]";
124 return analyze(file, property);
125 }
126
127 double analyzeReachability(std::string const& file) const {
128 std::string property = "Pmin=? [F \"failed\"]";
129 return analyze(file, property);
130 }
131
132 double precision() const {
133 return 1e-12;
134 }
135
136 double precisionReliability() const {
137 return 1e-10;
138 }
139
140 private:
141 DftAnalysisConfig config;
142};
143
144typedef ::testing::Types<NoOptimizationsConfig, DontCareOnlyConfig, ModularisationOnlyConfig, SymmetryReductionOnlyConfig, ModularisationConfig,
145 SymmetryReductionConfig, AllOptimizationsConfig>
147
148TYPED_TEST_SUITE(DftModelCheckerTest, TestingTypes, );
149
150TYPED_TEST(DftModelCheckerTest, AndMTTF) {
151 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/and.dft");
152 EXPECT_NEAR(result, 3, this->precision());
153}
154
155TYPED_TEST(DftModelCheckerTest, OrMTTF) {
156 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/or.dft");
157 EXPECT_NEAR(result, 1, this->precision());
158}
159
160TYPED_TEST(DftModelCheckerTest, VotingMTTF) {
161 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/voting.dft");
162 EXPECT_NEAR(result, 5 / 3.0, this->precision());
163 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/voting2.dft");
164 EXPECT_NEAR(result, 10 / 17.0, this->precision());
165 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/voting3.dft");
166 EXPECT_NEAR(result, 2685 / 1547.0, this->precision());
167 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/voting4.dft");
168 EXPECT_NEAR(result, 5 / 6.0, this->precision());
169}
170
171TYPED_TEST(DftModelCheckerTest, PandMTTF) {
172 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/pand.dft");
173 EXPECT_EQ(result, storm::utility::infinity<double>());
174}
175
176TYPED_TEST(DftModelCheckerTest, PorMTTF) {
177 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/por.dft");
178 EXPECT_EQ(result, storm::utility::infinity<double>());
179}
180
181TYPED_TEST(DftModelCheckerTest, FdepMTTF) {
182 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep2.dft");
183 EXPECT_NEAR(result, 2, this->precision());
184 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep3.dft");
185 EXPECT_NEAR(result, 5 / 2.0, this->precision());
186 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep7.dft");
187 EXPECT_NEAR(result, 5 / 12.0, this->precision());
188
189 if (this->getConfig().useMod) {
190 STORM_SILENT_EXPECT_THROW(this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep.dft"), storm::exceptions::NotSupportedException);
191 STORM_SILENT_EXPECT_THROW(this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep4.dft"), storm::exceptions::NotSupportedException);
192 STORM_SILENT_EXPECT_THROW(this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep5.dft"), storm::exceptions::NotSupportedException);
193 STORM_SILENT_EXPECT_THROW(this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep6.dft"), storm::exceptions::NotSupportedException);
194 } else {
195 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep.dft");
196 EXPECT_NEAR(result, 2 / 3.0, this->precision());
197 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep4.dft");
198 EXPECT_NEAR(result, 1, this->precision());
199 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep5.dft");
200 EXPECT_NEAR(result, 3, this->precision());
201 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/fdep6.dft");
202 EXPECT_NEAR(result, 9 / 56.0, this->precision());
203 }
204}
205
206TYPED_TEST(DftModelCheckerTest, PdepMTTF) {
207 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/pdep.dft");
208 EXPECT_NEAR(result, 8 / 3.0, this->precision());
209 if (this->getConfig().useMod && !this->getConfig().useDC) {
210 STORM_SILENT_EXPECT_THROW(this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/pdep2.dft"), storm::exceptions::NotSupportedException);
211 } else {
212 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/pdep2.dft");
213 EXPECT_NEAR(result, 38 / 15.0, this->precision());
214 }
215 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/pdep3.dft");
216 EXPECT_NEAR(result, 67 / 24.0, this->precision());
217
218 if (this->getConfig().useMod) {
219 STORM_SILENT_EXPECT_THROW(this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/pdep4.dft"), storm::exceptions::NotSupportedException);
220 } else {
221 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/pdep4.dft");
222 EXPECT_EQ(result, storm::utility::infinity<double>());
223 }
224}
225
226TYPED_TEST(DftModelCheckerTest, SpareMTTF) {
227 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare.dft");
228 EXPECT_NEAR(result, 46 / 13.0, this->precision());
229 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare2.dft");
230 EXPECT_NEAR(result, 43 / 23.0, this->precision());
231 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare3.dft");
232 EXPECT_NEAR(result, 14 / 11.0, this->precision());
233 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare4.dft");
234 EXPECT_NEAR(result, 18836 / 3887.0, this->precision());
235 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare5.dft");
236 EXPECT_NEAR(result, 8 / 3.0, this->precision());
237 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare6.dft");
238 EXPECT_NEAR(result, 7 / 5.0, this->precision());
239 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare7.dft");
240 EXPECT_NEAR(result, 551 / 150.0, this->precision());
241 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare8.dft");
242 EXPECT_NEAR(result, 249 / 52.0, this->precision()); // DFTCalc has result of 4.33779 due to different semantics of nested spares
243 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare_dc.dft");
244 EXPECT_NEAR(result, 78311 / 182700.0, this->precision());
245 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/modules3.dft");
246 EXPECT_NEAR(result, 7 / 6.0, this->precision());
247 // Spare gate is part of spare module. As a result it is not activated.
248 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/spare_contains_spare.dft");
249 EXPECT_NEAR(result, 1, this->precision());
250}
251
252TYPED_TEST(DftModelCheckerTest, SeqMTTF) {
253 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq.dft");
254 EXPECT_NEAR(result, 4, this->precision());
255 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq2.dft");
256 EXPECT_NEAR(result, 6, this->precision());
257 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq3.dft");
258 EXPECT_NEAR(result, 6, this->precision());
259 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq4.dft");
260 EXPECT_NEAR(result, 6, this->precision());
261 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq5.dft");
262 EXPECT_EQ(result, storm::utility::infinity<double>());
263 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq6.dft");
264 EXPECT_NEAR(result, 30000, this->precision());
265
266 if (this->getConfig().useMod) {
267 STORM_SILENT_EXPECT_THROW(this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq7.dft"), storm::exceptions::NotSupportedException);
268 } else {
269 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq7.dft");
270 EXPECT_EQ(result, storm::utility::infinity<double>());
271 }
272 result = this->analyzeReliability(STORM_TEST_RESOURCES_DIR "/dft/seq7.dft", 1.0);
273 EXPECT_NEAR(result, 0.08, this->precision());
274 result = this->analyzeReachability(STORM_TEST_RESOURCES_DIR "/dft/seq7.dft");
275 EXPECT_NEAR(result, 0.08, this->precision());
276 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/seq8.dft");
277 EXPECT_NEAR(result, 11 / 8.0, this->precision());
278}
279
280TYPED_TEST(DftModelCheckerTest, Mutex) {
281 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/mutex.dft");
282 EXPECT_NEAR(result, 1 / 2.0, this->precision());
283 result = this->analyzeReliability(STORM_TEST_RESOURCES_DIR "/dft/mutex.dft", 1.0);
284 EXPECT_NEAR(result, 0.8646647168, this->precisionReliability());
285 result = this->analyzeReachability(STORM_TEST_RESOURCES_DIR "/dft/mutex.dft");
286 EXPECT_NEAR(result, 1, this->precision());
287
288 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/mutex2.dft");
289 EXPECT_EQ(result, storm::utility::infinity<double>());
290 result = this->analyzeReliability(STORM_TEST_RESOURCES_DIR "/dft/mutex2.dft", 1.0);
291 EXPECT_NEAR(result, 0, this->precision());
292 result = this->analyzeReachability(STORM_TEST_RESOURCES_DIR "/dft/mutex2.dft");
293 EXPECT_NEAR(result, 0, this->precision());
294
295 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/mutex3.dft");
296 EXPECT_EQ(result, storm::utility::infinity<double>());
297 result = this->analyzeReliability(STORM_TEST_RESOURCES_DIR "/dft/mutex3.dft", 1.0);
298 EXPECT_NEAR(result, 0, this->precision());
299 result = this->analyzeReachability(STORM_TEST_RESOURCES_DIR "/dft/mutex3.dft");
300 EXPECT_NEAR(result, 0, this->precision());
301
302 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/mutex4.dft");
303 EXPECT_EQ(result, storm::utility::infinity<double>());
304 result = this->analyzeReliability(STORM_TEST_RESOURCES_DIR "/dft/mutex4.dft", 1.0);
305 EXPECT_NEAR(result, 0.5842978146, this->precisionReliability());
306 result = this->analyzeReachability(STORM_TEST_RESOURCES_DIR "/dft/mutex4.dft");
307 EXPECT_NEAR(result, 5 / 8.0, this->precision());
308}
309
310TYPED_TEST(DftModelCheckerTest, Symmetry) {
311 double result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/symmetry6.dft");
312 EXPECT_NEAR(result, 2804183 / 2042040.0, this->precision());
313 result = this->analyzeReliability(STORM_TEST_RESOURCES_DIR "/dft/symmetry6.dft", 1.0);
314 EXPECT_NEAR(result, 0.3421934224, this->precisionReliability());
315
316 result = this->analyzeMTTF(STORM_TEST_RESOURCES_DIR "/dft/pdep_symmetry.dft");
317 EXPECT_NEAR(result, 6553 / 5376.0, this->precision());
318 result = this->analyzeReliability(STORM_TEST_RESOURCES_DIR "/dft/pdep_symmetry.dft", 1.0);
319 EXPECT_NEAR(result, 0.4223514414, this->precisionReliability());
320}
321
322TYPED_TEST(DftModelCheckerTest, HecsReliability) {
323 if (!this->getConfig().useDC) {
324 // Skip configurations because it takes too long
325 GTEST_SKIP();
326 return;
327 }
328 double result = this->analyzeReliability(STORM_TEST_RESOURCES_DIR "/dft/hecs_2_2.dft", 1.0);
329 EXPECT_NEAR(result, 0.00021997582, this->precisionReliability());
330}
331} // namespace
std::vector< boost::variant< ValueType, approximation_result > > dft_results
std::vector< storm::jani::Property > parseProperties(storm::parser::FormulaParser &formulaParser, std::string const &inputString, 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)
std::shared_ptr< storm::dft::storage::DFT< ValueType > > prepareForMarkovAnalysis(storm::dft::storage::DFT< ValueType > const &dft)
Apply transformations to make DFT feasible for Markovian analysis.
std::shared_ptr< storm::dft::storage::DFT< ValueType > > loadDFTGalileoFile(std::string const &file)
Load DFT from Galileo file.
Definition io.cpp:14
std::pair< bool, std::string > isWellFormed(storm::dft::storage::DFT< ValueType > const &dft, bool validForMarkovianAnalysis)
Check whether the DFT is well-formed.
storm::dft::utility::RelevantEvents computeRelevantEvents(std::vector< std::shared_ptr< storm::logic::Formula const > > const &properties, std::vector< std::string > const &additionalRelevantEventNames)
Get relevant event ids from given relevant event names and labels in properties.
Definition analysis.cpp:20
storm::dft::modelchecker::DFTModelChecker< ValueType >::dft_results analyzeDFT(storm::dft::storage::DFT< ValueType > const &dft, std::vector< std::shared_ptr< storm::logic::Formula const > > const &properties, bool symred, bool allowModularisation, storm::dft::utility::RelevantEvents const &relevantEvents, bool allowDCForRelevant, double approximationError, storm::dft::builder::ApproximationHeuristic approximationHeuristic, bool eliminateChains, storm::transformer::EliminationLabelBehavior labelBehavior, bool printOutput)
Compute the exact or approximate analysis result of the given DFT according to the given properties.
Definition analysis.cpp:28
ValueType infinity()
Definition constants.cpp:29
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
Definition GraphTest.cpp:64
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes
Definition GraphTest.cpp:61
#define STORM_SILENT_EXPECT_THROW(statement, expected_exception)
Definition storm_gtest.h:19