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
20
21namespace storm::dft {
22namespace modelchecker {
23
24template<typename ValueType>
27 std::vector<std::shared_ptr<const storm::logic::Formula>> const& properties,
28 storm::dft::utility::RelevantEvents const& relevantEvents) {
29 totalTimer.start();
30 dft_results results;
31
32 // Check well-formedness of DFT
33 auto wellFormedResult = storm::dft::api::isWellFormed(origDft, true);
34 STORM_LOG_THROW(wellFormedResult.first, storm::exceptions::InvalidModelException,
35 "DFT is not well-formed for analysis: " << wellFormedResult.second << ".");
36
37 // Optimizing DFT for modularisation
39 if (env.analysis().isUseModularisation()) {
40 dft = origDft.optimize();
41 }
42
43 // TODO: check that all paths reach the target state for approximation
44
45 // Checking DFT
46 // TODO: distinguish for all properties, not only for first one
47 if (properties[0]->isTimeOperatorFormula() && env.analysis().isUseModularisation()) {
48 // Use parallel composition as modularisation approach for expected time
49 std::shared_ptr<storm::models::sparse::Model<ValueType>> model = buildModelViaComposition(env, dft, properties, relevantEvents);
50 // Model checking
51 std::vector<ExtendedValueType> resultsValue = checkModel(env, model, properties);
52 for (auto& result : resultsValue) {
53 results.push_back(std::move(result));
54 }
55 } else {
56 results = checkHelper(env, dft, properties, relevantEvents);
57 }
58 totalTimer.stop();
59 return results;
60}
61
62template<typename ValueType>
63typename DFTModelChecker<ValueType>::dft_results DFTModelChecker<ValueType>::checkHelper(storm::dft::DftEnvironment const& env,
65 property_vector const& properties,
66 storm::dft::utility::RelevantEvents const& relevantEvents) {
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 (env.analysis().isUseModularisation()) {
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 STORM_LOG_ASSERT(env.analysis().isUseModularisation(), "Modularisation should be enabled.");
117 // TODO: allow approximation in modularisation
119 storm::exceptions::NotSupportedException, "Combining modularisation with the partial state space generation is not supported.");
120 for (auto const& ft : dfts) {
121 dft_results ftResults = checkHelper(env, ft, {property}, relevantEvents);
122 STORM_LOG_ASSERT(ftResults.size() == 1, "Wrong number of results.");
123 res.push_back(storm::utility::narrow<ValueType>(boost::get<ExtendedValueType>(ftResults[0])));
124 }
125
126 // Combine modularisation results
127 STORM_LOG_TRACE("Combining all results... K=" << nrK << "; M=" << nrM << "; invResults=" << (invResults ? "On" : "Off"));
129 int limK = invResults ? -1 : nrM + 1;
130 int chK = invResults ? -1 : 1;
131 for (int cK = nrK; cK != limK; cK += chK) {
132 STORM_LOG_ASSERT(cK >= 0, "Ck negative.");
133 uint64_t permutation = smallestIntWithNBitsSet(static_cast<uint64_t>(cK));
134 do {
135 STORM_LOG_TRACE("Permutation=" << permutation);
137 for (size_t i = 0; i < res.size(); ++i) {
138 if (permutation & (1ul << i)) {
139 permResult *= res[i];
140 } else {
141 permResult *= storm::utility::one<ValueType>() - res[i];
142 }
143 }
144 STORM_LOG_TRACE("Result for permutation:" << permResult);
145 permutation = nextBitPermutation(permutation);
146 result += permResult;
147 } while (permutation < (1ul << nrM) && permutation != 0);
148 }
149 if (invResults) {
150 result = storm::utility::one<ValueType>() - result;
151 }
152 results.push_back(result);
153 }
154 }
155 return results;
156 } else {
157 // No modularisation was possible
158 return checkDFT(env, dft, properties, relevantEvents);
159 }
160}
161
162namespace {
163template<typename ValueType>
164auto getBisimOptions() {
165 storm::bisimulation::Options bisimOptions;
167 if constexpr (std::is_same_v<ValueType, double>) {
168 bisimOptions.tolerance = storm::utility::convertNumber<storm::RationalNumber>(1e-9); // TODO: make tolerance configurable
169 }
170 return bisimOptions;
171}
172} // namespace
173
174template<typename ValueType>
175std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> DFTModelChecker<ValueType>::buildModelViaComposition(
176 storm::dft::DftEnvironment const& env, storm::dft::storage::DFT<ValueType> const& dft, property_vector const& properties,
177 storm::dft::utility::RelevantEvents const& relevantEvents) {
178 // TODO: use approximation?
179 STORM_LOG_TRACE("Build model via composition");
180 std::vector<storm::dft::storage::DFT<ValueType>> dfts;
181 bool isAnd = true;
182
183 // Try modularisation.
184 STORM_LOG_ASSERT(env.analysis().isUseModularisation(), "Modularisation should be enabled.");
185 switch (dft.getTopLevelType()) {
187 STORM_LOG_TRACE("top modularisation called AND");
188 dfts = dft.topModularisation();
189 STORM_LOG_TRACE("Modularisation into " << dfts.size() << " submodules.");
190 isAnd = true;
191 break;
193 STORM_LOG_TRACE("top modularisation called OR");
194 dfts = dft.topModularisation();
195 STORM_LOG_TRACE("Modularisation into " << dfts.size() << " submodules.");
196 isAnd = false;
197 break;
199 // TODO enable modularisation for voting gate
200 break;
201 default:
202 // No static gate -> no modularisation applicable
203 break;
204 }
205
206 // Perform modularisation via parallel composition
207 if (dfts.size() > 1) {
208 STORM_LOG_TRACE("Recursive CHECK Call");
209 bool firstTime = true;
210 std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> composedModel;
211 for (auto const& ft : dfts) {
212 STORM_LOG_DEBUG("Building Model via parallel composition...");
213 explorationTimer.start();
214
215 ft.setRelevantEvents(relevantEvents, env.modelBuilder().isAllowDCForRelevantEvents());
216 // Find symmetries
217 storm::dft::storage::DftSymmetries symmetries;
220 STORM_LOG_DEBUG("Found " << symmetries.nrSymmetries() << " symmetries.");
221 STORM_LOG_TRACE("Symmetries: \n" << symmetries);
222 }
223
224 // Build a single CTMC
225 STORM_LOG_DEBUG("Building Model from DFT with top level element " << *ft.getElement(ft.getTopLevelIndex()) << " ...");
226 storm::dft::builder::ExplicitDFTModelBuilder<ValueType> builder(env, ft, symmetries);
227 builder.buildModel(0, 0.0);
228 std::shared_ptr<storm::models::sparse::Model<ValueType>> model = builder.getModel();
229 explorationTimer.stop();
230
231 STORM_LOG_THROW(model->isOfType(storm::models::ModelType::Ctmc), storm::exceptions::NotSupportedException,
232 "Parallel composition only applicable for CTMCs.");
233 std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> ctmc = model->template as<storm::models::sparse::Ctmc<ValueType>>();
234
235 // Apply bisimulation to new CTMC
236 bisimulationTimer.start();
237 ctmc = storm::api::performBisimulationMinimization<ValueType>(ctmc, properties, getBisimOptions<ValueType>())
238 ->template as<storm::models::sparse::Ctmc<ValueType>>();
239 bisimulationTimer.stop();
240
241 if (firstTime) {
242 composedModel = ctmc;
243 firstTime = false;
244 } else {
245 composedModel = storm::builder::ParallelCompositionBuilder<ValueType>::compose(composedModel, ctmc, isAnd);
246 }
247
248 // Apply bisimulation to parallel composition
249 bisimulationTimer.start();
250 composedModel = storm::api::performBisimulationMinimization<ValueType>(composedModel, properties, getBisimOptions<ValueType>())
251 ->template as<storm::models::sparse::Ctmc<ValueType>>();
252 bisimulationTimer.stop();
253
254 STORM_LOG_DEBUG("No. states (Composed): " << composedModel->getNumberOfStates());
255 STORM_LOG_DEBUG("No. transitions (Composed): " << composedModel->getNumberOfTransitions());
256 if (composedModel->getNumberOfStates() <= 15) {
257 STORM_LOG_TRACE("Transition matrix: \n" << composedModel->getTransitionMatrix());
258 } else {
259 STORM_LOG_TRACE("Transition matrix: too big to print");
260 }
261 }
262 if (printInfo) {
263 composedModel->printModelInformationToStream(std::cout);
264 }
265 return composedModel;
266 } else {
267 // No composition was possible
268 explorationTimer.start();
269
270 dft.setRelevantEvents(relevantEvents, env.modelBuilder().isAllowDCForRelevantEvents());
271
272 // Find symmetries
273 storm::dft::storage::DftSymmetries symmetries;
276 STORM_LOG_DEBUG("Found " << symmetries.nrSymmetries() << " symmetries.");
277 STORM_LOG_TRACE("Symmetries: \n" << symmetries);
278 }
279 // Build a single CTMC
280 STORM_LOG_DEBUG("Building Model...");
281
282 storm::dft::builder::ExplicitDFTModelBuilder<ValueType> builder(env, dft, symmetries);
283 builder.buildModel(0, 0.0);
284 std::shared_ptr<storm::models::sparse::Model<ValueType>> model = builder.getModel();
285 if (printInfo) {
286 model->printModelInformationToStream(std::cout);
287 }
288 explorationTimer.stop();
289 STORM_LOG_THROW(model->isOfType(storm::models::ModelType::Ctmc), storm::exceptions::NotSupportedException,
290 "Parallel composition only applicable for CTMCs.");
291 return model->template as<storm::models::sparse::Ctmc<ValueType>>();
292 }
293}
294
295template<typename ValueType>
296typename DFTModelChecker<ValueType>::dft_results DFTModelChecker<ValueType>::checkDFT(storm::dft::DftEnvironment const& env,
297 storm::dft::storage::DFT<ValueType> const& dft,
298 property_vector const& properties,
299 storm::dft::utility::RelevantEvents const& relevantEvents) {
300 explorationTimer.start();
301
302 double const approximationError = env.analysis().isApproximationErrorSet() ? env.analysis().getApproximationError() : 0.0;
303
304 dft.setRelevantEvents(relevantEvents, env.modelBuilder().isAllowDCForRelevantEvents());
305
306 // Find symmetries
307 storm::dft::storage::DftSymmetries symmetries;
310 STORM_LOG_DEBUG("Found " << symmetries.nrSymmetries() << " symmetries.");
311 STORM_LOG_TRACE("Symmetries: \n" << symmetries);
312 }
313
314 if (approximationError > 0.0) {
315 // Comparator for checking the error of the approximation
316 // TODO: better handling of precision for comparison
317 // Comparator precision is currently derived from the linear equation solver's precision.
319 storm::RationalNumber const precisionValue = precisionInfo.first.get_value_or(storm::utility::convertNumber<storm::RationalNumber>(1e-6));
320 ValueType const precision =
321 std::is_same_v<ValueType, storm::RationalFunction> ? storm::utility::zero<ValueType>() : storm::utility::convertNumber<ValueType>(precisionValue);
322 storm::utility::ConstantsComparator<ValueType> comparator(precision);
323
324 // Build approximate Markov Automata for lower and upper bound
325 std::pair<ValueType, ValueType> approxResult = std::make_pair(storm::utility::zero<ValueType>(), storm::utility::zero<ValueType>());
326 std::shared_ptr<storm::models::sparse::Model<ValueType>> model;
327 std::vector<ExtendedValueType> newResult;
328 storm::dft::builder::ExplicitDFTModelBuilder<ValueType> builder(env, dft, symmetries);
329
330 // TODO: compute approximation for all properties simultaneously?
331 std::shared_ptr<const storm::logic::Formula> property = properties[0];
332 if (properties.size() > 1) {
333 STORM_LOG_WARN("Computing approximation only for first property: " << *property);
334 }
335
336 bool probabilityFormula = property->isProbabilityOperatorFormula();
337 STORM_LOG_ASSERT((property->isTimeOperatorFormula() && !probabilityFormula) || (!property->isTimeOperatorFormula() && probabilityFormula),
338 "Probability formula not initialized correctly.");
339 size_t iteration = 0;
340 do {
341 // Iteratively build finer models
342 if (iteration > 0) {
343 explorationTimer.start();
344 }
345 STORM_LOG_DEBUG("Building model...");
346 // TODO refine model using existing model and MC results
347 builder.buildModel(iteration, approximationError, env.analysis().getApproximationHeuristic());
348 explorationTimer.stop();
349 buildingTimer.start();
350
351 // TODO: possible to do bisimulation on approximated model and not on concrete one?
352
353 // Build model for lower bound
354 STORM_LOG_DEBUG("Getting model for lower bound...");
355 model = builder.getModelApproximation(true, !probabilityFormula);
356 // We only output the info from the lower bound as the info for the upper bound is the same
357 if (printInfo) {
358 std::cout << "Model in iteration " << (iteration + 1) << ":\n";
359 model->printModelInformationToStream(std::cout);
360 }
361 buildingTimer.stop();
362
363 if (exportCallback) {
364 exportCallback(model, false);
365 }
366
367 // Check lower bounds
368 newResult = checkModel(env, model, {property});
369 STORM_LOG_ASSERT(newResult.size() == 1, "Wrong size for result vector.");
370 STORM_LOG_THROW(storm::utility::isFinite(newResult[0]), storm::exceptions::NotSupportedException,
371 "Approximation does not work if result might be infinity.");
372 ValueType lowerBound = storm::utility::narrow<ValueType>(newResult[0]);
373 STORM_LOG_ASSERT(iteration == 0 || !comparator.isLess(lowerBound, approxResult.first),
374 "New under-approximation " << lowerBound << " is smaller than old result " << approxResult.first);
375 approxResult.first = std::move(lowerBound);
376
377 // Build model for upper bound
378 STORM_LOG_DEBUG("Getting model for upper bound...");
379 buildingTimer.start();
380 model = builder.getModelApproximation(false, !probabilityFormula);
381 buildingTimer.stop();
382 // Check upper bound
383 newResult = checkModel(env, model, {property});
384 STORM_LOG_ASSERT(newResult.size() == 1, "Wrong size for result vector.");
385 STORM_LOG_THROW(storm::utility::isFinite(newResult[0]), storm::exceptions::NotSupportedException,
386 "Approximation does not work if result might be infinity.");
387 ValueType upperBound = storm::utility::narrow<ValueType>(newResult[0]);
388 STORM_LOG_ASSERT(iteration == 0 || !comparator.isLess(approxResult.second, upperBound),
389 "New over-approximation " << upperBound << " is greater than old result " << approxResult.second);
390 approxResult.second = std::move(upperBound);
391
392 STORM_LOG_ASSERT(comparator.isLess(approxResult.first, approxResult.second) || comparator.isEqual(approxResult.first, approxResult.second),
393 "Under-approximation " << approxResult.first << " is greater than over-approximation " << approxResult.second);
394 totalTimer.stop();
395 STORM_LOG_STATISTICS_LAZY([this, iteration, &approxResult](std::ostream& out) {
396 out << "Result after iteration " << (iteration + 1) << ": (" << approxResult.first << ", " << approxResult.second << ")\n";
397 printTimings(out);
398 return true;
399 });
400 STORM_LOG_DEBUG("Result after iteration " << (iteration + 1) << ": (" << approxResult.first << ", " << approxResult.second << ")");
401
402 totalTimer.start();
403 ++iteration;
404 } while (!isApproximationSufficient(approxResult.first, approxResult.second, approximationError, probabilityFormula));
405
406 // STORM_LOG_INFO("Finished approximation after " << iteration << " iteration" << (iteration > 1 ? "s." : "."));
407 if (printInfo) {
408 model->printModelInformationToStream(std::cout);
409 }
410 // Export the model if required
411 if (exportCallback) {
412 exportCallback(model, true);
413 }
414 dft_results results;
415 results.push_back(approximation_result(std::move(approxResult.first), std::move(approxResult.second)));
416 return results;
417 } else {
418 // Build a single Markov Automaton
419 STORM_LOG_DEBUG("Building Model...");
420 storm::dft::builder::ExplicitDFTModelBuilder<ValueType> builder(env, dft, symmetries);
421 builder.buildModel(0, 0.0);
422 std::shared_ptr<storm::models::sparse::Model<ValueType>> model = builder.getModel();
424 auto ma = std::static_pointer_cast<storm::models::sparse::MarkovAutomaton<ValueType>>(model);
426 }
427 explorationTimer.stop();
428
429 // Print model information
430 if (printInfo) {
431 model->printModelInformationToStream(std::cout);
432 }
433
434 // Export the model if required
435 if (exportCallback) {
436 exportCallback(model, true);
437 }
438
439 // Model checking
440 std::vector<ExtendedValueType> resultsValue = checkModel(env, model, properties);
441 dft_results results;
442 for (auto& result : resultsValue) {
443 results.push_back(std::move(result));
444 }
445 return results;
446 }
447}
448
449template<typename ValueType>
450std::vector<typename DFTModelChecker<ValueType>::ExtendedValueType> DFTModelChecker<ValueType>::checkModel(
451 storm::dft::DftEnvironment const& env, std::shared_ptr<storm::models::sparse::Model<ValueType>>& model, property_vector const& properties) {
452 // Bisimulation
453 if (model->isOfType(storm::models::ModelType::Ctmc) && env.transformation().isUseBisimulation()) {
454 bisimulationTimer.start();
455 STORM_LOG_DEBUG("Bisimulation...");
456 model = storm::api::performBisimulationMinimization<ValueType>(model, properties, getBisimOptions<ValueType>());
457 STORM_LOG_DEBUG("No. states (Bisimulation): " << model->getNumberOfStates());
458 STORM_LOG_DEBUG("No. transitions (Bisimulation): " << model->getNumberOfTransitions());
459 bisimulationTimer.stop();
460 }
461
462 // Check the model
463 STORM_LOG_DEBUG("Model checking...");
464 modelCheckingTimer.start();
465 std::vector<ExtendedValueType> results;
466
467 // Check each property
468 storm::utility::Stopwatch singleModelCheckingTimer;
469 for (auto property : properties) {
470 singleModelCheckingTimer.reset();
471 singleModelCheckingTimer.start();
472 // STORM_PRINT_AND_LOG("Model checking property " << *property << " ...\n");
473 std::unique_ptr<storm::modelchecker::CheckResult> result(
475
476 if (result) {
477 result->filter(storm::modelchecker::ExplicitQualitativeCheckResult<ValueType>(model->getInitialStates()));
478 results.push_back(result->asExplicitQuantitativeCheckResult<ValueType>().getValueVector().front());
479 } else {
480 STORM_LOG_WARN("The property '" << *property << "' could not be checked with the current settings.");
481 results.push_back(-storm::utility::one<ExtendedValueType>());
482 }
483 // STORM_PRINT_AND_LOG("Result (initial states): " << resultValue << '\n');
484 singleModelCheckingTimer.stop();
485 // STORM_PRINT_AND_LOG("Time for model checking: " << singleModelCheckingTimer << ".\n");
486 }
487 modelCheckingTimer.stop();
488 STORM_LOG_DEBUG("Model checking done.");
489 return results;
490}
491
492template<typename ValueType>
493bool DFTModelChecker<ValueType>::isApproximationSufficient(ValueType, ValueType, double, bool) {
494 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Approximation works only for double.");
495}
496
497template<>
498bool DFTModelChecker<double>::isApproximationSufficient(double lowerBound, double upperBound, double approximationError, bool relative) {
499 STORM_LOG_THROW(!std::isnan(lowerBound) && !std::isnan(upperBound), storm::exceptions::NotSupportedException,
500 "Approximation does not work if result is NaN.");
501 if (relative) {
502 return upperBound - lowerBound <= approximationError;
503 } else {
504 return upperBound - lowerBound <= approximationError * (lowerBound + upperBound) / 2;
505 }
506}
507
508template<typename ValueType>
509void DFTModelChecker<ValueType>::printTimings(std::ostream& os) const {
510 os << "Times:\n";
511 os << "Exploration:\t" << explorationTimer << '\n';
512 os << "Building:\t" << buildingTimer << '\n';
513 os << "Bisimulation:\t" << bisimulationTimer << '\n';
514 os << "Modelchecking:\t" << modelCheckingTimer << '\n';
515 os << "Total:\t\t" << totalTimer << '\n';
516}
517
518template<typename ValueType>
519void DFTModelChecker<ValueType>::printResults(dft_results const& results, std::ostream& os) const {
520 bool first = true;
521 os << "Result: [";
522 for (auto result : results) {
523 if (first) {
524 first = false;
525 } else {
526 os << ", ";
527 }
528 boost::variant<std::ostream&> stream(os);
529 boost::apply_visitor(ResultOutputVisitor(), result, stream);
530 }
531 os << "]\n";
532}
533
534template class DFTModelChecker<double>;
536
537} // namespace modelchecker
538} // 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)
SolverEnvironment & solver()
storm::solver::EquationSolverType const & getLinearEquationSolverType() const
std::pair< boost::optional< storm::RationalNumber >, boost::optional< bool > > getPrecisionOfLinearEquationSolver(storm::solver::EquationSolverType const &solverType) const
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)
storm::dft::builder::ApproximationHeuristic getApproximationHeuristic() const
Environment for storm-dft.
AnalysisEnvironment & analysis()
ModelBuilderEnvironment & modelBuilder()
TransformationEnvironment & transformation()
storm::Environment & core()
storm::transformer::EliminationLabelBehavior getLabelBehavior() const
dft_results check(storm::dft::DftEnvironment const &env, storm::dft::storage::DFT< ValueType > const &origDft, property_vector const &properties, storm::dft::utility::RelevantEvents const &relevantEvents={})
Main method for checking DFTs.
std::vector< boost::variant< ExtendedValueType, approximation_result > > dft_results
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:50
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:107
DFTElementCPointer getTopLevelElement() const
Definition DFT.h:211
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:35
#define STORM_LOG_DEBUG(message)
Definition logging.h:28
#define STORM_LOG_STATISTICS_LAZY(...)
Definition logging.h:75
#define STORM_LOG_TRACE(message)
Definition logging.h:22
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:39
storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > createTask(std::shared_ptr< const storm::logic::Formula > const &formula, bool onlyInitialStatesRelevant=false)
std::shared_ptr< storm::models::sparse::Model< ValueType > > performBisimulationMinimization(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, std::vector< std::shared_ptr< storm::logic::Formula const > > const &formulas={}, storm::bisimulation::Options const &options={})
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, bool preferEliminationChecker=false)
std::pair< bool, std::string > isWellFormed(storm::dft::storage::DFT< ValueType > const &dft, bool validForMarkovianAnalysis)
Check whether the DFT is well-formed.
SFTBDDChecker::ValueType ValueType
bool isFinite(ExtendedNumber< ValueType > const &value)
ValueType zero()
Definition constants.cpp:26
ValueType narrow(ExtendedValueType< ValueType > const &value)
Narrows an extended value back into the plain value type, for the interfaces that cannot hold an infi...
ValueType one()
Definition constants.cpp:21
TargetType convertNumber(SourceType const &number)
BisimulationType bisimulationType
Definition Options.h:32
std::optional< storm::RationalNumber > tolerance
Definition Options.h:35