Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
storm-pars.cpp
Go to the documentation of this file.
9
13
19
21
30
34
36
38#include "storm/api/storm.h"
39
44
46
48
50
53
54#include "storm/io/file.h"
59
65
66namespace storm {
67namespace pars {
69 PreprocessResult(std::shared_ptr<storm::models::ModelBase> const& model, bool changed) : changed(changed), model(model) {
70 // Intentionally left empty.
71 }
72
73 bool changed;
74 std::shared_ptr<storm::models::ModelBase> model;
75 boost::optional<std::vector<std::shared_ptr<storm::logic::Formula const>>> formulas;
76};
77
78template<typename ValueType>
79std::vector<storm::storage::ParameterRegion<ValueType>> parseRegions(std::shared_ptr<storm::models::ModelBase> const& model) {
80 std::vector<storm::storage::ParameterRegion<ValueType>> result;
81 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
82 if (regionSettings.isRegionSet()) {
83 result = storm::api::parseRegions<ValueType>(regionSettings.getRegionString(), *model);
84 } else if (regionSettings.isRegionBoundSet()) {
85 result = storm::api::createRegion<ValueType>(regionSettings.getRegionBoundString(), *model);
86 }
87 if (regionSettings.isAssumeGraphPreservingSet()) {
88 // We want to warn the user in case the model is actually not graph preserving.
89 // However, determining graph-preservingness precisely is hard.
90 // As an approximation, we only check if the region intersects 0 or 1.
91 for (auto const& region : result) {
92 for (auto const& variable : region.getVariables()) {
93 if (region.getLowerBoundary(variable) <= storm::utility::zero<typename storm::utility::parametric::CoefficientType<ValueType>::type>() ||
94 region.getUpperBoundary(variable) >= storm::utility::one<typename storm::utility::parametric::CoefficientType<ValueType>::type>()) {
96 "Region "
97 << region
98 << " appears to not preserve the graph structure of the parametric model. If this is the case, set --assume-graph-preserving false.");
99 break;
100 }
101 }
102 }
103 }
104 return result;
105}
106
107template<typename ValueType>
108std::shared_ptr<storm::models::ModelBase> eliminateScc(std::shared_ptr<storm::models::ModelBase> const& model) {
109 storm::utility::Stopwatch eliminationWatch(true);
110 std::shared_ptr<storm::models::ModelBase> result;
111 if (model->isOfType(storm::models::ModelType::Dtmc)) {
112 STORM_PRINT("Applying scc elimination\n");
113 auto sparseModel = model->as<storm::models::sparse::Model<ValueType>>();
114 auto matrix = sparseModel->getTransitionMatrix();
115 auto backwardsTransitionMatrix = matrix.transpose();
116
118 auto decomposition = storm::storage::StronglyConnectedComponentDecomposition<ValueType>(matrix, options);
119
120 storm::storage::BitVector selectedStates(matrix.getRowCount());
121 storm::storage::BitVector selfLoopStates(matrix.getRowCount());
122 for (size_t i = 0; i < decomposition.size(); ++i) {
123 auto scc = decomposition.getBlock(i);
124 if (scc.size() > 1) {
125 auto statesScc = scc.getStates();
126 std::vector<uint_fast64_t> entryStates;
127 for (auto state : statesScc) {
128 auto row = backwardsTransitionMatrix.getRow(state);
129 bool found = false;
130 for (auto backState : row) {
131 if (!scc.containsState(backState.getColumn())) {
132 found = true;
133 }
134 }
135 if (found) {
136 entryStates.push_back(state);
137 selfLoopStates.set(state);
138 } else {
139 selectedStates.set(state);
140 }
141 }
142
143 if (entryStates.size() != 1) {
144 STORM_LOG_THROW(entryStates.size() > 1, storm::exceptions::NotImplementedException,
145 "state elimination not implemented for scc with more than 1 entry points");
146 }
147 }
148 }
149
151 storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(backwardsTransitionMatrix, true);
152 auto actionRewards = std::vector<ValueType>(matrix.getRowCount(), storm::utility::zero<ValueType>());
153 storm::solver::stateelimination::NondeterministicModelStateEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions,
154 actionRewards);
155 for (auto state : selectedStates) {
156 stateEliminator.eliminateState(state, true);
157 }
158 for (auto state : selfLoopStates) {
159 auto row = flexibleMatrix.getRow(state);
160 stateEliminator.eliminateLoop(state);
161 }
162 selectedStates.complement();
163 auto keptRows = matrix.getRowFilter(selectedStates);
164 storm::storage::SparseMatrix<ValueType> newTransitionMatrix = flexibleMatrix.createSparseMatrix(keptRows, selectedStates);
165 // TODO @Jip: note that rewards get lost
166 result = std::make_shared<storm::models::sparse::Dtmc<ValueType>>(std::move(newTransitionMatrix),
167 sparseModel->getStateLabeling().getSubLabeling(selectedStates));
168
169 eliminationWatch.stop();
170 STORM_PRINT("\nTime for scc elimination: " << eliminationWatch << ".\n\n");
171 result->printModelInformationToStream(std::cout);
172 } else if (model->isOfType(storm::models::ModelType::Mdp)) {
173 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException,
174 "Unable to perform SCC elimination for monotonicity analysis on MDP: Not mplemented");
175 } else {
176 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Unable to perform monotonicity analysis on the provided model type.");
177 }
178 return result;
179}
180
181template<typename ValueType>
182std::shared_ptr<storm::models::ModelBase> simplifyModel(std::shared_ptr<storm::models::ModelBase> const& model, cli::SymbolicInput const& input) {
183 storm::utility::Stopwatch simplifyingWatch(true);
184 std::shared_ptr<storm::models::ModelBase> result;
185 if (model->isOfType(storm::models::ModelType::Dtmc)) {
187 *(model->template as<storm::models::sparse::Dtmc<ValueType>>()));
188
189 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::api::extractFormulasFromProperties(input.properties);
190 STORM_LOG_THROW(formulas.begin() != formulas.end(), storm::exceptions::NotSupportedException, "Only one formula at the time supported");
191
192 if (!simplifier.simplify(*(formulas[0]))) {
193 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Simplifying the model was not successfull.");
194 }
195 result = simplifier.getSimplifiedModel();
196 } else if (model->isOfType(storm::models::ModelType::Mdp)) {
198 *(model->template as<storm::models::sparse::Mdp<ValueType>>()));
199
200 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::api::extractFormulasFromProperties(input.properties);
201 STORM_LOG_THROW(formulas.begin() != formulas.end(), storm::exceptions::NotSupportedException, "Only one formula at the time supported");
202
203 if (!simplifier.simplify(*(formulas[0]))) {
204 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Simplifying the model was not successfull.");
205 }
206 result = simplifier.getSimplifiedModel();
207 } else {
208 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Unable to perform monotonicity analysis on the provided model type.");
209 }
210
211 simplifyingWatch.stop();
212 STORM_PRINT("\nTime for model simplification: " << simplifyingWatch << ".\n\n");
213 result->printModelInformationToStream(std::cout);
214 return result;
215}
216
217template<typename ValueType>
220 auto bisimulationSettings = storm::settings::getModule<storm::settings::modules::BisimulationSettings>();
221 auto parametricSettings = storm::settings::getModule<storm::settings::modules::ParametricSettings>();
222 auto transformationSettings = storm::settings::getModule<storm::settings::modules::TransformationSettings>();
223 auto monSettings = storm::settings::getModule<storm::settings::modules::MonotonicitySettings>();
224 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
225
226 PreprocessResult result(model, false);
227 // TODO: why only simplify in these modes
228 if (parametricSettings.getOperationMode() == storm::pars::utility::ParametricMode::Monotonicity ||
229 parametricSettings.getOperationMode() == storm::pars::utility::ParametricMode::Feasibility) {
230 STORM_LOG_THROW(!input.properties.empty(), storm::exceptions::InvalidSettingsException, "Simplification requires property to be specified");
231 result.model = storm::pars::simplifyModel<ValueType>(result.model, input);
232 result.changed = true;
233 }
234
235 if (result.model->isOfType(storm::models::ModelType::MarkovAutomaton)) {
237 result.changed = true;
238 }
239
240 if (mpi.applyBisimulation) {
242 bisimulationSettings, regionSettings.isAssumeGraphPreservingSet());
243 result.changed = true;
244 }
245
246 if (parametricSettings.isLinearToSimpleEnabled()) {
247 STORM_LOG_INFO("Transforming linear to simple...");
249 result.model = transformer.transform(*result.model->template as<storm::models::sparse::Dtmc<RationalFunction>>(), true);
250 result.changed = true;
251 }
252
253 if (parametricSettings.isBigStepEnabled()) {
257 auto bigStepResult = tt.bigStep(*result.model->template as<storm::models::sparse::Dtmc<RationalFunction>>(), checkTask);
258 result.model = std::make_shared<storm::models::sparse::Dtmc<RationalFunction>>(bigStepResult.first);
259
260 if (mpi.applyBisimulation) {
262 bisimulationSettings, regionSettings.isAssumeGraphPreservingSet());
263 }
264 result.changed = true;
265 }
266
267 if (transformationSettings.isChainEliminationSet() && model->isOfType(storm::models::ModelType::MarkovAutomaton)) {
268 // TODO: Why only on MAs?
269 auto eliminationResult =
271 storm::api::extractFormulasFromProperties(input.properties), transformationSettings.getLabelBehavior());
272 result.model = eliminationResult.first;
273 // Set transformed properties as new properties in input
274 result.formulas = eliminationResult.second;
275 result.changed = true;
276 }
277
278 if (parametricSettings.transformContinuousModel() &&
279 (model->isOfType(storm::models::ModelType::Ctmc) || model->isOfType(storm::models::ModelType::MarkovAutomaton))) {
282 result.model = transformResult.first;
283 // Set transformed properties as new properties in input
284 result.formulas = transformResult.second;
285 result.changed = true;
286 }
287
288 if (monSettings.isSccEliminationSet()) {
289 // TODO move this into the API?
290 result.model = storm::pars::eliminateScc<ValueType>(result.model);
291 result.changed = true;
292 }
293
294 return result;
295}
296
297template<storm::dd::DdType DdType, typename ValueType>
300 auto bisimulationSettings = storm::settings::getModule<storm::settings::modules::BisimulationSettings>();
301
302 PreprocessResult result(model, false);
303
305 // Currently, hybrid engine for parametric models just refers to building the model symbolically.
306 STORM_LOG_INFO("Translating symbolic model to sparse model...");
308 result.changed = true;
309 // Invoke preprocessing on the sparse model
310 PreprocessResult sparsePreprocessingResult =
311 storm::pars::preprocessSparseModel<ValueType>(result.model->as<storm::models::sparse::Model<ValueType>>(), input, mpi);
312 if (sparsePreprocessingResult.changed) {
313 result.model = sparsePreprocessingResult.model;
314 result.formulas = sparsePreprocessingResult.formulas;
315 }
316 } else {
317 STORM_LOG_ASSERT(mpi.engine == storm::utility::Engine::Dd, "Expected Dd engine.");
318 if (mpi.applyBisimulation) {
320 bisimulationSettings, mpi);
321 result.changed = true;
322 }
323 }
324 return result;
325}
326
327template<storm::dd::DdType DdType, typename ValueType>
328PreprocessResult preprocessModel(std::shared_ptr<storm::models::ModelBase> const& model, cli::SymbolicInput const& input,
330 storm::utility::Stopwatch preprocessingWatch(true);
331
332 PreprocessResult result(model, false);
333 if (model->isSparseModel()) {
334 result = storm::pars::preprocessSparseModel<ValueType>(result.model->as<storm::models::sparse::Model<ValueType>>(), input, mpi);
335 } else {
336 STORM_LOG_ASSERT(model->isSymbolicModel(), "Unexpected model type.");
337 result = storm::pars::preprocessDdModel<DdType, ValueType>(result.model->as<storm::models::symbolic::Model<DdType, ValueType>>(), input, mpi);
338 }
339
340 if (result.changed) {
341 STORM_PRINT_AND_LOG("\nTime for model preprocessing: " << preprocessingWatch << ".\n\n");
342 }
343 return result;
344}
345
346template<typename ValueType>
348 std::vector<storm::storage::ParameterRegion<ValueType>> const& regions,
350 STORM_LOG_THROW(regions.size() == 1, storm::exceptions::NotSupportedException, "Region verification is supported for a (single) region only.");
351 storm::storage::ParameterRegion<ValueType> const& region = regions.front();
352 STORM_LOG_THROW(input.properties.size() == 1, storm::exceptions::NotSupportedException, "Region verification is supported for a (single) property only.");
353 auto const& property = input.properties.front();
354
355 auto const& rvs = storm::settings::getModule<storm::settings::modules::RegionVerificationSettings>();
356 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
357
358 auto engine = rvs.getRegionCheckEngine();
359 bool graphPreserving = regionSettings.isAssumeGraphPreservingSet();
360
361 STORM_LOG_THROW(graphPreserving || engine == storm::modelchecker::RegionCheckEngine::RobustParameterLifting, storm::exceptions::NotSupportedException,
362 "Selected region verification engine (--regionverif:engine) requires the assumption that the region is graph-preserving "
363 "(--assume-graph-preserving true).");
364
365 auto splittingStrategy = storm::modelchecker::RegionSplittingStrategy();
366
367 splittingStrategy.heuristic = rvs.getRegionSplittingHeuristic();
368 splittingStrategy.estimateKind = rvs.getRegionSplittingEstimateMethod();
369 if (rvs.isSplittingThresholdSet()) {
370 splittingStrategy.maxSplitDimensions = rvs.getSplittingThreshold();
371 }
372
373 auto parsedDiscreteVars = storm::api::parseVariableList<ValueType>(regionSettings.getDiscreteVariablesString(), *model);
374 std::set<typename storm::storage::ParameterRegion<ValueType>::VariableType> discreteVariables(parsedDiscreteVars.begin(), parsedDiscreteVars.end());
375
376 storm::utility::Stopwatch watch(true);
377
378 auto const& settings = storm::api::RefinementOptions<ValueType>{
379 model,
380 *(property.getRawFormula()),
381 engine,
382 splittingStrategy,
383 monotonicitySettings,
384 discreteVariables,
385 true, // allow model simplification
386 graphPreserving,
387 false // preconditions not yet validated
388 };
389
390 if (storm::api::verifyRegion<ValueType>(settings, region)) {
391 STORM_PRINT_AND_LOG("Formula is satisfied by all parameter instantiations.\n");
392 } else {
393 STORM_PRINT_AND_LOG("Formula is not satisfied by all parameter instantiations.\n");
394 }
395 STORM_PRINT_AND_LOG("Time for model checking: " << watch << ".\n");
396}
397
398template<typename ValueType>
400 std::vector<storm::storage::ParameterRegion<ValueType>> const& regions,
402 uint64_t monThresh = 0) {
403 STORM_LOG_ASSERT(!regions.empty(), "Can not analyze an empty set of regions.");
404 STORM_LOG_THROW(regions.size() == 1, storm::exceptions::NotSupportedException, "Region refinement is not supported for multiple initial regions.");
405 STORM_LOG_THROW(input.properties.size() == 1, storm::exceptions::NotSupportedException, "Region verification is supported for a (single) property only.");
406 auto const& property = input.properties.front();
407
408 auto parametricSettings = storm::settings::getModule<storm::settings::modules::ParametricSettings>();
409 auto rvs = storm::settings::getModule<storm::settings::modules::RegionVerificationSettings>();
410 auto partitionSettings = storm::settings::getModule<storm::settings::modules::PartitionSettings>();
411 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
412
413 ValueType refinementThreshold = storm::utility::convertNumber<ValueType>(partitionSettings.getCoverageThreshold());
414 std::optional<uint64_t> optionalDepthLimit;
415 if (partitionSettings.isDepthLimitSet()) {
416 optionalDepthLimit = partitionSettings.getDepthLimit();
417 }
418
420 STORM_PRINT_AND_LOG("Analyzing parameter region " << regions.front());
421
422 auto engine = rvs.getRegionCheckEngine();
423 STORM_PRINT_AND_LOG(" using " << engine);
424
425 auto splittingStrategy = storm::modelchecker::RegionSplittingStrategy();
426
427 splittingStrategy.heuristic = rvs.getRegionSplittingHeuristic();
428 splittingStrategy.estimateKind = rvs.getRegionSplittingEstimateMethod();
429 if (rvs.isSplittingThresholdSet()) {
430 splittingStrategy.maxSplitDimensions = rvs.getSplittingThreshold();
431 }
432
433 bool graphPreserving = regionSettings.isAssumeGraphPreservingSet();
434
435 auto parsedDiscreteVars = storm::api::parseVariableList<ValueType>(regionSettings.getDiscreteVariablesString(), *model);
436 std::set<typename storm::storage::ParameterRegion<ValueType>::VariableType> discreteVariables(parsedDiscreteVars.begin(), parsedDiscreteVars.end());
437
438 STORM_PRINT_AND_LOG(" and splitting heuristic " << splittingStrategy.heuristic);
439 if (monotonicitySettings.useMonotonicity) {
440 STORM_PRINT_AND_LOG(" with local monotonicity and");
441 }
442
443 STORM_PRINT_AND_LOG(" with iterative refinement until "
444 << (1.0 - partitionSettings.getCoverageThreshold()) * 100.0 << "% is covered."
445 << (partitionSettings.isDepthLimitSet() ? " Depth limit is " + std::to_string(partitionSettings.getDepthLimit()) + "." : "") << '\n');
446
448 storm::utility::Stopwatch watch(true);
449
451 model,
452 storm::api::createTask<ValueType>(property.getRawFormula(), true),
453 engine,
454 splittingStrategy,
455 monotonicitySettings,
456 discreteVariables,
457 true, // allow model simplification
458 graphPreserving,
459 false // preconditions not yet validated
460 };
461 std::unique_ptr<storm::modelchecker::CheckResult> result = storm::api::checkAndRefineRegionWithSparseEngine<ValueType>(
462 settings, regions.front(), refinementThreshold, optionalDepthLimit, storm::modelchecker::RegionResultHypothesis::Unknown, monThresh);
463 watch.stop();
464 printInitialStatesResult<ValueType>(result, &watch);
465
466 if (parametricSettings.exportResultToFile()) {
467 storm::api::exportRegionCheckResultToFile<ValueType>(result, parametricSettings.exportResultPath());
468 }
469}
470
472 auto ioSettings = storm::settings::getModule<storm::settings::modules::IOSettings>();
473 auto buildSettings = storm::settings::getModule<storm::settings::modules::BuildSettings>();
474 auto parSettings = storm::settings::getModule<storm::settings::modules::ParametricSettings>();
475 auto monSettings = storm::settings::getModule<storm::settings::modules::MonotonicitySettings>();
476 auto sampleSettings = storm::settings::getModule<storm::settings::modules::SamplingSettings>();
477 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
478
480 storm::exceptions::InvalidSettingsException, "The selected engine is not supported for parametric models.");
481 STORM_LOG_THROW(parSettings.hasOperationModeBeenSet(), storm::exceptions::InvalidSettingsException, "An operation mode must be selected with --mode");
482 std::shared_ptr<storm::models::ModelBase> model;
483 if (!buildSettings.isNoBuildModelSet()) {
484 model = storm::cli::buildModel(input, ioSettings, mpi);
485 }
486
487 STORM_LOG_THROW(model, storm::exceptions::InvalidSettingsException, "No input model.");
488 if (model) {
489 model->printModelInformationToStream(std::cout);
490 }
491
492 using ValueType = storm::RationalFunction;
493 auto const DdType = storm::dd::DdType::Sylvan;
494 STORM_LOG_THROW(model->supportsParameters(), storm::exceptions::UnexpectedException, "Expected a parametric model.");
495 STORM_LOG_THROW(model->isSparseModel() || model->getDdType().value() == DdType, storm::exceptions::UnexpectedException,
496 "Expected type of model representation.");
497
498 // If minimization is active and the model is parametric, parameters might be minimized away because they are inconsequential.
499 // This is the set of all such inconsequential parameters.
500 std::set<RationalFunctionVariable> omittedParameters;
501
502 if (model) {
503 auto preprocessingResult = storm::pars::preprocessModel<DdType, ValueType>(model, input, mpi);
504 if (preprocessingResult.changed) {
505 if (model->isOfType(models::ModelType::Dtmc) || model->isOfType(models::ModelType::Mdp)) {
506 auto const previousParams = storm::models::sparse::getAllParameters(*model->template as<storm::models::sparse::Model<ValueType>>());
507 auto const currentParams =
508 storm::models::sparse::getAllParameters(*(preprocessingResult.model)->template as<storm::models::sparse::Model<ValueType>>());
509 for (auto const& variable : previousParams) {
510 if (!currentParams.count(variable)) {
511 omittedParameters.insert(variable);
512 }
513 }
514 }
515 model = preprocessingResult.model;
516
517 if (preprocessingResult.formulas) {
518 std::vector<storm::jani::Property> newProperties;
519 for (size_t i = 0; i < preprocessingResult.formulas.get().size(); ++i) {
520 auto formula = preprocessingResult.formulas.get().at(i);
521 STORM_LOG_ASSERT(i < input.properties.size(), "Index " << i << " greater than number of properties.");
522 storm::jani::Property property = input.properties.at(i);
523 newProperties.push_back(storm::jani::Property(property.getName(), formula, property.getUndefinedConstants(), property.getComment()));
524 }
525 input.properties = newProperties;
526 }
527 model->printModelInformationToStream(std::cout);
528 }
529 }
530
531 std::vector<storm::storage::ParameterRegion<ValueType>> regions = parseRegions<ValueType>(model);
532 if (!model) {
533 return;
534 } else {
535 storm::cli::castAndApply(model, [&input](auto const& m) { storm::cli::exportModel(m, input); });
536 }
537
538 // TODO move this.
539 storm::api::MonotonicitySetting monotonicitySettings(parSettings.isUseMonotonicitySet(), false, monSettings.isUsePLABoundsSet());
540 uint64_t monThresh = monSettings.getMonotonicityThreshold();
541
542 auto mode = parSettings.getOperationMode();
544 STORM_LOG_INFO("Solution function mode started.");
545 STORM_LOG_THROW(regions.empty(), storm::exceptions::InvalidSettingsException,
546 "Solution function computations cannot be restricted to specific regions");
547 STORM_LOG_ERROR_COND(!regionSettings.isAssumeGraphPreservingSet(), "Solution function computations assume graph preservation.");
548
549 if (model->isSparseModel()) {
551 } else {
553 }
555 STORM_LOG_INFO("Monotonicity mode started.");
556 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Monotonicity analysis is only supported on sparse models.");
559 STORM_LOG_INFO("Feasibility mode started.");
560 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Feasibility analysis is only supported on sparse models.");
561 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::api::extractFormulasFromProperties(input.properties);
562 STORM_LOG_THROW(formulas.size() == 1, storm::exceptions::InvalidSettingsException,
563 "Feasibility analysis is only supported for single-objective properties.");
564 auto formula = formulas[0];
565 storm::pars::performFeasibility<ValueType>(model->as<storm::models::sparse::Model<ValueType>>(),
566 createFeasibilitySynthesisTaskFromSettings(formula, regions), omittedParameters, monotonicitySettings);
568 STORM_LOG_INFO("Verification mode started.");
569 STORM_LOG_THROW(input.properties.size() == 1, storm::exceptions::InvalidSettingsException,
570 "Verification analysis is only supported for single-objective properties.");
571 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Verification analysis is only supported on sparse models.");
572 verifyRegionWithSparseEngine(model->as<storm::models::sparse::Model<ValueType>>(), input, regions, monotonicitySettings);
573
575 STORM_LOG_INFO("Partition mode started.");
576 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException,
577 "Parameter space partitioning is only supported on sparse models.");
578 STORM_LOG_THROW(regions.size() == 1, storm::exceptions::InvalidSettingsException, "Partitioning requires a (single) initial region.");
579
580 // TODO Partition mode does not support monotonicity. This should generally be possible.
581 // TODO here setting monotone parameters from the outside may actually be useful
582
583 assert(!monotonicitySettings.useOnlyGlobalMonotonicity);
584 assert(!monotonicitySettings.useBoundsFromPLA);
586 monThresh);
588 STORM_LOG_INFO("Sampling mode started.");
589 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Sampling analysis is currently only supported on sparse models.");
590 // TODO unclear why this only works for sparse models?
591
592 std::string samplesAsString = sampleSettings.getSamples();
594 if (!samplesAsString.empty()) {
595 samples = parseSamples<ValueType>(model, samplesAsString, sampleSettings.isSamplesAreGraphPreservingSet());
596 samples.exact = sampleSettings.isSampleExactSet();
597 }
598 if (!samples.empty()) {
599 STORM_LOG_TRACE("Sampling the model at given points.");
600
601 if (samples.exact) {
602 verifyPropertiesAtSamplePointsWithSparseEngine<ValueType, storm::RationalNumber>(model->as<storm::models::sparse::Model<ValueType>>(), input,
603 samples);
604 } else {
605 verifyPropertiesAtSamplePointsWithSparseEngine<ValueType, double>(model->as<storm::models::sparse::Model<ValueType>>(), input, samples);
606 }
607 }
608 } else {
609 STORM_LOG_ASSERT(false, "Unknown operation mode.");
610 }
611}
612
614 auto coreSettings = storm::settings::getModule<storm::settings::modules::CoreSettings>();
615 auto engine = coreSettings.getEngine();
617 engine != storm::utility::Engine::Dd || engine != storm::utility::Engine::Hybrid || coreSettings.getDdLibraryType() == storm::dd::DdType::Sylvan,
618 "The selected DD library does not support parametric models. Switching to Sylvan...");
619
620 // Parse and preprocess symbolic input (PRISM, JANI, properties, etc.)
621 auto symbolicInput = storm::cli::parseSymbolicInput();
623 std::tie(symbolicInput, mpi) = storm::cli::preprocessSymbolicInput(symbolicInput);
627 processInput(std::move(symbolicInput), mpi);
628}
629} // namespace pars
630} // namespace storm
631
635int main(const int argc, const char** argv) {
636 try {
637 return storm::cli::process("Storm-pars", "storm-pars", storm::settings::initializeParsSettings, storm::pars::processOptions, argc, argv);
638 } catch (storm::exceptions::BaseException const& exception) {
639 STORM_LOG_ERROR("An exception caused Storm-pars to terminate. The message of the exception is: " << exception.what());
640 return 1;
641 } catch (std::exception const& exception) {
642 STORM_LOG_ERROR("An unexpected exception occurred and caused Storm-pars to terminate. The message of this exception is: " << exception.what());
643 return 2;
644 }
645}
This class represents the base class of all exception classes.
virtual const char * what() const noexcept override
Retrieves the message associated with this exception.
This class represents a discrete-time Markov chain.
Definition Dtmc.h:14
This class represents a Markov automaton.
This class represents a (discrete-time) Markov decision process.
Definition Mdp.h:14
Base class for all sparse models.
Definition Model.h:32
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:197
Base class for all symbolic models.
Definition Model.h:45
void eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions)
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void complement()
Negates all bits in the bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
The flexible sparse matrix is used during state elimination.
storm::storage::SparseMatrix< ValueType > createSparseMatrix()
Creates a sparse matrix from the flexible sparse matrix.
row_type & getRow(index_type)
Returns an object representing the given row.
A class that holds a possibly non-square matrix in the compressed row storage format.
This class represents the decomposition of a graph-like structure into its strongly connected compone...
Shorthand for std::unordered_map<T, uint64_t>.
Definition BigStep.h:177
std::pair< models::sparse::Dtmc< RationalFunction >, std::map< UniPoly, Annotation > > bigStep(models::sparse::Dtmc< RationalFunction > const &model, modelchecker::CheckTask< logic::Formula, RationalFunction > const &checkTask)
Perform big-step on the given model and the given checkTask.
Definition BigStep.cpp:387
std::shared_ptr< storm::models::sparse::Dtmc< RationalFunction > > transform(storm::models::sparse::Dtmc< RationalFunction > const &dtmc, bool keepStateValuations=false) const
Transforms a pDTMC that has linear transitions (e.g.
This class performs different steps to simplify the given (parametric) model.
This class performs different steps to simplify the given (parametric) model.
A class that provides convenience operations to display run times.
Definition Stopwatch.h:14
void stop()
Stop stopwatch and add measured time to total time.
Definition Stopwatch.cpp:42
#define STORM_LOG_INFO(message)
Definition logging.h:24
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#define STORM_LOG_ERROR(message)
Definition logging.h:26
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:52
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
#define STORM_PRINT_AND_LOG(message)
Definition macros.h:68
#define STORM_PRINT(message)
Define the macros that print information and optionally also log it.
Definition macros.h:62
std::pair< std::shared_ptr< storm::models::sparse::Model< ValueType > >, std::vector< std::shared_ptr< storm::logic::Formula const > > > eliminateNonMarkovianChains(std::shared_ptr< storm::models::sparse::MarkovAutomaton< ValueType > > const &ma, std::vector< std::shared_ptr< storm::logic::Formula const > > const &formulas, storm::transformer::EliminationLabelBehavior labelBehavior)
Eliminates chains of non-Markovian states from a given Markov Automaton.
std::shared_ptr< storm::models::sparse::Model< ValueType > > transformSymbolicToSparseModel(std::shared_ptr< storm::models::symbolic::Model< Type, ValueType > > const &symbolicModel, std::vector< std::shared_ptr< storm::logic::Formula const > > const &formulas=std::vector< std::shared_ptr< storm::logic::Formula const > >())
Transforms the given symbolic model to a sparse model.
std::pair< std::shared_ptr< storm::models::sparse::Model< ValueType > >, std::vector< std::shared_ptr< storm::logic::Formula const > > > transformContinuousToDiscreteTimeSparseModel(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, std::vector< std::shared_ptr< storm::logic::Formula const > > const &formulas)
Transforms the given continuous model to a discrete time model.
std::vector< std::shared_ptr< storm::logic::Formula const > > extractFormulasFromProperties(std::vector< storm::jani::Property > const &properties)
void exportModel(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, SymbolicInput const &input)
auto castAndApply(std::shared_ptr< storm::models::ModelBase > const &model, auto const &callback)
std::shared_ptr< storm::models::sparse::Model< ValueType > > preprocessSparseModelBisimulation(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, SymbolicInput const &input, storm::settings::modules::BisimulationSettings const &bisimulationSettings, bool graphPreserving=true)
SymbolicInput parseSymbolicInput()
int process(std::string const &name, std::string const &executableName, std::function< void(std::string const &, std::string const &)> initSettingsFunc, std::function< void(void)> processOptionsFunc, const int argc, const char **argv)
Processes the options and returns the exit code.
Definition cli.cpp:84
std::shared_ptr< storm::models::sparse::Model< ValueType > > preprocessSparseMarkovAutomaton(std::shared_ptr< storm::models::sparse::MarkovAutomaton< ValueType > > const &model)
std::pair< SymbolicInput, ModelProcessingInformation > preprocessSymbolicInput(SymbolicInput const &input)
std::shared_ptr< storm::models::ModelBase > buildModel(SymbolicInput const &input, storm::settings::modules::IOSettings const &ioSettings, ModelProcessingInformation const &mpi)
void printModelCheckingProperty(storm::jani::Property const &property)
std::shared_ptr< storm::models::Model< ExportValueType > > preprocessDdModelBisimulation(std::shared_ptr< storm::models::symbolic::Model< DdType, ValueType > > const &model, SymbolicInput const &input, storm::settings::modules::BisimulationSettings const &bisimulationSettings, ModelProcessingInformation const &mpi)
@ RobustParameterLifting
Parameter lifting approach based on robust markov models instead of generating nondeterminism.
std::set< storm::RationalFunctionVariable > getAllParameters(Model< storm::RationalFunction > const &model)
Get all parameters (probability, rewards, and rates) occurring in the model.
Definition Model.cpp:728
std::shared_ptr< storm::models::ModelBase > simplifyModel(std::shared_ptr< storm::models::ModelBase > const &model, cli::SymbolicInput const &input)
void parameterSpacePartitioningWithSparseEngine(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, cli::SymbolicInput const &input, std::vector< storm::storage::ParameterRegion< ValueType > > const &regions, storm::api::MonotonicitySetting monotonicitySettings=storm::api::MonotonicitySetting(), uint64_t monThresh=0)
void analyzeMonotonicity(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, cli::SymbolicInput const &input, std::vector< storm::storage::ParameterRegion< ValueType > > const &regions)
void processOptions()
PreprocessResult preprocessSparseModel(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, cli::SymbolicInput const &input, storm::cli::ModelProcessingInformation const &mpi)
std::shared_ptr< storm::models::ModelBase > eliminateScc(std::shared_ptr< storm::models::ModelBase > const &model)
void computeSolutionFunctionsWithSymbolicEngine(std::shared_ptr< storm::models::symbolic::Model< DdType, ValueType > > const &model, cli::SymbolicInput const &input)
PreprocessResult preprocessDdModel(std::shared_ptr< storm::models::symbolic::Model< DdType, ValueType > > const &model, cli::SymbolicInput const &input, storm::cli::ModelProcessingInformation const &mpi)
void processInput(cli::SymbolicInput &&input, storm::cli::ModelProcessingInformation const &mpi)
PreprocessResult preprocessModel(std::shared_ptr< storm::models::ModelBase > const &model, cli::SymbolicInput const &input, storm::cli::ModelProcessingInformation const &mpi)
void verifyRegionWithSparseEngine(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, cli::SymbolicInput const &input, std::vector< storm::storage::ParameterRegion< ValueType > > const &regions, storm::api::MonotonicitySetting monotonicitySettings=storm::api::MonotonicitySetting())
std::vector< storm::storage::ParameterRegion< ValueType > > parseRegions(std::shared_ptr< storm::models::ModelBase > const &model)
std::shared_ptr< FeasibilitySynthesisTask const > createFeasibilitySynthesisTaskFromSettings(std::shared_ptr< storm::logic::Formula const > const &formula, std::vector< storm::storage::ParameterRegion< storm::RationalFunction > > const &regions)
void computeSolutionFunctionsWithSparseEngine(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, cli::SymbolicInput const &input)
void initializeParsSettings(std::string const &name, std::string const &executableName)
carl::RationalFunction< Polynomial, true > RationalFunction
int main(const int argc, const char **argv)
Main entry point of the executable storm-pars.
std::vector< storm::jani::Property > properties
boost::optional< std::vector< std::shared_ptr< storm::logic::Formula const > > > formulas
PreprocessResult(std::shared_ptr< storm::models::ModelBase > const &model, bool changed)
std::shared_ptr< storm::models::ModelBase > model