#pragma once #include "storm/transformer/ContinuousToDiscreteTimeModelTransformer.h" #include "storm/transformer/SymbolicToSparseTransformer.h" #include "storm/transformer/NonMarkovianChainTransformer.h" #include "storm/utility/macros.h" #include "storm/utility/builder.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm/exceptions/NotSupportedException.h" namespace storm { namespace api { /*! * Eliminates chains of non-Markovian states from a given Markov Automaton */ template std::pair>, std::vector>> eliminateNonMarkovianChains(std::shared_ptr> const &ma, std::vector> const &formulas, storm::transformer::EliminationLabelBehavior labelBehavior) { auto newFormulas = storm::transformer::NonMarkovianChainTransformer::checkAndTransformFormulas(formulas); STORM_LOG_WARN_COND(newFormulas.size() == formulas.size(), "The state elimination does not preserve all properties."); STORM_LOG_WARN_COND(!(labelBehavior == storm::transformer::EliminationLabelBehavior::KeepLabels), "Labels are not preserved by the state elimination. This may cause incorrect results."); return std::make_pair(storm::transformer::NonMarkovianChainTransformer::eliminateNonmarkovianStates(ma, labelBehavior), newFormulas); } /*! * Transforms the given continuous model to a discrete time model. * If such a transformation does not preserve one of the given formulas, a warning is issued. */ template std::pair>, std::vector>> transformContinuousToDiscreteTimeSparseModel(std::shared_ptr> const& model, std::vector> const& formulas) { storm::transformer::ContinuousToDiscreteTimeModelTransformer transformer; std::string timeRewardName = "_time"; while(model->hasRewardModel(timeRewardName)) { timeRewardName += "_"; } auto newFormulas = transformer.checkAndTransformFormulas(formulas, timeRewardName); STORM_LOG_WARN_COND(newFormulas.size() == formulas.size(), "Transformation of a " << model->getType() << " to a discrete time model does not preserve all properties."); if (model->isOfType(storm::models::ModelType::Ctmc)) { return std::make_pair(transformer.transform(*model->template as>(), timeRewardName), newFormulas); } else if (model->isOfType(storm::models::ModelType::MarkovAutomaton)) { return std::make_pair(transformer.transform(*model->template as>(), timeRewardName), newFormulas); } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Transformation of a " << model->getType() << " to a discrete time model is not supported"); } return std::make_pair(nullptr, newFormulas);; } /*! * Transforms the given continuous model to a discrete time model IN PLACE. * This means that the input continuous time model is replaced by the new discrete time model. * If such a transformation does not preserve one of the given formulas, an error is issued. */ template std::pair>, std::vector>> transformContinuousToDiscreteTimeSparseModel(storm::models::sparse::Model&& model, std::vector> const& formulas) { storm::transformer::ContinuousToDiscreteTimeModelTransformer transformer; std::string timeRewardName = "_time"; while(model.hasRewardModel(timeRewardName)) { timeRewardName += "_"; } auto newFormulas = transformer.checkAndTransformFormulas(formulas, timeRewardName); STORM_LOG_WARN_COND(newFormulas.size() == formulas.size(), "Transformation of a " << model.getType() << " to a discrete time model does not preserve all properties."); if (model.isOfType(storm::models::ModelType::Ctmc)) { return std::make_pair(transformer.transform(std::move(*model.template as>()), timeRewardName), newFormulas); } else if (model.isOfType(storm::models::ModelType::MarkovAutomaton)) { return std::make_pair(transformer.transform(std::move(*model.template as>()), timeRewardName), newFormulas); } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Transformation of a " << model.getType() << " to a discrete time model is not supported."); } return std::make_pair(nullptr, newFormulas);; } template std::shared_ptr checkAndTransformContinuousToDiscreteTimeFormula(storm::logic::Formula const& formula, std::string const& timeRewardName = "_time") { storm::transformer::ContinuousToDiscreteTimeModelTransformer transformer; if (transformer.preservesFormula(formula)) { return transformer.checkAndTransformFormulas({formula.asSharedPointer()}, timeRewardName).front(); } else { STORM_LOG_ERROR("Unable to transform formula " << formula << " to discrete time."); } return nullptr; } /*! * Transforms the given symbolic model to a sparse model. */ template std::shared_ptr> transformSymbolicToSparseModel(std::shared_ptr> const& symbolicModel, std::vector> const& formulas = std::vector>()) { switch (symbolicModel->getType()) { case storm::models::ModelType::Dtmc: return storm::transformer::SymbolicDtmcToSparseDtmcTransformer().translate(*symbolicModel->template as>(), formulas); case storm::models::ModelType::Mdp: return storm::transformer::SymbolicMdpToSparseMdpTransformer::translate(*symbolicModel->template as>(), formulas); case storm::models::ModelType::Ctmc: return storm::transformer::SymbolicCtmcToSparseCtmcTransformer::translate(*symbolicModel->template as>(), formulas); case storm::models::ModelType::MarkovAutomaton: return storm::transformer::SymbolicMaToSparseMaTransformer::translate(*symbolicModel->template as>(), formulas); default: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Transformation of symbolic " << symbolicModel->getType() << " to sparse model is not supported."); } return nullptr; } template std::shared_ptr> transformToNondeterministicModel(storm::models::sparse::Model&& model) { storm::storage::sparse::ModelComponents components(std::move(model.getTransitionMatrix()), std::move(model.getStateLabeling()), std::move(model.getRewardModels())); components.choiceLabeling = std::move(model.getOptionalChoiceLabeling()); components.stateValuations = std::move(model.getOptionalStateValuations()); components.choiceOrigins = std::move(model.getOptionalChoiceOrigins()); if (model.isOfType(storm::models::ModelType::Dtmc)) { return storm::utility::builder::buildModelFromComponents(storm::models::ModelType::Mdp, std::move(components)); } else if (model.isOfType(storm::models::ModelType::Ctmc)) { components.rateTransitions = true; components.markovianStates = storm::storage::BitVector(components.transitionMatrix.getRowGroupCount(), true); return storm::utility::builder::buildModelFromComponents(storm::models::ModelType::MarkovAutomaton, std::move(components)); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Cannot transform model of type " << model.getType() << " to a nondeterministic model."); } } } }