@ -85,136 +85,200 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            template  < class  SparseMdpModelType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            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 ,  weightVector ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                + + numCheckedEpochs ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swEqBuilding . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                + + numCheckedEpochs ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swEpochModelBuild . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto &  epochModel  =  rewardUnfolding . setCurrentEpoch ( epoch ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swEpochModelBuild . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swEpochModelAnalysis . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : vector < typename  MultiDimensionalRewardUnfolding < ValueType ,  false > : : SolutionType >  result ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                result . reserve ( epochModel . epochInStates . getNumberOfSetBits ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                uint64_t  solutionSize  =  this - > objectives . size ( )  +  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Formulate a min-max equation system max(A*x+b)=x for the weighted sum of the objectives
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                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 ] )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            cachedData . bMinMax [ choice ]  + =  weight  *  objectiveReward [ choice ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // If the epoch matrix is empty we do not need to solve linear equation systems
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( epochModel . epochMatrix . getEntryCount ( )  = =  0 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : vector < ValueType >  weights  =  weightVector ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( uint64_t  objIndex  =  0 ;  objIndex  <  this - > objectives . size ( ) ;  + + objIndex )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( storm : : solver : : minimize ( this - > objectives [ objIndex ] . formula - > getOptimalityType ( ) ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            weights [ objIndex ]  * =  - storm : : utility : : one < ValueType > ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto  stepSolutionIt  =  epochModel . stepSolutions . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  const &  choice  :  epochModel . stepChoices )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    cachedData . bMinMax [ choice ]  + =  stepSolutionIt - > front ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    + + stepSolutionIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swAux1 . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Invoke the min max solver
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swEqBuilding . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swMinMaxSolving . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                cachedData . minMaxSolver - > solveEquations ( cachedData . xMinMax ,  cachedData . bMinMax ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swMinMaxSolving . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swEqBuilding . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  const &  state  :  epochModel . epochInStates )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    result . emplace_back ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    result . back ( ) . reserve ( solutionSize ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    result . back ( ) . push_back ( cachedData . xMinMax [ state ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Check whether the linear equation solver needs to be updated
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto  const &  choices  =  cachedData . minMaxSolver - > getSchedulerChoices ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( cachedData . schedulerChoices  ! =  choices )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : vector < uint64_t >  choicesTmp  =  choices ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    cachedData . minMaxSolver - > setInitialScheduler ( std : : move ( choicesTmp ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    swAux2 . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    + + numSchedChanges ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    cachedData . schedulerChoices  =  choices ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : solver : : GeneralLinearEquationSolverFactory < ValueType >  linEqSolverFactory ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bool  needEquationSystem  =  linEqSolverFactory . getEquationProblemFormat ( )  = =  storm : : solver : : LinearEquationSolverProblemFormat : : EquationSystem ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : SparseMatrix < ValueType >  subMatrix  =  epochModel . epochMatrix . selectRowsFromRowGroups ( choices ,  needEquationSystem ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( needEquationSystem )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        subMatrix . convertToEquationSystem ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    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 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  const &  obj  =  this - > objectives [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : vector < ValueType >  const &  objectiveReward  =  epochModel . objectiveRewards [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  rowGroupIndexIt  =  epochModel . epochMatrix . getRowGroupIndices ( ) . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  choiceIt  =  choices . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  stepChoiceIt  =  epochModel . stepChoices . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  stepSolutionIt  =  epochModel . stepSolutions . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : vector < ValueType > &  x  =  cachedData . xLinEq [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  xIt  =  x . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( auto &  b_i  :  cachedData . bLinEq )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        uint64_t  i  =  * rowGroupIndexIt  +  * choiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( epochModel . objectiveRewardFilter [ objIndex ] . get ( i ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            b_i  =  objectiveReward [ i ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            b_i  =  storm : : utility : : zero < ValueType > ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        while  ( * stepChoiceIt  <  i )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + stepChoiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + stepSolutionIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( i  = =  * stepChoiceIt )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            b_i  + =  ( * stepSolutionIt ) [ objIndex  +  1 ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + stepChoiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + stepSolutionIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  stepChoiceIt  =  epochModel . stepChoices . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( auto  const &  state  :  epochModel . epochInStates )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // Obtain the best choice for this state according to the weighted combination of objectives
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        ValueType  bestValue ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        uint64_t  bestChoice  =  std : : numeric_limits < uint64_t > : : max ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  bestChoiceStepSolutionIt  =  epochModel . stepSolutions . end ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        uint64_t  lastChoice  =  epochModel . epochMatrix . getRowGroupIndices ( ) [ state  +  1 ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        bool  firstChoice  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        for  ( uint64_t  choice  =  epochModel . epochMatrix . getRowGroupIndices ( ) [ state ] ;  choice  <  lastChoice ;  + + choice )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            ValueType  choiceValue  =  storm : : utility : : zero < ValueType > ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            // Obtain the (weighted) objective rewards
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            for  ( uint64_t  objIndex  =  0 ;  objIndex  <  this - > objectives . size ( ) ;  + + objIndex )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                if  ( epochModel . objectiveRewardFilter [ objIndex ] . get ( choice ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    choiceValue  + =  weights [ objIndex ]  *  epochModel . objectiveRewards [ objIndex ] [ choice ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            // Obtain the step solution if this is a step choice
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            while  ( * stepChoiceIt  <  choice )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                + + stepChoiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                + + stepSolutionIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            if  ( * stepChoiceIt  = =  choice )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                choiceValue  + =  stepSolutionIt - > front ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                // Check if this choice is better
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                if  ( firstChoice  | |  choiceValue  >  bestValue )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    bestValue  =  std : : move ( choiceValue ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    bestChoice  =  choice ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    bestChoiceStepSolutionIt  =  stepSolutionIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  else  if  ( firstChoice  | |  choiceValue  >  bestValue )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                bestValue  =  std : : move ( choiceValue ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                bestChoice  =  choice ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                bestChoiceStepSolutionIt  =  epochModel . stepSolutions . end ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            firstChoice  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // We can already set x_i correctly if row i is empty.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // Appearingly, some linear equation solvers struggle to converge otherwise.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( epochModel . epochMatrix . getRow ( i ) . getNumberOfEntries ( )  = =  0 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            * xIt  =  b_i ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // Insert the solution w.r.t. this choice
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        result . emplace_back ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        result . back ( ) . reserve ( solutionSize ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        result . back ( ) . push_back ( std : : move ( bestValue ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( bestChoiceStepSolutionIt  ! =  epochModel . stepSolutions . end ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            for  ( uint64_t  objIndex  =  0 ;  objIndex  <  this - > objectives . size ( ) ;  + + objIndex )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                if  ( epochModel . objectiveRewardFilter [ objIndex ] . get ( bestChoice ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    result . back ( ) . push_back ( ( epochModel . objectiveRewards [ objIndex ] [ bestChoice ]  +  ( * bestChoiceStepSolutionIt ) [ objIndex  +  1 ] ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    result . back ( ) . push_back ( ( * bestChoiceStepSolutionIt ) [ objIndex  +  1 ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            for  ( uint64_t  objIndex  =  0 ;  objIndex  <  this - > objectives . size ( ) ;  + + objIndex )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                if  ( epochModel . objectiveRewardFilter [ objIndex ] . get ( bestChoice ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    result . back ( ) . push_back ( ( epochModel . objectiveRewards [ objIndex ] [ bestChoice ] ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    result . back ( ) . push_back ( storm : : utility : : zero < ValueType > ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + xIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + rowGroupIndexIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + choiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    assert ( x . size ( )  = =  choices . size ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  req  =  cachedData . linEqSolver - > getRequirements ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    cachedData . linEqSolver - > clearBounds ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( obj . lowerResultBound )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        req . clearLowerBounds ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . linEqSolver - > setLowerBound ( * obj . lowerResultBound ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    updateCachedData ( epochModel ,  cachedData ,  weightVector ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Formulate a min-max equation system max(A*x+b)=x for the weighted sum of the objectives
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    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 ] )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                cachedData . bMinMax [ choice ]  + =  weight  *  objectiveReward [ choice ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( obj . upperResultBound )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . linEqSolver - > setUpperBound ( * obj . upperResultBound ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        req . clearUpperBounds ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  stepSolutionIt  =  epochModel . stepSolutions . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( auto  const &  choice  :  epochModel . stepChoices )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . bMinMax [ choice ]  + =  stepSolutionIt - > front ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + stepSolutionIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    STORM_LOG_THROW ( req . empty ( ) ,  storm : : exceptions : : UncheckedRequirementException ,  " At least one requirement of the LinearEquationSolver was not met. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    swEqBuilding . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    swLinEqSolving . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    cachedData . linEqSolver - > solveEquations ( x ,  cachedData . bLinEq ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    swLinEqSolving . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    swEqBuilding . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  resultIt  =  result . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Invoke the min max solver
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    cachedData . minMaxSolver - > solveEquations ( cachedData . xMinMax ,  cachedData . bMinMax ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( auto  const &  state  :  epochModel . epochInStates )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        resultIt - > push_back ( x [ state ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + resultIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        result . emplace_back ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        result . back ( ) . reserve ( solutionSize ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        result . back ( ) . push_back ( cachedData . xMinMax [ state ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Check whether the linear equation solver needs to be updated
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  const &  choices  =  cachedData . minMaxSolver - > getSchedulerChoices ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( cachedData . schedulerChoices  ! =  choices )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        std : : vector < uint64_t >  choicesTmp  =  choices ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . minMaxSolver - > setInitialScheduler ( std : : move ( choicesTmp ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + numSchedChanges ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . schedulerChoices  =  choices ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        storm : : solver : : GeneralLinearEquationSolverFactory < ValueType >  linEqSolverFactory ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        bool  needEquationSystem  =  linEqSolverFactory . getEquationProblemFormat ( )  = =  storm : : solver : : LinearEquationSolverProblemFormat : : EquationSystem ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        storm : : storage : : SparseMatrix < ValueType >  subMatrix  =  epochModel . epochMatrix . selectRowsFromRowGroups ( choices ,  needEquationSystem ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( needEquationSystem )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            subMatrix . convertToEquationSystem ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . linEqSolver  =  linEqSolverFactory . create ( std : : move ( subMatrix ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . linEqSolver - > setCachingEnabled ( true ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Formulate for each objective the linear equation system induced by the performed choices
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    assert ( cachedData . bLinEq . size ( )  = =  choices . size ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( uint64_t  objIndex  =  0 ;  objIndex  <  this - > objectives . size ( ) ;  + + objIndex )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  const &  obj  =  this - > objectives [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        std : : vector < ValueType >  const &  objectiveReward  =  epochModel . objectiveRewards [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  rowGroupIndexIt  =  epochModel . epochMatrix . getRowGroupIndices ( ) . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  choiceIt  =  choices . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  stepChoiceIt  =  epochModel . stepChoices . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  stepSolutionIt  =  epochModel . stepSolutions . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        std : : vector < ValueType > &  x  =  cachedData . xLinEq [ objIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  xIt  =  x . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        for  ( auto &  b_i  :  cachedData . bLinEq )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            uint64_t  i  =  * rowGroupIndexIt  +  * choiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            if  ( epochModel . objectiveRewardFilter [ objIndex ] . get ( i ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                b_i  =  objectiveReward [ i ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                b_i  =  storm : : utility : : zero < ValueType > ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            while  ( * stepChoiceIt  <  i )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                + + stepChoiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                + + stepSolutionIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            if  ( i  = =  * stepChoiceIt )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                b_i  + =  ( * stepSolutionIt ) [ objIndex  +  1 ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                + + stepChoiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                + + stepSolutionIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            // We can already set x_i correctly if row i is empty.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            // Appearingly, some linear equation solvers struggle to converge otherwise.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            if  ( epochModel . epochMatrix . getRow ( i ) . getNumberOfEntries ( )  = =  0 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                * xIt  =  b_i ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + xIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + rowGroupIndexIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + choiceIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        assert ( x . size ( )  = =  choices . size ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  req  =  cachedData . linEqSolver - > getRequirements ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . linEqSolver - > clearBounds ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( obj . lowerResultBound )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            req . clearLowerBounds ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            cachedData . linEqSolver - > setLowerBound ( * obj . lowerResultBound ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( obj . upperResultBound )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            cachedData . linEqSolver - > setUpperBound ( * obj . upperResultBound ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            req . clearUpperBounds ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        STORM_LOG_THROW ( req . empty ( ) ,  storm : : exceptions : : UncheckedRequirementException ,  " At least one requirement of the LinearEquationSolver was not met. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        cachedData . linEqSolver - > solveEquations ( x ,  cachedData . bLinEq ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  resultIt  =  result . begin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        for  ( auto  const &  state  :  epochModel . epochInStates )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            resultIt - > push_back ( x [ state ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + resultIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swEqBuilding . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swAux3 . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                rewardUnfolding . setSolutionForCurrentEpoch ( std : : move ( result ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                swEpochModelAnalysis . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            template  < class  SparseMdpModelType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            void  SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : updateCachedData ( typename  MultiDimensionalRewardUnfolding < ValueType ,  false > : : EpochModel  const &  epochModel ,  EpochCheckingData &  cachedData ,  std : : vector < ValueType >  const &  weightVector )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( epochModel . epochMatrixChanged )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    swDataUpdate . start ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Update the cached MinMaxSolver data
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    cachedData . bMinMax . resize ( epochModel . epochMatrix . getRowCount ( ) ) ;  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				
					@ -249,7 +313,6 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( auto &  x_o  :  cachedData . xLinEq )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        x_o . assign ( epochModel . epochMatrix . getRowGroupCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    swDataUpdate . stop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }