You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

274 lines
18 KiB

#include "SymbolicToSparseTransformer.h"
#include "storm/storage/dd/DdManager.h"
#include "storm/storage/dd/Add.h"
#include "storm/storage/dd/Bdd.h"
#include "storm/storage/sparse/ModelComponents.h"
#include "storm/models/symbolic/StandardRewardModel.h"
#include "storm/models/sparse/StandardRewardModel.h"
#include "storm/utility/macros.h"
#include "storm/exceptions/NotImplementedException.h"
#include "storm/logic/AtomicExpressionFormula.h"
#include "storm/logic/AtomicLabelFormula.h"
namespace storm {
namespace transformer {
struct LabelInformation {
LabelInformation(std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
for (auto const& formula : formulas) {
std::vector<std::shared_ptr<storm::logic::AtomicLabelFormula const>> atomicLabelFormulas = formula->getAtomicLabelFormulas();
for (auto const& labelFormula : atomicLabelFormulas) {
atomicLabels.insert(labelFormula->getLabel());
}
std::vector<std::shared_ptr<storm::logic::AtomicExpressionFormula const>> atomicExpressionFormulas = formula->getAtomicExpressionFormulas();
for (auto const& expressionFormula : atomicExpressionFormulas) {
std::stringstream ss;
ss << expressionFormula->getExpression();
expressionLabels[ss.str()] = expressionFormula->getExpression();
}
}
}
std::set<std::string> atomicLabels;
std::map<std::string, storm::expressions::Expression> expressionLabels;
};
template<storm::dd::DdType Type, typename ValueType>
std::shared_ptr<storm::models::sparse::Dtmc<ValueType>> SymbolicDtmcToSparseDtmcTransformer<Type, ValueType>::translate(storm::models::symbolic::Dtmc<Type, ValueType> const& symbolicDtmc, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
this->odd = symbolicDtmc.getReachableStates().createOdd();
storm::storage::SparseMatrix<ValueType> transitionMatrix = symbolicDtmc.getTransitionMatrix().toMatrix(this->odd, this->odd);
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ValueType>> rewardModels;
for (auto const& rewardModelNameAndModel : symbolicDtmc.getRewardModels()) {
boost::optional<std::vector<ValueType>> stateRewards;
boost::optional<std::vector<ValueType>> stateActionRewards;
boost::optional<storm::storage::SparseMatrix<ValueType>> transitionRewards;
if (rewardModelNameAndModel.second.hasStateRewards()) {
stateRewards = rewardModelNameAndModel.second.getStateRewardVector().toVector(this->odd);
}
if (rewardModelNameAndModel.second.hasStateActionRewards()) {
stateActionRewards = rewardModelNameAndModel.second.getStateActionRewardVector().toVector(this->odd);
}
if (rewardModelNameAndModel.second.hasTransitionRewards()) {
transitionRewards = rewardModelNameAndModel.second.getTransitionRewardMatrix().toMatrix(this->odd, this->odd);
}
rewardModels.emplace(rewardModelNameAndModel.first,storm::models::sparse::StandardRewardModel<ValueType>(stateRewards, stateActionRewards, transitionRewards));
}
storm::models::sparse::StateLabeling labelling(transitionMatrix.getRowGroupCount());
labelling.addLabel("init", symbolicDtmc.getInitialStates().toVector(this->odd));
labelling.addLabel("deadlock", symbolicDtmc.getDeadlockStates().toVector(this->odd));
if (formulas.empty()) {
for (auto const& label : symbolicDtmc.getLabels()) {
labelling.addLabel(label, symbolicDtmc.getStates(label).toVector(this->odd));
}
} else {
LabelInformation labelInfo(formulas);
for (auto const& label : labelInfo.atomicLabels) {
labelling.addLabel(label, symbolicDtmc.getStates(label).toVector(this->odd));
}
for (auto const& expressionLabel : labelInfo.expressionLabels) {
labelling.addLabel(expressionLabel.first, symbolicDtmc.getStates(expressionLabel.second).toVector(this->odd));
}
}
return std::make_shared<storm::models::sparse::Dtmc<ValueType>>(transitionMatrix, labelling, rewardModels);
}
template<storm::dd::DdType Type, typename ValueType>
storm::dd::Odd const& SymbolicDtmcToSparseDtmcTransformer<Type, ValueType>::getOdd() const {
return this->odd;
}
template<storm::dd::DdType Type, typename ValueType>
std::shared_ptr<storm::models::sparse::Mdp<ValueType>> SymbolicMdpToSparseMdpTransformer<Type, ValueType>::translate(storm::models::symbolic::Mdp<Type, ValueType> const& symbolicMdp, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
storm::dd::Odd odd = symbolicMdp.getReachableStates().createOdd();
// Collect action reward vectors that need translation
std::vector<storm::dd::Add<Type, ValueType>> symbolicActionRewardVectors;
std::map<std::string, uint64_t> rewardNameToActionRewardIndexMap;
for (auto const& rewardModelNameAndModel : symbolicMdp.getRewardModels()) {
if (rewardModelNameAndModel.second.hasStateActionRewards()) {
rewardNameToActionRewardIndexMap.emplace(rewardModelNameAndModel.first, symbolicActionRewardVectors.size());
symbolicActionRewardVectors.push_back(rewardModelNameAndModel.second.getStateActionRewardVector());
}
}
// Build transition matrix and (potentially) actionRewardVectors.
storm::storage::SparseMatrix<ValueType> transitionMatrix;
std::vector<std::vector<ValueType>> actionRewardVectors;
if (symbolicActionRewardVectors.empty()) {
transitionMatrix = symbolicMdp.getTransitionMatrix().toMatrix(symbolicMdp.getNondeterminismVariables(), odd, odd);
} else {
auto matrRewards = symbolicMdp.getTransitionMatrix().toMatrixVectors(symbolicActionRewardVectors, symbolicMdp.getNondeterminismVariables(), odd, odd);
transitionMatrix = std::move(matrRewards.first);
actionRewardVectors = std::move(matrRewards.second);
}
// Translate reward models
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ValueType>> rewardModels;
for (auto const& rewardModelNameAndModel : symbolicMdp.getRewardModels()) {
boost::optional<std::vector<ValueType>> stateRewards;
boost::optional<std::vector<ValueType>> stateActionRewards;
boost::optional<storm::storage::SparseMatrix<ValueType>> transitionRewards;
if (rewardModelNameAndModel.second.hasStateRewards()) {
stateRewards = rewardModelNameAndModel.second.getStateRewardVector().toVector(odd);
}
auto actRewIndexIt = rewardNameToActionRewardIndexMap.find(rewardModelNameAndModel.first);
if (actRewIndexIt != rewardNameToActionRewardIndexMap.end()) {
stateActionRewards = std::move(actionRewardVectors[actRewIndexIt->second]);
}
STORM_LOG_THROW(!rewardModelNameAndModel.second.hasTransitionRewards(), storm::exceptions::NotImplementedException, "Translation of symbolic to explicit transition rewards is not yet supported.");
rewardModels.emplace(rewardModelNameAndModel.first, storm::models::sparse::StandardRewardModel<ValueType>(stateRewards, stateActionRewards, transitionRewards));
}
storm::models::sparse::StateLabeling labelling(transitionMatrix.getRowGroupCount());
labelling.addLabel("init", symbolicMdp.getInitialStates().toVector(odd));
labelling.addLabel("deadlock", symbolicMdp.getDeadlockStates().toVector(odd));
if (formulas.empty()) {
for (auto const& label : symbolicMdp.getLabels()) {
labelling.addLabel(label, symbolicMdp.getStates(label).toVector(odd));
}
} else {
LabelInformation labelInfo(formulas);
for (auto const& label : labelInfo.atomicLabels) {
labelling.addLabel(label, symbolicMdp.getStates(label).toVector(odd));
}
for (auto const& expressionLabel : labelInfo.expressionLabels) {
labelling.addLabel(expressionLabel.first, symbolicMdp.getStates(expressionLabel.second).toVector(odd));
}
}
return std::make_shared<storm::models::sparse::Mdp<ValueType>>(transitionMatrix, labelling, rewardModels);
}
template<storm::dd::DdType Type, typename ValueType>
std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> SymbolicCtmcToSparseCtmcTransformer<Type, ValueType>::translate(storm::models::symbolic::Ctmc<Type, ValueType> const& symbolicCtmc, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
storm::dd::Odd odd = symbolicCtmc.getReachableStates().createOdd();
storm::storage::SparseMatrix<ValueType> transitionMatrix = symbolicCtmc.getTransitionMatrix().toMatrix(odd, odd);
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ValueType>> rewardModels;
for (auto const& rewardModelNameAndModel : symbolicCtmc.getRewardModels()) {
boost::optional<std::vector<ValueType>> stateRewards;
boost::optional<std::vector<ValueType>> stateActionRewards;
boost::optional<storm::storage::SparseMatrix<ValueType>> transitionRewards;
if (rewardModelNameAndModel.second.hasStateRewards()) {
stateRewards = rewardModelNameAndModel.second.getStateRewardVector().toVector(odd);
}
if (rewardModelNameAndModel.second.hasStateActionRewards()) {
stateActionRewards = rewardModelNameAndModel.second.getStateActionRewardVector().toVector(odd);
}
if (rewardModelNameAndModel.second.hasTransitionRewards()) {
transitionRewards = rewardModelNameAndModel.second.getTransitionRewardMatrix().toMatrix(odd, odd);
}
rewardModels.emplace(rewardModelNameAndModel.first,storm::models::sparse::StandardRewardModel<ValueType>(stateRewards, stateActionRewards, transitionRewards));
}
storm::models::sparse::StateLabeling labelling(transitionMatrix.getRowGroupCount());
labelling.addLabel("init", symbolicCtmc.getInitialStates().toVector(odd));
labelling.addLabel("deadlock", symbolicCtmc.getDeadlockStates().toVector(odd));
if (formulas.empty()) {
for (auto const& label : symbolicCtmc.getLabels()) {
labelling.addLabel(label, symbolicCtmc.getStates(label).toVector(odd));
}
} else {
LabelInformation labelInfo(formulas);
for (auto const& label : labelInfo.atomicLabels) {
labelling.addLabel(label, symbolicCtmc.getStates(label).toVector(odd));
}
for (auto const& expressionLabel : labelInfo.expressionLabels) {
labelling.addLabel(expressionLabel.first, symbolicCtmc.getStates(expressionLabel.second).toVector(odd));
}
}
return std::make_shared<storm::models::sparse::Ctmc<ValueType>>(transitionMatrix, labelling, rewardModels);
}
template<storm::dd::DdType Type, typename ValueType>
std::shared_ptr<storm::models::sparse::MarkovAutomaton<ValueType>> SymbolicMaToSparseMaTransformer<Type, ValueType>::translate(storm::models::symbolic::MarkovAutomaton<Type, ValueType> const& symbolicMa, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
storm::dd::Odd odd = symbolicMa.getReachableStates().createOdd();
// Collect action reward vectors that need translation
std::vector<storm::dd::Add<Type, ValueType>> symbolicActionRewardVectors;
std::map<std::string, uint64_t> rewardNameToActionRewardIndexMap;
for (auto const& rewardModelNameAndModel : symbolicMa.getRewardModels()) {
if (rewardModelNameAndModel.second.hasStateActionRewards()) {
rewardNameToActionRewardIndexMap.emplace(rewardModelNameAndModel.first, symbolicActionRewardVectors.size());
symbolicActionRewardVectors.push_back(rewardModelNameAndModel.second.getStateActionRewardVector());
}
}
// Build transition matrix and (potentially) actionRewardVectors.
storm::storage::SparseMatrix<ValueType> transitionMatrix;
std::vector<std::vector<ValueType>> actionRewardVectors;
if (symbolicActionRewardVectors.empty()) {
transitionMatrix = symbolicMa.getTransitionMatrix().toMatrix(symbolicMa.getNondeterminismVariables(), odd, odd);
} else {
auto matrRewards = symbolicMa.getTransitionMatrix().toMatrixVectors(symbolicActionRewardVectors, symbolicMa.getNondeterminismVariables(), odd, odd);
transitionMatrix = std::move(matrRewards.first);
actionRewardVectors = std::move(matrRewards.second);
}
// Translate reward models
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ValueType>> rewardModels;
for (auto const& rewardModelNameAndModel : symbolicMa.getRewardModels()) {
boost::optional<std::vector<ValueType>> stateRewards;
boost::optional<std::vector<ValueType>> stateActionRewards;
boost::optional<storm::storage::SparseMatrix<ValueType>> transitionRewards;
if (rewardModelNameAndModel.second.hasStateRewards()) {
stateRewards = rewardModelNameAndModel.second.getStateRewardVector().toVector(odd);
}
auto actRewIndexIt = rewardNameToActionRewardIndexMap.find(rewardModelNameAndModel.first);
if (actRewIndexIt != rewardNameToActionRewardIndexMap.end()) {
stateActionRewards = std::move(actionRewardVectors[actRewIndexIt->second]);
}
STORM_LOG_THROW(!rewardModelNameAndModel.second.hasTransitionRewards(), storm::exceptions::NotImplementedException, "Translation of symbolic to explicit transition rewards is not yet supported.");
rewardModels.emplace(rewardModelNameAndModel.first, storm::models::sparse::StandardRewardModel<ValueType>(stateRewards, stateActionRewards, transitionRewards));
}
storm::models::sparse::StateLabeling labelling(transitionMatrix.getRowGroupCount());
labelling.addLabel("init", symbolicMa.getInitialStates().toVector(odd));
labelling.addLabel("deadlock", symbolicMa.getDeadlockStates().toVector(odd));
if (formulas.empty()) {
for (auto const& label : symbolicMa.getLabels()) {
labelling.addLabel(label, symbolicMa.getStates(label).toVector(odd));
}
} else {
LabelInformation labelInfo(formulas);
for (auto const& label : labelInfo.atomicLabels) {
labelling.addLabel(label, symbolicMa.getStates(label).toVector(odd));
}
for (auto const& expressionLabel : labelInfo.expressionLabels) {
labelling.addLabel(expressionLabel.first, symbolicMa.getStates(expressionLabel.second).toVector(odd));
}
}
storm::storage::BitVector markovianStates = symbolicMa.getMarkovianStates().toVector(odd);
storm::storage::sparse::ModelComponents<ValueType> components(std::move(transitionMatrix), std::move(labelling), std::move(rewardModels), false, std::move(markovianStates));
components.exitRates = symbolicMa.getExitRateVector().toVector(odd);
return std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType>>(std::move(components));
}
template class SymbolicDtmcToSparseDtmcTransformer<storm::dd::DdType::CUDD, double>;
template class SymbolicDtmcToSparseDtmcTransformer<storm::dd::DdType::Sylvan, double>;
template class SymbolicDtmcToSparseDtmcTransformer<storm::dd::DdType::Sylvan, storm::RationalNumber>;
template class SymbolicDtmcToSparseDtmcTransformer<storm::dd::DdType::Sylvan, storm::RationalFunction>;
template class SymbolicMdpToSparseMdpTransformer<storm::dd::DdType::CUDD, double>;
template class SymbolicMdpToSparseMdpTransformer<storm::dd::DdType::Sylvan, double>;
template class SymbolicMdpToSparseMdpTransformer<storm::dd::DdType::Sylvan, storm::RationalNumber>;
template class SymbolicMdpToSparseMdpTransformer<storm::dd::DdType::Sylvan, storm::RationalFunction>;
template class SymbolicCtmcToSparseCtmcTransformer<storm::dd::DdType::CUDD, double>;
template class SymbolicCtmcToSparseCtmcTransformer<storm::dd::DdType::Sylvan, double>;
template class SymbolicCtmcToSparseCtmcTransformer<storm::dd::DdType::Sylvan, storm::RationalNumber>;
template class SymbolicCtmcToSparseCtmcTransformer<storm::dd::DdType::Sylvan, storm::RationalFunction>;
template class SymbolicMaToSparseMaTransformer<storm::dd::DdType::CUDD, double>;
template class SymbolicMaToSparseMaTransformer<storm::dd::DdType::Sylvan, double>;
template class SymbolicMaToSparseMaTransformer<storm::dd::DdType::Sylvan, storm::RationalNumber>;
template class SymbolicMaToSparseMaTransformer<storm::dd::DdType::Sylvan, storm::RationalFunction>;
}
}