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.
 
 
 
 

158 lines
9.8 KiB

#include "storm/transformer/SparseParametricModelSimplifier.h"
#include "storm/adapters/CarlAdapter.h"
#include "storm/models/sparse/Dtmc.h"
#include "storm/models/sparse/Mdp.h"
#include "storm/models/sparse/StandardRewardModel.h"
#include "storm/solver/stateelimination/NondeterministicModelStateEliminator.h"
#include "storm/storage/FlexibleSparseMatrix.h"
#include "storm/utility/vector.h"
#include "storm/exceptions/InvalidStateException.h"
#include "storm/exceptions/NotImplementedException.h"
#include "storm/exceptions/InvalidPropertyException.h"
namespace storm {
namespace transformer {
template<typename SparseModelType>
SparseParametricModelSimplifier<SparseModelType>::SparseParametricModelSimplifier(SparseModelType const& model) : originalModel(model) {
// intentionally left empty
}
template<typename SparseModelType>
bool SparseParametricModelSimplifier<SparseModelType>::simplify(storm::logic::Formula const& formula) {
// Make sure that there is no old result from a previous call
simplifiedModel = nullptr;
simplifiedFormula = nullptr;
if (formula.isProbabilityOperatorFormula()) {
storm::logic::ProbabilityOperatorFormula const& probOpForm = formula.asProbabilityOperatorFormula();
if (probOpForm.getSubformula().isUntilFormula()) {
return simplifyForUntilProbabilities(probOpForm);
} else if (probOpForm.getSubformula().isReachabilityProbabilityFormula()) {
return simplifyForReachabilityProbabilities(probOpForm);
} else if (probOpForm.getSubformula().isBoundedUntilFormula()) {
return simplifyForBoundedUntilProbabilities(probOpForm);
}
} else if (formula.isRewardOperatorFormula()) {
storm::logic::RewardOperatorFormula rewOpForm = formula.asRewardOperatorFormula();
STORM_LOG_THROW((rewOpForm.hasRewardModelName() && originalModel.hasRewardModel(rewOpForm.getRewardModelName())) || (!rewOpForm.hasRewardModelName() && originalModel.hasUniqueRewardModel()), storm::exceptions::InvalidPropertyException, "The reward model specified by formula " << formula << " is not available in the given model.");
if (rewOpForm.getSubformula().isReachabilityRewardFormula()) {
return simplifyForReachabilityRewards(rewOpForm);
} else if (rewOpForm.getSubformula().isCumulativeRewardFormula()) {
return simplifyForCumulativeRewards(rewOpForm);
}
}
// reaching this point means that the provided formula is not supported. Thus, no simplification is possible.
STORM_LOG_DEBUG("Simplification not possible because the formula is not suppoerted. Formula: " << formula);
return false;
}
template<typename SparseModelType>
std::shared_ptr<SparseModelType> SparseParametricModelSimplifier<SparseModelType>::getSimplifiedModel() const {
STORM_LOG_THROW(simplifiedModel, storm::exceptions::InvalidStateException, "Tried to get the simplified model but simplification was not invoked before.");
return simplifiedModel;
}
template<typename SparseModelType>
std::shared_ptr<storm::logic::Formula const> SparseParametricModelSimplifier<SparseModelType>::getSimplifiedFormula() const {
STORM_LOG_THROW(simplifiedFormula, storm::exceptions::InvalidStateException, "Tried to get the simplified formula but simplification was not invoked before.");
return simplifiedFormula;
}
template<typename SparseModelType>
bool SparseParametricModelSimplifier<SparseModelType>::simplifyForUntilProbabilities(storm::logic::ProbabilityOperatorFormula const& formula) {
// If this method was not overriden by any subclass, simplification is not possible
STORM_LOG_DEBUG("Simplification not possible because the formula is not suppoerted. Formula: " << formula);
return false;
}
template<typename SparseModelType>
bool SparseParametricModelSimplifier<SparseModelType>::simplifyForReachabilityProbabilities(storm::logic::ProbabilityOperatorFormula const& formula) {
// transform to until formula
auto untilFormula = std::make_shared<storm::logic::UntilFormula const>(storm::logic::Formula::getTrueFormula(), formula.getSubformula().asEventuallyFormula().getSubformula().asSharedPointer());
return simplifyForUntilProbabilities(storm::logic::ProbabilityOperatorFormula(untilFormula, formula.getOperatorInformation()));
}
template<typename SparseModelType>
bool SparseParametricModelSimplifier<SparseModelType>::simplifyForBoundedUntilProbabilities(storm::logic::ProbabilityOperatorFormula const& formula) {
// If this method was not overriden by any subclass, simplification is not possible
STORM_LOG_DEBUG("Simplification not possible because the formula is not suppoerted. Formula: " << formula);
return false;
}
template<typename SparseModelType>
bool SparseParametricModelSimplifier<SparseModelType>::simplifyForReachabilityRewards(storm::logic::RewardOperatorFormula const& formula) {
// If this method was not overriden by any subclass, simplification is not possible
STORM_LOG_DEBUG("Simplification not possible because the formula is not suppoerted. Formula: " << formula);
return false;
}
template<typename SparseModelType>
bool SparseParametricModelSimplifier<SparseModelType>::simplifyForCumulativeRewards(storm::logic::RewardOperatorFormula const& formula) {
// If this method was not overriden by any subclass, simplification is not possible
STORM_LOG_DEBUG("Simplification not possible because the formula is not suppoerted. Formula: " << formula);
return false;
}
template<typename SparseModelType>
std::shared_ptr<SparseModelType> SparseParametricModelSimplifier<SparseModelType>::eliminateConstantDeterministicStates(SparseModelType const& model, boost::optional<std::string> const& rewardModelName) {
storm::storage::SparseMatrix<typename SparseModelType::ValueType> const& sparseMatrix = model.getTransitionMatrix();
// Get the states without any label
storm::storage::BitVector considerForElimination(model.getNumberOfStates(), false);
for(auto const& label : model.getStateLabeling().getLabels()) {
considerForElimination |= model.getStateLabeling().getStates(label);
}
considerForElimination.complement();
// get the action-based reward values
std::vector<typename SparseModelType::ValueType> actionRewards;
if(rewardModelName) {
actionRewards = model.getRewardModel(*rewardModelName).getTotalRewardVector(sparseMatrix);
} else {
actionRewards = std::vector<typename SparseModelType::ValueType>(model.getTransitionMatrix().getRowCount(), storm::utility::zero<typename SparseModelType::ValueType>());
}
// Find the states that are to be eliminated
storm::storage::BitVector selectedStates = considerForElimination;
for (auto state : considerForElimination) {
if (sparseMatrix.getRowGroupSize(state) == 1 && (!rewardModelName.is_initialized() || storm::utility::isConstant(actionRewards[sparseMatrix.getRowGroupIndices()[state]]))) {
for (auto const& entry : sparseMatrix.getRowGroup(state)) {
if(!storm::utility::isConstant(entry.getValue())) {
selectedStates.set(state, false);
break;
}
}
} else {
selectedStates.set(state, false);
}
}
// invoke elimination and obtain resulting transition matrix
storm::storage::FlexibleSparseMatrix<typename SparseModelType::ValueType> flexibleMatrix(sparseMatrix);
storm::storage::FlexibleSparseMatrix<typename SparseModelType::ValueType> flexibleBackwardTransitions(sparseMatrix.transpose(), true);
storm::solver::stateelimination::NondeterministicModelStateEliminator<typename SparseModelType::ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions, actionRewards);
for(auto state : selectedStates) {
stateEliminator.eliminateState(state, true);
}
selectedStates.complement();
auto keptRows = sparseMatrix.getRowFilter(selectedStates);
storm::storage::SparseMatrix<typename SparseModelType::ValueType> newTransitionMatrix = flexibleMatrix.createSparseMatrix(keptRows, selectedStates);
// obtain the reward model for the resulting system
std::unordered_map<std::string, typename SparseModelType::RewardModelType> rewardModels;
if(rewardModelName) {
storm::utility::vector::filterVectorInPlace(actionRewards, keptRows);
rewardModels.insert(std::make_pair(*rewardModelName, typename SparseModelType::RewardModelType(boost::none, std::move(actionRewards))));
}
return std::make_shared<SparseModelType>(std::move(newTransitionMatrix), model.getStateLabeling().getSubLabeling(selectedStates), std::move(rewardModels));
}
template class SparseParametricModelSimplifier<storm::models::sparse::Dtmc<storm::RationalFunction>>;
template class SparseParametricModelSimplifier<storm::models::sparse::Mdp<storm::RationalFunction>>;
}
}