/* * File: ModelInstantiator.cpp * Author: Tim Quatmann * * Created on February 23, 2016 */ #include "storm/utility/ModelInstantiator.h" #include "storm/models/sparse/StandardRewardModel.h" namespace storm { namespace utility { template<typename ParametricSparseModelType, typename ConstantSparseModelType> ModelInstantiator<ParametricSparseModelType, ConstantSparseModelType>::ModelInstantiator(ParametricSparseModelType const& parametricModel){ //Now pre-compute the information for the equation system. initializeModelSpecificData(parametricModel); initializeMatrixMapping(this->instantiatedModel->getTransitionMatrix(), this->functions, this->matrixMapping, parametricModel.getTransitionMatrix()); for(auto& rewModel : this->instantiatedModel->getRewardModels()) { if(rewModel.second.hasStateRewards()){ initializeVectorMapping(rewModel.second.getStateRewardVector(), this->functions, this->vectorMapping, parametricModel.getRewardModel(rewModel.first).getStateRewardVector()); } if(rewModel.second.hasStateActionRewards()){ initializeVectorMapping(rewModel.second.getStateActionRewardVector(), this->functions, this->vectorMapping, parametricModel.getRewardModel(rewModel.first).getStateActionRewardVector()); } if(rewModel.second.hasTransitionRewards()){ initializeMatrixMapping(rewModel.second.getTransitionRewardMatrix(), this->functions, this->matrixMapping, parametricModel.getRewardModel(rewModel.first).getTransitionRewardMatrix()); } } } template<typename ParametricSparseModelType, typename ConstantType> ModelInstantiator<ParametricSparseModelType, ConstantType>::~ModelInstantiator() { //Intentionally left empty } template<typename ParametricSparseModelType, typename ConstantSparseModelType> storm::storage::SparseMatrix<typename ConstantSparseModelType::ValueType> ModelInstantiator<ParametricSparseModelType, ConstantSparseModelType>::buildDummyMatrix(storm::storage::SparseMatrix<ParametricType> const& parametricMatrix) const{ storm::storage::SparseMatrixBuilder<ConstantType> matrixBuilder(parametricMatrix.getRowCount(), parametricMatrix.getColumnCount(), parametricMatrix.getEntryCount(), true, !parametricMatrix.hasTrivialRowGrouping(), parametricMatrix.hasTrivialRowGrouping() ? 0 : parametricMatrix.getRowGroupCount()); ConstantType dummyValue = storm::utility::one<ConstantType>(); if (parametricMatrix.hasTrivialRowGrouping()) { for (uint_fast64_t row = 0; row < parametricMatrix.getRowCount(); ++row) { for (auto const& paramEntry : parametricMatrix.getRow(row)) { matrixBuilder.addNextValue(row, paramEntry.getColumn(), dummyValue); } } } else { for(uint_fast64_t rowGroup = 0; rowGroup < parametricMatrix.getRowGroupCount(); ++rowGroup){ matrixBuilder.newRowGroup(parametricMatrix.getRowGroupIndices()[rowGroup]); for (uint_fast64_t row = parametricMatrix.getRowGroupIndices()[rowGroup]; row < parametricMatrix.getRowGroupIndices()[rowGroup+1]; ++row) { for(auto const& paramEntry : parametricMatrix.getRow(row)){ matrixBuilder.addNextValue(row, paramEntry.getColumn(), dummyValue); } } } } return matrixBuilder.build(); } template<typename ParametricSparseModelType, typename ConstantSparseModelType> std::unordered_map<std::string, typename ConstantSparseModelType::RewardModelType> ModelInstantiator<ParametricSparseModelType, ConstantSparseModelType>::buildDummyRewardModels(std::unordered_map<std::string, typename ParametricSparseModelType::RewardModelType> const& parametricRewardModel) const { std::unordered_map<std::string, typename ConstantSparseModelType::RewardModelType> result; for(auto const& paramRewardModel : parametricRewardModel){ auto const& rewModel = paramRewardModel.second; boost::optional<std::vector<ConstantType>> optionalStateRewardVector; if(rewModel.hasStateRewards()) { optionalStateRewardVector = std::vector<ConstantType>(rewModel.getStateRewardVector().size()); } boost::optional<std::vector<ConstantType>> optionalStateActionRewardVector; if(rewModel.hasStateActionRewards()) { optionalStateActionRewardVector = std::vector<ConstantType>(rewModel.getStateActionRewardVector().size()); } boost::optional<storm::storage::SparseMatrix<ConstantType>> optionalTransitionRewardMatrix; if(rewModel.hasTransitionRewards()) { optionalTransitionRewardMatrix = buildDummyMatrix(rewModel.getTransitionRewardMatrix()); } result.insert(std::make_pair(paramRewardModel.first, storm::models::sparse::StandardRewardModel<ConstantType>(std::move(optionalStateRewardVector), std::move(optionalStateActionRewardVector), std::move(optionalTransitionRewardMatrix)) )); } return result; } template<typename ParametricSparseModelType, typename ConstantSparseModelType> void ModelInstantiator<ParametricSparseModelType, ConstantSparseModelType>::initializeMatrixMapping(storm::storage::SparseMatrix<ConstantType>& constantMatrix, std::unordered_map<ParametricType, ConstantType>& functions, std::vector<std::pair<typename storm::storage::SparseMatrix<ConstantType>::iterator, ConstantType*>>& mapping, storm::storage::SparseMatrix<ParametricType> const& parametricMatrix) const{ ConstantType dummyValue = storm::utility::one<ConstantType>(); auto constantEntryIt = constantMatrix.begin(); auto parametricEntryIt = parametricMatrix.begin(); while(parametricEntryIt != parametricMatrix.end()){ STORM_LOG_ASSERT(parametricEntryIt->getColumn() == constantEntryIt->getColumn(), "Entries of parametric and constant matrix are not at the same position"); if(storm::utility::isConstant(parametricEntryIt->getValue())){ //Constant entries can be inserted directly constantEntryIt->setValue(storm::utility::convertNumber<ConstantType>(storm::utility::parametric::getConstantPart(parametricEntryIt->getValue()))); } else { //insert the new function and store that the current constantMatrix entry needs to be set to the value of this function auto functionsIt = functions.insert(std::make_pair(parametricEntryIt->getValue(), dummyValue)).first; mapping.emplace_back(std::make_pair(constantEntryIt, &(functionsIt->second))); //Note that references to elements of an unordered map remain valid after calling unordered_map::insert. } ++constantEntryIt; ++parametricEntryIt; } STORM_LOG_ASSERT(constantEntryIt == constantMatrix.end(), "Parametric matrix seems to have more or less entries then the constant matrix"); constantMatrix.updateNonzeroEntryCount(); } template<typename ParametricSparseModelType, typename ConstantSparseModelType> void ModelInstantiator<ParametricSparseModelType, ConstantSparseModelType>::initializeVectorMapping(std::vector<ConstantType>& constantVector, std::unordered_map<ParametricType, ConstantType>& functions, std::vector<std::pair<typename std::vector<ConstantType>::iterator, ConstantType*>>& mapping, std::vector<ParametricType> const& parametricVector) const{ ConstantType dummyValue = storm::utility::one<ConstantType>(); auto constantEntryIt = constantVector.begin(); auto parametricEntryIt = parametricVector.begin(); while(parametricEntryIt != parametricVector.end()){ if(storm::utility::isConstant(storm::utility::simplify(*parametricEntryIt))){ //Constant entries can be inserted directly *constantEntryIt = storm::utility::convertNumber<ConstantType>(storm::utility::parametric::getConstantPart(*parametricEntryIt)); } else { //insert the new function and store that the current constantVector entry needs to be set to the value of this function auto functionsIt = functions.insert(std::make_pair(*parametricEntryIt, dummyValue)).first; mapping.emplace_back(std::make_pair(constantEntryIt, &(functionsIt->second))); //Note that references to elements of an unordered map remain valid after calling unordered_map::insert. } ++constantEntryIt; ++parametricEntryIt; } STORM_LOG_ASSERT(constantEntryIt == constantVector.end(), "Parametric vector seems to have more or less entries then the constant vector"); } template<typename ParametricSparseModelType, typename ConstantSparseModelType> ConstantSparseModelType const& ModelInstantiator<ParametricSparseModelType, ConstantSparseModelType>::instantiate(std::map<VariableType, CoefficientType>const& valuation){ //Write results into the placeholders for(auto& functionResult : this->functions){ functionResult.second=storm::utility::convertNumber<ConstantType>( storm::utility::parametric::evaluate(functionResult.first, valuation)); } //Write the instantiated values to the matrices and vectors according to the stored mappings for(auto& entryValuePair : this->matrixMapping){ entryValuePair.first->setValue(*(entryValuePair.second)); } for(auto& entryValuePair : this->vectorMapping){ *(entryValuePair.first)=*(entryValuePair.second); } return *this->instantiatedModel; } template<typename ParametricSparseModelType, typename ConstantSparseModelType> void ModelInstantiator<ParametricSparseModelType, ConstantSparseModelType>::checkValid() const { // TODO write some checks } #ifdef STORM_HAVE_CARL template class ModelInstantiator<storm::models::sparse::Dtmc<storm::RationalFunction>, storm::models::sparse::Dtmc<double>>; template class ModelInstantiator<storm::models::sparse::Mdp<storm::RationalFunction>, storm::models::sparse::Mdp<double>>; template class ModelInstantiator<storm::models::sparse::Ctmc<storm::RationalFunction>, storm::models::sparse::Ctmc<double>>; template class ModelInstantiator<storm::models::sparse::MarkovAutomaton<storm::RationalFunction>, storm::models::sparse::MarkovAutomaton<double>>; template class ModelInstantiator<storm::models::sparse::StochasticTwoPlayerGame<storm::RationalFunction>, storm::models::sparse::StochasticTwoPlayerGame<double>>; #endif } //namespace utility } //namespace storm