diff --git a/src/builder/DdPrismModelBuilder.cpp b/src/builder/DdPrismModelBuilder.cpp index ec80e6dd6..329e1dfe3 100644 --- a/src/builder/DdPrismModelBuilder.cpp +++ b/src/builder/DdPrismModelBuilder.cpp @@ -1,6 +1,7 @@ #include "src/builder/DdPrismModelBuilder.h" #include "src/models/symbolic/Dtmc.h" +#include "src/models/symbolic/Ctmc.h" #include "src/models/symbolic/Mdp.h" #include "src/storage/dd/CuddDd.h" @@ -171,6 +172,7 @@ namespace storm { if (!commandDds.empty()) { switch (generationInfo.program.getModelType()){ case storm::prism::Program::ModelType::DTMC: + case storm::prism::Program::ModelType::CTMC: result = combineCommandsToActionDTMC(generationInfo, commandDds); break; case storm::prism::Program::ModelType::MDP: @@ -193,7 +195,9 @@ namespace storm { for (auto const& commandDd : commandDds) { // Check for overlapping guards. temporary = commandDd.guardDd * allGuards; - STORM_LOG_WARN_COND(temporary.isZero(), "Guard of a command overlaps with previous guards."); + + // Issue a warning if there are overlapping guards in a non-CTMC model. + STORM_LOG_WARN_COND(temporary.isZero() || generationInfo.program.getModelType() == storm::prism::Program::ModelType::CTMC, "Guard of a command overlaps with previous guards."); allGuards += commandDd.guardDd; allCommands += commandDd.guardDd * commandDd.transitionsDd; @@ -325,7 +329,7 @@ namespace storm { storm::dd::Add action1Extended = action1.transitionsDd * identityDd2; storm::dd::Add action2Extended = action2.transitionsDd * identityDd1; - if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC) { + if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC || generationInfo.program.getModelType() == storm::prism::Program::ModelType::CTMC) { return ActionDecisionDiagram(action1.guardDd + action2.guardDd, action1Extended + action2Extended, 0); } else if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::MDP) { if (action1.transitionsDd.isZero()) { @@ -432,7 +436,7 @@ namespace storm { } return result; - } else if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC) { + } else if (generationInfo.program.getModelType() == storm::prism::Program::ModelType::DTMC || generationInfo.program.getModelType() == storm::prism::Program::ModelType::CTMC) { // Simply add all actions. storm::dd::Add result = module.independentAction.transitionsDd; for (auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) { @@ -673,6 +677,8 @@ namespace storm { if (program.getModelType() == storm::prism::Program::ModelType::DTMC) { return std::shared_ptr>(new storm::models::symbolic::Dtmc(generationInfo.manager, reachableStates, initialStates, transitionMatrix, generationInfo.rowMetaVariables, generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.columnExpressionAdapter, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping, stateAndTransitionRewards ? stateAndTransitionRewards.get().first : boost::optional>(), stateAndTransitionRewards ? stateAndTransitionRewards.get().second : boost::optional>())); + } else if (program.getModelType() == storm::prism::Program::ModelType::CTMC) { + return std::shared_ptr>(new storm::models::symbolic::Ctmc(generationInfo.manager, reachableStates, initialStates, transitionMatrix, generationInfo.rowMetaVariables, generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.columnExpressionAdapter, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping, stateAndTransitionRewards ? stateAndTransitionRewards.get().first : boost::optional>(), stateAndTransitionRewards ? stateAndTransitionRewards.get().second : boost::optional>())); } else if (program.getModelType() == storm::prism::Program::ModelType::MDP) { return std::shared_ptr>(new storm::models::symbolic::Mdp(generationInfo.manager, reachableStates, initialStates, transitionMatrix, generationInfo.rowMetaVariables, generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.columnExpressionAdapter, generationInfo.rowColumnMetaVariablePairs, generationInfo.allNondeterminismVariables, labelToExpressionMapping, stateAndTransitionRewards ? stateAndTransitionRewards.get().first : boost::optional>(), stateAndTransitionRewards ? stateAndTransitionRewards.get().second : boost::optional>())); } else { diff --git a/src/models/symbolic/Ctmc.cpp b/src/models/symbolic/Ctmc.cpp new file mode 100644 index 000000000..b90aa5afd --- /dev/null +++ b/src/models/symbolic/Ctmc.cpp @@ -0,0 +1,29 @@ +#include "src/models/symbolic/Ctmc.h" + +namespace storm { + namespace models { + namespace symbolic { + + template + Ctmc::Ctmc(std::shared_ptr> manager, + storm::dd::Bdd reachableStates, + storm::dd::Bdd initialStates, + storm::dd::Add transitionMatrix, + std::set const& rowVariables, + std::shared_ptr> rowExpressionAdapter, + std::set const& columnVariables, + std::shared_ptr> columnExpressionAdapter, + std::vector> const& rowColumnMetaVariablePairs, + std::map labelToExpressionMap, + boost::optional> const& optionalStateRewardVector, + boost::optional> const& optionalTransitionRewardMatrix) + : DeterministicModel(storm::models::ModelType::Ctmc, manager, reachableStates, initialStates, transitionMatrix, rowVariables, rowExpressionAdapter, columnVariables, columnExpressionAdapter, rowColumnMetaVariablePairs, labelToExpressionMap, optionalStateRewardVector, optionalTransitionRewardMatrix) { + // Intentionally left empty. + } + + // Explicitly instantiate the template class. + template class Ctmc; + + } // namespace symbolic + } // namespace models +} // namespace storm \ No newline at end of file diff --git a/src/models/symbolic/Ctmc.h b/src/models/symbolic/Ctmc.h new file mode 100644 index 000000000..7d46dcd73 --- /dev/null +++ b/src/models/symbolic/Ctmc.h @@ -0,0 +1,61 @@ +#ifndef STORM_MODELS_SYMBOLIC_CTMC_H_ +#define STORM_MODELS_SYMBOLIC_CTMC_H_ + +#include "src/models/symbolic/DeterministicModel.h" +#include "src/utility/OsDetection.h" + +namespace storm { + namespace models { + namespace symbolic { + + /*! + * This class represents a continuous-time Markov chain. + */ + template + class Ctmc : public DeterministicModel { + public: + Ctmc(Ctmc const& other) = default; + Ctmc& operator=(Ctmc const& other) = default; + +#ifndef WINDOWS + Ctmc(Ctmc&& other) = default; + Ctmc& operator=(Ctmc&& other) = default; +#endif + + /*! + * Constructs a model from the given data. + * + * @param manager The manager responsible for the decision diagrams. + * @param reachableStates A DD representing the reachable states. + * @param initialStates A DD representing the initial states of the model. + * @param transitionMatrix The matrix representing the transitions in the model. + * @param rowVariables The set of row meta variables used in the DDs. + * @param rowExpressionAdapter An object that can be used to translate expressions in terms of the row + * meta variables. + * @param columVariables The set of column meta variables used in the DDs. + * @param columnExpressionAdapter An object that can be used to translate expressions in terms of the + * column meta variables. + * @param rowColumnMetaVariablePairs All pairs of row/column meta variables. + * @param labelToExpressionMap A mapping from label names to their defining expressions. + * @param optionalStateRewardVector The reward values associated with the states. + * @param optionalTransitionRewardMatrix The reward values associated with the transitions of the model. + */ + Ctmc(std::shared_ptr> manager, + storm::dd::Bdd reachableStates, + storm::dd::Bdd initialStates, + storm::dd::Add transitionMatrix, + std::set const& rowVariables, + std::shared_ptr> rowExpressionAdapter, + std::set const& columnVariables, + std::shared_ptr> columnExpressionAdapter, + std::vector> const& rowColumnMetaVariablePairs, + std::map labelToExpressionMap = std::map(), + boost::optional> const& optionalStateRewardVector = boost::optional>(), + boost::optional> const& optionalTransitionRewardMatrix = boost::optional>()); + }; + + } // namespace symbolic + } // namespace models +} // namespace storm + +#endif /* STORM_MODELS_SYMBOLIC_CTMC_H_ */ diff --git a/src/models/symbolic/Model.cpp b/src/models/symbolic/Model.cpp index fc7f1aad6..9f67ec7bd 100644 --- a/src/models/symbolic/Model.cpp +++ b/src/models/symbolic/Model.cpp @@ -138,7 +138,17 @@ namespace storm { out << "Model type: \t" << this->getType() << " (symbolic)" << std::endl; out << "States: \t" << this->getNumberOfStates() << " (" << reachableStates.getNodeCount() << " nodes)" << std::endl; out << "Transitions: \t" << this->getNumberOfTransitions() << " (" << transitionMatrix.getNodeCount() << " nodes)" << std::endl; - out << "Variables: \t" << "rows: " << this->rowVariables.size() << ", columns: " << this->columnVariables.size() << std::endl; + + uint_fast64_t rowVariableCount = 0; + for (auto const& metaVariable : this->rowVariables) { + rowVariableCount += this->getManager().getMetaVariable(metaVariable).getNumberOfDdVariables(); + } + uint_fast64_t columnVariableCount = 0; + for (auto const& metaVariable : this->columnVariables) { + columnVariableCount += this->getManager().getMetaVariable(metaVariable).getNumberOfDdVariables(); + } + + out << "Variables: \t" << "rows: " << this->rowVariables.size() << "(" << rowVariableCount << " dd variables)" << ", columns: " << this->columnVariables.size() << "(" << columnVariableCount << " dd variables)" << std::endl; out << "Labels: \t" << this->labelToExpressionMap.size() << std::endl; for (auto const& label : labelToExpressionMap) { out << " * " << label.first << std::endl;