@ -581,7 +581,7 @@ namespace storm {
template < typename ValueType >
DeterministicModelBisimulationDecomposition < ValueType > : : DeterministicModelBisimulationDecomposition ( storm : : models : : Dtmc < ValueType > const & model , boost : : optional < std : : set < std : : string > > const & atomicPropositions , bool weak , bool buildQuotient ) : comparator ( ) {
STORM_LOG_THROW ( ! model . hasState Rewards ( ) , storm : : exceptions : : IllegalFunctionCallException , " Bisimulation is currently only supported for models without reward structure s. " ) ;
STORM_LOG_THROW ( ! model . hasTransition Rewards ( ) , storm : : exceptions : : IllegalFunctionCallException , " Bisimulation is currently only supported for models without transition rewards. " ) ;
storm : : storage : : SparseMatrix < ValueType > backwardTransitions = model . getBackwardTransitions ( ) ;
BisimulationType bisimulationType = weak ? BisimulationType : : WeakDtmc : BisimulationType : : Strong ;
Partition initialPartition = getLabelBasedInitialPartition ( model , backwardTransitions , bisimulationType , atomicPropositions ) ;
@ -590,7 +590,7 @@ namespace storm {
template < typename ValueType >
DeterministicModelBisimulationDecomposition < ValueType > : : DeterministicModelBisimulationDecomposition ( storm : : models : : Ctmc < ValueType > const & model , boost : : optional < std : : set < std : : string > > const & atomicPropositions , bool weak , bool buildQuotient ) {
STORM_LOG_THROW ( ! model . hasStateRewards ( ) & & ! model . has TransitionRewards ( ) , storm : : exceptions : : IllegalFunctionCallException , " Bisimulation is currently only supported for models without reward structure s. " ) ;
STORM_LOG_THROW ( ! model . hasTransitionRewards ( ) , storm : : exceptions : : IllegalFunctionCallException , " Bisimulation is currently only supported for models without transition rewards. " ) ;
storm : : storage : : SparseMatrix < ValueType > backwardTransitions = model . getBackwardTransitions ( ) ;
BisimulationType bisimulationType = weak ? BisimulationType : : WeakCtmc : BisimulationType : : Strong ;
Partition initialPartition = getLabelBasedInitialPartition ( model , backwardTransitions , bisimulationType , atomicPropositions ) ;
@ -599,7 +599,7 @@ namespace storm {
template < typename ValueType >
DeterministicModelBisimulationDecomposition < ValueType > : : DeterministicModelBisimulationDecomposition ( storm : : models : : Dtmc < ValueType > const & model , std : : string const & phiLabel , std : : string const & psiLabel , bool weak , bool bounded , bool buildQuotient ) {
STORM_LOG_THROW ( ! model . hasStateRewards ( ) & & ! model . has TransitionRewards ( ) , storm : : exceptions : : IllegalFunctionCallException , " Bisimulation is currently only supported for models without reward structure s. " ) ;
STORM_LOG_THROW ( ! model . hasTransitionRewards ( ) , storm : : exceptions : : IllegalFunctionCallException , " Bisimulation is currently only supported for models without transition rewards. " ) ;
STORM_LOG_THROW ( ! weak | | ! bounded , storm : : exceptions : : IllegalFunctionCallException , " Weak bisimulation does not preserve bounded properties. " ) ;
storm : : storage : : SparseMatrix < ValueType > backwardTransitions = model . getBackwardTransitions ( ) ;
BisimulationType bisimulationType = weak ? BisimulationType : : WeakDtmc : BisimulationType : : Strong ;
@ -609,7 +609,7 @@ namespace storm {
template < typename ValueType >
DeterministicModelBisimulationDecomposition < ValueType > : : DeterministicModelBisimulationDecomposition ( storm : : models : : Ctmc < ValueType > const & model , std : : string const & phiLabel , std : : string const & psiLabel , bool weak , bool bounded , bool buildQuotient ) {
STORM_LOG_THROW ( ! model . hasStateRewards ( ) & & ! model . has TransitionRewards ( ) , storm : : exceptions : : IllegalFunctionCallException , " Bisimulation is currently only supported for models without reward structure s. " ) ;
STORM_LOG_THROW ( ! model . hasTransitionRewards ( ) , storm : : exceptions : : IllegalFunctionCallException , " Bisimulation is currently only supported for models without transition rewards. " ) ;
STORM_LOG_THROW ( ! weak | | ! bounded , storm : : exceptions : : IllegalFunctionCallException , " Weak bisimulation does not preserve bounded properties. " ) ;
storm : : storage : : SparseMatrix < ValueType > backwardTransitions = model . getBackwardTransitions ( ) ;
BisimulationType bisimulationType = weak ? BisimulationType : : WeakCtmc : BisimulationType : : Strong ;
@ -1191,6 +1191,12 @@ namespace storm {
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > statesWithProbability01 = storm : : utility : : graph : : performProb01 ( backwardTransitions , phiLabel = = " true " ? storm : : storage : : BitVector ( model . getNumberOfStates ( ) , true ) : model . getLabeledStates ( phiLabel ) , model . getLabeledStates ( psiLabel ) ) ;
Partition partition ( model . getNumberOfStates ( ) , statesWithProbability01 . first , bounded ? model . getLabeledStates ( psiLabel ) : statesWithProbability01 . second , phiLabel , psiLabel , bisimulationType = = BisimulationType : : WeakDtmc ) ;
// If the model has state rewards, we need to consider them, because otherwise reward properties are not
// preserved.
if ( model . hasStateRewards ( ) ) {
this - > splitRewards ( model , partition ) ;
}
// If we are creating the initial partition for weak bisimulation, we need to (a) split off all divergent
// states of each initial block and (b) initialize the vector of silent probabilities held by the partition.
if ( bisimulationType = = BisimulationType : : WeakDtmc ) {
@ -1290,6 +1296,12 @@ namespace storm {
}
}
// If the model has state rewards, we need to consider them, because otherwise reward properties are not
// preserved.
if ( model . hasStateRewards ( ) ) {
this - > splitRewards ( model , partition ) ;
}
// If we are creating the initial partition for weak bisimulation, we need to (a) split off all divergent
// states of each initial block and (b) initialize the vector of silent probabilities held by the partition.
if ( bisimulationType = = BisimulationType : : WeakDtmc ) {
@ -1317,6 +1329,47 @@ namespace storm {
}
}
template < typename ValueType >
template < typename ModelType >
void DeterministicModelBisimulationDecomposition < ValueType > : : splitRewards ( ModelType const & model , Partition & partition ) {
if ( model . hasStateRewards ( ) ) {
return ;
}
for ( auto & block : partition . getBlocks ( ) ) {
std : : sort ( partition . getBegin ( block ) , partition . getEnd ( block ) , [ & model ] ( std : : pair < storm : : storage : : sparse : : state_type , ValueType > const & a , std : : pair < storm : : storage : : sparse : : state_type , ValueType > const & b ) { return model . getStateRewardVector ( ) [ a . first ] < model . getStateRewardVector ( ) [ b . first ] ; } ) ;
// Update the positions vector.
storm : : storage : : sparse : : state_type position = block . getBegin ( ) ;
for ( auto stateIt = partition . getBegin ( block ) , stateIte = partition . getEnd ( block ) ; stateIt ! = stateIte ; + + stateIt , + + position ) {
partition . setPosition ( stateIt - > first , position ) ;
}
// Finally, we need to scan the ranges of states that agree on the probability.
typename std : : vector < std : : pair < storm : : storage : : sparse : : state_type , ValueType > > : : const_iterator begin = partition . getBegin ( block ) ;
typename std : : vector < std : : pair < storm : : storage : : sparse : : state_type , ValueType > > : : const_iterator current = begin ;
typename std : : vector < std : : pair < storm : : storage : : sparse : : state_type , ValueType > > : : const_iterator end = partition . getEnd ( block ) - 1 ;
storm : : storage : : sparse : : state_type currentIndex = block . getBegin ( ) ;
// Now we can check whether the block needs to be split, which is the case iff the rewards for the first
// and the last state are different.
bool blockSplit = ! comparator . isEqual ( begin - > second , end - > second ) ;
while ( ! comparator . isEqual ( begin - > second , end - > second ) ) {
// Now we scan for the first state in the block that disagrees on the reward value. Note that we do
// not have to check currentIndex for staying within bounds, because we know the matching state is
// within bounds.
ValueType const & currentValue = begin - > second ;
+ + begin ;
+ + currentIndex ;
while ( begin ! = end & & comparator . isEqual ( begin - > second , currentValue ) ) {
+ + begin ;
+ + currentIndex ;
}
}
}
}
template class DeterministicModelBisimulationDecomposition < double > ;
}
}