@ -7,19 +7,33 @@
# include "utility/OsDetection.h"
# include "src/storage/sparse/StateType.h"
# include "src/models/symbolic/DeterministicModel.h"
# include "src/models/symbolic/NondeterministicModel.h"
# include "src/models/sparse/DeterministicModel.h"
# include "src/models/sparse/NondeterministicModel.h"
# include "src/utility/constants.h"
# include "src/exceptions/InvalidArgumentException.h"
# include "log4cplus/logger.h"
# include "log4cplus/loggingmacros.h"
extern log4cplus : : Logger logger ;
# include "src/models/sparse/DeterministicModel.h"
# include "src/storage/dd/DdType.h"
namespace storm {
namespace storage {
class BitVector ;
template < typename VT > class SparseMatrix ;
}
namespace models {
namespace symbolic {
template < storm : : dd : : DdType T > class Model ;
template < storm : : dd : : DdType T > class DeterministicModel ;
template < storm : : dd : : DdType T > class NondeterministicModel ;
}
}
namespace dd {
template < storm : : dd : : DdType T > class Bdd ;
template < storm : : dd : : DdType T > class Add ;
}
namespace utility {
namespace graph {
@ -34,38 +48,7 @@ namespace storm {
* @ param targetStates The target states that may not be passed .
*/
template < typename T >
storm : : storage : : BitVector getReachableStates ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , storm : : storage : : BitVector const & initialStates , storm : : storage : : BitVector const & constraintStates , storm : : storage : : BitVector const & targetStates ) {
storm : : storage : : BitVector reachableStates ( initialStates ) ;
/ / Initialize the stack used for the DFS with the states .
std : : vector < uint_fast64_t > stack ( initialStates . begin ( ) , initialStates . end ( ) ) ;
/ / Perform the actual DFS .
uint_fast64_t currentState = 0 ;
while ( ! stack . empty ( ) ) {
currentState = stack . back ( ) ;
stack . pop_back ( ) ;
for ( auto const & successor : transitionMatrix . getRowGroup ( currentState ) ) {
/ / Only explore the state if the transition was actually there and the successor has not yet
/ / been visited .
if ( successor . getValue ( ) ! = storm : : utility : : zero < T > ( ) & & ! reachableStates . get ( successor . getColumn ( ) ) ) {
/ / If the successor is one of the target states , we need to include it , but must not explore
/ / it further .
if ( targetStates . get ( successor . getColumn ( ) ) ) {
reachableStates . set ( successor . getColumn ( ) ) ;
} else if ( constraintStates . get ( successor . getColumn ( ) ) ) {
/ / However , if the state is in the constrained set of states , we need to follow it .
reachableStates . set ( successor . getColumn ( ) ) ;
stack . push_back ( successor . getColumn ( ) ) ;
}
}
}
}
return reachableStates ;
}
storm : : storage : : BitVector getReachableStates ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , storm : : storage : : BitVector const & initialStates , storm : : storage : : BitVector const & constraintStates , storm : : storage : : BitVector const & targetStates ) ;
/*!
* Performs a breadth - first search through the underlying graph structure to compute the distance from all
* states to the starting states of the search .
@ -75,35 +58,7 @@ namespace storm {
* @ return The distances of each state to the initial states of the sarch .
*/
template < typename T >
std : : vector < std : : size_t > getDistances ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , storm : : storage : : BitVector const & initialStates ) {
std : : vector < std : : size_t > distances ( transitionMatrix . getRowGroupCount ( ) ) ;
std : : vector < std : : pair < storm : : storage : : sparse : : state_type , std : : size_t > > stateQueue ;
stateQueue . reserve ( transitionMatrix . getRowGroupCount ( ) ) ;
storm : : storage : : BitVector statesInQueue ( transitionMatrix . getRowGroupCount ( ) ) ;
storm : : storage : : sparse : : state_type currentPosition = 0 ;
for ( auto const & initialState : initialStates ) {
stateQueue . emplace_back ( initialState , 0 ) ;
statesInQueue . set ( initialState ) ;
}
/ / Perform a BFS .
while ( currentPosition < stateQueue . size ( ) ) {
std : : pair < storm : : storage : : sparse : : state_type , std : : size_t > const & stateDistancePair = stateQueue [ currentPosition ] ;
distances [ stateDistancePair . first ] = stateDistancePair . second ;
for ( auto const & successorEntry : transitionMatrix . getRowGroup ( stateDistancePair . first ) ) {
if ( ! statesInQueue . get ( successorEntry . getColumn ( ) ) ) {
stateQueue . emplace_back ( successorEntry . getColumn ( ) , stateDistancePair . second + 1 ) ;
statesInQueue . set ( successorEntry . getColumn ( ) ) ;
}
}
+ + currentPosition ;
}
return distances ;
}
std : : vector < std : : size_t > getDistances ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , storm : : storage : : BitVector const & initialStates ) ;
/*!
* Performs a backward depth - first search trough the underlying graph structure
@ -118,61 +73,7 @@ namespace storm {
* @ return A bit vector with all indices of states that have a probability greater than 0.
*/
template < typename T >
storm : : storage : : BitVector performProbGreater0 ( storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , bool useStepBound = false , uint_fast64_t maximalSteps = 0 ) {
/ / Prepare the resulting bit vector .
uint_fast64_t numberOfStates = phiStates . size ( ) ;
storm : : storage : : BitVector statesWithProbabilityGreater0 ( numberOfStates ) ;
/ / Add all psi states as they already satisfy the condition .
statesWithProbabilityGreater0 | = psiStates ;
/ / Initialize the stack used for the DFS with the states .
std : : vector < uint_fast64_t > stack ( psiStates . begin ( ) , psiStates . end ( ) ) ;
/ / Initialize the stack for the step bound , if the number of steps is bounded .
std : : vector < uint_fast64_t > stepStack ;
std : : vector < uint_fast64_t > remainingSteps ;
if ( useStepBound ) {
stepStack . reserve ( numberOfStates ) ;
stepStack . insert ( stepStack . begin ( ) , psiStates . getNumberOfSetBits ( ) , maximalSteps ) ;
remainingSteps . resize ( numberOfStates ) ;
for ( auto state : psiStates ) {
remainingSteps [ state ] = maximalSteps ;
}
}
/ / Perform the actual DFS .
uint_fast64_t currentState , currentStepBound ;
while ( ! stack . empty ( ) ) {
currentState = stack . back ( ) ;
stack . pop_back ( ) ;
if ( useStepBound ) {
currentStepBound = stepStack . back ( ) ;
stepStack . pop_back ( ) ;
}
for ( typename storm : : storage : : SparseMatrix < T > : : const_iterator entryIt = backwardTransitions . begin ( currentState ) , entryIte = backwardTransitions . end ( currentState ) ; entryIt ! = entryIte ; + + entryIt ) {
if ( phiStates [ entryIt - > getColumn ( ) ] & & ( ! statesWithProbabilityGreater0 . get ( entryIt - > getColumn ( ) ) | | ( useStepBound & & remainingSteps [ entryIt - > getColumn ( ) ] < currentStepBound - 1 ) ) ) {
/ / If we don ' t have a bound on the number of steps to take , just add the state to the stack .
if ( ! useStepBound ) {
statesWithProbabilityGreater0 . set ( entryIt - > getColumn ( ) , true ) ;
stack . push_back ( entryIt - > getColumn ( ) ) ;
} else if ( currentStepBound > 0 ) {
/ / If there is at least one more step to go , we need to push the state and the new number of steps .
remainingSteps [ entryIt - > getColumn ( ) ] = currentStepBound - 1 ;
statesWithProbabilityGreater0 . set ( entryIt - > getColumn ( ) , true ) ;
stack . push_back ( entryIt - > getColumn ( ) ) ;
stepStack . push_back ( currentStepBound - 1 ) ;
}
}
}
}
/ / Return result .
return statesWithProbabilityGreater0 ;
}
storm : : storage : : BitVector performProbGreater0 ( storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , bool useStepBound = false , uint_fast64_t maximalSteps = 0 ) ;
/*!
* Computes the set of states of the given model for which all paths lead to
* the given set of target states and only visit states from the filter set
@ -188,11 +89,7 @@ namespace storm {
* @ return A bit vector with all indices of states that have a probability greater than 1.
*/
template < typename T >
storm : : storage : : BitVector performProb1 ( storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , storm : : storage : : BitVector const & statesWithProbabilityGreater0 ) {
storm : : storage : : BitVector statesWithProbability1 = performProbGreater0 ( backwardTransitions , ~ psiStates , ~ statesWithProbabilityGreater0 ) ;
statesWithProbability1 . complement ( ) ;
return statesWithProbability1 ;
}
storm : : storage : : BitVector performProb1 ( storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , storm : : storage : : BitVector const & statesWithProbabilityGreater0 ) ;
/*!
* Computes the set of states of the given model for which all paths lead to
@ -207,12 +104,7 @@ namespace storm {
* @ return A bit vector with all indices of states that have a probability greater than 1.
*/
template < typename T >
storm : : storage : : BitVector performProb1 ( storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
storm : : storage : : BitVector statesWithProbabilityGreater0 = performProbGreater0 ( backwardTransitions , phiStates , psiStates ) ;
storm : : storage : : BitVector statesWithProbability1 = performProbGreater0 ( backwardTransitions , ~ psiStates , ~ ( statesWithProbabilityGreater0 ) ) ;
statesWithProbability1 . complement ( ) ;
return statesWithProbability1 ;
}
storm : : storage : : BitVector performProb1 ( storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability 0 or 1 , respectively , of satisfying phi until psi in a
@ -225,14 +117,7 @@ namespace storm {
* with probability 0 and the second stores all indices of states with probability 1.
*/
template < typename T >
static std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01 ( storm : : models : : sparse : : DeterministicModel < T > const & model , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > result ;
storm : : storage : : SparseMatrix < T > backwardTransitions = model . getBackwardTransitions ( ) ;
result . first = performProbGreater0 ( backwardTransitions , phiStates , psiStates ) ;
result . second = performProb1 ( backwardTransitions , phiStates , psiStates , result . first ) ;
result . first . complement ( ) ;
return result ;
}
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01 ( storm : : models : : sparse : : DeterministicModel < T > const & model , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability 0 or 1 , respectively , of satisfying phi until psi in a
@ -245,13 +130,8 @@ namespace storm {
* with probability 0 and the second stores all indices of states with probability 1.
*/
template < typename T >
static std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01 ( storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > result ;
result . first = performProbGreater0 ( backwardTransitions , phiStates , psiStates ) ;
result . second = performProb1 ( backwardTransitions , phiStates , psiStates , result . first ) ;
result . first . complement ( ) ;
return result ;
}
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01 ( storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the set of states that has a positive probability of reaching psi states after only passing
@ -265,30 +145,7 @@ namespace storm {
* @ return All states with positive probability .
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProbGreater0 ( storm : : models : : symbolic : : Model < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates , boost : : optional < uint_fast64_t > const & stepBound = boost : : optional < uint_fast64_t > ( ) ) {
/ / Initialize environment for backward search .
storm : : dd : : DdManager < Type > const & manager = model . getManager ( ) ;
storm : : dd : : Bdd < Type > lastIterationStates = manager . getBddZero ( ) ;
storm : : dd : : Bdd < Type > statesWithProbabilityGreater0 = psiStates ;
uint_fast64_t iterations = 0 ;
while ( lastIterationStates ! = statesWithProbabilityGreater0 ) {
if ( stepBound & & iterations > = stepBound . get ( ) ) {
break ;
}
lastIterationStates = statesWithProbabilityGreater0 ;
statesWithProbabilityGreater0 = statesWithProbabilityGreater0 . swapVariables ( model . getRowColumnMetaVariablePairs ( ) ) ;
statesWithProbabilityGreater0 & = transitionMatrix ;
statesWithProbabilityGreater0 = statesWithProbabilityGreater0 . existsAbstract ( model . getColumnVariables ( ) ) ;
statesWithProbabilityGreater0 & = phiStates ;
statesWithProbabilityGreater0 | = lastIterationStates ;
+ + iterations ;
}
return statesWithProbabilityGreater0 ;
}
storm : : dd : : Bdd < Type > performProbGreater0 ( storm : : models : : symbolic : : Model < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates , boost : : optional < uint_fast64_t > const & stepBound = boost : : optional < uint_fast64_t > ( ) ) ;
/*!
* Computes the set of states that have a probability of one of reaching psi states after only passing
* through phi states before .
@ -302,11 +159,7 @@ namespace storm {
* @ return All states with probability 1.
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProb1 ( storm : : models : : symbolic : : Model < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates , storm : : dd : : Bdd < Type > const & statesWithProbabilityGreater0 ) {
storm : : dd : : Bdd < Type > statesWithProbability1 = performProbGreater0 ( model , transitionMatrix , ! psiStates & & model . getReachableStates ( ) , ! statesWithProbabilityGreater0 & & model . getReachableStates ( ) ) ;
statesWithProbability1 = ! statesWithProbability1 & & model . getReachableStates ( ) ;
return statesWithProbability1 ;
}
storm : : dd : : Bdd < Type > performProb1 ( storm : : models : : symbolic : : Model < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates , storm : : dd : : Bdd < Type > const & statesWithProbabilityGreater0 ) ;
/*!
* Computes the set of states that have a probability of one of reaching psi states after only passing
@ -319,10 +172,7 @@ namespace storm {
* @ return All states with probability 1.
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProb1 ( storm : : models : : symbolic : : Model < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
storm : : dd : : Bdd < Type > statesWithProbabilityGreater0 = performProbGreater0 ( model , transitionMatrix , phiStates , psiStates ) ;
return performProb1 ( model , transitionMatrix , phiStates , psiStates , statesWithProbabilityGreater0 ) ;
}
storm : : dd : : Bdd < Type > performProb1 ( storm : : models : : symbolic : : Model < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
/*!
* Computes the sets of states that have probability 0 or 1 , respectively , of satisfying phi until psi in a
@ -334,14 +184,7 @@ namespace storm {
* @ return A pair of BDDs that represent all states with probability 0 and 1 , respectively .
*/
template < storm : : dd : : DdType Type >
static std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > performProb01 ( storm : : models : : symbolic : : DeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > result ;
storm : : dd : : Bdd < Type > transitionMatrix = model . getTransitionMatrix ( ) . notZero ( ) ;
result . first = performProbGreater0 ( model , transitionMatrix , phiStates , psiStates ) ;
result . second = ! performProbGreater0 ( model , transitionMatrix , ! psiStates & & model . getReachableStates ( ) , ! result . first & & model . getReachableStates ( ) ) & & model . getReachableStates ( ) ;
result . first = ! result . first & & model . getReachableStates ( ) ;
return result ;
}
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > performProb01 ( storm : : models : : symbolic : : DeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
/*!
* Computes the sets of states that have probability 0 or 1 , respectively , of satisfying phi until psi in a
@ -354,14 +197,7 @@ namespace storm {
* @ return A pair of BDDs that represent all states with probability 0 and 1 , respectively .
*/
template < storm : : dd : : DdType Type >
static std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > performProb01 ( storm : : models : : symbolic : : Model < Type > const & model , storm : : dd : : Add < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > result ;
storm : : dd : : Bdd < Type > transitionMatrixBdd = transitionMatrix . notZero ( ) ;
result . first = performProbGreater0 ( model , transitionMatrixBdd , phiStates , psiStates ) ;
result . second = ! performProbGreater0 ( model , transitionMatrixBdd , ! psiStates & & model . getReachableStates ( ) , ! result . first & & model . getReachableStates ( ) ) & & model . getReachableStates ( ) ;
result . first = ! result . first & & model . getReachableStates ( ) ;
return result ;
}
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > performProb01 ( storm : : models : : symbolic : : Model < Type > const & model , storm : : dd : : Add < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
/*!
* Computes the sets of states that have probability greater 0 of satisfying phi until psi under at least
@ -378,67 +214,10 @@ namespace storm {
* @ return A bit vector that represents all states with probability 0.
*/
template < typename T >
storm : : storage : : BitVector performProbGreater0E ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , bool useStepBound = false , uint_fast64_t maximalSteps = 0 ) {
size_t numberOfStates = phiStates . size ( ) ;
/ / Prepare resulting bit vector .
storm : : storage : : BitVector statesWithProbabilityGreater0 ( numberOfStates ) ;
/ / Add all psi states as the already satisfy the condition .
statesWithProbabilityGreater0 | = psiStates ;
/ / Initialize the stack used for the DFS with the states
std : : vector < uint_fast64_t > stack ( psiStates . begin ( ) , psiStates . end ( ) ) ;
/ / Initialize the stack for the step bound , if the number of steps is bounded .
std : : vector < uint_fast64_t > stepStack ;
std : : vector < uint_fast64_t > remainingSteps ;
if ( useStepBound ) {
stepStack . reserve ( numberOfStates ) ;
stepStack . insert ( stepStack . begin ( ) , psiStates . getNumberOfSetBits ( ) , maximalSteps ) ;
remainingSteps . resize ( numberOfStates ) ;
for ( auto state : psiStates ) {
remainingSteps [ state ] = maximalSteps ;
}
}
/ / Perform the actual DFS .
uint_fast64_t currentState , currentStepBound ;
while ( ! stack . empty ( ) ) {
currentState = stack . back ( ) ;
stack . pop_back ( ) ;
if ( useStepBound ) {
currentStepBound = stepStack . back ( ) ;
stepStack . pop_back ( ) ;
}
for ( typename storm : : storage : : SparseMatrix < T > : : const_iterator entryIt = backwardTransitions . begin ( currentState ) , entryIte = backwardTransitions . end ( currentState ) ; entryIt ! = entryIte ; + + entryIt ) {
if ( phiStates . get ( entryIt - > getColumn ( ) ) & & ( ! statesWithProbabilityGreater0 . get ( entryIt - > getColumn ( ) ) | | ( useStepBound & & remainingSteps [ entryIt - > getColumn ( ) ] < currentStepBound - 1 ) ) ) {
/ / If we don ' t have a bound on the number of steps to take , just add the state to the stack .
if ( ! useStepBound ) {
statesWithProbabilityGreater0 . set ( entryIt - > getColumn ( ) , true ) ;
stack . push_back ( entryIt - > getColumn ( ) ) ;
} else if ( currentStepBound > 0 ) {
/ / If there is at least one more step to go , we need to push the state and the new number of steps .
remainingSteps [ entryIt - > getColumn ( ) ] = currentStepBound - 1 ;
statesWithProbabilityGreater0 . set ( entryIt - > getColumn ( ) , true ) ;
stack . push_back ( entryIt - > getColumn ( ) ) ;
stepStack . push_back ( currentStepBound - 1 ) ;
}
}
}
}
return statesWithProbabilityGreater0 ;
}
storm : : storage : : BitVector performProbGreater0E ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , bool useStepBound = false , uint_fast64_t maximalSteps = 0 ) ;
template < typename T >
storm : : storage : : BitVector performProb0A ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
storm : : storage : : BitVector statesWithProbability0 = performProbGreater0E ( transitionMatrix , nondeterministicChoiceIndices , backwardTransitions , phiStates , psiStates ) ;
statesWithProbability0 . complement ( ) ;
return statesWithProbability0 ;
}
storm : : storage : : BitVector performProb0A ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability 0 of satisfying phi until psi under all
@ -455,10 +234,7 @@ namespace storm {
* @ return A bit vector that represents all states with probability 0.
*/
template < typename T >
storm : : storage : : BitVector performProb0A ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
return performProb0A ( model . getTransitionMatrix ( ) , model . getNondeterministicChoiceIndices ( ) , backwardTransitions , phiStates , psiStates ) ;
}
storm : : storage : : BitVector performProb0A ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability 1 of satisfying phi until psi under at least
* one possible resolution of non - determinism in a non - deterministic model . Stated differently ,
@ -472,62 +248,7 @@ namespace storm {
* @ return A bit vector that represents all states with probability 1.
*/
template < typename T >
storm : : storage : : BitVector performProb1E ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
size_t numberOfStates = phiStates . size ( ) ;
/ / Initialize the environment for the iterative algorithm .
storm : : storage : : BitVector currentStates ( numberOfStates , true ) ;
std : : vector < uint_fast64_t > stack ;
stack . reserve ( numberOfStates ) ;
/ / Perform the loop as long as the set of states gets larger .
bool done = false ;
uint_fast64_t currentState ;
while ( ! done ) {
stack . clear ( ) ;
storm : : storage : : BitVector nextStates ( psiStates ) ;
stack . insert ( stack . end ( ) , psiStates . begin ( ) , psiStates . end ( ) ) ;
while ( ! stack . empty ( ) ) {
currentState = stack . back ( ) ;
stack . pop_back ( ) ;
for ( typename storm : : storage : : SparseMatrix < T > : : const_iterator predecessorEntryIt = backwardTransitions . begin ( currentState ) , predecessorEntryIte = backwardTransitions . end ( currentState ) ; predecessorEntryIt ! = predecessorEntryIte ; + + predecessorEntryIt ) {
if ( phiStates . get ( predecessorEntryIt - > getColumn ( ) ) & & ! nextStates . get ( predecessorEntryIt - > getColumn ( ) ) ) {
/ / Check whether the predecessor has only successors in the current state set for one of the
/ / nondeterminstic choices .
for ( uint_fast64_t row = nondeterministicChoiceIndices [ predecessorEntryIt - > getColumn ( ) ] ; row < nondeterministicChoiceIndices [ predecessorEntryIt - > getColumn ( ) + 1 ] ; + + row ) {
bool allSuccessorsInCurrentStates = true ;
for ( typename storm : : storage : : SparseMatrix < T > : : const_iterator successorEntryIt = transitionMatrix . begin ( row ) , successorEntryIte = transitionMatrix . end ( row ) ; successorEntryIt ! = successorEntryIte ; + + successorEntryIt ) {
if ( ! currentStates . get ( successorEntryIt - > getColumn ( ) ) ) {
allSuccessorsInCurrentStates = false ;
break ;
}
}
/ / If all successors for a given nondeterministic choice are in the current state set , we
/ / add it to the set of states for the next iteration and perform a backward search from
/ / that state .
if ( allSuccessorsInCurrentStates ) {
nextStates . set ( predecessorEntryIt - > getColumn ( ) , true ) ;
stack . push_back ( predecessorEntryIt - > getColumn ( ) ) ;
break ;
}
}
}
}
}
/ / Check whether we need to perform an additional iteration .
if ( currentStates = = nextStates ) {
done = true ;
} else {
currentStates = std : : move ( nextStates ) ;
}
}
return currentStates ;
}
storm : : storage : : BitVector performProb1E ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability 1 of satisfying phi until psi under at least
@ -542,18 +263,10 @@ namespace storm {
* @ return A bit vector that represents all states with probability 1.
*/
template < typename T >
storm : : storage : : BitVector performProb1E ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
return performProb1E ( model . getTransitionMatrix ( ) , model . getNondeterministicChoiceIndices ( ) , backwardTransitions , phiStates , psiStates ) ;
}
storm : : storage : : BitVector performProb1E ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
template < typename T >
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01Max ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > result ;
result . first = performProb0A ( transitionMatrix , nondeterministicChoiceIndices , backwardTransitions , phiStates , psiStates ) ;
result . second = performProb1E ( transitionMatrix , nondeterministicChoiceIndices , backwardTransitions , phiStates , psiStates ) ;
return result ;
}
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01Max ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability 0 or 1 , respectively , of satisfying phi
@ -566,9 +279,7 @@ namespace storm {
* @ return A pair of bit vectors that represent all states with probability 0 and 1 , respectively .
*/
template < typename T >
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01Max ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
return performProb01Max ( model . getTransitionMatrix ( ) , model . getTransitionMatrix ( ) . getRowGroupIndices ( ) , model . getBackwardTransitions ( ) , phiStates , psiStates ) ;
}
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01Max ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability greater 0 of satisfying phi until psi under any
@ -585,81 +296,7 @@ namespace storm {
* @ return A bit vector that represents all states with probability 0.
*/
template < typename T >
storm : : storage : : BitVector performProbGreater0A ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , bool useStepBound = false , uint_fast64_t maximalSteps = 0 ) {
size_t numberOfStates = phiStates . size ( ) ;
/ / Prepare resulting bit vector .
storm : : storage : : BitVector statesWithProbabilityGreater0 ( numberOfStates ) ;
/ / Add all psi states as the already satisfy the condition .
statesWithProbabilityGreater0 | = psiStates ;
/ / Initialize the stack used for the DFS with the states
std : : vector < uint_fast64_t > stack ( psiStates . begin ( ) , psiStates . end ( ) ) ;
/ / Initialize the stack for the step bound , if the number of steps is bounded .
std : : vector < uint_fast64_t > stepStack ;
std : : vector < uint_fast64_t > remainingSteps ;
if ( useStepBound ) {
stepStack . reserve ( numberOfStates ) ;
stepStack . insert ( stepStack . begin ( ) , psiStates . getNumberOfSetBits ( ) , maximalSteps ) ;
remainingSteps . resize ( numberOfStates ) ;
for ( auto state : psiStates ) {
remainingSteps [ state ] = maximalSteps ;
}
}
/ / Perform the actual DFS .
uint_fast64_t currentState , currentStepBound ;
while ( ! stack . empty ( ) ) {
currentState = stack . back ( ) ;
stack . pop_back ( ) ;
if ( useStepBound ) {
currentStepBound = stepStack . back ( ) ;
stepStack . pop_back ( ) ;
}
for ( typename storm : : storage : : SparseMatrix < T > : : const_iterator predecessorEntryIt = backwardTransitions . begin ( currentState ) , predecessorEntryIte = backwardTransitions . end ( currentState ) ; predecessorEntryIt ! = predecessorEntryIte ; + + predecessorEntryIt ) {
if ( phiStates . get ( predecessorEntryIt - > getColumn ( ) ) & & ( ! statesWithProbabilityGreater0 . get ( predecessorEntryIt - > getColumn ( ) ) | | ( useStepBound & & remainingSteps [ predecessorEntryIt - > getColumn ( ) ] < currentStepBound - 1 ) ) ) {
/ / Check whether the predecessor has at least one successor in the current state set for every
/ / nondeterministic choice .
bool addToStatesWithProbabilityGreater0 = true ;
for ( uint_fast64_t row = nondeterministicChoiceIndices [ predecessorEntryIt - > getColumn ( ) ] ; row < nondeterministicChoiceIndices [ predecessorEntryIt - > getColumn ( ) + 1 ] ; + + row ) {
bool hasAtLeastOneSuccessorWithProbabilityGreater0 = false ;
for ( typename storm : : storage : : SparseMatrix < T > : : const_iterator successorEntryIt = transitionMatrix . begin ( row ) , successorEntryIte = transitionMatrix . end ( row ) ; successorEntryIt ! = successorEntryIte ; + + successorEntryIt ) {
if ( statesWithProbabilityGreater0 . get ( successorEntryIt - > getColumn ( ) ) ) {
hasAtLeastOneSuccessorWithProbabilityGreater0 = true ;
break ;
}
}
if ( ! hasAtLeastOneSuccessorWithProbabilityGreater0 ) {
addToStatesWithProbabilityGreater0 = false ;
break ;
}
}
/ / If we need to add the state , then actually add it and perform further search from the state .
if ( addToStatesWithProbabilityGreater0 ) {
/ / If we don ' t have a bound on the number of steps to take , just add the state to the stack .
if ( ! useStepBound ) {
statesWithProbabilityGreater0 . set ( predecessorEntryIt - > getColumn ( ) , true ) ;
stack . push_back ( predecessorEntryIt - > getColumn ( ) ) ;
} else if ( currentStepBound > 0 ) {
/ / If there is at least one more step to go , we need to push the state and the new number of steps .
remainingSteps [ predecessorEntryIt - > getColumn ( ) ] = currentStepBound - 1 ;
statesWithProbabilityGreater0 . set ( predecessorEntryIt - > getColumn ( ) , true ) ;
stack . push_back ( predecessorEntryIt - > getColumn ( ) ) ;
stepStack . push_back ( currentStepBound - 1 ) ;
}
}
}
}
}
return statesWithProbabilityGreater0 ;
}
storm : : storage : : BitVector performProbGreater0A ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates , bool useStepBound = false , uint_fast64_t maximalSteps = 0 ) ;
/*!
* Computes the sets of states that have probability 0 of satisfying phi until psi under at least
@ -674,18 +311,9 @@ namespace storm {
* @ return A bit vector that represents all states with probability 0.
*/
template < typename T >
storm : : storage : : BitVector performProb0E ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
storm : : storage : : BitVector statesWithProbability0 = performProbGreater0A ( model . getTransitionMatrix ( ) , model . getNondeterministicChoiceIndices ( ) , backwardTransitions , phiStates , psiStates ) ;
statesWithProbability0 . complement ( ) ;
return statesWithProbability0 ;
}
storm : : storage : : BitVector performProb0E ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
template < typename T >
storm : : storage : : BitVector performProb0E ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
storm : : storage : : BitVector statesWithProbability0 = performProbGreater0A ( transitionMatrix , nondeterministicChoiceIndices , backwardTransitions , phiStates , psiStates ) ;
statesWithProbability0 . complement ( ) ;
return statesWithProbability0 ;
}
storm : : storage : : BitVector performProb0E ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability 1 of satisfying phi until psi under all
@ -700,79 +328,10 @@ namespace storm {
* @ return A bit vector that represents all states with probability 0.
*/
template < typename T >
storm : : storage : : BitVector performProb1A ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
size_t numberOfStates = phiStates . size ( ) ;
/ / Initialize the environment for the iterative algorithm .
storm : : storage : : BitVector currentStates ( numberOfStates , true ) ;
std : : vector < uint_fast64_t > stack ;
stack . reserve ( numberOfStates ) ;
/ / Perform the loop as long as the set of states gets smaller .
bool done = false ;
uint_fast64_t currentState ;
while ( ! done ) {
stack . clear ( ) ;
storm : : storage : : BitVector nextStates ( psiStates ) ;
stack . insert ( stack . end ( ) , psiStates . begin ( ) , psiStates . end ( ) ) ;
while ( ! stack . empty ( ) ) {
currentState = stack . back ( ) ;
stack . pop_back ( ) ;
for ( typename storm : : storage : : SparseMatrix < T > : : const_iterator predecessorEntryIt = backwardTransitions . begin ( currentState ) , predecessorEntryIte = backwardTransitions . end ( currentState ) ; predecessorEntryIt ! = predecessorEntryIte ; + + predecessorEntryIt ) {
if ( phiStates . get ( predecessorEntryIt - > getColumn ( ) ) & & ! nextStates . get ( predecessorEntryIt - > getColumn ( ) ) ) {
/ / Check whether the predecessor has only successors in the current state set for all of the
/ / nondeterminstic choices and that for each choice there exists a successor that is already
/ / in the next states .
bool addToStatesWithProbability1 = true ;
for ( uint_fast64_t row = nondeterministicChoiceIndices [ predecessorEntryIt - > getColumn ( ) ] ; row < nondeterministicChoiceIndices [ predecessorEntryIt - > getColumn ( ) + 1 ] ; + + row ) {
bool hasAtLeastOneSuccessorWithProbability1 = false ;
for ( typename storm : : storage : : SparseMatrix < T > : : const_iterator successorEntryIt = transitionMatrix . begin ( row ) , successorEntryIte = transitionMatrix . end ( row ) ; successorEntryIt ! = successorEntryIte ; + + successorEntryIt ) {
if ( ! currentStates . get ( successorEntryIt - > getColumn ( ) ) ) {
addToStatesWithProbability1 = false ;
goto afterCheckLoop ;
}
if ( nextStates . get ( successorEntryIt - > getColumn ( ) ) ) {
hasAtLeastOneSuccessorWithProbability1 = true ;
}
}
if ( ! hasAtLeastOneSuccessorWithProbability1 ) {
addToStatesWithProbability1 = false ;
break ;
}
}
afterCheckLoop :
/ / If all successors for all nondeterministic choices are in the current state set , we
/ / add it to the set of states for the next iteration and perform a backward search from
/ / that state .
if ( addToStatesWithProbability1 ) {
nextStates . set ( predecessorEntryIt - > getColumn ( ) , true ) ;
stack . push_back ( predecessorEntryIt - > getColumn ( ) ) ;
}
}
}
}
/ / Check whether we need to perform an additional iteration .
if ( currentStates = = nextStates ) {
done = true ;
} else {
currentStates = std : : move ( nextStates ) ;
}
}
return currentStates ;
}
storm : : storage : : BitVector performProb1A ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
template < typename T >
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01Min ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > result ;
result . first = performProb0E ( transitionMatrix , nondeterministicChoiceIndices , backwardTransitions , phiStates , psiStates ) ;
result . second = performProb1A ( transitionMatrix , nondeterministicChoiceIndices , backwardTransitions , phiStates , psiStates ) ;
return result ;
}
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01Min ( storm : : storage : : SparseMatrix < T > const & transitionMatrix , std : : vector < uint_fast64_t > const & nondeterministicChoiceIndices , storm : : storage : : SparseMatrix < T > const & backwardTransitions , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the sets of states that have probability 0 or 1 , respectively , of satisfying phi
@ -785,9 +344,7 @@ namespace storm {
* @ return A pair of bit vectors that represent all states with probability 0 and 1 , respectively .
*/
template < typename T >
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01Min ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) {
return performProb01Min ( model . getTransitionMatrix ( ) , model . getTransitionMatrix ( ) . getRowGroupIndices ( ) , model . getBackwardTransitions ( ) , phiStates , psiStates ) ;
}
std : : pair < storm : : storage : : BitVector , storm : : storage : : BitVector > performProb01Min ( storm : : models : : sparse : : NondeterministicModel < T > const & model , storm : : storage : : BitVector const & phiStates , storm : : storage : : BitVector const & psiStates ) ;
/*!
* Computes the set of states for which there exists a scheduler that achieves a probability greater than
@ -800,26 +357,7 @@ namespace storm {
* @ return A BDD representing all such states .
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProbGreater0E ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
/ / Initialize environment for backward search .
storm : : dd : : DdManager < Type > const & manager = model . getManager ( ) ;
storm : : dd : : Bdd < Type > lastIterationStates = manager . getBddZero ( ) ;
storm : : dd : : Bdd < Type > statesWithProbabilityGreater0E = psiStates ;
uint_fast64_t iterations = 0 ;
storm : : dd : : Bdd < Type > abstractedTransitionMatrix = transitionMatrix . existsAbstract ( model . getNondeterminismVariables ( ) ) ;
while ( lastIterationStates ! = statesWithProbabilityGreater0E ) {
lastIterationStates = statesWithProbabilityGreater0E ;
statesWithProbabilityGreater0E = statesWithProbabilityGreater0E . swapVariables ( model . getRowColumnMetaVariablePairs ( ) ) ;
statesWithProbabilityGreater0E = statesWithProbabilityGreater0E . andExists ( abstractedTransitionMatrix , model . getColumnVariables ( ) ) ;
statesWithProbabilityGreater0E & = phiStates ;
statesWithProbabilityGreater0E | = lastIterationStates ;
+ + iterations ;
}
return statesWithProbabilityGreater0E ;
}
storm : : dd : : Bdd < Type > performProbGreater0E ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
/*!
* Computes the set of states for which there does not exist a scheduler that achieves a probability greater
* than zero of satisfying phi until psi .
@ -831,10 +369,7 @@ namespace storm {
* @ return A BDD representing all such states .
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProb0A ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
return ! performProbGreater0E ( model , transitionMatrix , phiStates , psiStates ) & & model . getReachableStates ( ) ;
}
storm : : dd : : Bdd < Type > performProb0A ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
/*!
* Computes the set of states for which all schedulers achieve a probability greater than zero of satisfying
* phi until psi .
@ -846,27 +381,7 @@ namespace storm {
* @ return A BDD representing all such states .
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProbGreater0A ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
/ / Initialize environment for backward search .
storm : : dd : : DdManager < Type > const & manager = model . getManager ( ) ;
storm : : dd : : Bdd < Type > lastIterationStates = manager . getBddZero ( ) ;
storm : : dd : : Bdd < Type > statesWithProbabilityGreater0A = psiStates ;
uint_fast64_t iterations = 0 ;
while ( lastIterationStates ! = statesWithProbabilityGreater0A ) {
lastIterationStates = statesWithProbabilityGreater0A ;
statesWithProbabilityGreater0A = statesWithProbabilityGreater0A . swapVariables ( model . getRowColumnMetaVariablePairs ( ) ) ;
statesWithProbabilityGreater0A = statesWithProbabilityGreater0A . andExists ( transitionMatrix , model . getColumnVariables ( ) ) ;
statesWithProbabilityGreater0A | = model . getIllegalMask ( ) ;
statesWithProbabilityGreater0A = statesWithProbabilityGreater0A . universalAbstract ( model . getNondeterminismVariables ( ) ) ;
statesWithProbabilityGreater0A & = phiStates ;
statesWithProbabilityGreater0A | = psiStates ;
+ + iterations ;
}
return statesWithProbabilityGreater0A ;
}
storm : : dd : : Bdd < Type > performProbGreater0A ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
/*!
* Computes the set of states for which there exists a scheduler that achieves probability zero of satisfying
* phi until psi .
@ -878,9 +393,7 @@ namespace storm {
* @ return A BDD representing all such states .
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProb0E ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
return ! performProbGreater0A ( model , transitionMatrix , phiStates , psiStates ) & & model . getReachableStates ( ) ;
}
storm : : dd : : Bdd < Type > performProb0E ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
/*!
* Computes the set of states for which all schedulers achieve probability one of satisfying phi until psi .
@ -894,26 +407,7 @@ namespace storm {
* @ return A BDD representing all such states .
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProb1A ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates , storm : : dd : : Bdd < Type > const & statesWithProbabilityGreater0A ) {
/ / Initialize environment for backward search .
storm : : dd : : DdManager < Type > const & manager = model . getManager ( ) ;
storm : : dd : : Bdd < Type > lastIterationStates = manager . getBddZero ( ) ;
storm : : dd : : Bdd < Type > statesWithProbability1A = psiStates | | statesWithProbabilityGreater0A ;
uint_fast64_t iterations = 0 ;
while ( lastIterationStates ! = statesWithProbability1A ) {
lastIterationStates = statesWithProbability1A ;
statesWithProbability1A = statesWithProbability1A . swapVariables ( model . getRowColumnMetaVariablePairs ( ) ) ;
statesWithProbability1A = transitionMatrix . implies ( statesWithProbability1A ) . universalAbstract ( model . getColumnVariables ( ) ) ;
statesWithProbability1A | = model . getIllegalMask ( ) ;
statesWithProbability1A = statesWithProbability1A . universalAbstract ( model . getNondeterminismVariables ( ) ) ;
statesWithProbability1A & = statesWithProbabilityGreater0A ;
statesWithProbability1A | = psiStates ;
+ + iterations ;
}
return statesWithProbability1A ;
}
storm : : dd : : Bdd < Type > performProb1A ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates , storm : : dd : : Bdd < Type > const & statesWithProbabilityGreater0A ) ;
/*!
* Computes the set of states for which there exists a scheduler that achieves probability one of satisfying
@ -928,63 +422,13 @@ namespace storm {
* @ return A BDD representing all such states .
*/
template < storm : : dd : : DdType Type >
storm : : dd : : Bdd < Type > performProb1E ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates , storm : : dd : : Bdd < Type > const & statesWithProbabilityGreater0E ) {
/ / Initialize environment for backward search .
storm : : dd : : DdManager < Type > const & manager = model . getManager ( ) ;
storm : : dd : : Bdd < Type > statesWithProbability1E = statesWithProbabilityGreater0E ;
uint_fast64_t iterations = 0 ;
bool outerLoopDone = false ;
while ( ! outerLoopDone ) {
storm : : dd : : Bdd < Type > innerStates = manager . getBddZero ( ) ;
bool innerLoopDone = false ;
while ( ! innerLoopDone ) {
storm : : dd : : Bdd < Type > temporary = statesWithProbability1E . swapVariables ( model . getRowColumnMetaVariablePairs ( ) ) ;
temporary = transitionMatrix . implies ( temporary ) . universalAbstract ( model . getColumnVariables ( ) ) ;
storm : : dd : : Bdd < Type > temporary2 = innerStates . swapVariables ( model . getRowColumnMetaVariablePairs ( ) ) ;
temporary2 = transitionMatrix . andExists ( temporary2 , model . getColumnVariables ( ) ) ;
temporary = temporary . andExists ( temporary2 , model . getNondeterminismVariables ( ) ) ;
temporary & = phiStates ;
temporary | = psiStates ;
if ( innerStates = = temporary ) {
innerLoopDone = true ;
} else {
innerStates = temporary ;
}
}
if ( statesWithProbability1E = = innerStates ) {
outerLoopDone = true ;
} else {
statesWithProbability1E = innerStates ;
}
+ + iterations ;
}
return statesWithProbability1E ;
}
storm : : dd : : Bdd < Type > performProb1E ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & transitionMatrix , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates , storm : : dd : : Bdd < Type > const & statesWithProbabilityGreater0E ) ;
template < storm : : dd : : DdType Type >
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > performProb01Max ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > result ;
storm : : dd : : Bdd < Type > transitionMatrix = model . getTransitionMatrix ( ) . notZero ( ) ;
result . first = performProb0A ( model , transitionMatrix , phiStates , psiStates ) ;
result . second = performProb1E ( model , transitionMatrix , phiStates , psiStates , ! result . first & & model . getReachableStates ( ) ) ;
return result ;
}
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > performProb01Max ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
template < storm : : dd : : DdType Type >
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > performProb01Min ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) {
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > result ;
storm : : dd : : Bdd < Type > transitionMatrix = model . getTransitionMatrix ( ) . notZero ( ) ;
result . first = performProb0E ( model , transitionMatrix , phiStates , psiStates ) ;
result . second = performProb1A ( model , transitionMatrix , phiStates , psiStates , ! result . first & & model . getReachableStates ( ) ) ;
return result ;
}
std : : pair < storm : : dd : : Bdd < Type > , storm : : dd : : Bdd < Type > > performProb01Min ( storm : : models : : symbolic : : NondeterministicModel < Type > const & model , storm : : dd : : Bdd < Type > const & phiStates , storm : : dd : : Bdd < Type > const & psiStates ) ;
/*!
* Performs a topological sort of the states of the system according to the given transitions .
@ -993,73 +437,7 @@ namespace storm {
* @ return A vector of indices that is a topological sort of the states .
*/
template < typename T >
std : : vector < uint_fast64_t > getTopologicalSort ( storm : : storage : : SparseMatrix < T > const & matrix ) {
if ( matrix . getRowCount ( ) ! = matrix . getColumnCount ( ) ) {
LOG4CPLUS_ERROR ( logger , " Provided matrix is required to be square. " ) ;
throw storm : : exceptions : : InvalidArgumentException ( ) < < " Provided matrix is required to be square. " ;
}
uint_fast64_t numberOfStates = matrix . getRowCount ( ) ;
/ / Prepare the result . This relies on the matrix being square .
std : : vector < uint_fast64_t > topologicalSort ;
topologicalSort . reserve ( numberOfStates ) ;
/ / Prepare the stacks needed for recursion .
std : : vector < uint_fast64_t > recursionStack ;
recursionStack . reserve ( matrix . getRowCount ( ) ) ;
std : : vector < typename storm : : storage : : SparseMatrix < T > : : const_iterator > iteratorRecursionStack ;
iteratorRecursionStack . reserve ( numberOfStates ) ;
/ / Perform a depth - first search over the given transitions and record states in the reverse order they were visited .
storm : : storage : : BitVector visitedStates ( numberOfStates ) ;
for ( uint_fast64_t state = 0 ; state < numberOfStates ; + + state ) {
if ( ! visitedStates . get ( state ) ) {
recursionStack . push_back ( state ) ;
iteratorRecursionStack . push_back ( matrix . begin ( state ) ) ;
recursionStepForward :
while ( ! recursionStack . empty ( ) ) {
uint_fast64_t currentState = recursionStack . back ( ) ;
typename storm : : storage : : SparseMatrix < T > : : const_iterator successorIterator = iteratorRecursionStack . back ( ) ;
visitedStates . set ( currentState , true ) ;
recursionStepBackward :
for ( ; successorIterator ! = matrix . end ( currentState ) ; + + successorIterator ) {
if ( ! visitedStates . get ( successorIterator - > getColumn ( ) ) ) {
/ / Put unvisited successor on top of our recursion stack and remember that .
recursionStack . push_back ( successorIterator - > getColumn ( ) ) ;
/ / Also , put initial value for iterator on corresponding recursion stack .
iteratorRecursionStack . push_back ( matrix . begin ( successorIterator - > getColumn ( ) ) ) ;
goto recursionStepForward ;
}
}
topologicalSort . push_back ( currentState ) ;
/ / If we reach this point , we have completed the recursive descent for the current state .
/ / That is , we need to pop it from the recursion stacks .
recursionStack . pop_back ( ) ;
iteratorRecursionStack . pop_back ( ) ;
/ / If there is at least one state under the current one in our recursion stack , we need
/ / to restore the topmost state as the current state and jump to the part after the
/ / original recursive call .
if ( recursionStack . size ( ) > 0 ) {
currentState = recursionStack . back ( ) ;
successorIterator = iteratorRecursionStack . back ( ) ;
goto recursionStepBackward ;
}
}
}
}
return topologicalSort ;
}
std : : vector < uint_fast64_t > getTopologicalSort ( storm : : storage : : SparseMatrix < T > const & matrix ) ;
/*!
* A class needed to compare the distances for two states in the Dijkstra search .
@ -1084,59 +462,7 @@ namespace storm {
std : : pair < std : : vector < T > , std : : vector < uint_fast64_t > > performDijkstra ( storm : : models : : sparse : : Model < T > const & model ,
storm : : storage : : SparseMatrix < T > const & transitions ,
storm : : storage : : BitVector const & startingStates ,
storm : : storage : : BitVector const * filterStates = nullptr ) {
LOG4CPLUS_INFO ( logger , " Performing Dijkstra search. " ) ;
const uint_fast64_t noPredecessorValue = storm : : utility : : zero < uint_fast64_t > ( ) ;
std : : vector < T > probabilities ( model . getNumberOfStates ( ) , storm : : utility : : zero < T > ( ) ) ;
std : : vector < uint_fast64_t > predecessors ( model . getNumberOfStates ( ) , noPredecessorValue ) ;
/ / Set the probability to 1 for all starting states .
std : : set < std : : pair < T , uint_fast64_t > , DistanceCompare < T > > probabilityStateSet ;
for ( auto state : startingStates ) {
probabilityStateSet . emplace ( storm : : utility : : one < T > ( ) , state ) ;
probabilities [ state ] = storm : : utility : : one < T > ( ) ;
}
/ / As long as there is one reachable state , we need to consider it .
while ( ! probabilityStateSet . empty ( ) ) {
/ / Get the state with the least distance from the set and remove it .
std : : pair < T , uint_fast64_t > probabilityStatePair = * probabilityStateSet . begin ( ) ;
probabilityStateSet . erase ( probabilityStateSet . begin ( ) ) ;
/ / Now check the new distances for all successors of the current state .
typename storm : : storage : : SparseMatrix < T > : : Rows row = transitions . getRow ( probabilityStatePair . second ) ;
for ( auto const & transition : row ) {
/ / Only follow the transition if it lies within the filtered states .
if ( filterStates ! = nullptr & & filterStates - > get ( transition . first ) ) {
/ / Calculate the distance we achieve when we take the path to the successor via the current state .
T newDistance = probabilityStatePair . first * transition . second ;
/ / We found a cheaper way to get to the target state of the transition .
if ( newDistance > probabilities [ transition . first ] ) {
/ / Remove the old distance .
if ( probabilities [ transition . first ] ! = noPredecessorValue ) {
probabilityStateSet . erase ( std : : make_pair ( probabilities [ transition . first ] , transition . first ) ) ;
}
/ / Set and add the new distance .
probabilities [ transition . first ] = newDistance ;
predecessors [ transition . first ] = probabilityStatePair . second ;
probabilityStateSet . insert ( std : : make_pair ( newDistance , transition . first ) ) ;
}
}
}
}
/ / Move the values into the result and return it .
std : : pair < std : : vector < T > , std : : vector < uint_fast64_t > > result ;
result . first = std : : move ( probabilities ) ;
result . second = std : : move ( predecessors ) ;
LOG4CPLUS_INFO ( logger , " Done performing Dijkstra search. " ) ;
return result ;
}
storm : : storage : : BitVector const * filterStates = nullptr ) ;
} / / namespace graph
} / / namespace utility
xxxxxxxxxx