@ -155,7 +155,6 @@ namespace storm { 
			
		
	
		
			
				
					                auto  memoryStateMap  =  computeMemoryStateMap ( memoryStructure ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                productModel  =  std : : make_unique < ProductModel < ValueType > > ( model ,  memoryStructure ,  dimensions ,  objectiveDimensions ,  epochManager ,  std : : move ( memoryStateMap ) ,  epochSteps ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template < typename  ValueType ,  bool  SingleObjectiveMode >  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -276,6 +275,13 @@ namespace storm { 
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                swSetEpoch . start ( ) ;  
			
		
	
		
			
				
					                bool  containsLowerBoundedObjective  =  false ;  
			
		
	
		
			
				
					                for  ( auto  const &  dimension  :  dimensions )  {  
			
		
	
		
			
				
					                    if  ( ! dimension . isUpperBounded )  {  
			
		
	
		
			
				
					                        containsLowerBoundedObjective  =  true ;  
			
		
	
		
			
				
					                        break ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                epochModel . stepSolutions . resize ( epochModel . stepChoices . getNumberOfSetBits ( ) ) ;  
			
		
	
		
			
				
					                auto  stepSolIt  =  epochModel . stepSolutions . begin ( ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -301,12 +307,11 @@ namespace storm { 
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        epochModel . objectiveRewardFilter [ objIndex ] . set ( reducedChoice ,  rewardEarned ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    // compute the solution for the stepChoices
  
			
		
	
		
			
				
					                    // For optimization purposes, we distinguish the easier case where the successor epoch lies in the same epoch class
  
			
		
	
		
			
				
					                    SolutionType  choiceSolution ;  
			
		
	
		
			
				
					                    bool  firstSuccessor  =  true ;  
			
		
	
		
			
				
					                    if  ( epochManager . compareEpochClass ( epoch ,  successorEpoch ) )  {  
			
		
	
		
			
				
					                    if  ( ! containsLowerBoundedObjective  & &  epochManager . compareEpochClass ( epoch ,  successorEpoch ) )  {  
			
		
	
		
			
				
					                        for  ( auto  const &  successor  :  productModel - > getProduct ( ) . getTransitionMatrix ( ) . getRow ( productChoice ) )  {  
			
		
	
		
			
				
					                            if  ( firstSuccessor )  {  
			
		
	
		
			
				
					                                choiceSolution  =  getScaledSolution ( getStateSolution ( successorEpoch ,  successor . getColumn ( ) ) ,  successor . getValue ( ) ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -326,7 +331,7 @@ namespace storm { 
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        for  ( auto  const &  successor  :  productModel - > getProduct ( ) . getTransitionMatrix ( ) . getRow ( productChoice ) )  {  
			
		
	
		
			
				
					                            storm : : storage : : BitVector  successorMemoryState  =  ( productModel - > convertMemoryState ( productModel - > getMemoryState ( successor . getColumn ( ) ) )  &  allowedRelevantDimensions )  |  forc edRelevantDimensions;  
			
		
	
		
			
				
					                            storm : : storage : : BitVector  successorMemoryState  =  ( productModel - > convertMemoryState ( productModel - > getMemoryState ( successor . getColumn ( ) ) )  |  forcedRelevantDimensions )  &  allow edRelevantDimensions;  
			
		
	
		
			
				
					                            uint64_t  successorProductState  =  productModel - > getProductState ( productModel - > getModelState ( successor . getColumn ( ) ) ,  productModel - > convertMemoryState ( successorMemoryState ) ) ;  
			
		
	
		
			
				
					                            SolutionType  const &  successorSolution  =  getStateSolution ( successorEpoch ,  successorProductState ) ;  
			
		
	
		
			
				
					                            if  ( firstSuccessor )  {  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -370,7 +375,7 @@ namespace storm { 
			
		
	
		
			
				
					            template < typename  ValueType ,  bool  SingleObjectiveMode >  
			
		
	
		
			
				
					            void  MultiDimensionalRewardUnfolding < ValueType ,  SingleObjectiveMode > : : setCurrentEpochClass ( Epoch  const &  epoch )  {  
			
		
	
		
			
				
					                EpochClass  epochClass  =  epochManager . getEpochClass ( epoch ) ;  
			
		
	
		
			
				
					                // std::cout << "Setting epoch class for epoch " << storm::utility::vector:: toString(epoch) << std::endl;
  
			
		
	
		
			
				
					                // std::cout << "Setting epoch class for epoch " << epochManager. toString(epoch) << std::endl;
  
			
		
	
		
			
				
					                swSetEpochClass . start ( ) ;  
			
		
	
		
			
				
					                swAux1 . start ( ) ;  
			
		
	
		
			
				
					                auto  productObjectiveRewards  =  productModel - > computeObjectiveRewards ( epochClass ,  objectives ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -392,12 +397,16 @@ namespace storm { 
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                if  ( ! violatedLowerBoundedDimensions . empty ( ) )  {  
			
		
	
		
			
				
					                    for  ( auto &  entry  :  epochModel . epochMatrix )  {  
			
		
	
		
			
				
					                    for  ( uint64_t  state  =  0 ;  state  <  epochModel . epochMatrix . getRowGroupCount ( ) ;  + + state )  {  
			
		
	
		
			
				
					                        auto  const &  memoryState  =  productModel - > convertMemoryState ( productModel - > getMemoryState ( state ) ) ;  
			
		
	
		
			
				
					                        storm : : storage : : BitVector  forcedRelevantDimensions  =  memoryState  &  violatedLowerBoundedDimensions ;  
			
		
	
		
			
				
					                        for  ( auto &  entry  :  epochModel . epochMatrix . getRowGroup ( state ) )  {  
			
		
	
		
			
				
					                            storm : : storage : : BitVector  successorMemoryState  =  productModel - > convertMemoryState ( productModel - > getMemoryState ( entry . getColumn ( ) ) ) ;  
			
		
	
		
			
				
					                        successorMemoryState  | =  violatedLowerBoundedDimensions ;  
			
		
	
		
			
				
					                             successorMemoryState  | =  forcedRelevant Dimensions;  
			
		
	
		
			
				
					                            entry . setColumn ( productModel - > getProductState ( productModel - > getModelState ( entry . getColumn ( ) ) ,  productModel - > convertMemoryState ( successorMemoryState ) ) ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                storm : : storage : : BitVector  zeroObjRewardChoices ( productModel - > getProduct ( ) . getNumberOfChoices ( ) ,  true ) ;  
			
		
	
		
			
				
					                for  ( uint64_t  objIndex  =  0 ;  objIndex  <  objectives . size ( ) ;  + + objIndex )  {  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -435,21 +444,15 @@ namespace storm { 
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                epochModel . objectiveRewards . clear ( ) ;  
			
		
	
		
			
				
					                for  ( uint64_t  objIndex  =  0 ;  objIndex  <  objectives . size ( ) ;  + + objIndex )  {  
			
		
	
		
			
				
					                    bool  objHasViolatedLowerDimension  =  false ;  
			
		
	
		
			
				
					                    for  ( auto  const &  dim  :  objectiveDimensions [ objIndex ] )  {  
			
		
	
		
			
				
					                        if  ( ! dimensions [ dim ] . isUpperBounded  & &  ! epochManager . isBottomDimensionEpochClass ( epochClass ,  dim ) )  {  
			
		
	
		
			
				
					                            objHasViolatedLowerDimension  =  true ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    std : : vector < ValueType >  reducedModelObjRewards ;  
			
		
	
		
			
				
					                    if  ( objHasViolatedLowerDimension )  {  
			
		
	
		
			
				
					                        reducedModelObjRewards . assign ( epochModel . epochMatrix . getRowCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                    std : : vector < ValueType >  const &  productObjRew  =  productObjectiveRewards [ objIndex ] ;  
			
		
	
		
			
				
					                    std : : vector < ValueType >  reducedModelObjRewards ;  
			
		
	
		
			
				
					                    reducedModelObjRewards . reserve ( epochModel . epochMatrix . getRowCount ( ) ) ;  
			
		
	
		
			
				
					                    for  ( auto  const &  productChoice  :  epochModelToProductChoiceMap )  {  
			
		
	
		
			
				
					                        reducedModelObjRewards . push_back ( productObjRew [ productChoice ] ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    // Check if the objective is violated in the current epoch
  
			
		
	
		
			
				
					                    if  ( ! violatedLowerBoundedDimensions . isDisjointFrom ( objectiveDimensions [ objIndex ] ) )  {  
			
		
	
		
			
				
					                        storm : : utility : : vector : : setVectorValues ( reducedModelObjRewards ,  ~ epochModel . stepChoices ,  storm : : utility : : zero < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    epochModel . objectiveRewards . push_back ( std : : move ( reducedModelObjRewards ) ) ;  
			
		
	
		
			
				
					                }  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -512,24 +515,27 @@ namespace storm { 
			
		
	
		
			
				
					            template < typename  ValueType ,  bool  SingleObjectiveMode >  
			
		
	
		
			
				
					            template < bool  SO ,  typename  std : : enable_if < SO ,  int > : : type >  
			
		
	
		
			
				
					            std : : string  MultiDimensionalRewardUnfolding < ValueType ,  SingleObjectiveMode > : : solutionToString ( SolutionType  const &  solution )  const  {  
			
		
	
		
			
				
					                return  std : : to_string ( solution ) ;  
			
		
	
		
			
				
					                std : : stringstream  stringstream ;  
			
		
	
		
			
				
					                stringstream  < <  solution ;  
			
		
	
		
			
				
					                return  stringstream . str ( ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template < typename  ValueType ,  bool  SingleObjectiveMode >  
			
		
	
		
			
				
					            template < bool  SO ,  typename  std : : enable_if < ! SO ,  int > : : type >  
			
		
	
		
			
				
					            std : : string  MultiDimensionalRewardUnfolding < ValueType ,  SingleObjectiveMode > : : solutionToString ( SolutionType  const &  solution )  const  {  
			
		
	
		
			
				
					                std : : string  res  =  " ( " ;  
			
		
	
		
			
				
					                std : : stringstream  stringstream ;  
			
		
	
		
			
				
					                stringstream  < <  " ( " ;  
			
		
	
		
			
				
					                bool  first  =  true ;  
			
		
	
		
			
				
					                for  ( auto  const &  s  :  solution )  {  
			
		
	
		
			
				
					                    if  ( first )  {  
			
		
	
		
			
				
					                        first  =  false ;  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                        res  + = " ,  " ;  
			
		
	
		
			
				
					                        stringstream  < < " ,  " ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    res  + =  std : : to_string ( s ) ;  
			
		
	
		
			
				
					                    stringstream  < <  s ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                res  + = " ) " ;  
			
		
	
		
			
				
					                return  res  ;  
			
		
	
		
			
				
					                stringstream  < < " ) " ;  
			
		
	
		
			
				
					                return  stringst ream . str ( ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template < typename  ValueType ,  bool  SingleObjectiveMode >  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -571,8 +577,11 @@ namespace storm { 
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template < typename  ValueType ,  bool  SingleObjectiveMode >  
			
		
	
		
			
				
					            typename  MultiDimensionalRewardUnfolding < ValueType ,  SingleObjectiveMode > : : SolutionType  const &  MultiDimensionalRewardUnfolding < ValueType ,  SingleObjectiveMode > : : getStateSolution ( Epoch  const &  epoch ,  uint64_t  const &  productState )  {  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( epochSolutions . find ( epoch )  ! =  epochSolutions . end ( ) ,  " Requested unexisting solution for epoch  "  < <  epochManager . toString ( epoch )  < <  " . " ) ;  
			
		
	
		
			
				
					                EpochSolution  const &  epochSolution  =  epochSolutions [ epoch ] ;  
			
		
	
		
			
				
					                auto  epochSolutionIt  =  epochSolutions . find ( epoch ) ;  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( epochSolutionIt  ! =  epochSolutions . end ( ) ,  " Requested unexisting solution for epoch  "  < <  epochManager . toString ( epoch )  < <  " . " ) ;  
			
		
	
		
			
				
					                auto  const &  epochSolution  =  epochSolutionIt - > second ;  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( productState  <  epochSolution . productStateToSolutionVectorMap - > size ( ) ,  " Requested solution for epoch  "  < <  epochManager . toString ( epoch )  < <  "  at an unexisting product state. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( ( * epochSolution . productStateToSolutionVectorMap ) [ productState ]  <  epochSolution . solutions . size ( ) ,  " Requested solution for epoch  "  < <  epochManager . toString ( epoch )  < <  "  at a state for which no solution was stored. " ) ;  
			
		
	
		
			
				
					                return  epochSolution . solutions [ ( * epochSolution . productStateToSolutionVectorMap ) [ productState ] ] ;  
			
		
	
		
			
				
					            }