@ -52,92 +52,27 @@ public:
class ExplicitModelAdapter {
class ExplicitModelAdapter {
public :
public :
template < class T >
std : : shared_ptr < storm : : storage : : SparseMatrix < T > > toSparseMatrix ( storm : : ir : : Program const & program ) {
LOG4CPLUS_INFO ( logger , " Creating sparse matrix for probabilistic program. " ) ;
this - > computeReachableStateSpace ( program ) ;
std : : shared_ptr < storm : : storage : : SparseMatrix < T > > resultMatrix ( new storm : : storage : : SparseMatrix < T > ( allStates . size ( ) ) ) ;
resultMatrix - > initialize ( totalNumberOfTransitions ) ;
uint_fast64_t currentIndex = 0 ;
for ( StateType * currentState : allStates ) {
bool hasTransition = false ;
/ / Iterate over all modules .
for ( uint_fast64_t i = 0 ; i < program . getNumberOfModules ( ) ; + + i ) {
storm : : ir : : Module const & module = program . getModule ( i ) ;
/ / Iterate over all commands .
for ( uint_fast64_t j = 0 ; j < module . getNumberOfCommands ( ) ; + + j ) {
storm : : ir : : Command const & command = module . getCommand ( j ) ;
/ / Check if this command is enabled in the current state .
if ( command . getGuard ( ) - > getValueAsBool ( currentState ) ) {
hasTransition = true ;
std : : map < uint_fast64_t , double > stateIndexToProbabilityMap ;
for ( uint_fast64_t k = 0 ; k < command . getNumberOfUpdates ( ) ; + + k ) {
storm : : ir : : Update const & update = command . getUpdate ( k ) ;
StateType * newState = new StateType ( * currentState ) ;
std : : map < std : : string , storm : : ir : : Assignment > const & booleanAssignmentMap = update . getBooleanAssignments ( ) ;
for ( auto assignedVariable : booleanAssignmentMap ) {
setValue ( newState , booleanVariableToIndexMap [ assignedVariable . first ] , assignedVariable . second . getExpression ( ) - > getValueAsBool ( currentState ) ) ;
}
std : : map < std : : string , storm : : ir : : Assignment > const & integerAssignmentMap = update . getIntegerAssignments ( ) ;
for ( auto assignedVariable : integerAssignmentMap ) {
setValue ( newState , integerVariableToIndexMap [ assignedVariable . first ] , assignedVariable . second . getExpression ( ) - > getValueAsInt ( currentState ) ) ;
}
ExplicitModelAdapter ( std : : shared_ptr < storm : : ir : : Program > program ) : program ( program ) , allStates ( ) ,
stateToIndexMap ( ) , booleanVariables ( ) , integerVariables ( ) , booleanVariableToIndexMap ( ) ,
integerVariableToIndexMap ( ) , numberOfTransitions ( 0 ) {
uint_fast64_t targetIndex = ( * stateToIndexMap . find ( newState ) ) . second ;
delete newState ;
auto probIt = stateIndexToProbabilityMap . find ( targetIndex ) ;
if ( probIt ! = stateIndexToProbabilityMap . end ( ) ) {
stateIndexToProbabilityMap [ targetIndex ] + = update . getLikelihoodExpression ( ) - > getValueAsDouble ( currentState ) ;
} else {
stateIndexToProbabilityMap [ targetIndex ] = update . getLikelihoodExpression ( ) - > getValueAsDouble ( currentState ) ;
}
}
/ / Now insert the actual values into the matrix .
for ( auto targetIndex : stateIndexToProbabilityMap ) {
resultMatrix - > addNextValue ( currentIndex , targetIndex . first , targetIndex . second ) ;
}
}
}
}
if ( ! hasTransition ) {
resultMatrix - > addNextValue ( currentIndex , currentIndex , 1 ) ;
}
}
+ + currentIndex ;
}
template < class T >
std : : shared_ptr < storm : : storage : : SparseMatrix < T > > toSparseMatrix ( ) {
LOG4CPLUS_INFO ( logger , " Creating sparse matrix for probabilistic program. " ) ;
resultMatrix - > finalize ( ) ;
this - > computeReachableStateSpace ( ) ;
std : : shared_ptr < storm : : storage : : SparseMatrix < T > > resultMatrix = this - > buildMatrix < T > ( ) ;
LOG4CPLUS_INFO ( logger , " Created sparse matrix with " < < allStates . size ( ) < < " reachable states and " < < totalNumberOfTransitions < < " transitions. " ) ;
LOG4CPLUS_INFO ( logger , " Created sparse matrix with " < < resultMatrix - > getRowCount ( ) < < " reachable states and " < < resultMatrix - > getNonZeroEntryCount ( ) < < " transitions. " ) ;
/ / Now free all the elements we allocated .
for ( auto element : allStates ) {
delete element ;
}
this - > clearReachableStateSpace ( ) ;
return resultMatrix ;
return resultMatrix ;
}
}
private :
private :
static StateType * getNewState ( uint_fast64_t numberOfBooleanVariables , uint_fast64_t numberOfIntegerVariables ) {
StateType * result = new StateType ( ) ;
result - > first . resize ( numberOfBooleanVariables ) ;
result - > second . resize ( numberOfIntegerVariables ) ;
return result ;
}
static void setValue ( StateType * state , uint_fast64_t index , bool value ) {
static void setValue ( StateType * state , uint_fast64_t index , bool value ) {
std : : get < 0 > ( * state ) [ index ] = value ;
std : : get < 0 > ( * state ) [ index ] = value ;
}
}
@ -146,28 +81,21 @@ private:
std : : get < 1 > ( * state ) [ index ] = value ;
std : : get < 1 > ( * state ) [ index ] = value ;
}
}
void computeReachableStateSpace ( storm : : ir : : Program const & program ) {
bool nondeterministicModel = program . getModelType ( ) = = storm : : ir : : Program : : MDP | | program . getModelType ( ) = = storm : : ir : : Program : : CTMDP ;
void prepareAuxiliaryDatastructures ( ) {
uint_fast64_t numberOfIntegerVariables = 0 ;
uint_fast64_t numberOfIntegerVariables = 0 ;
uint_fast64_t numberOfBooleanVariables = 0 ;
uint_fast64_t numberOfBooleanVariables = 0 ;
for ( uint_fast64_t i = 0 ; i < program . getNumberOfModules ( ) ; + + i ) {
numberOfIntegerVariables + = program . getModule ( i ) . getNumberOfIntegerVariables ( ) ;
numberOfBooleanVariables + = program . getModule ( i ) . getNumberOfBooleanVariables ( ) ;
for ( uint_fast64_t i = 0 ; i < program - > getNumberOfModules ( ) ; + + i ) {
numberOfIntegerVariables + = program - > getModule ( i ) . getNumberOfIntegerVariables ( ) ;
numberOfBooleanVariables + = program - > getModule ( i ) . getNumberOfBooleanVariables ( ) ;
}
}
std : : vector < storm : : ir : : BooleanVariable > booleanVariables ;
std : : vector < storm : : ir : : IntegerVariable > integerVariables ;
booleanVariables . resize ( numberOfBooleanVariables ) ;
booleanVariables . resize ( numberOfBooleanVariables ) ;
integerVariables . resize ( numberOfIntegerVariables ) ;
integerVariables . resize ( numberOfIntegerVariables ) ;
std : : unordered_map < std : : string , uint_fast64_t > booleanVariableToIndexMap ;
std : : unordered_map < std : : string , uint_fast64_t > integerVariableToIndexMap ;
uint_fast64_t nextBooleanVariableIndex = 0 ;
uint_fast64_t nextBooleanVariableIndex = 0 ;
uint_fast64_t nextIntegerVariableIndex = 0 ;
uint_fast64_t nextIntegerVariableIndex = 0 ;
for ( uint_fast64_t i = 0 ; i < program . getNumberOfModules ( ) ; + + i ) {
storm : : ir : : Module const & module = program . getModule ( i ) ;
for ( uint_fast64_t i = 0 ; i < program - > getNumberOfModules ( ) ; + + i ) {
storm : : ir : : Module const & module = program - > getModule ( i ) ;
for ( uint_fast64_t j = 0 ; j < module . getNumberOfBooleanVariables ( ) ; + + j ) {
for ( uint_fast64_t j = 0 ; j < module . getNumberOfBooleanVariables ( ) ; + + j ) {
booleanVariables [ nextBooleanVariableIndex ] = module . getBooleanVariable ( j ) ;
booleanVariables [ nextBooleanVariableIndex ] = module . getBooleanVariable ( j ) ;
@ -180,39 +108,53 @@ private:
+ + nextIntegerVariableIndex ;
+ + nextIntegerVariableIndex ;
}
}
}
}
}
void computeReachableStateSpace ( ) {
bool nondeterministicModel = program - > getModelType ( ) = = storm : : ir : : Program : : MDP | | program - > getModelType ( ) = = storm : : ir : : Program : : CTMDP ;
/ / Prepare some internal data structures , such as mappings from variables to indices and so on .
this - > prepareAuxiliaryDatastructures ( ) ;
StateType * initialState = getNewState ( numberOfBooleanVariables , numberOfIntegerVariables ) ;
/ / Create a fresh state which can hold as many boolean and integer variables as there are .
StateType * initialState = new StateType ( ) ;
initialState - > first . resize ( booleanVariables . size ( ) ) ;
initialState - > second . resize ( integerVariables . size ( ) ) ;
for ( uint_fast64_t i = 0 ; i < numberOfBooleanVariables ; + + i ) {
/ / Now initialize all fields in the value vectors of the state according to the initial
/ / values provided by the input program .
for ( uint_fast64_t i = 0 ; i < booleanVariables . size ( ) ; + + i ) {
bool initialValue = booleanVariables [ i ] . getInitialValue ( ) - > getValueAsBool ( initialState ) ;
bool initialValue = booleanVariables [ i ] . getInitialValue ( ) - > getValueAsBool ( initialState ) ;
std : : get < 0 > ( * initialState ) [ i ] = initialValue ;
std : : get < 0 > ( * initialState ) [ i ] = initialValue ;
}
}
for ( uint_fast64_t i = 0 ; i < numberOfIntegerVariables ; + + i ) {
for ( uint_fast64_t i = 0 ; i < integerVariables . size ( ) ; + + i ) {
int_fast64_t initialValue = integerVariables [ i ] . getInitialValue ( ) - > getValueAsInt ( initialState ) ;
int_fast64_t initialValue = integerVariables [ i ] . getInitialValue ( ) - > getValueAsInt ( initialState ) ;
std : : get < 1 > ( * initialState ) [ i ] = initialValue ;
std : : get < 1 > ( * initialState ) [ i ] = initialValue ;
}
}
/ / Now set up the environment for a breadth - first search starting from the initial state .
uint_fast64_t nextIndex = 1 ;
uint_fast64_t nextIndex = 1 ;
std : : unordered_map < StateType * , uint_fast64_t , StateHash , StateCompare > stateToIndexMap ;
std : : vector < StateType * > allStates ;
allStates . clear ( ) ;
stateToIndexMap . clear ( ) ;
std : : queue < StateType * > stateQueue ;
std : : queue < StateType * > stateQueue ;
allStates . push_back ( initialState ) ;
allStates . push_back ( initialState ) ;
stateQueue . push ( initialState ) ;
stateQueue . push ( initialState ) ;
stateToIndexMap [ initialState ] = 0 ;
stateToIndexMap [ initialState ] = 0 ;
ui nt_fast64_t totalN umberOfTransitions = 0 ;
numberOfTransitions = 0 ;
while ( ! stateQueue . empty ( ) ) {
while ( ! stateQueue . empty ( ) ) {
/ / Get first state in queue .
/ / Get first state in queue .
StateType * currentState = stateQueue . front ( ) ;
StateType * currentState = stateQueue . front ( ) ;
stateQueue . pop ( ) ;
stateQueue . pop ( ) ;
/ / Remember whether the state has at least one transition such that transitions can be
/ / inserted upon detection of a deadlock state .
bool hasTransition = false ;
bool hasTransition = false ;
/ / Iterate over all modules .
/ / Iterate over all modules .
for ( uint_fast64_t i = 0 ; i < program . getNumberOfModules ( ) ; + + i ) {
storm : : ir : : Module const & module = program . getModule ( i ) ;
for ( uint_fast64_t i = 0 ; i < program - > getNumberOfModules ( ) ; + + i ) {
storm : : ir : : Module const & module = program - > getModule ( i ) ;
/ / Iterate over all commands .
/ / Iterate over all commands .
for ( uint_fast64_t j = 0 ; j < module . getNumberOfCommands ( ) ; + + j ) {
for ( uint_fast64_t j = 0 ; j < module . getNumberOfCommands ( ) ; + + j ) {
@ -221,11 +163,26 @@ private:
/ / Check if this command is enabled in the current state .
/ / Check if this command is enabled in the current state .
if ( command . getGuard ( ) - > getValueAsBool ( currentState ) ) {
if ( command . getGuard ( ) - > getValueAsBool ( currentState ) ) {
hasTransition = true ;
hasTransition = true ;
/ / Remember what states are targeted by an update of the current command
/ / in order to be able to sum those probabilities and not increase the
/ / transition count .
std : : unordered_map < StateType * , double , StateHash , StateCompare > stateToProbabilityMap ;
std : : unordered_map < StateType * , double , StateHash , StateCompare > stateToProbabilityMap ;
/ / Keep a queue of states to delete after the current command . When one
/ / command is processed and states are encountered which were already found
/ / before , we can only delete them after the command has been processed ,
/ / because the stateToProbabilityMap will contain illegal values otherwise .
std : : queue < StateType * > statesToDelete ;
std : : queue < StateType * > statesToDelete ;
/ / Now iterate over all updates to see where the updates take the current
/ / state .
for ( uint_fast64_t k = 0 ; k < command . getNumberOfUpdates ( ) ; + + k ) {
for ( uint_fast64_t k = 0 ; k < command . getNumberOfUpdates ( ) ; + + k ) {
storm : : ir : : Update const & update = command . getUpdate ( k ) ;
storm : : ir : : Update const & update = command . getUpdate ( k ) ;
/ / Now copy the current state and only overwrite the entries in the
/ / vectors if there is an assignment to that variable in the current
/ / update .
StateType * newState = new StateType ( * currentState ) ;
StateType * newState = new StateType ( * currentState ) ;
std : : map < std : : string , storm : : ir : : Assignment > const & booleanAssignmentMap = update . getBooleanAssignments ( ) ;
std : : map < std : : string , storm : : ir : : Assignment > const & booleanAssignmentMap = update . getBooleanAssignments ( ) ;
for ( auto assignedVariable : booleanAssignmentMap ) {
for ( auto assignedVariable : booleanAssignmentMap ) {
@ -236,23 +193,29 @@ private:
setValue ( newState , integerVariableToIndexMap [ assignedVariable . first ] , assignedVariable . second . getExpression ( ) - > getValueAsInt ( currentState ) ) ;
setValue ( newState , integerVariableToIndexMap [ assignedVariable . first ] , assignedVariable . second . getExpression ( ) - > getValueAsInt ( currentState ) ) ;
}
}
/ / If we have already found the target state of the update , we must not
/ / increase the transition count .
auto probIt = stateToProbabilityMap . find ( newState ) ;
auto probIt = stateToProbabilityMap . find ( newState ) ;
if ( probIt ! = stateToProbabilityMap . end ( ) ) {
if ( probIt ! = stateToProbabilityMap . end ( ) ) {
stateToProbabilityMap [ newState ] + = update . getLikelihoodExpression ( ) - > getValueAsDouble ( currentState ) ;
stateToProbabilityMap [ newState ] + = update . getLikelihoodExpression ( ) - > getValueAsDouble ( currentState ) ;
} else {
} else {
+ + totalN umberOfTransitions;
+ + n umberOfTransitions;
stateToProbabilityMap [ newState ] = update . getLikelihoodExpression ( ) - > getValueAsDouble ( currentState ) ;
stateToProbabilityMap [ newState ] = update . getLikelihoodExpression ( ) - > getValueAsDouble ( currentState ) ;
}
}
/ / Depending on whether the state was found previously , we mark it for
/ / deletion or add it to the reachable state space and mark it for
/ / further exploration .
auto it = stateToIndexMap . find ( newState ) ;
auto it = stateToIndexMap . find ( newState ) ;
if ( it ! = stateToIndexMap . end ( ) ) {
if ( it ! = stateToIndexMap . end ( ) ) {
/ / Delete the state object directly as we have already seen that state .
/ / Queue the state object for deletion as we have already seen that
/ / state .
statesToDelete . push ( newState ) ;
statesToDelete . push ( newState ) ;
} else {
} else {
/ / Add state to the queue of states that are still to be explored .
/ / Add state to the queue of states that are still to be explored .
stateQueue . push ( newState ) ;
stateQueue . push ( newState ) ;
/ / Add state to list of all states so that we can delete it at the end .
/ / Add state to list of all reachable states .
allStates . push_back ( newState ) ;
allStates . push_back ( newState ) ;
/ / Give a unique index to the newly found state .
/ / Give a unique index to the newly found state .
@ -260,6 +223,8 @@ private:
+ + nextIndex ;
+ + nextIndex ;
}
}
}
}
/ / Now delete all states queued for deletion .
while ( ! statesToDelete . empty ( ) ) {
while ( ! statesToDelete . empty ( ) ) {
delete statesToDelete . front ( ) ;
delete statesToDelete . front ( ) ;
statesToDelete . pop ( ) ;
statesToDelete . pop ( ) ;
@ -268,9 +233,12 @@ private:
}
}
}
}
/ / If the state is a deadlock state , and the corresponding flag is set , we tolerate that
/ / and increase the number of transitions by one , because a self - loop is going to be
/ / inserted in the next step . If the flag is not set , an exception is thrown .
if ( ! hasTransition ) {
if ( ! hasTransition ) {
if ( storm : : settings : : instance ( ) - > isSet ( " fix-deadlocks " ) ) {
if ( storm : : settings : : instance ( ) - > isSet ( " fix-deadlocks " ) ) {
+ + totalNumberOfTransitions ;
+ + n umberOfTransitions;
} else {
} else {
LOG4CPLUS_ERROR ( logger , " Error while creating sparse matrix from probabilistic program: found deadlock state. " ) ;
LOG4CPLUS_ERROR ( logger , " Error while creating sparse matrix from probabilistic program: found deadlock state. " ) ;
throw storm : : exceptions : : WrongFileFormatException ( ) < < " Error while creating sparse matrix from probabilistic program: found deadlock state. " ;
throw storm : : exceptions : : WrongFileFormatException ( ) < < " Error while creating sparse matrix from probabilistic program: found deadlock state. " ;
@ -279,9 +247,91 @@ private:
}
}
}
}
template < class T >
std : : shared_ptr < storm : : storage : : SparseMatrix < T > > buildMatrix ( ) {
std : : shared_ptr < storm : : storage : : SparseMatrix < T > > resultMatrix ( new storm : : storage : : SparseMatrix < T > ( allStates . size ( ) ) ) ;
resultMatrix - > initialize ( numberOfTransitions ) ;
/ / Keep track of the running index to insert values into correct matrix row .
uint_fast64_t currentIndex = 0 ;
/ / Determine the matrix content for every row ( i . e . reachable state ) .
for ( StateType * currentState : allStates ) {
bool hasTransition = false ;
/ / Iterate over all modules .
for ( uint_fast64_t i = 0 ; i < program - > getNumberOfModules ( ) ; + + i ) {
storm : : ir : : Module const & module = program - > getModule ( i ) ;
/ / Iterate over all commands .
for ( uint_fast64_t j = 0 ; j < module . getNumberOfCommands ( ) ; + + j ) {
storm : : ir : : Command const & command = module . getCommand ( j ) ;
/ / Check if this command is enabled in the current state .
if ( command . getGuard ( ) - > getValueAsBool ( currentState ) ) {
hasTransition = true ;
std : : map < uint_fast64_t , double > stateIndexToProbabilityMap ;
for ( uint_fast64_t k = 0 ; k < command . getNumberOfUpdates ( ) ; + + k ) {
storm : : ir : : Update const & update = command . getUpdate ( k ) ;
StateType * newState = new StateType ( * currentState ) ;
std : : map < std : : string , storm : : ir : : Assignment > const & booleanAssignmentMap = update . getBooleanAssignments ( ) ;
for ( auto assignedVariable : booleanAssignmentMap ) {
setValue ( newState , booleanVariableToIndexMap [ assignedVariable . first ] , assignedVariable . second . getExpression ( ) - > getValueAsBool ( currentState ) ) ;
}
std : : map < std : : string , storm : : ir : : Assignment > const & integerAssignmentMap = update . getIntegerAssignments ( ) ;
for ( auto assignedVariable : integerAssignmentMap ) {
setValue ( newState , integerVariableToIndexMap [ assignedVariable . first ] , assignedVariable . second . getExpression ( ) - > getValueAsInt ( currentState ) ) ;
}
uint_fast64_t targetIndex = ( * stateToIndexMap . find ( newState ) ) . second ;
delete newState ;
auto probIt = stateIndexToProbabilityMap . find ( targetIndex ) ;
if ( probIt ! = stateIndexToProbabilityMap . end ( ) ) {
stateIndexToProbabilityMap [ targetIndex ] + = update . getLikelihoodExpression ( ) - > getValueAsDouble ( currentState ) ;
} else {
stateIndexToProbabilityMap [ targetIndex ] = update . getLikelihoodExpression ( ) - > getValueAsDouble ( currentState ) ;
}
}
/ / Now insert the actual values into the matrix .
for ( auto targetIndex : stateIndexToProbabilityMap ) {
resultMatrix - > addNextValue ( currentIndex , targetIndex . first , targetIndex . second ) ;
}
}
}
}
/ / If the state is a deadlock state , a self - loop is inserted . Note that we do not have
/ / to check whether - - fix - deadlocks is set , because if this was not the case an
/ / exception would have been thrown earlier .
if ( ! hasTransition ) {
resultMatrix - > addNextValue ( currentIndex , currentIndex , 1 ) ;
}
+ + currentIndex ;
}
/ / Finalize matrix and return it .
resultMatrix - > finalize ( ) ;
return resultMatrix ;
}
void clearReachableStateSpace ( ) {
allStates . clear ( ) ;
stateToIndexMap . clear ( ) ;
}
std : : shared_ptr < storm : : ir : : Program > program ;
std : : vector < StateType * > allStates ;
std : : vector < StateType * > allStates ;
std : : unordered_map < StateType * , uint_fast64_t , StateHash , StateCompare > stateToIndexMap ;
std : : vector < storm : : ir : : BooleanVariable > booleanVariables ;
std : : vector < storm : : ir : : IntegerVariable > integerVariables ;
std : : unordered_map < std : : string , uint_fast64_t > booleanVariableToIndexMap ;
std : : unordered_map < std : : string , uint_fast64_t > integerVariableToIndexMap ;
uint_fast64_t numberOfTransitions ;
uint_fast64_t numberOfTransitions ;
std : : vector < uint_fast64_t > numbersOfNondeterministicChoices ;
} ;
} ;
} / / namespace adapters
} / / namespace adapters