@ -20,7 +20,6 @@
# include "src/storage/prism/CompositionVisitor.h"
# include "src/storage/prism/Compositions.h"
# include "src/storage/prism/CompositionToJaniVisitor.h"
namespace storm {
namespace prism {
@ -1610,180 +1609,10 @@ namespace storm {
return this - > indexToActionMap . rbegin ( ) - > first ;
}
storm : : expressions : : ExpressionManager const & Program : : getManager ( ) const {
storm : : expressions : : ExpressionManager & Program : : getManager ( ) const {
return * this - > manager ;
}
storm : : expressions : : ExpressionManager & Program : : getManager ( ) {
return * this - > manager ;
}
storm : : jani : : Model Program : : toJani ( bool allVariablesGlobal ) const {
// Start by creating an empty JANI model.
storm : : jani : : ModelType modelType ;
switch ( this - > getModelType ( ) ) {
case Program : : ModelType : : DTMC : modelType = storm : : jani : : ModelType : : DTMC ;
break ;
case Program : : ModelType : : CTMC : modelType = storm : : jani : : ModelType : : CTMC ;
break ;
case Program : : ModelType : : MDP : modelType = storm : : jani : : ModelType : : MDP ;
break ;
case Program : : ModelType : : CTMDP : modelType = storm : : jani : : ModelType : : CTMDP ;
break ;
case Program : : ModelType : : MA : modelType = storm : : jani : : ModelType : : MA ;
break ;
default : modelType = storm : : jani : : ModelType : : UNDEFINED ;
}
storm : : jani : : Model janiModel ( " jani_from_prism " , modelType , 1 , manager ) ;
// Add all constants of the PRISM program to the JANI model.
for ( auto const & constant : constants ) {
janiModel . addConstant ( storm : : jani : : Constant ( constant . getName ( ) , constant . getExpressionVariable ( ) , constant . isDefined ( ) ? boost : : optional < storm : : expressions : : Expression > ( constant . getExpression ( ) ) : boost : : none ) ) ;
}
// Maintain a mapping from expression variables to JANI variables so we can fill in the correct objects when
// creating assignments.
std : : map < storm : : expressions : : Variable , std : : reference_wrapper < storm : : jani : : Variable const > > variableToVariableMap ;
// Add all global variables of the PRISM program to the JANI model.
for ( auto const & variable : globalIntegerVariables ) {
if ( variable . hasInitialValue ( ) ) {
storm : : jani : : BoundedIntegerVariable const & createdVariable = janiModel . addBoundedIntegerVariable ( storm : : jani : : BoundedIntegerVariable ( variable . getName ( ) , variable . getExpressionVariable ( ) , variable . getInitialValueExpression ( ) , false , variable . getLowerBoundExpression ( ) , variable . getUpperBoundExpression ( ) ) ) ;
variableToVariableMap . emplace ( variable . getExpressionVariable ( ) , createdVariable ) ;
} else {
storm : : jani : : BoundedIntegerVariable const & createdVariable = janiModel . addBoundedIntegerVariable ( storm : : jani : : BoundedIntegerVariable ( variable . getName ( ) , variable . getExpressionVariable ( ) , false , variable . getLowerBoundExpression ( ) , variable . getUpperBoundExpression ( ) ) ) ;
variableToVariableMap . emplace ( variable . getExpressionVariable ( ) , createdVariable ) ;
}
}
for ( auto const & variable : globalBooleanVariables ) {
if ( variable . hasInitialValue ( ) ) {
storm : : jani : : BooleanVariable const & createdVariable = janiModel . addBooleanVariable ( storm : : jani : : BooleanVariable ( variable . getName ( ) , variable . getExpressionVariable ( ) , variable . getInitialValueExpression ( ) , false ) ) ;
variableToVariableMap . emplace ( variable . getExpressionVariable ( ) , createdVariable ) ;
} else {
storm : : jani : : BooleanVariable const & createdVariable = janiModel . addBooleanVariable ( storm : : jani : : BooleanVariable ( variable . getName ( ) , variable . getExpressionVariable ( ) , false ) ) ;
variableToVariableMap . emplace ( variable . getExpressionVariable ( ) , createdVariable ) ;
}
}
// Add all actions of the PRISM program to the JANI model.
for ( auto const & action : indexToActionMap ) {
// Ignore the empty action as every JANI program has predefined tau action.
if ( ! action . second . empty ( ) ) {
janiModel . addAction ( storm : : jani : : Action ( action . second ) ) ;
}
}
// Because of the rules of JANI, we have to make all variables of modules global that are read by other modules.
// Create a mapping from variables to the indices of module indices that write/read the variable.
std : : map < storm : : expressions : : Variable , std : : set < uint_fast64_t > > variablesToAccessingModuleIndices ;
for ( uint_fast64_t index = 0 ; index < modules . size ( ) ; + + index ) {
storm : : prism : : Module const & module = modules [ index ] ;
for ( auto const & command : module . getCommands ( ) ) {
std : : set < storm : : expressions : : Variable > variables = command . getGuardExpression ( ) . getVariables ( ) ;
for ( auto const & variable : variables ) {
variablesToAccessingModuleIndices [ variable ] . insert ( index ) ;
}
for ( auto const & update : command . getUpdates ( ) ) {
for ( auto const & assignment : update . getAssignments ( ) ) {
variables = assignment . getExpression ( ) . getVariables ( ) ;
for ( auto const & variable : variables ) {
variablesToAccessingModuleIndices [ variable ] . insert ( index ) ;
}
variablesToAccessingModuleIndices [ assignment . getVariable ( ) ] . insert ( index ) ;
}
}
}
}
// Now create the separate JANI automata from the modules of the PRISM program. While doing so, we use the
// previously built mapping to make variables global that are read by more than one module.
for ( auto const & module : modules ) {
storm : : jani : : Automaton automaton ( module . getName ( ) ) ;
for ( auto const & variable : module . getIntegerVariables ( ) ) {
storm : : jani : : BoundedIntegerVariable newIntegerVariable = * storm : : jani : : makeBoundedIntegerVariable ( variable . getName ( ) , variable . getExpressionVariable ( ) , variable . hasInitialValue ( ) ? boost : : make_optional ( variable . getInitialValueExpression ( ) ) : boost : : none , false , variable . getLowerBoundExpression ( ) , variable . getUpperBoundExpression ( ) ) ;
std : : set < uint_fast64_t > const & accessingModuleIndices = variablesToAccessingModuleIndices [ variable . getExpressionVariable ( ) ] ;
// If there is exactly one module reading and writing the variable, we can make the variable local to this module.
if ( ! allVariablesGlobal & & accessingModuleIndices . size ( ) = = 1 ) {
storm : : jani : : BoundedIntegerVariable const & createdVariable = automaton . addBoundedIntegerVariable ( newIntegerVariable ) ;
variableToVariableMap . emplace ( variable . getExpressionVariable ( ) , createdVariable ) ;
} else if ( ! accessingModuleIndices . empty ( ) ) {
// Otherwise, we need to make it global.
storm : : jani : : BoundedIntegerVariable const & createdVariable = janiModel . addBoundedIntegerVariable ( newIntegerVariable ) ;
variableToVariableMap . emplace ( variable . getExpressionVariable ( ) , createdVariable ) ;
}
}
for ( auto const & variable : module . getBooleanVariables ( ) ) {
storm : : jani : : BooleanVariable newBooleanVariable = * storm : : jani : : makeBooleanVariable ( variable . getName ( ) , variable . getExpressionVariable ( ) , variable . hasInitialValue ( ) ? boost : : make_optional ( variable . getInitialValueExpression ( ) ) : boost : : none , false ) ;
std : : set < uint_fast64_t > const & accessingModuleIndices = variablesToAccessingModuleIndices [ variable . getExpressionVariable ( ) ] ;
// If there is exactly one module reading and writing the variable, we can make the variable local to this module.
if ( ! allVariablesGlobal & & accessingModuleIndices . size ( ) = = 1 ) {
storm : : jani : : BooleanVariable const & createdVariable = automaton . addBooleanVariable ( newBooleanVariable ) ;
variableToVariableMap . emplace ( variable . getExpressionVariable ( ) , createdVariable ) ;
} else if ( ! accessingModuleIndices . empty ( ) ) {
// Otherwise, we need to make it global.
storm : : jani : : BooleanVariable const & createdVariable = janiModel . addBooleanVariable ( newBooleanVariable ) ;
variableToVariableMap . emplace ( variable . getExpressionVariable ( ) , createdVariable ) ;
}
}
automaton . setInitialStatesRestriction ( manager - > boolean ( true ) ) ;
// Create a single location that will have all the edges.
uint64_t onlyLocation = automaton . addLocation ( storm : : jani : : Location ( " l " ) ) ;
automaton . addInitialLocation ( onlyLocation ) ;
for ( auto const & command : module . getCommands ( ) ) {
boost : : optional < storm : : expressions : : Expression > rateExpression ;
std : : vector < storm : : jani : : EdgeDestination > destinations ;
if ( this - > getModelType ( ) = = Program : : ModelType : : CTMC | | this - > getModelType ( ) = = Program : : ModelType : : CTMDP ) {
for ( auto const & update : command . getUpdates ( ) ) {
if ( rateExpression ) {
rateExpression = rateExpression . get ( ) + update . getLikelihoodExpression ( ) ;
} else {
rateExpression = update . getLikelihoodExpression ( ) ;
}
}
}
for ( auto const & update : command . getUpdates ( ) ) {
std : : vector < storm : : jani : : Assignment > assignments ;
for ( auto const & assignment : update . getAssignments ( ) ) {
assignments . push_back ( storm : : jani : : Assignment ( variableToVariableMap . at ( assignment . getVariable ( ) ) . get ( ) , assignment . getExpression ( ) ) ) ;
}
if ( rateExpression ) {
destinations . push_back ( storm : : jani : : EdgeDestination ( onlyLocation , manager - > integer ( 1 ) / rateExpression . get ( ) , assignments ) ) ;
} else {
destinations . push_back ( storm : : jani : : EdgeDestination ( onlyLocation , update . getLikelihoodExpression ( ) , assignments ) ) ;
}
}
automaton . addEdge ( storm : : jani : : Edge ( onlyLocation , janiModel . getActionIndex ( command . getActionName ( ) ) , rateExpression , command . getGuardExpression ( ) , destinations ) ) ;
}
janiModel . addAutomaton ( automaton ) ;
}
if ( this - > hasInitialConstruct ( ) ) {
janiModel . setInitialStatesRestriction ( this - > getInitialConstruct ( ) . getInitialStatesExpression ( ) ) ;
} else {
janiModel . setInitialStatesRestriction ( manager - > boolean ( true ) ) ;
}
// Set the standard system composition. This is possible, because we reject non-standard compositions anyway.
if ( this - > specifiesSystemComposition ( ) ) {
CompositionToJaniVisitor visitor ;
janiModel . setSystemComposition ( visitor . toJani ( this - > getSystemCompositionConstruct ( ) . getSystemComposition ( ) , janiModel ) ) ;
} else {
janiModel . setSystemComposition ( janiModel . getStandardSystemComposition ( ) ) ;
}
janiModel . finalize ( ) ;
return janiModel ;
}
void Program : : createMissingInitialValues ( ) {
for ( auto & variable : globalBooleanVariables ) {
if ( ! variable . hasInitialValue ( ) ) {
xxxxxxxxxx