#include "storm/models/symbolic/Model.h" #include #include "storm/exceptions/IllegalArgumentException.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm/adapters/AddExpressionAdapter.h" #include "storm/models/symbolic/StandardRewardModel.h" #include "storm/utility/macros.h" #include "storm/utility/dd.h" #include "storm/exceptions/NotSupportedException.h" #include "storm/exceptions/WrongFormatException.h" namespace storm { namespace models { namespace symbolic { template Model::Model(storm::models::ModelType const& modelType, std::shared_ptr> manager, storm::dd::Bdd reachableStates, storm::dd::Bdd initialStates, storm::dd::Bdd deadlockStates, storm::dd::Add transitionMatrix, std::set const& rowVariables, std::shared_ptr> rowExpressionAdapter, std::set const& columnVariables, std::vector> const& rowColumnMetaVariablePairs, std::map labelToExpressionMap, std::unordered_map const& rewardModels) : storm::models::Model(modelType), manager(manager), reachableStates(reachableStates), transitionMatrix(transitionMatrix), rowVariables(rowVariables), rowExpressionAdapter(rowExpressionAdapter), columnVariables(columnVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs), labelToExpressionMap(labelToExpressionMap), rewardModels(rewardModels) { this->labelToBddMap.emplace("init", initialStates); this->labelToBddMap.emplace("deadlock", deadlockStates); } template Model::Model(storm::models::ModelType const& modelType, std::shared_ptr> manager, storm::dd::Bdd reachableStates, storm::dd::Bdd initialStates, storm::dd::Bdd deadlockStates, storm::dd::Add transitionMatrix, std::set const& rowVariables, std::set const& columnVariables, std::vector> const& rowColumnMetaVariablePairs, std::map> labelToBddMap, std::unordered_map const& rewardModels) : storm::models::Model(modelType), manager(manager), reachableStates(reachableStates), transitionMatrix(transitionMatrix), rowVariables(rowVariables), rowExpressionAdapter(nullptr), columnVariables(columnVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs), labelToBddMap(labelToBddMap), rewardModels(rewardModels) { STORM_LOG_THROW(this->labelToBddMap.find("init") == this->labelToBddMap.end(), storm::exceptions::WrongFormatException, "Illegal custom label 'init'."); STORM_LOG_THROW(this->labelToBddMap.find("deadlock") == this->labelToBddMap.end(), storm::exceptions::WrongFormatException, "Illegal custom label 'deadlock'."); this->labelToBddMap.emplace("init", initialStates); this->labelToBddMap.emplace("deadlock", deadlockStates); } template uint_fast64_t Model::getNumberOfStates() const { return reachableStates.getNonZeroCount(); } template uint_fast64_t Model::getNumberOfTransitions() const { return transitionMatrix.getNonZeroCount(); } template uint_fast64_t Model::getNumberOfChoices() const { return reachableStates.getNonZeroCount(); } template storm::dd::DdManager& Model::getManager() const { return *manager; } template std::shared_ptr> const& Model::getManagerAsSharedPointer() const { return manager; } template storm::dd::Bdd const& Model::getReachableStates() const { return reachableStates; } template storm::dd::Bdd const& Model::getInitialStates() const { return labelToBddMap.at("init"); } template storm::dd::Bdd const& Model::getDeadlockStates() const { return labelToBddMap.at("deadlock"); } template storm::dd::Bdd Model::getStates(std::string const& label) const { // First check whether we have a BDD for this label. auto bddIt = labelToBddMap.find(label); if (bddIt != labelToBddMap.end()) { return bddIt->second; } else { // If not, check for an expression we can translate. auto expressionIt = labelToExpressionMap.find(label); STORM_LOG_THROW(expressionIt != labelToExpressionMap.end(), storm::exceptions::IllegalArgumentException, "The label " << label << " is invalid for the labeling of the model."); return this->getStates(expressionIt->second); } } template storm::expressions::Expression Model::getExpression(std::string const& label) const { auto expressionIt = labelToExpressionMap.find(label); STORM_LOG_THROW(expressionIt != labelToExpressionMap.end(), storm::exceptions::IllegalArgumentException, "Cannot retrieve the expression for the label " << label << "."); return expressionIt->second; } template storm::dd::Bdd Model::getStates(storm::expressions::Expression const& expression) const { if (expression.isTrue()) { return this->getReachableStates(); } else if (expression.isFalse()) { return manager->getBddZero(); } // Look up the string equivalent of the expression. std::stringstream stream; stream << expression; auto bddIt = labelToBddMap.find(stream.str()); if (bddIt != labelToBddMap.end()) { return bddIt->second; } // Finally try to translate the expression with an adapter. STORM_LOG_THROW(rowExpressionAdapter != nullptr, storm::exceptions::InvalidOperationException, "Cannot create BDD for expression without expression adapter."); return rowExpressionAdapter->translateExpression(expression).toBdd() && this->reachableStates; } template bool Model::hasLabel(std::string const& label) const { auto bddIt = labelToBddMap.find(label); if (bddIt != labelToBddMap.end()) { return true; } auto expressionIt = labelToExpressionMap.find(label); if (expressionIt != labelToExpressionMap.end()) { return true; } else { return false; } } template storm::dd::Add const& Model::getTransitionMatrix() const { return transitionMatrix; } template storm::dd::Add& Model::getTransitionMatrix() { return transitionMatrix; } template storm::dd::Bdd Model::getQualitativeTransitionMatrix(bool) const { return this->getTransitionMatrix().notZero(); } template std::set const& Model::getRowVariables() const { return rowVariables; } template std::set const& Model::getColumnVariables() const { return columnVariables; } template std::set Model::getRowAndNondeterminismVariables() const { std::set result; std::set_union(this->getRowVariables().begin(), this->getRowVariables().end(), this->getNondeterminismVariables().begin(), this->getNondeterminismVariables().end(), std::inserter(result, result.begin())); return result; } template std::set Model::getColumnAndNondeterminismVariables() const { std::set result; std::set_union(this->getColumnVariables().begin(), this->getColumnVariables().end(), this->getNondeterminismVariables().begin(), this->getNondeterminismVariables().end(), std::inserter(result, result.begin())); return result; } template std::set const& Model::getNondeterminismVariables() const { return emptyVariableSet; } template std::vector> const& Model::getRowColumnMetaVariablePairs() const { return rowColumnMetaVariablePairs; } template void Model::setTransitionMatrix(storm::dd::Add const& transitionMatrix) { this->transitionMatrix = transitionMatrix; } template std::map const& Model::getLabelToExpressionMap() const { return labelToExpressionMap; } template storm::dd::Add Model::getRowColumnIdentity() const { return (storm::utility::dd::getRowColumnDiagonal(this->getManager(), this->getRowColumnMetaVariablePairs()) && this->getReachableStates()).template toAdd(); } template bool Model::hasRewardModel(std::string const& rewardModelName) const { return this->rewardModels.find(rewardModelName) != this->rewardModels.end(); } template typename Model::RewardModelType const& Model::getRewardModel(std::string const& rewardModelName) const { auto it = this->rewardModels.find(rewardModelName); if (it == this->rewardModels.end()) { if (rewardModelName.empty()) { if (this->hasUniqueRewardModel()) { return this->getUniqueRewardModel(); } else { STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "Unable to refer to default reward model, because there is no default model or it is not unique."); } } else { STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "The requested reward model '" << rewardModelName << "' does not exist."); } } return it->second; } template typename Model::RewardModelType const& Model::getUniqueRewardModel() const { STORM_LOG_THROW(this->hasUniqueRewardModel(), storm::exceptions::InvalidOperationException, "Cannot retrieve unique reward model, because there is no unique one."); return this->rewardModels.cbegin()->second; } template std::string const& Model::getUniqueRewardModelName() const { STORM_LOG_THROW(this->hasUniqueRewardModel(), storm::exceptions::InvalidOperationException, "Cannot retrieve name of unique reward model, because there is no unique one."); return this->rewardModels.cbegin()->first; } template typename Model::RewardModelType& Model::getUniqueRewardModel() { STORM_LOG_THROW(this->hasUniqueRewardModel(), storm::exceptions::InvalidOperationException, "Cannot retrieve unique reward model, because there is no unique one."); return this->rewardModels.begin()->second; } template bool Model::hasUniqueRewardModel() const { return this->rewardModels.size() == 1; } template bool Model::hasRewardModel() const { return !this->rewardModels.empty(); } template std::unordered_map::RewardModelType>& Model::getRewardModels() { return this->rewardModels; } template std::unordered_map::RewardModelType> const& Model::getRewardModels() const { return this->rewardModels; } template void Model::printModelInformationToStream(std::ostream& out) const { this->printModelInformationHeaderToStream(out); this->printModelInformationFooterToStream(out); } template std::vector Model::getLabels() const { std::vector labels; for(auto const& entry : labelToExpressionMap) { labels.push_back(entry.first); } return labels; } template void Model::printModelInformationHeaderToStream(std::ostream& out) const { out << "-------------------------------------------------------------- " << std::endl; 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; } template void Model::printModelInformationFooterToStream(std::ostream& out) const { this->printRewardModelsInformationToStream(out); this->printDdVariableInformationToStream(out); out << std::endl; out << "Labels: \t" << (this->labelToExpressionMap.size() + this->labelToBddMap.size()) << std::endl; for (auto const& label : labelToBddMap) { out << " * " << label.first << " -> " << label.second.getNonZeroCount() << " state(s) (" << label.second.getNodeCount() << " nodes)" << std::endl; } for (auto const& label : labelToExpressionMap) { out << " * " << label.first << std::endl; } out << "-------------------------------------------------------------- " << std::endl; } template void Model::printRewardModelsInformationToStream(std::ostream& out) const { if (this->rewardModels.size()) { std::vector rewardModelNames; std::for_each(this->rewardModels.cbegin(), this->rewardModels.cend(), [&rewardModelNames] (typename std::pair const& nameRewardModelPair) { if (nameRewardModelPair.first.empty()) { rewardModelNames.push_back("(default)"); } else { rewardModelNames.push_back(nameRewardModelPair.first); } }); out << "Reward Models: " << boost::join(rewardModelNames, ", ") << std::endl; } else { out << "Reward Models: none" << std::endl; } } template void Model::printDdVariableInformationToStream(std::ostream& out) const { 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() << " meta variables (" << rowVariableCount << " DD variables)" << ", columns: " << this->columnVariables.size() << " meta variables (" << columnVariableCount << " DD variables)"; } template std::shared_ptr> const& Model::getRowExpressionAdapter() const { return this->rowExpressionAdapter; } template bool Model::isSymbolicModel() const { return true; } template void Model::addParameters(std::set const& parameters) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "This value type does not support parameters."); } template std::set const& Model::getParameters() const { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "This value type does not support parameters."); } template<> void Model::addParameters(std::set const& parameters) { this->parameters.insert(parameters.begin(), parameters.end()); } template<> std::set const& Model::getParameters() const { return parameters; } // Explicitly instantiate the template class. template class Model; template class Model; template class Model; template class Model; } // namespace symbolic } // namespace models } // namespace storm