@ -21,15 +21,27 @@ namespace storm { 
			
		
	
		
			
				
					        namespace  helper  {  
			
		
	
		
			
				
					         
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            SparseNondeterministicInfiniteHorizonHelper < ValueType > : : SparseNondeterministicInfiniteHorizonHelper ( storm : : storage : : SparseMatrix < ValueType >  const &  transitionMatrix ,  storm : : storage : : SparseMatrix < ValueType >  const &  backwardTransitions )  :  _transitionMatrix ( transitionMatrix ) ,  _backwardTransitions ( backwardTransitions ) ,  _markovianStates ( nullptr ) ,  _exitRates ( nullptr ) ,  _produceScheduler ( false )  {  
			
		
	
		
			
				
					            SparseNondeterministicInfiniteHorizonHelper < ValueType > : : SparseNondeterministicInfiniteHorizonHelper ( storm : : storage : : SparseMatrix < ValueType >  const &  transitionMatrix )  :  _transitionMatrix ( transitionMatrix ) ,  _backwardTransitions ( nullptr ) ,  _mecDecomposition ( nullptr ) ,  _markovianStates ( nullptr ) ,  _exitRates ( nullptr )  {  
			
		
	
		
			
				
					                // Intentionally left empty.
  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            SparseNondeterministicInfiniteHorizonHelper < ValueType > : : SparseNondeterministicInfiniteHorizonHelper ( storm : : storage : : SparseMatrix < ValueType >  const &  transitionMatrix ,  storm : : storage : : SparseMatrix < ValueType >  const &  backwardTransitions ,  storm : : storage : : BitVector  const &  markovianStates ,  std : : vector < ValueType >  const &  exitRates )  :  _transitionMatrix ( transitionMatrix ) ,  _backwardTransitions ( backwardTransitions ) ,  _markovianStates ( & markovianStates ) ,  _exitRates ( & exitRates ) ,  _produceScheduler ( false )  {  
			
		
	
		
			
				
					            SparseNondeterministicInfiniteHorizonHelper < ValueType > : : SparseNondeterministicInfiniteHorizonHelper ( storm : : storage : : SparseMatrix < ValueType >  const &  transitionMatrix ,  storm : : storage : : BitVector  const &  markovianStates ,  std : : vector < ValueType >  const &  exitRates )  :  _transitionMatrix ( transitionMatrix ) ,  _backwardTransitions ( nullptr ) ,  _mecDecomposition ( nullptr ) ,  _markovianStates ( & markovianStates ) ,  _exitRates ( & exitRates )  {  
			
		
	
		
			
				
					                // Intentionally left empty.
  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            void  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : provideBackwardTransitions ( storm : : storage : : SparseMatrix < ValueType >  const &  backwardTransitions )  {  
			
		
	
		
			
				
					                STORM_LOG_WARN_COND ( _backwardTransitions  = =  nullptr ,  " Backwards transitions were provided but they were already computed or set before. " ) ;  
			
		
	
		
			
				
					                _backwardTransitions  =  & backwardTransitions ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            void  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : provideMaximalEndComponentDecomposition ( storm : : storage : : MaximalEndComponentDecomposition < ValueType >  const &  mecDecomposition )  {  
			
		
	
		
			
				
					                STORM_LOG_WARN_COND ( _mecDecomposition  = =  nullptr ,  " Backwards transitions were provided but they were already computed or set before. " ) ;  
			
		
	
		
			
				
					                _mecDecomposition  =  & mecDecomposition ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            std : : vector < ValueType >  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : computeLongRunAverageProbabilities ( Environment  const &  env ,  storm : : storage : : BitVector  const &  psiStates )  {  
			
		
	
		
			
				
					                return  computeLongRunAverageValues ( env ,  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -96,7 +108,7 @@ namespace storm { 
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // If requested, allocate memory for the choices made
  
			
		
	
		
			
				
					                if  ( isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                if  ( this - > isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                    if  ( ! _producedOptimalChoices . is_initialized ( ) )  {  
			
		
	
		
			
				
					                        _producedOptimalChoices . emplace ( ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -104,40 +116,37 @@ namespace storm { 
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Start by decomposing the Model into its MECs.
  
			
		
	
		
			
				
					                storm : : storage : : MaximalEndComponentDecomposition < ValueType >  mecDecomposition ( _transitionMatrix ,  _backwardTransitions ) ;  
			
		
	
		
			
				
					                if  ( _mecDecomposition  = =  nullptr )  {  
			
		
	
		
			
				
					                    // The decomposition has not been provided or computed, yet.
  
			
		
	
		
			
				
					                    if  ( _backwardTransitions  = =  nullptr )  {  
			
		
	
		
			
				
					                        _computedBackwardTransitions  =  _transitionMatrix . transpose ( true ) ;  
			
		
	
		
			
				
					                        _backwardTransitions  =  & _computedBackwardTransitions ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    _computedMecDecomposition  =  storm : : storage : : MaximalEndComponentDecomposition < ValueType > ( _transitionMatrix ,  * _backwardTransitions ) ;  
			
		
	
		
			
				
					                    _mecDecomposition  =  & _computedMecDecomposition ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                // Compute the long-run average for all end components in isolation.
  
			
		
	
		
			
				
					                std : : vector < ValueType >  mecLraValues ;  
			
		
	
		
			
				
					                mecLraValues . reserve ( mecDecomposition . size ( ) ) ;  
			
		
	
		
			
				
					                for  ( auto  const &  mec  :  mecDecomposition )  {  
			
		
	
		
			
				
					                mecLraValues . reserve ( _mecDecomposition - > size ( ) ) ;  
			
		
	
		
			
				
					                for  ( auto  const &  mec  :  * _ mecDecomposition)  {  
			
		
	
		
			
				
					                    mecLraValues . push_back ( computeLraForMec ( underlyingSolverEnvironment ,  stateRewardsGetter ,  actionRewardsGetter ,  mec ) ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Solve the resulting SSP where end components are collapsed into single auxiliary states
  
			
		
	
		
			
				
					                return  buildAndSolveSsp ( underlyingSolverEnvironment ,  mecDecomposition ,  mecLraValues ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            void  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : setProduceScheduler ( bool  value )  {  
			
		
	
		
			
				
					                _produceScheduler  =  value ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            bool  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : isProduceSchedulerSet ( )  const  {  
			
		
	
		
			
				
					                return  _produceScheduler ;  
			
		
	
		
			
				
					                return  buildAndSolveSsp ( underlyingSolverEnvironment ,  mecLraValues ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            std : : vector < uint64_t >  const &  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : getProducedOptimalChoices ( )  const  {  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( isProduceSchedulerSet ( ) ,  " Trying to get the produced optimal choices although no scheduler was requested. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( this - > isProduceSchedulerSet ( ) ,  " Trying to get the produced optimal choices although no scheduler was requested. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( _producedOptimalChoices . is_initialized ( ) ,  " Trying to get the produced optimal choices but none were available. Was there a computation call before? " ) ;  
			
		
	
		
			
				
					                return  _producedOptimalChoices . get ( ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            std : : vector < uint64_t > &  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : getProducedOptimalChoices ( )  {  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( isProduceSchedulerSet ( ) ,  " Trying to get the produced optimal choices although no scheduler was requested. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( this - > isProduceSchedulerSet ( ) ,  " Trying to get the produced optimal choices although no scheduler was requested. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( _producedOptimalChoices . is_initialized ( ) ,  " Trying to get the produced optimal choices but none were available. Was there a computation call before? " ) ;  
			
		
	
		
			
				
					                return  _producedOptimalChoices . get ( ) ;  
			
		
	
		
			
				
					            }  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -169,7 +178,7 @@ namespace storm { 
			
		
	
		
			
				
					                        // Singleton MECs have to consist of a Markovian state because of the non-Zenoness assumption. Then, there is just one possible choice.
  
			
		
	
		
			
				
					                        STORM_LOG_THROW ( _markovianStates - > get ( state ) ,  storm : : exceptions : : InvalidOperationException ,  " Markov Automaton has Zeno behavior. Computation of Long Run Average values not supported. " ) ;  
			
		
	
		
			
				
					                        STORM_LOG_ASSERT ( mec . begin ( ) - > second . size ( )  = =  1 ,  " Markovian state has Nondeterministic behavior. " ) ;  
			
		
	
		
			
				
					                        if  ( isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                        if  ( this - > isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                            _producedOptimalChoices . get ( ) [ state ]  =  0 ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        return  stateRewardsGetter ( state )  +  ( * _exitRates ) [ state ]  *  actionRewardsGetter ( * choiceIt ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -184,7 +193,7 @@ namespace storm { 
			
		
	
		
			
				
					                                bestChoice  =  * choiceIt ;  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        if  ( isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                        if  ( this - > isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                            _producedOptimalChoices . get ( ) [ state ]  =  bestChoice  -  _transitionMatrix . getRowGroupIndices ( ) [ state ] ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        return  bestValue  +  stateRewardsGetter ( state ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -200,7 +209,7 @@ namespace storm { 
			
		
	
		
			
				
					                    STORM_LOG_INFO ( " Selecting 'VI' as the solution technique for long-run properties to guarantee sound results. If you want to override this, please explicitly specify a different LRA method. " ) ;  
			
		
	
		
			
				
					                    method  =  storm : : solver : : LraMethod : : ValueIteration ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                STORM_LOG_ERROR_COND ( ! isProduceSchedulerSet ( )  | |  method  = =  storm : : solver : : LraMethod : : ValueIteration ,  " Scheduler generation not supported for the chosen LRA method. Try value-iteration. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_ERROR_COND ( ! this - > isProduceSchedulerSet ( )  | |  method  = =  storm : : solver : : LraMethod : : ValueIteration ,  " Scheduler generation not supported for the chosen LRA method. Try value-iteration. " ) ;  
			
		
	
		
			
				
					                if  ( method  = =  storm : : solver : : LraMethod : : LinearProgramming )  {  
			
		
	
		
			
				
					                    return  computeLraForMecLp ( env ,  stateRewardsGetter ,  actionRewardsGetter ,  mec ) ;  
			
		
	
		
			
				
					                }  else  if  ( method  = =  storm : : solver : : LraMethod : : ValueIteration )  {  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -216,7 +225,7 @@ namespace storm { 
			
		
	
		
			
				
					                // Collect some parameters of the computation
  
			
		
	
		
			
				
					                ValueType  aperiodicFactor  =  storm : : utility : : convertNumber < ValueType > ( env . solver ( ) . lra ( ) . getAperiodicFactor ( ) ) ;  
			
		
	
		
			
				
					                std : : vector < uint64_t > *  optimalChoices  =  nullptr ;  
			
		
	
		
			
				
					                if  ( isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                if  ( this - > isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                    optimalChoices  =  & _producedOptimalChoices . get ( ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -296,7 +305,7 @@ namespace storm { 
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                solver - > optimize ( ) ;  
			
		
	
		
			
				
					                STORM_LOG_THROW ( ! isProduceSchedulerSet ( ) ,  storm : : exceptions : : NotImplementedException ,  " Scheduler extraction is not yet implemented for LP based LRA method. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_THROW ( ! this - > isProduceSchedulerSet ( ) ,  storm : : exceptions : : NotImplementedException ,  " Scheduler extraction is not yet implemented for LP based LRA method. " ) ;  
			
		
	
		
			
				
					                return  solver - > getContinuousValue ( k ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -339,7 +348,8 @@ namespace storm { 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < typename  ValueType >  
			
		
	
		
			
				
					            std : : vector < ValueType >  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : buildAndSolveSsp ( Environment  const &  env ,  storm : : storage : : MaximalEndComponentDecomposition < ValueType >  const &  mecDecomposition ,  std : : vector < ValueType >  const &  mecLraValues )  {  
			
		
	
		
			
				
					            std : : vector < ValueType >  SparseNondeterministicInfiniteHorizonHelper < ValueType > : : buildAndSolveSsp ( Environment  const &  env ,  std : : vector < ValueType >  const &  mecLraValues )  {  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( _mecDecomposition  ! =  nullptr ,  " Decomposition not computed, yet. " ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Let's improve readability a bit
  
			
		
	
		
			
				
					                uint64_t  numberOfStates  =  _transitionMatrix . getRowGroupCount ( ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -353,8 +363,8 @@ namespace storm { 
			
		
	
		
			
				
					                // and create a mapping from states that lie in a MEC to the corresponding MEC index.
  
			
		
	
		
			
				
					                storm : : storage : : BitVector  statesInMecs ( numberOfStates ) ;  
			
		
	
		
			
				
					                std : : vector < uint64_t >  inputToSspStateMap ( numberOfStates ,  std : : numeric_limits < uint64_t > : : max ( ) ) ;  
			
		
	
		
			
				
					                for  ( uint64_t  currentMecIndex  =  0 ;  currentMecIndex  <  mecDecomposition . size ( ) ;  + + currentMecIndex )  {  
			
		
	
		
			
				
					                    for  ( auto  const &  stateChoicesPair  :  mecDecomposition [ currentMecIndex ] )  {  
			
		
	
		
			
				
					                for  ( uint64_t  currentMecIndex  =  0 ;  currentMecIndex  <  _mecDecomposition - > size ( ) ;  + + currentMecIndex )  {  
			
		
	
		
			
				
					                    for  ( auto  const &  stateChoicesPair  :  ( * _ mecDecomposition) [ currentMecIndex ] )  {  
			
		
	
		
			
				
					                        statesInMecs . set ( stateChoicesPair . first ) ;  
			
		
	
		
			
				
					                        inputToSspStateMap [ stateChoicesPair . first ]  =  currentMecIndex ;  
			
		
	
		
			
				
					                    }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -379,7 +389,7 @@ namespace storm { 
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // The next step is to create the SSP matrix and the right-hand side of the SSP.
  
			
		
	
		
			
				
					                std : : vector < ValueType >  rhs ;  
			
		
	
		
			
				
					                uint64_t  numberOfSspStates  =  numberOfStatesNotInMecs  +  mecDecomposition . size ( ) ;  
			
		
	
		
			
				
					                uint64_t  numberOfSspStates  =  numberOfStatesNotInMecs  +  _mecDecomposition - > size ( ) ;  
			
		
	
		
			
				
					                typename  storm : : storage : : SparseMatrixBuilder < ValueType >  sspMatrixBuilder ( 0 ,  numberOfSspStates  ,  0 ,  false ,  true ,  numberOfSspStates ) ;  
			
		
	
		
			
				
					                // If the source state of a transition is not contained in any MEC, we copy its choices (and perform the necessary modifications).
  
			
		
	
		
			
				
					                uint64_t  currentSspChoice  =  0 ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -392,8 +402,8 @@ namespace storm { 
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                // Now we construct the choices for the auxiliary states which reflect former MEC states.
  
			
		
	
		
			
				
					                for  ( uint64_t  mecIndex  =  0 ;  mecIndex  <  mecDecomposition . size ( ) ;  + + mecIndex )  {  
			
		
	
		
			
				
					                    storm : : storage : : MaximalEndComponent  const &  mec  =  mecDecomposition [ mecIndex ] ;  
			
		
	
		
			
				
					                for  ( uint64_t  mecIndex  =  0 ;  mecIndex  <  _mecDecomposition - > size ( ) ;  + + mecIndex )  {  
			
		
	
		
			
				
					                    storm : : storage : : MaximalEndComponent  const &  mec  =  ( * _ mecDecomposition) [ mecIndex ] ;  
			
		
	
		
			
				
					                    sspMatrixBuilder . newRowGroup ( currentSspChoice ) ;  
			
		
	
		
			
				
					                    for  ( auto  const &  stateChoicesPair  :  mec )  {  
			
		
	
		
			
				
					                        uint64_t  const &  mecState  =  stateChoicesPair . first ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -403,7 +413,7 @@ namespace storm { 
			
		
	
		
			
				
					                            if  ( choicesInMec . find ( choice )  = =  choicesInMec . end ( ) )  {  
			
		
	
		
			
				
					                                rhs . push_back ( storm : : utility : : zero < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                                addSspMatrixChoice ( choice ,  _transitionMatrix ,  inputToSspStateMap ,  numberOfStatesNotInMecs ,  currentSspChoice ,  sspMatrixBuilder ) ;  
			
		
	
		
			
				
					                                if  ( isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                                if  ( this - > isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                                    // Later we need to be able to map this choice back to the original input model
  
			
		
	
		
			
				
					                                    sspMecExitChoicesToOriginalMap . emplace_back ( mecState ,  choice  -  nondeterministicChoiceIndices [ mecState ] ) ;  
			
		
	
		
			
				
					                                }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -413,7 +423,7 @@ namespace storm { 
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    // For each auxiliary state, there is the option to achieve the reward value of the LRA associated with the MEC.
  
			
		
	
		
			
				
					                    rhs . push_back ( mecLraValues [ mecIndex ] ) ;  
			
		
	
		
			
				
					                    if  ( isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                    if  ( this - > isProduceSchedulerSet ( ) )  {  
			
		
	
		
			
				
					                        // Insert some invalid values so we can later detect that this choice is not an exit choice
  
			
		
	
		
			
				
					                        sspMecExitChoicesToOriginalMap . emplace_back ( std : : numeric_limits < uint_fast64_t > : : max ( ) ,  std : : numeric_limits < uint_fast64_t > : : max ( ) ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -429,7 +439,7 @@ namespace storm { 
			
		
	
		
			
				
					                std : : unique_ptr < storm : : solver : : MinMaxLinearEquationSolver < ValueType > >  solver  =  minMaxLinearEquationSolverFactory . create ( env ,  sspMatrix ) ;  
			
		
	
		
			
				
					                solver - > setHasUniqueSolution ( ) ;  
			
		
	
		
			
				
					                solver - > setHasNoEndComponents ( ) ;  
			
		
	
		
			
				
					                solver - > setTrackScheduler ( isProduceSchedulerSet ( ) ) ;  
			
		
	
		
			
				
					                solver - > setTrackScheduler ( this - > isProduceSchedulerSet ( ) ) ;  
			
		
	
		
			
				
					                auto  lowerUpperBounds  =  std : : minmax_element ( mecLraValues . begin ( ) ,  mecLraValues . end ( ) ) ;  
			
		
	
		
			
				
					                solver - > setLowerBound ( * lowerUpperBounds . first ) ;  
			
		
	
		
			
				
					                solver - > setUpperBound ( * lowerUpperBounds . second ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -440,7 +450,7 @@ namespace storm { 
			
		
	
		
			
				
					                solver - > solveEquations ( env ,  this - > getOptimizationDirection ( ) ,  x ,  rhs ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                // Prepare scheduler (if requested)
  
			
		
	
		
			
				
					                if  ( isProduceSchedulerSet ( )  & &  solver - > hasScheduler ( ) )  {  
			
		
	
		
			
				
					                if  ( this - > isProduceSchedulerSet ( )  & &  solver - > hasScheduler ( ) )  {  
			
		
	
		
			
				
					                    // Translate result for ssp matrix to original model
  
			
		
	
		
			
				
					                    auto  const &  sspChoices  =  solver - > getSchedulerChoices ( ) ;  
			
		
	
		
			
				
					                    // We first take care of non-mec states
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -451,7 +461,7 @@ namespace storm { 
			
		
	
		
			
				
					                    //      a) we take an exit (non-MEC) choice at the given state
  
			
		
	
		
			
				
					                    //      b) we have to take a MEC choice at the given state in a way that eventually an exit state of the MEC is reached
  
			
		
	
		
			
				
					                    uint64_t  exitChoiceOffset  =  sspMatrix . getRowGroupIndices ( ) [ numberOfStatesNotInMecs ] ;  
			
		
	
		
			
				
					                    for  ( auto  const &  mec  :  mecDecomposition )  {  
			
		
	
		
			
				
					                    for  ( auto  const &  mec  :  * _ mecDecomposition)  {  
			
		
	
		
			
				
					                        // Get the sspState of this MEC (using one representative mec state)
  
			
		
	
		
			
				
					                        auto  const &  sspState  =  inputToSspStateMap [ mec . begin ( ) - > first ] ;  
			
		
	
		
			
				
					                        uint64_t  sspChoiceIndex  =  sspMatrix . getRowGroupIndices ( ) [ sspState ]  +  sspChoices [ sspState ] ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -474,12 +484,17 @@ namespace storm { 
			
		
	
		
			
				
					                                    _producedOptimalChoices . get ( ) [ stateActions . first ]  =  std : : numeric_limits < uint64_t > : : max ( ) ;  
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                            // Ensure that backwards transitions are available
  
			
		
	
		
			
				
					                            if  ( _backwardTransitions  = =  nullptr )  {  
			
		
	
		
			
				
					                                _computedBackwardTransitions  =  _transitionMatrix . transpose ( true ) ;  
			
		
	
		
			
				
					                                _backwardTransitions  =  & _computedBackwardTransitions ;  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                            // Now start a backwards DFS
  
			
		
	
		
			
				
					                            std : : vector < uint64_t >  stack  =  { originalStateChoice . first } ;  
			
		
	
		
			
				
					                            while  ( ! stack . empty ( ) )  {  
			
		
	
		
			
				
					                                uint64_t  currentState  =  stack . back ( ) ;  
			
		
	
		
			
				
					                                stack . pop_back ( ) ;  
			
		
	
		
			
				
					                                for  ( auto  const &  backwardsTransition  :  _backwardTransitions . getRowGroup ( currentState ) )  {  
			
		
	
		
			
				
					                                for  ( auto  const &  backwardsTransition  :  _backwardTransitions - > getRowGroup ( currentState ) )  {  
			
		
	
		
			
				
					                                    uint64_t  predecessorState  =  backwardsTransition . getColumn ( ) ;  
			
		
	
		
			
				
					                                    if  ( mec . containsState ( predecessorState ) )  {  
			
		
	
		
			
				
					                                        auto &  selectedPredChoice  =  _producedOptimalChoices . get ( ) [ predecessorState ] ;  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -506,7 +521,7 @@ namespace storm { 
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  else  {  
			
		
	
		
			
				
					                    STORM_LOG_ERROR_COND ( ! isProduceSchedulerSet ( ) ,  " Requested to produce a scheduler, but no scheduler was generated. " ) ;  
			
		
	
		
			
				
					                    STORM_LOG_ERROR_COND ( ! this - > isProduceSchedulerSet ( ) ,  " Requested to produce a scheduler, but no scheduler was generated. " ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Prepare result vector.