74 std::shared_ptr<storm::models::ModelBase>
model;
75 boost::optional<std::vector<std::shared_ptr<storm::logic::Formula const>>>
formulas;
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);
87 if (regionSettings.isAssumeGraphPreservingSet()) {
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>()) {
98 <<
" appears to not preserve the graph structure of the parametric model. If this is the case, set --assume-graph-preserving false.");
107template<
typename ValueType>
108std::shared_ptr<storm::models::ModelBase>
eliminateScc(std::shared_ptr<storm::models::ModelBase>
const& model) {
110 std::shared_ptr<storm::models::ModelBase> result;
115 auto backwardsTransitionMatrix = matrix.transpose();
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);
130 for (
auto backState : row) {
131 if (!scc.containsState(backState.getColumn())) {
136 entryStates.push_back(state);
137 selfLoopStates.
set(state);
139 selectedStates.
set(state);
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");
152 auto actionRewards = std::vector<ValueType>(matrix.getRowCount(), storm::utility::zero<ValueType>());
155 for (
auto state : selectedStates) {
158 for (
auto state : selfLoopStates) {
159 auto row = flexibleMatrix.
getRow(state);
163 auto keptRows = matrix.getRowFilter(selectedStates);
166 result = std::make_shared<storm::models::sparse::Dtmc<ValueType>>(std::move(newTransitionMatrix),
167 sparseModel->getStateLabeling().getSubLabeling(selectedStates));
169 eliminationWatch.
stop();
170 STORM_PRINT(
"\nTime for scc elimination: " << eliminationWatch <<
".\n\n");
171 result->printModelInformationToStream(std::cout);
174 "Unable to perform SCC elimination for monotonicity analysis on MDP: Not mplemented");
176 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Unable to perform monotonicity analysis on the provided model type.");
181template<
typename ValueType>
184 std::shared_ptr<storm::models::ModelBase> result;
190 STORM_LOG_THROW(formulas.begin() != formulas.end(), storm::exceptions::NotSupportedException,
"Only one formula at the time supported");
192 if (!simplifier.
simplify(*(formulas[0]))) {
193 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"Simplifying the model was not successfull.");
201 STORM_LOG_THROW(formulas.begin() != formulas.end(), storm::exceptions::NotSupportedException,
"Only one formula at the time supported");
203 if (!simplifier.
simplify(*(formulas[0]))) {
204 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"Simplifying the model was not successfull.");
208 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Unable to perform monotonicity analysis on the provided model type.");
211 simplifyingWatch.
stop();
212 STORM_PRINT(
"\nTime for model simplification: " << simplifyingWatch <<
".\n\n");
213 result->printModelInformationToStream(std::cout);
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>();
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);
242 bisimulationSettings, regionSettings.isAssumeGraphPreservingSet());
246 if (parametricSettings.isLinearToSimpleEnabled()) {
253 if (parametricSettings.isBigStepEnabled()) {
258 result.
model = std::make_shared<storm::models::sparse::Dtmc<RationalFunction>>(bigStepResult.first);
262 bisimulationSettings, regionSettings.isAssumeGraphPreservingSet());
269 auto eliminationResult =
272 result.
model = eliminationResult.first;
274 result.
formulas = eliminationResult.second;
278 if (parametricSettings.transformContinuousModel() &&
282 result.
model = transformResult.first;
284 result.
formulas = transformResult.second;
288 if (monSettings.isSccEliminationSet()) {
290 result.
model = storm::pars::eliminateScc<ValueType>(result.
model);
297template<storm::dd::DdType DdType,
typename ValueType>
300 auto bisimulationSettings = storm::settings::getModule<storm::settings::modules::BisimulationSettings>();
312 if (sparsePreprocessingResult.
changed) {
313 result.
model = sparsePreprocessingResult.
model;
320 bisimulationSettings, mpi);
327template<storm::dd::DdType DdType,
typename ValueType>
333 if (model->isSparseModel()) {
346template<
typename ValueType>
350 STORM_LOG_THROW(regions.size() == 1, storm::exceptions::NotSupportedException,
"Region verification is supported for a (single) region only.");
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();
355 auto const& rvs = storm::settings::getModule<storm::settings::modules::RegionVerificationSettings>();
356 auto regionSettings = storm::settings::getModule<storm::settings::modules::RegionSettings>();
358 auto engine = rvs.getRegionCheckEngine();
359 bool graphPreserving = regionSettings.isAssumeGraphPreservingSet();
362 "Selected region verification engine (--regionverif:engine) requires the assumption that the region is graph-preserving "
363 "(--assume-graph-preserving true).");
367 splittingStrategy.heuristic = rvs.getRegionSplittingHeuristic();
368 splittingStrategy.estimateKind = rvs.getRegionSplittingEstimateMethod();
369 if (rvs.isSplittingThresholdSet()) {
370 splittingStrategy.maxSplitDimensions = rvs.getSplittingThreshold();
373 auto parsedDiscreteVars = storm::api::parseVariableList<ValueType>(regionSettings.getDiscreteVariablesString(), *model);
374 std::set<typename storm::storage::ParameterRegion<ValueType>::VariableType> discreteVariables(parsedDiscreteVars.begin(), parsedDiscreteVars.end());
380 *(
property.getRawFormula()),
383 monotonicitySettings,
390 if (storm::api::verifyRegion<ValueType>(settings, region)) {
398template<
typename ValueType>
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();
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>();
413 ValueType refinementThreshold = storm::utility::convertNumber<ValueType>(partitionSettings.getCoverageThreshold());
414 std::optional<uint64_t> optionalDepthLimit;
415 if (partitionSettings.isDepthLimitSet()) {
416 optionalDepthLimit = partitionSettings.getDepthLimit();
422 auto engine = rvs.getRegionCheckEngine();
427 splittingStrategy.heuristic = rvs.getRegionSplittingHeuristic();
428 splittingStrategy.estimateKind = rvs.getRegionSplittingEstimateMethod();
429 if (rvs.isSplittingThresholdSet()) {
430 splittingStrategy.maxSplitDimensions = rvs.getSplittingThreshold();
433 bool graphPreserving = regionSettings.isAssumeGraphPreservingSet();
435 auto parsedDiscreteVars = storm::api::parseVariableList<ValueType>(regionSettings.getDiscreteVariablesString(), *model);
436 std::set<typename storm::storage::ParameterRegion<ValueType>::VariableType> discreteVariables(parsedDiscreteVars.begin(), parsedDiscreteVars.end());
439 if (monotonicitySettings.useMonotonicity) {
444 << (1.0 - partitionSettings.getCoverageThreshold()) * 100.0 <<
"% is covered."
445 << (partitionSettings.isDepthLimitSet() ?
" Depth limit is " + std::to_string(partitionSettings.getDepthLimit()) +
"." :
"") <<
'\n');
452 storm::api::createTask<ValueType>(property.getRawFormula(),
true),
455 monotonicitySettings,
461 std::unique_ptr<storm::modelchecker::CheckResult> result = storm::api::checkAndRefineRegionWithSparseEngine<ValueType>(
464 printInitialStatesResult<ValueType>(result, &watch);
466 if (parametricSettings.exportResultToFile()) {
467 storm::api::exportRegionCheckResultToFile<ValueType>(result, parametricSettings.exportResultPath());
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>();
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()) {
487 STORM_LOG_THROW(model, storm::exceptions::InvalidSettingsException,
"No input model.");
489 model->printModelInformationToStream(std::cout);
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.");
500 std::set<RationalFunctionVariable> omittedParameters;
503 auto preprocessingResult = storm::pars::preprocessModel<DdType, ValueType>(model, input, mpi);
504 if (preprocessingResult.changed) {
507 auto const currentParams =
509 for (
auto const& variable : previousParams) {
510 if (!currentParams.count(variable)) {
511 omittedParameters.insert(variable);
515 model = preprocessingResult.model;
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);
523 newProperties.push_back(
storm::jani::Property(property.getName(), formula, property.getUndefinedConstants(), property.getComment()));
527 model->printModelInformationToStream(std::cout);
531 std::vector<storm::storage::ParameterRegion<ValueType>> regions = parseRegions<ValueType>(model);
540 uint64_t monThresh = monSettings.getMonotonicityThreshold();
542 auto mode = parSettings.getOperationMode();
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.");
549 if (model->isSparseModel()) {
556 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException,
"Monotonicity analysis is only supported on sparse models.");
560 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException,
"Feasibility analysis is only supported on sparse models.");
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];
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.");
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.");
589 STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException,
"Sampling analysis is currently only supported on sparse models.");
592 std::string samplesAsString = sampleSettings.getSamples();
594 if (!samplesAsString.empty()) {
595 samples = parseSamples<ValueType>(model, samplesAsString, sampleSettings.isSamplesAreGraphPreservingSet());
596 samples.
exact = sampleSettings.isSampleExactSet();
598 if (!samples.
empty()) {
614 auto coreSettings = storm::settings::getModule<storm::settings::modules::CoreSettings>();
615 auto engine = coreSettings.getEngine();
618 "The selected DD library does not support parametric models. Switching to Sylvan...");
635int main(
const int argc,
const char** argv) {
639 STORM_LOG_ERROR(
"An exception caused Storm-pars to terminate. The message of the exception is: " << exception.
what());
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());
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.
This class represents a Markov automaton.
This class represents a (discrete-time) Markov decision process.
Base class for all sparse models.
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Base class for all symbolic models.
void eliminateLoop(uint64_t row)
void eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions)
A bit vector that is internally represented as a vector of 64-bit values.
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...
A class that provides convenience operations to display run times.
void stop()
Stop stopwatch and add measured time to total time.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ERROR(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_ERROR_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
#define STORM_PRINT_AND_LOG(message)
#define STORM_PRINT(message)
Define the macros that print information and optionally also log it.
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.
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.
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 ®ions, 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 ®ions)
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 ®ions, 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 ®ions)
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.
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
bool useOnlyGlobalMonotonicity