@ -305,7 +305,7 @@ namespace storm {
// Initialize the solution vector.
std : : vector < ValueType > x = hint . hasValueHint ( ) ? std : : move ( hint . getValueHint ( ) ) : std : : vector < ValueType > ( submatrix . getRowGroupCount ( ) , hint . hasLowerResultBound ( ) ? hint . getLowerResultBound ( ) : storm : : utility : : zero < ValueType > ( ) ) ;
// Solve the corresponding system of equations.
solver - > solveEquations ( x , b ) ;
@ -423,10 +423,10 @@ namespace storm {
struct SparseMdpEndComponentInformation {
SparseMdpEndComponentInformation ( storm : : storage : : MaximalEndComponentDecomposition < ValueType > const & endComponentDecomposition , storm : : storage : : BitVector const & maybeStates ) : eliminatedEndComponents ( false ) , numberOfMaybeStatesInEc ( 0 ) , numberOfMaybeStatesNotInEc ( 0 ) , numberOfEc ( endComponentDecomposition . size ( ) ) {
// (0 ) Compute how many maybe states there are before each other maybe state.
// (1 ) Compute how many maybe states there are before each other maybe state.
maybeStatesBefore = maybeStates . getNumberOfSetBitsBeforeIndices ( ) ;
// (1 ) Create mapping from maybe states to their MEC. If they are not contained in an MEC, their value
// (2 ) Create mapping from maybe states to their MEC. If they are not contained in an MEC, their value
// is set to a special constant.
maybeStateToEc . resize ( maybeStates . getNumberOfSetBits ( ) , NOT_IN_EC ) ;
uint64_t mecIndex = 0 ;
@ -437,6 +437,9 @@ namespace storm {
}
+ + mecIndex ;
}
// (3) Compute number of states not in MECs.
numberOfMaybeStatesNotInEc = maybeStateToEc . size ( ) - numberOfMaybeStatesInEc ;
}
bool isMaybeStateInEc ( uint64_t maybeState ) const {
@ -467,6 +470,10 @@ namespace storm {
return maybeStateToEc [ maybeStatesBefore [ state ] ] ;
}
uint64_t getSubmatrixRowGroupOfStateInEc ( uint64_t state ) const {
return numberOfMaybeStatesNotInEc + getEc ( state ) ;
}
bool eliminatedEndComponents ;
std : : vector < uint64_t > maybeStatesBefore ;
@ -478,37 +485,48 @@ namespace storm {
} ;
template < typename ValueType >
SparseMdpEndComponentInformation < ValueType > eliminateEndComponents ( storm : : storage : : MaximalEndComponentDecomposition < ValueType > const & endComponentDecomposition , storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , QualitativeStateSetsUntilProbabilities const & qualitativeStateSets , storm : : storage : : SparseMatrix < ValueType > & submatrix , std : : vector < ValueType > & b ) {
SparseMdpEndComponentInformation < ValueType > eliminateEndComponents ( storm : : storage : : MaximalEndComponentDecomposition < ValueType > const & endComponentDecomposition , storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : BitVector const & maybeStates , storm : : storage : : BitVector const * sumColumns , storm : : storage : : BitVector const * selectedChoices , std : : vector < ValueType > const * summand , storm : : storage : : SparseMatrix < ValueType > & submatrix , std : : vector < ValueType > & b ) {
SparseMdpEndComponentInformation < ValueType > result ( endComponentDecomposition , qualitativeStateSets . maybeStates ) ;
SparseMdpEndComponentInformation < ValueType > result ( endComponentDecomposition , maybeStates ) ;
// (2 ) Compute the number of maybe states not in ECs before any other maybe state.
// (1 ) Compute the number of maybe states not in ECs before any other maybe state.
std : : vector < uint64_t > maybeStatesNotInEcBefore = result . getNumberOfMaybeStatesNotInEcBeforeIndices ( ) ;
uint64_t numberOfMaybeStatesNotInEc = qualitativeStateSets . maybeStates . getNumberOfSetBits ( ) - result . numberOfMaybeStatesInEc ;
// Create temporary vector storing possible transitions to ECs.
std : : vector < std : : pair < uint64_t , ValueType > > ecValuePairs ;
// (3) Create the parts of the submatrix and vector b that belong to states not contained in ECs.
storm : : storage : : SparseMatrixBuilder < ValueType > builder ( 0 , 0 , 0 , false , true , result . numberOfMaybeStatesNotInEc + result . numberOfEc ) ;
b . resize ( result . numberOfMaybeStatesNotInEc + result . numberOfEc ) ;
// (2) Create the parts of the submatrix and vector b that belong to states not contained in ECs.
uint64_t numberOfStates = result . numberOfMaybeStatesNotInEc + result . numberOfEc ;
STORM_LOG_TRACE ( " Found " < < numberOfStates < < " states, " < < result . numberOfMaybeStatesNotInEc < < " not in ECs, " < < result . numberOfMaybeStatesInEc < < " in ECs and " < < result . numberOfEc < < " ECs. " ) ;
storm : : storage : : SparseMatrixBuilder < ValueType > builder ( 0 , numberOfStates , 0 , true , true , numberOfStates ) ;
b . resize ( numberOfStates ) ;
uint64_t currentRow = 0 ;
for ( auto state : qualitativeStateSets . maybeStates ) {
for ( auto state : maybeStates ) {
if ( ! result . isStateInEc ( state ) ) {
builder . newRowGroup ( currentRow ) ;
for ( uint64_t row = transitionMatrix . getRowGroupIndices ( ) [ state ] , endRow = transitionMatrix . getRowGroupIndices ( ) [ state + 1 ] ; row < endRow ; + + row , + + currentRow ) {
for ( uint64_t row = transitionMatrix . getRowGroupIndices ( ) [ state ] , endRow = transitionMatrix . getRowGroupIndices ( ) [ state + 1 ] ; row < endRow ; + + row ) {
// If the choices is not in the selected ones, drop it.
if ( selectedChoices & & ! selectedChoices - > get ( row ) ) {
continue ;
}
ecValuePairs . clear ( ) ;
if ( summand ) {
b [ currentRow ] + = ( * summand ) [ row ] ;
}
for ( auto const & e : transitionMatrix . getRow ( row ) ) {
if ( qualitativeStateSets . statesWithProbability1 . get ( e . getColumn ( ) ) ) {
if ( sumColumns & & sumColumns - > get ( e . getColumn ( ) ) ) {
b [ currentRow ] + = e . getValue ( ) ;
} else if ( qualitativeStateSets . maybeStates . get ( e . getColumn ( ) ) ) {
} else if ( maybeStates . get ( e . getColumn ( ) ) ) {
// If the target state of the transition is not contained in an EC, we can just add the entry.
if ( result . isStateInEc ( e . getColumn ( ) ) ) {
builder . addNextValue ( currentRow , maybeStatesNotInEcBefore [ result . maybeStatesBefore [ e . getColumn ( ) ] ] , e . getValue ( ) ) ;
} else {
// Otherwise, we store the information that the state can go to a certain EC.
ecValuePairs . push_back ( std : : make_pair ( result . getEc ( e . getColumn ( ) ) , e . getValue ( ) ) ) ;
ecValuePairs . emplace_back ( result . getEc ( e . getColumn ( ) ) , e . getValue ( ) ) ;
}
}
}
@ -517,16 +535,19 @@ namespace storm {
std : : sort ( ecValuePairs . begin ( ) , ecValuePairs . end ( ) ) ;
for ( auto const & e : ecValuePairs ) {
builder . addNextValue ( currentRow , numberOfMaybeStatesNotInEc + e . first , e . second ) ;
builder . addNextValue ( currentRow , result . numberOfMaybeStatesNotInEc + e . first , e . second ) ;
}
}
+ + currentRow ;
}
}
}
// (4 ) Create the parts of the submatrix and vector b that belong to states contained in ECs.
// (3 ) Create the parts of the submatrix and vector b that belong to states contained in ECs.
for ( auto const & mec : endComponentDecomposition ) {
builder . newRowGroup ( currentRow ) ;
for ( auto const & stateActions : mec ) {
uint64_t const & state = stateActions . first ;
for ( uint64_t row = transitionMatrix . getRowGroupIndices ( ) [ state ] , endRow = transitionMatrix . getRowGroupIndices ( ) [ state + 1 ] ; row < endRow ; + + row ) {
@ -534,19 +555,26 @@ namespace storm {
if ( stateActions . second . find ( row ) ! = stateActions . second . end ( ) ) {
continue ;
}
// If the choices is not in the selected ones, drop it.
if ( selectedChoices & & ! selectedChoices - > get ( row ) ) {
continue ;
}
ecValuePairs . clear ( ) ;
if ( summand ) {
b [ currentRow ] + = ( * summand ) [ row ] ;
}
for ( auto const & e : transitionMatrix . getRow ( row ) ) {
if ( qualitativeStateSets . statesWithProbability1 . get ( e . getColumn ( ) ) ) {
if ( sumColumns & & sumColumns - > get ( e . getColumn ( ) ) ) {
b [ currentRow ] + = e . getValue ( ) ;
} else if ( qualitativeStateSets . maybeStates . get ( e . getColumn ( ) ) ) {
} else if ( maybeStates . get ( e . getColumn ( ) ) ) {
// If the target state of the transition is not contained in an EC, we can just add the entry.
if ( result . isStateInEc ( e . getColumn ( ) ) ) {
builder . addNextValue ( currentRow , maybeStatesNotInEcBefore [ result . maybeStatesBefore [ e . getColumn ( ) ] ] , e . getValue ( ) ) ;
} else {
// Otherwise, we store the information that the state can go to a certain EC.
ecValuePairs . push_back ( std : : make_pair ( result . getEc ( e . getColumn ( ) ) , e . getValue ( ) ) ) ;
ecValuePairs . emplace_back ( result . getEc ( e . getColumn ( ) ) , e . getValue ( ) ) ;
}
}
}
@ -555,7 +583,7 @@ namespace storm {
std : : sort ( ecValuePairs . begin ( ) , ecValuePairs . end ( ) ) ;
for ( auto const & e : ecValuePairs ) {
builder . addNextValue ( currentRow , numberOfMaybeStatesNotInEc + e . first , e . second ) ;
builder . addNextValue ( currentRow , result . numberOfMaybeStatesNotInEc + e . first , e . second ) ;
}
}
@ -565,7 +593,6 @@ namespace storm {
}
submatrix = builder . build ( ) ;
return result ;
}
@ -578,7 +605,7 @@ namespace storm {
// Only do more work if there are actually end-components.
if ( ! endComponentDecomposition . empty ( ) ) {
STORM_LOG_DEBUG ( " Eliminating " < < endComponentDecomposition . size ( ) < < " ECs. " ) ;
return eliminateEndComponents ( endComponentDecomposition , transitionMatrix , qualitativeStateSets , submatrix , b ) ;
return eliminateEndComponents < ValueType > ( endComponentDecomposition , transitionMatrix , qualitativeStateSets . maybeStates , & qualitativeStateSets . statesWithProbability1 , nullptr , nullptr , submatrix , b ) ;
} else {
STORM_LOG_DEBUG ( " Not eliminating ECs as there are none. " ) ;
computeFixedPointSystemUntilProbabilities ( transitionMatrix , qualitativeStateSets , submatrix , b ) ;
@ -591,7 +618,7 @@ namespace storm {
auto notInEcResultIt = result . begin ( ) ;
for ( auto state : maybeStates ) {
if ( ecInformation . isStateInEc ( state ) ) {
result [ state ] = result [ ecInformation . numberOfMaybeStatesNotInEc + ecInformation . get Ec( state ) ] ;
result [ state ] = result [ ecInformation . getSubmatrixRowGroupOfStateIn Ec( state ) ] ;
} else {
result [ state ] = * notInEcResultIt ;
+ + notInEcResultIt ;
@ -635,7 +662,7 @@ namespace storm {
storm : : storage : : SparseMatrix < ValueType > submatrix ;
std : : vector < ValueType > b ;
// If the hint information tells us that we have to do an (M)EC decomposition, we compute one now.
// If the hint information tells us that we have to eliminate MECs, we do so now.
boost : : optional < SparseMdpEndComponentInformation < ValueType > > ecInformation ;
if ( hintInformation . getEliminateEndComponents ( ) ) {
ecInformation = computeFixedPointSystemUntilProbabilitiesEliminateEndComponents ( transitionMatrix , backwardTransitions , qualitativeStateSets , submatrix , b ) ;
@ -643,6 +670,7 @@ namespace storm {
// Make sure we are not supposed to produce a scheduler if we actually eliminate end components.
STORM_LOG_THROW ( ! ecInformation | | ! ecInformation . get ( ) . eliminatedEndComponents | | ! produceScheduler , storm : : exceptions : : NotSupportedException , " Producing schedulers is not supported if end-components need to be eliminated for the solver. " ) ;
} else {
// Otherwise, we compute the standard equations.
computeFixedPointSystemUntilProbabilities ( transitionMatrix , qualitativeStateSets , submatrix , b ) ;
}
@ -841,6 +869,96 @@ namespace storm {
}
}
template < typename ValueType >
void extractSchedulerChoices ( storm : : storage : : Scheduler < ValueType > & scheduler , storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , std : : vector < uint_fast64_t > const & subChoices , storm : : storage : : BitVector const & maybeStates , boost : : optional < storm : : storage : : BitVector > const & selectedChoices ) {
auto subChoiceIt = subChoices . begin ( ) ;
if ( selectedChoices ) {
for ( auto maybeState : maybeStates ) {
// find the rowindex that corresponds to the selected row of the submodel
uint_fast64_t firstRowIndex = transitionMatrix . getRowGroupIndices ( ) [ maybeState ] ;
uint_fast64_t selectedRowIndex = selectedChoices - > getNextSetIndex ( firstRowIndex ) ;
for ( uint_fast64_t choice = 0 ; choice < * subChoiceIt ; + + choice ) {
selectedRowIndex = selectedChoices - > getNextSetIndex ( selectedRowIndex + 1 ) ;
}
scheduler . setChoice ( selectedRowIndex - firstRowIndex , maybeState ) ;
+ + subChoiceIt ;
}
} else {
for ( auto maybeState : maybeStates ) {
scheduler . setChoice ( * subChoiceIt , maybeState ) ;
+ + subChoiceIt ;
}
}
assert ( subChoiceIt = = subChoices . end ( ) ) ;
}
template < typename ValueType >
void computeFixedPointSystemReachabilityRewards ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , QualitativeStateSetsReachabilityRewards const & qualitativeStateSets , boost : : optional < storm : : storage : : BitVector > const & selectedChoices , std : : function < std : : vector < ValueType > ( uint_fast64_t , storm : : storage : : SparseMatrix < ValueType > const & , storm : : storage : : BitVector const & ) > const & totalStateRewardVectorGetter , storm : : storage : : SparseMatrix < ValueType > & submatrix , std : : vector < ValueType > & b ) {
// Remove rows and columns from the original transition probability matrix for states whose reward values are already known.
// If there are infinity states, we additionally have to remove choices of maybeState that lead to infinity.
if ( qualitativeStateSets . infinityStates . empty ( ) ) {
submatrix = transitionMatrix . getSubmatrix ( true , qualitativeStateSets . maybeStates , qualitativeStateSets . maybeStates , false ) ;
b = totalStateRewardVectorGetter ( submatrix . getRowCount ( ) , transitionMatrix , qualitativeStateSets . maybeStates ) ;
} else {
submatrix = transitionMatrix . getSubmatrix ( false , * selectedChoices , qualitativeStateSets . maybeStates , false ) ;
b = totalStateRewardVectorGetter ( transitionMatrix . getRowCount ( ) , transitionMatrix , storm : : storage : : BitVector ( transitionMatrix . getRowGroupCount ( ) , true ) ) ;
storm : : utility : : vector : : filterVectorInPlace ( b , * selectedChoices ) ;
}
}
template < typename ValueType >
boost : : optional < SparseMdpEndComponentInformation < ValueType > > computeFixedPointSystemReachabilityRewardsEliminateEndComponents ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : SparseMatrix < ValueType > const & backwardTransitions , QualitativeStateSetsReachabilityRewards const & qualitativeStateSets , boost : : optional < storm : : storage : : BitVector > const & selectedChoices , std : : function < std : : vector < ValueType > ( uint_fast64_t , storm : : storage : : SparseMatrix < ValueType > const & , storm : : storage : : BitVector const & ) > const & totalStateRewardVectorGetter , storm : : storage : : SparseMatrix < ValueType > & submatrix , std : : vector < ValueType > & b ) {
// Start by computing the choices with reward 0, as we only want ECs within this fragment.
storm : : storage : : BitVector zeroRewardChoices ( transitionMatrix . getRowCount ( ) ) ;
// Get the rewards of all choices.
std : : vector < ValueType > rewardVector = totalStateRewardVectorGetter ( transitionMatrix . getRowCount ( ) , transitionMatrix , storm : : storage : : BitVector ( transitionMatrix . getRowGroupCount ( ) , true ) ) ;
uint64_t index = 0 ;
for ( auto const & e : rewardVector ) {
if ( storm : : utility : : isZero ( e ) ) {
zeroRewardChoices . set ( index ) ;
}
+ + index ;
}
// Compute the states that have some zero reward choice.
storm : : storage : : BitVector candidateStates ( qualitativeStateSets . maybeStates ) ;
for ( auto state : qualitativeStateSets . maybeStates ) {
bool keepState = false ;
for ( auto row = transitionMatrix . getRowGroupIndices ( ) [ state ] , rowEnd = transitionMatrix . getRowGroupIndices ( ) [ state + 1 ] ; row < rowEnd ; + + row ) {
if ( zeroRewardChoices . get ( row ) ) {
keepState = true ;
break ;
}
}
if ( ! keepState ) {
candidateStates . set ( state , false ) ;
}
}
bool doDecomposition = ! candidateStates . empty ( ) ;
storm : : storage : : MaximalEndComponentDecomposition < ValueType > endComponentDecomposition ;
if ( doDecomposition ) {
// Then compute the states that are in MECs with zero reward.
endComponentDecomposition = storm : : storage : : MaximalEndComponentDecomposition < ValueType > ( transitionMatrix , backwardTransitions , candidateStates , zeroRewardChoices ) ;
}
// Only do more work if there are actually end-components.
if ( doDecomposition & & ! endComponentDecomposition . empty ( ) ) {
STORM_LOG_DEBUG ( " Eliminating " < < endComponentDecomposition . size ( ) < < " ECs. " ) ;
return eliminateEndComponents < ValueType > ( endComponentDecomposition , transitionMatrix , qualitativeStateSets . maybeStates , nullptr , selectedChoices ? & selectedChoices . get ( ) : nullptr , & rewardVector , submatrix , b ) ;
} else {
STORM_LOG_DEBUG ( " Not eliminating ECs as there are none. " ) ;
computeFixedPointSystemReachabilityRewards ( transitionMatrix , qualitativeStateSets , selectedChoices , totalStateRewardVectorGetter , submatrix , b ) ;
return boost : : none ;
}
}
template < typename ValueType >
MDPSparseModelCheckingHelperReturnType < ValueType > SparseMdpPrctlHelper < ValueType > : : computeReachabilityRewardsHelper ( storm : : solver : : SolveGoal const & goal , storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : SparseMatrix < ValueType > const & backwardTransitions , std : : function < std : : vector < ValueType > ( uint_fast64_t , storm : : storage : : SparseMatrix < ValueType > const & , storm : : storage : : BitVector const & ) > const & totalStateRewardVectorGetter , storm : : storage : : BitVector const & targetStates , bool qualitative , bool produceScheduler , storm : : solver : : MinMaxLinearEquationSolverFactory < ValueType > const & minMaxLinearEquationSolverFactory , ModelCheckerHint const & hint ) {
@ -866,54 +984,45 @@ namespace storm {
} else {
if ( ! qualitativeStateSets . maybeStates . empty ( ) ) {
// In this case we have to compute the reward values for the remaining states.
// Store the choices that lead to non-infinity values. If none, all choices im maybe states can be selected.
boost : : optional < storm : : storage : : BitVector > selectedChoices ;
if ( ! qualitativeStateSets . infinityStates . empty ( ) ) {
selectedChoices = transitionMatrix . getRowFilter ( qualitativeStateSets . maybeStates , ~ qualitativeStateSets . infinityStates ) ;
}
// Obtain proper hint information either from the provided hint or from requirements of the solver.
SparseMdpHintType < ValueType > hintInformation = computeHints ( storm : : solver : : EquationSystemType : : ReachabilityRewards , hint , goal . direction ( ) , transitionMatrix , backwardTransitions , qualitativeStateSets . maybeStates , ~ targetStates , targetStates , minMaxLinearEquationSolverFactory , selectedChoices ) ;
// Prepare matrix and vector for the equation system.
// Declare the components of the equation system we will solve .
storm : : storage : : SparseMatrix < ValueType > submatrix ;
std : : vector < ValueType > b ;
// Remove rows and columns from the original transition probability matrix for states whose reward values are already known.
// If there are infinity states, we additionaly have to remove choices of maybeState that lead to infinity
boost : : optional < storm : : storage : : BitVector > selectedChoices ; // if not given, all maybeState choices are selected
if ( qualitativeStateSets . infinityStates . empty ( ) ) {
submatrix = transitionMatrix . getSubmatrix ( true , qualitativeStateSets . maybeStates , qualitativeStateSets . maybeStates , false ) ;
b = totalStateRewardVectorGetter ( submatrix . getRowCount ( ) , transitionMatrix , qualitativeStateSets . maybeStates ) ;
// If the hint information tells us that we have to eliminate MECs, we do so now.
boost : : optional < SparseMdpEndComponentInformation < ValueType > > ecInformation ;
if ( hintInformation . getEliminateEndComponents ( ) ) {
ecInformation = computeFixedPointSystemReachabilityRewardsEliminateEndComponents ( transitionMatrix , backwardTransitions , qualitativeStateSets , selectedChoices , totalStateRewardVectorGetter , submatrix , b ) ;
// Make sure we are not supposed to produce a scheduler if we actually eliminate end components.
STORM_LOG_THROW ( ! ecInformation | | ! ecInformation . get ( ) . eliminatedEndComponents | | ! produceScheduler , storm : : exceptions : : NotSupportedException , " Producing schedulers is not supported if end-components need to be eliminated for the solver. " ) ;
} else {
selectedChoices = transitionMatrix . getRowFilter ( qualitativeStateSets . maybeStates , ~ qualitativeStateSets . infinityStates ) ;
submatrix = transitionMatrix . getSubmatrix ( false , * selectedChoices , qualitativeStateSets . maybeStates , false ) ;
b = totalStateRewardVectorGetter ( transitionMatrix . getRowCount ( ) , transitionMatrix , storm : : storage : : BitVector ( transitionMatrix . getRowGroupCount ( ) , true ) ) ;
storm : : utility : : vector : : filterVectorInPlace ( b , * selectedChoices ) ;
// Otherwise, we compute the standard equations.
computeFixedPointSystemReachabilityRewards ( transitionMatrix , qualitativeStateSets , selectedChoices , totalStateRewardVectorGetter , submatrix , b ) ;
}
// Obtain proper hint information either from the provided hint or from requirements of the solver.
SparseMdpHintType < ValueType > hintInformation = computeHints ( storm : : solver : : EquationSystemType : : ReachabilityRewards , hint , goal . direction ( ) , transitionMatrix , backwardTransitions , qualitativeStateSets . maybeStates , ~ targetStates , targetStates , minMaxLinearEquationSolverFactory , selectedChoices ) ;
// Now compute the results for the maybe states.
MaybeStateResult < ValueType > resultForMaybeStates = computeValuesForMaybeStates ( goal , submatrix , b , produceScheduler , minMaxLinearEquationSolverFactory , hintInformation ) ;
// Set values of resulting vector according to result.
storm : : utility : : vector : : setVectorValues < ValueType > ( result , qualitativeStateSets . maybeStates , resultForMaybeStates . getValues ( ) ) ;
// If we eliminated end components, we need to extract the result differently.
if ( ecInformation & & ecInformation . get ( ) . eliminatedEndComponents ) {
setResultValuesWrtEndComponents ( ecInformation . get ( ) , result , qualitativeStateSets . maybeStates , resultForMaybeStates . getValues ( ) ) ;
} else {
// Set values of resulting vector according to result.
storm : : utility : : vector : : setVectorValues < ValueType > ( result , qualitativeStateSets . maybeStates , resultForMaybeStates . getValues ( ) ) ;
}
if ( produceScheduler ) {
std : : vector < uint_fast64_t > const & subChoices = resultForMaybeStates . getScheduler ( ) ;
auto subChoiceIt = subChoices . begin ( ) ;
if ( selectedChoices ) {
for ( auto maybeState : qualitativeStateSets . maybeStates ) {
// find the rowindex that corresponds to the selected row of the submodel
uint_fast64_t firstRowIndex = transitionMatrix . getRowGroupIndices ( ) [ maybeState ] ;
uint_fast64_t selectedRowIndex = selectedChoices - > getNextSetIndex ( firstRowIndex ) ;
for ( uint_fast64_t choice = 0 ; choice < * subChoiceIt ; + + choice ) {
selectedRowIndex = selectedChoices - > getNextSetIndex ( selectedRowIndex + 1 ) ;
}
scheduler - > setChoice ( selectedRowIndex - firstRowIndex , maybeState ) ;
+ + subChoiceIt ;
}
} else {
for ( auto maybeState : qualitativeStateSets . maybeStates ) {
scheduler - > setChoice ( * subChoiceIt , maybeState ) ;
+ + subChoiceIt ;
}
}
assert ( subChoiceIt = = subChoices . end ( ) ) ;
extractSchedulerChoices ( * scheduler , transitionMatrix , resultForMaybeStates . getScheduler ( ) , qualitativeStateSets . maybeStates , selectedChoices ) ;
}
}
}