@ -3,6 +3,7 @@
# include "storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.h"
# include "storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.h"
# include "storm/storage/SparseMatrix.h"
# include "storm/storage/SparseMatrix.h"
# include "storm/storage/MaximalEndComponentDecomposition.h"
# include "storm/storage/Scheduler.h"
# include "storm/storage/Scheduler.h"
# include "storm/solver/MinMaxLinearEquationSolver.h"
# include "storm/solver/MinMaxLinearEquationSolver.h"
@ -26,25 +27,99 @@ namespace storm {
// Intentionally left empty.
// Intentionally left empty.
}
}
template < typename ValueType >
std : : vector < uint64_t > const & SparseNondeterministicGameInfiniteHorizonHelper < 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 > & SparseNondeterministicGameInfiniteHorizonHelper < 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 > SparseNondeterministicGameInfiniteHorizonHelper < 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 >
template < typename ValueType >
void SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : createDecomposition ( ) {
void SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : createDecomposition ( ) {
STORM_LOG_THROW ( false , storm : : exceptions : : InternalException , " Creating Decompositions of SMGs is currently not possible. " ) ;
// TODO This needs to be changed to return the whole model as one component as long as there is no overwritten version of MaximalEndComponentDecomposition for SMGs.
if ( this - > _longRunComponentDecomposition = = nullptr ) {
// The decomposition has not been provided or computed, yet.
if ( this - > _backwardTransitions = = nullptr ) {
this - > _computedBackwardTransitions = std : : make_unique < storm : : storage : : SparseMatrix < ValueType > > ( this - > _transitionMatrix . transpose ( true ) ) ;
this - > _backwardTransitions = this - > _computedBackwardTransitions . get ( ) ;
}
this - > _computedLongRunComponentDecomposition = std : : make_unique < storm : : storage : : MaximalEndComponentDecomposition < ValueType > > ( this - > _transitionMatrix , * this - > _backwardTransitions ) ;
this - > _longRunComponentDecomposition = this - > _computedLongRunComponentDecomposition . get ( ) ;
}
}
template < typename ValueType >
std : : vector < ValueType > SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : computeLongRunAverageValues ( Environment const & env , ValueGetter const & stateValuesGetter , ValueGetter const & actionValuesGetter ) {
auto underlyingSolverEnvironment = env ;
std : : vector < ValueType > componentLraValues ;
createDecomposition ( ) ;
componentLraValues . reserve ( this - > _longRunComponentDecomposition - > size ( ) ) ;
for ( auto const & c : * ( this - > _longRunComponentDecomposition ) ) {
componentLraValues . push_back ( computeLraForComponent ( underlyingSolverEnvironment , stateValuesGetter , actionValuesGetter , c ) ) ;
}
return componentLraValues ;
}
}
template < typename ValueType >
template < typename ValueType >
ValueType SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : computeLraForComponent ( Environment const & env , ValueGetter const & stateRewardsGetter , ValueGetter const & actionRewardsGetter , storm : : storage : : MaximalEndComponent const & component ) {
ValueType SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : computeLraForComponent ( Environment const & env , ValueGetter const & stateRewardsGetter , ValueGetter const & actionRewardsGetter , storm : : storage : : MaximalEndComponent const & component ) {
// Allocate memory for the nondeterministic choices.
if ( this - > isProduceSchedulerSet ( ) ) {
if ( ! this - > _producedOptimalChoices . is_initialized ( ) ) {
this - > _producedOptimalChoices . emplace ( ) ;
}
this - > _producedOptimalChoices - > resize ( this - > _transitionMatrix . getRowGroupCount ( ) ) ;
}
STORM_LOG_THROW ( false , storm : : exceptions : : InternalException , " Computing values for LRA for SMGs components is currently not possible. " ) ;
storm : : solver : : LraMethod method = env . solver ( ) . lra ( ) . getNondetLraMethod ( ) ;
if ( method = = storm : : solver : : LraMethod : : LinearProgramming ) {
STORM_LOG_THROW ( false , storm : : exceptions : : InvalidSettingsException , " Unsupported technique. " ) ;
} else if ( method = = storm : : solver : : LraMethod : : ValueIteration ) {
return computeLraVi ( env , stateRewardsGetter , actionRewardsGetter , component ) ;
} else {
STORM_LOG_THROW ( false , storm : : exceptions : : InvalidSettingsException , " Unsupported technique. " ) ;
}
}
}
template < typename ValueType >
template < typename ValueType >
std : : vector < ValueType > SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : buildAndSolveSsp ( Environment const & env , std : : vector < ValueType > const & componentLraValues ) {
STORM_LOG_THROW ( false , storm : : exceptions : : InternalException , " buildAndSolveSsp not available for SMGs " ) ;
ValueType SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : computeLraVi ( Environment const & env , ValueGetter const & stateRewardsGetter , ValueGetter const & actionRewardsGetter , storm : : storage : : MaximalEndComponent const & mec ) {
// Collect some parameters of the computation
ValueType aperiodicFactor = storm : : utility : : convertNumber < ValueType > ( env . solver ( ) . lra ( ) . getAperiodicFactor ( ) ) ;
std : : vector < uint64_t > * optimalChoices = nullptr ;
if ( this - > isProduceSchedulerSet ( ) ) {
optimalChoices = & this - > _producedOptimalChoices . get ( ) ;
}
// Now create a helper and perform the algorithm
if ( this - > isContinuousTime ( ) ) {
STORM_LOG_THROW ( false , storm : : exceptions : : InternalException , " We cannot handle continuous time games. " ) ;
} else {
storm : : modelchecker : : helper : : internal : : LraViHelper < ValueType , storm : : storage : : MaximalEndComponent , storm : : modelchecker : : helper : : internal : : LraViTransitionsType : : GameNondetTsNoIs > viHelper ( mec , this - > _transitionMatrix , aperiodicFactor ) ;
return viHelper . performValueIteration ( env , stateRewardsGetter , actionRewardsGetter , nullptr , & this - > getOptimizationDirection ( ) , optimalChoices ) ;
}
}
}
template < typename ValueType >
template < typename ValueType >
std : : vector < ValueType > SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : computeLongRunAverageValues ( Environment const & env , ValueGetter const & stateRewardsGetter , ValueGetter const & actionRewardsGetter ) {
STORM_LOG_THROW ( false , storm : : exceptions : : InternalException , " computeLongRunAverageValues not possible yet. " ) ;
std : : vector < ValueType > SparseNondeterministicGameInfiniteHorizonHelper < ValueType > : : buildAndSolveSsp ( Environment const & env , std : : vector < ValueType > const & componentLraValues ) {
STORM_LOG_THROW ( false , storm : : exceptions : : InternalException , " We do not create compositions for LRA for SMGs, solving a stochastic shortest path problem is not available ." ) ;
}
}