@ -90,6 +90,13 @@ namespace storm { 
		
	
		
			
				                    }                     }  
		
	
		
			
				                }                 }  
		
	
		
			
				                                 
		
	
		
			
				                // Set data for LRA objectives (if available)
  
		
	
		
			
				                if  ( ! lraObjectives . empty ( ) )  {  
		
	
		
			
				                    lraMecDecomposition  =  LraMecDecomposition ( ) ;  
		
	
		
			
				                    lraMecDecomposition - > mecs  =  storm : : storage : : MaximalEndComponentDecomposition < ValueType > ( transitionMatrix ,  transitionMatrix . transpose ( true ) ,  totalReward0EStates ,  actionsWithoutRewardInUnboundedPhase ) ;  
		
	
		
			
				                    lraMecDecomposition - > auxMecValues . resize ( lraMecDecomposition - > mecs . size ( ) ) ;  
		
	
		
			
				                }  
		
	
		
			
				                 
		
	
		
			
				                // initialize data for the results
                 // initialize data for the results
  
		
	
		
			
				                checkHasBeenCalled  =  false ;                 checkHasBeenCalled  =  false ;  
		
	
		
			
				                objectiveResults . resize ( this - > objectives . size ( ) ) ;                 objectiveResults . resize ( this - > objectives . size ( ) ) ;  
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -98,21 +105,37 @@ namespace storm { 
		
	
		
			
				                optimalChoices . resize ( transitionMatrix . getRowGroupCount ( ) ,  0 ) ;                 optimalChoices . resize ( transitionMatrix . getRowGroupCount ( ) ,  0 ) ;  
		
	
		
			
				            }             }  
		
	
		
			
				
 
		
	
		
			
				             
		
	
		
			
				            template  < class  SparseModelType >             template  < class  SparseModelType >  
		
	
		
			
				            void  StandardPcaaWeightVectorChecker < SparseModelType > : : check ( Environment  const &  env ,  std : : vector < ValueType >  const &  weightVector )  {             void  StandardPcaaWeightVectorChecker < SparseModelType > : : check ( Environment  const &  env ,  std : : vector < ValueType >  const &  weightVector )  {  
		
	
		
			
				                checkHasBeenCalled  =  true ;                 checkHasBeenCalled  =  true ;  
		
	
		
			
				                STORM_LOG_INFO ( " Invoked WeightVectorChecker with weights  "  < <  std : : endl  < <  " \t "  < <  storm : : utility : : vector : : toString ( storm : : utility : : vector : : convertNumericVector < double > ( weightVector ) ) ) ;                 STORM_LOG_INFO ( " Invoked WeightVectorChecker with weights  "  < <  std : : endl  < <  " \t "  < <  storm : : utility : : vector : : toString ( storm : : utility : : vector : : convertNumericVector < double > ( weightVector ) ) ) ;  
		
	
		
			
				                                 
		
	
		
			
				                // Prepare and invoke weighted infinite horizon (long run average) phase
  
		
	
		
			
				                std : : vector < ValueType >  weightedRewardVector ( transitionMatrix . getRowCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;                 std : : vector < ValueType >  weightedRewardVector ( transitionMatrix . getRowCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
		
	
		
			
				                for  ( auto  objIndex  :  objectivesWithNoUpperTimeBound )  {  
		
	
		
			
				                if  ( ! lraObjectives . empty ( ) )  {  
		
	
		
			
				                    boost : : optional < std : : vector < ValueType > >  weightedStateRewardVector ;  
		
	
		
			
				                    for  ( auto  objIndex  :  lraObjectives )  {  
		
	
		
			
				                        ValueType  weight  =  storm : : solver : : minimize ( this - > objectives [ objIndex ] . formula - > getOptimalityType ( ) )  ?  - weightVector [ objIndex ]  :  weightVector [ objIndex ] ;  
		
	
		
			
				                        storm : : utility : : vector : : addScaledVector ( weightedRewardVector ,  actionRewards [ objIndex ] ,  weight ) ;  
		
	
		
			
				                        if  ( ! stateRewards [ objIndex ] . empty ( ) )  {  
		
	
		
			
				                            weightedStateRewardVector - > resize ( transitionMatrix . getRowGroupCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
		
	
		
			
				                            storm : : utility : : vector : : addScaledVector ( weightedStateRewardVector . get ( ) ,  stateRewards [ objIndex ] ,  weight ) ;  
		
	
		
			
				                        }  
		
	
		
			
				                    }  
		
	
		
			
				                    infiniteHorizonWeightedPhase ( env ,  weightedRewardVector ,  weightedStateRewardVector ) ;  
		
	
		
			
				                    // Clear all values of the weighted reward vector
  
		
	
		
			
				                    weightedRewardVector . assign ( weightedRewardVector . size ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
		
	
		
			
				                }  
		
	
		
			
				                 
		
	
		
			
				                // Prepare and invoke weighted indefinite horizon (unbounded total reward) phase
  
		
	
		
			
				                auto  totalRewardObjectives  =  objectivesWithNoUpperTimeBound  &  ~ lraObjectives ;  
		
	
		
			
				                for  ( auto  objIndex  :  totalRewardObjectives )  {  
		
	
		
			
				                    if  ( storm : : solver : : minimize ( this - > objectives [ objIndex ] . formula - > getOptimalityType ( ) ) )  {                     if  ( storm : : solver : : minimize ( this - > objectives [ objIndex ] . formula - > getOptimalityType ( ) ) )  {  
		
	
		
			
				                        storm : : utility : : vector : : addScaledVector ( weightedRewardVector ,  actionRewards [ objIndex ] ,  - weightVector [ objIndex ] ) ;                         storm : : utility : : vector : : addScaledVector ( weightedRewardVector ,  actionRewards [ objIndex ] ,  - weightVector [ objIndex ] ) ;  
		
	
		
			
				                    }  else  {                     }  else  {  
		
	
		
			
				                        storm : : utility : : vector : : addScaledVector ( weightedRewardVector ,  actionRewards [ objIndex ] ,  weightVector [ objIndex ] ) ;                         storm : : utility : : vector : : addScaledVector ( weightedRewardVector ,  actionRewards [ objIndex ] ,  weightVector [ objIndex ] ) ;  
		
	
		
			
				                    }                     }  
		
	
		
			
				                }                 }  
		
	
		
			
				                 
		
	
		
			
				                unboundedWeightedPhase ( env ,  weightedRewardVector ,  weightVector ) ;                 unboundedWeightedPhase ( env ,  weightedRewardVector ,  weightVector ) ;  
		
	
		
			
				                                 
		
	
		
			
				                unboundedIndividualPhase ( env ,  weightVector ) ;                 unboundedIndividualPhase ( env ,  weightVector ) ;  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -282,9 +305,32 @@ namespace storm { 
		
	
		
			
				                return  result ;                 return  result ;  
		
	
		
			
				            }             }  
		
	
		
			
				                         
		
	
		
			
				            template  < class  SparseModelType >  
		
	
		
			
				            void  StandardPcaaWeightVectorChecker < SparseModelType > : : infiniteHorizonWeightedPhase ( Environment  const &  env ,  std : : vector < ValueType >  const &  weightedActionRewardVector ,  boost : : optional < std : : vector < ValueType > >  const &  weightedStateRewardVector )  {  
		
	
		
			
				                // Compute the optimal (weighted) lra value for each mec, keeping track of the optimal choices
  
		
	
		
			
				                STORM_LOG_ASSERT ( lraMecDecomposition ,  " Mec decomposition for lra computations not initialized. " ) ;  
		
	
		
			
				                storm : : modelchecker : : helper : : SparseNondeterministicInfiniteHorizonHelper < ValueType >  helper  =  createNondetInfiniteHorizonHelper ( ) ;  
		
	
		
			
				                helper . provideLongRunComponentDecomposition ( lraMecDecomposition - > mecs ) ;  
		
	
		
			
				                helper . setOptimizationDirection ( storm : : solver : : OptimizationDirection : : Maximize ) ;  
		
	
		
			
				                helper . setProduceScheduler ( true ) ;  
		
	
		
			
				                for  ( uint64_t  mecIndex  =  0 ;  mecIndex  <  lraMecDecomposition - > mecs . size ( ) ;  + + mecIndex )  {  
		
	
		
			
				                    auto  const &  mec  =  lraMecDecomposition - > mecs [ mecIndex ] ;  
		
	
		
			
				                    auto  actionValueGetter  =  [ & weightedActionRewardVector ]  ( uint64_t  const &  a )  {  return  weightedActionRewardVector [ a ] ;  } ;  
		
	
		
			
				                    typename  storm : : modelchecker : : helper : : SparseNondeterministicInfiniteHorizonHelper < ValueType > : : ValueGetter  stateValueGetter ;  
		
	
		
			
				                    if  ( weightedStateRewardVector )  {  
		
	
		
			
				                        stateValueGetter  =  [ & weightedStateRewardVector ]  ( uint64_t  const &  s )  {  return  weightedStateRewardVector . get ( ) [ s ] ;  } ;  
		
	
		
			
				                    }  else  {  
		
	
		
			
				                        stateValueGetter  =  [ ]  ( uint64_t  const & )  {  return  storm : : utility : : zero < ValueType > ( ) ;  } ;  
		
	
		
			
				                    }  
		
	
		
			
				                    lraMecDecomposition - > auxMecValues [ mecIndex ]  =  helper . computeLraForComponent ( env ,  stateValueGetter ,  actionValueGetter ,  mec ) ;  
		
	
		
			
				                }  
		
	
		
			
				                // Extract the produced optimal choices for the MECs
  
		
	
		
			
				                this - > optimalChoices  =  std : : move ( helper . getProducedOptimalChoices ( ) ) ;  
		
	
		
			
				            }  
		
	
		
			
				             
		
	
		
			
				            template  < class  SparseModelType >             template  < class  SparseModelType >  
		
	
		
			
				            void  StandardPcaaWeightVectorChecker < SparseModelType > : : unboundedWeightedPhase ( Environment  const &  env ,  std : : vector < ValueType >  const &  weightedRewardVector ,  std : : vector < ValueType >  const &  weightVector )  {             void  StandardPcaaWeightVectorChecker < SparseModelType > : : unboundedWeightedPhase ( Environment  const &  env ,  std : : vector < ValueType >  const &  weightedRewardVector ,  std : : vector < ValueType >  const &  weightVector )  {  
		
	
		
			
				                if  ( this - > objectivesWithNoUpperTimeBound . empty ( )  | |  ! storm : : utility : : vector : : hasNonZeroEntry ( weightedRewardVector ) )  {  
		
	
		
			
				                if  ( this - > objectivesWithNoUpperTimeBound . empty ( )  | |  ( this - > lraObjectives . empty ( )  & &  ! storm : : utility : : vector : : hasNonZeroEntry ( weightedRewardVector ) ) )  {  
		
	
		
			
				                    this - > weightedResult  =  std : : vector < ValueType > ( transitionMatrix . getRowGroupCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;                     this - > weightedResult  =  std : : vector < ValueType > ( transitionMatrix . getRowGroupCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
		
	
		
			
				                    // Get an arbitrary scheduler that yields finite reward for all objectives
                     // Get an arbitrary scheduler that yields finite reward for all objectives
  
		
	
		
			
				                    this - > optimalChoices  =  computeSchedulerFinitelyOften ( transitionMatrix ,  transitionMatrix . transpose ( true ) ,  ~ actionsWithoutRewardInUnboundedPhase ) ;                     this - > optimalChoices  =  computeSchedulerFinitelyOften ( transitionMatrix ,  transitionMatrix . transpose ( true ) ,  ~ actionsWithoutRewardInUnboundedPhase ) ;  
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -293,7 +339,30 @@ namespace storm { 
		
	
		
			
				                                 
		
	
		
			
				                updateEcQuotient ( weightedRewardVector ) ;                 updateEcQuotient ( weightedRewardVector ) ;  
		
	
		
			
				                                 
		
	
		
			
				                // Set up the choice values
  
		
	
		
			
				                storm : : utility : : vector : : selectVectorValues ( ecQuotient - > auxChoiceValues ,  ecQuotient - > ecqToOriginalChoiceMapping ,  weightedRewardVector ) ;                 storm : : utility : : vector : : selectVectorValues ( ecQuotient - > auxChoiceValues ,  ecQuotient - > ecqToOriginalChoiceMapping ,  weightedRewardVector ) ;  
		
	
		
			
				                if  ( ! lraObjectives . empty ( ) )  {  
		
	
		
			
				                    // We also need to assign a value for each ecQuotientChoice that corresponds to "staying" in the eliminated EC. (at this point these choices should all have a value of zero).
  
		
	
		
			
				                    // Since each of the eliminated ECs has to contain *at least* one LRA EC, we need to find the largest value among the contained LRA ECs
  
		
	
		
			
				                    storm : : storage : : BitVector  foundEcqChoices ( ecQuotient - > matrix . getRowCount ( ) ,  false ) ;  // keeps track of choices we have already seen before
  
		
	
		
			
				                    for  ( uint64_t  mecIndex  =  0 ;  mecIndex  <  lraMecDecomposition - > mecs . size ( ) ;  + + mecIndex )  {  
		
	
		
			
				                        auto  const &  mec  =  lraMecDecomposition - > mecs [ mecIndex ] ;  
		
	
		
			
				                        auto  const &  mecValue  =  lraMecDecomposition - > auxMecValues [ mecIndex ] ;  
		
	
		
			
				                        uint64_t  ecqState  =  ecQuotient - > originalToEcqStateMapping [ mec . begin ( ) - > first ] ;  
		
	
		
			
				                        uint64_t  ecqChoice  =  ecQuotient - > ecqStayInEcChoices . getNextSetIndex ( ecQuotient - > matrix . getRowGroupIndices ( ) [ ecqState ] ) ;  
		
	
		
			
				                        STORM_LOG_ASSERT ( ecqChoice  <  ecQuotient - > matrix . getRowGroupIndices ( ) [ ecqState  +  1 ] ,  " Unable to find choice that represents staying inside the (eliminated) ec. " ) ;  
		
	
		
			
				                        auto &  ecqChoiceValue  =  ecQuotient - > auxChoiceValues [ ecqChoice ] ;  
		
	
		
			
				                        if  ( foundEcqChoices . get ( ecqChoice ) )  {  
		
	
		
			
				                            ecqChoiceValue  =  std : : max ( ecqChoiceValue ,  mecValue ) ;  
		
	
		
			
				                        }  else  {  
		
	
		
			
				                            STORM_LOG_ASSERT ( storm : : utility : : isZero ( ecqChoiceValue ) ,  " Expected a total reward of zero for choices that represent staying in an EC for ever. " ) ;  
		
	
		
			
				                            ecqChoiceValue  =  mecValue ;  
		
	
		
			
				                            foundEcqChoices . set ( ecqChoice ,  true ) ;  
		
	
		
			
				                        }  
		
	
		
			
				                    }  
		
	
		
			
				                }  
		
	
		
			
				                 
		
	
		
			
				                // TODO: Continue to integrate LRA here (solver bounds need to be set correctly)
  
		
	
		
			
				                                 
		
	
		
			
				                storm : : solver : : GeneralMinMaxLinearEquationSolverFactory < ValueType >  solverFactory ;                 storm : : solver : : GeneralMinMaxLinearEquationSolverFactory < ValueType >  solverFactory ;  
		
	
		
			
				                std : : unique_ptr < storm : : solver : : MinMaxLinearEquationSolver < ValueType > >  solver  =  solverFactory . create ( env ,  ecQuotient - > matrix ) ;                 std : : unique_ptr < storm : : solver : : MinMaxLinearEquationSolver < ValueType > >  solver  =  solverFactory . create ( env ,  ecQuotient - > matrix ) ;  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -420,20 +489,32 @@ namespace storm { 
		
	
		
			
				            template  < class  SparseModelType >             template  < class  SparseModelType >  
		
	
		
			
				            void  StandardPcaaWeightVectorChecker < SparseModelType > : : updateEcQuotient ( std : : vector < ValueType >  const &  weightedRewardVector )  {             void  StandardPcaaWeightVectorChecker < SparseModelType > : : updateEcQuotient ( std : : vector < ValueType >  const &  weightedRewardVector )  {  
		
	
		
			
				                // Check whether we need to update the currently cached ecElimResult
                 // Check whether we need to update the currently cached ecElimResult
  
		
	
		
			
				                storm : : storage : : BitVector  newReward0Choices  =  storm : : utility : : vector : : filterZero ( weightedRewardVector ) ;  
		
	
		
			
				                storm : : storage : : BitVector  newTotalReward0Choices  =  storm : : utility : : vector : : filterZero ( weightedRewardVector ) ;  
		
	
		
			
				                storm : : storage : : BitVector  zeroLraRewardChoices ( weightedRewardVector . size ( ) ,  true ) ;  
		
	
		
			
				                if  ( lraMecDecomposition )  {  
		
	
		
			
				                    for  ( uint64_t  mecIndex  =  0 ;  mecIndex  <  lraMecDecomposition - > mecs . size ( ) ;  + + mecIndex )  {  
		
	
		
			
				                        if  ( ! storm : : utility : : isZero ( lraMecDecomposition - > auxMecValues [ mecIndex ] ) )  {  
		
	
		
			
				                            // The mec has a non-zero value, so flag all its choices as non-zero
  
		
	
		
			
				                            auto  const &  mec  =  lraMecDecomposition - > mecs [ mecIndex ] ;  
		
	
		
			
				                            for  ( auto  const &  stateChoices  :  mec )  {  
		
	
		
			
				                                for  ( auto  const &  choice  :  stateChoices . second )  {  
		
	
		
			
				                                    zeroLraRewardChoices . set ( choice ,  false ) ;  
		
	
		
			
				                                }  
		
	
		
			
				                            }  
		
	
		
			
				                        }  
		
	
		
			
				                    }  
		
	
		
			
				                }  
		
	
		
			
				                storm : : storage : : BitVector  newReward0Choices  =  newTotalReward0Choices  &  zeroLraRewardChoices ;  
		
	
		
			
				                if  ( ! ecQuotient  | |  ecQuotient - > origReward0Choices  ! =  newReward0Choices )  {                 if  ( ! ecQuotient  | |  ecQuotient - > origReward0Choices  ! =  newReward0Choices )  {  
		
	
		
			
				                                         
		
	
		
			
				                    // It is sufficient to consider the states from which a transition with non-zero reward is reachable. (The remaining states always have reward zero).
                     // It is sufficient to consider the states from which a transition with non-zero reward is reachable. (The remaining states always have reward zero).
  
		
	
		
			
				                    storm : : storage : : BitVector  nonZeroRewardStates ( transitionMatrix . getRowGroupCount ( ) ,  false ) ;  
		
	
		
			
				                    for  ( uint_fast64_t  state  =  0 ;  state  <  transitionMatrix . getRowGroupCount ( ) ;  + + state ) {  
		
	
		
			
				                        if  ( newReward0Choices . getNextUnsetIndex ( transitionMatrix . getRowGroupIndices ( ) [ state ] )  <  transitionMatrix . getRowGroupIndices ( ) [ state + 1 ] )  {  
		
	
		
			
				                            nonZeroRewardStates . set ( state ) ;  
		
	
		
			
				                        }  
		
	
		
			
				                    }  
		
	
		
			
				                    auto  nonZeroRewardStates  =  transitionMatrix . getRowGroupFilter ( newReward0Choices ,  true ) ;  
		
	
		
			
				                    nonZeroRewardStates . complement ( ) ;  
		
	
		
			
				                    storm : : storage : : BitVector  subsystemStates  =  storm : : utility : : graph : : performProbGreater0E ( transitionMatrix . transpose ( true ) ,  storm : : storage : : BitVector ( transitionMatrix . getRowGroupCount ( ) ,  true ) ,  nonZeroRewardStates ) ;                     storm : : storage : : BitVector  subsystemStates  =  storm : : utility : : graph : : performProbGreater0E ( transitionMatrix . transpose ( true ) ,  storm : : storage : : BitVector ( transitionMatrix . getRowGroupCount ( ) ,  true ) ,  nonZeroRewardStates ) ;  
		
	
		
			
				                                 
		
	
		
			
				                    // Remove neutral end components, i.e., ECs in which no reward is earned.
  
		
	
		
			
				                    auto  ecElimResult  =  storm : : transformer : : EndComponentEliminator < ValueType > : : transform ( transitionMatrix ,  subsystemStates ,  ecChoicesHint  &  newReward0Choices ,  reward0EStates ) ;  
		
	
		
			
				                    // Remove neutral end components, i.e., ECs in which no total reward is earned.
  
		
	
		
			
				                    // Note that such ECs contain one (or maybe more) LRA ECs.
  
		
	
		
			
				                    auto  ecElimResult  =  storm : : transformer : : EndComponentEliminator < ValueType > : : transform ( transitionMatrix ,  subsystemStates ,  ecChoicesHint  &  newTotalReward0Choices ,  totalReward0EStates ) ;  
		
	
		
			
				                                         
		
	
		
			
				                    storm : : storage : : BitVector  rowsWithSumLessOne ( ecElimResult . matrix . getRowCount ( ) ,  false ) ;                     storm : : storage : : BitVector  rowsWithSumLessOne ( ecElimResult . matrix . getRowCount ( ) ,  false ) ;  
		
	
		
			
				                    for  ( uint64_t  row  =  0 ;  row  <  rowsWithSumLessOne . size ( ) ;  + + row )  {                     for  ( uint64_t  row  =  0 ;  row  <  rowsWithSumLessOne . size ( ) ;  + + row )  {  
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -453,11 +534,10 @@ namespace storm { 
		
	
		
			
				                    ecQuotient - > matrix  =  std : : move ( ecElimResult . matrix ) ;                     ecQuotient - > matrix  =  std : : move ( ecElimResult . matrix ) ;  
		
	
		
			
				                    ecQuotient - > ecqToOriginalChoiceMapping  =  std : : move ( ecElimResult . newToOldRowMapping ) ;                     ecQuotient - > ecqToOriginalChoiceMapping  =  std : : move ( ecElimResult . newToOldRowMapping ) ;  
		
	
		
			
				                    ecQuotient - > originalToEcqStateMapping  =  std : : move ( ecElimResult . oldToNewStateMapping ) ;                     ecQuotient - > originalToEcqStateMapping  =  std : : move ( ecElimResult . oldToNewStateMapping ) ;  
		
	
		
			
				                    ecQuotient - > ecqStayInEcChoices  =  std : : move ( ecElimResult . sinkRows ) ;  
		
	
		
			
				                    ecQuotient - > origReward0Choices  =  std : : move ( newReward0Choices ) ;                     ecQuotient - > origReward0Choices  =  std : : move ( newReward0Choices ) ;  
		
	
		
			
				                    ecQuotient - > rowsWithSumLessOne  =  std : : move ( rowsWithSumLessOne ) ;                     ecQuotient - > rowsWithSumLessOne  =  std : : move ( rowsWithSumLessOne ) ;  
		
	
		
			
				                    ecQuotient - > auxStateValues . reserve ( transitionMatrix . getRowGroupCount ( ) ) ;  
		
	
		
			
				                    ecQuotient - > auxStateValues . resize ( ecQuotient - > matrix . getRowGroupCount ( ) ) ;                     ecQuotient - > auxStateValues . resize ( ecQuotient - > matrix . getRowGroupCount ( ) ) ;  
		
	
		
			
				                    ecQuotient - > auxChoiceValues . reserve ( transitionMatrix . getRowCount ( ) ) ;  
		
	
		
			
				                    ecQuotient - > auxChoiceValues . resize ( ecQuotient - > matrix . getRowCount ( ) ) ;                     ecQuotient - > auxChoiceValues . resize ( ecQuotient - > matrix . getRowCount ( ) ) ;  
		
	
		
			
				                }                 }  
		
	
		
			
				            }             }