@ -22,61 +22,54 @@ namespace storm {
}
template < storm : : dd : : DdType Type , typename ValueType >
storm : : dd : : Bdd < Type > pickPivotState ( storm : : dd : : Bdd < Type > const & initialStates , storm : : dd : : Bdd < Type > const & transitionsMin , storm : : dd : : Bdd < Type > const & transitionsMax , std : : set < storm : : expressions : : Variable > const & rowVariables , std : : set < storm : : expressions : : Variable > const & columnVariables , storm : : dd : : Bdd < Type > const & pivotStates , boost : : optional < QuantitativeResultMinMax < Type , ValueType > > const & quantitativeResult = boost : : none ) {
storm : : dd : : Bdd < Type > pickPivotStateWithMinimalDistance ( storm : : dd : : Bdd < Type > const & initialStates , storm : : dd : : Bdd < Type > const & transitionsMin , storm : : dd : : Bdd < Type > const & transitionsMax , std : : set < storm : : expressions : : Variable > const & rowVariables , std : : set < storm : : expressions : : Variable > const & columnVariables , storm : : dd : : Bdd < Type > const & pivotStates , boost : : optional < QuantitativeResultMinMax < Type , ValueType > > const & quantitativeResult = boost : : none ) {
// Perform a BFS and pick the first pivot state we encounter.
storm : : dd : : Bdd < Type > pivotState ;
// Set up used variables.
storm : : dd : : Bdd < Type > frontierMin = initialStates ;
storm : : dd : : Bdd < Type > frontierMax = initialStates ;
storm : : dd : : Bdd < Type > frontierMinPivotStates = frontierMin & & pivotStates ;
storm : : dd : : Bdd < Type > frontierMaxPivotStates = frontierMinPivotStates ;
storm : : dd : : Bdd < Type > frontierPivotStates = frontierMin & & pivotStates ;
// Check whether we have pivot states on the very first level.
uint64_t level = 0 ;
bool foundPivotState = ! frontierMin PivotStates . isZero ( ) ;
bool foundPivotState = ! frontierPivotStates . isZero ( ) ;
if ( foundPivotState ) {
pivotState = frontierMinPivotStates . existsAbstractRepresentative ( rowVariables ) ;
STORM_LOG_TRACE ( " Picked pivot state from " < < frontierMinPivotStates . getNonZeroCount ( ) < < " candidates on level " < < level < < " , " < < pivotStates . getNonZeroCount ( ) < < " candidates in total. " ) ;
STORM_LOG_TRACE ( " Picked pivot state from " < < frontierPivotStates . getNonZeroCount ( ) < < " candidates on level " < < level < < " , " < < pivotStates . getNonZeroCount ( ) < < " candidates in total. " ) ;
return frontierPivotStates . existsAbstractRepresentative ( rowVariables ) ;
} else {
// Otherwise, we perform a simulatenous BFS in the sense that we make one step in both the min and max
// transitions and check for pivot states we encounter.
while ( ! foundPivotState ) {
frontierMin = frontierMin . relationalProduct ( transitionsMin , rowVariables , columnVariables ) ;
frontierMax = frontierMax . relationalProduct ( transitionsMax , rowVariables , columnVariables ) ;
frontierMinPivotStates = frontierMin & & pivotStates ;
frontierMaxPivotStates = frontierMax & & pivotStates ;
if ( ! frontierMinPivotStates . isZero ( ) ) {
if ( quantitativeResult ) {
storm : : dd : : Add < Type , ValueType > frontierPivotStatesAdd = frontierMinPivotStates . template toAdd < ValueType > ( ) ;
storm : : dd : : Add < Type , ValueType > diff = frontierPivotStatesAdd * quantitativeResult . get ( ) . max . values - frontierPivotStatesAdd * quantitativeResult . get ( ) . min . values ;
pivotState = diff . maxAbstractRepresentative ( rowVariables ) ;
STORM_LOG_TRACE ( " Picked pivot state with difference " < < diff . getMax ( ) < < " from " < < ( frontierMinPivotStates . getNonZeroCount ( ) + frontierMaxPivotStates . getNonZeroCount ( ) ) < < " candidates on level " < < level < < " , " < < pivotStates . getNonZeroCount ( ) < < " candidates in total. " ) ;
foundPivotState = true ;
} else {
pivotState = frontierMinPivotStates . existsAbstractRepresentative ( rowVariables ) ;
STORM_LOG_TRACE ( " Picked pivot state from " < < ( frontierMinPivotStates . getNonZeroCount ( ) + frontierMaxPivotStates . getNonZeroCount ( ) ) < < " candidates on level " < < level < < " , " < < pivotStates . getNonZeroCount ( ) < < " candidates in total. " ) ;
foundPivotState = true ;
}
} else if ( ! frontierMaxPivotStates . isZero ( ) ) {
frontierPivotStates = ( frontierMin & & pivotStates ) | | ( frontierMax & & pivotStates ) ;
if ( ! frontierPivotStates . isZero ( ) ) {
if ( quantitativeResult ) {
storm : : dd : : Add < Type , ValueType > frontierPivotStatesAdd = frontierMax PivotStates . template toAdd < ValueType > ( ) ;
storm : : dd : : Add < Type , ValueType > frontierPivotStatesAdd = frontierPivotStates . template toAdd < ValueType > ( ) ;
storm : : dd : : Add < Type , ValueType > diff = frontierPivotStatesAdd * quantitativeResult . get ( ) . max . values - frontierPivotStatesAdd * quantitativeResult . get ( ) . min . values ;
pivotState = diff . maxAbstractRepresentative ( rowVariables ) ;
STORM_LOG_TRACE ( " Picked pivot state with difference " < < diff . getMax ( ) < < " from " < < ( frontierMinPivotStates . getNonZeroCount ( ) + frontierMaxPivotStates . getNonZeroCount ( ) ) < < " candidates on level " < < level < < " , " < < pivotStates . getNonZeroCount ( ) < < " candidates in total. " ) ;
foundPivotState = true ;
STORM_LOG_TRACE ( " Picked pivot state with difference " < < diff . getMax ( ) < < " from " < < frontierPivotStates . getNonZeroCount ( ) < < " candidates on level " < < level < < " , " < < pivotStates . getNonZeroCount ( ) < < " candidates in total. " ) ;
return diff . maxAbstractRepresentative ( rowVariables ) ;
} else {
pivotState = frontierMinPivotStates . existsAbstractRepresentative ( rowVariables ) ;
STORM_LOG_TRACE ( " Picked pivot state from " < < ( frontierMinPivotStates . getNonZeroCount ( ) + frontierMaxPivotStates . getNonZeroCount ( ) ) < < " candidates on level " < < level < < " , " < < pivotStates . getNonZeroCount ( ) < < " candidates in total. " ) ;
foundPivotState = true ;
STORM_LOG_TRACE ( " Picked pivot state from " < < frontierPivotStates . getNonZeroCount ( ) < < " candidates on level " < < level < < " , " < < pivotStates . getNonZeroCount ( ) < < " candidates in total. " ) ;
return frontierPivotStates . existsAbstractRepresentative ( rowVariables ) ;
}
}
+ + level ;
}
}
return pivotState ;
STORM_LOG_ASSERT ( false , " This point must not be reached, because then no pivot state could be found. " ) ;
return storm : : dd : : Bdd < Type > ( ) ;
}
template < storm : : dd : : DdType Type , typename ValueType >
void MenuGameRefiner < Type , ValueType > : : refine ( storm : : dd : : Bdd < Type > const & pivotState , storm : : dd : : Bdd < Type > const & player1Choice , storm : : dd : : Bdd < Type > const & lowerChoice , storm : : dd : : Bdd < Type > const & upperChoice ) const {
storm : : expressions : : Expression MenuGameRefiner < Type , ValueType > : : derivePredicateFromDifferingChoices ( storm : : dd : : Bdd < Type > const & pivotState , storm : : dd : : Bdd < Type > const & player1Choice , storm : : dd : : Bdd < Type > const & lowerChoice , storm : : dd : : Bdd < Type > const & upperChoice ) const {
// Prepare result.
storm : : expressions : : Expression newPredicate ;
// Get abstraction informatin for easier access.
AbstractionInformation < Type > const & abstractionInformation = abstractor . get ( ) . getAbstractionInformation ( ) ;
// Decode the index of the command chosen by player 1.
@ -92,9 +85,8 @@ namespace storm {
// command (that is the player 1 choice).
if ( buttomStateSuccessor ) {
STORM_LOG_TRACE ( " One of the successors is a bottom state, taking a guard as a new predicate. " ) ;
storm : : expressions : : Expression newPredicate = abstractor . get ( ) . getGuard ( player1Index ) ;
STORM_LOG_DEBUG ( " Derived new predicate: " < < newPredicate ) ;
this - > performRefinement ( { newPredicate } ) ;
newPredicate = abstractor . get ( ) . getGuard ( player1Index ) ;
STORM_LOG_DEBUG ( " Derived new predicate (based on guard): " < < newPredicate ) ;
} else {
STORM_LOG_TRACE ( " No bottom state successor. Deriving a new predicate using weakest precondition. " ) ;
@ -104,7 +96,6 @@ namespace storm {
STORM_LOG_ASSERT ( lowerChoiceUpdateToSuccessorMapping . size ( ) = = upperChoiceUpdateToSuccessorMapping . size ( ) , " Mismatching sizes after decode ( " < < lowerChoiceUpdateToSuccessorMapping . size ( ) < < " vs. " < < upperChoiceUpdateToSuccessorMapping . size ( ) < < " ). " ) ;
// Now go through the mappings and find points of deviation. Currently, we take the first deviation.
storm : : expressions : : Expression newPredicate ;
auto lowerIt = lowerChoiceUpdateToSuccessorMapping . begin ( ) ;
auto lowerIte = lowerChoiceUpdateToSuccessorMapping . end ( ) ;
auto upperIt = upperChoiceUpdateToSuccessorMapping . begin ( ) ;
@ -123,43 +114,36 @@ namespace storm {
}
}
STORM_LOG_ASSERT ( newPredicate . isInitialized ( ) , " Could not derive new predicate as there is no deviation. " ) ;
STORM_LOG_DEBUG ( " Derived new predicate: " < < newPredicate ) ;
this - > performRefinement ( { newPredicate } ) ;
STORM_LOG_DEBUG ( " Derived new predicate (based on weakest-precondition): " < < newPredicate ) ;
}
STORM_LOG_TRACE ( " Current set of predicates: " ) ;
for ( auto const & predicate : abstractionInformation . getPredicates ( ) ) {
STORM_LOG_TRACE ( predicate ) ;
}
return newPredicate ;
}
template < storm : : dd : : DdType Type >
struct PivotStateResult {
storm : : dd : : Bdd < Type > reachableTransitionsMin ;
storm : : dd : : Bdd < Type > reachableTransitionsMax ;
storm : : dd : : Bdd < Type > pivotStates ;
} ;
template < storm : : dd : : DdType Type , typename ValueType >
bool MenuGameRefiner < Type , ValueType > : : refine ( storm : : abstraction : : MenuGame < Type , ValueType > const & game , storm : : dd : : Bdd < Type > const & transitionMatrixBdd , QualitativeResultMinMax < Type > const & qualitativeResult ) const {
STORM_LOG_TRACE ( " Trying refinement after qualitative check. " ) ;
// Get all relevant strategies.
storm : : dd : : Bdd < Type > minPlayer1Strategy = qualitativeResult . prob0Min . getPlayer1Strategy ( ) ;
storm : : dd : : Bdd < Type > minPlayer2Strategy = qualitativeResult . prob0Min . getPlayer2Strategy ( ) ;
storm : : dd : : Bdd < Type > maxPlayer1Strategy = qualitativeResult . prob1Max . getPlayer1Strategy ( ) ;
storm : : dd : : Bdd < Type > maxPlayer2Strategy = qualitativeResult . prob1Max . getPlayer2Strategy ( ) ;
PivotStateResult < Type > computePivotStates ( storm : : abstraction : : MenuGame < Type , ValueType > const & game , storm : : dd : : Bdd < Type > const & transitionMatrixBdd , storm : : dd : : Bdd < Type > const & minPlayer1Strategy , storm : : dd : : Bdd < Type > const & minPlayer2Strategy , storm : : dd : : Bdd < Type > const & maxPlayer1Strategy , storm : : dd : : Bdd < Type > const & maxPlayer2Strategy ) {
// Redirect all player 1 choices of the min strategy to that of the max strategy if this leads to a player 2
// state that is also a prob 0 state.
minPlayer1Strategy = ( maxPlayer1Strategy & & qualitativeResult . prob0Min . getPlayer2States ( ) ) . existsAbstract ( game . getPlayer1Variables ( ) ) . ite ( maxPlayer1Strategy , minPlayer1Strategy ) ;
PivotStateResult < Type > result ;
// Build the fragment of transitions that is reachable by either the min or the max strategies.
storm : : dd : : Bdd < Type > reachableTransitions = transitionMatrixBdd & & ( minPlayer1Strategy | | maxPlayer1Strategy ) & & minPlayer2Strategy & & maxPlayer2Strategy ;
reachableTransitions = reachableTransitions . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
storm : : dd : : Bdd < Type > reachableTransitionsMin = ( transitionMatrixBdd & & minPlayer1Strategy & & minPlayer2Strategy ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
storm : : dd : : Bdd < Type > reachableTransitionsMax = ( transitionMatrixBdd & & maxPlayer1Strategy & & maxPlayer2Strategy ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
result . reachableTransitionsMin = ( transitionMatrixBdd & & minPlayer1Strategy & & minPlayer2Strategy ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
result . reachableTransitionsMax = ( transitionMatrixBdd & & maxPlayer1Strategy & & maxPlayer2Strategy ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
// Start with all reachable states as potential pivot states.
storm : : dd : : Bdd < Type > pivotStates = storm : : utility : : dd : : computeReachableStates ( game . getInitialStates ( ) , reachableTransitionsMin , game . getRowVariables ( ) , game . getColumnVariables ( ) ) | |
storm : : utility : : dd : : computeReachableStates ( game . getInitialStates ( ) , reachableTransitionsMax , game . getRowVariables ( ) , game . getColumnVariables ( ) ) ;
//storm::dd::Bdd<Type> pivotStates = storm::utility::dd::computeReachableStates(game.getInitialStates(), reachableTransitions, game.getRowVariables(), game.getColumnVariables());
result . pivotStates = storm : : utility : : dd : : computeReachableStates ( game . getInitialStates ( ) , result . reachableTransitionsMin , game . getRowVariables ( ) , game . getColumnVariables ( ) ) | |
storm : : utility : : dd : : computeReachableStates ( game . getInitialStates ( ) , result . reachableTransitionsMax , game . getRowVariables ( ) , game . getColumnVariables ( ) ) ;
// Then constrain these states by the requirement that for either the lower or upper player 1 choice the player 2 choices must be different and
// that the difference is not because of a missing strategy in either case.
@ -170,22 +154,13 @@ namespace storm {
constraint & = minPlayer2Strategy . exclusiveOr ( maxPlayer2Strategy ) ;
// Then restrict the pivot states by requiring existing and different player 2 choices.
// pivotStates &= ((minPlayer1Strategy || maxPlayer1Strategy) && constraint).existsAbstract(game.getNondeterminismVariables());
pivotStates & = ( ( minPlayer1Strategy & & maxPlayer1Strategy ) & & constraint ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
// We can only refine in case we have a reachable player 1 state with a player 2 successor (under either
// player 1's min or max strategy) such that from this player 2 state, both prob0 min and prob1 max define
// strategies and they differ. Hence, it is possible that we arrive at a point where no suitable pivot state
// is found. In this case, we abort the qualitative refinement here.
if ( pivotStates . isZero ( ) ) {
return false ;
}
STORM_LOG_ASSERT ( ! pivotStates . isZero ( ) , " Unable to proceed without pivot state candidates. " ) ;
// Now that we have the pivot state candidates, we need to pick one.
storm : : dd : : Bdd < Type > pivotState = pickPivotState < Type , ValueType > ( game . getInitialStates ( ) , reachableTransitionsMin , reachableTransitionsMax , game . getRowVariables ( ) , game . getColumnVariables ( ) , pivotStates ) ;
result . pivotStates & = ( ( minPlayer1Strategy & & maxPlayer1Strategy ) & & constraint ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
return result ;
}
template < storm : : dd : : DdType Type , typename ValueType >
storm : : expressions : : Expression MenuGameRefiner < Type , ValueType > : : derivePredicateFromPivotState ( storm : : abstraction : : MenuGame < Type , ValueType > const & game , storm : : dd : : Bdd < Type > const & pivotState , storm : : dd : : Bdd < Type > const & minPlayer1Strategy , storm : : dd : : Bdd < Type > const & minPlayer2Strategy , storm : : dd : : Bdd < Type > const & maxPlayer1Strategy , storm : : dd : : Bdd < Type > const & maxPlayer2Strategy ) const {
// Compute the lower and the upper choice for the pivot state.
std : : set < storm : : expressions : : Variable > variablesToAbstract = game . getNondeterminismVariables ( ) ;
variablesToAbstract . insert ( game . getRowVariables ( ) . begin ( ) , game . getRowVariables ( ) . end ( ) ) ;
@ -198,10 +173,10 @@ namespace storm {
STORM_LOG_TRACE ( " Refining based on lower choice. " ) ;
auto refinementStart = std : : chrono : : high_resolution_clock : : now ( ) ;
this - > refine ( pivotState , ( pivotState & & minPlayer1Strategy ) . existsAbstract ( game . getRowVariables ( ) ) , lowerChoice1 , lowerChoice2 ) ;
storm : : expressions : : Expression newPredicate = derivePredicateFromDifferingChoices ( pivotState , ( pivotState & & minPlayer1Strategy ) . existsAbstract ( game . getRowVariables ( ) ) , lowerChoice1 , lowerChoice2 ) ;
auto refinementEnd = std : : chrono : : high_resolution_clock : : now ( ) ;
STORM_LOG_TRACE ( " Refinement completed in " < < std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( refinementEnd - refinementStart ) . count ( ) < < " ms. " ) ;
return tru e ;
return newPredica te;
} else {
storm : : dd : : Bdd < Type > upperChoice = pivotState & & game . getExtendedTransitionMatrix ( ) . toBdd ( ) & & maxPlayer1Strategy ;
storm : : dd : : Bdd < Type > upperChoice1 = ( upperChoice & & minPlayer2Strategy ) . existsAbstract ( variablesToAbstract ) ;
@ -211,15 +186,48 @@ namespace storm {
if ( upperChoicesDifferent ) {
STORM_LOG_TRACE ( " Refining based on upper choice. " ) ;
auto refinementStart = std : : chrono : : high_resolution_clock : : now ( ) ;
this - > refine ( pivotState , ( pivotState & & maxPlayer1Strategy ) . existsAbstract ( game . getRowVariables ( ) ) , upperChoice1 , upperChoice2 ) ;
storm : : expressions : : Expression newPredicate = derivePredicateFromDifferingChoices ( pivotState , ( pivotState & & maxPlayer1Strategy ) . existsAbstract ( game . getRowVariables ( ) ) , upperChoice1 , upperChoice2 ) ;
auto refinementEnd = std : : chrono : : high_resolution_clock : : now ( ) ;
STORM_LOG_TRACE ( " Refinement completed in " < < std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( refinementEnd - refinementStart ) . count ( ) < < " ms. " ) ;
return tru e ;
return newPredica te;
} else {
STORM_LOG_ASSERT ( false , " Did not find choices from which to derive predicates. " ) ;
}
}
return false ;
}
template < storm : : dd : : DdType Type , typename ValueType >
bool MenuGameRefiner < Type , ValueType > : : refine ( storm : : abstraction : : MenuGame < Type , ValueType > const & game , storm : : dd : : Bdd < Type > const & transitionMatrixBdd , QualitativeResultMinMax < Type > const & qualitativeResult ) const {
STORM_LOG_TRACE ( " Trying refinement after qualitative check. " ) ;
// Get all relevant strategies.
storm : : dd : : Bdd < Type > minPlayer1Strategy = qualitativeResult . prob0Min . getPlayer1Strategy ( ) ;
storm : : dd : : Bdd < Type > minPlayer2Strategy = qualitativeResult . prob0Min . getPlayer2Strategy ( ) ;
storm : : dd : : Bdd < Type > maxPlayer1Strategy = qualitativeResult . prob1Max . getPlayer1Strategy ( ) ;
storm : : dd : : Bdd < Type > maxPlayer2Strategy = qualitativeResult . prob1Max . getPlayer2Strategy ( ) ;
// Redirect all player 1 choices of the min strategy to that of the max strategy if this leads to a player 2
// state that is also a prob 0 state.
minPlayer1Strategy = ( maxPlayer1Strategy & & qualitativeResult . prob0Min . getPlayer2States ( ) ) . existsAbstract ( game . getPlayer1Variables ( ) ) . ite ( maxPlayer1Strategy , minPlayer1Strategy ) ;
// Compute all reached pivot states.
PivotStateResult < Type > pivotStateResult = computePivotStates ( game , transitionMatrixBdd , minPlayer1Strategy , minPlayer2Strategy , maxPlayer1Strategy , maxPlayer2Strategy ) ;
// We can only refine in case we have a reachable player 1 state with a player 2 successor (under either
// player 1's min or max strategy) such that from this player 2 state, both prob0 min and prob1 max define
// strategies and they differ. Hence, it is possible that we arrive at a point where no suitable pivot state
// is found. In this case, we abort the qualitative refinement here.
if ( pivotStateResult . pivotStates . isZero ( ) ) {
return false ;
}
STORM_LOG_ASSERT ( ! pivotStateResult . pivotStates . isZero ( ) , " Unable to proceed without pivot state candidates. " ) ;
// Now that we have the pivot state candidates, we need to pick one.
storm : : dd : : Bdd < Type > pivotState = pickPivotStateWithMinimalDistance < Type , ValueType > ( game . getInitialStates ( ) , pivotStateResult . reachableTransitionsMin , pivotStateResult . reachableTransitionsMax , game . getRowVariables ( ) , game . getColumnVariables ( ) , pivotStateResult . pivotStates ) ;
// Derive predicate based on the selected pivot state.
storm : : expressions : : Expression newPredicate = derivePredicateFromPivotState ( game , pivotState , minPlayer1Strategy , minPlayer2Strategy , maxPlayer1Strategy , maxPlayer2Strategy ) ;
performRefinement ( { newPredicate } ) ;
return true ;
}
template < storm : : dd : : DdType Type , typename ValueType >
@ -231,75 +239,21 @@ namespace storm {
storm : : dd : : Bdd < Type > maxPlayer1Strategy = quantitativeResult . max . player1Strategy ;
storm : : dd : : Bdd < Type > maxPlayer2Strategy = quantitativeResult . max . player2Strategy ;
// TODO: fix min strategies to take the max strategies if possible.
// Build the fragment of transitions that is reachable by both the min and the max strategies.
storm : : dd : : Bdd < Type > reachableTransitions = transitionMatrixBdd & & ( minPlayer1Strategy | | maxPlayer1Strategy ) & & minPlayer2Strategy & & maxPlayer2Strategy ;
reachableTransitions = reachableTransitions . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
storm : : dd : : Bdd < Type > reachableTransitionsMin = ( transitionMatrixBdd & & minPlayer1Strategy & & minPlayer2Strategy ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
storm : : dd : : Bdd < Type > reachableTransitionsMax = ( transitionMatrixBdd & & maxPlayer1Strategy & & maxPlayer2Strategy ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
// Start with all reachable states as potential pivot states.
// storm::dd::Bdd<Type> pivotStates = storm::utility::dd::computeReachableStates(game.getInitialStates(), reachableTransitions, game.getRowVariables(), game.getColumnVariables());
storm : : dd : : Bdd < Type > pivotStates = storm : : utility : : dd : : computeReachableStates ( game . getInitialStates ( ) , reachableTransitionsMin , game . getRowVariables ( ) , game . getColumnVariables ( ) ) | |
storm : : utility : : dd : : computeReachableStates ( game . getInitialStates ( ) , reachableTransitionsMax , game . getRowVariables ( ) , game . getColumnVariables ( ) ) ;
// Compute all reached pivot states.
PivotStateResult < Type > pivotStateResult = computePivotStates ( game , transitionMatrixBdd , minPlayer1Strategy , minPlayer2Strategy , maxPlayer1Strategy , maxPlayer2Strategy ) ;
// TODO: required?
// Require the pivot state to be a state with a lower bound strictly smaller than the upper bound.
pivotStates & = quantitativeResult . min . values . less ( quantitativeResult . max . values ) ;
STORM_LOG_ASSERT ( ! pivotStates . isZero ( ) , " Unable to refine without pivot state candidates. " ) ;
// Then constrain these states by the requirement that for either the lower or upper player 1 choice the player 2 choices must be different and
// that the difference is not because of a missing strategy in either case.
// Start with constructing the player 2 states that have a (min) and a (max) strategy.
// TODO: necessary?
storm : : dd : : Bdd < Type > constraint = minPlayer2Strategy . existsAbstract ( game . getPlayer2Variables ( ) ) & & maxPlayer2Strategy . existsAbstract ( game . getPlayer2Variables ( ) ) ;
// Now construct all player 2 choices that actually exist and differ in the min and max case.
constraint & = minPlayer2Strategy . exclusiveOr ( maxPlayer2Strategy ) ;
// Then restrict the pivot states by requiring existing and different player 2 choices.
// pivotStates &= ((minPlayer1Strategy || maxPlayer1Strategy) && constraint).existsAbstract(game.getNondeterminismVariables());
pivotStates & = ( ( minPlayer1Strategy & & maxPlayer1Strategy ) & & constraint ) . existsAbstract ( game . getNondeterminismVariables ( ) ) ;
STORM_LOG_ASSERT ( ! pivotStates . isZero ( ) , " Unable to refine without pivot state candidates. " ) ;
pivotStateResult . pivotStates & = quantitativeResult . min . values . less ( quantitativeResult . max . values ) ;
STORM_LOG_ASSERT ( ! pivotStateResult . pivotStates . isZero ( ) , " Unable to refine without pivot state candidates. " ) ;
// Now that we have the pivot state candidates, we need to pick one.
storm : : dd : : Bdd < Type > pivotState = pickPivotState < Type , ValueType > ( game . getInitialStates ( ) , reachableTransitionsMin , reachableTransitionsMax , game . getRowVariables ( ) , game . getColumnVariables ( ) , pivotStates , quantitativeResult ) ;
// Compute the lower and the upper choice for the pivot state.
std : : set < storm : : expressions : : Variable > variablesToAbstract = game . getNondeterminismVariables ( ) ;
variablesToAbstract . insert ( game . getRowVariables ( ) . begin ( ) , game . getRowVariables ( ) . end ( ) ) ;
storm : : dd : : Bdd < Type > lowerChoice = pivotState & & game . getExtendedTransitionMatrix ( ) . toBdd ( ) & & minPlayer1Strategy ;
storm : : dd : : Bdd < Type > lowerChoice1 = ( lowerChoice & & minPlayer2Strategy ) . existsAbstract ( variablesToAbstract ) ;
storm : : dd : : Bdd < Type > lowerChoice2 = ( lowerChoice & & maxPlayer2Strategy ) . existsAbstract ( variablesToAbstract ) ;
bool lowerChoicesDifferent = ! lowerChoice1 . exclusiveOr ( lowerChoice2 ) . isZero ( ) ;
if ( lowerChoicesDifferent ) {
STORM_LOG_TRACE ( " Refining based on lower choice. " ) ;
auto refinementStart = std : : chrono : : high_resolution_clock : : now ( ) ;
this - > refine ( pivotState , ( pivotState & & minPlayer1Strategy ) . existsAbstract ( game . getRowVariables ( ) ) , lowerChoice1 , lowerChoice2 ) ;
auto refinementEnd = std : : chrono : : high_resolution_clock : : now ( ) ;
STORM_LOG_TRACE ( " Refinement completed in " < < std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( refinementEnd - refinementStart ) . count ( ) < < " ms. " ) ;
} else {
storm : : dd : : Bdd < Type > upperChoice = pivotState & & game . getExtendedTransitionMatrix ( ) . toBdd ( ) & & maxPlayer1Strategy ;
storm : : dd : : Bdd < Type > upperChoice1 = ( upperChoice & & minPlayer2Strategy ) . existsAbstract ( variablesToAbstract ) ;
storm : : dd : : Bdd < Type > upperChoice2 = ( upperChoice & & maxPlayer2Strategy ) . existsAbstract ( variablesToAbstract ) ;
bool upperChoicesDifferent = ! upperChoice1 . exclusiveOr ( upperChoice2 ) . isZero ( ) ;
if ( upperChoicesDifferent ) {
STORM_LOG_TRACE ( " Refining based on upper choice. " ) ;
auto refinementStart = std : : chrono : : high_resolution_clock : : now ( ) ;
this - > refine ( pivotState , ( pivotState & & maxPlayer1Strategy ) . existsAbstract ( game . getRowVariables ( ) ) , upperChoice1 , upperChoice2 ) ;
auto refinementEnd = std : : chrono : : high_resolution_clock : : now ( ) ;
STORM_LOG_TRACE ( " Refinement completed in " < < std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( refinementEnd - refinementStart ) . count ( ) < < " ms. " ) ;
} else {
STORM_LOG_ASSERT ( false , " Did not find choices from which to derive predicates. " ) ;
}
}
storm : : dd : : Bdd < Type > pivotState = pickPivotStateWithMinimalDistance < Type , ValueType > ( game . getInitialStates ( ) , pivotStateResult . reachableTransitionsMin , pivotStateResult . reachableTransitionsMax , game . getRowVariables ( ) , game . getColumnVariables ( ) , pivotStateResult . pivotStates ) ;
// Derive predicate based on the selected pivot state.
storm : : expressions : : Expression newPredicate = derivePredicateFromPivotState ( game , pivotState , minPlayer1Strategy , minPlayer2Strategy , maxPlayer1Strategy , maxPlayer2Strategy ) ;
performRefinement ( { newPredicate } ) ;
return true ;
}