diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index bdc1ee630..b1d667d64 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -665,7 +665,7 @@ namespace storm { return model; } - template + template void processInputWithValueTypeAndDdlib(SymbolicInput const& input) { auto coreSettings = storm::settings::getModule(); auto abstractionSettings = storm::settings::getModule(); @@ -674,19 +674,26 @@ namespace storm { storm::settings::modules::CoreSettings::Engine engine = coreSettings.getEngine(); if (engine == storm::settings::modules::CoreSettings::Engine::AbstractionRefinement && abstractionSettings.getAbstractionRefinementMethod() == storm::settings::modules::AbstractionSettings::Method::Games) { - verifyWithAbstractionRefinementEngine(input); + verifyWithAbstractionRefinementEngine(input); } else if (engine == storm::settings::modules::CoreSettings::Engine::Exploration) { - verifyWithExplorationEngine(input); + verifyWithExplorationEngine(input); } else { - std::shared_ptr model = buildPreprocessExportModelWithValueTypeAndDdlib(input, engine); + std::shared_ptr model = buildPreprocessExportModelWithValueTypeAndDdlib(input, engine); if (model) { + if (!std::is_same::value) { + if (model->isSymbolicModel()) { + auto symbolicModel = model->as>(); + model = symbolicModel->template toValueType(); + } + } + if (coreSettings.isCounterexampleSet()) { auto ioSettings = storm::settings::getModule(); - generateCounterexamples(model, input); + generateCounterexamples(model, input); } else { auto ioSettings = storm::settings::getModule(); - verifyModel(model, input, coreSettings); + verifyModel(model, input, coreSettings); } } } @@ -696,10 +703,14 @@ namespace storm { void processInputWithValueType(SymbolicInput const& input) { auto coreSettings = storm::settings::getModule(); auto generalSettings = storm::settings::getModule(); + auto bisimulationSettings = storm::settings::getModule(); if (coreSettings.getDdLibraryType() == storm::dd::DdType::CUDD && coreSettings.isDdLibraryTypeSetFromDefaultValue() && generalSettings.isExactSet()) { STORM_LOG_INFO("Switching to DD library sylvan to allow for rational arithmetic."); - processInputWithValueTypeAndDdlib(input); + processInputWithValueTypeAndDdlib(input); + } else if (coreSettings.getDdLibraryType() == storm::dd::DdType::CUDD && coreSettings.isDdLibraryTypeSetFromDefaultValue() && std::is_same::value && generalSettings.isBisimulationSet() && bisimulationSettings.useExactArithmeticInDdBisimulation()) { + STORM_LOG_INFO("Switching to DD library sylvan to allow for rational arithmetic."); + processInputWithValueTypeAndDdlib(input); } else if (coreSettings.getDdLibraryType() == storm::dd::DdType::CUDD) { processInputWithValueTypeAndDdlib(input); } else { diff --git a/src/storm/models/Model.h b/src/storm/models/Model.h index 4f17fdf24..52dfec2b6 100644 --- a/src/storm/models/Model.h +++ b/src/storm/models/Model.h @@ -16,6 +16,7 @@ namespace storm { Model(ModelType const& modelType) : ModelBase(modelType) { // Intentionally left empty. } + }; diff --git a/src/storm/models/ModelBase.h b/src/storm/models/ModelBase.h index 49f96d5ed..77fa5b60d 100644 --- a/src/storm/models/ModelBase.h +++ b/src/storm/models/ModelBase.h @@ -48,7 +48,7 @@ namespace storm { std::shared_ptr as() const { return std::dynamic_pointer_cast(this->shared_from_this()); } - + /*! * @brief Return the actual type of the model. * diff --git a/src/storm/models/symbolic/Ctmc.cpp b/src/storm/models/symbolic/Ctmc.cpp index e94079efc..4b05372be 100644 --- a/src/storm/models/symbolic/Ctmc.cpp +++ b/src/storm/models/symbolic/Ctmc.cpp @@ -84,11 +84,29 @@ namespace storm { return exitRates.get(); } + template + template + std::shared_ptr> Ctmc::toValueType() const { + typedef typename DeterministicModel::RewardModelType NewRewardModelType; + std::unordered_map newRewardModels; + + for (auto const& e : this->getRewardModels()) { + newRewardModels.emplace(e.first, e.second.template toValueType()); + } + + auto newLabelToBddMap = this->getLabelToBddMap(); + newLabelToBddMap.erase("init"); + newLabelToBddMap.erase("deadlock"); + + return std::make_shared>(this->getManagerAsSharedPointer(), this->getReachableStates(), this->getInitialStates(), this->getDeadlockStates(), this->getTransitionMatrix().template toValueType(), this->getExitRateVector().template toValueType(), this->getRowVariables(), this->getColumnVariables(), this->getRowColumnMetaVariablePairs(), newLabelToBddMap, newRewardModels); + } + // Explicitly instantiate the template class. template class Ctmc; template class Ctmc; template class Ctmc; + template std::shared_ptr> Ctmc::toValueType() const; template class Ctmc; } // namespace symbolic diff --git a/src/storm/models/symbolic/Ctmc.h b/src/storm/models/symbolic/Ctmc.h index 68c4e7b35..0035e3ffb 100644 --- a/src/storm/models/symbolic/Ctmc.h +++ b/src/storm/models/symbolic/Ctmc.h @@ -141,6 +141,9 @@ namespace storm { */ storm::dd::Add const& getExitRateVector() const; + template + std::shared_ptr> toValueType() const; + private: mutable boost::optional> exitRates; }; diff --git a/src/storm/models/symbolic/Dtmc.cpp b/src/storm/models/symbolic/Dtmc.cpp index fdd478b71..2b4adb149 100644 --- a/src/storm/models/symbolic/Dtmc.cpp +++ b/src/storm/models/symbolic/Dtmc.cpp @@ -43,11 +43,29 @@ namespace storm { // Intentionally left empty. } + template + template + std::shared_ptr> Dtmc::toValueType() const { + typedef typename DeterministicModel::RewardModelType NewRewardModelType; + std::unordered_map newRewardModels; + + for (auto const& e : this->getRewardModels()) { + newRewardModels.emplace(e.first, e.second.template toValueType()); + } + + auto newLabelToBddMap = this->getLabelToBddMap(); + newLabelToBddMap.erase("init"); + newLabelToBddMap.erase("deadlock"); + + return std::make_shared>(this->getManagerAsSharedPointer(), this->getReachableStates(), this->getInitialStates(), this->getDeadlockStates(), this->getTransitionMatrix().template toValueType(), this->getRowVariables(), this->getColumnVariables(), this->getRowColumnMetaVariablePairs(), newLabelToBddMap, newRewardModels); + } + // Explicitly instantiate the template class. template class Dtmc; template class Dtmc; template class Dtmc; + template std::shared_ptr> Dtmc::toValueType() const; template class Dtmc; } // namespace symbolic diff --git a/src/storm/models/symbolic/Dtmc.h b/src/storm/models/symbolic/Dtmc.h index ebe837e1c..76a3e81ca 100644 --- a/src/storm/models/symbolic/Dtmc.h +++ b/src/storm/models/symbolic/Dtmc.h @@ -76,6 +76,10 @@ namespace storm { std::vector> const& rowColumnMetaVariablePairs, std::map> labelToBddMap = std::map>(), std::unordered_map const& rewardModels = std::unordered_map()); + + template + std::shared_ptr> toValueType() const; + }; } // namespace symbolic diff --git a/src/storm/models/symbolic/MarkovAutomaton.cpp b/src/storm/models/symbolic/MarkovAutomaton.cpp index 09b2fe7b3..add866c8b 100644 --- a/src/storm/models/symbolic/MarkovAutomaton.cpp +++ b/src/storm/models/symbolic/MarkovAutomaton.cpp @@ -115,11 +115,29 @@ namespace storm { return this->exitRateVector; } + template + template + std::shared_ptr> MarkovAutomaton::toValueType() const { + typedef typename NondeterministicModel::RewardModelType NewRewardModelType; + std::unordered_map newRewardModels; + + for (auto const& e : this->getRewardModels()) { + newRewardModels.emplace(e.first, e.second.template toValueType()); + } + + auto newLabelToBddMap = this->getLabelToBddMap(); + newLabelToBddMap.erase("init"); + newLabelToBddMap.erase("deadlock"); + + return std::make_shared>(this->getManagerAsSharedPointer(), this->getMarkovianMarker(), this->getReachableStates(), this->getInitialStates(), this->getDeadlockStates(), this->getTransitionMatrix().template toValueType(), this->getRowVariables(), this->getColumnVariables(), this->getRowColumnMetaVariablePairs(), this->getNondeterminismVariables(), newLabelToBddMap, newRewardModels); + } + // Explicitly instantiate the template class. template class MarkovAutomaton; template class MarkovAutomaton; template class MarkovAutomaton; + template std::shared_ptr> MarkovAutomaton::toValueType() const; template class MarkovAutomaton; } // namespace symbolic diff --git a/src/storm/models/symbolic/MarkovAutomaton.h b/src/storm/models/symbolic/MarkovAutomaton.h index 30b1dbdfc..e2e0f3369 100644 --- a/src/storm/models/symbolic/MarkovAutomaton.h +++ b/src/storm/models/symbolic/MarkovAutomaton.h @@ -92,6 +92,9 @@ namespace storm { storm::dd::Add const& getExitRateVector() const; + template + std::shared_ptr> toValueType() const; + private: /*! * Computes the member data related to Markovian stuff. diff --git a/src/storm/models/symbolic/Mdp.cpp b/src/storm/models/symbolic/Mdp.cpp index c5de7a371..65bd49769 100644 --- a/src/storm/models/symbolic/Mdp.cpp +++ b/src/storm/models/symbolic/Mdp.cpp @@ -45,11 +45,29 @@ namespace storm { // Intentionally left empty. } + template + template + std::shared_ptr> Mdp::toValueType() const { + typedef typename NondeterministicModel::RewardModelType NewRewardModelType; + std::unordered_map newRewardModels; + + for (auto const& e : this->getRewardModels()) { + newRewardModels.emplace(e.first, e.second.template toValueType()); + } + + auto newLabelToBddMap = this->getLabelToBddMap(); + newLabelToBddMap.erase("init"); + newLabelToBddMap.erase("deadlock"); + + return std::make_shared>(this->getManagerAsSharedPointer(), this->getReachableStates(), this->getInitialStates(), this->getDeadlockStates(), this->getTransitionMatrix().template toValueType(), this->getRowVariables(), this->getColumnVariables(), this->getRowColumnMetaVariablePairs(), this->getNondeterminismVariables(), newLabelToBddMap, newRewardModels); + } + // Explicitly instantiate the template class. template class Mdp; template class Mdp; template class Mdp; + template std::shared_ptr> Mdp::toValueType() const; template class Mdp; } // namespace symbolic diff --git a/src/storm/models/symbolic/Mdp.h b/src/storm/models/symbolic/Mdp.h index 771f0bd05..d8432ad49 100644 --- a/src/storm/models/symbolic/Mdp.h +++ b/src/storm/models/symbolic/Mdp.h @@ -83,6 +83,9 @@ namespace storm { std::map> labelToBddMap = std::map>(), std::unordered_map const& rewardModels = std::unordered_map()); + template + std::shared_ptr> toValueType() const; + }; } // namespace symbolic diff --git a/src/storm/models/symbolic/Model.cpp b/src/storm/models/symbolic/Model.cpp index 1c1ebf749..71897fded 100644 --- a/src/storm/models/symbolic/Model.cpp +++ b/src/storm/models/symbolic/Model.cpp @@ -2,6 +2,11 @@ #include +#include "storm/models/symbolic/Dtmc.h" +#include "storm/models/symbolic/Ctmc.h" +#include "storm/models/symbolic/Mdp.h" +#include "storm/models/symbolic/MarkovAutomaton.h" + #include "storm/exceptions/IllegalArgumentException.h" #include "storm/exceptions/InvalidOperationException.h" @@ -211,6 +216,11 @@ namespace storm { return labelToExpressionMap; } + template + std::map> const& Model::getLabelToBddMap() const { + return labelToBddMap; + } + template storm::dd::Add Model::getRowColumnIdentity() const { return (storm::utility::dd::getRowColumnDiagonal(this->getManager(), this->getRowColumnMetaVariablePairs()) && this->getReachableStates()).template toAdd(); @@ -372,11 +382,30 @@ namespace storm { return parameters; } + template + template + std::shared_ptr> Model::toValueType() const { + // Make a huge branching here as we cannot make a templated function virtual. + if (this->getType() == storm::models::ModelType::Dtmc) { + return this->template as>()->template toValueType(); + } else if (this->getType() == storm::models::ModelType::Ctmc) { + return this->template as>()->template toValueType(); + } else if (this->getType() == storm::models::ModelType::Mdp) { + return this->template as>()->template toValueType(); + } else if (this->getType() == storm::models::ModelType::MarkovAutomaton) { + return this->template as>()->template toValueType(); + } + + STORM_LOG_WARN("Could not convert value type of model."); + return nullptr; + } + // Explicitly instantiate the template class. template class Model; template class Model; template class Model; + template std::shared_ptr> Model::toValueType() const; template class Model; } // namespace symbolic } // namespace models diff --git a/src/storm/models/symbolic/Model.h b/src/storm/models/symbolic/Model.h index 42cf143f1..e194dfabc 100644 --- a/src/storm/models/symbolic/Model.h +++ b/src/storm/models/symbolic/Model.h @@ -327,6 +327,9 @@ namespace storm { std::set const& getParameters() const; + template + std::shared_ptr> toValueType() const; + protected: /*! * Sets the transition matrix of the model. @@ -342,6 +345,13 @@ namespace storm { */ std::map const& getLabelToExpressionMap() const; + /*! + * Retrieves the mapping of labels to their defining expressions. + * + * @returns The mapping of labels to their defining expressions. + */ + std::map> const& getLabelToBddMap() const; + /*! * Prints the information header (number of states and transitions) of the model to the specified stream. * diff --git a/src/storm/models/symbolic/StandardRewardModel.cpp b/src/storm/models/symbolic/StandardRewardModel.cpp index ffd94ad74..38bd56c5c 100644 --- a/src/storm/models/symbolic/StandardRewardModel.cpp +++ b/src/storm/models/symbolic/StandardRewardModel.cpp @@ -196,10 +196,17 @@ namespace storm { } } + template + template + StandardRewardModel StandardRewardModel::toValueType() const { + return StandardRewardModel(this->hasStateRewards() ? boost::make_optional(this->getStateRewardVector().template toValueType()) : boost::none, this->hasStateActionRewards() ? boost::make_optional(this->getStateActionRewardVector().template toValueType()) : boost::none, this->hasTransitionRewards() ? boost::make_optional(this->getTransitionRewardMatrix().template toValueType()) : boost::none); + } + template class StandardRewardModel; template class StandardRewardModel; template class StandardRewardModel; + template StandardRewardModel StandardRewardModel::toValueType() const; template class StandardRewardModel; } diff --git a/src/storm/models/symbolic/StandardRewardModel.h b/src/storm/models/symbolic/StandardRewardModel.h index c16f144e5..3d705e448 100644 --- a/src/storm/models/symbolic/StandardRewardModel.h +++ b/src/storm/models/symbolic/StandardRewardModel.h @@ -212,6 +212,9 @@ namespace storm { */ void reduceToStateBasedRewards(storm::dd::Add const& transitionMatrix, std::set const& rowVariables, std::set const& columnVariables, bool reduceToStateRewards); + template + StandardRewardModel toValueType() const; + private: // The state reward vector. boost::optional> optionalStateRewardVector; diff --git a/src/storm/settings/modules/BisimulationSettings.cpp b/src/storm/settings/modules/BisimulationSettings.cpp index 56b3419e9..0b7c219f5 100644 --- a/src/storm/settings/modules/BisimulationSettings.cpp +++ b/src/storm/settings/modules/BisimulationSettings.cpp @@ -21,6 +21,7 @@ namespace storm { const std::string BisimulationSettings::reuseOptionName = "reuse"; const std::string BisimulationSettings::initialPartitionOptionName = "init"; const std::string BisimulationSettings::refinementModeOptionName = "refine"; + const std::string BisimulationSettings::exactArithmeticDdOptionName = "ddexact"; BisimulationSettings::BisimulationSettings() : ModuleSettings(moduleName) { std::vector types = { "strong", "weak" }; @@ -31,6 +32,7 @@ namespace storm { this->addOption(storm::settings::OptionBuilder(moduleName, representativeOptionName, false, "Sets whether to use representatives in the quotient rather than block numbers.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, originalVariablesOptionName, false, "Sets whether to use the original variables in the quotient rather than the block variables.").build()); + this->addOption(storm::settings::OptionBuilder(moduleName, exactArithmeticDdOptionName, false, "Sets whether to use exact arithmetic in dd-based bisimulation.").build()); std::vector signatureModes = { "eager", "lazy" }; this->addOption(storm::settings::OptionBuilder(moduleName, signatureModeOptionName, false, "Sets the signature computation mode.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("mode", "The mode to use.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(signatureModes)).setDefaultValueString("eager").build()).build()); @@ -84,6 +86,10 @@ namespace storm { return this->getOption(originalVariablesOptionName).getHasOptionBeenSet(); } + bool BisimulationSettings::useExactArithmeticInDdBisimulation() const { + return this->getOption(exactArithmeticDdOptionName).getHasOptionBeenSet(); + } + storm::dd::bisimulation::SignatureMode BisimulationSettings::getSignatureMode() const { std::string modeAsString = this->getOption(signatureModeOptionName).getArgumentByName("mode").getValueAsString(); if (modeAsString == "eager") { diff --git a/src/storm/settings/modules/BisimulationSettings.h b/src/storm/settings/modules/BisimulationSettings.h index eb9627f68..c06713a8a 100644 --- a/src/storm/settings/modules/BisimulationSettings.h +++ b/src/storm/settings/modules/BisimulationSettings.h @@ -63,6 +63,13 @@ namespace storm { */ bool isUseOriginalVariablesSet() const; + /*! + * Retrieves whether exact arithmetic is to be used in symbolic bisimulation minimization. + * + * @return True iff exact arithmetic is to be used in symbolic bisimulation minimization. + */ + bool useExactArithmeticInDdBisimulation() const; + /*! * Retrieves the mode to compute signatures. */ @@ -99,6 +106,7 @@ namespace storm { static const std::string initialPartitionOptionName; static const std::string refinementModeOptionName; static const std::string parallelismModeOptionName; + static const std::string exactArithmeticDdOptionName; }; } // namespace modules } // namespace settings