Browse Source
Merge pull request 'Feature: Implementing Sound Versions of Reachability and LRA for SMGs' (#60) from sound_game_vi into tempestpy_adaptions
Merge pull request 'Feature: Implementing Sound Versions of Reachability and LRA for SMGs' (#60) from sound_game_vi into tempestpy_adaptions
Reviewed-on: https://git.pranger.xyz/TEMPEST/tempest-devel/pulls/60main
11 changed files with 1409 additions and 8 deletions
-
32resources/examples/testfiles/smg/example_smg.nm
-
311src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.cpp
-
108src/storm/modelchecker/helper/infinitehorizon/internal/SparseSmgLraHelper.h
-
44src/storm/modelchecker/rpatl/SparseSmgRpatlModelChecker.cpp
-
99src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.cpp
-
3src/storm/modelchecker/rpatl/helper/SparseSmgRpatlHelper.h
-
371src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.cpp
-
136src/storm/modelchecker/rpatl/helper/internal/SoundGameViHelper.h
-
16src/storm/storage/MaximalEndComponent.cpp
-
11src/storm/storage/MaximalEndComponent.h
-
286src/test/storm/modelchecker/rpatl/smg/SmgRpatlModelCheckerTest.cpp
@ -0,0 +1,32 @@ |
|||||
|
// taken from Julia Eisentraut "Value iteration for simple stochastic games: Stopping criterion |
||||
|
// and learning algorithm" - Fig. 1 |
||||
|
|
||||
|
|
||||
|
smg |
||||
|
|
||||
|
const double p = 2/3; |
||||
|
|
||||
|
player maxP |
||||
|
[q_action1], [q_action2] |
||||
|
endplayer |
||||
|
|
||||
|
player minP |
||||
|
[p_action1] |
||||
|
endplayer |
||||
|
|
||||
|
player sinkstates |
||||
|
state_space |
||||
|
endplayer |
||||
|
|
||||
|
|
||||
|
module state_space |
||||
|
s : [0..3]; |
||||
|
|
||||
|
[p_action1] s=0 -> (s'=1); |
||||
|
|
||||
|
[q_action1] s=1 -> (s'=0); |
||||
|
[q_action2] s=1 -> (1-p) : (s'=1) + (p/2) : (s'=2) + (p/2) : (s'=3); |
||||
|
|
||||
|
[] s=2 -> true; |
||||
|
[] s=3 -> true; |
||||
|
endmodule |
@ -0,0 +1,311 @@ |
|||||
|
#include "SparseSmgLraHelper.h"
|
||||
|
|
||||
|
#include "storm/storage/MaximalEndComponent.h"
|
||||
|
#include "storm/storage/StronglyConnectedComponent.h"
|
||||
|
|
||||
|
#include "storm/utility/graph.h"
|
||||
|
#include "storm/utility/vector.h"
|
||||
|
#include "storm/utility/macros.h"
|
||||
|
#include "storm/utility/SignalHandler.h"
|
||||
|
|
||||
|
#include "storm/environment/solver/SolverEnvironment.h"
|
||||
|
#include "storm/environment/solver/LongRunAverageSolverEnvironment.h"
|
||||
|
#include "storm/environment/solver/MinMaxSolverEnvironment.h"
|
||||
|
#include "storm/environment/solver/MultiplierEnvironment.h"
|
||||
|
#include "storm/environment/solver/GameSolverEnvironment.h"
|
||||
|
|
||||
|
#include "modelchecker/helper/infinitehorizon/SparseNondeterministicInfiniteHorizonHelper.h"
|
||||
|
#include "storm/exceptions/UnmetRequirementException.h"
|
||||
|
|
||||
|
#define SOLVE_MDP 50
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace modelchecker { |
||||
|
namespace helper { |
||||
|
namespace internal { |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
SparseSmgLraHelper<ValueType>::SparseSmgLraHelper(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const statesOfCoalition) : _transitionMatrix(transitionMatrix), _statesOfCoalition(statesOfCoalition) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> SparseSmgLraHelper<ValueType>::computeLongRunAverageRewardsSound(Environment const& env, storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel) { |
||||
|
std::vector<ValueType> result; |
||||
|
std::vector<ValueType> stateRewardsGetter = std::vector<ValueType>(_transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>()); |
||||
|
if (rewardModel.hasStateRewards()) { |
||||
|
stateRewardsGetter = rewardModel.getStateRewardVector(); |
||||
|
} |
||||
|
ValueGetter actionRewardsGetter; |
||||
|
if (rewardModel.hasStateActionRewards() || rewardModel.hasTransitionRewards()) { |
||||
|
if (rewardModel.hasTransitionRewards()) { |
||||
|
actionRewardsGetter = [&] (uint64_t globalChoiceIndex) { return rewardModel.getStateActionAndTransitionReward(globalChoiceIndex, this->_transitionMatrix); }; |
||||
|
} else { |
||||
|
actionRewardsGetter = [&] (uint64_t globalChoiceIndex) { return rewardModel.getStateActionReward(globalChoiceIndex); }; |
||||
|
} |
||||
|
} else { |
||||
|
actionRewardsGetter = [] (uint64_t) { return storm::utility::zero<ValueType>(); }; |
||||
|
} |
||||
|
_b = getBVector(stateRewardsGetter, actionRewardsGetter); |
||||
|
|
||||
|
// If requested, allocate memory for the choices made
|
||||
|
if (this->_produceScheduler) { |
||||
|
if (!this->_producedOptimalChoices.is_initialized()) { |
||||
|
_producedOptimalChoices.emplace(); |
||||
|
} |
||||
|
_producedOptimalChoices->resize(_transitionMatrix.getRowGroupCount()); |
||||
|
} |
||||
|
|
||||
|
prepareMultiplier(env, rewardModel); |
||||
|
performValueIteration(env, rewardModel, _b, result); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> SparseSmgLraHelper<ValueType>::getBVector(std::vector<ValueType> const& stateRewardsGetter, ValueGetter const& actionRewardsGetter) { |
||||
|
std::vector<ValueType> b = std::vector<ValueType>(_transitionMatrix.getRowCount()); |
||||
|
size_t globalChoiceCount = 0; |
||||
|
auto rowGroupIndices = _transitionMatrix.getRowGroupIndices(); |
||||
|
for (size_t state = 0; state < _transitionMatrix.getRowGroupCount(); state++) { |
||||
|
size_t rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; |
||||
|
for (size_t choice = 0; choice < rowGroupSize; choice++, globalChoiceCount++) |
||||
|
{ |
||||
|
b[globalChoiceCount] = stateRewardsGetter[state] + actionRewardsGetter(globalChoiceCount); |
||||
|
} |
||||
|
} |
||||
|
return b; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SparseSmgLraHelper<ValueType>::performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel, std::vector<ValueType> const& b, std::vector<ValueType>& result) |
||||
|
{ |
||||
|
std::vector<uint64_t> choicesForStrategies = std::vector<uint64_t>(_transitionMatrix.getRowGroupCount(), 0); |
||||
|
auto precision = storm::utility::convertNumber<ValueType>(env.solver().lra().getPrecision()); |
||||
|
|
||||
|
Environment envMinMax = env; |
||||
|
envMinMax.solver().lra().setPrecision(precision / storm::utility::convertNumber<storm::RationalNumber>(2)); |
||||
|
do |
||||
|
{ |
||||
|
size_t iteration_count = 0; |
||||
|
// Convergent recommender procedure
|
||||
|
|
||||
|
_multiplier->multiplyAndReduce(env, _optimizationDirection, xNew(), &b, xNew(), &choicesForStrategies, &_statesOfCoalition); |
||||
|
|
||||
|
if (iteration_count % SOLVE_MDP == 0) { // only every 50th iteration
|
||||
|
storm::storage::BitVector fixedMaxStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MaxStrategy); |
||||
|
storm::storage::BitVector fixedMinStrat = getStrategyFixedBitVec(choicesForStrategies, MinMaxStrategy::MinStrategy); |
||||
|
|
||||
|
// compute bounds
|
||||
|
if (fixedMaxStrat != _fixedMaxStrat) { |
||||
|
storm::storage::SparseMatrix<ValueType> restrictedMaxMatrix = _transitionMatrix.restrictRows(fixedMaxStrat); |
||||
|
|
||||
|
storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper<ValueType> MaxSolver(restrictedMaxMatrix); |
||||
|
|
||||
|
MaxSolver.setOptimizationDirection(OptimizationDirection::Minimize); |
||||
|
MaxSolver.setProduceChoiceValues(false); |
||||
|
_resultForMax = MaxSolver.computeLongRunAverageRewards(envMinMax, rewardModel); |
||||
|
_fixedMaxStrat = fixedMaxStrat; |
||||
|
|
||||
|
for (size_t i = 0; i < xNewL().size(); i++) { |
||||
|
xNewL()[i] = std::max(xNewL()[i], _resultForMax[i]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (fixedMinStrat != _fixedMinStrat) { |
||||
|
storm::storage::SparseMatrix<ValueType> restrictedMinMatrix = _transitionMatrix.restrictRows(fixedMinStrat); |
||||
|
|
||||
|
storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper<ValueType> MinSolver(restrictedMinMatrix); |
||||
|
MinSolver.setOptimizationDirection(OptimizationDirection::Maximize); |
||||
|
MinSolver.setProduceChoiceValues(false); |
||||
|
_resultForMin = MinSolver.computeLongRunAverageRewards(envMinMax, rewardModel); |
||||
|
_fixedMinStrat = fixedMinStrat; |
||||
|
|
||||
|
for (size_t i = 0; i < xNewU().size(); i++) { |
||||
|
xNewU()[i] = std::min(xNewU()[i], _resultForMin[i]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} while (!checkConvergence(precision)); |
||||
|
|
||||
|
if (_produceScheduler) { |
||||
|
_multiplier->multiplyAndReduce(env, _optimizationDirection, xNew(), &b, xNew(), &_producedOptimalChoices.get(), &_statesOfCoalition); |
||||
|
} |
||||
|
|
||||
|
if (_produceChoiceValues) { |
||||
|
if (!this->_choiceValues.is_initialized()) { |
||||
|
this->_choiceValues.emplace(); |
||||
|
} |
||||
|
this->_choiceValues->resize(this->_transitionMatrix.getRowCount()); |
||||
|
_choiceValues = calcChoiceValues(env, rewardModel); |
||||
|
} |
||||
|
result = xNewL(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template <typename ValueType> |
||||
|
storm::storage::BitVector SparseSmgLraHelper<ValueType>::getStrategyFixedBitVec(std::vector<uint64_t> const& choices, MinMaxStrategy strategy) { |
||||
|
storm::storage::BitVector restrictBy(_transitionMatrix.getRowCount(), true); |
||||
|
auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); |
||||
|
|
||||
|
for(uint state = 0; state < _transitionMatrix.getRowGroupCount(); state++) { |
||||
|
if ((_minimizerStates[state] && strategy == MinMaxStrategy::MaxStrategy) || (!_minimizerStates[state] && strategy == MinMaxStrategy::MinStrategy)) |
||||
|
continue; |
||||
|
|
||||
|
uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; |
||||
|
for(uint rowGroupIndex = 0; rowGroupIndex < rowGroupSize; rowGroupIndex++) { |
||||
|
if ((rowGroupIndex) != choices[state]) { |
||||
|
restrictBy.set(rowGroupIndex + rowGroupIndices[state], false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return restrictBy; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> SparseSmgLraHelper<ValueType>::calcChoiceValues(Environment const& env, storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel) { |
||||
|
std::vector<ValueType> choiceValues(_transitionMatrix.getRowCount()); |
||||
|
_multiplier->multiply(env, xNewL(), nullptr, choiceValues); |
||||
|
|
||||
|
return choiceValues; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> SparseSmgLraHelper<ValueType>::getChoiceValues() const { |
||||
|
STORM_LOG_ASSERT(_produceChoiceValues, "Trying to get the computed choice values although this was not requested."); |
||||
|
STORM_LOG_ASSERT(this->_choiceValues.is_initialized(), "Trying to get the computed choice values but none were available. Was there a computation call before?"); |
||||
|
return this->_choiceValues.get(); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
storm::storage::Scheduler<ValueType> SparseSmgLraHelper<ValueType>::extractScheduler() const{ |
||||
|
auto const& optimalChoices = getProducedOptimalChoices(); |
||||
|
storm::storage::Scheduler<ValueType> scheduler(optimalChoices.size()); |
||||
|
|
||||
|
for (uint64_t state = 0; state < optimalChoices.size(); ++state) { |
||||
|
scheduler.setChoice(optimalChoices[state], state); |
||||
|
} |
||||
|
|
||||
|
return scheduler; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<uint64_t> const& SparseSmgLraHelper<ValueType>::getProducedOptimalChoices() const { |
||||
|
STORM_LOG_ASSERT(_produceScheduler, "Trying to get the produced optimal choices although no scheduler was requested."); |
||||
|
STORM_LOG_ASSERT(this->_producedOptimalChoices.is_initialized(), "Trying to get the produced optimal choices but none were available. Was there a computation call before?"); |
||||
|
|
||||
|
return this->_producedOptimalChoices.get(); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SparseSmgLraHelper<ValueType>::prepareMultiplier(const Environment& env, storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel) |
||||
|
{ |
||||
|
_multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, _transitionMatrix); |
||||
|
if (_statesOfCoalition.size()) { |
||||
|
_minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; |
||||
|
} |
||||
|
else { |
||||
|
_minimizerStates = storm::storage::BitVector(_transitionMatrix.getRowGroupCount(), _optimizationDirection == OptimizationDirection::Minimize); |
||||
|
} |
||||
|
|
||||
|
_xL = std::vector<ValueType>(_transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>()); |
||||
|
_x = _xL; |
||||
|
|
||||
|
_fixedMaxStrat = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); |
||||
|
_fixedMinStrat = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); |
||||
|
|
||||
|
_resultForMin = std::vector<ValueType>(_transitionMatrix.getRowGroupCount()); |
||||
|
_resultForMax = std::vector<ValueType>(_transitionMatrix.getRowGroupCount()); |
||||
|
|
||||
|
_xU = std::vector<ValueType>(_transitionMatrix.getRowGroupCount(), std::numeric_limits<ValueType>::infinity()); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
bool SparseSmgLraHelper<ValueType>::checkConvergence(ValueType threshold) const { |
||||
|
STORM_LOG_ASSERT(_multiplier, "tried to check for convergence without doing an iteration first."); |
||||
|
// Now check whether the currently produced results are precise enough
|
||||
|
STORM_LOG_ASSERT(threshold > storm::utility::zero<ValueType>(), "Did not expect a non-positive threshold."); |
||||
|
auto x1It = xNewL().begin(); |
||||
|
auto x1Ite = xNewL().end(); |
||||
|
auto x2It = xNewU().begin(); |
||||
|
for (; x1It != x1Ite; x1It++, x2It++) { |
||||
|
ValueType diff = (*x2It - *x1It); |
||||
|
if (diff > threshold) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType>& SparseSmgLraHelper<ValueType>::xNewL() { |
||||
|
return _xL; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> const& SparseSmgLraHelper<ValueType>::xNewL() const { |
||||
|
return _xL; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType>& SparseSmgLraHelper<ValueType>::xNewU() { |
||||
|
return _xU; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> const& SparseSmgLraHelper<ValueType>::xNewU() const { |
||||
|
return _xU; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType>& SparseSmgLraHelper<ValueType>::xNew() { |
||||
|
return _x; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> const& SparseSmgLraHelper<ValueType>::xNew() const { |
||||
|
return _x; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SparseSmgLraHelper<ValueType>::setRelevantStates(storm::storage::BitVector relevantStates){ |
||||
|
_relevantStates = relevantStates; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SparseSmgLraHelper<ValueType>::setValueThreshold(storm::logic::ComparisonType const& comparisonType, const ValueType &thresholdValue) { |
||||
|
_valueThreshold = std::make_pair(comparisonType, thresholdValue); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SparseSmgLraHelper<ValueType>::setOptimizationDirection(storm::solver::OptimizationDirection const& direction) { |
||||
|
_optimizationDirection = direction; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SparseSmgLraHelper<ValueType>::setProduceScheduler(bool value) { |
||||
|
_produceScheduler = value; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SparseSmgLraHelper<ValueType>::setProduceChoiceValues(bool value) { |
||||
|
_produceChoiceValues = value; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SparseSmgLraHelper<ValueType>::setQualitative(bool value) { |
||||
|
_isQualitativeSet = value; |
||||
|
} |
||||
|
|
||||
|
template class SparseSmgLraHelper<double>; |
||||
|
#ifdef STORM_HAVE_CARL
|
||||
|
template class SparseSmgLraHelper<storm::RationalNumber>; |
||||
|
#endif
|
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1,108 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "storm/storage/SparseMatrix.h" |
||||
|
#include "storm/storage/BitVector.h" |
||||
|
#include "storm/solver/LinearEquationSolver.h" |
||||
|
#include "storm/solver/MinMaxLinearEquationSolver.h" |
||||
|
#include "storm/solver/Multiplier.h" |
||||
|
#include "storm/logic/ComparisonType.h" |
||||
|
|
||||
|
|
||||
|
namespace storm { |
||||
|
class Environment; |
||||
|
|
||||
|
|
||||
|
namespace modelchecker { |
||||
|
namespace helper { |
||||
|
namespace internal { |
||||
|
|
||||
|
enum class MinMaxStrategy { |
||||
|
MaxStrategy, |
||||
|
MinStrategy |
||||
|
}; |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
class SparseSmgLraHelper { |
||||
|
public: |
||||
|
// Function mapping from indices to values |
||||
|
typedef std::function<ValueType(uint64_t)> ValueGetter; |
||||
|
|
||||
|
SparseSmgLraHelper(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const statesOfCoalition); |
||||
|
|
||||
|
void performValueIteration(Environment const& env, storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel, std::vector<ValueType> const& b, std::vector<ValueType>& result); |
||||
|
|
||||
|
std::vector<ValueType> getChoiceValues() const; |
||||
|
|
||||
|
storm::storage::Scheduler<ValueType> extractScheduler() const; |
||||
|
|
||||
|
std::vector<uint64_t> const& getProducedOptimalChoices() const; |
||||
|
|
||||
|
void prepareMultiplier(const Environment& env, storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel); |
||||
|
|
||||
|
std::vector<ValueType> computeLongRunAverageRewardsSound(Environment const& env, storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel); |
||||
|
|
||||
|
void setRelevantStates(storm::storage::BitVector relevantStates); |
||||
|
|
||||
|
void setValueThreshold(storm::logic::ComparisonType const& comparisonType, ValueType const& thresholdValue); |
||||
|
|
||||
|
void setOptimizationDirection(storm::solver::OptimizationDirection const& direction); |
||||
|
|
||||
|
void setProduceScheduler(bool value); |
||||
|
|
||||
|
void setProduceChoiceValues(bool value); |
||||
|
|
||||
|
void setQualitative(bool value); |
||||
|
|
||||
|
private: |
||||
|
|
||||
|
bool checkConvergence(ValueType threshold) const; |
||||
|
|
||||
|
storm::storage::BitVector getStrategyFixedBitVec(std::vector<uint64_t> const& choices, MinMaxStrategy strategy); |
||||
|
|
||||
|
std::vector<ValueType> getBVector(std::vector<ValueType> const& stateRewardsGetter, ValueGetter const& actionRewardsGetter); |
||||
|
|
||||
|
std::vector<ValueType> calcChoiceValues(Environment const& env, storm::models::sparse::StandardRewardModel<ValueType> const& rewardModel); |
||||
|
|
||||
|
std::vector<ValueType>& xNew(); |
||||
|
std::vector<ValueType> const& xNew() const; |
||||
|
|
||||
|
std::vector<ValueType>& xNewL(); |
||||
|
std::vector<ValueType> const& xNewL() const; |
||||
|
|
||||
|
std::vector<ValueType>& xNewU(); |
||||
|
std::vector<ValueType> const& xNewU() const; |
||||
|
|
||||
|
storm::storage::SparseMatrix<ValueType> const& _transitionMatrix; |
||||
|
storm::storage::BitVector const _statesOfCoalition; |
||||
|
|
||||
|
storm::storage::BitVector _relevantStates; |
||||
|
storm::storage::BitVector _minimizerStates; |
||||
|
|
||||
|
storm::storage::BitVector _fixedMinStrat; |
||||
|
storm::storage::BitVector _fixedMaxStrat; |
||||
|
std::vector<ValueType> _resultForMax; |
||||
|
std::vector<ValueType> _resultForMin; |
||||
|
|
||||
|
std::vector<ValueType> _b; |
||||
|
|
||||
|
boost::optional<std::pair<storm::logic::ComparisonType, ValueType>> _valueThreshold; |
||||
|
storm::solver::OptimizationDirection _optimizationDirection; |
||||
|
bool _produceScheduler; |
||||
|
bool _produceChoiceValues; |
||||
|
bool _isQualitativeSet; |
||||
|
|
||||
|
std::vector<ValueType> _x, _xL, _xU; |
||||
|
std::vector<ValueType> _Tsx1, _Tsx2, _TsChoiceValues; |
||||
|
std::vector<ValueType> _Isx, _Isb, _IsChoiceValues; |
||||
|
std::unique_ptr<storm::solver::Multiplier<ValueType>> _multiplier; |
||||
|
std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> _Solver; |
||||
|
std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> _DetIsSolver; |
||||
|
std::unique_ptr<storm::Environment> _IsSolverEnv; |
||||
|
|
||||
|
boost::optional<std::vector<uint64_t>> _producedOptimalChoices; |
||||
|
boost::optional<std::vector<ValueType>> _choiceValues; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,371 @@ |
|||||
|
#include "SoundGameViHelper.h"
|
||||
|
|
||||
|
#include "storm/environment/Environment.h"
|
||||
|
#include "storm/environment/solver/SolverEnvironment.h"
|
||||
|
#include "storm/environment/solver/GameSolverEnvironment.h"
|
||||
|
|
||||
|
|
||||
|
#include "storm/utility/SignalHandler.h"
|
||||
|
#include "storm/utility/vector.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace modelchecker { |
||||
|
namespace helper { |
||||
|
namespace internal { |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
SoundGameViHelper<ValueType>::SoundGameViHelper(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> b, storm::storage::BitVector statesOfCoalition, storm::storage::BitVector psiStates, OptimizationDirection const& optimizationDirection) : _transitionMatrix(transitionMatrix), _backwardTransitions(backwardTransitions), _statesOfCoalition(statesOfCoalition), _psiStates(psiStates), _optimizationDirection(optimizationDirection), _b(b) { |
||||
|
// Intentionally left empty.
|
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::prepareSolversAndMultipliers(const Environment& env) { |
||||
|
_multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, _transitionMatrix); |
||||
|
_x1IsCurrent = false; |
||||
|
if (_statesOfCoalition.size()) { |
||||
|
_minimizerStates = _optimizationDirection == OptimizationDirection::Maximize ? _statesOfCoalition : ~_statesOfCoalition; |
||||
|
} |
||||
|
else { |
||||
|
_minimizerStates = storm::storage::BitVector(_transitionMatrix.getRowGroupCount(), _optimizationDirection == OptimizationDirection::Minimize); |
||||
|
} |
||||
|
_oldPolicy = storm::storage::BitVector(_transitionMatrix.getRowCount(), false); |
||||
|
_timing = std::vector<double>(5, 0); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::performValueIteration(Environment const& env, std::vector<ValueType>& xL, std::vector<ValueType>& xU, storm::solver::OptimizationDirection const dir, std::vector<ValueType>& constrainedChoiceValues) { |
||||
|
|
||||
|
prepareSolversAndMultipliers(env); |
||||
|
// Get precision for convergence check.
|
||||
|
ValueType precision = storm::utility::convertNumber<ValueType>(env.solver().game().getPrecision()); |
||||
|
|
||||
|
uint64_t maxIter = env.solver().game().getMaximalNumberOfIterations(); |
||||
|
_x1L = xL; |
||||
|
_x2L = _x1L; |
||||
|
|
||||
|
_x1U = xU; |
||||
|
_x2U = _x1U; |
||||
|
|
||||
|
if (this->isProduceSchedulerSet()) { |
||||
|
if (!this->_producedOptimalChoices.is_initialized()) { |
||||
|
this->_producedOptimalChoices.emplace(); |
||||
|
} |
||||
|
this->_producedOptimalChoices->resize(this->_transitionMatrix.getRowGroupCount()); |
||||
|
} |
||||
|
|
||||
|
uint64_t iter = 0; |
||||
|
constrainedChoiceValues = std::vector<ValueType>(_transitionMatrix.getRowCount(), storm::utility::zero<ValueType>()); |
||||
|
|
||||
|
while (iter < maxIter) { |
||||
|
performIterationStep(env, dir); |
||||
|
if (checkConvergence(precision)) { |
||||
|
// one last iteration for shield
|
||||
|
_multiplier->multiply(env, xNewL(), nullptr, constrainedChoiceValues); |
||||
|
storm::storage::BitVector psiStates = _psiStates; |
||||
|
auto xL_begin = xNewL().begin(); |
||||
|
std::for_each(xNewL().begin(), xNewL().end(), [&psiStates, &xL_begin](ValueType &it){ |
||||
|
if (psiStates[&it - &(*xL_begin)]) |
||||
|
it = 1; |
||||
|
}); |
||||
|
break; |
||||
|
} |
||||
|
if (storm::utility::resources::isTerminate()) { |
||||
|
break; |
||||
|
} |
||||
|
++iter; |
||||
|
} |
||||
|
xL = xNewL(); |
||||
|
xU = xNewU(); |
||||
|
|
||||
|
if (isProduceSchedulerSet()) { |
||||
|
// We will be doing one more iteration step and track scheduler choices this time.
|
||||
|
_x1IsCurrent = !_x1IsCurrent; |
||||
|
_multiplier->multiplyAndReduce(env, dir, xOldL(), nullptr, xNewL(), &_producedOptimalChoices.get(), &_statesOfCoalition); |
||||
|
storm::storage::BitVector psiStates = _psiStates; |
||||
|
auto xL_begin = xNewL().begin(); |
||||
|
std::for_each(xNewL().begin(), xNewL().end(), [&psiStates, &xL_begin](ValueType &it) |
||||
|
{ |
||||
|
if (psiStates[&it - &(*xL_begin)]) |
||||
|
it = 1; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector<uint64_t>* choices) { |
||||
|
storm::storage::BitVector reducedMinimizerActions = {storm::storage::BitVector(this->_transitionMatrix.getRowCount(), true)}; |
||||
|
|
||||
|
// under approximation
|
||||
|
if (!_multiplier) { |
||||
|
prepareSolversAndMultipliers(env); |
||||
|
} |
||||
|
_x1IsCurrent = !_x1IsCurrent; |
||||
|
std::vector<ValueType> choiceValuesL = std::vector<ValueType>(this->_transitionMatrix.getRowCount(), storm::utility::zero<ValueType>()); |
||||
|
|
||||
|
_multiplier->multiply(env, xOldL(), nullptr, choiceValuesL); |
||||
|
reduceChoiceValues(choiceValuesL, &reducedMinimizerActions, xNewL()); |
||||
|
storm::storage::BitVector psiStates = _psiStates; |
||||
|
auto xL_begin = xNewL().begin(); |
||||
|
std::for_each(xNewL().begin(), xNewL().end(), [&psiStates, &xL_begin](ValueType &it) |
||||
|
{ |
||||
|
if (psiStates[&it - &(*xL_begin)]) |
||||
|
it = 1; |
||||
|
}); |
||||
|
|
||||
|
// over_approximation
|
||||
|
std::vector<ValueType> choiceValuesU = std::vector<ValueType>(this->_transitionMatrix.getRowCount(), storm::utility::zero<ValueType>()); |
||||
|
|
||||
|
_multiplier->multiply(env, xOldU(), nullptr, choiceValuesU); |
||||
|
reduceChoiceValues(choiceValuesU, nullptr, xNewU()); |
||||
|
auto xU_begin = xNewU().begin(); |
||||
|
std::for_each(xNewU().begin(), xNewU().end(), [&psiStates, &xU_begin](ValueType &it) |
||||
|
{ |
||||
|
if (psiStates[&it - &(*xU_begin)]) |
||||
|
it = 1; |
||||
|
}); |
||||
|
|
||||
|
if (reducedMinimizerActions != _oldPolicy) { // new MECs only if Policy changed
|
||||
|
// restricting the none optimal minimizer choices
|
||||
|
_restrictedTransitions = this->_transitionMatrix.restrictRows(reducedMinimizerActions); |
||||
|
|
||||
|
// find_MSECs()
|
||||
|
_MSECs = storm::storage::MaximalEndComponentDecomposition<ValueType>(_restrictedTransitions, _restrictedTransitions.transpose(true)); |
||||
|
} |
||||
|
|
||||
|
// reducing the choiceValuesU
|
||||
|
size_t i = 0; |
||||
|
auto new_end = std::remove_if(choiceValuesU.begin(), choiceValuesU.end(), [&reducedMinimizerActions, &i](const auto& item) { |
||||
|
bool ret = !(reducedMinimizerActions[i]); |
||||
|
i++; |
||||
|
return ret; |
||||
|
}); |
||||
|
choiceValuesU.erase(new_end, choiceValuesU.end()); |
||||
|
|
||||
|
_oldPolicy = reducedMinimizerActions; |
||||
|
|
||||
|
// deflating the MSECs
|
||||
|
deflate(_MSECs, _restrictedTransitions, xNewU(), choiceValuesU); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::deflate(storm::storage::MaximalEndComponentDecomposition<ValueType> const MSEC, storage::SparseMatrix<ValueType> const restrictedMatrix, std::vector<ValueType>& xU, std::vector<ValueType> choiceValues) { |
||||
|
|
||||
|
auto rowGroupIndices = restrictedMatrix.getRowGroupIndices(); |
||||
|
auto choice_begin = choiceValues.begin(); |
||||
|
// iterating over all MSECs
|
||||
|
for (auto smec_it : MSEC) { |
||||
|
ValueType bestExit = 0; |
||||
|
auto stateSet = smec_it.getStateSet(); |
||||
|
for (uint state : stateSet) { |
||||
|
if (_psiStates[state]) { |
||||
|
bestExit = 1; |
||||
|
break; |
||||
|
} |
||||
|
if (_minimizerStates[state]) continue; |
||||
|
uint rowGroupIndex = rowGroupIndices[state]; |
||||
|
auto exitingCompare = [&state, &smec_it, &choice_begin](const ValueType &lhs, const ValueType &rhs) |
||||
|
{ |
||||
|
bool lhsExiting = !smec_it.containsChoice(state, (&lhs - &(*choice_begin))); |
||||
|
bool rhsExiting = !smec_it.containsChoice(state, (&rhs - &(*choice_begin))); |
||||
|
if( lhsExiting && !rhsExiting) return false; |
||||
|
if(!lhsExiting && rhsExiting) return true; |
||||
|
if(!lhsExiting && !rhsExiting) return false; |
||||
|
return lhs < rhs; |
||||
|
}; |
||||
|
uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndex; |
||||
|
|
||||
|
auto choice_it = choice_begin + rowGroupIndex; |
||||
|
auto it = std::max_element(choice_it, choice_it + rowGroupSize, exitingCompare); |
||||
|
ValueType newBestExit = 0; |
||||
|
if (!smec_it.containsChoice(state, it - choice_begin)) { |
||||
|
newBestExit = *it; |
||||
|
} |
||||
|
if (newBestExit > bestExit) |
||||
|
bestExit = newBestExit; |
||||
|
} |
||||
|
// deflating the states of the current MSEC
|
||||
|
for (uint state : stateSet) { |
||||
|
xU[state] = std::min(xU[state], bestExit); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::reduceChoiceValues(std::vector<ValueType>& choiceValues, storm::storage::BitVector* result, std::vector<ValueType>& x) |
||||
|
{ |
||||
|
// result BitVec should be initialized with 1s outside the method
|
||||
|
|
||||
|
auto rowGroupIndices = this->_transitionMatrix.getRowGroupIndices(); |
||||
|
auto choice_it = choiceValues.begin(); |
||||
|
|
||||
|
for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { |
||||
|
uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; |
||||
|
ValueType optChoice; |
||||
|
if (_minimizerStates[state]) { // check if current state is minimizer state
|
||||
|
// getting the optimal minimizer choice for the given state
|
||||
|
optChoice = *std::min_element(choice_it, choice_it + rowGroupSize); |
||||
|
|
||||
|
if (result != nullptr) { |
||||
|
for (uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { |
||||
|
if (*choice_it > optChoice) { |
||||
|
result->set(rowGroupIndices[state] + choice, 0); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
choice_it += rowGroupSize; |
||||
|
} |
||||
|
// reducing the xNew() vector for minimizer states
|
||||
|
x[state] = optChoice; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
optChoice = *std::max_element(choice_it, choice_it + rowGroupSize); |
||||
|
// reducing the xNew() vector for maximizer states
|
||||
|
x[state] = optChoice; |
||||
|
choice_it += rowGroupSize; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template <typename ValueType> |
||||
|
bool SoundGameViHelper<ValueType>::checkConvergence(ValueType threshold) const { |
||||
|
STORM_LOG_ASSERT(_multiplier, "tried to check for convergence without doing an iteration first."); |
||||
|
// Now check whether the currently produced results are precise enough
|
||||
|
STORM_LOG_ASSERT(threshold > storm::utility::zero<ValueType>(), "Did not expect a non-positive threshold."); |
||||
|
auto x1It = xNewL().begin(); |
||||
|
auto x1Ite = xNewL().end(); |
||||
|
auto x2It = xNewU().begin(); |
||||
|
for (; x1It != x1Ite; x1It++, x2It++) { |
||||
|
ValueType diff = (*x2It - *x1It); |
||||
|
if (diff > threshold) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::setProduceScheduler(bool value) { |
||||
|
_produceScheduler = value; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template <typename ValueType> |
||||
|
bool SoundGameViHelper<ValueType>::isProduceSchedulerSet() const { |
||||
|
return _produceScheduler; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::setShieldingTask(bool value) { |
||||
|
_shieldingTask = value; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
bool SoundGameViHelper<ValueType>::isShieldingTask() const { |
||||
|
return _shieldingTask; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::updateTransitionMatrix(storm::storage::SparseMatrix<ValueType> newTransitionMatrix) { |
||||
|
_transitionMatrix = newTransitionMatrix; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::updateStatesOfCoalition(storm::storage::BitVector newStatesOfCoalition) { |
||||
|
_statesOfCoalition = newStatesOfCoalition; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<uint64_t> const& SoundGameViHelper<ValueType>::getProducedOptimalChoices() const { |
||||
|
STORM_LOG_ASSERT(this->isProduceSchedulerSet(), "Trying to get the produced optimal choices although no scheduler was requested."); |
||||
|
STORM_LOG_ASSERT(this->_producedOptimalChoices.is_initialized(), "Trying to get the produced optimal choices but none were available. Was there a computation call before?"); |
||||
|
return this->_producedOptimalChoices.get(); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<uint64_t>& SoundGameViHelper<ValueType>::getProducedOptimalChoices() { |
||||
|
STORM_LOG_ASSERT(this->isProduceSchedulerSet(), "Trying to get the produced optimal choices although no scheduler was requested."); |
||||
|
STORM_LOG_ASSERT(this->_producedOptimalChoices.is_initialized(), "Trying to get the produced optimal choices but none were available. Was there a computation call before?"); |
||||
|
return this->_producedOptimalChoices.get(); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
storm::storage::Scheduler<ValueType> SoundGameViHelper<ValueType>::extractScheduler() const{ |
||||
|
auto const& optimalChoices = getProducedOptimalChoices(); |
||||
|
storm::storage::Scheduler<ValueType> scheduler(optimalChoices.size()); |
||||
|
for (uint64_t state = 0; state < optimalChoices.size(); ++state) { |
||||
|
scheduler.setChoice(optimalChoices[state], state); |
||||
|
} |
||||
|
return scheduler; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::getChoiceValues(Environment const& env, std::vector<ValueType> const& x, std::vector<ValueType>& choiceValues) { |
||||
|
_multiplier->multiply(env, x, nullptr, choiceValues); |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void SoundGameViHelper<ValueType>::fillChoiceValuesVector(std::vector<ValueType>& choiceValues, storm::storage::BitVector psiStates, std::vector<storm::storage::SparseMatrix<double>::index_type> rowGroupIndices) { |
||||
|
std::vector<ValueType> allChoices = std::vector<ValueType>(rowGroupIndices.at(rowGroupIndices.size() - 1), storm::utility::zero<ValueType>()); |
||||
|
auto choice_it = choiceValues.begin(); |
||||
|
for(uint state = 0; state < rowGroupIndices.size() - 1; state++) { |
||||
|
uint rowGroupSize = rowGroupIndices[state + 1] - rowGroupIndices[state]; |
||||
|
if (psiStates.get(state)) { |
||||
|
for(uint choice = 0; choice < rowGroupSize; choice++, choice_it++) { |
||||
|
allChoices.at(rowGroupIndices.at(state) + choice) = *choice_it; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
choiceValues = allChoices; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType>& SoundGameViHelper<ValueType>::xNewL() { |
||||
|
return _x1IsCurrent ? _x1L : _x2L; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> const& SoundGameViHelper<ValueType>::xNewL() const { |
||||
|
return _x1IsCurrent ? _x1L : _x2L; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType>& SoundGameViHelper<ValueType>::xOldL() { |
||||
|
return _x1IsCurrent ? _x2L : _x1L; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> const& SoundGameViHelper<ValueType>::xOldL() const { |
||||
|
return _x1IsCurrent ? _x2L : _x1L; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType>& SoundGameViHelper<ValueType>::xNewU() { |
||||
|
return _x1IsCurrent ? _x1U : _x2U; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> const& SoundGameViHelper<ValueType>::xNewU() const { |
||||
|
return _x1IsCurrent ? _x1U : _x2U; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType>& SoundGameViHelper<ValueType>::xOldU() { |
||||
|
return _x1IsCurrent ? _x2U : _x1U; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
std::vector<ValueType> const& SoundGameViHelper<ValueType>::xOldU() const { |
||||
|
return _x1IsCurrent ? _x2U : _x1U; |
||||
|
} |
||||
|
|
||||
|
template class SoundGameViHelper<double>; |
||||
|
#ifdef STORM_HAVE_CARL
|
||||
|
template class SoundGameViHelper<storm::RationalNumber>; |
||||
|
#endif
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,136 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "storm/storage/SparseMatrix.h" |
||||
|
#include "storm/solver/LinearEquationSolver.h" |
||||
|
#include "storm/solver/MinMaxLinearEquationSolver.h" |
||||
|
#include "storm/solver/Multiplier.h" |
||||
|
#include "storm/storage/MaximalEndComponentDecomposition.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
class Environment; |
||||
|
|
||||
|
namespace storage { |
||||
|
template <typename VT> class Scheduler; |
||||
|
} |
||||
|
|
||||
|
namespace modelchecker { |
||||
|
namespace helper { |
||||
|
namespace internal { |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
class SoundGameViHelper { |
||||
|
public: |
||||
|
SoundGameViHelper(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> b, storm::storage::BitVector statesOfCoalition, storm::storage::BitVector psiStates, OptimizationDirection const& optimizationDirection); |
||||
|
|
||||
|
void prepareSolversAndMultipliers(const Environment& env); |
||||
|
|
||||
|
/*! |
||||
|
* Perform value iteration until convergence |
||||
|
*/ |
||||
|
void performValueIteration(Environment const& env, std::vector<ValueType>& xL, std::vector<ValueType>& xU, storm::solver::OptimizationDirection const dir, std::vector<ValueType>& constrainedChoiceValues); |
||||
|
|
||||
|
/*! |
||||
|
* Sets whether an optimal scheduler shall be constructed during the computation |
||||
|
*/ |
||||
|
void setProduceScheduler(bool value); |
||||
|
|
||||
|
/*! |
||||
|
* @return whether an optimal scheduler shall be constructed during the computation |
||||
|
*/ |
||||
|
bool isProduceSchedulerSet() const; |
||||
|
|
||||
|
/*! |
||||
|
* Sets whether an optimal scheduler shall be constructed during the computation |
||||
|
*/ |
||||
|
void setShieldingTask(bool value); |
||||
|
|
||||
|
/*! |
||||
|
* @return whether an optimal scheduler shall be constructed during the computation |
||||
|
*/ |
||||
|
bool isShieldingTask() const; |
||||
|
|
||||
|
/*! |
||||
|
* Changes the transitionMatrix to the given one. |
||||
|
*/ |
||||
|
void updateTransitionMatrix(storm::storage::SparseMatrix<ValueType> newTransitionMatrix); |
||||
|
|
||||
|
/*! |
||||
|
* Changes the statesOfCoalition to the given one. |
||||
|
*/ |
||||
|
void updateStatesOfCoalition(storm::storage::BitVector newStatesOfCoalition); |
||||
|
|
||||
|
storm::storage::Scheduler<ValueType> extractScheduler() const; |
||||
|
|
||||
|
void getChoiceValues(Environment const& env, std::vector<ValueType> const& x, std::vector<ValueType>& choiceValues); |
||||
|
|
||||
|
/*! |
||||
|
* Fills the choice values vector to the original size with zeros for ~psiState choices. |
||||
|
*/ |
||||
|
void fillChoiceValuesVector(std::vector<ValueType>& choiceValues, storm::storage::BitVector psiStates, std::vector<storm::storage::SparseMatrix<double>::index_type> rowGroupIndices); |
||||
|
|
||||
|
void deflate(storm::storage::MaximalEndComponentDecomposition<ValueType> const MECD, storage::SparseMatrix<ValueType> const restrictedMatrix, std::vector<ValueType>& xU, std::vector<ValueType> choiceValues); |
||||
|
|
||||
|
void reduceChoiceValues(std::vector<ValueType>& choiceValues, storm::storage::BitVector* result, std::vector<ValueType>& x); |
||||
|
|
||||
|
private: |
||||
|
/*! |
||||
|
* Performs one iteration step for value iteration |
||||
|
*/ |
||||
|
void performIterationStep(Environment const& env, storm::solver::OptimizationDirection const dir, std::vector<uint64_t>* choices = nullptr); |
||||
|
|
||||
|
/*! |
||||
|
* Checks whether the curently computed value achieves the desired precision |
||||
|
*/ |
||||
|
bool checkConvergence(ValueType precision) const; |
||||
|
|
||||
|
std::vector<ValueType>& xNewL(); |
||||
|
std::vector<ValueType> const& xNewL() const; |
||||
|
|
||||
|
std::vector<ValueType>& xOldL(); |
||||
|
std::vector<ValueType> const& xOldL() const; |
||||
|
|
||||
|
std::vector<ValueType>& xNewU(); |
||||
|
std::vector<ValueType> const& xNewU() const; |
||||
|
|
||||
|
std::vector<ValueType>& xOldU(); |
||||
|
std::vector<ValueType> const& xOldU() const; |
||||
|
|
||||
|
bool _x1IsCurrent; |
||||
|
|
||||
|
storm::storage::BitVector _minimizerStates; |
||||
|
|
||||
|
/*! |
||||
|
* @pre before calling this, a computation call should have been performed during which scheduler production was enabled. |
||||
|
* @return the produced scheduler of the most recent call. |
||||
|
*/ |
||||
|
std::vector<uint64_t> const& getProducedOptimalChoices() const; |
||||
|
|
||||
|
/*! |
||||
|
* @pre before calling this, a computation call should have been performed during which scheduler production was enabled. |
||||
|
* @return the produced scheduler of the most recent call. |
||||
|
*/ |
||||
|
std::vector<uint64_t>& getProducedOptimalChoices(); |
||||
|
|
||||
|
std::unique_ptr<storm::solver::Multiplier<ValueType>> _multiplier; |
||||
|
|
||||
|
storm::storage::SparseMatrix<ValueType> _transitionMatrix; |
||||
|
storm::storage::SparseMatrix<ValueType> _backwardTransitions; |
||||
|
storm::storage::SparseMatrix<ValueType> _restrictedTransitions; |
||||
|
storm::storage::BitVector _oldPolicy; |
||||
|
storm::storage::BitVector _statesOfCoalition; |
||||
|
storm::storage::BitVector _psiStates; |
||||
|
std::vector<ValueType> _x, _x1L, _x2L, _x1U, _x2U, _b; |
||||
|
OptimizationDirection _optimizationDirection; |
||||
|
|
||||
|
storm::storage::MaximalEndComponentDecomposition<ValueType> _MSECs; |
||||
|
|
||||
|
bool _produceScheduler = false; |
||||
|
bool _shieldingTask = false; |
||||
|
boost::optional<std::vector<uint64_t>> _producedOptimalChoices; |
||||
|
|
||||
|
std::vector<double> _timing; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue