@ -75,12 +75,12 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    updateDataToCurrentEpoch ( MS ,  PS ,  * minMax ,  consideredObjectives ,  currentEpoch ,  weightVector ,  lowerTimeBoundIt ,  lowerTimeBounds ,  upperTimeBoundIt ,  upperTimeBounds ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Compute the values that can be obtained at probabilistic states in the current time epoch
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    performPSStep ( PS ,  MS ,  * minMax ,  * linEq ,  optimalChoicesAtCurrentEpoch ,   consideredObjectives ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    performPSStep ( PS ,  MS ,  * minMax ,  * linEq ,  optimalChoicesAtCurrentEpoch ,   consideredObjectives ,  weightVector ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Compute values that can be obtained at Markovian states after letting one (digitized) time unit pass.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Only perform such a step if there is time left.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if ( currentEpoch > 0 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        performMSStep ( MS ,  PS ,  consideredObjectives ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        performMSStep ( MS ,  PS ,  consideredObjectives ,  weightVector ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        - - currentEpoch ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        break ;  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				
					@ -355,55 +355,73 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            template  < class  SparseMaModelType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            void  SparseMaPcaaWeightVectorChecker < SparseMaModelType > : : performPSStep ( SubModel &  PS ,  SubModel  const &  MS ,  MinMaxSolverData &  minMax ,  LinEqSolverData &  linEq ,  std : : vector < uint_fast64_t > &  optimalChoicesAtCurrentEpoch ,   storm : : storage : : BitVector  const &  consideredObjectives )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            void  SparseMaPcaaWeightVectorChecker < SparseMaModelType > : : performPSStep ( SubModel &  PS ,  SubModel  const &  MS ,  MinMaxSolverData &  minMax ,  LinEqSolverData &  linEq ,  std : : vector < uint_fast64_t > &  optimalChoicesAtCurrentEpoch ,   storm : : storage : : BitVector  const &  consideredObjectives ,  std : : vector < ValueType >  const &  weightVector )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // compute a choice vector for the probabilistic states that is optimal w.r.t. the weighted reward vector
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                minMax . solver - > solveEquations ( PS . weightedSolutionVector ,  minMax . b ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto  newScheduler  =  minMax . solver - > getScheduler ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // check whether the linEqSolver needs to be updated, i.e., whether the scheduler has changed
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if ( linEq . solver  = =  nullptr  | |  newScheduler - > getChoices ( )  ! =  optimalChoicesAtCurrentEpoch )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if ( consideredObjectives . getNumberOfSetBits ( )  = =  1  & &  ! storm : : utility : : isZero ( weightVector [ * consideredObjectives . begin ( ) ] ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // In this case there is no need to perform the computation on the individual objectives
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    optimalChoicesAtCurrentEpoch  =  newScheduler - > getChoices ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    linEq . solver  =  nullptr ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : SparseMatrix < ValueType >  linEqMatrix  =  PS . toPS . selectRowsFromRowGroups ( optimalChoicesAtCurrentEpoch ,  true ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    linEqMatrix . convertToEquationSystem ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    linEq . solver  =  linEq . factory . create ( std : : move ( linEqMatrix ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    linEq . solver - > setCachingEnabled ( true ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Get the results for the individual objectives.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Note that we do not consider an estimate for each objective (as done in the unbounded phase) since the results from the previous epoch are already pretty close
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for ( auto  objIndex  :  consideredObjectives )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  const &  objectiveRewardVectorPS  =  PS . objectiveRewardVectors [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  const &  objectiveSolutionVectorMS  =  MS . objectiveSolutionVectors [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // compute rhs of equation system, i.e., PS.toMS * x + Rewards
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // To safe some time, only do this for the obtained optimal choices
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  itGroupIndex  =  PS . toPS . getRowGroupIndices ( ) . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  itChoiceOffset  =  optimalChoicesAtCurrentEpoch . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for ( auto &  bValue  :  linEq . b )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        uint_fast64_t  row  =  ( * itGroupIndex )  +  ( * itChoiceOffset ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        bValue  =  objectiveRewardVectorPS [ row ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        for ( auto  const &  entry  :  PS . toMS . getRow ( row ) ) {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            bValue  + =  entry . getValue ( )  *  objectiveSolutionVectorMS [ entry . getColumn ( ) ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  objIndex  =  * consideredObjectives . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    PS . objectiveSolutionVectors [ objIndex ]  =  PS . weightedSolutionVector ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if ( ! storm : : utility : : isOne ( weightVector [ objIndex ] ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        storm : : utility : : vector : : scaleVectorInPlace ( PS . objectiveSolutionVectors [ objIndex ] ,  storm : : utility : : one < ValueType > ( ) / weightVector [ objIndex ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // check whether the linEqSolver needs to be updated, i.e., whether the scheduler has changed
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if ( linEq . solver  = =  nullptr  | |  newScheduler - > getChoices ( )  ! =  optimalChoicesAtCurrentEpoch )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        optimalChoicesAtCurrentEpoch  =  newScheduler - > getChoices ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        linEq . solver  =  nullptr ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        storm : : storage : : SparseMatrix < ValueType >  linEqMatrix  =  PS . toPS . selectRowsFromRowGroups ( optimalChoicesAtCurrentEpoch ,  true ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        linEqMatrix . convertToEquationSystem ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        linEq . solver  =  linEq . factory . create ( std : : move ( linEqMatrix ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        linEq . solver - > setCachingEnabled ( true ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Get the results for the individual objectives.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Note that we do not consider an estimate for each objective (as done in the unbounded phase) since the results from the previous epoch are already pretty close
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for ( auto  objIndex  :  consideredObjectives )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  const &  objectiveRewardVectorPS  =  PS . objectiveRewardVectors [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  const &  objectiveSolutionVectorMS  =  MS . objectiveSolutionVectors [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // compute rhs of equation system, i.e., PS.toMS * x + Rewards
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // To safe some time, only do this for the obtained optimal choices
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  itGroupIndex  =  PS . toPS . getRowGroupIndices ( ) . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  itChoiceOffset  =  optimalChoicesAtCurrentEpoch . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        for ( auto &  bValue  :  linEq . b )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            uint_fast64_t  row  =  ( * itGroupIndex )  +  ( * itChoiceOffset ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            bValue  =  objectiveRewardVectorPS [ row ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            for ( auto  const &  entry  :  PS . toMS . getRow ( row ) ) {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                bValue  + =  entry . getValue ( )  *  objectiveSolutionVectorMS [ entry . getColumn ( ) ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + itGroupIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + itChoiceOffset ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + itGroupIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + itChoiceOffset ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        linEq . solver - > solveEquations ( PS . objectiveSolutionVectors [ objIndex ] ,  linEq . b ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    linEq . solver - > solveEquations ( PS . objectiveSolutionVectors [ objIndex ] ,  linEq . b ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            template  < class  SparseMaModelType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            void  SparseMaPcaaWeightVectorChecker < SparseMaModelType > : : performMSStep ( SubModel &  MS ,  SubModel  const &  PS ,  storm : : storage : : BitVector  const &  consideredObjectives )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            void  SparseMaPcaaWeightVectorChecker < SparseMaModelType > : : performMSStep ( SubModel &  MS ,  SubModel  const &  PS ,  storm : : storage : : BitVector  const &  consideredObjectives ,  std : : vector < ValueType >  const &  weightVector )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                MS . toMS . multiplyWithVector ( MS . weightedSolutionVector ,  MS . auxChoiceValues ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : utility : : vector : : addVectors ( MS . weightedRewardVector ,  MS . auxChoiceValues ,  MS . weightedSolutionVector ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                MS . toPS . multiplyWithVector ( PS . weightedSolutionVector ,  MS . auxChoiceValues ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : utility : : vector : : addVectors ( MS . weightedSolutionVector ,  MS . auxChoiceValues ,  MS . weightedSolutionVector ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for ( auto  objIndex  :  consideredObjectives )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    MS . toMS . multiplyWithVector ( MS . objectiveSolutionVectors [ objIndex ] ,  MS . auxChoiceValues ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : utility : : vector : : addVectors ( MS . objectiveRewardVectors [ objIndex ] ,  MS . auxChoiceValues ,  MS . objectiveSolutionVectors [ objIndex ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    MS . toPS . multiplyWithVector ( PS . objectiveSolutionVectors [ objIndex ] ,  MS . auxChoiceValues ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : utility : : vector : : addVectors ( MS . objectiveSolutionVectors [ objIndex ] ,  MS . auxChoiceValues ,  MS . objectiveSolutionVectors [ objIndex ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if ( consideredObjectives . getNumberOfSetBits ( )  = =  1  & &  ! storm : : utility : : isZero ( weightVector [ * consideredObjectives . begin ( ) ] ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // In this case there is no need to perform the computation on the individual objectives
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  objIndex  =  * consideredObjectives . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    MS . objectiveSolutionVectors [ objIndex ]  =  MS . weightedSolutionVector ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if ( ! storm : : utility : : isOne ( weightVector [ objIndex ] ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        storm : : utility : : vector : : scaleVectorInPlace ( MS . objectiveSolutionVectors [ objIndex ] ,  storm : : utility : : one < ValueType > ( ) / weightVector [ objIndex ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for ( auto  objIndex  :  consideredObjectives )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        MS . toMS . multiplyWithVector ( MS . objectiveSolutionVectors [ objIndex ] ,  MS . auxChoiceValues ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        storm : : utility : : vector : : addVectors ( MS . objectiveRewardVectors [ objIndex ] ,  MS . auxChoiceValues ,  MS . objectiveSolutionVectors [ objIndex ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        MS . toPS . multiplyWithVector ( PS . objectiveSolutionVectors [ objIndex ] ,  MS . auxChoiceValues ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        storm : : utility : : vector : : addVectors ( MS . objectiveSolutionVectors [ objIndex ] ,  MS . auxChoiceValues ,  MS . objectiveSolutionVectors [ objIndex ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }