@ -17,6 +17,9 @@ 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "storm/settings/SettingsManager.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "storm/settings/modules/CoreSettings.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "storm/utility/macros.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "storm/exceptions/NotSupportedException.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "storm/utility/counterexamples.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# include  "storm/utility/cli.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				
					@ -596,28 +599,6 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  cuts .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : unique_ptr < storm : : solver : : SmtSolver >  localSolver ( new  storm : : solver : : Z3SmtSolver ( program . getManager ( ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : expressions : : ExpressionManager  const &  localManager  =  program . getManager ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 / /  Create  a  context  and  register  all  variables  of  the  program  with  their  correct  type .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 z3 : : context  localContext ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 z3 : : solver  localSolver ( localContext ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 std : : map < std : : string ,  z3 : : expr >  solverVariables ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 for  ( auto  const &  booleanVariable  :  program . getGlobalBooleanVariables ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                     solverVariables . emplace ( booleanVariable . getName ( ) ,  localContext . bool_const ( booleanVariable . getName ( ) . c_str ( ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 for  ( auto  const &  integerVariable  :  program . getGlobalIntegerVariables ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                     solverVariables . emplace ( integerVariable . getName ( ) ,  localContext . int_const ( integerVariable . getName ( ) . c_str ( ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 for  ( auto  const &  module  :  program . getModules ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                     for  ( auto  const &  booleanVariable  :  module . getBooleanVariables ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                         solverVariables . emplace ( booleanVariable . getName ( ) ,  localContext . bool_const ( booleanVariable . getName ( ) . c_str ( ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                     }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                     for  ( auto  const &  integerVariable  :  module . getIntegerVariables ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                         solverVariables . emplace ( integerVariable . getName ( ) ,  localContext . int_const ( integerVariable . getName ( ) . c_str ( ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                     }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ /                 storm : : adapters : : Z3ExpressionAdapter  expressionAdapter ( localContext ,  false ,  solverVariables ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  Then  add  the  constraints  for  bounds  of  the  integer  variables . .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  const &  integerVariable  :  program . getGlobalIntegerVariables ( ) )  {  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				
					@ -1592,9 +1573,7 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  Returns  the  submdp  obtained  from  removing  all  choices  that  do  not  originate  from  the  specified  filterLabelSet .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  Also  returns  the  Labelsets  of  the  submdp  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             */  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            static  std : : pair < storm : : models : : sparse : : Mdp < T > ,  std : : vector < boost : : container : : flat_set < uint_fast64_t > > >  restrictMdpToLabelSet ( storm : : models : : sparse : : Mdp < T >  const &  mdp ,   std : : vector < boost : : container : : flat_set < uint_fast64_t > >  const &  labelSets ,  boost : : container : : flat_set < uint_fast64_t >  const &  filterLabelSet )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                STORM_LOG_THROW ( mdp . getNumberOfChoices ( )  = =  labelSets . size ( ) ,  storm : : exceptions : : InvalidArgumentException ,  " The given number of labels does not match the number of choices. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            static  std : : pair < storm : : models : : sparse : : Mdp < T > ,  std : : vector < boost : : container : : flat_set < uint_fast64_t > > >  restrictMdpToLabelSet ( storm : : models : : sparse : : Mdp < T >  const &  mdp ,   boost : : container : : flat_set < uint_fast64_t >  const &  filterLabelSet )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : vector < boost : : container : : flat_set < uint_fast64_t > >  resultLabelSet ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : SparseMatrixBuilder < T >  transitionMatrixBuilder ( 0 ,  mdp . getTransitionMatrix ( ) . getColumnCount ( ) ,  0 ,  true ,  true ,  mdp . getTransitionMatrix ( ) . getRowGroupCount ( ) ) ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -1604,7 +1583,8 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for ( uint_fast64_t  state  =  0 ;  state  <  mdp . getNumberOfStates ( ) ;  + + state )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bool  stateHasValidChoice  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( uint_fast64_t  choice  =  mdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state ] ;  choice  <  mdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state  +  1 ] ;  + + choice )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        bool  choiceValid  =  std : : includes ( filterLabelSet . begin ( ) ,  filterLabelSet . end ( ) ,  labelSets [ choice ] . begin ( ) ,  labelSets [ choice ] . end ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  const &  choiceLabelSet  =  mdp . getChoiceOrigins ( ) - > asPrismChoiceOrigins ( ) . getCommandSet ( choice ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        bool  choiceValid  =  std : : includes ( filterLabelSet . begin ( ) ,  filterLabelSet . end ( ) ,  choiceLabelSet . begin ( ) ,  choiceLabelSet . end ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        / /  If  the  choice  is  valid ,  copy  over  all  its  elements .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( choiceValid )  {  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -1615,7 +1595,7 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            for  ( auto  const &  entry  :  mdp . getTransitionMatrix ( ) . getRow ( choice ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                transitionMatrixBuilder . addNextValue ( currentRow ,  entry . getColumn ( ) ,  entry . getValue ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            resultLabelSet . push_back ( labelSets [ choice ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            resultLabelSet . push_back ( choiceLabelSet ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            + + currentRow ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -1636,8 +1616,6 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        public :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					          
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            /*!  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  Computes  the  minimal  command  set  that  is  needed  in  the  given  MDP  to  exceed  the  given  probability  threshold  for  satisfying  phi  until  psi .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -1645,9 +1623,8 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  @ param  mdp  The  MDP  in  which  to  find  the  minimal  command  set .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  @ param  phiStates  A  bit  vector  characterizing  all  phi  states  in  the  model .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  @ param  psiStates  A  bit  vector  characterizing  all  psi  states  in  the  model .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  @ param  probabilityThreshold  The  probability  value  that  must  be  achieved  or  exceeded .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  @ param  strictBound  A  flag  indicating  whether  the  probability  must  be  achieved  ( in  which  case  the  flag  must  be  set )  or  strictly  exceeded  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  ( if  the  flag  is  set  to  false ) .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  @ param  probabilityThreshold  The  threshold  that  is  to  be  achieved  or  exceeded .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  @ param  strictBound  Indicates  whether  the  threshold  needs  to  be  achieved  ( true )  or  exceeded  ( false ) .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  @ param  checkThresholdFeasible  If  set ,  it  is  verified  that  the  model  can  actually  achieve / exceed  the  given  probability  value .  If  this  check  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             *  is  made  and  fails ,  an  exception  is  thrown .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             */  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -1672,7 +1649,7 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  ( 0 )  Obtain  the  label  sets  for  each  choice .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  The  label  set  of  a  choice  corresponds  to  the  set  of  prism  commands  that  induce  the  choice .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                STORM_LOG_THROW ( mdp . hasChoiceOrigins ( ) ,  storm : : exceptions : : InvalidArgumentException ,  " Restriction to minimal command set is impossible for model without choice origns. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                STORM_LOG_THROW ( mdp . hasChoiceOrigins ( ) ,  storm : : exceptions : : InvalidArgumentException ,  " Restriction to minimal command set is impossible for model without choice origi ns. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                STORM_LOG_THROW ( mdp . getChoiceOrigins ( ) - > isPrismChoiceOrigins ( ) ,  storm : : exceptions : : InvalidArgumentException ,  " Restriction to command set is impossible for model without prism choice origins. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : sparse : : PrismChoiceOrigins  const &  choiceOrigins  =  mdp . getChoiceOrigins ( ) - > asPrismChoiceOrigins ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : vector < boost : : container : : flat_set < uint_fast64_t > >  labelSets ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -1698,8 +1675,8 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                RelevancyInformation  relevancyInformation  =  determineRelevantStatesAndLabels ( mdp ,  labelSets ,  phiStates ,  psiStates ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  ( 3 )  Create  a  solver .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : shared_ptr < storm : : expressions : : ExpressionManager >  manager ( new  storm : : expressions : : ExpressionManager ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : unique_ptr < storm : : solver : : SmtSolver >  solver ( new  storm : : solver : : Z3SmtSolver ( * manager ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : shared_ptr < storm : : expressions : : ExpressionManager >  manager  =  std : : make_shared <  storm : : expressions : : ExpressionManager > ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : unique_ptr < storm : : solver : : SmtSolver >  solver  =  std : : make_unique <  storm : : solver : : Z3SmtSolver > ( * manager ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  ( 4 )  Create  the  variables  for  the  relevant  commands .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                VariableInformation  variableInformation  =  createVariables ( manager ,  mdp ,  psiStates ,  relevancyInformation ,  includeReachabilityEncoding ) ;  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				
					@ -1747,7 +1724,7 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  Restrict  the  given  MDP  to  the  current  set  of  labels  and  compute  the  reachability  probability .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    modelCheckingClock  =  std : : chrono : : high_resolution_clock : : now ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    commandSet . insert ( relevancyInformation . knownLabels . begin ( ) ,  relevancyInformation . knownLabels . end ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  subMdpChoiceOrigins  =  restrictMdpToLabelSet ( mdp ,  labelSets ,  commandSet ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  subMdpChoiceOrigins  =  restrictMdpToLabelSet ( mdp ,  commandSet ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : models : : sparse : : Mdp < T >  const &  subMdp  =  subMdpChoiceOrigins . first ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : vector < boost : : container : : flat_set < uint_fast64_t > >  const &  subLabelSets  =  subMdpChoiceOrigins . second ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					   
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				
					@ -1811,25 +1788,94 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# endif  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            static  std : : shared_ptr < PrismHighLevelCounterexample >  computeCounterexample ( Environment  const &  env , storm : : prism : : Program  program ,  storm : : models : : sparse : : Mdp < T >  const &  mdp ,  std : : shared_ptr < storm : : logic : : Formula  const >  const &  formula )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            static  void  extendCommandSetLowerBound ( storm : : models : : sparse : : Mdp < T >  const &  mdp ,  boost : : container : : flat_set < uint_fast64_t > &  commandSet ,  storm : : storage : : BitVector  const &  phiStates ,  storm : : storage : : BitVector  const &  psiStates )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto  startTime  =  std : : chrono : : high_resolution_clock : : now ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  Create  sub - MDP  that  only  contains  the  choices  allowed  by  the  given  command  set .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : models : : sparse : : Mdp < T >  subMdp  =  restrictMdpToLabelSet ( mdp ,  commandSet ) . first ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  Then  determine  all  prob0E ( psi )  states  that  are  reachable  in  the  sub - MDP .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : BitVector  reachableProb0EStates  =  storm : : utility : : graph : : getReachableStates ( subMdp . getTransitionMatrix ( ) ,  subMdp . getInitialStates ( ) ,  phiStates ,  psiStates ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  Create  a  queue  of  reachable  prob0E ( psi )  states  so  we  can  check  which  commands  need  to  be  added  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  to  give  them  a  strategy  that  avoids  psi  states .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : queue < uint_fast64_t >  prob0EWorklist ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  const &  e  :  reachableProb0EStates )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    prob0EWorklist . push ( e ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  As  long  as  there  are  reachable  prob0E ( psi )  states ,  we  add  commands  so  they  can  stay  within  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  prob0E ( states ) .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                while  ( ! prob0EWorklist . empty ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    uint_fast64_t  state  =  prob0EWorklist . front ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    prob0EWorklist . pop ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  Now  iterate  over  the  original  choices  of  the  prob0E ( psi )  state  and  add  at  least  one .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bool  hasLabeledChoice  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    uint64_t  smallestCommandSetSize  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    uint64_t  smallestCommandChoice  =  mdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  Determine  the  choice  with  the  least  amount  of  commands  ( bad  heuristic ) .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( uint64_t  choice  =  smallestCommandChoice ;  choice  <  mdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) [ state  +  1 ] ;  + + choice )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        bool  onlyProb0ESuccessors  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        for  ( auto  const &  successorEntry  :  mdp . getTransitionMatrix ( ) . getRow ( choice ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            if  ( ! psiStates . get ( successorEntry . getColumn ( ) ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                onlyProb0ESuccessors  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                break ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( onlyProb0ESuccessors )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            auto  const &  labelSet  =  mdp . getChoiceOrigins ( ) - > asPrismChoiceOrigins ( ) . getCommandSet ( choice ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            hasLabeledChoice  | =  ! labelSet . empty ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            if  ( smallestCommandChoice  = =  0  | |  labelSet . size ( )  <  smallestCommandSetSize )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                smallestCommandSetSize  =  labelSet . size ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                smallestCommandChoice  =  choice ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( hasLabeledChoice )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        / /  Take  all  labels  of  the  selected  choice .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        auto  const &  labelSet  =  mdp . getChoiceOrigins ( ) - > asPrismChoiceOrigins ( ) . getCommandSet ( smallestCommandChoice ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        commandSet . insert ( labelSet . begin ( ) ,  labelSet . end ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        / /  Check  for  which  successor  states  choices  need  to  be  added  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        for  ( auto  const &  successorEntry  :  mdp . getTransitionMatrix ( ) . getRow ( smallestCommandChoice ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            if  ( ! storm : : utility : : isZero ( successorEntry . getValue ( ) ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                if  ( ! reachableProb0EStates . get ( successorEntry . getColumn ( ) ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    reachableProb0EStates . set ( successorEntry . getColumn ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    prob0EWorklist . push ( successorEntry . getColumn ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto  endTime  =  std : : chrono : : high_resolution_clock : : now ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  std : : endl  < <  " Extended command for lower bounded property to size  "  < <  commandSet . size ( )  < <  "  in  "  < <  std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( endTime  -  startTime ) . count ( )  < <  " ms. "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            static  std : : shared_ptr < PrismHighLevelCounterexample >  computeCounterexample ( Environment  const &  env ,  storm : : prism : : Program  program ,  storm : : models : : sparse : : Mdp < T >  const &  mdp ,  std : : shared_ptr < storm : : logic : : Formula  const >  const &  formula )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# ifdef STORM_HAVE_Z3  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  std : : endl  < <  " Generating minimal label counterexample for formula  "  < <  * formula  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                STORM_LOG_THROW ( formula - > isProbabilityOperatorFormula ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " Counterexample generation does not support this kind of formula. Expecting a probability operator as the outermost formula element. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : logic : : ProbabilityOperatorFormula  const &  probabilityOperator  =  formula - > asProbabilityOperatorFormula ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                STORM_LOG_THROW ( probabilityOperator . hasBound ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " Counterexample generation only supports bounded formulas. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : logic : : ComparisonType  comparisonType  =  probabilityOperator . getComparisonType ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                STORM_LOG_THROW ( comparisonType  = =  storm : : logic : : ComparisonType : : Less  | |  comparisonType  = =  storm : : logic : : ComparisonType : : LessEqual ,  storm : : exceptions : : InvalidPropertyException ,  " Counterexample generation only supports formulas with an upper probability bound. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                STORM_LOG_THROW ( probabilityOperator . getSubformula ( ) . isUntilFormula ( )  | |  probabilityOperator . getSubformula ( ) . isEventuallyFormula ( ) ,  storm : : exceptions : : InvalidPropertyException ,  " Path formula is required to be of the form 'phi U psi' for counterexample generation. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : logic : : ComparisonType  comparisonType  =  probabilityOperator . getComparisonType ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                bool  strictBound  =  comparisonType  = =  storm : : logic : : ComparisonType : : Less ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                double  threshold  =  probabilityOperator . getThresholdAs < double > ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                double  threshold  =  probabilityOperator . getThresholdAs < T > ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : BitVector  phiStates ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : BitVector  psiStates ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : modelchecker : : SparseMdpPrctlModelChecker < storm : : models : : sparse : : Mdp < T > >  modelchecker ( mdp ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( probabilityOperator . getSubformula ( ) . isUntilFormula ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    STORM_LOG_THROW ( ! storm : : logic : : isLowerBound ( comparisonType ) ,  storm : : exceptions : : NotSupportedException ,  " Lower bounds in counterexamples are only supported for eventually formulas. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : logic : : UntilFormula  const &  untilFormula  =  probabilityOperator . getSubformula ( ) . asUntilFormula ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : unique_ptr < storm : : modelchecker : : CheckResult >  leftResult  =  modelchecker . check ( env ,  untilFormula . getLeftSubformula ( ) ) ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -1851,12 +1897,43 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    psiStates  =  subQualitativeResult . getTruthValuesVector ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                bool  lowerBoundedFormula  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( storm : : logic : : isLowerBound ( comparisonType ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  If  the  formula  specifies  a  lower  bound ,  we  need  to  modify  the  phi  and  psi  states .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  More  concretely ,  we  convert  P ( min ) > lambda ( F  psi )  to  P ( max ) < ( 1 - lambda ) ( G  ! psi )  =  P ( max ) < ( 1 - lambda ) ( ! psi  U  prob0E ( psi ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  where  prob0E ( psi )  is  the  set  of  states  for  which  there  exists  a  strategy  \ sigma_0  that  avoids  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  reaching  psi  states  completely .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  This  means  that  from  all  states  in  prob0E ( psi )  we  need  to  include  labels  such  that  \ sigma_0  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  is  actually  included  in  the  resulting  MDP .  This  prevents  us  from  guaranteeing  the  minimality  of  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  the  returned  counterexample ,  so  we  warn  about  that .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    STORM_LOG_WARN ( " Generating counterexample for lower-bounded property. The resulting command set need not be minimal. " ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  Modify  bound  appropriately .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    comparisonType  =  storm : : logic : : invertPreserveStrictness ( comparisonType ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    threshold  =  storm : : utility : : one < T > ( )  -  threshold ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  Modify  the  phi  and  psi  states  appropriately .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : BitVector  statesWithProbability0E  =  storm : : utility : : graph : : performProb0E ( mdp . getTransitionMatrix ( ) ,  mdp . getTransitionMatrix ( ) . getRowGroupIndices ( ) ,  mdp . getBackwardTransitions ( ) ,  phiStates ,  psiStates ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    phiStates  =  ~ psiStates ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    psiStates  =  std : : move ( statesWithProbability0E ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  Remember  our  transformation  so  we  can  add  commands  to  guarantee  that  the  prob0E ( a )  states  actually  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    / /  have  a  strategy  that  voids  a  states .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    lowerBoundedFormula  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  Delegate  the  actual  computation  work  to  the  function  of  equal  name .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto  startTime  =  std : : chrono : : high_resolution_clock : : now ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto  commandSet  =  getMinimalCommandSet ( env ,  program ,  mdp ,  phiStates ,  psiStates ,  threshold ,  strictBound ,  true ,  storm : : settings : : getModule < storm : : settings : : modules : : CounterexampleGeneratorSettings > ( ) . isEncodeReachabilitySet ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                auto  endTime  =  std : : chrono : : high_resolution_clock : : now ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  std : : endl  < <  " Computed minimal command set of size  "  < <  commandSet . size ( )  < <  "  in  "  < <  std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( endTime  -  startTime ) . count ( )  < <  " ms. "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                / /  Extend  the  command  set  properly .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( lowerBoundedFormula )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    extendCommandSetLowerBound ( mdp ,  commandSet ,  phiStates ,  psiStates ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                return  std : : make_shared < PrismHighLevelCounterexample > ( program . restrictCommands ( commandSet ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					# else