Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
storm-pars.cpp
Go to the documentation of this file.
25#include "storm/api/storm.h"
41
42namespace storm {
43namespace pars {
45 PreprocessResult(std::shared_ptr<storm::models::ModelBase> const& model, bool changed) : changed(changed), model(model) {
46 // Intentionally left empty.
47 }
48
49 bool changed;
50 std::shared_ptr<storm::models::ModelBase> model;
51 boost::optional<std::vector<std::shared_ptr<storm::logic::Formula const>>> formulas;
52};
53
54template<typename ValueType>
55std::vector<storm::storage::ParameterRegion<ValueType>> parseRegions(std::shared_ptr<storm::models::ModelBase> const& model) {
56 std::vector<storm::storage::ParameterRegion<ValueType>> result;
57 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
58 if (regionSettings.isRegionSet()) {
59 result = storm::api::parseRegions<ValueType>(regionSettings.getRegionString(), *model);
60 } else if (regionSettings.isRegionBoundSet()) {
61 result = storm::api::createRegion<ValueType>(regionSettings.getRegionBoundString(), *model);
62 }
63 if (regionSettings.isAssumeGraphPreservingSet()) {
64 // We want to warn the user in case the model is actually not graph preserving.
65 // However, determining graph-preservingness precisely is hard.
66 // As an approximation, we only check if the region intersects 0 or 1.
67 for (auto const& region : result) {
68 for (auto const& variable : region.getVariables()) {
69 if (region.getLowerBoundary(variable) <= storm::utility::zero<typename storm::utility::parametric::CoefficientType<ValueType>::type>() ||
70 region.getUpperBoundary(variable) >= storm::utility::one<typename storm::utility::parametric::CoefficientType<ValueType>::type>()) {
72 "Region "
73 << region
74 << " appears to not preserve the graph structure of the parametric model. If this is the case, set --assume-graph-preserving false.");
75 break;
76 }
77 }
78 }
79 }
80 return result;
81}
82
83template<typename ValueType>
84std::shared_ptr<storm::models::ModelBase> eliminateScc(std::shared_ptr<storm::models::ModelBase> const& model) {
85 storm::utility::Stopwatch eliminationWatch(true);
86 std::shared_ptr<storm::models::ModelBase> result;
87 if (model->isOfType(storm::models::ModelType::Dtmc)) {
88 STORM_PRINT("Applying scc elimination\n");
89 auto sparseModel = model->as<storm::models::sparse::Model<ValueType>>();
90 auto matrix = sparseModel->getTransitionMatrix();
91 auto backwardsTransitionMatrix = matrix.transpose();
92
95
96 storm::storage::BitVector selectedStates(matrix.getRowCount());
97 storm::storage::BitVector selfLoopStates(matrix.getRowCount());
98 for (size_t i = 0; i < decomposition.size(); ++i) {
99 auto scc = decomposition.getBlock(i);
100 if (scc.size() > 1) {
101 auto statesScc = scc.getStates();
102 std::vector<uint_fast64_t> entryStates;
103 for (auto state : statesScc) {
104 auto row = backwardsTransitionMatrix.getRow(state);
105 bool found = false;
106 for (auto backState : row) {
107 if (!scc.containsState(backState.getColumn())) {
108 found = true;
109 }
110 }
111 if (found) {
112 entryStates.push_back(state);
113 selfLoopStates.set(state);
114 } else {
115 selectedStates.set(state);
116 }
117 }
118
119 if (entryStates.size() != 1) {
120 STORM_LOG_THROW(entryStates.size() > 1, storm::exceptions::NotImplementedException,
121 "state elimination not implemented for scc with more than 1 entry points");
122 }
123 }
124 }
125
127 storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(backwardsTransitionMatrix, true);
128 auto actionRewards = std::vector<ValueType>(matrix.getRowCount(), storm::utility::zero<ValueType>());
129 storm::solver::stateelimination::NondeterministicModelStateEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions,
130 actionRewards);
131 for (auto state : selectedStates) {
132 stateEliminator.eliminateState(state, true);
133 }
134 for (auto state : selfLoopStates) {
135 auto row = flexibleMatrix.getRow(state);
136 stateEliminator.eliminateLoop(state);
137 }
138 selectedStates.complement();
139 auto keptRows = matrix.getRowFilter(selectedStates);
140 storm::storage::SparseMatrix<ValueType> newTransitionMatrix = flexibleMatrix.createSparseMatrix(keptRows, selectedStates);
141 // TODO @Jip: note that rewards get lost
142 result = std::make_shared<storm::models::sparse::Dtmc<ValueType>>(std::move(newTransitionMatrix),
143 sparseModel->getStateLabeling().getSubLabeling(selectedStates));
144
145 eliminationWatch.stop();
146 STORM_PRINT("\nTime for scc elimination: " << eliminationWatch << ".\n\n");
147 result->printModelInformationToStream(std::cout);
148 } else if (model->isOfType(storm::models::ModelType::Mdp)) {
149 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException,
150 "Unable to perform SCC elimination for monotonicity analysis on MDP: Not mplemented");
151 } else {
152 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Unable to perform monotonicity analysis on the provided model type.");
153 }
154 return result;
155}
156
157template<typename ValueType>
158std::shared_ptr<storm::models::ModelBase> simplifyModel(std::shared_ptr<storm::models::ModelBase> const& model, cli::SymbolicInput const& input) {
159 storm::utility::Stopwatch simplifyingWatch(true);
160 std::shared_ptr<storm::models::ModelBase> result;
161 if (model->isOfType(storm::models::ModelType::Dtmc)) {
163 *(model->template as<storm::models::sparse::Dtmc<ValueType>>()));
164
165 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::api::extractFormulasFromProperties(input.properties);
166 STORM_LOG_THROW(formulas.begin() != formulas.end(), storm::exceptions::NotSupportedException, "Only one formula at the time supported");
167
168 if (!simplifier.simplify(*(formulas[0]))) {
169 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Simplifying the model was not successfull.");
170 }
171 result = simplifier.getSimplifiedModel();
172 } else if (model->isOfType(storm::models::ModelType::Mdp)) {
174 *(model->template as<storm::models::sparse::Mdp<ValueType>>()));
175
176 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::api::extractFormulasFromProperties(input.properties);
177 STORM_LOG_THROW(formulas.begin() != formulas.end(), storm::exceptions::NotSupportedException, "Only one formula at the time supported");
178
179 if (!simplifier.simplify(*(formulas[0]))) {
180 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Simplifying the model was not successfull.");
181 }
182 result = simplifier.getSimplifiedModel();
183 } else {
184 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Unable to perform monotonicity analysis on the provided model type.");
185 }
186
187 simplifyingWatch.stop();
188 STORM_PRINT("\nTime for model simplification: " << simplifyingWatch << ".\n\n");
189 result->printModelInformationToStream(std::cout);
190 return result;
191}
192
193template<typename ValueType>
196 auto bisimulationSettings = storm::settings::getModule<storm::settings::modules::BisimulationSettings>();
197 auto parametricSettings = storm::settings::getModule<storm::settings::modules::ParametricSettings>();
198 auto transformationSettings = storm::settings::getModule<storm::settings::modules::TransformationSettings>();
199 auto monSettings = storm::settings::getModule<storm::settings::modules::MonotonicitySettings>();
200 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
201
202 PreprocessResult result(model, false);
203 // TODO: why only simplify in these modes
204 if (parametricSettings.getOperationMode() == storm::pars::utility::ParametricMode::Monotonicity ||
205 parametricSettings.getOperationMode() == storm::pars::utility::ParametricMode::Feasibility) {
206 STORM_LOG_THROW(!input.properties.empty(), storm::exceptions::InvalidSettingsException, "Simplification requires property to be specified");
207 result.model = storm::pars::simplifyModel<ValueType>(result.model, input);
208 result.changed = true;
209 }
210
211 if (result.model->isOfType(storm::models::ModelType::MarkovAutomaton)) {
213 result.changed = true;
214 }
215
216 if (mpi.applyBisimulation) {
218 bisimulationSettings, regionSettings.isAssumeGraphPreservingSet());
219 result.changed = true;
220 }
221
222 if (parametricSettings.isLinearToSimpleEnabled()) {
223 STORM_LOG_INFO("Transforming linear to simple...");
225 result.model = transformer.transform(*result.model->template as<storm::models::sparse::Dtmc<RationalFunction>>(), true);
226 result.changed = true;
227 }
228
229 if (parametricSettings.isBigStepEnabled()) {
233 auto bigStepResult = tt.bigStep(*result.model->template as<storm::models::sparse::Dtmc<RationalFunction>>(), checkTask);
234 result.model = std::make_shared<storm::models::sparse::Dtmc<RationalFunction>>(bigStepResult.first);
235
236 if (mpi.applyBisimulation) {
238 bisimulationSettings, regionSettings.isAssumeGraphPreservingSet());
239 }
240 result.changed = true;
241 }
242
243 if (transformationSettings.isChainEliminationSet() && model->isOfType(storm::models::ModelType::MarkovAutomaton)) {
244 // TODO: Why only on MAs?
245 auto eliminationResult =
247 storm::api::extractFormulasFromProperties(input.properties), transformationSettings.getLabelBehavior());
248 result.model = eliminationResult.first;
249 // Set transformed properties as new properties in input
250 result.formulas = eliminationResult.second;
251 result.changed = true;
252 }
253
254 if (parametricSettings.transformContinuousModel() &&
255 (model->isOfType(storm::models::ModelType::Ctmc) || model->isOfType(storm::models::ModelType::MarkovAutomaton))) {
258 result.model = transformResult.first;
259 // Set transformed properties as new properties in input
260 result.formulas = transformResult.second;
261 result.changed = true;
262 }
263
264 if (monSettings.isSccEliminationSet()) {
265 // TODO move this into the API?
266 result.model = storm::pars::eliminateScc<ValueType>(result.model);
267 result.changed = true;
268 }
269
270 return result;
271}
272
273template<storm::dd::DdType DdType, typename ValueType>
276 auto bisimulationSettings = storm::settings::getModule<storm::settings::modules::BisimulationSettings>();
277
278 PreprocessResult result(model, false);
279
281 // Currently, hybrid engine for parametric models just refers to building the model symbolically.
282 STORM_LOG_INFO("Translating symbolic model to sparse model...");
284 result.changed = true;
285 // Invoke preprocessing on the sparse model
286 PreprocessResult sparsePreprocessingResult =
287 storm::pars::preprocessSparseModel<ValueType>(result.model->as<storm::models::sparse::Model<ValueType>>(), input, mpi);
288 if (sparsePreprocessingResult.changed) {
289 result.model = sparsePreprocessingResult.model;
290 result.formulas = sparsePreprocessingResult.formulas;
291 }
292 } else {
293 STORM_LOG_ASSERT(mpi.engine == storm::utility::Engine::Dd, "Expected Dd engine.");
294 if (mpi.applyBisimulation) {
296 bisimulationSettings, mpi);
297 result.changed = true;
298 }
299 }
300 return result;
301}
302
303template<storm::dd::DdType DdType, typename ValueType>
304PreprocessResult preprocessModel(std::shared_ptr<storm::models::ModelBase> const& model, cli::SymbolicInput const& input,
306 storm::utility::Stopwatch preprocessingWatch(true);
307
308 PreprocessResult result(model, false);
309 if (model->isSparseModel()) {
310 result = storm::pars::preprocessSparseModel<ValueType>(result.model->as<storm::models::sparse::Model<ValueType>>(), input, mpi);
311 } else {
312 STORM_LOG_ASSERT(model->isSymbolicModel(), "Unexpected model type.");
313 result = storm::pars::preprocessDdModel<DdType, ValueType>(result.model->as<storm::models::symbolic::Model<DdType, ValueType>>(), input, mpi);
314 }
315
316 if (result.changed) {
317 STORM_PRINT_AND_LOG("\nTime for model preprocessing: " << preprocessingWatch << ".\n\n");
318 }
319 return result;
320}
321
322template<typename ValueType>
324 std::vector<storm::storage::ParameterRegion<ValueType>> const& regions,
326 STORM_LOG_THROW(regions.size() == 1, storm::exceptions::NotSupportedException, "Region verification is supported for a (single) region only.");
327 storm::storage::ParameterRegion<ValueType> const& region = regions.front();
328 STORM_LOG_THROW(input.properties.size() == 1, storm::exceptions::NotSupportedException, "Region verification is supported for a (single) property only.");
329 auto const& property = input.properties.front();
330
331 auto const& rvs = storm::settings::getModule<storm::settings::modules::RegionVerificationSettings>();
332 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
333
334 auto engine = rvs.getRegionCheckEngine();
335 bool graphPreserving = regionSettings.isAssumeGraphPreservingSet();
336
337 STORM_LOG_THROW(graphPreserving || engine == storm::modelchecker::RegionCheckEngine::RobustParameterLifting, storm::exceptions::NotSupportedException,
338 "Selected region verification engine (--regionverif:engine) requires the assumption that the region is graph-preserving "
339 "(--assume-graph-preserving true).");
340
341 auto splittingStrategy = storm::modelchecker::RegionSplittingStrategy();
342
343 splittingStrategy.heuristic = rvs.getRegionSplittingHeuristic();
344 splittingStrategy.estimateKind = rvs.getRegionSplittingEstimateMethod();
345 if (rvs.isSplittingThresholdSet()) {
346 splittingStrategy.maxSplitDimensions = rvs.getSplittingThreshold();
347 }
348
349 auto parsedDiscreteVars = storm::api::parseVariableList<ValueType>(regionSettings.getDiscreteVariablesString(), *model);
350 std::set<typename storm::storage::ParameterRegion<ValueType>::VariableType> discreteVariables(parsedDiscreteVars.begin(), parsedDiscreteVars.end());
351
352 storm::utility::Stopwatch watch(true);
353
354 auto const& settings = storm::api::RefinementOptions<ValueType>{
355 model,
356 *(property.getRawFormula()),
357 engine,
358 splittingStrategy,
359 monotonicitySettings,
360 discreteVariables,
361 true, // allow model simplification
362 graphPreserving,
363 false // preconditions not yet validated
364 };
365
366 if (storm::api::verifyRegion<ValueType>(settings, region)) {
367 STORM_PRINT_AND_LOG("Formula is satisfied by all parameter instantiations.\n");
368 } else {
369 STORM_PRINT_AND_LOG("Formula is not satisfied by all parameter instantiations.\n");
370 }
371 STORM_PRINT_AND_LOG("Time for model checking: " << watch << ".\n");
372}
373
374template<typename ValueType>
376 std::vector<storm::storage::ParameterRegion<ValueType>> const& regions,
378 uint64_t monThresh = 0) {
379 STORM_LOG_ASSERT(!regions.empty(), "Can not analyze an empty set of regions.");
380 STORM_LOG_THROW(regions.size() == 1, storm::exceptions::NotSupportedException, "Region refinement is not supported for multiple initial regions.");
381 STORM_LOG_THROW(input.properties.size() == 1, storm::exceptions::NotSupportedException, "Region verification is supported for a (single) property only.");
382 auto const& property = input.properties.front();
383
384 auto parametricSettings = storm::settings::getModule<storm::settings::modules::ParametricSettings>();
385 auto rvs = storm::settings::getModule<storm::settings::modules::RegionVerificationSettings>();
386 auto partitionSettings = storm::settings::getModule<storm::settings::modules::PartitionSettings>();
387 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
388
389 ValueType refinementThreshold = storm::utility::convertNumber<ValueType>(partitionSettings.getCoverageThreshold());
390 std::optional<uint64_t> optionalDepthLimit;
391 if (partitionSettings.isDepthLimitSet()) {
392 optionalDepthLimit = partitionSettings.getDepthLimit();
393 }
394
396 STORM_PRINT_AND_LOG("Analyzing parameter region " << regions.front());
397
398 auto engine = rvs.getRegionCheckEngine();
399 STORM_PRINT_AND_LOG(" using " << engine);
400
401 auto splittingStrategy = storm::modelchecker::RegionSplittingStrategy();
402
403 splittingStrategy.heuristic = rvs.getRegionSplittingHeuristic();
404 splittingStrategy.estimateKind = rvs.getRegionSplittingEstimateMethod();
405 if (rvs.isSplittingThresholdSet()) {
406 splittingStrategy.maxSplitDimensions = rvs.getSplittingThreshold();
407 }
408
409 bool graphPreserving = regionSettings.isAssumeGraphPreservingSet();
410
411 auto parsedDiscreteVars = storm::api::parseVariableList<ValueType>(regionSettings.getDiscreteVariablesString(), *model);
412 std::set<typename storm::storage::ParameterRegion<ValueType>::VariableType> discreteVariables(parsedDiscreteVars.begin(), parsedDiscreteVars.end());
413
414 STORM_PRINT_AND_LOG(" and splitting heuristic " << splittingStrategy.heuristic);
415 if (monotonicitySettings.useMonotonicity) {
416 STORM_PRINT_AND_LOG(" with local monotonicity and");
417 }
418
419 STORM_PRINT_AND_LOG(" with iterative refinement until "
420 << (1.0 - partitionSettings.getCoverageThreshold()) * 100.0 << "% is covered."
421 << (partitionSettings.isDepthLimitSet() ? " Depth limit is " + std::to_string(partitionSettings.getDepthLimit()) + "." : "") << '\n');
422
424 storm::utility::Stopwatch watch(true);
425
427 model,
428 storm::api::createTask<ValueType>(property.getRawFormula(), true),
429 engine,
430 splittingStrategy,
431 monotonicitySettings,
432 discreteVariables,
433 true, // allow model simplification
434 graphPreserving,
435 false // preconditions not yet validated
436 };
437 std::unique_ptr<storm::modelchecker::CheckResult> result = storm::api::checkAndRefineRegionWithSparseEngine<ValueType>(
438 settings, regions.front(), refinementThreshold, optionalDepthLimit, storm::modelchecker::RegionResultHypothesis::Unknown, monThresh);
439 watch.stop();
440 printInitialStatesResult<ValueType>(result, &watch);
441
442 if (parametricSettings.exportResultToFile()) {
443 storm::api::exportRegionCheckResultToFile<ValueType>(result, parametricSettings.exportResultPath());
444 }
445}
446
448 auto ioSettings = storm::settings::getModule<storm::settings::modules::IOSettings>();
449 auto buildSettings = storm::settings::getModule<storm::settings::modules::BuildSettings>();
450 auto parSettings = storm::settings::getModule<storm::settings::modules::ParametricSettings>();
451 auto monSettings = storm::settings::getModule<storm::settings::modules::MonotonicitySettings>();
452 auto sampleSettings = storm::settings::getModule<storm::settings::modules::SamplingSettings>();
453 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
454
456 storm::exceptions::InvalidSettingsException, "The selected engine is not supported for parametric models.");
457 STORM_LOG_THROW(parSettings.hasOperationModeBeenSet(), storm::exceptions::InvalidSettingsException, "An operation mode must be selected with --mode");
458 std::shared_ptr<storm::models::ModelBase> model;
459 if (!buildSettings.isNoBuildModelSet()) {
460 model = storm::cli::buildModel(input, ioSettings, mpi);
461 }
462
463 STORM_LOG_THROW(model, storm::exceptions::InvalidSettingsException, "No input model.");
464 if (model) {
465 model->printModelInformationToStream(std::cout);
466 }
467
468 using ValueType = storm::RationalFunction;
469 auto const DdType = storm::dd::DdType::Sylvan;
470 STORM_LOG_THROW(model->supportsParameters(), storm::exceptions::UnexpectedException, "Expected a parametric model.");
471 STORM_LOG_THROW(model->isSparseModel() || model->getDdType().value() == DdType, storm::exceptions::UnexpectedException,
472 "Expected type of model representation.");
473
474 // If minimization is active and the model is parametric, parameters might be minimized away because they are inconsequential.
475 // This is the set of all such inconsequential parameters.
476 std::set<RationalFunctionVariable> omittedParameters;
477
478 if (model) {
479 auto preprocessingResult = storm::pars::preprocessModel<DdType, ValueType>(model, input, mpi);
480 if (preprocessingResult.changed) {
481 if (model->isOfType(models::ModelType::Dtmc) || model->isOfType(models::ModelType::Mdp)) {
482 auto const previousParams = storm::models::sparse::getAllParameters(*model->template as<storm::models::sparse::Model<ValueType>>());
483 auto const currentParams =
484 storm::models::sparse::getAllParameters(*(preprocessingResult.model)->template as<storm::models::sparse::Model<ValueType>>());
485 for (auto const& variable : previousParams) {
486 if (!currentParams.count(variable)) {
487 omittedParameters.insert(variable);
488 }
489 }
490 }
491 model = preprocessingResult.model;
492
493 if (preprocessingResult.formulas) {
494 std::vector<storm::jani::Property> newProperties;
495 for (size_t i = 0; i < preprocessingResult.formulas.get().size(); ++i) {
496 auto formula = preprocessingResult.formulas.get().at(i);
497 STORM_LOG_ASSERT(i < input.properties.size(), "Index " << i << " greater than number of properties.");
498 storm::jani::Property property = input.properties.at(i);
499 newProperties.push_back(storm::jani::Property(property.getName(), formula, property.getUndefinedConstants(), property.getComment()));
500 }
501 input.properties = newProperties;
502 }
503 model->printModelInformationToStream(std::cout);
504 }
505 }
506
507 std::vector<storm::storage::ParameterRegion<ValueType>> regions = parseRegions<ValueType>(model);
508 if (!model) {
509 return;
510 } else {
511 storm::cli::castAndApply(model, [&input](auto const& m) { storm::cli::exportModel(m, input); });
512 }
513
514 // TODO move this.
515 storm::api::MonotonicitySetting monotonicitySettings(parSettings.isUseMonotonicitySet(), false, monSettings.isUsePLABoundsSet());
516 uint64_t monThresh = monSettings.getMonotonicityThreshold();
517
518 auto mode = parSettings.getOperationMode();
520 STORM_LOG_INFO("Solution function mode started.");
521 STORM_LOG_THROW(regions.empty(), storm::exceptions::InvalidSettingsException,
522 "Solution function computations cannot be restricted to specific regions");
523 STORM_LOG_ERROR_COND(!regionSettings.isAssumeGraphPreservingSet(), "Solution function computations assume graph preservation.");
524
525 if (model->isSparseModel()) {
527 } else {
529 }
531 STORM_LOG_INFO("Monotonicity mode started.");
532 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Monotonicity analysis is only supported on sparse models.");
535 STORM_LOG_INFO("Feasibility mode started.");
536 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Feasibility analysis is only supported on sparse models.");
537 std::vector<std::shared_ptr<storm::logic::Formula const>> formulas = storm::api::extractFormulasFromProperties(input.properties);
538 STORM_LOG_THROW(formulas.size() == 1, storm::exceptions::InvalidSettingsException,
539 "Feasibility analysis is only supported for single-objective properties.");
540 auto formula = formulas[0];
541 storm::pars::performFeasibility<ValueType>(model->as<storm::models::sparse::Model<ValueType>>(),
542 createFeasibilitySynthesisTaskFromSettings(formula, regions), omittedParameters, monotonicitySettings);
544 STORM_LOG_INFO("Verification mode started.");
545 STORM_LOG_THROW(input.properties.size() == 1, storm::exceptions::InvalidSettingsException,
546 "Verification analysis is only supported for single-objective properties.");
547 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Verification analysis is only supported on sparse models.");
548 verifyRegionWithSparseEngine(model->as<storm::models::sparse::Model<ValueType>>(), input, regions, monotonicitySettings);
549
551 STORM_LOG_INFO("Partition mode started.");
552 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException,
553 "Parameter space partitioning is only supported on sparse models.");
554 STORM_LOG_THROW(regions.size() == 1, storm::exceptions::InvalidSettingsException, "Partitioning requires a (single) initial region.");
555
556 // TODO Partition mode does not support monotonicity. This should generally be possible.
557 // TODO here setting monotone parameters from the outside may actually be useful
558
559 assert(!monotonicitySettings.useOnlyGlobalMonotonicity);
560 assert(!monotonicitySettings.useBoundsFromPLA);
562 monThresh);
564 STORM_LOG_INFO("Sampling mode started.");
565 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Sampling analysis is currently only supported on sparse models.");
566 // TODO unclear why this only works for sparse models?
567
568 std::string samplesAsString = sampleSettings.getSamples();
570 if (!samplesAsString.empty()) {
571 samples = parseSamples<ValueType>(model, samplesAsString, sampleSettings.isSamplesAreGraphPreservingSet());
572 samples.exact = sampleSettings.isSampleExactSet();
573 }
574 if (!samples.empty()) {
575 STORM_LOG_TRACE("Sampling the model at given points.");
576
577 if (samples.exact) {
578 verifyPropertiesAtSamplePointsWithSparseEngine<ValueType, storm::RationalNumber>(model->as<storm::models::sparse::Model<ValueType>>(), input,
579 samples);
580 } else {
581 verifyPropertiesAtSamplePointsWithSparseEngine<ValueType, double>(model->as<storm::models::sparse::Model<ValueType>>(), input, samples);
582 }
583 }
584 } else {
585 STORM_LOG_ASSERT(false, "Unknown operation mode.");
586 }
587}
588
590 auto coreSettings = storm::settings::getModule<storm::settings::modules::CoreSettings>();
591 auto engine = coreSettings.getEngine();
593 engine != storm::utility::Engine::Dd || engine != storm::utility::Engine::Hybrid || coreSettings.getDdLibraryType() == storm::dd::DdType::Sylvan,
594 "The selected DD library does not support parametric models. Switching to Sylvan...");
595
596 // Parse and preprocess symbolic input (PRISM, JANI, properties, etc.)
597 auto symbolicInput = storm::cli::parseSymbolicInput();
599 std::tie(symbolicInput, mpi) = storm::cli::preprocessSymbolicInput(symbolicInput);
603 processInput(std::move(symbolicInput), mpi);
604}
605} // namespace pars
606} // namespace storm
607
611int main(const int argc, const char** argv) {
612 try {
613 return storm::cli::process("Storm-pars", "storm-pars", storm::settings::initializeParsSettings, storm::pars::processOptions, argc, argv);
614 } catch (storm::exceptions::BaseException const& exception) {
615 STORM_LOG_ERROR("An exception caused Storm-pars to terminate. The message of the exception is: " << exception.what());
616 return 1;
617 } catch (std::exception const& exception) {
618 STORM_LOG_ERROR("An unexpected exception occurred and caused Storm-pars to terminate. The message of this exception is: " << exception.what());
619 return 2;
620 }
621}
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:13
This class represents a Markov automaton.
This class represents a (discrete-time) Markov decision process.
Definition Mdp.h:13
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:199
Base class for all symbolic models.
Definition Model.h:42
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:176
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:381
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:720
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