Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DFTModelChecker.cpp
Go to the documentation of this file.
2
12
18
19namespace storm::dft {
20namespace modelchecker {
21
22template<typename ValueType>
24 storm::dft::storage::DFT<ValueType> const& origDft, std::vector<std::shared_ptr<const storm::logic::Formula>> const& properties, bool symred,
25 bool allowModularisation, storm::dft::utility::RelevantEvents const& relevantEvents, bool allowDCForRelevant, double approximationError,
26 storm::dft::builder::ApproximationHeuristic approximationHeuristic, bool eliminateChains, storm::transformer::EliminationLabelBehavior labelBehavior) {
27 totalTimer.start();
28 dft_results results;
29
30 // Check well-formedness of DFT
31 auto wellFormedResult = storm::dft::api::isWellFormed(origDft, true);
32 STORM_LOG_THROW(wellFormedResult.first, storm::exceptions::InvalidModelException, "DFT is not well-formed for analysis: " << wellFormedResult.second);
33
34 // Optimizing DFT for modularisation
36 if (allowModularisation) {
37 dft = origDft.optimize();
38 }
39
40 // TODO: check that all paths reach the target state for approximation
41
42 // Checking DFT
43 // TODO: distinguish for all properties, not only for first one
44 if (properties[0]->isTimeOperatorFormula() && allowModularisation) {
45 // Use parallel composition as modularisation approach for expected time
46 std::shared_ptr<storm::models::sparse::Model<ValueType>> model =
47 buildModelViaComposition(dft, properties, symred, true, relevantEvents, allowDCForRelevant);
48 // Model checking
49 std::vector<ValueType> resultsValue = checkModel(model, properties);
50 for (ValueType result : resultsValue) {
51 results.push_back(result);
52 }
53 } else {
54 results = checkHelper(dft, properties, symred, allowModularisation, relevantEvents, allowDCForRelevant, approximationError, approximationHeuristic,
55 eliminateChains, labelBehavior);
56 }
57 totalTimer.stop();
58 return results;
59}
60
61template<typename ValueType>
63 storm::dft::storage::DFT<ValueType> const& dft, property_vector const& properties, bool symred, bool allowModularisation,
64 storm::dft::utility::RelevantEvents const& relevantEvents, bool allowDCForRelevant, double approximationError,
65 storm::dft::builder::ApproximationHeuristic approximationHeuristic, bool eliminateChains, storm::transformer::EliminationLabelBehavior labelBehavior) {
66 STORM_LOG_TRACE("Check helper called");
67 std::vector<storm::dft::storage::DFT<ValueType>> dfts;
68 bool invResults = false;
69 size_t nrK = 0; // K out of M
70 size_t nrM = 0; // K out of M
71
72 // Try modularisation
73 if (allowModularisation) {
74 switch (dft.getTopLevelType()) {
76 STORM_LOG_TRACE("top modularisation called AND");
77 dfts = dft.topModularisation();
78 nrK = dfts.size();
79 nrM = dfts.size();
80 break;
82 STORM_LOG_TRACE("top modularisation called OR");
83 dfts = dft.topModularisation();
84 nrK = 0;
85 nrM = dfts.size();
86 invResults = true;
87 break;
89 STORM_LOG_TRACE("top modularisation called VOT");
90 dfts = dft.topModularisation();
91 nrK = std::static_pointer_cast<storm::dft::storage::elements::DFTVot<ValueType> const>(dft.getTopLevelElement())->threshold();
92 nrM = dfts.size();
93 if (nrK <= nrM / 2) {
94 nrK -= 1;
95 invResults = true;
96 }
97 break;
98 default:
99 // No static gate -> no modularisation applicable
100 break;
101 }
102 }
103
104 // Perform modularisation
105 if (dfts.size() > 1) {
106 STORM_LOG_DEBUG("Modularisation of " << dft.getTopLevelElement()->name() << " into " << dfts.size() << " submodules.");
107 // TODO: compute simultaneously
108 dft_results results;
109 for (auto property : properties) {
110 if (!property->isProbabilityOperatorFormula()) {
111 STORM_LOG_WARN("Could not check property: " << *property);
112 } else {
113 // Recursively call model checking
114 std::vector<ValueType> res;
115 for (auto const& ft : dfts) {
116 // TODO: allow approximation in modularisation
117 dft_results ftResults = checkHelper(ft, {property}, symred, true, relevantEvents, allowDCForRelevant, 0.0);
118 STORM_LOG_ASSERT(ftResults.size() == 1, "Wrong number of results");
119 res.push_back(boost::get<ValueType>(ftResults[0]));
120 }
121
122 // Combine modularisation results
123 STORM_LOG_TRACE("Combining all results... K=" << nrK << "; M=" << nrM << "; invResults=" << (invResults ? "On" : "Off"));
124 ValueType result = storm::utility::zero<ValueType>();
125 int limK = invResults ? -1 : nrM + 1;
126 int chK = invResults ? -1 : 1;
127 for (int cK = nrK; cK != limK; cK += chK) {
128 STORM_LOG_ASSERT(cK >= 0, "ck negative.");
129 uint64_t permutation = smallestIntWithNBitsSet(static_cast<uint64_t>(cK));
130 do {
131 STORM_LOG_TRACE("Permutation=" << permutation);
132 ValueType permResult = storm::utility::one<ValueType>();
133 for (size_t i = 0; i < res.size(); ++i) {
134 if (permutation & (1ul << i)) {
135 permResult *= res[i];
136 } else {
137 permResult *= storm::utility::one<ValueType>() - res[i];
138 }
139 }
140 STORM_LOG_TRACE("Result for permutation:" << permResult);
141 permutation = nextBitPermutation(permutation);
142 result += permResult;
143 } while (permutation < (1ul << nrM) && permutation != 0);
144 }
145 if (invResults) {
146 result = storm::utility::one<ValueType>() - result;
147 }
148 results.push_back(result);
149 }
150 }
151 return results;
152 } else {
153 // No modularisation was possible
154 return checkDFT(dft, properties, symred, relevantEvents, allowDCForRelevant, approximationError, approximationHeuristic, eliminateChains,
155 labelBehavior);
156 }
157}
158
159template<typename ValueType>
160std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> DFTModelChecker<ValueType>::buildModelViaComposition(
161 storm::dft::storage::DFT<ValueType> const& dft, property_vector const& properties, bool symred, bool allowModularisation,
162 storm::dft::utility::RelevantEvents const& relevantEvents, bool allowDCForRelevant) {
163 // TODO: use approximation?
164 STORM_LOG_TRACE("Build model via composition");
165 std::vector<storm::dft::storage::DFT<ValueType>> dfts;
166 bool isAnd = true;
167
168 // Try modularisation
169 if (allowModularisation) {
170 switch (dft.getTopLevelType()) {
172 STORM_LOG_TRACE("top modularisation called AND");
173 dfts = dft.topModularisation();
174 STORM_LOG_TRACE("Modularisation into " << dfts.size() << " submodules.");
175 isAnd = true;
176 break;
178 STORM_LOG_TRACE("top modularisation called OR");
179 dfts = dft.topModularisation();
180 STORM_LOG_TRACE("Modularsation into " << dfts.size() << " submodules.");
181 isAnd = false;
182 break;
184 // TODO enable modularisation for voting gate
185 break;
186 default:
187 // No static gate -> no modularisation applicable
188 break;
189 }
190 }
191
192 // Perform modularisation via parallel composition
193 if (dfts.size() > 1) {
194 STORM_LOG_TRACE("Recursive CHECK Call");
195 bool firstTime = true;
196 std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> composedModel;
197 for (auto const& ft : dfts) {
198 STORM_LOG_DEBUG("Building Model via parallel composition...");
199 explorationTimer.start();
200
201 ft.setRelevantEvents(relevantEvents, allowDCForRelevant);
202 // Find symmetries
204 if (symred) {
206 STORM_LOG_DEBUG("Found " << symmetries.nrSymmetries() << " symmetries.");
207 STORM_LOG_TRACE("Symmetries: \n" << symmetries);
208 }
209
210 // Build a single CTMC
211 STORM_LOG_DEBUG("Building Model from DFT with top level element " << *ft.getElement(ft.getTopLevelIndex()) << " ...");
213 builder.buildModel(0, 0.0);
214 std::shared_ptr<storm::models::sparse::Model<ValueType>> model = builder.getModel();
215 explorationTimer.stop();
216
217 STORM_LOG_THROW(model->isOfType(storm::models::ModelType::Ctmc), storm::exceptions::NotSupportedException,
218 "Parallel composition only applicable for CTMCs");
219 std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> ctmc = model->template as<storm::models::sparse::Ctmc<ValueType>>();
220
221 // Apply bisimulation to new CTMC
222 bisimulationTimer.start();
223 ctmc = storm::api::performDeterministicSparseBisimulationMinimization<storm::models::sparse::Ctmc<ValueType>>(
226 bisimulationTimer.stop();
227
228 if (firstTime) {
229 composedModel = ctmc;
230 firstTime = false;
231 } else {
232 composedModel = storm::builder::ParallelCompositionBuilder<ValueType>::compose(composedModel, ctmc, isAnd);
233 }
234
235 // Apply bisimulation to parallel composition
236 bisimulationTimer.start();
237 composedModel = storm::api::performDeterministicSparseBisimulationMinimization<storm::models::sparse::Ctmc<ValueType>>(
238 composedModel, properties, storm::storage::BisimulationType::Weak)
240 bisimulationTimer.stop();
241
242 STORM_LOG_DEBUG("No. states (Composed): " << composedModel->getNumberOfStates());
243 STORM_LOG_DEBUG("No. transitions (Composed): " << composedModel->getNumberOfTransitions());
244 if (composedModel->getNumberOfStates() <= 15) {
245 STORM_LOG_TRACE("Transition matrix: \n" << composedModel->getTransitionMatrix());
246 } else {
247 STORM_LOG_TRACE("Transition matrix: too big to print");
248 }
249 }
250 if (printInfo) {
251 composedModel->printModelInformationToStream(std::cout);
252 }
253 return composedModel;
254 } else {
255 // No composition was possible
256 explorationTimer.start();
257
258 dft.setRelevantEvents(relevantEvents, allowDCForRelevant);
259
260 // Find symmetries
262 if (symred) {
264 STORM_LOG_DEBUG("Found " << symmetries.nrSymmetries() << " symmetries.");
265 STORM_LOG_TRACE("Symmetries: \n" << symmetries);
266 }
267 // Build a single CTMC
268 STORM_LOG_DEBUG("Building Model...");
269
271 builder.buildModel(0, 0.0);
272 std::shared_ptr<storm::models::sparse::Model<ValueType>> model = builder.getModel();
273 if (printInfo) {
274 model->printModelInformationToStream(std::cout);
275 }
276 explorationTimer.stop();
277 STORM_LOG_THROW(model->isOfType(storm::models::ModelType::Ctmc), storm::exceptions::NotSupportedException,
278 "Parallel composition only applicable for CTMCs");
279 return model->template as<storm::models::sparse::Ctmc<ValueType>>();
280 }
281}
282
283template<typename ValueType>
284typename DFTModelChecker<ValueType>::dft_results DFTModelChecker<ValueType>::checkDFT(
285 storm::dft::storage::DFT<ValueType> const& dft, property_vector const& properties, bool symred, storm::dft::utility::RelevantEvents const& relevantEvents,
286 bool allowDCForRelevant, double approximationError, storm::dft::builder::ApproximationHeuristic approximationHeuristic, bool eliminateChains,
288 explorationTimer.start();
291
292 dft.setRelevantEvents(relevantEvents, allowDCForRelevant);
293
294 // Find symmetries
296 if (symred) {
298 STORM_LOG_DEBUG("Found " << symmetries.nrSymmetries() << " symmetries.");
299 STORM_LOG_TRACE("Symmetries: \n" << symmetries);
300 }
301
302 if (approximationError > 0.0) {
303 // Comparator for checking the error of the approximation
305 // Build approximate Markov Automata for lower and upper bound
306 approximation_result approxResult = std::make_pair(storm::utility::zero<ValueType>(), storm::utility::zero<ValueType>());
307 std::shared_ptr<storm::models::sparse::Model<ValueType>> model;
308 std::vector<ValueType> newResult;
310
311 // TODO: compute approximation for all properties simultaneously?
312 std::shared_ptr<const storm::logic::Formula> property = properties[0];
313 if (properties.size() > 1) {
314 STORM_LOG_WARN("Computing approximation only for first property: " << *property);
315 }
316
317 bool probabilityFormula = property->isProbabilityOperatorFormula();
318 STORM_LOG_ASSERT((property->isTimeOperatorFormula() && !probabilityFormula) || (!property->isTimeOperatorFormula() && probabilityFormula),
319 "Probability formula not initialized correctly");
320 size_t iteration = 0;
321 do {
322 // Iteratively build finer models
323 if (iteration > 0) {
324 explorationTimer.start();
325 }
326 STORM_LOG_DEBUG("Building model...");
327 // TODO refine model using existing model and MC results
328 builder.buildModel(iteration, approximationError, approximationHeuristic);
329 explorationTimer.stop();
330 buildingTimer.start();
331
332 // TODO: possible to do bisimulation on approximated model and not on concrete one?
333
334 // Build model for lower bound
335 STORM_LOG_DEBUG("Getting model for lower bound...");
336 model = builder.getModelApproximation(true, !probabilityFormula);
337 // We only output the info from the lower bound as the info for the upper bound is the same
338 if (printInfo && dftIOSettings.isShowDftStatisticsSet()) {
339 std::cout << "Model in iteration " << (iteration + 1) << ":\n";
340 model->printModelInformationToStream(std::cout);
341 }
342 buildingTimer.stop();
343
344 if (ioSettings.isExportExplicitSet()) {
345 std::vector<std::string> parameterNames;
346 // TODO fill parameter names
347 storm::api::exportSparseModelAsDrn(model, ioSettings.getExportExplicitFilename(), parameterNames,
348 !ioSettings.isExplicitExportPlaceholdersDisabled());
349 }
350
351 // Check lower bounds
352 newResult = checkModel(model, {property});
353 STORM_LOG_ASSERT(newResult.size() == 1, "Wrong size for result vector.");
354 STORM_LOG_ASSERT(iteration == 0 || !comparator.isLess(newResult[0], approxResult.first),
355 "New under-approximation " << newResult[0] << " is smaller than old result " << approxResult.first);
356 approxResult.first = newResult[0];
357
358 // Build model for upper bound
359 STORM_LOG_DEBUG("Getting model for upper bound...");
360 buildingTimer.start();
361 model = builder.getModelApproximation(false, !probabilityFormula);
362 buildingTimer.stop();
363 // Check upper bound
364 newResult = checkModel(model, {property});
365 STORM_LOG_ASSERT(newResult.size() == 1, "Wrong size for result vector.");
366 STORM_LOG_ASSERT(iteration == 0 || !comparator.isLess(approxResult.second, newResult[0]),
367 "New over-approximation " << newResult[0] << " is greater than old result " << approxResult.second);
368 approxResult.second = newResult[0];
369
370 STORM_LOG_ASSERT(comparator.isLess(approxResult.first, approxResult.second) || comparator.isEqual(approxResult.first, approxResult.second),
371 "Under-approximation " << approxResult.first << " is greater than over-approximation " << approxResult.second);
372 totalTimer.stop();
373 if (printInfo && dftIOSettings.isShowDftStatisticsSet()) {
374 std::cout << "Result after iteration " << (iteration + 1) << ": (" << approxResult.first << ", " << approxResult.second << ")\n";
375 printTimings();
376 std::cout << '\n';
377 } else {
378 STORM_LOG_DEBUG("Result after iteration " << (iteration + 1) << ": (" << approxResult.first << ", " << approxResult.second << ")");
379 }
380
381 totalTimer.start();
382 STORM_LOG_THROW(!storm::utility::isInfinity<ValueType>(approxResult.first) && !storm::utility::isInfinity<ValueType>(approxResult.second),
383 storm::exceptions::NotSupportedException, "Approximation does not work if result might be infinity.");
384 ++iteration;
385 } while (!isApproximationSufficient(approxResult.first, approxResult.second, approximationError, probabilityFormula));
386
387 // STORM_LOG_INFO("Finished approximation after " << iteration << " iteration" << (iteration > 1 ? "s." : "."));
388 if (printInfo) {
389 model->printModelInformationToStream(std::cout);
390 }
391 dft_results results;
392 results.push_back(approxResult);
393 return results;
394 } else {
395 // Build a single Markov Automaton
397 STORM_LOG_DEBUG("Building Model...");
399 builder.buildModel(0, 0.0);
400 std::shared_ptr<storm::models::sparse::Model<ValueType>> model = builder.getModel();
401 if (eliminateChains && model->isOfType(storm::models::ModelType::MarkovAutomaton)) {
402 auto ma = std::static_pointer_cast<storm::models::sparse::MarkovAutomaton<ValueType>>(model);
404 }
405 explorationTimer.stop();
406
407 // Print model information
408 if (printInfo) {
409 model->printModelInformationToStream(std::cout);
410 }
411
412 // Export the model if required
413 // TODO move this outside of the model checker?
414 if (ioSettings.isExportExplicitSet()) {
415 std::vector<std::string> parameterNames;
416 // TODO fill parameter names
417 storm::api::exportSparseModelAsDrn(model, ioSettings.getExportExplicitFilename(), parameterNames,
418 !ioSettings.isExplicitExportPlaceholdersDisabled());
419 }
420 if (ioSettings.isExportDotSet()) {
421 storm::api::exportSparseModelAsDot(model, ioSettings.getExportDotFilename(), ioSettings.getExportDotMaxWidth());
422 }
423
424 // Model checking
425 std::vector<ValueType> resultsValue = checkModel(model, properties);
426 dft_results results;
427 for (ValueType result : resultsValue) {
428 results.push_back(result);
429 }
430 return results;
431 }
432}
433
434template<typename ValueType>
435std::vector<ValueType> DFTModelChecker<ValueType>::checkModel(std::shared_ptr<storm::models::sparse::Model<ValueType>>& model,
436 property_vector const& properties) {
437 // Bisimulation
439 bisimulationTimer.start();
440 STORM_LOG_DEBUG("Bisimulation...");
441 model = storm::api::performDeterministicSparseBisimulationMinimization<storm::models::sparse::Ctmc<ValueType>>(
442 model->template as<storm::models::sparse::Ctmc<ValueType>>(), properties, storm::storage::BisimulationType::Weak)
443 ->template as<storm::models::sparse::Ctmc<ValueType>>();
444 STORM_LOG_DEBUG("No. states (Bisimulation): " << model->getNumberOfStates());
445 STORM_LOG_DEBUG("No. transitions (Bisimulation): " << model->getNumberOfTransitions());
446 bisimulationTimer.stop();
447 }
448
449 // Check the model
450 STORM_LOG_DEBUG("Model checking...");
451 modelCheckingTimer.start();
452 std::vector<ValueType> results;
453
454 // Check each property
455 storm::utility::Stopwatch singleModelCheckingTimer;
456 for (auto property : properties) {
457 singleModelCheckingTimer.reset();
458 singleModelCheckingTimer.start();
459 // STORM_PRINT_AND_LOG("Model checking property " << *property << " ...\n");
460 std::unique_ptr<storm::modelchecker::CheckResult> result(
461 storm::api::verifyWithSparseEngine<ValueType>(model, storm::api::createTask<ValueType>(property, true)));
462
463 if (result) {
464 result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates()));
465 ValueType resultValue = result->asExplicitQuantitativeCheckResult<ValueType>().getValueMap().begin()->second;
466 results.push_back(resultValue);
467 } else {
468 STORM_LOG_WARN("The property '" << *property << "' could not be checked with the current settings.");
469 results.push_back(-storm::utility::one<ValueType>());
470 }
471 // STORM_PRINT_AND_LOG("Result (initial states): " << resultValue << '\n');
472 singleModelCheckingTimer.stop();
473 // STORM_PRINT_AND_LOG("Time for model checking: " << singleModelCheckingTimer << ".\n");
474 }
475 modelCheckingTimer.stop();
476 STORM_LOG_DEBUG("Model checking done.");
477 return results;
478}
479
480template<typename ValueType>
481bool DFTModelChecker<ValueType>::isApproximationSufficient(ValueType, ValueType, double, bool) {
482 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Approximation works only for double.");
483}
484
485template<>
486bool DFTModelChecker<double>::isApproximationSufficient(double lowerBound, double upperBound, double approximationError, bool relative) {
487 STORM_LOG_THROW(!std::isnan(lowerBound) && !std::isnan(upperBound), storm::exceptions::NotSupportedException,
488 "Approximation does not work if result is NaN.");
489 if (relative) {
490 return upperBound - lowerBound <= approximationError;
491 } else {
492 return upperBound - lowerBound <= approximationError * (lowerBound + upperBound) / 2;
493 }
494}
495
496template<typename ValueType>
498 os << "Times:\n";
499 os << "Exploration:\t" << explorationTimer << '\n';
500 os << "Building:\t" << buildingTimer << '\n';
501 os << "Bisimulation:\t" << bisimulationTimer << '\n';
502 os << "Modelchecking:\t" << modelCheckingTimer << '\n';
503 os << "Total:\t\t" << totalTimer << '\n';
504}
505
506template<typename ValueType>
507void DFTModelChecker<ValueType>::printResults(dft_results const& results, std::ostream& os) {
508 bool first = true;
509 os << "Result: [";
510 for (auto result : results) {
511 if (first) {
512 first = false;
513 } else {
514 os << ", ";
515 }
516 boost::variant<std::ostream&> stream(os);
517 boost::apply_visitor(ResultOutputVisitor(), result, stream);
518 }
519 os << "]\n";
520}
521
522template class DFTModelChecker<double>;
524
525} // namespace modelchecker
526} // namespace storm::dft
void checkModel(std::string const &path, std::string const &formulaString, double maxmin, double maxmax, double minmax, double minmin, bool produceScheduler)
uint64_t nextBitPermutation(uint64_t v)
The next bit permutation in a lexicographical sense.
uint64_t smallestIntWithNBitsSet(uint64_t n)
static std::shared_ptr< storm::models::sparse::Ctmc< ValueType > > compose(std::shared_ptr< storm::models::sparse::Ctmc< ValueType > > const &ctmcA, std::shared_ptr< storm::models::sparse::Ctmc< ValueType > > const &ctmcB, bool labelAnd)
void printTimings(std::ostream &os=std::cout)
Print timings of all operations to stream.
void printResults(dft_results const &results, std::ostream &os=std::cout)
Print result to stream.
std::vector< boost::variant< ValueType, approximation_result > > dft_results
dft_results check(storm::dft::storage::DFT< ValueType > const &origDft, property_vector const &properties, bool symred=true, bool allowModularisation=true, storm::dft::utility::RelevantEvents const &relevantEvents={}, bool allowDCForRelevant=false, double approximationError=0.0, storm::dft::builder::ApproximationHeuristic approximationHeuristic=storm::dft::builder::ApproximationHeuristic::DEPTH, bool eliminateChains=false, storm::transformer::EliminationLabelBehavior labelBehavior=storm::transformer::EliminationLabelBehavior::KeepLabels)
Main method for checking DFTs.
Represents a Dynamic Fault Tree.
Definition DFT.h:52
void setRelevantEvents(storm::dft::utility::RelevantEvents const &relevantEvents, bool const allowDCForRelevant) const
Set the relevance flag for all elements according to the given relevant events.
Definition DFT.cpp:690
storm::dft::storage::elements::DFTElementType getTopLevelType() const
Definition DFT.h:110
DFTElementCPointer getTopLevelElement() const
Definition DFT.h:214
std::vector< DFT< ValueType > > topModularisation() const
Definition DFT.cpp:320
DFT< ValueType > optimize() const
Definition DFT.cpp:373
static storm::dft::storage::DftSymmetries findSymmetries(storm::dft::storage::DFT< ValueType > const &dft)
Find symmetries in the given DFT.
This class represents a continuous-time Markov chain.
Definition Ctmc.h:15
Base class for all sparse models.
Definition Model.h:33
static std::shared_ptr< models::sparse::Model< ValueType, RewardModelType > > eliminateNonmarkovianStates(std::shared_ptr< models::sparse::MarkovAutomaton< ValueType, RewardModelType > > ma, EliminationLabelBehavior labelBehavior=EliminationLabelBehavior::KeepLabels)
Generates a model with the same basic behavior as the input, but eliminates non-Markovian chains.
bool isEqual(ValueType const &value1, ValueType const &value2) const
bool isLess(ValueType const &value1, ValueType const &value2) const
A class that provides convenience operations to display run times.
Definition Stopwatch.h:14
void start()
Start stopwatch (again) and start measuring time.
Definition Stopwatch.cpp:48
void reset()
Reset the stopwatch.
Definition Stopwatch.cpp:54
void stop()
Stop stopwatch and add measured time to total time.
Definition Stopwatch.cpp:42
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_DEBUG(message)
Definition logging.h:23
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
void exportSparseModelAsDrn(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, std::string const &filename, std::vector< std::string > const &parameterNames={}, bool allowPlaceholders=true)
Definition export.h:25
void exportSparseModelAsDot(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, std::string const &filename, size_t maxWidth=30)
Definition export.h:41
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
ApproximationHeuristic
Enum representing the heuristic used for deciding which states to expand.
SFTBDDChecker::ValueType ValueType
SettingsType const & getModule()
Get module.
EliminationLabelBehavior
Specify criteria whether a state can be eliminated and how its labels should be treated.