@ -4,6 +4,7 @@ 
			
		 
		
	
		
			
				 
				 
				# include  "src/models/sparse/StandardRewardModel.h" 
  
				 
				 
				# include  "src/models/sparse/StandardRewardModel.h" 
  
			
		 
		
	
		
			
				 
				 
				# include  "src/modelchecker/propositional/SparsePropositionalModelChecker.h" 
  
				 
				 
				# include  "src/modelchecker/propositional/SparsePropositionalModelChecker.h" 
  
			
		 
		
	
		
			
				 
				 
				# include  "src/modelchecker/results/ExplicitQualitativeCheckResult.h" 
  
				 
				 
				# include  "src/modelchecker/results/ExplicitQualitativeCheckResult.h" 
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				# include  "src/storage/MaximalEndComponentDecomposition.h" 
  
			
		 
		
	
		
			
				 
				 
				# include  "src/transformer/StateDuplicator.h" 
  
				 
				 
				# include  "src/transformer/StateDuplicator.h" 
  
			
		 
		
	
		
			
				 
				 
				# include  "src/transformer/SubsystemBuilder.h" 
  
				 
				 
				# include  "src/transformer/SubsystemBuilder.h" 
  
			
		 
		
	
		
			
				 
				 
				# include  "src/utility/macros.h" 
  
				 
				 
				# include  "src/utility/macros.h" 
  
			
		 
		
	
	
		
			
				
					
					
					
						
							 
						 
					
				 
				@ -18,10 +19,16 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				        namespace  helper  {  
				 
				 
				        namespace  helper  {  
			
		 
		
	
		
			
				 
				 
				             
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				            template < typename  SparseModelType >  
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				            typename  SparseMultiObjectivePreprocessor < SparseModelType > : : PreprocessorData  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocess ( storm : : logic : : MultiObjectiveFormula  const &  originalFormula ,  SparseModelType  const &  originalModel ,  storm : : storage : : BitVector  const &  subsystem )  {  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            typename  SparseMultiObjectivePreprocessor < SparseModelType > : : PreprocessorData  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocess ( storm : : logic : : MultiObjectiveFormula  const &  originalFormula ,  SparseModelType  const &  originalModel )  {  
			
		 
		
	
		
			
				 
				 
				                 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				                auto  subsystemBuilderResult  =  storm : : transformer : : SubsystemBuilder < SparseModelType > : : transform ( originalModel ,  subsystem ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                PreprocessorData  data ( originalModel ,  std : : move ( * subsystemBuilderResult . model ) ,  std : : move ( subsystemBuilderResult . newToOldStateIndexMapping ) ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                PreprocessorData  data ( originalFormula ,  originalModel ,  SparseModelType ( originalModel ) ,  storm : : utility : : vector : : buildVectorForRange ( 0 ,  originalModel . getNumberOfStates ( ) ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                data . objectivesSolvedInPreprocessing  =  storm : : storage : : BitVector ( originalFormula . getNumberOfSubformulas ( ) ,  false ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                // get a unique name for the labels of states that have to be reached with probability 1 and add the label
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                data . prob1StatesLabel  =  " prob1 " ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                while ( data . preprocessedModel . hasLabel ( data . prob1StatesLabel ) )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    data . prob1StatesLabel  =  " _ "  +  data . prob1StatesLabel ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                data . preprocessedModel . getStateLabeling ( ) . addLabel ( data . prob1StatesLabel ) ;  
			
		 
		
	
		
			
				 
				 
				                 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				                //Invoke preprocessing on the individual objectives
  
				 
				 
				                //Invoke preprocessing on the individual objectives
  
			
		 
		
	
		
			
				 
				 
				                for ( auto  const &  subFormula  :  originalFormula . getSubFormulas ( ) ) {  
				 
				 
				                for ( auto  const &  subFormula  :  originalFormula . getSubFormulas ( ) ) {  
			
		 
		
	
	
		
			
				
					
					
					
						
							 
						 
					
				 
				@ -42,6 +49,10 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				                    data . preprocessedModel . removeRewardModel ( rewModel ) ;  
				 
				 
				                    data . preprocessedModel . removeRewardModel ( rewModel ) ;  
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				                 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                assertRewardFiniteness ( data ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                data . objectives  =  storm : : utility : : vector : : filterVector ( data . objectives ,  ~ data . objectivesSolvedInPreprocessing ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				                //Set the query type. In case of a numerical query, also set the index of the objective to be optimized.
  
				 
				 
				                //Set the query type. In case of a numerical query, also set the index of the objective to be optimized.
  
			
		 
		
	
		
			
				 
				 
				                storm : : storage : : BitVector  objectivesWithoutThreshold ( data . objectives . size ( ) ) ;  
				 
				 
				                storm : : storage : : BitVector  objectivesWithoutThreshold ( data . objectives . size ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				                for ( uint_fast64_t  objIndex  =  0 ;  objIndex  <  data . objectives . size ( ) ;  + + objIndex )  {  
				 
				 
				                for ( uint_fast64_t  objIndex  =  0 ;  objIndex  <  data . objectives . size ( ) ;  + + objIndex )  {  
			
		 
		
	
	
		
			
				
					
						
							 
						 
					
					
						
							 
						 
					
					
				 
				@ -107,14 +118,22 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				             
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				            template < typename  SparseModelType >  
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : ProbabilityOperatorFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective )  {  
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : ProbabilityOperatorFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                currentObjective . rewardFinitenessChecked  =  true ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                bool  isProb0Formula  =  false ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                bool  isProb1Formula  =  false ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                if ( currentObjective . threshold  & &  ! currentObjective . thresholdIsStrict )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    isProb0Formula  =  ! currentObjective . rewardsArePositive  & &  storm : : utility : : isZero ( * currentObjective . threshold ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    isProb1Formula  =  currentObjective . rewardsArePositive  & &  storm : : utility : : isOne ( * currentObjective . threshold ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				                if ( formula . getSubformula ( ) . isUntilFormula ( ) ) {  
				 
				 
				                if ( formula . getSubformula ( ) . isUntilFormula ( ) ) {  
			
		 
		
	
		
			
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asUntilFormula ( ) ,  data ,  currentObjective ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asUntilFormula ( ) ,  data ,  currentObjective ,  isProb0Formula ,  isProb1Formula ) ;  
			
		 
		
	
		
			
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isBoundedUntilFormula ( ) ) {  
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isBoundedUntilFormula ( ) ) {  
			
		 
		
	
		
			
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asBoundedUntilFormula ( ) ,  data ,  currentObjective ) ;  
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asBoundedUntilFormula ( ) ,  data ,  currentObjective ) ;  
			
		 
		
	
		
			
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isGloballyFormula ( ) ) {  
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isGloballyFormula ( ) ) {  
			
		 
		
	
		
			
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asGloballyFormula ( ) ,  data ,  currentObjective ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asGloballyFormula ( ) ,  data ,  currentObjective ,  isProb0Formula ,  isProb1Formula ) ;  
			
		 
		
	
		
			
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isEventuallyFormula ( ) ) {  
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isEventuallyFormula ( ) ) {  
			
		 
		
	
		
			
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asEventuallyFormula ( ) ,  data ,  currentObjective ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asEventuallyFormula ( ) ,  data ,  currentObjective ,  isProb0Formula ,  isProb1Formula ) ;  
			
		 
		
	
		
			
				 
				 
				                }  else  {  
				 
				 
				                }  else  {  
			
		 
		
	
		
			
				 
				 
				                    STORM_LOG_THROW ( false ,  storm : : exceptions : : InvalidPropertyException ,  " The subformula of  "  < <  formula  < <  "  is not supported. " ) ;  
				 
				 
				                    STORM_LOG_THROW ( false ,  storm : : exceptions : : InvalidPropertyException ,  " The subformula of  "  < <  formula  < <  "  is not supported. " ) ;  
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				                }  
			
		 
		
	
	
		
			
				
					
					
					
						
							 
						 
					
				 
				@ -125,8 +144,12 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				                // Check if the reward model is uniquely specified
  
				 
				 
				                // Check if the reward model is uniquely specified
  
			
		 
		
	
		
			
				 
				 
				                STORM_LOG_THROW ( ( formula . hasRewardModelName ( )  & &  data . preprocessedModel . hasRewardModel ( formula . getRewardModelName ( ) ) )  
				 
				 
				                STORM_LOG_THROW ( ( formula . hasRewardModelName ( )  & &  data . preprocessedModel . hasRewardModel ( formula . getRewardModelName ( ) ) )  
			
		 
		
	
		
			
				 
				 
				                                | |  data . preprocessedModel . hasUniqueRewardModel ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " The reward model is not unique and the formula  "  < <  formula  < <  "  does not specify a reward model. " ) ;  
				 
				 
				                                | |  data . preprocessedModel . hasUniqueRewardModel ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " The reward model is not unique and the formula  "  < <  formula  < <  "  does not specify a reward model. " ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                // reward finiteness has to be checked later iff infinite reward is possible for the subformula
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                currentObjective . rewardFinitenessChecked  =  formula . getSubformula ( ) . isCumulativeRewardFormula ( ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				                if ( formula . getSubformula ( ) . isEventuallyFormula ( ) ) {  
				 
				 
				                if ( formula . getSubformula ( ) . isEventuallyFormula ( ) ) {  
			
		 
		
	
		
			
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asEventuallyFormula ( ) ,  data ,  currentObjective ,  formula . getOptionalRewardModelName ( ) ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asEventuallyFormula ( ) ,  data ,  currentObjective ,  false ,  false ,  formula . getOptionalRewardModelName ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isCumulativeRewardFormula ( ) )  {  
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isCumulativeRewardFormula ( ) )  {  
			
		 
		
	
		
			
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asCumulativeRewardFormula ( ) ,  data ,  currentObjective ,  formula . getOptionalRewardModelName ( ) ) ;  
				 
				 
				                    preprocessFormula ( formula . getSubformula ( ) . asCumulativeRewardFormula ( ) ,  data ,  currentObjective ,  formula . getOptionalRewardModelName ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isTotalRewardFormula ( ) )  {  
				 
				 
				                }  else  if ( formula . getSubformula ( ) . isTotalRewardFormula ( ) )  {  
			
		 
		
	
	
		
			
				
					
					
					
						
							 
						 
					
				 
				@ -137,7 +160,7 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				            }  
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				             
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				            template < typename  SparseModelType >  
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : UntilFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective )  {  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : UntilFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective ,  bool  isProb0Formula ,  bool  isProb1Formula )  {  
			
		 
		
	
		
			
				 
				 
				                CheckTask < storm : : logic : : Formula >  phiTask ( formula . getLeftSubformula ( ) ) ;  
				 
				 
				                CheckTask < storm : : logic : : Formula >  phiTask ( formula . getLeftSubformula ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				                CheckTask < storm : : logic : : Formula >  psiTask ( formula . getRightSubformula ( ) ) ;  
				 
				 
				                CheckTask < storm : : logic : : Formula >  psiTask ( formula . getRightSubformula ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				                storm : : modelchecker : : SparsePropositionalModelChecker < SparseModelType >  mc ( data . preprocessedModel ) ;  
				 
				 
				                storm : : modelchecker : : SparsePropositionalModelChecker < SparseModelType >  mc ( data . preprocessedModel ) ;  
			
		 
		
	
	
		
			
				
					
					
					
						
							 
						 
					
				 
				@ -146,20 +169,46 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				                storm : : storage : : BitVector  psiStates  =  mc . check ( psiTask ) - > asExplicitQualitativeCheckResult ( ) . getTruthValuesVector ( ) ;  
				 
				 
				                storm : : storage : : BitVector  psiStates  =  mc . check ( psiTask ) - > asExplicitQualitativeCheckResult ( ) . getTruthValuesVector ( ) ;  
			
		 
		
	
		
			
				 
				 
				                 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				                auto  duplicatorResult  =  storm : : transformer : : StateDuplicator < SparseModelType > : : transform ( data . preprocessedModel ,  ~ phiStates  |  psiStates ) ;  
				 
				 
				                auto  duplicatorResult  =  storm : : transformer : : StateDuplicator < SparseModelType > : : transform ( data . preprocessedModel ,  ~ phiStates  |  psiStates ) ;  
			
		 
		
	
		
			
				 
				 
				                data . preprocessedModel  =  std : : move ( * duplicatorResult . model ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                // duplicatorResult.newToOldStateIndexMapping now reffers to the indices of the model we had before preprocessing this formula.
  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                // This might not be the actual original model.
  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                for ( auto  &  originalModelStateIndex  :  duplicatorResult . newToOldStateIndexMapping ) {  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                    originalModelStateIndex  =  data . newToOldStateIndexMapping [ originalModelStateIndex ] ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                data . newToOldStateIndexMapping  =  std : : move ( duplicatorResult . newToOldStateIndexMapping ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                updatePreprocessedModel ( data ,  * duplicatorResult . model ,  duplicatorResult . newToOldStateIndexMapping ) ;  
			
		 
		
	
		
			
				 
				 
				                 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				                // build stateAction reward vector that gives (one*transitionProbability) reward whenever a transition leads from the firstCopy to a psiState
  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                storm : : storage : : BitVector  newPsiStates ( data . preprocessedModel . getNumberOfStates ( ) ,  false ) ;  
				 
				 
				                storm : : storage : : BitVector  newPsiStates ( data . preprocessedModel . getNumberOfStates ( ) ,  false ) ;  
			
		 
		
	
		
			
				 
				 
				                for ( auto  const &  oldPsiState  :  psiStates ) {  
				 
				 
				                for ( auto  const &  oldPsiState  :  psiStates ) {  
			
		 
		
	
		
			
				 
				 
				                    //note that psiStates are always located in the second copy
  
				 
				 
				                    //note that psiStates are always located in the second copy
  
			
		 
		
	
		
			
				 
				 
				                    newPsiStates . set ( duplicatorResult . secondCopyOldToNewStateIndexMapping [ oldPsiState ] ,  true ) ;  
				 
				 
				                    newPsiStates . set ( duplicatorResult . secondCopyOldToNewStateIndexMapping [ oldPsiState ] ,  true ) ;  
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                if ( isProb0Formula  | |  isProb1Formula )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    storm : : storage : : BitVector  subsystemStates ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    storm : : storage : : BitVector  noIncomingTransitionFromFirstCopyStates ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    if ( isProb0Formula )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        subsystemStates  =  storm : : utility : : graph : : performProb0E ( data . preprocessedModel ,  data . preprocessedModel . getBackwardTransitions ( ) ,  duplicatorResult . firstCopy ,  newPsiStates ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        subsystemStates  | =  duplicatorResult . secondCopy ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        noIncomingTransitionFromFirstCopyStates  =  newPsiStates ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    }  else  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        for ( auto  psiState  :  newPsiStates )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                            data . preprocessedModel . getStateLabeling ( ) . addLabelToState ( data . prob1StatesLabel ,  psiState ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        subsystemStates  =  storm : : utility : : graph : : performProb1E ( data . preprocessedModel ,  data . preprocessedModel . getBackwardTransitions ( ) ,  duplicatorResult . firstCopy ,  newPsiStates ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        subsystemStates  | =  duplicatorResult . secondCopy ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        noIncomingTransitionFromFirstCopyStates  =  duplicatorResult . secondCopy  &  ( ~ newPsiStates ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    storm : : storage : : BitVector  consideredActions ( data . preprocessedModel . getTransitionMatrix ( ) . getRowCount ( ) ,  true ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    for ( auto  state  :  duplicatorResult . firstCopy )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        for ( uint_fast64_t  action  =  data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state ] ;  action  <  data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state  + 1 ]  ;  + + action )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                            for ( auto  const &  entry  :  data . preprocessedModel . getTransitionMatrix ( ) . getRow ( action ) )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                if ( noIncomingTransitionFromFirstCopyStates . get ( entry . getColumn ( ) ) )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                    consideredActions . set ( action ,  false ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                    break ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                            }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    subsystemStates  =  storm : : utility : : graph : : getReachableStates ( data . preprocessedModel . getTransitionMatrix ( ) ,  data . preprocessedModel . getInitialStates ( ) ,  subsystemStates ,  storm : : storage : : BitVector ( subsystemStates . size ( ) ,  false ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    auto  subsystemBuilderResult  =  storm : : transformer : : SubsystemBuilder < SparseModelType > : : transform ( data . preprocessedModel ,  subsystemStates ,  consideredActions ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    updatePreprocessedModel ( data ,  * subsystemBuilderResult . model ,  subsystemBuilderResult . newToOldStateIndexMapping ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    data . objectivesSolvedInPreprocessing . set ( data . objectives . size ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  else  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    // build stateAction reward vector that gives (one*transitionProbability) reward whenever a transition leads from the firstCopy to a psiState
  
			
		 
		
	
		
			
				 
				 
				                    std : : vector < ValueType >  objectiveRewards ( data . preprocessedModel . getTransitionMatrix ( ) . getRowCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
				 
				 
				                    std : : vector < ValueType >  objectiveRewards ( data . preprocessedModel . getTransitionMatrix ( ) . getRowCount ( ) ,  storm : : utility : : zero < ValueType > ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				                    for  ( auto  const &  firstCopyState  :  duplicatorResult . firstCopy )  {  
				 
				 
				                    for  ( auto  const &  firstCopyState  :  duplicatorResult . firstCopy )  {  
			
		 
		
	
		
			
				 
				 
				                        for  ( uint_fast64_t  row  =  data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ firstCopyState ] ;  row  <  data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ firstCopyState  +  1 ] ;  + + row )  {  
				 
				 
				                        for  ( uint_fast64_t  row  =  data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ firstCopyState ] ;  row  <  data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ firstCopyState  +  1 ] ;  + + row )  {  
			
		 
		
	
	
		
			
				
					
					
					
						
							 
						 
					
				 
				@ -171,35 +220,32 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				                    }  
				 
				 
				                    }  
			
		 
		
	
		
			
				 
				 
				                    data . preprocessedModel . addRewardModel ( currentObjective . rewardModelName ,  RewardModelType ( boost : : none ,  objectiveRewards ) ) ;  
				 
				 
				                    data . preprocessedModel . addRewardModel ( currentObjective . rewardModelName ,  RewardModelType ( boost : : none ,  objectiveRewards ) ) ;  
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				             
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				            template < typename  SparseModelType >  
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : BoundedUntilFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective )  {  
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : BoundedUntilFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective )  {  
			
		 
		
	
		
			
				 
				 
				                STORM_LOG_THROW ( formula . hasDiscreteTimeBound ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " Expected a boundedUntilFormula with a discrete time bound but got  "  < <  formula  < <  " . " ) ;  
				 
				 
				                STORM_LOG_THROW ( formula . hasDiscreteTimeBound ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " Expected a boundedUntilFormula with a discrete time bound but got  "  < <  formula  < <  " . " ) ;  
			
		 
		
	
		
			
				 
				 
				                currentObjective . stepBound  =  formula . getDiscreteTimeBound ( ) ;  
				 
				 
				                currentObjective . stepBound  =  formula . getDiscreteTimeBound ( ) ;  
			
		 
		
	
		
			
				 
				 
				                     preprocessFormula ( storm : : logic : : UntilFormula ( formula . getLeftSubformula ( ) . asSharedPointer ( ) ,  formula . getRightSubformula ( ) . asSharedPointer ( ) ) ,  data ,  currentObjective ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                preprocessFormula ( storm : : logic : : UntilFormula ( formula . getLeftSubformula ( ) . asSharedPointer ( ) ,  formula . getRightSubformula ( ) . asSharedPointer ( ) ) ,  data ,  currentObjective ,  false ,  fals e ) ;  
			
		 
		
	
		
			
				 
				 
				            }  
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				             
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				            template < typename  SparseModelType >  
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : GloballyFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective )  {  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : GloballyFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective ,  bool  isProb0Formula ,  bool  isProb1Formula )  {  
			
		 
		
	
		
			
				 
				 
				                // The formula will be transformed to an until formula for the complementary event.
  
				 
				 
				                // The formula will be transformed to an until formula for the complementary event.
  
			
		 
		
	
		
			
				 
				 
				                // If the original formula minimizes, the complementary one will maximize and vice versa.
  
				 
				 
				                // If the original formula minimizes, the complementary one will maximize and vice versa.
  
			
		 
		
	
		
			
				 
				 
				                // Hence, the decision whether to consider positive or negative rewards flips.
  
				 
				 
				                // Hence, the decision whether to consider positive or negative rewards flips.
  
			
		 
		
	
		
			
				 
				 
				                currentObjective . rewardsArePositive  =  ! currentObjective . rewardsArePositive ;  
				 
				 
				                currentObjective . rewardsArePositive  =  ! currentObjective . rewardsArePositive ;  
			
		 
		
	
		
			
				 
				 
				                // To transform from the value of the preprocessed model back to the value of the original model, we have to add 1 to the result.
  
				 
				 
				                // To transform from the value of the preprocessed model back to the value of the original model, we have to add 1 to the result.
  
			
		 
		
	
		
			
				 
				 
				                // The transformation factor has already been set correctly
  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                // The transformation factor has already been set correctly. 
  
			
		 
		
	
		
			
				 
				 
				                currentObjective . toOriginalValueTransformationOffset  =  storm : : utility : : one < ValueType > ( ) ;  
				 
				 
				                currentObjective . toOriginalValueTransformationOffset  =  storm : : utility : : one < ValueType > ( ) ;  
			
		 
		
	
		
			
				 
				 
				                if ( currentObjective . threshold )  {  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                    // Strict thresholds become non-strict and vice versa
  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                    currentObjective . thresholdIsStrict  =  ! currentObjective . thresholdIsStrict ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                auto  negatedSubformula  =  std : : make_shared < storm : : logic : : UnaryBooleanStateFormula > ( storm : : logic : : UnaryBooleanStateFormula : : OperatorType : : Not ,  formula . getSubformula ( ) . asSharedPointer ( ) ) ;  
				 
				 
				                auto  negatedSubformula  =  std : : make_shared < storm : : logic : : UnaryBooleanStateFormula > ( storm : : logic : : UnaryBooleanStateFormula : : OperatorType : : Not ,  formula . getSubformula ( ) . asSharedPointer ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				                preprocessFormula ( storm : : logic : : UntilFormula ( storm : : logic : : Formula : : getTrueFormula ( ) ,  negatedSubformula ) ,  data ,  currentObjective ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                preprocessFormula ( storm : : logic : : UntilFormula ( storm : : logic : : Formula : : getTrueFormula ( ) ,  negatedSubformula ) ,  data ,  currentObjective ,  isProb1Formula ,  isProb0Formula ) ;  
			
		 
		
	
		
			
				 
				 
				            }  
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				             
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				            template < typename  SparseModelType >  
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : EventuallyFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective ,  boost : : optional < std : : string >  const &  optionalRewardModelName )  {  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : EventuallyFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective ,   bool  isProb0Formula ,  bool  isProb1Formula ,   boost : : optional < std : : string >  const &  optionalRewardModelName )  {  
			
		 
		
	
		
			
				 
				 
				                if ( formula . isReachabilityProbabilityFormula ( ) ) {  
				 
				 
				                if ( formula . isReachabilityProbabilityFormula ( ) ) {  
			
		 
		
	
		
			
				 
				 
				                    preprocessFormula ( storm : : logic : : UntilFormula ( storm : : logic : : Formula : : getTrueFormula ( ) ,  formula . getSubformula ( ) . asSharedPointer ( ) ) ,  data ,  currentObjective ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    preprocessFormula ( storm : : logic : : UntilFormula ( storm : : logic : : Formula : : getTrueFormula ( ) ,  formula . getSubformula ( ) . asSharedPointer ( ) ) ,  data ,  currentObjective ,  isProb0Formula ,  isProb1Formula ) ;  
			
		 
		
	
		
			
				 
				 
				                    return ;  
				 
				 
				                    return ;  
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				                STORM_LOG_THROW ( formula . isReachabilityRewardFormula ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " The formula  "  < <  formula  < <  "  neither considers reachability Probabilities nor reachability rewards " ) ;  
				 
				 
				                STORM_LOG_THROW ( formula . isReachabilityRewardFormula ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " The formula  "  < <  formula  < <  "  neither considers reachability Probabilities nor reachability rewards " ) ;  
			
		 
		
	
	
		
			
				
					
					
					
						
							 
						 
					
				 
				@ -208,16 +254,21 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				                storm : : modelchecker : : SparsePropositionalModelChecker < SparseModelType >  mc ( data . preprocessedModel ) ;  
				 
				 
				                storm : : modelchecker : : SparsePropositionalModelChecker < SparseModelType >  mc ( data . preprocessedModel ) ;  
			
		 
		
	
		
			
				 
				 
				                STORM_LOG_THROW ( mc . canHandle ( targetTask ) ,  storm : : exceptions : : InvalidPropertyException ,  " The subformula of  "  < <  formula  < <  "  should be propositional. " ) ;  
				 
				 
				                STORM_LOG_THROW ( mc . canHandle ( targetTask ) ,  storm : : exceptions : : InvalidPropertyException ,  " The subformula of  "  < <  formula  < <  "  should be propositional. " ) ;  
			
		 
		
	
		
			
				 
				 
				                storm : : storage : : BitVector  targetStates  =  mc . check ( targetTask ) - > asExplicitQualitativeCheckResult ( ) . getTruthValuesVector ( ) ;  
				 
				 
				                storm : : storage : : BitVector  targetStates  =  mc . check ( targetTask ) - > asExplicitQualitativeCheckResult ( ) . getTruthValuesVector ( ) ;  
			
		 
		
	
		
			
				 
				 
				                 
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                STORM_LOG_WARN ( " There is no check for reward finiteness yet " ) ;  //TODO
  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                auto  duplicatorResult  =  storm : : transformer : : StateDuplicator < SparseModelType > : : transform ( data . preprocessedModel ,  targetStates ) ;  
				 
				 
				                auto  duplicatorResult  =  storm : : transformer : : StateDuplicator < SparseModelType > : : transform ( data . preprocessedModel ,  targetStates ) ;  
			
		 
		
	
		
			
				 
				 
				                data . preprocessedModel  =  std : : move ( * duplicatorResult . model ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                // duplicatorResult.newToOldStateIndexMapping now reffers to the indices of the model we had before preprocessing this formula.
  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                // This might not be the actual original model.
  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                for ( auto  &  originalModelStateIndex  :  duplicatorResult . newToOldStateIndexMapping ) {  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                    originalModelStateIndex  =  data . newToOldStateIndexMapping [ originalModelStateIndex ] ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                updatePreprocessedModel ( data ,  * duplicatorResult . model ,  duplicatorResult . newToOldStateIndexMapping ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                // States of the first copy from which the second copy is not reachable with prob 1 under any scheduler can
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                // be removed as the expected reward is not defined for these states.
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                // We also need to enforce that the second copy will be reached eventually with prob 1.
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                for ( auto  targetState  :  duplicatorResult . gateStates )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    data . preprocessedModel . getStateLabeling ( ) . addLabelToState ( data . prob1StatesLabel ,  targetState ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  subsystemStates  =  storm : : utility : : graph : : performProb1E ( data . preprocessedModel ,  data . preprocessedModel . getBackwardTransitions ( ) ,  duplicatorResult . firstCopy ,  duplicatorResult . gateStates ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                subsystemStates  | =  duplicatorResult . secondCopy ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                if ( ! subsystemStates . full ( ) )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    auto  subsystemBuilderResult  =  storm : : transformer : : SubsystemBuilder < SparseModelType > : : transform ( data . preprocessedModel ,  subsystemStates ,  storm : : storage : : BitVector ( data . preprocessedModel . getTransitionMatrix ( ) . getRowCount ( ) ,  true ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    updatePreprocessedModel ( data ,  * subsystemBuilderResult . model ,  subsystemBuilderResult . newToOldStateIndexMapping ) ;  
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				                data . newToOldStateIndexMapping  =  std : : move ( duplicatorResult . newToOldStateIndexMapping ) ;  
				 
				 
				 
			
		 
		
	
		
			
				 
				 
				                 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				                // Add a reward model that gives zero reward to the states of the second copy.
  
				 
				 
				                // Add a reward model that gives zero reward to the states of the second copy.
  
			
		 
		
	
		
			
				 
				 
				                std : : vector < ValueType >  objectiveRewards  =  data . preprocessedModel . getRewardModel ( optionalRewardModelName  ?  optionalRewardModelName . get ( )  :  " " ) . getTotalRewardVector ( data . preprocessedModel . getTransitionMatrix ( ) ) ;  
				 
				 
				                std : : vector < ValueType >  objectiveRewards  =  data . preprocessedModel . getRewardModel ( optionalRewardModelName  ?  optionalRewardModelName . get ( )  :  " " ) . getTotalRewardVector ( data . preprocessedModel . getTransitionMatrix ( ) ) ;  
			
		 
		
	
	
		
			
				
					
						
							 
						 
					
					
						
							 
						 
					
					
				 
				@ -246,12 +297,119 @@ namespace storm { 
			
		 
		
	
		
			
				 
				 
				            template < typename  SparseModelType >  
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : TotalRewardFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective ,  boost : : optional < std : : string >  const &  optionalRewardModelName )  {  
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : preprocessFormula ( storm : : logic : : TotalRewardFormula  const &  formula ,  PreprocessorData &  data ,  ObjectiveInformation &  currentObjective ,  boost : : optional < std : : string >  const &  optionalRewardModelName )  {  
			
		 
		
	
		
			
				 
				 
				                std : : vector < ValueType >  objectiveRewards  =  data . preprocessedModel . getRewardModel ( optionalRewardModelName  ?  optionalRewardModelName . get ( )  :  " " ) . getTotalRewardVector ( data . preprocessedModel . getTransitionMatrix ( ) ) ;  
				 
				 
				                std : : vector < ValueType >  objectiveRewards  =  data . preprocessedModel . getRewardModel ( optionalRewardModelName  ?  optionalRewardModelName . get ( )  :  " " ) . getTotalRewardVector ( data . preprocessedModel . getTransitionMatrix ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  positiveRewards  =  storm : : utility : : vector : : filterGreaterZero ( objectiveRewards ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  nonNegativeRewards  =  positiveRewards  |  storm : : utility : : vector : : filterZero ( objectiveRewards ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                STORM_LOG_THROW ( nonNegativeRewards . full ( )  | |  positiveRewards . empty ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " The reward model for the formula  "  < <  formula  < <  "  has positive and negative rewards which is not supported. " ) ;  
			
		 
		
	
		
			
				 
				 
				                if ( ! currentObjective . rewardsArePositive ) {  
				 
				 
				                if ( ! currentObjective . rewardsArePositive ) {  
			
		 
		
	
		
			
				 
				 
				                    storm : : utility : : vector : : scaleVectorInPlace ( objectiveRewards ,  - storm : : utility : : one < ValueType > ( ) ) ;  
				 
				 
				                    storm : : utility : : vector : : scaleVectorInPlace ( objectiveRewards ,  - storm : : utility : : one < ValueType > ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				                }  
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				                data . preprocessedModel . addRewardModel ( currentObjective . rewardModelName ,  RewardModelType ( boost : : none ,  objectiveRewards ) ) ;  
				 
				 
				                data . preprocessedModel . addRewardModel ( currentObjective . rewardModelName ,  RewardModelType ( boost : : none ,  objectiveRewards ) ) ;  
			
		 
		
	
		
			
				 
				 
				            }  
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				             
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : assertRewardFiniteness ( PreprocessorData &  data )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                bool  negativeRewardsOccur  =  false ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                bool  positiveRewardsOccur  =  false ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                for ( auto &  obj  :  data . objectives )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    if  ( ! obj . rewardFinitenessChecked )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        negativeRewardsOccur  | =  ! obj . rewardsArePositive ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        positiveRewardsOccur  | =  obj . rewardsArePositive ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  actionsWithNegativeReward ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                if ( negativeRewardsOccur )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    actionsWithNegativeReward  =  assertNegativeRewardFiniteness ( data ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  else  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    actionsWithNegativeReward  =  storm : : storage : : BitVector ( data . preprocessedModel . getTransitionMatrix ( ) . getRowCount ( ) ,  false ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                if ( positiveRewardsOccur )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    assertPositiveRewardFiniteness ( data ,  actionsWithNegativeReward ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            storm : : storage : : BitVector  SparseMultiObjectivePreprocessor < SparseModelType > : : assertNegativeRewardFiniteness ( PreprocessorData &  data )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				
 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  actionsWithNonNegativeReward ( data . preprocessedModel . getTransitionMatrix ( ) . getRowCount ( ) ,  true ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                for ( auto &  obj  :  data . objectives )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    if  ( ! obj . rewardFinitenessChecked  & &  ! obj . rewardsArePositive )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        obj . rewardFinitenessChecked  =  true ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        actionsWithNonNegativeReward  & =  storm : : utility : : vector : : filterZero ( data . preprocessedModel . getRewardModel ( obj . rewardModelName ) . getStateActionRewardVector ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  statesWithNegativeRewardForAllChoices ( data . preprocessedModel . getNumberOfStates ( ) ,  true ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                for ( uint_fast64_t  state  =  0 ;  state  <  data . preprocessedModel . getNumberOfStates ( ) ;  + + state )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    // state has negative reward for all choices iff there is no bit set in actionsWithNonNegativeReward for all actions of state
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    statesWithNegativeRewardForAllChoices . set ( state ,  actionsWithNonNegativeReward . getNextSetIndex ( data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state ] )  > =  data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state + 1 ] ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  submatrixRows  =  actionsWithNonNegativeReward ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                //enable one row for the statesWithRewardForAllChoices so that the rowgroups will not be deleted when taking the submatrix
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                for ( auto  state  :  statesWithNegativeRewardForAllChoices )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    submatrixRows . set ( data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state ] ,  true ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  allStates ( data . preprocessedModel . getNumberOfStates ( ) ,  true ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : SparseMatrix < ValueType >  transitionsWithNonNegativeReward  =  data . preprocessedModel . getTransitionMatrix ( ) . getSubmatrix ( false ,  submatrixRows ,  allStates ,  true ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                STORM_LOG_ASSERT ( data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupCount ( )  = =  transitionsWithNonNegativeReward . getRowGroupCount ( ) ,  " Row group count mismatch. " ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  statesNeverReachingNegativeRewardForSomeScheduler  =  storm : : utility : : graph : : performProb0E ( transitionsWithNonNegativeReward ,  transitionsWithNonNegativeReward . getRowGroupIndices ( ) ,  transitionsWithNonNegativeReward . transpose ( true ) ,  allStates ,  statesWithNegativeRewardForAllChoices ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                storm : : storage : : BitVector  statesReachingNegativeRewardsFinitelyOftenForSomeScheduler  =  storm : : utility : : graph : : performProb1E ( data . preprocessedModel . getTransitionMatrix ( ) ,  data . preprocessedModel . getTransitionMatrix ( ) . getRowGroupIndices ( ) ,  data . preprocessedModel . getBackwardTransitions ( ) ,  allStates ,  statesNeverReachingNegativeRewardForSomeScheduler ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                auto  subsystemBuilderResult  =  storm : : transformer : : SubsystemBuilder < SparseModelType > : : transform ( data . preprocessedModel ,  statesReachingNegativeRewardsFinitelyOftenForSomeScheduler ,  storm : : storage : : BitVector ( data . preprocessedModel . getTransitionMatrix ( ) . getRowCount ( ) ,  true ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                data . preprocessedModel  =  std : : move ( * subsystemBuilderResult . model ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                // subsystemBuilderResult.newToOldStateIndexMapping now reffers to the indices of the model we had before building the subsystem
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                for ( auto  &  originalModelStateIndex  :  subsystemBuilderResult . newToOldStateIndexMapping ) {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    originalModelStateIndex  =  data . newToOldStateIndexMapping [ originalModelStateIndex ] ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                data . newToOldStateIndexMapping  =  std : : move ( subsystemBuilderResult . newToOldStateIndexMapping ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                return  ( ~ actionsWithNonNegativeReward )  %  subsystemBuilderResult . subsystemActions ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : assertPositiveRewardFiniteness ( PreprocessorData &  data ,  storm : : storage : : BitVector  const &  actionsWithNegativeReward )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                 
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                auto  mecDecomposition  =  storm : : storage : : MaximalEndComponentDecomposition < ValueType > ( data . preprocessedModel . getTransitionMatrix ( ) ,  data . preprocessedModel . getBackwardTransitions ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                if ( mecDecomposition . empty ( ) )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    return ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                for ( uint_fast64_t  objIndex  =  0 ;  objIndex  <  data . objectives . size ( ) ;  + + objIndex )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    auto &  obj  =  data . objectives [ objIndex ] ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    if  ( ! obj . rewardFinitenessChecked  & &  obj . rewardsArePositive )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        obj . rewardFinitenessChecked  =  true ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        // Find maximal end components that contain a state with positive reward
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        storm : : storage : : BitVector  actionsWithPositiveRewards  =  storm : : utility : : vector : : filterGreaterZero ( data . preprocessedModel . getRewardModel ( obj . rewardModelName ) . getStateActionRewardVector ( ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        for ( auto  const &  mec  :  mecDecomposition )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                            bool  ecHasActionWithPositiveReward  =  false ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                            for ( auto  const &  stateActionsPair  :  mec )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                for ( auto  const &  action  :  stateActionsPair . second )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                    STORM_LOG_THROW ( ! actionsWithNegativeReward . get ( action ) ,  storm : : exceptions : : InvalidPropertyException ,  " Found an end componet that contains rewards for a maximizing and a minimizing objective. This is not supported " ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                    // Note: we could also check whether some sub EC exists that does not contain negative rewards.
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                    ecHasActionWithPositiveReward  | =  ( actionsWithPositiveRewards . get ( action ) ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                            }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                            if ( ecHasActionWithPositiveReward )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                STORM_LOG_DEBUG ( " Found end component that contains positive rewards for current objective  "  < <  * obj . originalFormula  < <  " . " ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                data . objectivesSolvedInPreprocessing . set ( objIndex ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                                break ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                            }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                        }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            template < typename  SparseModelType >  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            void  SparseMultiObjectivePreprocessor < SparseModelType > : : updatePreprocessedModel ( PreprocessorData &  data ,  SparseModelType &  newPreprocessedModel ,  std : : vector < uint_fast64_t > &  newToOldStateIndexMapping )  {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                data . preprocessedModel  =  std : : move ( newPreprocessedModel ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                // the given newToOldStateIndexMapping reffers to the indices of the former preprocessedModel as 'old indices'
  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                for ( auto  &  preprocessedModelStateIndex  :  newToOldStateIndexMapping ) {  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                    preprocessedModelStateIndex  =  data . newToOldStateIndexMapping [ preprocessedModelStateIndex ] ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				                data . newToOldStateIndexMapping  =  std : : move ( newToOldStateIndexMapping ) ;  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				            }  
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				 
				 
				 
				             
			
		 
		
	
		
			
				 
				 
				            template  class  SparseMultiObjectivePreprocessor < storm : : models : : sparse : : Mdp < double > > ;  
				 
				 
				            template  class  SparseMultiObjectivePreprocessor < storm : : models : : sparse : : Mdp < double > > ;