@ -15,6 +15,10 @@
# include "src/storage/dd/Bdd.h"
# include "src/adapters/AddExpressionAdapter.h"
# include "src/models/symbolic/Dtmc.h"
# include "src/models/symbolic/Ctmc.h"
# include "src/models/symbolic/Mdp.h"
# include "src/utility/macros.h"
# include "src/utility/jani.h"
# include "src/exceptions/InvalidArgumentException.h"
@ -412,8 +416,6 @@ namespace storm {
return result ;
}
static int c = 0 ;
// A class that is responsible for performing the actual composition.
template < storm : : dd : : DdType Type , typename ValueType >
class AutomatonComposer : public storm : : jani : : CompositionVisitor {
@ -704,7 +706,18 @@ namespace storm {
}
template < storm : : dd : : DdType Type , typename ValueType >
storm : : dd : : Add < Type , ValueType > createGlobalTransitionRelation ( storm : : jani : : Model const & model , AutomatonDd < Type , ValueType > const & automatonDd , CompositionVariables < Type , ValueType > const & variables ) {
struct SystemDd {
SystemDd ( storm : : dd : : Add < Type , ValueType > const & transitionsDd , storm : : dd : : Add < Type , ValueType > const & stateActionDd , uint64_t numberOfNondeterminismVariables = 0 ) : transitionsDd ( transitionsDd ) , stateActionDd ( stateActionDd ) , numberOfNondeterminismVariables ( numberOfNondeterminismVariables ) {
// Intentionally left empty.
}
storm : : dd : : Add < Type , ValueType > transitionsDd ;
storm : : dd : : Add < Type , ValueType > stateActionDd ;
uint64_t numberOfNondeterminismVariables ;
} ;
template < storm : : dd : : DdType Type , typename ValueType >
SystemDd < Type , ValueType > buildSystemDd ( storm : : jani : : Model const & model , AutomatonDd < Type , ValueType > const & automatonDd , CompositionVariables < Type , ValueType > const & variables ) {
// If the model is an MDP, we need to encode the nondeterminism using additional variables.
if ( model . getModelType ( ) = = storm : : jani : : ModelType : : MDP ) {
// Determine how many nondeterminism variables we need.
@ -735,6 +748,8 @@ namespace storm {
result + = edgesForAction * encodeAction < Type , ValueType > ( actionIndexToVariableIndex . at ( action . first ) , actionVariables , variables ) ;
}
return SystemDd < Type , ValueType > ( result , result . sumAbstract ( variables . columnMetaVariables ) , numberOfNondeterminismVariables ) ;
} else if ( model . getModelType ( ) = = storm : : jani : : ModelType : : DTMC | | model . getModelType ( ) = = storm : : jani : : ModelType : : CTMC ) {
// Simply add all actions, but make sure to include the missing global variable identities.
storm : : dd : : Add < Type , ValueType > result = variables . manager - > template getAddZero < ValueType > ( ) ;
@ -743,25 +758,95 @@ namespace storm {
result + = edge . transitionsDd * computeMissingGlobalVariableIdentities ( edge , variables ) ;
}
}
return result ;
return SystemDd < Type , ValueType > ( result , result . sumAbstract ( variables . columnMetaVariables ) ) ;
}
STORM_LOG_THROW ( false , storm : : exceptions : : InvalidArgumentException , " Illegal model type. " ) ;
}
template < storm : : dd : : DdType Type , typename ValueType >
struct ModelComponents {
storm : : dd : : Bdd < Type > reachableStates ;
storm : : dd : : Bdd < Type > initialStates ;
storm : : dd : : Add < Type , ValueType > transitionMatrix ;
std : : unordered_map < std : : string , storm : : models : : symbolic : : StandardRewardModel < Type , ValueType > > rewardModels ;
} ;
template < storm : : dd : : DdType Type , typename ValueType >
std : : shared_ptr < storm : : models : : symbolic : : Model < Type , ValueType > > createModel ( storm : : jani : : ModelType const & modelType , CompositionVariables < Type , ValueType > const & variables , ModelComponents < Type , ValueType > const & modelComponents ) {
if ( modelType = = storm : : jani : : ModelType : : DTMC ) {
return std : : shared_ptr < storm : : models : : symbolic : : Model < Type , ValueType > > ( new storm : : models : : symbolic : : Dtmc < Type , ValueType > ( variables . manager , modelComponents . reachableStates , modelComponents . initialStates , modelComponents . transitionMatrix , variables . rowMetaVariables , variables . rowExpressionAdapter , variables . columnMetaVariables , variables . columnExpressionAdapter , variables . rowColumnMetaVariablePairs , std : : map < std : : string , storm : : expressions : : Expression > ( ) , modelComponents . rewardModels ) ) ;
} else if ( modelType = = storm : : jani : : ModelType : : CTMC ) {
return std : : shared_ptr < storm : : models : : symbolic : : Model < Type , ValueType > > ( new storm : : models : : symbolic : : Ctmc < Type , ValueType > ( variables . manager , modelComponents . reachableStates , modelComponents . initialStates , modelComponents . transitionMatrix , variables . rowMetaVariables , variables . rowExpressionAdapter , variables . columnMetaVariables , variables . columnExpressionAdapter , variables . rowColumnMetaVariablePairs , std : : map < std : : string , storm : : expressions : : Expression > ( ) , modelComponents . rewardModels ) ) ;
} else if ( modelType = = storm : : jani : : ModelType : : MDP ) {
return std : : shared_ptr < storm : : models : : symbolic : : Model < Type , ValueType > > ( new storm : : models : : symbolic : : Mdp < Type , ValueType > ( variables . manager , modelComponents . reachableStates , modelComponents . initialStates , modelComponents . transitionMatrix , variables . rowMetaVariables , variables . rowExpressionAdapter , variables . columnMetaVariables , variables . columnExpressionAdapter , variables . rowColumnMetaVariablePairs , variables . allNondeterminismVariables , std : : map < std : : string , storm : : expressions : : Expression > ( ) , modelComponents . rewardModels ) ) ;
} else {
STORM_LOG_THROW ( false , storm : : exceptions : : InvalidArgumentException , " Illegal model type. " ) ;
STORM_LOG_THROW ( false , storm : : exceptions : : InvalidArgumentException , " Invalid model type. " ) ;
}
return storm : : dd : : Add < Type , ValueType > ( ) ;
}
template < storm : : dd : : DdType Type , typename ValueType >
void postprocessSystemDd ( storm : : jani : : Model const & model , SystemDd < Type , ValueType > & system , CompositionVariables < Type , ValueType > const & variables , typename DdJaniModelBuilder < Type , ValueType > : : Options const & options ) {
// For DTMCs, we normalize each row to 1 (to account for non-determinism).
if ( model . getModelType ( ) = = storm : : jani : : ModelType : : DTMC ) {
system . transitionsDd = system . transitionsDd / system . stateActionDd ;
}
// If we were asked to treat some states as terminal states, we cut away their transitions now.
if ( options . terminalStates | | options . negatedTerminalStates ) {
std : : map < storm : : expressions : : Variable , storm : : expressions : : Expression > constantsSubstitution = model . getConstantsSubstitution ( ) ;
storm : : dd : : Bdd < Type > terminalStatesBdd = variables . manager - > getBddZero ( ) ;
if ( options . terminalStates ) {
storm : : expressions : : Expression terminalExpression = options . terminalStates . get ( ) . substitute ( constantsSubstitution ) ;
STORM_LOG_TRACE ( " Making the states satisfying " < < terminalExpression < < " terminal. " ) ;
terminalStatesBdd = variables . rowExpressionAdapter - > translateExpression ( terminalExpression ) . toBdd ( ) ;
}
if ( options . negatedTerminalStates ) {
storm : : expressions : : Expression negatedTerminalExpression = options . negatedTerminalStates . get ( ) . substitute ( constantsSubstitution ) ;
STORM_LOG_TRACE ( " Making the states *not* satisfying " < < negatedTerminalExpression < < " terminal. " ) ;
terminalStatesBdd | = ! variables . rowExpressionAdapter - > translateExpression ( negatedTerminalExpression ) . toBdd ( ) ;
}
system . transitionMatrix * = ( ! terminalStatesBdd ) . template toAdd < ValueType > ( ) ;
}
}
template < storm : : dd : : DdType Type , typename ValueType >
storm : : dd : : Bdd < Type > computeInitial ( storm : : jani : : Model const & model , CompositionVariables < Type , ValueType > const & variables ) {
storm : : dd : : Bdd < Type > initialStates = variables . rowExpressionAdapter - > translateExpression ( generationInfo . program . getInitialConstruct ( ) . getInitialStatesExpression ( ) ) . toBdd ( ) ;
for ( auto const & metaVariable : generationInfo . rowMetaVariables ) {
initialStates & = generationInfo . manager - > getRange ( metaVariable ) ;
}
return initialStates ;
}
template < storm : : dd : : DdType Type , typename ValueType >
std : : shared_ptr < storm : : models : : symbolic : : Model < Type , ValueType > > DdJaniModelBuilder < Type , ValueType > : : translate ( ) {
// Create all necessary variables.
CompositionVariableCreator < Type , ValueType > variableCreator ( * this - > model ) ;
CompositionVariables < Type , ValueType > variables = variableCreator . create ( ) ;
// Compose the automata to a single automaton.
AutomatonComposer < Type , ValueType > composer ( * this - > model , variables ) ;
AutomatonDd < Type , ValueType > system = composer . compose ( ) ;
AutomatonDd < Type , ValueType > globalAutomaton = composer . compose ( ) ;
// Combine the edges of the single automaton to the full system DD.
SystemDd < Type , ValueType > system = buildSystemDd ( * this - > model , globalAutomaton , variables ) ;
// Postprocess the system. This modifies the systemDd in place.
postprocessSystemDd ( * this - > model , system , variables , options ) ;
storm : : dd : : Add < Type , ValueType > transitions = createGlobalTransitionRelation ( * this - > model , system , variables ) ;
ModelComponents < Type , ValueType > modelComponents ;
// FIXME
return nullptr ;
return createModel ( this - > model - > getModelType ( ) , variables , modelComponents ) ;
}
template class DdJaniModelBuilder < storm : : dd : : DdType : : CUDD , double > ;