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