@ -25,14 +25,19 @@ namespace storm { 
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                STORM_LOG_THROW ( preprocessorResult . rewardFinitenessType  = =  SparseMultiObjectivePreprocessorResult < SparseMdpModelType > : : RewardFinitenessType : : AllFinite ,  storm : : exceptions : : NotSupportedException ,  " There is a scheduler that yields infinite reward for one  objective. This is not supported. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_THROW ( preprocessorResult . preprocessedModel - > getInitialStates ( ) . getNumberOfSetBits ( )  = =  1 ,  storm : : exceptions : : NotSupportedException ,  " The model has multiple initial states. " ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                numSchedChanges  =  0 ;  
			
		
	
		
			
				
					                numCheckedEpochs  =  0 ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < class  SparseMdpModelType >  
			
		
	
		
			
				
					            void  SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : check ( std : : vector < ValueType >  const &  weightVector )  {  
			
		
	
		
			
				
					                auto  initEpoch  =  rewardUnfolding . getStartEpoch ( ) ;  
			
		
	
		
			
				
					                auto  epochOrder  =  rewardUnfolding . getEpochComputationOrder ( initEpoch ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                EpochCheckingData  cachedData ;  
			
		
	
		
			
				
					                for  ( auto  const &  epoch  :  epochOrder )  {  
			
		
	
		
			
				
					                    computeEpochSolution ( epoch ,  weightVector ) ;  
			
		
	
		
			
				
					                    computeEpochSolution ( epoch ,  weightVector ,  cachedData ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                auto  solution  =  rewardUnfolding . getInitialStateResult ( initEpoch ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -45,73 +50,96 @@ namespace storm { 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < class  SparseMdpModelType >  
			
		
	
		
			
				
					            void  SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : computeEpochSolution ( typename  MultiDimensionalRewardUnfolding < ValueType ,  false > : : Epoch  const &  epoch ,  std : : vector < ValueType >  const &  weightVector )  {  
			
		
	
		
			
				
					            void  SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : computeEpochSolution ( typename  MultiDimensionalRewardUnfolding < ValueType ,  false > : : Epoch  const &  epoch ,  std : : vector < ValueType >  const &  weightVector ,  EpochCheckingData &  cachedData )  {  
			
		
	
		
			
				
					                auto &  epochModel  =  rewardUnfolding . setCurrentEpoch ( epoch ) ;  
			
		
	
		
			
				
					                updateCachedData ( epochModel ,  cachedData ) ;  
			
		
	
		
			
				
					                + + numCheckedEpochs ;  
			
		
	
		
			
				
					                swEqBuilding . start ( ) ;  
			
		
	
		
			
				
					                uint64_t  stateSolutionSize  =  this - > objectives . size ( )  +  1 ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                //TODO  result can now be set from the cacheData
  
			
		
	
		
			
				
					                auto &  result  =  epochModel . inStateSolutions ;  
			
		
	
		
			
				
					                result . resize ( epochModel . epochInStates . getNumberOfSetBits ( ) ,  typename  MultiDimensionalRewardUnfolding < ValueType ,  false > : : SolutionType ( stateSolutionSize ) ) ;  
			
		
	
		
			
				
					                result . resize ( epochModel . epochInStates . getNumberOfSetBits ( ) ,  typename  MultiDimensionalRewardUnfolding < ValueType ,  false > : : SolutionType ( this - > objectives . size ( )  +  1 ) ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Formulate a min-max equation system max(A*x+b)=x for the weighted sum of the objectives
  
			
		
	
		
			
				
					                std : : vector < ValueType >  b ( epochModel . epochMatrix . getRowCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                swAux1 . start ( ) ;  
			
		
	
		
			
				
					                assert ( cachedData . bMinMax . capacity ( )  > =  epochModel . epochMatrix . getRowCount ( ) ) ;  
			
		
	
		
			
				
					                assert ( cachedData . xMinMax . size ( )  = =  epochModel . epochMatrix . getRowGroupCount ( ) ) ;  
			
		
	
		
			
				
					                cachedData . bMinMax . assign ( epochModel . epochMatrix . getRowCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                for  ( uint64_t  objIndex  =  0 ;  objIndex  <  this - > objectives . size ( ) ;  + + objIndex )  {  
			
		
	
		
			
				
					                    ValueType  weight  =  storm : : solver : : minimize ( this - > objectives [ objIndex ] . formula - > getOptimalityType ( ) )  ?  - weightVector [ objIndex ]  :  weightVector [ objIndex ] ;  
			
		
	
		
			
				
					                    if  ( ! storm : : utility : : isZero ( weight ) )  {  
			
		
	
		
			
				
					                        std : : vector < ValueType >  const &  objectiveReward  =  epochModel . objectiveRewards [ objIndex ] ;  
			
		
	
		
			
				
					                        for  ( auto  const &  choice  :  epochModel . objectiveRewardFilter [ objIndex ] )  {  
			
		
	
		
			
				
					                            b [ choice ]  + =  weight  *  objectiveReward [ choice ] ;  
			
		
	
		
			
				
					                            cachedData . bMinMax  [ choice ]  + =  weight  *  objectiveReward [ choice ] ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                auto  stepSolutionIt  =  epochModel . stepSolutions . begin ( ) ;  
			
		
	
		
			
				
					                for  ( auto  const &  choice  :  epochModel . stepChoices )  {  
			
		
	
		
			
				
					                    b [ choice ]  + =  stepSolutionIt - > front ( ) ;  
			
		
	
		
			
				
					                    cachedData . bMinMax  [ choice ]  + =  stepSolutionIt - > front ( ) ;  
			
		
	
		
			
				
					                    + + stepSolutionIt ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                swAux1 . stop ( ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Invoke the min max solver
  
			
		
	
		
			
				
					                storm : : solver : : GeneralMinMaxLinearEquationSolverFactory < ValueType >  minMaxSolverFactory ;  
			
		
	
		
			
				
					                auto  minMaxSolver  =  minMaxSolverFactory . create ( epochModel . epochMatrix ) ;  
			
		
	
		
			
				
					                minMaxSolver - > setOptimizationDirection ( storm : : solver : : OptimizationDirection : : Maximize ) ;  
			
		
	
		
			
				
					                minMaxSolver - > setTrackScheduler ( true ) ;  
			
		
	
		
			
				
					                //minMaxSolver->setCachingEnabled(true);
  
			
		
	
		
			
				
					                std : : vector < ValueType >  x ( epochModel . epochMatrix . getRowGroupCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                swEqBuilding . stop ( ) ;  
			
		
	
		
			
				
					                swMinMaxSolving . start ( ) ;  
			
		
	
		
			
				
					                minMaxSolver - > solveEquations ( x ,  b ) ;  
			
		
	
		
			
				
					                cachedData . minMaxSolver - > solveEquations ( cachedData . xMinMax ,  cachedData . bMinMax ) ;  
			
		
	
		
			
				
					                swMinMaxSolving . stop ( ) ;  
			
		
	
		
			
				
					                swEqBuilding . start ( ) ;  
			
		
	
		
			
				
					                auto  resultIt  =  result . begin ( ) ;  
			
		
	
		
			
				
					                for  ( auto  const &  state  :  epochModel . epochInStates )  {  
			
		
	
		
			
				
					                    resultIt - > front ( )  =  x [ state ] ;  
			
		
	
		
			
				
					                    resultIt - > front ( )  =  cachedData . xMinMa x[ state ] ;  
			
		
	
		
			
				
					                    + + resultIt ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Formulate for each objective the linear equation system induced by the performed choices
  
			
		
	
		
			
				
					                auto  const &  choices  =  minMaxSolver - > getSchedulerChoices ( ) ;  
			
		
	
		
			
				
					                // Check whether the linear equation solver needs to be updated
  
			
		
	
		
			
				
					                auto  const &  choices  =  cachedData . minMaxSolver - > getSchedulerChoices ( ) ;  
			
		
	
		
			
				
					                if  ( cachedData . schedulerChoices  ! =  choices )  {  
			
		
	
		
			
				
					                    swAux2 . start ( ) ;  
			
		
	
		
			
				
					                    + + numSchedChanges ;  
			
		
	
		
			
				
					                    cachedData . schedulerChoices  =  choices ;  
			
		
	
		
			
				
					                    storm : : storage : : SparseMatrix < ValueType >  subMatrix  =  epochModel . epochMatrix . selectRowsFromRowGroups ( choices ,  true ) ;  
			
		
	
		
			
				
					                    subMatrix . convertToEquationSystem ( ) ;  
			
		
	
		
			
				
					                    storm : : solver : : GeneralLinearEquationSolverFactory < ValueType >  linEqSolverFactory ;  
			
		
	
		
			
				
					                auto  linEqSolver  =  linEqSolverFactory . create ( std : : move ( subMatrix ) ) ;  
			
		
	
		
			
				
					                b . resize ( choices . size ( ) ) ;  
			
		
	
		
			
				
					                // TODO: start with a better initial guess
  
			
		
	
		
			
				
					                x . resize ( choices . size ( ) ) ;  
			
		
	
		
			
				
					                    cachedData . linEqSolver  =  linEqSolverFactory . create ( std : : move ( subMatrix ) ) ;  
			
		
	
		
			
				
					                    cachedData . linEqSolver - > setCachingEnabled ( true ) ;  
			
		
	
		
			
				
					                    swAux2 . stop ( ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Formulate for each objective the linear equation system induced by the performed choices
  
			
		
	
		
			
				
					                swAux3 . start ( ) ;  
			
		
	
		
			
				
					                assert ( cachedData . bLinEq . size ( )  = =  choices . size ( ) ) ;  
			
		
	
		
			
				
					                for  ( uint64_t  objIndex  =  0 ;  objIndex  <  this - > objectives . size ( ) ;  + + objIndex )  {  
			
		
	
		
			
				
					                    std : : vector < ValueType >  const &  objectiveReward  =  epochModel . objectiveRewards [ objIndex ] ;  
			
		
	
		
			
				
					                    for  ( uint64_t  state  =  0 ;  state  <  choices . size ( ) ;  + + state )  {  
			
		
	
		
			
				
					                        uint64_t  choice  =  epochModel . epochMatrix . getRowGroupIndices ( ) [ state ]  +  choices [ state ] ;  
			
		
	
		
			
				
					                        if  ( epochModel . objectiveRewardFilter [ objIndex ] . get ( choice ) )  {  
			
		
	
		
			
				
					                            b [ state ]  =  objectiveReward [ choice ] ;  
			
		
	
		
			
				
					                    auto  rowGroupIndexIt  =  epochModel . epochMatrix . getRowGroupIndices ( ) . begin ( ) ;  
			
		
	
		
			
				
					                    auto  choiceIt  =  choices . begin ( ) ;  
			
		
	
		
			
				
					                    auto  stepChoiceIt  =  epochModel . stepChoices . begin ( ) ;  
			
		
	
		
			
				
					                    auto  stepSolutionIt  =  epochModel . stepSolutions . begin ( ) ;  
			
		
	
		
			
				
					                    for  ( auto &  b_i  :  cachedData . bLinEq )  {  
			
		
	
		
			
				
					                        uint64_t  i  =  * rowGroupIndexIt  +  * choiceIt ;  
			
		
	
		
			
				
					                        if  ( epochModel . objectiveRewardFilter [ objIndex ] . get ( i ) )  {  
			
		
	
		
			
				
					                            b_i  =  objectiveReward [ i ] ;  
			
		
	
		
			
				
					                        }  else  {  
			
		
	
		
			
				
					                            b [ state ]  =  storm : : utility : : zero < ValueType > ( ) ;  
			
		
	
		
			
				
					                            b_i  =  storm : : utility : : zero < ValueType > ( ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        while  ( * stepChoiceIt  <  i )  {  
			
		
	
		
			
				
					                            + + stepChoiceIt ;  
			
		
	
		
			
				
					                            + + stepSolutionIt ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        if  ( epochModel . stepChoices . get ( choice ) )  {  
			
		
	
		
			
				
					                            b [ state ]  + =  epochModel . stepSolutions [ epochModel . stepChoices . getNumberOfSetBitsBeforeIndex ( choice ) ] [ objIndex  +  1 ] ;  
			
		
	
		
			
				
					                        if  ( i  = =  * stepChoiceIt )  {  
			
		
	
		
			
				
					                            b_i  + =  ( * stepSolutionIt ) [ objIndex  +  1 ] ;  
			
		
	
		
			
				
					                            + + stepChoiceIt ;  
			
		
	
		
			
				
					                            + + stepSolutionIt ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        + + rowGroupIndexIt ;  
			
		
	
		
			
				
					                        + + choiceIt ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    std : : vector < ValueType > &  x  =  cachedData . xLinEq [ objIndex ] ;  
			
		
	
		
			
				
					                    assert ( x . size ( )  = =  choices . size ( ) ) ;  
			
		
	
		
			
				
					                    swEqBuilding . stop ( ) ;  
			
		
	
		
			
				
					                    swLinEqSolving . start ( ) ;  
			
		
	
		
			
				
					                    linEqSolver - > solveEquations ( x ,  b ) ;  
			
		
	
		
			
				
					                    cachedData . linEqSolver - > solveEquations ( x ,  cachedData . bLinEq  ) ;  
			
		
	
		
			
				
					                    swLinEqSolving . stop ( ) ;  
			
		
	
		
			
				
					                    swEqBuilding . start ( ) ;  
			
		
	
		
			
				
					                    resultIt  =  result . begin ( ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -121,10 +149,37 @@ namespace storm { 
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                swEqBuilding . stop ( ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                swAux3 . stop ( ) ;  
			
		
	
		
			
				
					                rewardUnfolding . setSolutionForCurrentEpoch ( ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            template  < class  SparseMdpModelType >  
			
		
	
		
			
				
					            void  SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : updateCachedData ( typename  MultiDimensionalRewardUnfolding < ValueType ,  false > : : EpochModel  const &  epochModel ,  EpochCheckingData &  cachedData )  {  
			
		
	
		
			
				
					                if  ( epochModel . epochMatrixChanged )  {  
			
		
	
		
			
				
					                    swDataUpdate . start ( ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                    // Update the cached MinMaxSolver data
  
			
		
	
		
			
				
					                    cachedData . bMinMax . resize ( epochModel . epochMatrix . getRowCount ( ) ) ;  
			
		
	
		
			
				
					                    cachedData . xMinMax . assign ( epochModel . epochMatrix . getRowGroupCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                    storm : : solver : : GeneralMinMaxLinearEquationSolverFactory < ValueType >  minMaxSolverFactory ;  
			
		
	
		
			
				
					                    cachedData . minMaxSolver  =  minMaxSolverFactory . create ( epochModel . epochMatrix ) ;  
			
		
	
		
			
				
					                    cachedData . minMaxSolver - > setOptimizationDirection ( storm : : solver : : OptimizationDirection : : Maximize ) ;  
			
		
	
		
			
				
					                    cachedData . minMaxSolver - > setTrackScheduler ( true ) ;  
			
		
	
		
			
				
					                    cachedData . minMaxSolver - > setCachingEnabled ( true ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                    // Set the scheduler choices to invalid choice indices so that an update of the linEqSolver is enforced
  
			
		
	
		
			
				
					                    cachedData . schedulerChoices . assign ( epochModel . epochMatrix . getRowGroupCount ( ) ,  std : : numeric_limits < uint64_t > : : max ( ) ) ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    // Update data for linear equation solving
  
			
		
	
		
			
				
					                    cachedData . bLinEq . resize ( epochModel . epochMatrix . getRowGroupCount ( ) ) ;  
			
		
	
		
			
				
					                    cachedData . xLinEq . resize ( this - > objectives . size ( ) ) ;  
			
		
	
		
			
				
					                    for  ( auto &  x_o  :  cachedData . xLinEq )  {  
			
		
	
		
			
				
					                        x_o . assign ( epochModel . epochMatrix . getRowGroupCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    swDataUpdate . stop ( ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template  < class  SparseMdpModelType >  
			
		
	
		
			
				
					            std : : vector < typename  SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : ValueType >  SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : getUnderApproximationOfInitialStateResults ( )  const  {  
			
		
	
		
			
				
					                STORM_LOG_THROW ( underApproxResult ,  storm : : exceptions : : InvalidOperationException ,  " Tried to retrieve results but check(..) has not been called before. " ) ;