@ -7,6 +7,8 @@
# include "storm/utility/DirectEncodingExporter.h"
# include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
# include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h"
# include "storm/models/ModelType.h"
# include "storm/transformer/NonMarkovianChainTransformer.h"
# include "storm-dft/builder/ExplicitDFTModelBuilder.h"
# include "storm-dft/storage/dft/DFTIsomorphism.h"
@ -17,7 +19,13 @@ namespace storm {
namespace modelchecker {
template < typename ValueType >
typename DFTModelChecker < ValueType > : : dft_results DFTModelChecker < ValueType > : : check ( storm : : storage : : DFT < ValueType > const & origDft , std : : vector < std : : shared_ptr < const storm : : logic : : Formula > > const & properties , bool symred , bool allowModularisation , std : : set < size_t > const & relevantEvents , bool allowDCForRelevantEvents , double approximationError , storm : : builder : : ApproximationHeuristic approximationHeuristic ) {
typename DFTModelChecker < ValueType > : : dft_results
DFTModelChecker < ValueType > : : check ( storm : : storage : : DFT < ValueType > const & origDft ,
std : : vector < std : : shared_ptr < const storm : : logic : : Formula > > const & properties ,
bool symred , bool allowModularisation , std : : set < size_t > const & relevantEvents ,
bool allowDCForRelevantEvents , double approximationError ,
storm : : builder : : ApproximationHeuristic approximationHeuristic ,
bool eliminateChains , bool ignoreLabeling ) {
totalTimer . start ( ) ;
dft_results results ;
@ -30,21 +38,32 @@ namespace storm {
// TODO: distinguish for all properties, not only for first one
if ( properties [ 0 ] - > isTimeOperatorFormula ( ) & & allowModularisation ) {
// Use parallel composition as modularisation approach for expected time
std : : shared_ptr < storm : : models : : sparse : : Model < ValueType > > model = buildModelViaComposition ( dft , properties , symred , true , relevantEvents ) ;
std : : shared_ptr < storm : : models : : sparse : : Model < ValueType > > model = buildModelViaComposition ( dft ,
properties ,
symred , true ,
relevantEvents ) ;
// Model checking
std : : vector < ValueType > resultsValue = checkModel ( model , properties ) ;
for ( ValueType result : resultsValue ) {
results . push_back ( result ) ;
}
} else {
results = checkHelper ( dft , properties , symred , allowModularisation , relevantEvents , allowDCForRelevantEvents , approximationError , approximationHeuristic ) ;
results = checkHelper ( dft , properties , symred , allowModularisation , relevantEvents ,
allowDCForRelevantEvents , approximationError , approximationHeuristic ,
eliminateChains , ignoreLabeling ) ;
}
totalTimer . stop ( ) ;
return results ;
}
template < typename ValueType >
typename DFTModelChecker < ValueType > : : dft_results DFTModelChecker < ValueType > : : checkHelper ( storm : : storage : : DFT < ValueType > const & dft , property_vector const & properties , bool symred , bool allowModularisation , std : : set < size_t > const & relevantEvents , bool allowDCForRelevantEvents , double approximationError , storm : : builder : : ApproximationHeuristic approximationHeuristic ) {
typename DFTModelChecker < ValueType > : : dft_results
DFTModelChecker < ValueType > : : checkHelper ( storm : : storage : : DFT < ValueType > const & dft ,
property_vector const & properties , bool symred ,
bool allowModularisation , std : : set < size_t > const & relevantEvents ,
bool allowDCForRelevantEvents , double approximationError ,
storm : : builder : : ApproximationHeuristic approximationHeuristic ,
bool eliminateChains , bool ignoreLabeling ) {
STORM_LOG_TRACE ( " Check helper called " ) ;
std : : vector < storm : : storage : : DFT < ValueType > > dfts ;
bool invResults = false ;
@ -52,7 +71,7 @@ namespace storm {
size_t nrM = 0 ; // K out of M
// Try modularisation
if ( allowModularisation ) {
if ( allowModularisation ) {
switch ( dft . topLevelType ( ) ) {
case storm : : storage : : DFTElementType : : AND :
STORM_LOG_TRACE ( " top modularisation called AND " ) ;
@ -73,9 +92,10 @@ namespace storm {
STORM_LOG_TRACE ( " top modularisation called VOT " ) ;
dfts = dft . topModularisation ( ) ;
STORM_LOG_TRACE ( " Modularisation into " < < dfts . size ( ) < < " submodules. " ) ;
nrK = std : : static_pointer_cast < storm : : storage : : DFTVot < ValueType > const > ( dft . getTopLevelGate ( ) ) - > threshold ( ) ;
nrK = std : : static_pointer_cast < storm : : storage : : DFTVot < ValueType > const > (
dft . getTopLevelGate ( ) ) - > threshold ( ) ;
nrM = dfts . size ( ) ;
if ( nrK < = nrM / 2 ) {
if ( nrK < = nrM / 2 ) {
nrK - = 1 ;
invResults = true ;
}
@ -87,7 +107,7 @@ namespace storm {
}
// Perform modularisation
if ( dfts . size ( ) > 1 ) {
if ( dfts . size ( ) > 1 ) {
STORM_LOG_TRACE ( " Recursive CHECK Call " ) ;
// TODO: compute simultaneously
dft_results results ;
@ -97,39 +117,42 @@ namespace storm {
} else {
// Recursively call model checking
std : : vector < ValueType > res ;
for ( auto const ft : dfts ) {
for ( auto const ft : dfts ) {
// TODO: allow approximation in modularisation
dft_results ftResults = checkHelper ( ft , { property } , symred , true , relevantEvents , allowDCForRelevantEvents , 0.0 ) ;
dft_results ftResults = checkHelper ( ft , { property } , symred , true , relevantEvents ,
allowDCForRelevantEvents , 0.0 ) ;
STORM_LOG_ASSERT ( ftResults . size ( ) = = 1 , " Wrong number of results " ) ;
res . push_back ( boost : : get < ValueType > ( ftResults [ 0 ] ) ) ;
}
// Combine modularisation results
STORM_LOG_TRACE ( " Combining all results... K= " < < nrK < < " ; M= " < < nrM < < " ; invResults= " < < ( invResults ? " On " : " Off " ) ) ;
STORM_LOG_TRACE ( " Combining all results... K= " < < nrK < < " ; M= " < < nrM < < " ; invResults= "
< < ( invResults ? " On " : " Off " ) ) ;
ValueType result = storm : : utility : : zero < ValueType > ( ) ;
int limK = invResults ? - 1 : nrM + 1 ;
int limK = invResults ? - 1 : nrM + 1 ;
int chK = invResults ? - 1 : 1 ;
// WARNING: there is a bug for computing permutations with more than 32 elements
STORM_LOG_THROW ( res . size ( ) < 32 , storm : : exceptions : : NotSupportedException , " Permutations work only for < 32 elements " ) ;
for ( int cK = nrK ; cK ! = limK ; cK + = chK ) {
STORM_LOG_THROW ( res . size ( ) < 32 , storm : : exceptions : : NotSupportedException ,
" Permutations work only for < 32 elements " ) ;
for ( int cK = nrK ; cK ! = limK ; cK + = chK ) {
STORM_LOG_ASSERT ( cK > = 0 , " ck negative. " ) ;
size_t permutation = smallestIntWithNBitsSet ( static_cast < size_t > ( cK ) ) ;
do {
STORM_LOG_TRACE ( " Permutation= " < < permutation ) ;
STORM_LOG_TRACE ( " Permutation= " < < permutation ) ;
ValueType permResult = storm : : utility : : one < ValueType > ( ) ;
for ( size_t i = 0 ; i < res . size ( ) ; + + i ) {
if ( permutation & ( 1 < < i ) ) {
for ( size_t i = 0 ; i < res . size ( ) ; + + i ) {
if ( permutation & ( 1 < < i ) ) {
permResult * = res [ i ] ;
} else {
permResult * = storm : : utility : : one < ValueType > ( ) - res [ i ] ;
}
}
STORM_LOG_TRACE ( " Result for permutation: " < < permResult ) ;
STORM_LOG_TRACE ( " Result for permutation: " < < permResult ) ;
permutation = nextBitPermutation ( permutation ) ;
result + = permResult ;
} while ( permutation < ( 1 < < nrM ) & & permutation ! = 0 ) ;
} while ( permutation < ( 1 < < nrM ) & & permutation ! = 0 ) ;
}
if ( invResults ) {
if ( invResults ) {
result = storm : : utility : : one < ValueType > ( ) - result ;
}
results . push_back ( result ) ;
@ -138,19 +161,25 @@ namespace storm {
return results ;
} else {
// No modularisation was possible
return checkDFT ( dft , properties , symred , relevantEvents , allowDCForRelevantEvents , approximationError , approximationHeuristic ) ;
return checkDFT ( dft , properties , symred , relevantEvents , allowDCForRelevantEvents , approximationError ,
approximationHeuristic , eliminateChains , ignoreLabeling ) ;
}
}
template < typename ValueType >
std : : shared_ptr < storm : : models : : sparse : : Ctmc < ValueType > > DFTModelChecker < ValueType > : : buildModelViaComposition ( storm : : storage : : DFT < ValueType > const & dft , property_vector const & properties , bool symred , bool allowModularisation , std : : set < size_t > const & relevantEvents , bool allowDCForRelevantEvents ) {
std : : shared_ptr < storm : : models : : sparse : : Ctmc < ValueType > >
DFTModelChecker < ValueType > : : buildModelViaComposition ( storm : : storage : : DFT < ValueType > const & dft ,
property_vector const & properties , bool symred ,
bool allowModularisation ,
std : : set < size_t > const & relevantEvents ,
bool allowDCForRelevantEvents ) {
// TODO: use approximation?
STORM_LOG_TRACE ( " Build model via composition " ) ;
std : : vector < storm : : storage : : DFT < ValueType > > dfts ;
bool isAnd = true ;
// Try modularisation
if ( allowModularisation ) {
if ( allowModularisation ) {
switch ( dft . topLevelType ( ) ) {
case storm : : storage : : DFTElementType : : AND :
STORM_LOG_TRACE ( " top modularisation called AND " ) ;
@ -174,7 +203,7 @@ namespace storm {
}
// Perform modularisation via parallel composition
if ( dfts . size ( ) > 1 ) {
if ( dfts . size ( ) > 1 ) {
STORM_LOG_TRACE ( " Recursive CHECK Call " ) ;
bool firstTime = true ;
std : : shared_ptr < storm : : models : : sparse : : Ctmc < ValueType > > composedModel ;
@ -185,7 +214,7 @@ namespace storm {
// Find symmetries
std : : map < size_t , std : : vector < std : : vector < size_t > > > emptySymmetry ;
storm : : storage : : DFTIndependentSymmetries symmetries ( emptySymmetry ) ;
if ( symred ) {
if ( symred ) {
auto colouring = ft . colourDFT ( ) ;
symmetries = ft . findSymmetries ( colouring ) ;
STORM_LOG_DEBUG ( " Found " < < symmetries . groups . size ( ) < < " symmetries. " ) ;
@ -194,29 +223,37 @@ namespace storm {
// Build a single CTMC
STORM_LOG_DEBUG ( " Building Model... " ) ;
storm : : builder : : ExplicitDFTModelBuilder < ValueType > builder ( ft , symmetries , relevantEvents , allowDCForRelevantEvents ) ;
storm : : builder : : ExplicitDFTModelBuilder < ValueType > builder ( ft , symmetries , relevantEvents ,
allowDCForRelevantEvents ) ;
builder . buildModel ( 0 , 0.0 ) ;
std : : shared_ptr < storm : : models : : sparse : : Model < ValueType > > model = builder . getModel ( ) ;
explorationTimer . stop ( ) ;
STORM_LOG_THROW ( model - > isOfType ( storm : : models : : ModelType : : Ctmc ) , storm : : exceptions : : NotSupportedException , " Parallel composition only applicable for CTMCs " ) ;
STORM_LOG_THROW ( model - > isOfType ( storm : : models : : ModelType : : Ctmc ) ,
storm : : exceptions : : NotSupportedException ,
" Parallel composition only applicable for CTMCs " ) ;
std : : shared_ptr < storm : : models : : sparse : : Ctmc < ValueType > > ctmc = model - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) ;
// Apply bisimulation to new CTMC
bisimulationTimer . start ( ) ;
ctmc = storm : : api : : performDeterministicSparseBisimulationMinimization < storm : : models : : sparse : : Ctmc < ValueType > > ( ctmc , properties , storm : : storage : : BisimulationType : : Weak ) - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) ;
ctmc = storm : : api : : performDeterministicSparseBisimulationMinimization < storm : : models : : sparse : : Ctmc < ValueType > > (
ctmc , properties ,
storm : : storage : : BisimulationType : : Weak ) - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) ;
bisimulationTimer . stop ( ) ;
if ( firstTime ) {
composedModel = ctmc ;
firstTime = false ;
} else {
composedModel = storm : : builder : : ParallelCompositionBuilder < ValueType > : : compose ( composedModel , ctmc , isAnd ) ;
composedModel = storm : : builder : : ParallelCompositionBuilder < ValueType > : : compose ( composedModel ,
ctmc , isAnd ) ;
}
// Apply bisimulation to parallel composition
bisimulationTimer . start ( ) ;
composedModel = storm : : api : : performDeterministicSparseBisimulationMinimization < storm : : models : : sparse : : Ctmc < ValueType > > ( composedModel , properties , storm : : storage : : BisimulationType : : Weak ) - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) ;
composedModel = storm : : api : : performDeterministicSparseBisimulationMinimization < storm : : models : : sparse : : Ctmc < ValueType > > (
composedModel , properties ,
storm : : storage : : BisimulationType : : Weak ) - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) ;
bisimulationTimer . stop ( ) ;
STORM_LOG_DEBUG ( " No. states (Composed): " < < composedModel - > getNumberOfStates ( ) ) ;
@ -236,7 +273,7 @@ namespace storm {
// Find symmetries
std : : map < size_t , std : : vector < std : : vector < size_t > > > emptySymmetry ;
storm : : storage : : DFTIndependentSymmetries symmetries ( emptySymmetry ) ;
if ( symred ) {
if ( symred ) {
auto colouring = dft . colourDFT ( ) ;
symmetries = dft . findSymmetries ( colouring ) ;
STORM_LOG_DEBUG ( " Found " < < symmetries . groups . size ( ) < < " symmetries. " ) ;
@ -245,24 +282,33 @@ namespace storm {
// Build a single CTMC
STORM_LOG_DEBUG ( " Building Model... " ) ;
storm : : builder : : ExplicitDFTModelBuilder < ValueType > builder ( dft , symmetries , relevantEvents , allowDCForRelevantEvents ) ;
storm : : builder : : ExplicitDFTModelBuilder < ValueType > builder ( dft , symmetries , relevantEvents ,
allowDCForRelevantEvents ) ;
builder . buildModel ( 0 , 0.0 ) ;
std : : shared_ptr < storm : : models : : sparse : : Model < ValueType > > model = builder . getModel ( ) ;
//model->printModelInformationToStream(std::cout);
explorationTimer . stop ( ) ;
STORM_LOG_THROW ( model - > isOfType ( storm : : models : : ModelType : : Ctmc ) , storm : : exceptions : : NotSupportedException , " Parallel composition only applicable for CTMCs " ) ;
STORM_LOG_THROW ( model - > isOfType ( storm : : models : : ModelType : : Ctmc ) ,
storm : : exceptions : : NotSupportedException ,
" Parallel composition only applicable for CTMCs " ) ;
return model - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) ;
}
}
template < typename ValueType >
typename DFTModelChecker < ValueType > : : dft_results DFTModelChecker < ValueType > : : checkDFT ( storm : : storage : : DFT < ValueType > const & dft , property_vector const & properties , bool symred , std : : set < size_t > const & relevantEvents , bool allowDCForRelevantEvents , double approximationError , storm : : builder : : ApproximationHeuristic approximationHeuristic ) {
typename DFTModelChecker < ValueType > : : dft_results
DFTModelChecker < ValueType > : : checkDFT ( storm : : storage : : DFT < ValueType > const & dft ,
property_vector const & properties , bool symred ,
std : : set < size_t > const & relevantEvents , bool allowDCForRelevantEvents ,
double approximationError ,
storm : : builder : : ApproximationHeuristic approximationHeuristic ,
bool eliminateChains , bool ignoreLabeling ) {
explorationTimer . start ( ) ;
// Find symmetries
std : : map < size_t , std : : vector < std : : vector < size_t > > > emptySymmetry ;
storm : : storage : : DFTIndependentSymmetries symmetries ( emptySymmetry ) ;
if ( symred ) {
if ( symred ) {
auto colouring = dft . colourDFT ( ) ;
symmetries = dft . findSymmetries ( colouring ) ;
STORM_LOG_DEBUG ( " Found " < < symmetries . groups . size ( ) < < " symmetries. " ) ;
@ -273,10 +319,12 @@ namespace storm {
// Comparator for checking the error of the approximation
storm : : utility : : ConstantsComparator < ValueType > comparator ;
// Build approximate Markov Automata for lower and upper bound
approximation_result approxResult = std : : make_pair ( storm : : utility : : zero < ValueType > ( ) , storm : : utility : : zero < ValueType > ( ) ) ;
approximation_result approxResult = std : : make_pair ( storm : : utility : : zero < ValueType > ( ) ,
storm : : utility : : zero < ValueType > ( ) ) ;
std : : shared_ptr < storm : : models : : sparse : : Model < ValueType > > model ;
std : : vector < ValueType > newResult ;
storm : : builder : : ExplicitDFTModelBuilder < ValueType > builder ( dft , symmetries , relevantEvents , allowDCForRelevantEvents ) ;
storm : : builder : : ExplicitDFTModelBuilder < ValueType > builder ( dft , symmetries , relevantEvents ,
allowDCForRelevantEvents ) ;
// TODO: compute approximation for all properties simultaneously?
std : : shared_ptr < const storm : : logic : : Formula > property = properties [ 0 ] ;
@ -285,7 +333,9 @@ namespace storm {
}
bool probabilityFormula = property - > isProbabilityOperatorFormula ( ) ;
STORM_LOG_ASSERT ( ( property - > isTimeOperatorFormula ( ) & & ! probabilityFormula ) | | ( ! property - > isTimeOperatorFormula ( ) & & probabilityFormula ) , " Probability formula not initialized correctly " ) ;
STORM_LOG_ASSERT ( ( property - > isTimeOperatorFormula ( ) & & ! probabilityFormula ) | |
( ! property - > isTimeOperatorFormula ( ) & & probabilityFormula ) ,
" Probability formula not initialized correctly " ) ;
size_t iteration = 0 ;
do {
// Iteratively build finer models
@ -310,7 +360,9 @@ namespace storm {
// Check lower bounds
newResult = checkModel ( model , { property } ) ;
STORM_LOG_ASSERT ( newResult . size ( ) = = 1 , " Wrong size for result vector. " ) ;
STORM_LOG_ASSERT ( iteration = = 0 | | ! comparator . isLess ( newResult [ 0 ] , approxResult . first ) , " New under-approximation " < < newResult [ 0 ] < < " is smaller than old result " < < approxResult . first ) ;
STORM_LOG_ASSERT ( iteration = = 0 | | ! comparator . isLess ( newResult [ 0 ] , approxResult . first ) ,
" New under-approximation " < < newResult [ 0 ] < < " is smaller than old result "
< < approxResult . first ) ;
approxResult . first = newResult [ 0 ] ;
// Build model for upper bound
@ -321,17 +373,27 @@ namespace storm {
// Check upper bound
newResult = checkModel ( model , { property } ) ;
STORM_LOG_ASSERT ( newResult . size ( ) = = 1 , " Wrong size for result vector. " ) ;
STORM_LOG_ASSERT ( iteration = = 0 | | ! comparator . isLess ( approxResult . second , newResult [ 0 ] ) , " New over-approximation " < < newResult [ 0 ] < < " is greater than old result " < < approxResult . second ) ;
STORM_LOG_ASSERT ( iteration = = 0 | | ! comparator . isLess ( approxResult . second , newResult [ 0 ] ) ,
" New over-approximation " < < newResult [ 0 ] < < " is greater than old result "
< < approxResult . second ) ;
approxResult . second = newResult [ 0 ] ;
+ + iteration ;
STORM_LOG_ASSERT ( comparator . isLess ( approxResult . first , approxResult . second ) | | comparator . isEqual ( approxResult . first , approxResult . second ) , " Under-approximation " < < approxResult . first < < " is greater than over-approximation " < < approxResult . second ) ;
STORM_LOG_ASSERT ( comparator . isLess ( approxResult . first , approxResult . second ) | |
comparator . isEqual ( approxResult . first , approxResult . second ) ,
" Under-approximation " < < approxResult . first
< < " is greater than over-approximation "
< < approxResult . second ) ;
//STORM_LOG_INFO("Result after iteration " << iteration << ": (" << std::setprecision(10) << approxResult.first << ", " << approxResult.second << ")");
totalTimer . stop ( ) ;
printTimings ( ) ;
totalTimer . start ( ) ;
STORM_LOG_THROW ( ! storm : : utility : : isInfinity < ValueType > ( approxResult . first ) & & ! storm : : utility : : isInfinity < ValueType > ( approxResult . second ) , storm : : exceptions : : NotSupportedException , " Approximation does not work if result might be infinity. " ) ;
} while ( ! isApproximationSufficient ( approxResult . first , approxResult . second , approximationError , probabilityFormula ) ) ;
STORM_LOG_THROW ( ! storm : : utility : : isInfinity < ValueType > ( approxResult . first ) & &
! storm : : utility : : isInfinity < ValueType > ( approxResult . second ) ,
storm : : exceptions : : NotSupportedException ,
" Approximation does not work if result might be infinity. " ) ;
} while ( ! isApproximationSufficient ( approxResult . first , approxResult . second , approximationError ,
probabilityFormula ) ) ;
//STORM_LOG_INFO("Finished approximation after " << iteration << " iteration" << (iteration > 1 ? "s." : "."));
dft_results results ;
@ -341,9 +403,15 @@ namespace storm {
// Build a single Markov Automaton
auto ioSettings = storm : : settings : : getModule < storm : : settings : : modules : : IOSettings > ( ) ;
STORM_LOG_DEBUG ( " Building Model... " ) ;
storm : : builder : : ExplicitDFTModelBuilder < ValueType > builder ( dft , symmetries , relevantEvents , allowDCForRelevantEvents ) ;
storm : : builder : : ExplicitDFTModelBuilder < ValueType > builder ( dft , symmetries , relevantEvents ,
allowDCForRelevantEvents ) ;
builder . buildModel ( 0 , 0.0 ) ;
std : : shared_ptr < storm : : models : : sparse : : Model < ValueType > > model = builder . getModel ( ) ;
if ( eliminateChains & & model - > isOfType ( storm : : models : : ModelType : : MarkovAutomaton ) ) {
auto ma = std : : static_pointer_cast < storm : : models : : sparse : : MarkovAutomaton < ValueType > > ( model ) ;
model = storm : : transformer : : NonMarkovianChainTransformer < ValueType > : : eliminateNonmarkovianStates ( ma ,
! ignoreLabeling ) ;
}
explorationTimer . stop ( ) ;
// Print model information
@ -376,12 +444,17 @@ namespace storm {
}
template < typename ValueType >
std : : vector < ValueType > DFTModelChecker < ValueType > : : checkModel ( std : : shared_ptr < storm : : models : : sparse : : Model < ValueType > > & model , property_vector const & properties ) {
std : : vector < ValueType >
DFTModelChecker < ValueType > : : checkModel ( std : : shared_ptr < storm : : models : : sparse : : Model < ValueType > > & model ,
property_vector const & properties ) {
// Bisimulation
if ( model - > isOfType ( storm : : models : : ModelType : : Ctmc ) & & storm : : settings : : getModule < storm : : settings : : modules : : GeneralSettings > ( ) . isBisimulationSet ( ) ) {
if ( model - > isOfType ( storm : : models : : ModelType : : Ctmc ) & &
storm : : settings : : getModule < storm : : settings : : modules : : GeneralSettings > ( ) . isBisimulationSet ( ) ) {
bisimulationTimer . start ( ) ;
STORM_LOG_DEBUG ( " Bisimulation... " ) ;
model = storm : : api : : performDeterministicSparseBisimulationMinimization < storm : : models : : sparse : : Ctmc < ValueType > > ( model - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) , properties , storm : : storage : : BisimulationType : : Weak ) - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) ;
model = storm : : api : : performDeterministicSparseBisimulationMinimization < storm : : models : : sparse : : Ctmc < ValueType > > (
model - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) , properties ,
storm : : storage : : BisimulationType : : Weak ) - > template as < storm : : models : : sparse : : Ctmc < ValueType > > ( ) ;
STORM_LOG_DEBUG ( " No. states (Bisimulation): " < < model - > getNumberOfStates ( ) ) ;
STORM_LOG_DEBUG ( " No. transitions (Bisimulation): " < < model - > getNumberOfTransitions ( ) ) ;
bisimulationTimer . stop ( ) ;
@ -398,7 +471,9 @@ namespace storm {
singleModelCheckingTimer . reset ( ) ;
singleModelCheckingTimer . start ( ) ;
//STORM_PRINT_AND_LOG("Model checking property " << *property << " ..." << std::endl);
std : : unique_ptr < storm : : modelchecker : : CheckResult > result ( storm : : api : : verifyWithSparseEngine < ValueType > ( model , storm : : api : : createTask < ValueType > ( property , true ) ) ) ;
std : : unique_ptr < storm : : modelchecker : : CheckResult > result (
storm : : api : : verifyWithSparseEngine < ValueType > ( model , storm : : api : : createTask < ValueType > ( property ,
true ) ) ) ;
STORM_LOG_ASSERT ( result , " Result does not exist. " ) ;
result - > filter ( storm : : modelchecker : : ExplicitQualitativeCheckResult ( model - > getInitialStates ( ) ) ) ;
ValueType resultValue = result - > asExplicitQuantitativeCheckResult < ValueType > ( ) . getValueMap ( ) . begin ( ) - > second ;
@ -413,13 +488,15 @@ namespace storm {
}
template < typename ValueType >
bool DFTModelChecker < ValueType > : : isApproximationSufficient ( ValueType , ValueType , double , bool ) {
bool DFTModelChecker < ValueType > : : isApproximationSufficient ( ValueType , ValueType , double , bool ) {
STORM_LOG_THROW ( false , storm : : exceptions : : NotImplementedException , " Approximation works only for double. " ) ;
}
template < >
bool DFTModelChecker < double > : : isApproximationSufficient ( double lowerBound , double upperBound , double approximationError , bool relative ) {
STORM_LOG_THROW ( ! std : : isnan ( lowerBound ) & & ! std : : isnan ( upperBound ) , storm : : exceptions : : NotSupportedException , " Approximation does not work if result is NaN. " ) ;
bool DFTModelChecker < double > : : isApproximationSufficient ( double lowerBound , double upperBound ,
double approximationError , bool relative ) {
STORM_LOG_THROW ( ! std : : isnan ( lowerBound ) & & ! std : : isnan ( upperBound ) ,
storm : : exceptions : : NotSupportedException , " Approximation does not work if result is NaN. " ) ;
if ( relative ) {
return upperBound - lowerBound < = approximationError ;
} else {
@ -428,17 +505,17 @@ namespace storm {
}
template < typename ValueType >
void DFTModelChecker < ValueType > : : printTimings ( std : : ostream & os ) {
void DFTModelChecker < ValueType > : : printTimings ( std : : ostream & os ) {
os < < " Times: " < < std : : endl ;
os < < " Exploration: \t " < < explorationTimer < < std : : endl ;
os < < " Building: \t " < < buildingTimer < < std : : endl ;
os < < " Bisimulation: \t " < < bisimulationTimer < < std : : endl ;
os < < " Bisimulation: \t " < < bisimulationTimer < < std : : endl ;
os < < " Modelchecking: \t " < < modelCheckingTimer < < std : : endl ;
os < < " Total: \t \t " < < totalTimer < < std : : endl ;
}
template < typename ValueType >
void DFTModelChecker < ValueType > : : printResults ( dft_results const & results , std : : ostream & os ) {
void DFTModelChecker < ValueType > : : printResults ( dft_results const & results , std : : ostream & os ) {
bool first = true ;
os < < " Result: [ " ;
for ( auto result : results ) {
@ -453,10 +530,14 @@ namespace storm {
}
template class DFTModelChecker < double > ;
template
class DFTModelChecker < double > ;
# ifdef STORM_HAVE_CARL
template class DFTModelChecker < storm : : RationalFunction > ;
template
class DFTModelChecker < storm : : RationalFunction > ;
# endif
}
}