@ -5,6 +5,8 @@
# include <chrono>
# include <iomanip>
# include "src/exceptions/IllegalFunctionCallException.h"
namespace storm {
namespace storage {
@ -299,6 +301,11 @@ namespace storm {
return * this - > stateToBlockMapping [ state ] ;
}
template < typename ValueType >
typename DeterministicModelBisimulationDecomposition < ValueType > : : Block const & DeterministicModelBisimulationDecomposition < ValueType > : : Partition : : getBlock ( storm : : storage : : sparse : : state_type state ) const {
return * this - > stateToBlockMapping [ state ] ;
}
template < typename ValueType >
std : : vector < storm : : storage : : sparse : : state_type > : : iterator DeterministicModelBisimulationDecomposition < ValueType > : : Partition : : getBeginOfStates ( Block const & block ) {
return this - > states . begin ( ) + block . getBegin ( ) ;
@ -467,12 +474,18 @@ namespace storm {
}
template < typename ValueType >
DeterministicModelBisimulationDecomposition < ValueType > : : DeterministicModelBisimulationDecomposition ( storm : : models : : Dtmc < ValueType > const & dtmc , bool weak ) : model ( dtmc ) , initialBlocks ( ) {
computeBisimulationEquivalenceClasses ( dtmc , weak ) ;
DeterministicModelBisimulationDecomposition < ValueType > : : DeterministicModelBisimulationDecomposition ( storm : : models : : Dtmc < ValueType > const & dtmc , bool weak , bool buildQuotient ) {
computeBisimulationEquivalenceClasses ( dtmc , weak , buildQuotient ) ;
}
template < typename ValueType >
std : : shared_ptr < storm : : models : : AbstractDeterministicModel < ValueType > > DeterministicModelBisimulationDecomposition < ValueType > : : getQuotient ( ) const {
STORM_LOG_THROW ( this - > quotient ! = nullptr , storm : : exceptions : : IllegalFunctionCallException , " Unable to retrieve quotient model from bisimulation decomposition, because it was not built. " ) ;
return this - > quotient ;
}
template < typename ValueType >
void DeterministicModelBisimulationDecomposition < ValueType > : : buildQuotient ( storm : : models : : Dtmc < ValueType > const & dtmc , Partition const & partition ) {
// In order to create the quotient model, we need to construct
// (a) the new transition matrix,
// (b) the new labeling,
@ -482,8 +495,8 @@ namespace storm {
storm : : storage : : SparseMatrixBuilder < ValueType > builder ;
// Prepare the new state labeling for (b).
storm : : models : : AtomicPropositionsLabeling newLabeling ( this - > size ( ) , model . getStateLabeling ( ) . getNumberOfAtomicPropositions ( ) ) ;
std : : set < std : : string > atomicPropositionsSet = model . getStateLabeling ( ) . getAtomicPropositions ( ) ;
storm : : models : : AtomicPropositionsLabeling newLabeling ( this - > size ( ) , dtmc . getStateLabeling ( ) . getNumberOfAtomicPropositions ( ) ) ;
std : : set < std : : string > atomicPropositionsSet = dtmc . getStateLabeling ( ) . getAtomicPropositions ( ) ;
std : : vector < std : : string > atomicPropositions = std : : vector < std : : string > ( atomicPropositionsSet . begin ( ) , atomicPropositionsSet . end ( ) ) ;
for ( auto const & ap : atomicPropositions ) {
newLabeling . addAtomicProposition ( ap ) ;
@ -500,18 +513,23 @@ namespace storm {
// Add all atomic propositions to the equivalence class that the representative state satisfies.
for ( auto const & ap : atomicPropositions ) {
if ( model . getStateLabeling ( ) . getStateHasAtomicProposition ( ap , representativeState ) ) {
if ( dtmc . getStateLabeling ( ) . getStateHasAtomicProposition ( ap , representativeState ) ) {
newLabeling . addAtomicPropositionToState ( ap , blockIndex ) ;
}
}
}
// Now check which of the blocks of the partition contain at least one initial state.
for ( auto initialState : dtmc . getInitialStates ( ) ) {
Block const & initialBlock = partition . getBlock ( initialState ) ;
newLabeling . addAtomicPropositionToState ( " init " , initialBlock . getId ( ) ) ;
}
return nullptr ;
this - > quotient = nullptr ;
}
template < typename ValueType >
void DeterministicModelBisimulationDecomposition < ValueType > : : computeBisimulationEquivalenceClasses ( storm : : models : : Dtmc < ValueType > const & dtmc , bool weak ) {
void DeterministicModelBisimulationDecomposition < ValueType > : : computeBisimulationEquivalenceClasses ( storm : : models : : Dtmc < ValueType > const & dtmc , bool weak , bool buildQuotient ) {
std : : chrono : : high_resolution_clock : : time_point totalStart = std : : chrono : : high_resolution_clock : : now ( ) ;
// We start by computing the initial partition.
@ -537,6 +555,11 @@ namespace storm {
splitterQueue . pop_front ( ) ;
}
// If we are required to build the quotient model, do so now.
if ( buildQuotient ) {
this - > buildQuotient ( dtmc , partition ) ;
}
// Now move the states from the internal partition into their final place in the decomposition. We do so in
// a way that maintains the block IDs as indices.
this - > blocks . resize ( partition . size ( ) ) ;
@ -544,17 +567,6 @@ namespace storm {
this - > blocks [ block . getId ( ) ] = block_type ( partition . getBeginOfStates ( block ) , partition . getEndOfStates ( block ) ) ;
}
// FIXME: as we will drop the state-to-block-mapping, we need to create the distribution of each block now.
// Now check which of the blocks of the partition contain at least one initial state.
for ( auto initialState : model . getInitialStates ( ) ) {
Block & initialBlock = partition . getBlock ( initialState ) ;
if ( std : : find ( this - > initialBlocks . begin ( ) , this - > initialBlocks . end ( ) , initialBlock . getId ( ) ) = = this - > initialBlocks . end ( ) ) {
this - > initialBlocks . emplace_back ( initialBlock . getId ( ) ) ;
}
}
std : : sort ( this - > initialBlocks . begin ( ) , this - > initialBlocks . end ( ) ) ;
std : : chrono : : high_resolution_clock : : duration totalTime = std : : chrono : : high_resolution_clock : : now ( ) - totalStart ;
if ( storm : : settings : : generalSettings ( ) . isShowStatisticsSet ( ) ) {