@ -2,6 +2,7 @@
# include "storm/utility/macros.h"
# include "storm/utility/graph.h"
# include "storm/utility/constants.h"
# include "storm/models/sparse/Pomdp.h"
# include "storm/modelchecker/propositional/SparsePropositionalModelChecker.h"
# include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h"
@ -85,9 +86,69 @@ namespace storm {
template < typename ValueType >
storm : : storage : : BitVector QualitativeAnalysisOnGraphs < ValueType > : : analyseProb1Max ( storm : : logic : : UntilFormula const & formula ) const {
// We consider the states that satisfy the formula with prob.1 under arbitrary schedulers as goal states.
storm : : storage : : BitVector g oalStates = storm : : utility : : graph : : performProb1A ( pomdp . getTransitionMatrix ( ) , pomdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) , pomdp . getBackwardTransitions ( ) , checkPropositionalFormula ( formula . getLeftSubformula ( ) ) , checkPropositionalFormula ( formula . getRightSubformula ( ) ) ) ;
STORM_LOG_TRACE ( " Prob1A states according to MDP: " < < g oalStates) ;
storm : : storage : : BitVector newG oalStates = storm : : utility : : graph : : performProb1A ( pomdp . getTransitionMatrix ( ) , pomdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) , pomdp . getBackwardTransitions ( ) , checkPropositionalFormula ( formula . getLeftSubformula ( ) ) , checkPropositionalFormula ( formula . getRightSubformula ( ) ) ) ;
STORM_LOG_TRACE ( " Prob1A states according to MDP: " < < newG oalStates) ;
// Now find a set of observations such that there is a memoryless scheduler inducing prob. 1 for each state whose observation is in the set.
storm : : storage : : BitVector potentialGoalStates = storm : : utility : : graph : : performProb1E ( pomdp . getTransitionMatrix ( ) , pomdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) , pomdp . getBackwardTransitions ( ) , checkPropositionalFormula ( formula . getLeftSubformula ( ) ) , newGoalStates ) ;
storm : : storage : : BitVector notGoalStates = ~ potentialGoalStates ;
storm : : storage : : BitVector potentialGoalObservations ( pomdp . getNrObservations ( ) , true ) ;
for ( uint64_t observation = 0 ; observation < pomdp . getNrObservations ( ) ; + + observation ) {
for ( uint64_t state : notGoalStates ) {
potentialGoalObservations . set ( pomdp . getObservation ( state ) , false ) ;
}
}
std : : vector < std : : vector < uint64_t > > statesPerObservation ( pomdp . getNrObservations ( ) , std : : vector < uint64_t > ( ) ) ;
for ( uint64_t state : potentialGoalStates ) {
statesPerObservation [ pomdp . getObservation ( state ) ] . push_back ( state ) ;
}
storm : : storage : : BitVector goalStates ( pomdp . getNumberOfStates ( ) ) ;
while ( goalStates ! = newGoalStates ) {
goalStates = storm : : utility : : graph : : performProb1A ( pomdp . getTransitionMatrix ( ) , pomdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) , pomdp . getBackwardTransitions ( ) , checkPropositionalFormula ( formula . getLeftSubformula ( ) ) , newGoalStates ) ;
newGoalStates = goalStates ;
STORM_LOG_TRACE ( " Prob1A states according to MDP: " < < newGoalStates ) ;
for ( uint64_t observation : potentialGoalObservations ) {
uint64_t actsForObservation = pomdp . getTransitionMatrix ( ) . getRowGroupSize ( statesPerObservation [ observation ] [ 0 ] ) ;
// Search whether we find an action that works for this observation.
for ( uint64_t act = 0 ; act < actsForObservation ; act + + ) {
bool isGoalAction = true ; // Assume that this works, then check whether we find a violation.
for ( uint64_t state : statesPerObservation [ observation ] ) {
if ( newGoalStates . get ( state ) ) {
// A state is only a goal state if all actions work,
// or if all states with the same observation are goal states (and then, it does not matter which action is a goal action).
// Notice that this can mean that we wrongly conclude that some action is okay even if this is not the correct action (but then some other action exists which is okay for all states).
continue ;
}
uint64_t row = pomdp . getNondeterministicChoiceIndices ( ) [ state ] + act ;
// Check whether all actions lead with a positive probabilty to a goal, and with zero probability to another (non-goal) state.
bool hasGoalEntry = false ;
for ( auto const & entry : pomdp . getTransitionMatrix ( ) . getRow ( row ) ) {
assert ( ! storm : : utility : : isZero ( entry . getValue ( ) ) ) ;
if ( newGoalStates . get ( entry . getColumn ( ) ) ) {
hasGoalEntry = true ;
}
else if ( pomdp . getObservation ( entry . getColumn ( ) ) ! = observation ) {
isGoalAction = false ;
break ;
}
}
if ( ! isGoalAction | | ! hasGoalEntry ) {
// Action is definitiely not a goal action, no need to check further states.
isGoalAction = false ;
break ;
}
}
if ( isGoalAction ) {
for ( uint64_t state : statesPerObservation [ observation ] ) {
newGoalStates . set ( state ) ;
}
// No need to check other actions.
break ;
}
}
}
}
// Notice that the goal states are not observable, i.e., the observations may not be sufficient to decide whether we are in a goal state.
return goalStates ;
}