Browse Source

added subsystemBuilder for preprocessing infinite rewards

Former-commit-id: 1dbec569cc
main
TimQu 9 years ago
parent
commit
ad1e530756
  1. 11
      src/modelchecker/multiobjective/helper/SparseMultiObjectivePreprocessor.cpp
  2. 5
      src/modelchecker/multiobjective/helper/SparseMultiObjectivePreprocessor.h
  3. 4
      src/modelchecker/multiobjective/helper/SparseMultiObjectivePreprocessorData.h
  4. 4
      src/transformer/StateDuplicator.h
  5. 211
      src/transformer/SubsystemBuilder.h

11
src/modelchecker/multiobjective/helper/SparseMultiObjectivePreprocessor.cpp

@ -4,8 +4,8 @@
#include "src/models/sparse/StandardRewardModel.h"
#include "src/modelchecker/propositional/SparsePropositionalModelChecker.h"
#include "src/modelchecker/results/ExplicitQualitativeCheckResult.h"
#include "src/storage/BitVector.h"
#include "src/transformer/StateDuplicator.h"
#include "src/transformer/SubsystemBuilder.h"
#include "src/utility/macros.h"
#include "src/utility/vector.h"
#include "src/utility/graph.h"
@ -18,10 +18,11 @@ namespace storm {
namespace helper {
template<typename SparseModelType>
typename SparseMultiObjectivePreprocessor<SparseModelType>::PreprocessorData SparseMultiObjectivePreprocessor<SparseModelType>::preprocess(storm::logic::MultiObjectiveFormula const& originalFormula, SparseModelType const& originalModel) {
PreprocessorData data(std::move(originalModel));
//Initialize the state mapping.
data.newToOldStateIndexMapping = storm::utility::vector::buildVectorForRange(0, data.preprocessedModel.getNumberOfStates());
typename SparseMultiObjectivePreprocessor<SparseModelType>::PreprocessorData SparseMultiObjectivePreprocessor<SparseModelType>::preprocess(storm::logic::MultiObjectiveFormula const& originalFormula, SparseModelType const& originalModel, storm::storage::BitVector const& subsystem) {
auto subsystemBuilderResult = storm::transformer::SubsystemBuilder<SparseModelType>::transform(originalModel, subsystem);
PreprocessorData data(originalModel, std::move(*subsystemBuilderResult.model), std::move(subsystemBuilderResult.newToOldStateIndexMapping));
//Invoke preprocessing on the individual objectives
for(auto const& subFormula : originalFormula.getSubFormulas()){
STORM_LOG_DEBUG("Preprocessing objective " << *subFormula<< ".");

5
src/modelchecker/multiobjective/helper/SparseMultiObjectivePreprocessor.h

@ -3,6 +3,7 @@
#include "src/logic/Formulas.h"
#include "src/modelchecker/multiobjective/helper/SparseMultiObjectivePreprocessorData.h"
#include "src/storage/BitVector.h"
namespace storm {
namespace modelchecker {
@ -25,8 +26,10 @@ namespace storm {
* Preprocesses the given model w.r.t. the given formulas.
* @param originalModel The considered model
* @param originalFormula the considered formula. The subformulas should only contain one OperatorFormula at top level, i.e., the formula is simple.
* @param subsystem the states of the original model which should be considered. Choices that have a transition leading outside of the subsystem will be
* removed. Hence, every state in the subsystem has to have one choice that stays inside the subsystem.
*/
static PreprocessorData preprocess(storm::logic::MultiObjectiveFormula const& originalFormula, SparseModelType const& originalModel);
static PreprocessorData preprocess(storm::logic::MultiObjectiveFormula const& originalFormula, SparseModelType const& originalModel, storm::storage::BitVector const& subsystem);
private:

4
src/modelchecker/multiobjective/helper/SparseMultiObjectivePreprocessorData.h

@ -17,8 +17,8 @@ namespace storm {
enum class QueryType { Achievability, Numerical, Pareto };
SparseModelType preprocessedModel;
SparseModelType const& originalModel;
SparseModelType preprocessedModel;
std::vector<uint_fast64_t> newToOldStateIndexMapping;
QueryType queryType;
@ -27,7 +27,7 @@ namespace storm {
bool produceSchedulers;
SparseMultiObjectivePreprocessorData(SparseModelType const& model) : preprocessedModel(model), originalModel(model), produceSchedulers(false) {
SparseMultiObjectivePreprocessorData(SparseModelType const& originalModel, SparseModelType&& preprocessedModel, std::vector<uint_fast64_t>&& newToOldStateIndexMapping) : originalModel(originalModel), preprocessedModel(preprocessedModel), newToOldStateIndexMapping(newToOldStateIndexMapping), produceSchedulers(false) {
//Intentionally left empty
}

4
src/transformer/StateDuplicator.h

@ -235,7 +235,7 @@ namespace storm {
std::is_same<MT,storm::models::sparse::Ctmc<typename SparseModelType::ValueType>>::value,
MT>::type
createTransformedModel(MT const& originalModel,
StateDuplicatorReturnType& result,
StateDuplicatorReturnType const& result,
storm::storage::SparseMatrix<typename MT::ValueType>& matrix,
storm::models::sparse::StateLabeling& stateLabeling,
std::unordered_map<std::string,
@ -249,7 +249,7 @@ namespace storm {
std::is_same<MT,storm::models::sparse::MarkovAutomaton<typename SparseModelType::ValueType>>::value,
MT>::type
createTransformedModel(MT const& originalModel,
StateDuplicatorReturnType& result,
StateDuplicatorReturnType const& result,
storm::storage::SparseMatrix<typename MT::ValueType>& matrix,
storm::models::sparse::StateLabeling& stateLabeling,
std::unordered_map<std::string,

211
src/transformer/SubsystemBuilder.h

@ -0,0 +1,211 @@
#ifndef STORM_TRANSFORMER_SUBSYSTEMBUILDER_H
#define STORM_TRANSFORMER_SUBSYSTEMBUILDER_H
#include <memory>
#include <boost/optional.hpp>
#include "src/models/sparse/StandardRewardModel.h"
#include "src/utility/constants.h"
#include "src/utility/graph.h"
#include "src/utility/macros.h"
#include "src/utility/vector.h"
#include "src/models/sparse/Dtmc.h"
#include "src/models/sparse/Mdp.h"
#include "src/models/sparse/Ctmc.h"
#include "src/models/sparse/MarkovAutomaton.h"
#include "src/exceptions/InvalidArgumentException.h"
#include "src/exceptions/InvalidStateException.h"
namespace storm {
namespace transformer {
/*
* Removes all states that are not part of the subsystem
*/
template <typename SparseModelType>
class SubsystemBuilder {
public:
struct SubsystemBuilderReturnType {
// The resulting model
std::shared_ptr<SparseModelType> model;
// Gives for each state in the resulting model the corresponding state in the original model and vice versa.
// If a state does not exist in the other model, an invalid index is given.
std::vector<uint_fast64_t> newToOldStateIndexMapping;
std::vector<uint_fast64_t> oldToNewStateIndexMapping;
// marks the actions of the original model that are still available in the subsystem
storm::storage::BitVector subsystemActions;
};
/*
* Removes all states that are not part of the subsystem
* all actions (i.e. rows) that lead outside of the subsystem are erased. Note that this might introduce deadlock states.
*
* @param originalModel The model to be duplicated
* @param subsystem The states that will be kept
*/
static SubsystemBuilderReturnType transform(SparseModelType const& originalModel, storm::storage::BitVector const& subsystem) {
STORM_LOG_DEBUG("Invoked subsystem builder on model with " << originalModel.getNumberOfStates() << " states.");
SubsystemBuilderReturnType result;
uint_fast64_t subsystemStateCount = subsystem.getNumberOfSetBits();
STORM_LOG_THROW(subsystemStateCount != 0, storm::exceptions::InvalidArgumentException, "Invoked SubsystemBuilder for an empty subsystem.");
if(subsystemStateCount == subsystem.size()) {
result.model = std::make_shared<SparseModelType>(originalModel);
result.newToOldStateIndexMapping = storm::utility::vector::buildVectorForRange(0, result.model->getNumberOfStates());
result.oldToNewStateIndexMapping = result.newToOldStateIndexMapping;
result.subsystemActions = storm::storage::BitVector(result.model->getTransitionMatrix().getRowCount(), true);
return result;
}
result.newToOldStateIndexMapping.reserve(subsystemStateCount);
result.oldToNewStateIndexMapping = std::vector<uint_fast64_t>(subsystem.size(), std::numeric_limits<uint_fast64_t>::max());
result.subsystemActions = storm::storage::BitVector(result.model->getTransitionMatrix().getRowCount(), false);
for(auto subsysState : subsystem) {
result.oldToNewStateIndexMapping[subsysState] = result.newToOldStateIndexMapping.size();
result.newToOldStateIndexMapping.push_back(subsysState);
for(uint_fast64_t row = originalModel.getTransitionMatrix().getRowGroupIndices()[subsysState]; row < originalModel.getTransitionMatrix().getRowGroupIndices()[subsysState+1]; ++row) {
result.subsystemActions.set(row, true);
for(auto const& entry : originalModel.getTransitionMatrix().getRow(row)) {
if(!subsystem.get(entry.getColumn())) {
result.subsystemActions.set(row, false);
break;
}
}
}
}
// Transform the ingedients of the model
storm::storage::SparseMatrix<typename SparseModelType::ValueType> matrix = transformMatrix(originalModel.getTransitionMatrix(), result);
storm::models::sparse::StateLabeling labeling(matrix.getRowGroupCount());
for(auto const& label : originalModel.getStateLabeling().getLabels()){
storm::storage::BitVector newBitVectorForLabel = transformStateBitVector(originalModel.getStateLabeling().getStates(label), subsystem);
labeling.addLabel(label, std::move(newBitVectorForLabel));
}
std::unordered_map<std::string, typename SparseModelType::RewardModelType> rewardModels;
for(auto const& rewardModel : originalModel.getRewardModels()){
rewardModels.insert(std::make_pair(rewardModel.first, transformRewardModel(rewardModel.second, originalModel.getTransitionMatrix().getRowGroupIndices(), subsystem, result)));
}
boost::optional<std::vector<storm::models::sparse::LabelSet>> choiceLabeling;
if(originalModel.hasChoiceLabeling()){
choiceLabeling = transformActionValueVector<storm::models::sparse::LabelSet>(originalModel.getChoiceLabeling(), result.subsystemActions);
}
result.model = std::make_shared<SparseModelType>(createTransformedModel(originalModel, subsystem, result, matrix, labeling, rewardModels, choiceLabeling));
STORM_LOG_DEBUG("Subsystem Builder is done. Resulting model has " << result.model->getNumberOfStates() << " states.");
return result;
}
private:
template<typename ValueType = typename SparseModelType::ValueType, typename RewardModelType = typename SparseModelType::RewardModelType>
static typename std::enable_if<std::is_same<RewardModelType, storm::models::sparse::StandardRewardModel<ValueType>>::value, RewardModelType>::type
transformRewardModel(RewardModelType const& originalRewardModel, std::vector<uint_fast64_t> const& originalRowGroupIndices, storm::storage::BitVector const& subsystem, SubsystemBuilderReturnType const& result) {
boost::optional<std::vector<ValueType>> stateRewardVector;
boost::optional<std::vector<ValueType>> stateActionRewardVector;
boost::optional<storm::storage::SparseMatrix<ValueType>> transitionRewardMatrix;
if(originalRewardModel.hasStateRewards()){
stateRewardVector = transformStateValueVector(originalRewardModel.getStateRewardVector(), subsystem);
}
if(originalRewardModel.hasStateActionRewards()){
stateActionRewardVector = transformActionValueVector(originalRewardModel.getStateActionRewardVector(), result.subsystemActions);
}
if(originalRewardModel.hasTransitionRewards()){
transitionRewardMatrix = transformMatrix(originalRewardModel.getTransitionRewardMatrix(), result);
}
return RewardModelType(std::move(stateRewardVector), std::move(stateActionRewardVector), std::move(transitionRewardMatrix));
}
template<typename ValueType = typename SparseModelType::ValueType>
static storm::storage::SparseMatrix<ValueType> transformMatrix(storm::storage::SparseMatrix<ValueType> const& originalMatrix, SubsystemBuilderReturnType const& result) {
// Build the builder
uint_fast64_t const numStates = result.newToOldStateIndexMapping.size();
uint_fast64_t const numRows = result.subsystemActions.getNumberOfSetBits();
uint_fast64_t numEntries = 0;
for(auto row : result.subsystemActions) {
numEntries += originalMatrix.getRow(row).getNumberOfEntries();
}
storm::storage::SparseMatrixBuilder<ValueType> builder(numRows, numStates, numEntries, true, !originalMatrix.hasTrivialRowGrouping(), originalMatrix.hasTrivialRowGrouping() ? 0 : numStates);
// Fill in the data
uint_fast64_t newRow = 0;
for(uint_fast64_t newState = 0; newState < numStates; ++newState){
if(!originalMatrix.hasTrivialRowGrouping()){
builder.newRowGroup(newRow);
}
uint_fast64_t oldState = result.newToOldStateIndexMapping[newState];
for (uint_fast64_t oldRow = result.subsystemActions.getNextSetIndex(originalMatrix.getRowGroupIndices()[oldState]); oldRow < originalMatrix.getRowGroupIndices()[oldState+1]; oldRow = result.subsystemActions.getNextSetIndex(oldRow+1)){
for(auto const& entry : originalMatrix.getRow(oldRow)){
builder.addNextValue(newRow, result.oldToNewStateIndexMapping[entry.getColumn()], entry.getValue());
}
++newRow;
}
}
return builder.build();
}
template<typename ValueType = typename SparseModelType::ValueType>
static std::vector<ValueType> transformActionValueVector(std::vector<ValueType> const& originalVector, storm::storage::BitVector const& subsystemActions) {
std::vector<ValueType> v;
v.reserve(subsystemActions.getNumberOfSetBits());
for(auto action : subsystemActions){
v.push_back(originalVector[action]);
}
return v;
}
template<typename ValueType = typename SparseModelType::ValueType>
static std::vector<ValueType> transformStateValueVector(std::vector<ValueType> const& originalVector, storm::storage::BitVector const& subsystem) {
std::vector<ValueType> v;
v.reserve(subsystem.getNumberOfSetBits());
for(auto state : subsystem){
v.push_back(originalVector[state]);
}
return v;
}
static storm::storage::BitVector transformStateBitVector(storm::storage::BitVector const& originalBitVector, storm::storage::BitVector const& subsystem) {
return originalBitVector % subsystem;
}
template<typename MT = SparseModelType>
static typename std::enable_if<
std::is_same<MT,storm::models::sparse::Dtmc<typename SparseModelType::ValueType>>::value ||
std::is_same<MT,storm::models::sparse::Mdp<typename SparseModelType::ValueType>>::value ||
std::is_same<MT,storm::models::sparse::Ctmc<typename SparseModelType::ValueType>>::value,
MT>::type
createTransformedModel(MT const& originalModel,
storm::storage::BitVector const& subsystem,
SubsystemBuilderReturnType const& result,
storm::storage::SparseMatrix<typename MT::ValueType>& matrix,
storm::models::sparse::StateLabeling& stateLabeling,
std::unordered_map<std::string,
typename MT::RewardModelType>& rewardModels,
boost::optional<std::vector<typename storm::models::sparse::LabelSet>>& choiceLabeling ) {
return MT(std::move(matrix), std::move(stateLabeling), std::move(rewardModels), std::move(choiceLabeling));
}
template<typename MT = SparseModelType>
static typename std::enable_if<
std::is_same<MT,storm::models::sparse::MarkovAutomaton<typename SparseModelType::ValueType>>::value,
MT>::type
createTransformedModel(MT const& originalModel,
storm::storage::BitVector const& subsystem,
SubsystemBuilderReturnType const& result,
storm::storage::SparseMatrix<typename MT::ValueType>& matrix,
storm::models::sparse::StateLabeling& stateLabeling,
std::unordered_map<std::string,
typename MT::RewardModelType>& rewardModels,
boost::optional<std::vector<typename storm::models::sparse::LabelSet>>& choiceLabeling ) {
storm::storage::BitVector markovianStates = transformStateBitVector(originalModel.getMarkovianStates(), subsystem);
std::vector<typename MT::ValueType> exitRates = transformStateValueVector(originalModel.getExitRates(), subsystem);
return MT(std::move(matrix), std::move(stateLabeling), std::move(markovianStates), std::move(exitRates), true, std::move(rewardModels), std::move(choiceLabeling));
}
};
}
}
#endif // STORM_TRANSFORMER_SUBSYSTEMBUILDER_H
Loading…
Cancel
Save