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