diff --git a/src/storm/api/storm.h b/src/storm/api/storm.h index c2856da48..ffc4c75a6 100644 --- a/src/storm/api/storm.h +++ b/src/storm/api/storm.h @@ -4,6 +4,7 @@ #include "storm/api/properties.h" #include "storm/api/builder.h" #include "storm/api/bisimulation.h" +#include "storm/api/transformation.h" #include "storm/api/verification.h" #include "storm/api/counterexamples.h" #include "storm/api/export.h" diff --git a/src/storm/api/transformation.h b/src/storm/api/transformation.h new file mode 100644 index 000000000..9f25e37fa --- /dev/null +++ b/src/storm/api/transformation.h @@ -0,0 +1,80 @@ +#pragma once + +#include "storm/transformer/ContinuousToDiscreteTimeModelTransformer.h" +#include "storm/transformer/SymbolicToSparseTransformer.h" + +#include "storm/utility/macros.h" +#include "storm/exceptions/InvalidOperationException.h" +#include "storm/exceptions/NotSupportedException.h" + +namespace storm { + namespace api { + + /*! + * Transforms the given continuous model to a discrete time model. + * If such a transformation does not preserve one of the given formulas, an error is issued. + */ + template + std::shared_ptr> transformContinuousToDiscreteTimeSparseModel(std::shared_ptr> const& model, std::vector> const& formulas) { + + storm::transformer::ContinuousToDiscreteTimeModelTransformer transformer; + + for (auto const& formula : formulas) { + STORM_LOG_THROW(transformer.preservesFormula(*formula), storm::exceptions::InvalidOperationException, "Transformation to discrete time model does not preserve formula " << *formula << "."); + } + + if (model->isOfType(storm::models::ModelType::Ctmc)) { + return transformer.transform(*model->template as>()); + } else if (model->isOfType(storm::models::ModelType::MarkovAutomaton)) { + return transformer.transform(*model->template as>()); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Transformation of a " << model->getType() << " to a discrete time model is not supported"); + } + return nullptr; + } + + /*! + * 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::shared_ptr> transformContinuousToDiscreteTimeSparseModel(storm::models::sparse::Model&& model, std::vector> const& formulas) { + + storm::transformer::ContinuousToDiscreteTimeModelTransformer transformer; + + for (auto const& formula : formulas) { + STORM_LOG_THROW(transformer.preservesFormula(*formula), storm::exceptions::InvalidOperationException, "Transformation to discrete time model does not preserve formula " << *formula << "."); + } + + if (model.isOfType(storm::models::ModelType::Ctmc)) { + transformer.transform(std::move(*model.template as>())); + } else if (model.isOfType(storm::models::ModelType::MarkovAutomaton)) { + transformer.transform(std::move(*model.template as>())); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Transformation of a " << model.getType() << " to a discrete time model is not supported."); + } + return nullptr; + + } + + /*! + * Transforms the given symbolic model to a sparse model. + */ + template + std::shared_ptr> transformSymbolicToSparseModel(std::shared_ptr> const& symbolicModel) { + switch (symbolicModel->getType()) { + case storm::models::ModelType::Dtmc: + return storm::transformer::SymbolicDtmcToSparseDtmcTransformer().translate(*symbolicModel->template as>()); + case storm::models::ModelType::Mdp: + return storm::transformer::SymbolicMdpToSparseMdpTransformer::translate(*symbolicModel->template as>()); + case storm::models::ModelType::Ctmc: + return storm::transformer::SymbolicCtmcToSparseCtmcTransformer::translate(*symbolicModel->template as>()); + default: + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Transformation of symbolic " << symbolicModel->getType() << " to sparse model is not supported."); + } + return nullptr; + } + + } +} diff --git a/src/storm/transformer/ContinuousToDiscreteTimeModelTransformer.cpp b/src/storm/transformer/ContinuousToDiscreteTimeModelTransformer.cpp index 0a1c03e4b..d083e17c1 100644 --- a/src/storm/transformer/ContinuousToDiscreteTimeModelTransformer.cpp +++ b/src/storm/transformer/ContinuousToDiscreteTimeModelTransformer.cpp @@ -14,72 +14,10 @@ namespace storm { namespace transformer { - - template - std::shared_ptr> transformContinuousToDiscreteModel(std::shared_ptr> markovModel, std::shared_ptr& formula) { - boost::optional timeRewardModelName; - if (formula->isTimeOperatorFormula()) { - auto const& timeOpFormula = formula->asTimeOperatorFormula(); - if (timeOpFormula.getSubformula().isReachabilityTimeFormula()) { - auto reachabilityRewardFormula = std::make_shared(storm::logic::CloneVisitor().clone(timeOpFormula.getSubformula().asReachabilityTimeFormula().getSubformula()), storm::logic::FormulaContext::Reward); - timeRewardModelName = "time"; - // make sure that the reward model name is not already in use - while (markovModel->hasRewardModel(*timeRewardModelName)) *timeRewardModelName += "_"; - formula = std::make_shared(reachabilityRewardFormula, timeRewardModelName, timeOpFormula.getOperatorInformation()); - } - } - - if (markovModel->isOfType(storm::models::ModelType::Ctmc)) { - SparseCtmcToSparseDtmcTransformer transformer; - if (transformer.transformationPreservesProperty(*formula)) { - STORM_LOG_INFO("Transforming Ctmc to embedded Dtmc..."); - return transformer.translate(*markovModel->template as>(), timeRewardModelName); - } - } else if (markovModel->isOfType(storm::models::ModelType::MarkovAutomaton)) { - SparseMaToSparseMdpTransformer transformer; - if (transformer.transformationPreservesProperty(*formula)) { - STORM_LOG_INFO("Transforming Markov automaton to embedded Mdp..."); - return transformer.translate(*markovModel->template as>(), timeRewardModelName); - } - } else { - STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Model type " << markovModel->getType() << " not expected."); - } - return nullptr; - } - - template - void transformContinuousToDiscreteModelInPlace(std::shared_ptr>& markovModel, std::shared_ptr& formula) { - boost::optional timeRewardModelName; - if (formula->isTimeOperatorFormula()) { - auto const& timeOpFormula = formula->asTimeOperatorFormula(); - if (timeOpFormula.getSubformula().isReachabilityTimeFormula()) { - auto reachabilityRewardFormula = std::make_shared(storm::logic::CloneVisitor().clone(timeOpFormula.getSubformula().asReachabilityTimeFormula().getSubformula()), storm::logic::FormulaContext::Reward); - timeRewardModelName = "time"; - // make sure that the reward model name is not already in use - while (markovModel->hasRewardModel(*timeRewardModelName)) *timeRewardModelName += "_"; - formula = std::make_shared(reachabilityRewardFormula, timeRewardModelName, timeOpFormula.getOperatorInformation()); - } - } - - if (markovModel->isOfType(storm::models::ModelType::Ctmc)) { - SparseCtmcToSparseDtmcTransformer transformer; - if (transformer.transformationPreservesProperty(*formula)) { - STORM_LOG_INFO("Transforming Ctmc to embedded Dtmc..."); - markovModel = transformer.translate(std::move(*markovModel->template as>()), timeRewardModelName); - } - } else if (markovModel->isOfType(storm::models::ModelType::MarkovAutomaton)) { - SparseMaToSparseMdpTransformer transformer; - if (transformer.transformationPreservesProperty(*formula)) { - STORM_LOG_INFO("Transforming Markov automaton to embedded Mdp..."); - markovModel = transformer.translate(std::move(*markovModel->template as>()), timeRewardModelName); - } - } else { - STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Model type " << markovModel->getType() << " not expected."); - } - } + template - std::shared_ptr> SparseCtmcToSparseDtmcTransformer::translate(storm::models::sparse::Ctmc const& ctmc, boost::optional const& timeRewardModelName) { + std::shared_ptr> ContinuousToDiscreteTimeModelTransformer::transform(storm::models::sparse::Ctmc const& ctmc, boost::optional const& timeRewardModelName) { // Init the dtmc components storm::storage::sparse::ModelComponents dtmcComponents(ctmc.getTransitionMatrix(), ctmc.getStateLabeling(), ctmc.getRewardModels()); dtmcComponents.choiceLabeling = ctmc.getOptionalChoiceLabeling(); @@ -113,7 +51,7 @@ namespace storm { } template - std::shared_ptr> SparseCtmcToSparseDtmcTransformer::translate(storm::models::sparse::Ctmc&& ctmc, boost::optional const& timeRewardModelName) { + std::shared_ptr> ContinuousToDiscreteTimeModelTransformer::transform(storm::models::sparse::Ctmc&& ctmc, boost::optional const& timeRewardModelName) { // Init the dtmc components storm::storage::sparse::ModelComponents dtmcComponents(std::move(ctmc.getTransitionMatrix()), std::move(ctmc.getStateLabeling()), std::move(ctmc.getRewardModels())); dtmcComponents.choiceLabeling = std::move(ctmc.getOptionalChoiceLabeling()); @@ -144,7 +82,7 @@ namespace storm { } template - bool SparseCtmcToSparseDtmcTransformer::transformationPreservesProperty(storm::logic::Formula const& formula) { + bool ContinuousToDiscreteTimeModelTransformer::preservesFormula(storm::logic::Formula const& formula) { storm::logic::FragmentSpecification fragment = storm::logic::propositional(); fragment.setProbabilityOperatorsAllowed(true); fragment.setGloballyFormulasAllowed(true); @@ -158,7 +96,7 @@ namespace storm { template - std::shared_ptr> SparseMaToSparseMdpTransformer::translate(storm::models::sparse::MarkovAutomaton const& ma, boost::optional const& timeRewardModelName) { + std::shared_ptr> ContinuousToDiscreteTimeModelTransformer::transform(storm::models::sparse::MarkovAutomaton const& ma, boost::optional const& timeRewardModelName) { STORM_LOG_THROW(ma.isClosed(), storm::exceptions::InvalidArgumentException, "Transformation of MA to its underlying MDP is only possible for closed MAs"); // Init the mdp components @@ -195,7 +133,7 @@ namespace storm { } template - std::shared_ptr> SparseMaToSparseMdpTransformer::translate(storm::models::sparse::MarkovAutomaton&& ma, boost::optional const& timeRewardModelName) { + std::shared_ptr> ContinuousToDiscreteTimeModelTransformer::transform(storm::models::sparse::MarkovAutomaton&& ma, boost::optional const& timeRewardModelName) { STORM_LOG_THROW(ma.isClosed(), storm::exceptions::InvalidArgumentException, "Transformation of MA to its underlying MDP is only possible for closed MAs"); std::vector& exitRates = ma.getExitRates(); @@ -231,31 +169,8 @@ namespace storm { return std::make_shared>(std::move(mdpComponents)); } - template - bool SparseMaToSparseMdpTransformer::transformationPreservesProperty(storm::logic::Formula const& formula) { - storm::logic::FragmentSpecification fragment = storm::logic::propositional(); - fragment.setProbabilityOperatorsAllowed(true); - fragment.setGloballyFormulasAllowed(true); - fragment.setReachabilityProbabilityFormulasAllowed(true); - fragment.setNextFormulasAllowed(true); - fragment.setUntilFormulasAllowed(true); - fragment.setRewardOperatorsAllowed(true); - fragment.setReachabilityRewardFormulasAllowed(true); - - return formula.isInFragment(fragment); - } - - template std::shared_ptr> transformContinuousToDiscreteModel(std::shared_ptr> markovModel, std::shared_ptr& formula); - template std::shared_ptr> transformContinuousToDiscreteModel(std::shared_ptr> markovModel, std::shared_ptr& formula); - template std::shared_ptr> transformContinuousToDiscreteModel(std::shared_ptr> markovModel, std::shared_ptr& formula); - template void transformContinuousToDiscreteModelInPlace(std::shared_ptr>& markovModel, std::shared_ptr& formula); - template void transformContinuousToDiscreteModelInPlace(std::shared_ptr>& markovModel, std::shared_ptr& formula); - template void transformContinuousToDiscreteModelInPlace(std::shared_ptr>& markovModel, std::shared_ptr& formula); - template class SparseCtmcToSparseDtmcTransformer; - template class SparseCtmcToSparseDtmcTransformer; - template class SparseCtmcToSparseDtmcTransformer; - template class SparseMaToSparseMdpTransformer; - template class SparseMaToSparseMdpTransformer; - template class SparseMaToSparseMdpTransformer; + template class ContinuousToDiscreteTimeModelTransformer; + template class ContinuousToDiscreteTimeModelTransformer; + template class ContinuousToDiscreteTimeModelTransformer; } } diff --git a/src/storm/transformer/ContinuousToDiscreteTimeModelTransformer.h b/src/storm/transformer/ContinuousToDiscreteTimeModelTransformer.h index cea1bf367..a84f19faa 100644 --- a/src/storm/transformer/ContinuousToDiscreteTimeModelTransformer.h +++ b/src/storm/transformer/ContinuousToDiscreteTimeModelTransformer.h @@ -12,41 +12,22 @@ namespace storm { namespace transformer { - - // Transforms the given continuous model to a discrete time model. - // If such a transformation does not preserve the given formula, the transformation does not take place and the original model is returned - // Moreover, the given formula might be changed (e.g. TimeOperatorFormulas become RewardOperatorFormulas). - template > - std::shared_ptr> transformContinuousToDiscreteModel(std::shared_ptr> markovModel, std::shared_ptr& formula); - - // Transforms the given continuous model to a discrete time model IN PLACE (i.e., the continuous model will be invalidated). - // If such a transformation does not preserve the given formula, the transformation does not take place. - // Moreover, the given formula might be changed (e.g. TimeOperatorFormulas become RewardOperatorFormulas). template > - void transformContinuousToDiscreteModelInPlace(std::shared_ptr>& markovModel, std::shared_ptr& formula); + class ContinuousToDiscreteTimeModelTransformer { + + // If this method returns true, the given formula is preserced by the transformation + static bool preservesFormula(storm::logic::Formula const& formula); - template > - class SparseCtmcToSparseDtmcTransformer { - public: // Transforms the given CTMC to its underlying (aka embedded) DTMC. // A reward model for time is added if a corresponding reward model name is given - static std::shared_ptr> translate(storm::models::sparse::Ctmc const& ctmc, boost::optional const& timeRewardModelName = boost::none); - static std::shared_ptr> translate(storm::models::sparse::Ctmc&& ctmc, boost::optional const& timeRewardModelName = boost::none); + static std::shared_ptr> transform(storm::models::sparse::Ctmc const& ctmc, boost::optional const& timeRewardModelName = boost::none); + static std::shared_ptr> transform(storm::models::sparse::Ctmc&& ctmc, boost::optional const& timeRewardModelName = boost::none); - // If this method returns true, the given formula is preserced by the transformation - static bool transformationPreservesProperty(storm::logic::Formula const& formula); - }; - - template > - class SparseMaToSparseMdpTransformer { - public: // Transforms the given MA to its underlying (aka embedded) MDP. // A reward model for time is added if a corresponding reward model name is given - static std::shared_ptr> translate(storm::models::sparse::MarkovAutomaton const& ma, boost::optional const& timeRewardModelName = boost::none); - static std::shared_ptr> translate(storm::models::sparse::MarkovAutomaton&& ma, boost::optional const& timeRewardModelName = boost::none); + static std::shared_ptr> transform(storm::models::sparse::MarkovAutomaton const& ma, boost::optional const& timeRewardModelName = boost::none); + static std::shared_ptr> transform(storm::models::sparse::MarkovAutomaton&& ma, boost::optional const& timeRewardModelName = boost::none); - // If this method returns true, the given formula is preserved by the transformation - static bool transformationPreservesProperty(storm::logic::Formula const& formula); }; } } diff --git a/src/storm/transformer/SymbolicToSparseTransformer.cpp b/src/storm/transformer/SymbolicToSparseTransformer.cpp index ec026968f..69b02acfb 100644 --- a/src/storm/transformer/SymbolicToSparseTransformer.cpp +++ b/src/storm/transformer/SymbolicToSparseTransformer.cpp @@ -11,22 +11,6 @@ namespace storm { namespace transformer { - template - std::shared_ptr> transformSymbolicToSparseModel(std::shared_ptr> const& symbolicModel) { - switch (symbolicModel->getType()) { - case storm::models::ModelType::Dtmc: - return SymbolicDtmcToSparseDtmcTransformer().translate(*symbolicModel->template as>()); - case storm::models::ModelType::Mdp: - return SymbolicMdpToSparseMdpTransformer::translate(*symbolicModel->template as>()); - case storm::models::ModelType::Ctmc: - return SymbolicCtmcToSparseCtmcTransformer::translate(*symbolicModel->template as>()); - default: - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Transformation of symbolic " << symbolicModel->getType() << " to sparse model is not implemented."); - } - return nullptr; - } - - template std::shared_ptr> SymbolicDtmcToSparseDtmcTransformer::translate(storm::models::symbolic::Dtmc const& symbolicDtmc) { this->odd = symbolicDtmc.getReachableStates().createOdd(); @@ -121,11 +105,6 @@ namespace storm { return std::make_shared>(transitionMatrix, labelling, rewardModels); } - template std::shared_ptr> transformSymbolicToSparseModel(std::shared_ptr> const& symbolicModel); - template std::shared_ptr> transformSymbolicToSparseModel(std::shared_ptr> const& symbolicModel); - template std::shared_ptr> transformSymbolicToSparseModel(std::shared_ptr> const& symbolicModel); - template std::shared_ptr> transformSymbolicToSparseModel(std::shared_ptr> const& symbolicModel); - template class SymbolicDtmcToSparseDtmcTransformer; template class SymbolicDtmcToSparseDtmcTransformer; template class SymbolicDtmcToSparseDtmcTransformer; diff --git a/src/storm/transformer/SymbolicToSparseTransformer.h b/src/storm/transformer/SymbolicToSparseTransformer.h index b55eb7ea9..5f4bed6c4 100644 --- a/src/storm/transformer/SymbolicToSparseTransformer.h +++ b/src/storm/transformer/SymbolicToSparseTransformer.h @@ -12,9 +12,6 @@ namespace storm { namespace transformer { - template - std::shared_ptr> transformSymbolicToSparseModel(std::shared_ptr> const& symbolicModel); - template class SymbolicDtmcToSparseDtmcTransformer { public: