@ -821,6 +821,7 @@ namespace storm {
QuotientExtractor < DdType , ValueType > : : QuotientExtractor ( ) : useRepresentatives ( false ) {
auto const & settings = storm : : settings : : getModule < storm : : settings : : modules : : BisimulationSettings > ( ) ;
this - > useRepresentatives = settings . isUseRepresentativesSet ( ) ;
this - > useOriginalVariables = settings . isUseOriginalVariablesSet ( ) ;
this - > quotientFormat = settings . getQuotientFormat ( ) ;
}
@ -921,7 +922,12 @@ namespace storm {
template < storm : : dd : : DdType DdType , typename ValueType >
std : : shared_ptr < storm : : models : : symbolic : : Model < DdType , ValueType > > QuotientExtractor < DdType , ValueType > : : extractDdQuotient ( storm : : models : : symbolic : : Model < DdType , ValueType > const & model , Partition < DdType , ValueType > const & partition , PreservationInformation < DdType , ValueType > const & preservationInformation ) {
return extractQuotientUsingBlockVariables ( model , partition , preservationInformation ) ;
if ( this - > useOriginalVariables ) {
return extractQuotientUsingOriginalVariables ( model , partition , preservationInformation ) ;
} else {
return extractQuotientUsingBlockVariables ( model , partition , preservationInformation ) ;
}
}
template < storm : : dd : : DdType DdType , typename ValueType >
@ -1036,6 +1042,134 @@ namespace storm {
STORM_LOG_THROW ( false , storm : : exceptions : : NotSupportedException , " Cannot extract quotient for this model type. " ) ;
}
}
template < storm : : dd : : DdType DdType , typename ValueType >
std : : shared_ptr < storm : : models : : symbolic : : Model < DdType , ValueType > > QuotientExtractor < DdType , ValueType > : : extractQuotientUsingOriginalVariables ( storm : : models : : symbolic : : Model < DdType , ValueType > const & model , Partition < DdType , ValueType > const & partition , PreservationInformation < DdType , ValueType > const & preservationInformation ) {
auto modelType = model . getType ( ) ;
if ( modelType = = storm : : models : : ModelType : : Dtmc | | modelType = = storm : : models : : ModelType : : Ctmc | | modelType = = storm : : models : : ModelType : : Mdp | | modelType = = storm : : models : : ModelType : : MarkovAutomaton ) {
STORM_LOG_WARN_COND ( ! this - > useRepresentatives , " Using representatives is unsupported for this extraction, falling back to regular extraction. " ) ;
// Sanity checks.
STORM_LOG_ASSERT ( partition . getNumberOfStates ( ) = = model . getNumberOfStates ( ) , " Mismatching partition size. " ) ;
STORM_LOG_ASSERT ( partition . getStates ( ) . renameVariables ( model . getColumnVariables ( ) , model . getRowVariables ( ) ) = = model . getReachableStates ( ) , " Mismatching partition. " ) ;
std : : set < storm : : expressions : : Variable > blockVariableSet = { partition . getBlockVariable ( ) } ;
std : : set < storm : : expressions : : Variable > blockPrimeVariableSet = { partition . getPrimedBlockVariable ( ) } ;
std : : vector < std : : pair < storm : : expressions : : Variable , storm : : expressions : : Variable > > blockMetaVariablePairs = { std : : make_pair ( partition . getBlockVariable ( ) , partition . getPrimedBlockVariable ( ) ) } ;
storm : : dd : : Bdd < DdType > partitionAsBdd = partition . storedAsBdd ( ) ? partition . asBdd ( ) : partition . asAdd ( ) . notZero ( ) ;
auto start = std : : chrono : : high_resolution_clock : : now ( ) ;
partitionAsBdd = partitionAsBdd . renameVariables ( model . getColumnVariables ( ) , model . getRowVariables ( ) ) ;
storm : : dd : : Bdd < DdType > reachableStates = partitionAsBdd . existsAbstract ( model . getRowVariables ( ) ) . renameVariablesAbstract ( blockVariableSet , model . getRowVariables ( ) ) ;
storm : : dd : : Bdd < DdType > initialStates = ( model . getInitialStates ( ) & & partitionAsBdd ) . existsAbstract ( model . getRowVariables ( ) ) . renameVariablesAbstract ( blockVariableSet , model . getRowVariables ( ) ) ;
std : : map < std : : string , storm : : dd : : Bdd < DdType > > preservedLabelBdds ;
for ( auto const & label : preservationInformation . getLabels ( ) ) {
preservedLabelBdds . emplace ( label , ( model . getStates ( label ) & & partitionAsBdd ) . existsAbstract ( model . getRowVariables ( ) ) . renameVariablesAbstract ( blockVariableSet , model . getRowVariables ( ) ) ) ;
}
for ( auto const & expression : preservationInformation . getExpressions ( ) ) {
std : : stringstream stream ;
stream < < expression ;
std : : string expressionAsString = stream . str ( ) ;
auto it = preservedLabelBdds . find ( expressionAsString ) ;
if ( it ! = preservedLabelBdds . end ( ) ) {
STORM_LOG_WARN ( " Duplicate label ' " < < expressionAsString < < " ', dropping second label definition. " ) ;
} else {
preservedLabelBdds . emplace ( stream . str ( ) , ( model . getStates ( expression ) & & partitionAsBdd ) . existsAbstract ( model . getRowVariables ( ) ) . renameVariablesAbstract ( blockVariableSet , model . getRowVariables ( ) ) ) ;
}
}
auto end = std : : chrono : : high_resolution_clock : : now ( ) ;
STORM_LOG_TRACE ( " Quotient labels extracted in " < < std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( end - start ) . count ( ) < < " ms. " ) ;
start = std : : chrono : : high_resolution_clock : : now ( ) ;
std : : set < storm : : expressions : : Variable > blockAndRowVariables ;
std : : set_union ( blockVariableSet . begin ( ) , blockVariableSet . end ( ) , model . getRowVariables ( ) . begin ( ) , model . getRowVariables ( ) . end ( ) , std : : inserter ( blockAndRowVariables , blockAndRowVariables . end ( ) ) ) ;
std : : set < storm : : expressions : : Variable > blockPrimeAndColumnVariables ;
std : : set_union ( blockPrimeVariableSet . begin ( ) , blockPrimeVariableSet . end ( ) , model . getColumnVariables ( ) . begin ( ) , model . getColumnVariables ( ) . end ( ) , std : : inserter ( blockPrimeAndColumnVariables , blockPrimeAndColumnVariables . end ( ) ) ) ;
storm : : dd : : Add < DdType , ValueType > partitionAsAdd = partitionAsBdd . template toAdd < ValueType > ( ) ;
storm : : dd : : Add < DdType , ValueType > quotientTransitionMatrix = model . getTransitionMatrix ( ) . multiplyMatrix ( partitionAsAdd . renameVariables ( blockAndRowVariables , blockPrimeAndColumnVariables ) , model . getColumnVariables ( ) ) . renameVariablesAbstract ( blockPrimeVariableSet , model . getColumnVariables ( ) ) ;
( model . getTransitionMatrix ( ) . multiplyMatrix ( partitionAsAdd . renameVariables ( blockAndRowVariables , blockPrimeAndColumnVariables ) , model . getColumnVariables ( ) ) . renameVariablesAbstract ( blockPrimeVariableSet , model . getColumnVariables ( ) ) ) . exportToDot ( " tmp0.dot " ) ;
quotientTransitionMatrix . exportToDot ( " tmp1.dot " ) ;
std : : cout < < " q1 size: " < < quotientTransitionMatrix . getNodeCount ( ) < < " , " < < quotientTransitionMatrix . getNonZeroCount ( ) < < std : : endl ;
quotientTransitionMatrix . sumAbstract ( model . getColumnVariables ( ) ) . exportToDot ( " tmp1_1.dot " ) ;
// quotientTransitionMatrix.sumAbstract(blockPrimeVariableSet).exportToDot("tmp1_1.dot");
// Pick a representative from each block.
auto representatives = InternalRepresentativeComputer < DdType > ( partitionAsBdd , model . getRowVariables ( ) ) . getRepresentatives ( ) ;
partitionAsBdd & = representatives ;
partitionAsAdd * = partitionAsBdd . template toAdd < ValueType > ( ) ;
partitionAsAdd . exportToDot ( " partrepr.dot " ) ;
partitionAsAdd . sumAbstract ( model . getRowVariables ( ) ) . exportToDot ( " part2.dot " ) ;
std : : cout < < " part size " < < partitionAsAdd . getNodeCount ( ) < < " , " < < partitionAsAdd . getNonZeroCount ( ) < < std : : endl ;
auto tmp1 = partitionAsAdd . multiplyMatrix ( quotientTransitionMatri , model . getRowVariables ( ) ) ;
auto tmp2 = ( quotientTransitionMatrix * partitionAsAdd ) . sumAbstract ( model . getRowVariables ( ) ) ;
std : : cout < < " size1: " < < tmp1 . getNodeCount ( ) < < " , " < < tmp1 . getNonZeroCount ( ) < < std : : endl ;
std : : cout < < " size2: " < < tmp2 . getNodeCount ( ) < < " , " < < tmp2 . getNonZeroCount ( ) < < std : : endl ;
if ( tmp1 ! = tmp2 ) {
tmp1 . exportToDot ( " tmp1__.dot " ) ;
tmp2 . exportToDot ( " tmp2__.dot " ) ;
( tmp2 - tmp1 ) . exportToDot ( " diff.dot " ) ;
STORM_LOG_ASSERT ( false , " error " ) ;
}
quotientTransitionMatrix . multiplyMatrix ( partitionAsAdd , model . getRowVariables ( ) ) . exportToDot ( " tmp2.dot " ) ;
quotientTransitionMatrix . multiplyMatrix ( partitionAsAdd , model . getRowVariables ( ) ) . sumAbstract ( model . getColumnVariables ( ) ) . exportToDot ( " tmp2_2.dot " ) ;
// quotientTransitionMatrix.multiplyMatrix(partitionAsAdd, model.getRowVariables()).sumAbstract(blockPrimeVariableSet).exportToDot("tmp2_2.dot");
quotientTransitionMatrix = quotientTransitionMatrix . multiplyMatrix ( partitionAsAdd , model . getRowVariables ( ) ) . renameVariablesAbstract ( blockVariableSet , model . getRowVariables ( ) ) ;
end = std : : chrono : : high_resolution_clock : : now ( ) ;
// Check quotient matrix for sanity.
if ( std : : is_same < ValueType , storm : : RationalNumber > : : value ) {
STORM_LOG_ASSERT ( quotientTransitionMatrix . greater ( storm : : utility : : one < ValueType > ( ) ) . isZero ( ) , " Illegal entries in quotient matrix. " ) ;
} else {
STORM_LOG_ASSERT ( quotientTransitionMatrix . greater ( storm : : utility : : one < ValueType > ( ) + storm : : utility : : convertNumber < ValueType > ( 1e-6 ) ) . isZero ( ) , " Illegal entries in quotient matrix. " ) ;
}
quotientTransitionMatrix . exportToDot ( " trans.dot " ) ;
quotientTransitionMatrix . sumAbstract ( model . getColumnVariables ( ) ) . exportToDot ( " trans1.dot " ) ;
quotientTransitionMatrix . notZero ( ) . existsAbstract ( model . getColumnVariables ( ) ) . template toAdd < ValueType > ( ) . exportToDot ( " trans2.dot " ) ;
STORM_LOG_ASSERT ( quotientTransitionMatrix . sumAbstract ( model . getColumnVariables ( ) ) . equalModuloPrecision ( quotientTransitionMatrix . notZero ( ) . existsAbstract ( model . getColumnVariables ( ) ) . template toAdd < ValueType > ( ) , storm : : utility : : convertNumber < ValueType > ( 1e-6 ) ) , " Illegal probabilistic matrix. " ) ;
STORM_LOG_TRACE ( " Quotient transition matrix extracted in " < < std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( end - start ) . count ( ) < < " ms. " ) ;
storm : : dd : : Bdd < DdType > quotientTransitionMatrixBdd = quotientTransitionMatrix . notZero ( ) ;
storm : : dd : : Bdd < DdType > deadlockStates = ! quotientTransitionMatrixBdd . existsAbstract ( model . getColumnVariables ( ) ) & & reachableStates ;
start = std : : chrono : : high_resolution_clock : : now ( ) ;
std : : unordered_map < std : : string , storm : : models : : symbolic : : StandardRewardModel < DdType , ValueType > > quotientRewardModels ;
for ( auto const & rewardModelName : preservationInformation . getRewardModelNames ( ) ) {
auto const & rewardModel = model . getRewardModel ( rewardModelName ) ;
boost : : optional < storm : : dd : : Add < DdType , ValueType > > quotientStateRewards ;
if ( rewardModel . hasStateRewards ( ) ) {
quotientStateRewards = rewardModel . getStateRewardVector ( ) . multiplyMatrix ( partitionAsAdd , model . getRowVariables ( ) ) . renameVariablesAbstract ( blockVariableSet , model . getRowVariables ( ) ) ;
}
boost : : optional < storm : : dd : : Add < DdType , ValueType > > quotientStateActionRewards ;
if ( rewardModel . hasStateActionRewards ( ) ) {
quotientStateActionRewards = rewardModel . getStateActionRewardVector ( ) . multiplyMatrix ( partitionAsAdd , model . getRowVariables ( ) ) . renameVariablesAbstract ( blockVariableSet , model . getRowVariables ( ) ) ;
}
quotientRewardModels . emplace ( rewardModelName , storm : : models : : symbolic : : StandardRewardModel < DdType , ValueType > ( quotientStateRewards , quotientStateActionRewards , boost : : none ) ) ;
}
end = std : : chrono : : high_resolution_clock : : now ( ) ;
STORM_LOG_TRACE ( " Reward models extracted in " < < std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( end - start ) . count ( ) < < " ms. " ) ;
if ( modelType = = storm : : models : : ModelType : : Dtmc ) {
return std : : shared_ptr < storm : : models : : symbolic : : Dtmc < DdType , ValueType > > ( new storm : : models : : symbolic : : Dtmc < DdType , ValueType > ( model . getManager ( ) . asSharedPointer ( ) , reachableStates , initialStates , deadlockStates , quotientTransitionMatrix , model . getRowVariables ( ) , model . getColumnVariables ( ) , model . getRowColumnMetaVariablePairs ( ) , preservedLabelBdds , quotientRewardModels ) ) ;
} else if ( modelType = = storm : : models : : ModelType : : Ctmc ) {
return std : : shared_ptr < storm : : models : : symbolic : : Ctmc < DdType , ValueType > > ( new storm : : models : : symbolic : : Ctmc < DdType , ValueType > ( model . getManager ( ) . asSharedPointer ( ) , reachableStates , initialStates , deadlockStates , quotientTransitionMatrix , blockVariableSet , blockPrimeVariableSet , blockMetaVariablePairs , preservedLabelBdds , quotientRewardModels ) ) ;
} else if ( modelType = = storm : : models : : ModelType : : Mdp ) {
return std : : shared_ptr < storm : : models : : symbolic : : Mdp < DdType , ValueType > > ( new storm : : models : : symbolic : : Mdp < DdType , ValueType > ( model . getManager ( ) . asSharedPointer ( ) , reachableStates , initialStates , deadlockStates , quotientTransitionMatrix , blockVariableSet , blockPrimeVariableSet , blockMetaVariablePairs , model . getNondeterminismVariables ( ) , preservedLabelBdds , quotientRewardModels ) ) ;
} else {
return std : : shared_ptr < storm : : models : : symbolic : : MarkovAutomaton < DdType , ValueType > > ( new storm : : models : : symbolic : : MarkovAutomaton < DdType , ValueType > ( model . getManager ( ) . asSharedPointer ( ) , model . template as < storm : : models : : symbolic : : MarkovAutomaton < DdType , ValueType > > ( ) - > getMarkovianMarker ( ) , reachableStates , initialStates , deadlockStates , quotientTransitionMatrix , blockVariableSet , blockPrimeVariableSet , blockMetaVariablePairs , model . getNondeterminismVariables ( ) , preservedLabelBdds , quotientRewardModels ) ) ;
}
} else {
STORM_LOG_THROW ( false , storm : : exceptions : : NotSupportedException , " Cannot extract quotient for this model type. " ) ;
}
}
template class QuotientExtractor < storm : : dd : : DdType : : CUDD , double > ;