Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DftTraceGeneratorTest.cpp
Go to the documentation of this file.
1#include "storm-config.h"
2#include "test/storm_gtest.h"
3
8
10
11namespace {
12
13// Configurations for DFT traces
14struct DftTracesConfig {
15 bool useDC;
16 bool useSR;
17};
18
19class NoOptimizationsConfig {
20 public:
21 typedef double ValueType;
22
23 static DftTracesConfig createConfig() {
24 return DftTracesConfig{false, false};
25 }
26};
27
28class DontCareConfig {
29 public:
30 typedef double ValueType;
31
32 static DftTracesConfig createConfig() {
33 return DftTracesConfig{true, false};
34 }
35};
36
37class SymmetryReductionConfig {
38 public:
39 typedef double ValueType;
40
41 static DftTracesConfig createConfig() {
42 return DftTracesConfig{false, true};
43 }
44};
45
46class AllOptimizationsConfig {
47 public:
48 typedef double ValueType;
49
50 static DftTracesConfig createConfig() {
51 return DftTracesConfig{true, true};
52 }
53};
54
55// General base class for testing of generating DFT traces.
56template<typename TestType>
57class DftTraceGeneratorTest : public ::testing::Test {
58 public:
59 typedef typename TestType::ValueType ValueType;
60
61 DftTraceGeneratorTest() : config(TestType::createConfig()) {}
62
63 DftTracesConfig const& getConfig() const {
64 return config;
65 }
66
67 std::pair<std::shared_ptr<storm::dft::storage::DFT<double>>, storm::dft::storage::DFTStateGenerationInfo> prepareDFT(std::string const& file) {
68 // Load, build and prepare DFT
69 std::shared_ptr<storm::dft::storage::DFT<double>> dft =
70 storm::dft::api::prepareForMarkovAnalysis<double>(*(storm::dft::api::loadDFTGalileoFile<double>(file)));
71 EXPECT_TRUE(storm::dft::api::isWellFormed(*dft).first);
72
73 // Compute relevant events
74 std::vector<std::string> relevantNames;
75 if (!config.useDC) {
76 relevantNames.push_back("all");
77 }
79 dft->setRelevantEvents(relevantEvents, false);
80
81 // Find symmetries
83 if (config.useSR) {
85 }
86 storm::dft::storage::DFTStateGenerationInfo stateGenerationInfo(dft->buildStateGenerationInfo(symmetries));
87 return std::make_pair(dft, stateGenerationInfo);
88 }
89
90 private:
91 DftTracesConfig config;
92};
93
94typedef ::testing::Types<NoOptimizationsConfig, DontCareConfig, SymmetryReductionConfig, AllOptimizationsConfig> TestingTypes;
95
96TYPED_TEST_SUITE(DftTraceGeneratorTest, TestingTypes, );
97
98TYPED_TEST(DftTraceGeneratorTest, And) {
99 auto pair = this->prepareDFT(STORM_TEST_RESOURCES_DIR "/dft/and.dft");
100 auto dft = pair.first;
101 EXPECT_EQ(this->getConfig().useSR && this->getConfig().useDC, pair.second.hasSymmetries());
102 storm::dft::generator::DftNextStateGenerator<double> generator(*dft, pair.second);
103
104 // Start with initial state
105 auto state = generator.createInitialState();
106 EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
107
108 bool changed = state->orderBySymmetry();
109 EXPECT_FALSE(changed);
110
111 // Let C fail
112 auto iterFailable = state->getFailableElements().begin();
113 ASSERT_NE(iterFailable, state->getFailableElements().end());
114 ++iterFailable;
115 ASSERT_NE(iterFailable, state->getFailableElements().end());
116 EXPECT_FALSE(iterFailable.isFailureDueToDependency());
117
118 auto nextBE = iterFailable.asBE(*dft);
119 EXPECT_EQ(nextBE->name(), "C");
120 state = generator.createSuccessorState(state, nextBE);
121 EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
122 changed = state->orderBySymmetry();
123 EXPECT_EQ(this->getConfig().useSR && this->getConfig().useDC, changed);
124 if (this->getConfig().useSR && this->getConfig().useDC) {
125 EXPECT_TRUE(state->hasFailed(0));
126 } else {
127 EXPECT_TRUE(state->hasFailed(1));
128 }
129
130 // Let B fail
131 iterFailable = state->getFailableElements().begin();
132 ASSERT_NE(iterFailable, state->getFailableElements().end());
133 EXPECT_FALSE(iterFailable.isFailureDueToDependency());
134
135 nextBE = iterFailable.asBE(*dft);
136 if (this->getConfig().useSR && this->getConfig().useDC) {
137 // TODO: Apply symmetry to failable elements as well
138 return;
139 EXPECT_EQ(nextBE->name(), "C");
140 } else {
141 EXPECT_EQ(nextBE->name(), "B");
142 }
143 state = generator.createSuccessorState(state, nextBE);
144 changed = state->orderBySymmetry();
145 EXPECT_FALSE(changed);
146 EXPECT_TRUE(state->hasFailed(dft->getTopLevelIndex()));
147}
148
149TYPED_TEST(DftTraceGeneratorTest, RandomStepsAnd) {
150 auto pair = this->prepareDFT(STORM_TEST_RESOURCES_DIR "/dft/and.dft");
151 auto dft = pair.first;
152 EXPECT_EQ(this->getConfig().useSR && this->getConfig().useDC, pair.second.hasSymmetries());
153
154 // Init random number generator
155 boost::mt19937 gen(5u);
156 storm::dft::simulator::DFTTraceSimulator<double> simulator(*dft, pair.second, gen);
157
158 auto state = simulator.getCurrentState();
159 EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
160
161 // First random step
162 storm::dft::simulator::SimulationStepResult res = simulator.randomStep();
164#if BOOST_VERSION > 106400
165 // Older Boost versions yield different value
166 EXPECT_NEAR(simulator.getCurrentTime(), 0.522079, 1e-6);
167#endif
168 state = simulator.getCurrentState();
169 EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
170
171 res = simulator.randomStep();
173#if BOOST_VERSION > 106400
174 // Older Boost versions yield different value
175 EXPECT_NEAR(simulator.getCurrentTime(), 0.522079 + 0.9497214, 1e-6);
176#endif
177 state = simulator.getCurrentState();
178 EXPECT_TRUE(state->hasFailed(dft->getTopLevelIndex()));
179}
180
181TYPED_TEST(DftTraceGeneratorTest, Reset) {
182 auto pair = this->prepareDFT(STORM_TEST_RESOURCES_DIR "/dft/and.dft");
183 auto dft = pair.first;
184 EXPECT_EQ(this->getConfig().useSR && this->getConfig().useDC, pair.second.hasSymmetries());
185
186 // Init random number generator
187 boost::mt19937 gen(5u);
188 storm::dft::simulator::DFTTraceSimulator<double> simulator(*dft, pair.second, gen);
189
190 auto state = simulator.getCurrentState();
191 EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
192
193 // First random step
194 storm::dft::simulator::SimulationStepResult res = simulator.randomStep();
196#if BOOST_VERSION > 106400
197 // Older Boost versions yield different value
198 EXPECT_NEAR(simulator.getCurrentTime(), 0.522079, 1e-6);
199#endif
200 auto stateStep1 = simulator.getCurrentState();
201 EXPECT_FALSE(stateStep1->hasFailed(dft->getTopLevelIndex()));
202
203 res = simulator.randomStep();
205#if BOOST_VERSION > 106400
206 // Older Boost versions yield different value
207 EXPECT_NEAR(simulator.getCurrentTime(), 0.522079 + 0.9497214, 1e-6);
208#endif
209 state = simulator.getCurrentState();
210 EXPECT_TRUE(state->hasFailed(dft->getTopLevelIndex()));
211
212 // Reset to previous state
213 simulator.resetToState(stateStep1);
214 state = simulator.getCurrentState();
215 EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
216
217 res = simulator.randomStep();
219#if BOOST_VERSION > 106400
220 // Older Boost versions yield different value
221 EXPECT_NEAR(simulator.getCurrentTime(), 0.522079 + 0.9497214 + 2.4686932, 1e-6);
222#endif
223 state = simulator.getCurrentState();
224 EXPECT_TRUE(state->hasFailed(dft->getTopLevelIndex()));
225}
226
227TYPED_TEST(DftTraceGeneratorTest, Fdep) {
228 auto pair = this->prepareDFT(STORM_TEST_RESOURCES_DIR "/dft/fdep.dft");
229 auto dft = pair.first;
230
231 // Init random number generator. Will not be important as we are choosing the steps deterministically.
232 boost::mt19937 gen(5u);
233 storm::dft::simulator::DFTTraceSimulator<double> simulator(*dft, pair.second, gen);
234
235 // Start with initial state
236 auto state = simulator.getCurrentState();
237 EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
238
239 // Let B_Power fail
240 auto iterFailable = state->getFailableElements().begin();
241 ASSERT_NE(iterFailable, state->getFailableElements().end());
242 ++iterFailable;
243 ASSERT_NE(iterFailable, state->getFailableElements().end());
244 ++iterFailable;
245 ASSERT_NE(iterFailable, state->getFailableElements().end());
246
247 EXPECT_FALSE(iterFailable.isFailureDueToDependency());
248 auto nextBE = iterFailable.asBE(*dft);
249 EXPECT_EQ(nextBE->name(), "B_Power");
250
251 storm::dft::simulator::SimulationStepResult res = simulator.step(iterFailable);
253 state = simulator.getCurrentState();
254 EXPECT_TRUE(state->hasFailed(4));
255
256 // Let B fail
257 iterFailable = state->getFailableElements().begin();
258 ASSERT_NE(iterFailable, state->getFailableElements().end());
259 ++iterFailable;
260 ASSERT_NE(iterFailable, state->getFailableElements().end());
261
262 EXPECT_TRUE(iterFailable.isFailureDueToDependency());
263 auto dependency = iterFailable.asDependency(*dft);
264 EXPECT_EQ(dependency->dependentEvents().front()->name(), "B");
265
266 res = simulator.step(iterFailable);
268 state = simulator.getCurrentState();
269 EXPECT_TRUE(state->hasFailed(dft->getTopLevelIndex()));
270}
271
272} // namespace
static storm::dft::storage::DftSymmetries findSymmetries(storm::dft::storage::DFT< ValueType > const &dft)
Find symmetries in the given DFT.
std::pair< bool, std::string > isWellFormed(storm::dft::storage::DFT< ValueType > const &dft, bool validForMarkovianAnalysis=true)
Check whether the DFT is well-formed.
Definition storm-dft.h:64
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.
SFTBDDChecker::ValueType ValueType
SimulationStepResult
Result of a single simulation step.
TYPED_TEST(GraphTestAR, SymbolicProb01StochasticGameDieSmall)
Definition GraphTest.cpp:49
TYPED_TEST_SUITE(GraphTestAR, TestingTypes,)
::testing::Types< Cudd, Sylvan > TestingTypes
Definition GraphTest.cpp:46