Browse Source
split weight vector checker into one for MDPs and one for MAs
split weight vector checker into one for MDPs and one for MAs
Former-commit-id: 142a151f3c
tempestpy_adaptions
TimQu
9 years ago
10 changed files with 333 additions and 108 deletions
-
4src/modelchecker/multiobjective/SparseMaMultiObjectiveModelChecker.cpp
-
4src/modelchecker/multiobjective/SparseMdpMultiObjectiveModelChecker.cpp
-
88src/modelchecker/multiobjective/helper/SparseMaMultiObjectiveWeightVectorChecker.cpp
-
47src/modelchecker/multiobjective/helper/SparseMaMultiObjectiveWeightVectorChecker.h
-
85src/modelchecker/multiobjective/helper/SparseMdpMultiObjectiveWeightVectorChecker.cpp
-
51src/modelchecker/multiobjective/helper/SparseMdpMultiObjectiveWeightVectorChecker.h
-
27src/modelchecker/multiobjective/helper/SparseMultiObjectiveHelper.cpp
-
11src/modelchecker/multiobjective/helper/SparseMultiObjectiveHelper.h
-
108src/modelchecker/multiobjective/helper/SparseMultiObjectiveWeightVectorChecker.cpp
-
16src/modelchecker/multiobjective/helper/SparseMultiObjectiveWeightVectorChecker.h
@ -0,0 +1,88 @@ |
|||
#include "src/modelchecker/multiobjective/helper/SparseMaMultiObjectiveWeightVectorChecker.h"
|
|||
|
|||
#include "src/adapters/CarlAdapter.h"
|
|||
#include "src/models/sparse/MarkovAutomaton.h"
|
|||
#include "src/models/sparse/StandardRewardModel.h"
|
|||
#include "src/utility/macros.h"
|
|||
#include "src/utility/vector.h"
|
|||
|
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace helper { |
|||
|
|||
template <class SparseMaModelType> |
|||
SparseMaMultiObjectiveWeightVectorChecker<SparseMaModelType>::SparseMaMultiObjectiveWeightVectorChecker(PreprocessorData const& data) : SparseMultiObjectiveWeightVectorChecker<SparseMaModelType>(data) { |
|||
// Intentionally left empty
|
|||
} |
|||
|
|||
template <class SparseMaModelType> |
|||
std::vector<typename SparseMaMultiObjectiveWeightVectorChecker<SparseMaModelType>::ValueType> SparseMaMultiObjectiveWeightVectorChecker<SparseMaModelType>::getObjectiveRewardAsDiscreteActionRewards(uint_fast64_t objectiveIndex) const { |
|||
// Assert that the state and transition rewards have already been removed in prerpocessing
|
|||
STORM_LOG_ASSERT(!this->data.preprocessedModel.getRewardModel(this->data.objectives[objectiveIndex].rewardModelName).hasStateRewards(), "Reward model has state rewards which is not expected."); |
|||
STORM_LOG_ASSERT(!this->data.preprocessedModel.getRewardModel(this->data.objectives[objectiveIndex].rewardModelName).hasTransitionRewards(), "Reward model has transition rewards which is not expected."); |
|||
return this->data.preprocessedModel.getRewardModel(this->data.objectives[objectiveIndex].rewardModelName).getStateActionRewardVector(); |
|||
} |
|||
|
|||
template <class SparseMaModelType> |
|||
void SparseMaMultiObjectiveWeightVectorChecker<SparseMaModelType>::boundedPhase(std::vector<ValueType> const& weightVector, std::vector<ValueType>& weightedRewardVector) { |
|||
STORM_LOG_ERROR("BOUNDED OBJECTIVES FOR MARKOV AUTOMATA NOT YET IMPLEMENTED"); |
|||
/*
|
|||
// Allocate some memory so this does not need to happen for each time epoch
|
|||
std::vector<uint_fast64_t> optimalChoicesInCurrentEpoch(this->data.preprocessedModel.getNumberOfStates()); |
|||
std::vector<ValueType> choiceValues(weightedRewardVector.size()); |
|||
std::vector<ValueType> temporaryResult(this->data.preprocessedModel.getNumberOfStates()); |
|||
// Get for each occurring timeBound the indices of the objectives with that bound.
|
|||
std::map<uint_fast64_t, storm::storage::BitVector, std::greater<uint_fast64_t>> timeBounds; |
|||
storm::storage::BitVector boundedObjectives = ~this->unboundedObjectives; |
|||
for(uint_fast64_t objIndex : boundedObjectives) { |
|||
uint_fast64_t timeBound = boost::get<uint_fast64_t>(this->data.objectives[objIndex].timeBounds.get()); |
|||
auto timeBoundIt = timeBounds.insert(std::make_pair(timeBound, storm::storage::BitVector(this->data.objectives.size(), false))).first; |
|||
timeBoundIt->second.set(objIndex); |
|||
} |
|||
storm::storage::BitVector objectivesAtCurrentEpoch = this->unboundedObjectives; |
|||
auto timeBoundIt = timeBounds.begin(); |
|||
for(uint_fast64_t currentEpoch = timeBoundIt->first; currentEpoch > 0; --currentEpoch) { |
|||
if(timeBoundIt != timeBounds.end() && currentEpoch == timeBoundIt->first) { |
|||
objectivesAtCurrentEpoch |= timeBoundIt->second; |
|||
for(auto objIndex : timeBoundIt->second) { |
|||
storm::utility::vector::addScaledVector(weightedRewardVector, getObjectiveRewardAsDiscreteActionRewards(objIndex), weightVector[objIndex]); |
|||
} |
|||
++timeBoundIt; |
|||
} |
|||
|
|||
// Get values and scheduler for weighted sum of objectives
|
|||
this->data.preprocessedModel.getTransitionMatrix().multiplyWithVector(this->weightedResult, choiceValues); |
|||
storm::utility::vector::addVectors(choiceValues, weightedRewardVector, choiceValues); |
|||
storm::utility::vector::reduceVectorMax(choiceValues, this->weightedResult, this->data.preprocessedModel.getTransitionMatrix().getRowGroupIndices(), &optimalChoicesInCurrentEpoch); |
|||
|
|||
// get values for individual objectives
|
|||
// TODO we could compute the result for one of the objectives from the weighted result, the given weight vector, and the remaining objective results.
|
|||
for(auto objIndex : objectivesAtCurrentEpoch) { |
|||
std::vector<ValueType>& objectiveResult = this->objectiveResults[objIndex]; |
|||
std::vector<ValueType> objectiveRewards = getObjectiveRewardAsDiscreteActionRewards(objIndex); |
|||
auto rowGroupIndexIt = this->data.preprocessedModel.getTransitionMatrix().getRowGroupIndices().begin(); |
|||
auto optimalChoiceIt = optimalChoicesInCurrentEpoch.begin(); |
|||
for(ValueType& stateValue : temporaryResult){ |
|||
uint_fast64_t row = (*rowGroupIndexIt) + (*optimalChoiceIt); |
|||
++rowGroupIndexIt; |
|||
++optimalChoiceIt; |
|||
stateValue = objectiveRewards[row]; |
|||
for(auto const& entry : this->data.preprocessedModel.getTransitionMatrix().getRow(row)) { |
|||
stateValue += entry.getValue() * objectiveResult[entry.getColumn()]; |
|||
} |
|||
} |
|||
objectiveResult.swap(temporaryResult); |
|||
} |
|||
} |
|||
*/ |
|||
} |
|||
|
|||
template class SparseMaMultiObjectiveWeightVectorChecker<storm::models::sparse::MarkovAutomaton<double>>; |
|||
#ifdef STORM_HAVE_CARL
|
|||
template class SparseMaMultiObjectiveWeightVectorChecker<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>>; |
|||
#endif
|
|||
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
#ifndef STORM_MODELCHECKER_MULTIOBJECTIVE_HELPER_SPARSEMAMULTIOBJECTIVEWEIGHTVECTORCHECKER_H_ |
|||
#define STORM_MODELCHECKER_MULTIOBJECTIVE_HELPER_SPARSEMAMULTIOBJECTIVEWEIGHTVECTORCHECKER_H_ |
|||
|
|||
#include <vector> |
|||
|
|||
#include "src/modelchecker/multiobjective/helper/SparseMultiObjectiveWeightVectorChecker.h" |
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace helper { |
|||
|
|||
/*! |
|||
* Helper Class that takes preprocessed multi objective data and a weight vector and ... |
|||
* - computes the maximal expected reward w.r.t. the weighted sum of the rewards of the individual objectives |
|||
* - extracts the scheduler that induces this maximum |
|||
* - computes for each objective the value induced by this scheduler |
|||
*/ |
|||
template <class SparseMaModelType> |
|||
class SparseMaMultiObjectiveWeightVectorChecker : public SparseMultiObjectiveWeightVectorChecker<SparseMaModelType> { |
|||
public: |
|||
typedef typename SparseMaModelType::ValueType ValueType; |
|||
typedef SparseMultiObjectivePreprocessorData<SparseMaModelType> PreprocessorData; |
|||
|
|||
SparseMaMultiObjectiveWeightVectorChecker(PreprocessorData const& data); |
|||
|
|||
private: |
|||
|
|||
|
|||
/*! |
|||
* Retrieves the rewards for the objective with the given index as state action reward vector. |
|||
*/ |
|||
virtual std::vector<ValueType> getObjectiveRewardAsDiscreteActionRewards(uint_fast64_t objectiveIndex) const override; |
|||
|
|||
/*! |
|||
* |
|||
* @param weightVector the weight vector of the current check |
|||
* @param weightedRewardVector the weighted rewards (initially only considering the unbounded objectives, will be extended to all objectives) |
|||
*/ |
|||
virtual void boundedPhase(std::vector<ValueType> const& weightVector, std::vector<ValueType>& weightedRewardVector) override; |
|||
|
|||
}; |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_MODELCHECKER_MULTIOBJECTIVE_HELPER_SPARSEMAMULTIOBJECTIVEWEIGHTEDVECTORCHECKER_H_ */ |
@ -0,0 +1,85 @@ |
|||
#include "src/modelchecker/multiobjective/helper/SparseMdpMultiObjectiveWeightVectorChecker.h"
|
|||
|
|||
#include "src/adapters/CarlAdapter.h"
|
|||
#include "src/models/sparse/Mdp.h"
|
|||
#include "src/models/sparse/StandardRewardModel.h"
|
|||
#include "src/utility/macros.h"
|
|||
#include "src/utility/vector.h"
|
|||
|
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace helper { |
|||
|
|||
template <class SparseMdpModelType> |
|||
SparseMdpMultiObjectiveWeightVectorChecker<SparseMdpModelType>::SparseMdpMultiObjectiveWeightVectorChecker(PreprocessorData const& data) : SparseMultiObjectiveWeightVectorChecker<SparseMdpModelType>(data) { |
|||
// Intentionally left empty
|
|||
} |
|||
|
|||
template <class SparseMdpModelType> |
|||
std::vector<typename SparseMdpMultiObjectiveWeightVectorChecker<SparseMdpModelType>::ValueType> SparseMdpMultiObjectiveWeightVectorChecker<SparseMdpModelType>::getObjectiveRewardAsDiscreteActionRewards(uint_fast64_t objectiveIndex) const { |
|||
// Assert that the state and transition rewards have already been removed in prerpocessing
|
|||
STORM_LOG_ASSERT(!this->data.preprocessedModel.getRewardModel(this->data.objectives[objectiveIndex].rewardModelName).hasStateRewards(), "Reward model has state rewards which is not expected."); |
|||
STORM_LOG_ASSERT(!this->data.preprocessedModel.getRewardModel(this->data.objectives[objectiveIndex].rewardModelName).hasTransitionRewards(), "Reward model has transition rewards which is not expected."); |
|||
return this->data.preprocessedModel.getRewardModel(this->data.objectives[objectiveIndex].rewardModelName).getStateActionRewardVector(); |
|||
} |
|||
|
|||
template <class SparseMdpModelType> |
|||
void SparseMdpMultiObjectiveWeightVectorChecker<SparseMdpModelType>::boundedPhase(std::vector<ValueType> const& weightVector, std::vector<ValueType>& weightedRewardVector) { |
|||
// Allocate some memory so this does not need to happen for each time epoch
|
|||
std::vector<uint_fast64_t> optimalChoicesInCurrentEpoch(this->data.preprocessedModel.getNumberOfStates()); |
|||
std::vector<ValueType> choiceValues(weightedRewardVector.size()); |
|||
std::vector<ValueType> temporaryResult(this->data.preprocessedModel.getNumberOfStates()); |
|||
// Get for each occurring timeBound the indices of the objectives with that bound.
|
|||
std::map<uint_fast64_t, storm::storage::BitVector, std::greater<uint_fast64_t>> timeBounds; |
|||
storm::storage::BitVector boundedObjectives = ~this->unboundedObjectives; |
|||
for(uint_fast64_t objIndex : boundedObjectives) { |
|||
uint_fast64_t timeBound = boost::get<uint_fast64_t>(this->data.objectives[objIndex].timeBounds.get()); |
|||
auto timeBoundIt = timeBounds.insert(std::make_pair(timeBound, storm::storage::BitVector(this->data.objectives.size(), false))).first; |
|||
timeBoundIt->second.set(objIndex); |
|||
} |
|||
storm::storage::BitVector objectivesAtCurrentEpoch = this->unboundedObjectives; |
|||
auto timeBoundIt = timeBounds.begin(); |
|||
for(uint_fast64_t currentEpoch = timeBoundIt->first; currentEpoch > 0; --currentEpoch) { |
|||
if(timeBoundIt != timeBounds.end() && currentEpoch == timeBoundIt->first) { |
|||
objectivesAtCurrentEpoch |= timeBoundIt->second; |
|||
for(auto objIndex : timeBoundIt->second) { |
|||
storm::utility::vector::addScaledVector(weightedRewardVector, getObjectiveRewardAsDiscreteActionRewards(objIndex), weightVector[objIndex]); |
|||
} |
|||
++timeBoundIt; |
|||
} |
|||
|
|||
// Get values and scheduler for weighted sum of objectives
|
|||
this->data.preprocessedModel.getTransitionMatrix().multiplyWithVector(this->weightedResult, choiceValues); |
|||
storm::utility::vector::addVectors(choiceValues, weightedRewardVector, choiceValues); |
|||
storm::utility::vector::reduceVectorMax(choiceValues, this->weightedResult, this->data.preprocessedModel.getTransitionMatrix().getRowGroupIndices(), &optimalChoicesInCurrentEpoch); |
|||
|
|||
// get values for individual objectives
|
|||
// TODO we could compute the result for one of the objectives from the weighted result, the given weight vector, and the remaining objective results.
|
|||
for(auto objIndex : objectivesAtCurrentEpoch) { |
|||
std::vector<ValueType>& objectiveResult = this->objectiveResults[objIndex]; |
|||
std::vector<ValueType> objectiveRewards = getObjectiveRewardAsDiscreteActionRewards(objIndex); |
|||
auto rowGroupIndexIt = this->data.preprocessedModel.getTransitionMatrix().getRowGroupIndices().begin(); |
|||
auto optimalChoiceIt = optimalChoicesInCurrentEpoch.begin(); |
|||
for(ValueType& stateValue : temporaryResult){ |
|||
uint_fast64_t row = (*rowGroupIndexIt) + (*optimalChoiceIt); |
|||
++rowGroupIndexIt; |
|||
++optimalChoiceIt; |
|||
stateValue = objectiveRewards[row]; |
|||
for(auto const& entry : this->data.preprocessedModel.getTransitionMatrix().getRow(row)) { |
|||
stateValue += entry.getValue() * objectiveResult[entry.getColumn()]; |
|||
} |
|||
} |
|||
objectiveResult.swap(temporaryResult); |
|||
} |
|||
} |
|||
} |
|||
|
|||
template class SparseMdpMultiObjectiveWeightVectorChecker<storm::models::sparse::Mdp<double>>; |
|||
#ifdef STORM_HAVE_CARL
|
|||
template class SparseMdpMultiObjectiveWeightVectorChecker<storm::models::sparse::Mdp<storm::RationalNumber>>; |
|||
#endif
|
|||
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,51 @@ |
|||
#ifndef STORM_MODELCHECKER_MULTIOBJECTIVE_HELPER_SPARSEMDPMULTIOBJECTIVEWEIGHTVECTORCHECKER_H_ |
|||
#define STORM_MODELCHECKER_MULTIOBJECTIVE_HELPER_SPARSEMDPMULTIOBJECTIVEWEIGHTVECTORCHECKER_H_ |
|||
|
|||
#include <vector> |
|||
|
|||
#include "src/modelchecker/multiobjective/helper/SparseMultiObjectiveWeightVectorChecker.h" |
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace helper { |
|||
|
|||
/*! |
|||
* Helper Class that takes preprocessed multi objective data and a weight vector and ... |
|||
* - computes the maximal expected reward w.r.t. the weighted sum of the rewards of the individual objectives |
|||
* - extracts the scheduler that induces this maximum |
|||
* - computes for each objective the value induced by this scheduler |
|||
*/ |
|||
template <class SparseMdpModelType> |
|||
class SparseMdpMultiObjectiveWeightVectorChecker : public SparseMultiObjectiveWeightVectorChecker<SparseMdpModelType> { |
|||
public: |
|||
typedef typename SparseMdpModelType::ValueType ValueType; |
|||
typedef SparseMultiObjectivePreprocessorData<SparseMdpModelType> PreprocessorData; |
|||
|
|||
SparseMdpMultiObjectiveWeightVectorChecker(PreprocessorData const& data); |
|||
|
|||
private: |
|||
|
|||
|
|||
/*! |
|||
* Retrieves the rewards for the objective with the given index as state action reward vector. |
|||
*/ |
|||
virtual std::vector<ValueType> getObjectiveRewardAsDiscreteActionRewards(uint_fast64_t objectiveIndex) const override; |
|||
|
|||
/*! |
|||
* For each time epoch (starting with the maximal stepBound occurring in the objectives), this method |
|||
* - determines the objectives that are relevant in the current time epoch |
|||
* - determines the maximizing scheduler for the weighted reward vector of these objectives |
|||
* - computes the values of these objectives w.r.t. this scheduler |
|||
* |
|||
* @param weightVector the weight vector of the current check |
|||
* @param weightedRewardVector the weighted rewards (initially only considering the unbounded objectives, will be extended to all objectives) |
|||
*/ |
|||
virtual void boundedPhase(std::vector<ValueType> const& weightVector, std::vector<ValueType>& weightedRewardVector) override; |
|||
|
|||
}; |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_MODELCHECKER_MULTIOBJECTIVE_HELPER_SPARSEMDPMULTIOBJECTIVEWEIGHTEDVECTORCHECKER_H_ */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue