@ -46,7 +46,7 @@ namespace storm {
return result ;
}
template < typename ValueType , typename RewardModelType >
std : : vector < ValueType > SparseDtmcPrctlHelper < ValueType , RewardModelType > : : computeUntilProbabilities ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : SparseMatrix < ValueType > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , bool qualitative , storm : : utility : : solver : : LinearEquationSolverFactory < ValueType > const & linearEquationSolverFactory ) {
// We need to identify the states which have to be taken out of the matrix, i.e.
@ -154,7 +154,7 @@ namespace storm {
return result ;
}
template < typename ValueType , typename RewardModelType >
std : : vector < ValueType > SparseDtmcPrctlHelper < ValueType , RewardModelType > : : computeReachabilityRewards ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : SparseMatrix < ValueType > const & backwardTransitions , RewardModelType const & rewardModel , storm : : storage : : BitVector const & targetStates , bool qualitative , storm : : utility : : solver : : LinearEquationSolverFactory < ValueType > const & linearEquationSolverFactory ) {
return computeReachabilityRewards ( transitionMatrix , backwardTransitions , [ & ] ( uint_fast64_t numberOfRows , storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : BitVector const & maybeStates ) { return rewardModel . getTotalRewardVector ( numberOfRows , transitionMatrix , maybeStates ) ; } , targetStates , qualitative , linearEquationSolverFactory ) ;
@ -170,7 +170,7 @@ namespace storm {
} ,
targetStates , qualitative , linearEquationSolverFactory ) ;
}
template < typename ValueType , typename RewardModelType >
std : : vector < ValueType > SparseDtmcPrctlHelper < ValueType , RewardModelType > : : computeReachabilityRewards ( 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 , storm : : utility : : solver : : LinearEquationSolverFactory < ValueType > const & linearEquationSolverFactory ) {
@ -222,23 +222,26 @@ namespace storm {
return result ;
}
template < typename ValueType , typename RewardModelType >
std : : vector < ValueType > SparseDtmcPrctlHelper < ValueType , RewardModelType > : : computeLongRunAverageProbabilities ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : BitVector const & psiStates , bool qualitative , storm : : utility : : solver : : LinearEquationSolverFactory < ValueType > const & linearEquationSolverFactory ) {
return SparseCtmcCslHelper < ValueType > : : computeLongRunAverageProbabilities ( transitionMatrix , psiStates , nullptr , qualitative , linearEquationSolverFactory ) ;
}
template < typename ValueType , typename RewardModelType >
std : : vector < ValueType > SparseDtmcPrctlHelper < ValueType , RewardModelType > : : computeConditionalProbabilities ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : SparseMatrix < ValueType > const & backwardTransitions , storm : : storage : : BitVector const & targetStates , storm : : storage : : BitVector const & conditionStates , bool qualitative , storm : : utility : : solver : : LinearEquationSolverFactory < ValueType > const & linearEquationSolverFactory ) {
std : : vector < ValueType > probabilitiesToReachConditionStates = computeUntilProbabilities ( transitionMatrix , backwardTransitions , storm : : storage : : BitVector ( transitionMatrix . getRowCount ( ) , true ) , conditionStates , false , linearEquationSolverFactory ) ;
typename SparseDtmcPrctlHelper < ValueType , RewardModelType > : : BaierTransformedModel SparseDtmcPrctlHelper < ValueType , RewardModelType > : : computeBaierTransformation ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : SparseMatrix < ValueType > const & backwardTransitions , storm : : storage : : BitVector const & targetStates , storm : : storage : : BitVector const & conditionStates , boost : : optional < std : : vector < ValueType > > const & stateRewards , storm : : utility : : solver : : LinearEquationSolverFactory < ValueType > const & linearEquationSolverFactory ) {
BaierTransformedModel result ;
// Start by computing all 'before' states, i.e. the states for which the conditional probability is defined.
storm : : storage : : BitVector beforeStates ( targetStates . size ( ) , true ) ;
std : : vector < ValueType > probabilitiesToReachConditionStates = computeUntilProbabilities ( transitionMatrix , backwardTransitions , storm : : storage : : BitVector ( transitionMatrix . getRowCount ( ) , true ) , conditionStates , false , linearEquationSolverFactory ) ;
result . beforeStates = storm : : storage : : BitVector ( targetStates . size ( ) , true ) ;
uint_fast64_t state = 0 ;
uint_fast64_t beforeStateIndex = 0 ;
for ( auto const & value : probabilitiesToReachConditionStates ) {
if ( value = = storm : : utility : : zero < ValueType > ( ) ) {
beforeStates . set ( state , false ) ;
result . beforeStates . set ( state , false ) ;
} else {
probabilitiesToReachConditionStates [ beforeStateIndex ] = value ;
+ + beforeStateIndex ;
@ -246,35 +249,33 @@ namespace storm {
+ + state ;
}
probabilitiesToReachConditionStates . resize ( beforeStateIndex ) ;
// If there were any before states, we can compute their conditional probabilities. If not, the result
// is undefined for all states.
std : : vector < ValueType > result ( transitionMatrix . getRowCount ( ) , storm : : utility : : infinity < ValueType > ( ) ) ;
if ( targetStates . empty ( ) ) {
storm : : utility : : vector : : setVectorValues ( result , beforeStates , storm : : utility : : zero < ValueType > ( ) ) ;
} else if ( ! beforeStates . empty ( ) ) {
result . noTargetStates = true ;
return result ;
} else if ( ! result . beforeStates . empty ( ) ) {
// If there are some states for which the conditional probability is defined and there are some
// states that can reach the target states without visiting condition states first, we need to
// do more work.
// First, compute the relevant states and some offsets.
storm : : storage : : BitVector allStates ( targetStates . size ( ) , true ) ;
std : : vector < uint_fast64_t > numberOfBeforeStatesUpToState = beforeStates . getNumberOfSetBitsBeforeIndices ( ) ;
std : : vector < uint_fast64_t > numberOfBeforeStatesUpToState = result . beforeStates . getNumberOfSetBitsBeforeIndices ( ) ;
storm : : storage : : BitVector statesWithProbabilityGreater0 = storm : : utility : : graph : : performProbGreater0 ( backwardTransitions , allStates , targetStates ) ;
statesWithProbabilityGreater0 & = storm : : utility : : graph : : getReachableStates ( transitionMatrix , conditionStates , allStates , targetStates ) ;
uint_fast64_t normalStatesOffset = beforeStates . getNumberOfSetBits ( ) ;
uint_fast64_t normalStatesOffset = result . beforeStates . getNumberOfSetBits ( ) ;
std : : vector < uint_fast64_t > numberOfNormalStatesUpToState = statesWithProbabilityGreater0 . getNumberOfSetBitsBeforeIndices ( ) ;
// All transitions going to states with probability zero, need to be redirected to a deadlock state.
bool addDeadlockState = false ;
uint_fast64_t deadlockState = normalStatesOffset + statesWithProbabilityGreater0 . getNumberOfSetBits ( ) ;
// Now, we create the matrix of 'before' and 'normal' states.
storm : : storage : : SparseMatrixBuilder < ValueType > builder ;
// Start by creating the transitions of the 'before' states.
uint_fast64_t currentRow = 0 ;
for ( auto beforeState : beforeStates ) {
for ( auto beforeState : result . beforeStates ) {
if ( conditionStates . get ( beforeState ) ) {
// For condition states, we move to the 'normal' states.
ValueType zeroProbability = storm : : utility : : zero < ValueType > ( ) ;
@ -291,7 +292,7 @@ namespace storm {
} else {
// For non-condition states, we scale the probabilities going to other before states.
for ( auto const & successorEntry : transitionMatrix . getRow ( beforeState ) ) {
if ( beforeStates . get ( successorEntry . getColumn ( ) ) ) {
if ( result . beforeStates . get ( successorEntry . getColumn ( ) ) ) {
builder . addNextValue ( currentRow , numberOfBeforeStatesUpToState [ successorEntry . getColumn ( ) ] , successorEntry . getValue ( ) * probabilitiesToReachConditionStates [ numberOfBeforeStatesUpToState [ successorEntry . getColumn ( ) ] ] / probabilitiesToReachConditionStates [ currentRow ] ) ;
}
}
@ -320,21 +321,84 @@ namespace storm {
}
// Build the new transition matrix and the new targets.
storm : : storage : : SparseMatrix < ValueType > newT ransitionMatrix = builder . build ( ) ;
storm : : storage : : BitVector newTargetStates = targetStates % beforeStates ;
newTargetStates . resize ( newTransitionMatrix . getRowCount ( ) ) ;
result . t ransitionMatrix = builder . build ( ) ;
storm : : storage : : BitVector newTargetStates = targetStates % result . beforeStates ;
newTargetStates . resize ( result . transitionMatrix . get ( ) . getRowCount ( ) ) ;
for ( auto state : targetStates % statesWithProbabilityGreater0 ) {
newTargetStates . set ( normalStatesOffset + state , true ) ;
}
result . targetStates = std : : move ( newTargetStates ) ;
// If a reward model was given, we need to compute the rewards for the transformed model.
if ( stateRewards ) {
std : : vector < ValueType > newStateRewards ( result . beforeStates . getNumberOfSetBits ( ) ) ;
storm : : utility : : vector : : selectVectorValues ( newStateRewards , result . beforeStates , stateRewards . get ( ) ) ;
newStateRewards . reserve ( newStateRewards . size ( ) + statesWithProbabilityGreater0 . getNumberOfSetBits ( ) + 1 ) ;
for ( auto state : statesWithProbabilityGreater0 ) {
newStateRewards . push_back ( stateRewards . get ( ) [ state ] ) ;
}
// Add a zero reward to the deadlock state.
newStateRewards . push_back ( storm : : utility : : zero < ValueType > ( ) ) ;
result . stateRewards = std : : move ( newStateRewards ) ;
}
// Finally, compute the conditional probabiltities by a reachability query.
std : : vector < ValueType > conditionalProbabilities = computeUntilProbabilities ( newTransitionMatrix , newTransitionMatrix . transpose ( ) , storm : : storage : : BitVector ( newTransitionMatrix . getRowCount ( ) , true ) , newTargetStates , qualitative , linearEquationSolverFactory ) ;
storm : : utility : : vector : : setVectorValues ( result , beforeStates , conditionalProbabilities ) ;
}
return result ;
}
template < typename ValueType , typename RewardModelType >
std : : vector < ValueType > SparseDtmcPrctlHelper < ValueType , RewardModelType > : : computeConditionalProbabilities ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : SparseMatrix < ValueType > const & backwardTransitions , storm : : storage : : BitVector const & targetStates , storm : : storage : : BitVector const & conditionStates , bool qualitative , storm : : utility : : solver : : LinearEquationSolverFactory < ValueType > const & linearEquationSolverFactory ) {
// Prepare result vector.
std : : vector < ValueType > result ( transitionMatrix . getRowCount ( ) , storm : : utility : : infinity < ValueType > ( ) ) ;
if ( ! conditionStates . empty ( ) ) {
BaierTransformedModel transformedModel = computeBaierTransformation ( transitionMatrix , backwardTransitions , targetStates , conditionStates , boost : : none , linearEquationSolverFactory ) ;
if ( transformedModel . noTargetStates ) {
storm : : utility : : vector : : setVectorValues ( result , transformedModel . beforeStates , storm : : utility : : zero < ValueType > ( ) ) ;
} else {
// At this point, we do not need to check whether there are 'before' states, since the condition
// states were non-empty so there is at least one state with a positive probability of satisfying
// the condition.
// Now compute reachability probabilities in the transformed model.
storm : : storage : : SparseMatrix < ValueType > const & newTransitionMatrix = transformedModel . transitionMatrix . get ( ) ;
std : : vector < ValueType > conditionalProbabilities = computeUntilProbabilities ( newTransitionMatrix , newTransitionMatrix . transpose ( ) , storm : : storage : : BitVector ( newTransitionMatrix . getRowCount ( ) , true ) , transformedModel . targetStates . get ( ) , qualitative , linearEquationSolverFactory ) ;
storm : : utility : : vector : : setVectorValues ( result , transformedModel . beforeStates , conditionalProbabilities ) ;
}
}
return result ;
}
template < typename ValueType , typename RewardModelType >
std : : vector < ValueType > SparseDtmcPrctlHelper < ValueType , RewardModelType > : : computeConditionalRewards ( storm : : storage : : SparseMatrix < ValueType > const & transitionMatrix , storm : : storage : : SparseMatrix < ValueType > const & backwardTransitions , RewardModelType const & rewardModel , storm : : storage : : BitVector const & targetStates , storm : : storage : : BitVector const & conditionStates , bool qualitative , storm : : utility : : solver : : LinearEquationSolverFactory < ValueType > const & linearEquationSolverFactory ) {
// Prepare result vector.
std : : vector < ValueType > result ( transitionMatrix . getRowCount ( ) , storm : : utility : : infinity < ValueType > ( ) ) ;
if ( ! conditionStates . empty ( ) ) {
BaierTransformedModel transformedModel = computeBaierTransformation ( transitionMatrix , backwardTransitions , targetStates , conditionStates , rewardModel . getTotalRewardVector ( transitionMatrix ) , linearEquationSolverFactory ) ;
if ( transformedModel . noTargetStates ) {
storm : : utility : : vector : : setVectorValues ( result , transformedModel . beforeStates , storm : : utility : : zero < ValueType > ( ) ) ;
} else {
// At this point, we do not need to check whether there are 'before' states, since the condition
// states were non-empty so there is at least one state with a positive probability of satisfying
// the condition.
// Now compute reachability probabilities in the transformed model.
storm : : storage : : SparseMatrix < ValueType > const & newTransitionMatrix = transformedModel . transitionMatrix . get ( ) ;
std : : vector < ValueType > conditionalProbabilities = computeUntilProbabilities ( newTransitionMatrix , newTransitionMatrix . transpose ( ) , storm : : storage : : BitVector ( newTransitionMatrix . getRowCount ( ) , true ) , transformedModel . targetStates . get ( ) , qualitative , linearEquationSolverFactory ) ;
storm : : utility : : vector : : setVectorValues ( result , transformedModel . beforeStates , conditionalProbabilities ) ;
}
}
return result ;
}
template class SparseDtmcPrctlHelper < double > ;
}
}