Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DFTModelChecker.cpp
Go to the documentation of this file.
2
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();
289 auto ioSettings = storm::settings::getModule<storm::settings::modules::IOSettings>();
290 auto dftIOSettings = storm::settings::getModule<storm::dft::settings::modules::DftIOSettings>();
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 auto const& generalSettings = storm::settings::getModule<storm::settings::modules::GeneralSettings>();
303 ValueType const precision = std::is_same<ValueType, storm::RationalFunction>::value
304 ? storm::utility::zero<ValueType>()
305 : storm::utility::convertNumber<ValueType>(generalSettings.getPrecision());
306 if (approximationError > 0.0) {
307 // Comparator for checking the error of the approximation
309
310 // Build approximate Markov Automata for lower and upper bound
311 approximation_result approxResult = std::make_pair(storm::utility::zero<ValueType>(), storm::utility::zero<ValueType>());
312 std::shared_ptr<storm::models::sparse::Model<ValueType>> model;
313 std::vector<ValueType> newResult;
315
316 // TODO: compute approximation for all properties simultaneously?
317 std::shared_ptr<const storm::logic::Formula> property = properties[0];
318 if (properties.size() > 1) {
319 STORM_LOG_WARN("Computing approximation only for first property: " << *property);
320 }
321
322 bool probabilityFormula = property->isProbabilityOperatorFormula();
323 STORM_LOG_ASSERT((property->isTimeOperatorFormula() && !probabilityFormula) || (!property->isTimeOperatorFormula() && probabilityFormula),
324 "Probability formula not initialized correctly");
325 size_t iteration = 0;
326 do {
327 // Iteratively build finer models
328 if (iteration > 0) {
329 explorationTimer.start();
330 }
331 STORM_LOG_DEBUG("Building model...");
332 // TODO refine model using existing model and MC results
333 builder.buildModel(iteration, approximationError, approximationHeuristic);
334 explorationTimer.stop();
335 buildingTimer.start();
336
337 // TODO: possible to do bisimulation on approximated model and not on concrete one?
338
339 // Build model for lower bound
340 STORM_LOG_DEBUG("Getting model for lower bound...");
341 model = builder.getModelApproximation(true, !probabilityFormula);
342 // We only output the info from the lower bound as the info for the upper bound is the same
343 if (printInfo && dftIOSettings.isShowDftStatisticsSet()) {
344 std::cout << "Model in iteration " << (iteration + 1) << ":\n";
345 model->printModelInformationToStream(std::cout);
346 }
347 buildingTimer.stop();
348
349 if (ioSettings.isExportExplicitSet()) {
350 std::vector<std::string> parameterNames;
351 // TODO fill parameter names
352 storm::api::exportSparseModelAsDrn(model, ioSettings.getExportExplicitFilename(), parameterNames,
353 !ioSettings.isExplicitExportPlaceholdersDisabled());
354 }
355
356 // Check lower bounds
357 newResult = checkModel(model, {property});
358 STORM_LOG_ASSERT(newResult.size() == 1, "Wrong size for result vector.");
359 STORM_LOG_ASSERT(iteration == 0 || !comparator.isLess(newResult[0], approxResult.first),
360 "New under-approximation " << newResult[0] << " is smaller than old result " << approxResult.first);
361 approxResult.first = newResult[0];
362
363 // Build model for upper bound
364 STORM_LOG_DEBUG("Getting model for upper bound...");
365 buildingTimer.start();
366 model = builder.getModelApproximation(false, !probabilityFormula);
367 buildingTimer.stop();
368 // Check upper bound
369 newResult = checkModel(model, {property});
370 STORM_LOG_ASSERT(newResult.size() == 1, "Wrong size for result vector.");
371 STORM_LOG_ASSERT(iteration == 0 || !comparator.isLess(approxResult.second, newResult[0]),
372 "New over-approximation " << newResult[0] << " is greater than old result " << approxResult.second);
373 approxResult.second = newResult[0];
374
375 STORM_LOG_ASSERT(comparator.isLess(approxResult.first, approxResult.second) || comparator.isEqual(approxResult.first, approxResult.second),
376 "Under-approximation " << approxResult.first << " is greater than over-approximation " << approxResult.second);
377 totalTimer.stop();
378 if (printInfo && dftIOSettings.isShowDftStatisticsSet()) {
379 std::cout << "Result after iteration " << (iteration + 1) << ": (" << approxResult.first << ", " << approxResult.second << ")\n";
380 printTimings();
381 std::cout << '\n';
382 } else {
383 STORM_LOG_DEBUG("Result after iteration " << (iteration + 1) << ": (" << approxResult.first << ", " << approxResult.second << ")");
384 }
385
386 totalTimer.start();
387 STORM_LOG_THROW(!storm::utility::isInfinity<ValueType>(approxResult.first) && !storm::utility::isInfinity<ValueType>(approxResult.second),
388 storm::exceptions::NotSupportedException, "Approximation does not work if result might be infinity.");
389 ++iteration;
390 } while (!isApproximationSufficient(approxResult.first, approxResult.second, approximationError, probabilityFormula));
391
392 // STORM_LOG_INFO("Finished approximation after " << iteration << " iteration" << (iteration > 1 ? "s." : "."));
393 if (printInfo) {
394 model->printModelInformationToStream(std::cout);
395 }
396 dft_results results;
397 results.push_back(approxResult);
398 return results;
399 } else {
400 // Build a single Markov Automaton
401 auto ioSettings = storm::settings::getModule<storm::settings::modules::IOSettings>();
402 STORM_LOG_DEBUG("Building Model...");
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
443 if (model->isOfType(storm::models::ModelType::Ctmc) && storm::settings::getModule<storm::settings::modules::GeneralSettings>().isBisimulationSet()) {
444 bisimulationTimer.start();
445 STORM_LOG_DEBUG("Bisimulation...");
446 model = storm::api::performDeterministicSparseBisimulationMinimization<storm::models::sparse::Ctmc<ValueType>>(
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(
466 storm::api::verifyWithSparseEngine<ValueType>(model, storm::api::createTask<ValueType>(property, true)));
467
468 if (result) {
469 result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(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>
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) {
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)
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:111
DFTElementCPointer getTopLevelElement() const
Definition DFT.h:215
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:13
Base class for all sparse models.
Definition Model.h:32
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.
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:25
#define STORM_LOG_DEBUG(message)
Definition logging.h:18
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#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:29
void exportSparseModelAsDot(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, std::string const &filename, size_t maxWidth=30)
Definition export.h:45
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:63
ApproximationHeuristic
Enum representing the heuristic used for deciding which states to expand.
SFTBDDChecker::ValueType ValueType
EliminationLabelBehavior
Specify criteria whether a state can be eliminated and how its labels should be treated.
TargetType convertNumber(SourceType const &number)