@ -35,7 +35,7 @@ namespace storm { 
			
		
	
		
			
				
					                template < typename  ValueType >  
			
		
	
		
			
				
					                ValueType  computeMaxRelDiff ( std : : vector < ValueType >  const &  allOldValues ,  std : : vector < ValueType >  const &  allNewValues ,  storm : : storage : : BitVector  const &  relevantValues )  {  
			
		
	
		
			
				
					                    ValueType  result  =  storm : : utility : : zero < ValueType > ( ) ;  
			
		
	
		
			
				
					                    for  ( auto  const &  i  :  relevantValues )  {  
			
		
	
		
			
				
					                    for  ( auto  i  :  relevantValues )  {  
			
		
	
		
			
				
					                        STORM_LOG_ASSERT ( ! storm : : utility : : isZero ( allNewValues [ i ] )  | |  storm : : utility : : isZero ( allOldValues [ i ] ) ,  " Unexpected entry in iteration vector. " ) ;  
			
		
	
		
			
				
					                        if  ( ! storm : : utility : : isZero ( allNewValues [ i ] ) )  {  
			
		
	
		
			
				
					                            result  =  storm : : utility : : max < ValueType > ( result ,  storm : : utility : : abs < ValueType > ( allNewValues [ i ]  -  allOldValues [ i ] )  /  allNewValues [ i ] ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -48,7 +48,7 @@ namespace storm { 
			
		
	
		
			
				
					                ValueType  computeMaxRelDiff ( std : : vector < ValueType >  const &  allOldValues ,  std : : vector < ValueType >  const &  allNewValues )  {  
			
		
	
		
			
				
					                    ValueType  result  =  storm : : utility : : zero < ValueType > ( ) ;  
			
		
	
		
			
				
					                    for  ( uint64_t  i  =  0 ;  i  <  allOldValues . size ( ) ;  + + i )  {  
			
		
	
		
			
				
					                        STORM_LOG_ASSERT  ( ! storm : : utility : : isZero ( allNewValues [ i ] )  | |  storm : : utility : : isZero ( allOldValues [ i ] ) ,  " Unexpected entry in iteration vector. " ) ;  
			
		
	
		
			
				
					                        STORM_LOG_WARN_COND  ( ! storm : : utility : : isZero ( allNewValues [ i ] )  | |  storm : : utility : : isZero ( allOldValues [ i ] ) ,  " Unexpected entry in iteration vector. " ) ;  
			
		
	
		
			
				
					                        if  ( ! storm : : utility : : isZero ( allNewValues [ i ] ) )  {  
			
		
	
		
			
				
					                            result  =  storm : : utility : : max < ValueType > ( result ,  storm : : utility : : abs < ValueType > ( allNewValues [ i ]  -  allOldValues [ i ] )  /  allNewValues [ i ] ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -57,14 +57,9 @@ namespace storm { 
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					     
			
		
	
		
			
				
					                template < typename  ValueType >  
			
		
	
		
			
				
					                ValueType  updateIterationPrecision ( storm : : Environment  const &  env ,  std : : vector < ValueType > const &  currentX ,  std : : vector < ValueType >  const &  newX ,  bool  const &  relative ,  boost : : optional < storm : : storage : : BitVector >  const &  relevantValues )  {  
			
		
	
		
			
				
					                ValueType  updateIterationPrecision ( storm : : Environment  const &  env ,  ValueType  const &  diff )  {  
			
		
	
		
			
				
					                    auto  factor  =  storm : : utility : : convertNumber < ValueType > ( env . solver ( ) . ovi ( ) . getPrecisionUpdateFactor ( ) ) ;  
			
		
	
		
			
				
					                    bool  useRelevant  =  relevantValues . is_initialized ( )  & &  env . solver ( ) . ovi ( ) . useRelevantValuesForPrecisionUpdate ( ) ;  
			
		
	
		
			
				
					                    if  ( relative )  {  
			
		
	
		
			
				
					                        return  ( useRelevant  ?  computeMaxRelDiff ( newX ,  currentX ,  relevantValues . get ( ) )  :  computeMaxRelDiff ( newX ,  currentX ) )  *  factor ;  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                        return  ( useRelevant  ?  computeMaxAbsDiff ( newX ,  currentX ,  relevantValues . get ( ) )  :  computeMaxAbsDiff ( newX ,  currentX ) )  *  factor ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    return  factor  *  diff ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					     
			
		
	
		
			
				
					                template < typename  ValueType >  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -78,7 +73,7 @@ namespace storm { 
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                UpperBound Iterator< ValueType > : : UpperBound Iterator( storm : : storage : : SparseMatrix < ValueType >  const &  matrix )  {  
			
		
	
		
			
				
					                Iterati onHelpe r < ValueType > : : Iterati onHelpe r ( storm : : storage : : SparseMatrix < ValueType >  const &  matrix )  {  
			
		
	
		
			
				
					                    STORM_LOG_THROW ( static_cast < uint64_t > ( std : : numeric_limits < uint32_t > : : max ( ) )  >  matrix . getRowCount ( )  +  1 ,  storm : : exceptions : : NotSupportedException ,  " Matrix dimensions too large. " ) ;  
			
		
	
		
			
				
					                    STORM_LOG_THROW ( static_cast < uint64_t > ( std : : numeric_limits < uint32_t > : : max ( ) )  >  matrix . getEntryCount ( ) ,  storm : : exceptions : : NotSupportedException ,  " Matrix dimensions too large. " ) ;  
			
		
	
		
			
				
					                    matrixValues . reserve ( matrix . getNonzeroEntryCount ( ) ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -97,23 +92,120 @@ namespace storm { 
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                ValueType  IterationHelper < ValueType > : : singleIterationWithDiff ( std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  computeRelativeDiff )  {  
			
		
	
		
			
				
					                    return  singleIterationWithDiffInternal < false ,  storm : : solver : : OptimizationDirection : : Minimize > ( x ,  b ,  computeRelativeDiff ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                ValueType  IterationHelper < ValueType > : : singleIterationWithDiff ( storm : : solver : : OptimizationDirection  const &  dir ,  std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  computeRelativeDiff )  {  
			
		
	
		
			
				
					                    if  ( minimize ( dir ) )  {  
			
		
	
		
			
				
					                        return  singleIterationWithDiffInternal < true ,  storm : : solver : : OptimizationDirection : : Minimize > ( x ,  b ,  computeRelativeDiff ) ;  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                        return  singleIterationWithDiffInternal < true ,  storm : : solver : : OptimizationDirection : : Maximize > ( x ,  b ,  computeRelativeDiff ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                template < bool  HasRowGroups ,  storm : : solver : : OptimizationDirection  Dir >  
			
		
	
		
			
				
					                ValueType  IterationHelper < ValueType > : : singleIterationWithDiffInternal ( std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  computeRelativeDiff )  {  
			
		
	
		
			
				
					                    STORM_LOG_ASSERT ( x . size ( )  >  0 ,  " Empty equation system not expected. " ) ;  
			
		
	
		
			
				
					                    ValueType  diff  =  storm : : utility : : zero < ValueType > ( ) ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    IndexType  i  =  x . size ( ) ;  
			
		
	
		
			
				
					                    while  ( i  >  0 )  {  
			
		
	
		
			
				
					                        - - i ;  
			
		
	
		
			
				
					                        ValueType  newXi  =  HasRowGroups  ?  multiplyRowGroup < Dir > ( i ,  b ,  x )  :  multiplyRow ( i ,  b [ i ] ,  x ) ;  
			
		
	
		
			
				
					                        ValueType &  oldXi  =  x [ i ] ;  
			
		
	
		
			
				
					                        if  ( computeRelativeDiff )  {  
			
		
	
		
			
				
					                            if  ( storm : : utility : : isZero ( newXi ) )  {  
			
		
	
		
			
				
					                                if  ( storm : : utility : : isZero ( oldXi ) )  {  
			
		
	
		
			
				
					                                    // this operation has no effect:
  
			
		
	
		
			
				
					                                    // diff = std::max(diff, storm::utility::zero<ValueType>());
  
			
		
	
		
			
				
					                                }  else  {  
			
		
	
		
			
				
					                                    diff  =  std : : max ( diff ,  storm : : utility : : one < ValueType > ( ) ) ;  
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                            }  else  {  
			
		
	
		
			
				
					                                diff  =  std : : max ( diff ,  storm : : utility : : abs < ValueType > ( ( newXi  -  oldXi )  /  newXi ) ) ;  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  else  {  
			
		
	
		
			
				
					                            diff  =  std : : max ( diff ,  storm : : utility : : abs < ValueType > ( newXi  -  oldXi ) ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        oldXi  =  std : : move ( newXi ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    return  diff ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                uint64_t  IterationHelper < ValueType > : : repeatedIterate ( storm : : solver : : OptimizationDirection  const &  dir ,  std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  ValueType  precision ,  bool  relative )  {  
			
		
	
		
			
				
					                    if  ( minimize ( dir ) )  {  
			
		
	
		
			
				
					                        return  repeatedIterateInternal < true ,  storm : : solver : : OptimizationDirection : : Minimize > ( x ,  b ,  precision ,  relative ) ;  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                        return  repeatedIterateInternal < true ,  storm : : solver : : OptimizationDirection : : Maximize > ( x ,  b ,  precision ,  relative ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                typename  UpperBoundIterator < ValueType > : : IterateResult  UpperBoundIterator < ValueType > : : iterate ( std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  takeMinOfOldAndNew )  {  
			
		
	
		
			
				
					                    return  iterateInternal < false ,  storm : : solver : : OptimizationDirection : : Minimize > ( x ,  b ,  takeMinOfOldAndNew ) ;  
			
		
	
		
			
				
					                uint64_t  IterationHelper < ValueType > : : repeatedIterate ( std : : vector < ValueType > &  x ,  const  std : : vector < ValueType > &  b ,  ValueType  precision ,  bool  relative )  {  
			
		
	
		
			
				
					                    return  repeatedIterateInternal < false ,  storm : : solver : : OptimizationDirection : : Minimize > ( x ,  b ,  precision ,  relative ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                template < bool  HasRowGroups ,  storm : : solver : : OptimizationDirection  Dir >  
			
		
	
		
			
				
					                uint64_t  IterationHelper < ValueType > : : repeatedIterateInternal ( std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  ValueType  precision ,  bool  relative )  {  
			
		
	
		
			
				
					                    // Do a backwards gauss-seidel style iteration
  
			
		
	
		
			
				
					                    bool  convergence  =  true ;  
			
		
	
		
			
				
					                    IndexType  i  =  x . size ( ) ;  
			
		
	
		
			
				
					                    while  ( i  >  0 )  {  
			
		
	
		
			
				
					                        - - i ;  
			
		
	
		
			
				
					                        ValueType  newXi  =  HasRowGroups  ?  multiplyRowGroup < Dir > ( i ,  b ,  x )  :  multiplyRow ( i ,  b [ i ] ,  x ) ;  
			
		
	
		
			
				
					                        ValueType &  oldXi  =  x [ i ] ;  
			
		
	
		
			
				
					                        // Check if we converged
  
			
		
	
		
			
				
					                        if  ( relative )  {  
			
		
	
		
			
				
					                            if  ( storm : : utility : : isZero ( oldXi ) )  {  
			
		
	
		
			
				
					                                if  ( ! storm : : utility : : isZero ( newXi ) )  {  
			
		
	
		
			
				
					                                    convergence  =  false ;  
			
		
	
		
			
				
					                                    break ;  
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                            }  else  if  ( storm : : utility : : abs < ValueType > ( ( newXi  -  oldXi )  /  oldXi )  >  precision )  {  
			
		
	
		
			
				
					                                convergence  =  false ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  else  {  
			
		
	
		
			
				
					                            if  ( storm : : utility : : abs < ValueType > ( ( newXi  -  oldXi ) )  >  precision )  {  
			
		
	
		
			
				
					                                convergence  =  false ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    if  ( ! convergence )  {  
			
		
	
		
			
				
					                        // we now know that we did not converge. We still need to set the remaining values
  
			
		
	
		
			
				
					                        while  ( i  >  0 )  {  
			
		
	
		
			
				
					                            - - i ;  
			
		
	
		
			
				
					                            x [ i ]  =  HasRowGroups  ?  multiplyRowGroup < Dir > ( i ,  b ,  x )  :  multiplyRow ( i ,  b [ i ] ,  x ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    return  convergence ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                typename  UpperBoundIterator < ValueType > : : IterateResult  UpperBoundIterator < ValueType > : : iterate ( storm : : solver : : OptimizationDirection  const &  dir ,  std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  takeMinOfOldAndNew )  {  
			
		
	
		
			
				
					                typename  Iterati onHelpe r < ValueType > : : IterateResult  Iterati onHelpe r < ValueType > : : iterateUpper  ( storm : : solver : : OptimizationDirection  const &  dir ,  std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  takeMinOfOldAndNew )  {  
			
		
	
		
			
				
					                    if  ( minimize ( dir ) )  {  
			
		
	
		
			
				
					                        return  iterateInternal < true ,  storm : : solver : : OptimizationDirection : : Minimize > ( x ,  b ,  takeMinOfOldAndNew ) ;  
			
		
	
		
			
				
					                        return  iterateUpper Internal < true ,  storm : : solver : : OptimizationDirection : : Minimize > ( x ,  b ,  takeMinOfOldAndNew ) ;  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                        return  iterateInternal < true ,  storm : : solver : : OptimizationDirection : : Maximize > ( x ,  b ,  takeMinOfOldAndNew ) ;  
			
		
	
		
			
				
					                        return  iterateUpper Internal < true ,  storm : : solver : : OptimizationDirection : : Maximize > ( x ,  b ,  takeMinOfOldAndNew ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                typename  IterationHelper < ValueType > : : IterateResult  IterationHelper < ValueType > : : iterateUpper ( std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  takeMinOfOldAndNew )  {  
			
		
	
		
			
				
					                    return  iterateUpperInternal < false ,  storm : : solver : : OptimizationDirection : : Minimize > ( x ,  b ,  takeMinOfOldAndNew ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                template < bool  HasRowGroups ,  storm : : solver : : OptimizationDirection  Dir >  
			
		
	
		
			
				
					                typename  UpperBoundIterator < ValueType > : : IterateResult  UpperBoundIterator < ValueType > : : iterateInternal ( std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  takeMinOfOldAndNew )  {  
			
		
	
		
			
				
					                typename  Iterati onHelpe r < ValueType > : : IterateResult  Iterati onHelpe r < ValueType > : : iterateUpper Internal ( std : : vector < ValueType > &  x ,  std : : vector < ValueType >  const &  b ,  bool  takeMinOfOldAndNew )  {  
			
		
	
		
			
				
					                    // For each row compare the new upper bound candidate with the old one
  
			
		
	
		
			
				
					                    bool  newUpperBoundAlwaysHigherEqual  =  true ;  
			
		
	
		
			
				
					                    bool  newUpperBoundAlwaysLowerEqual  =  true ;  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -150,7 +242,7 @@ namespace storm { 
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                ValueType  UpperBound Iterator< ValueType > : : multiplyRow ( IndexType  const &  rowIndex ,  ValueType  const &  bi ,  std : : vector < ValueType >  const &  x )  {  
			
		
	
		
			
				
					                ValueType  Iterati onHelpe r < ValueType > : : multiplyRow ( IndexType  const &  rowIndex ,  ValueType  const &  bi ,  std : : vector < ValueType >  const &  x )  {  
			
		
	
		
			
				
					                    assert ( rowIndex  <  rowIndications . size ( ) ) ;  
			
		
	
		
			
				
					                    ValueType  xRes  =  bi ;  
			
		
	
		
			
				
					                     
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -165,7 +257,7 @@ namespace storm { 
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                template  < typename  ValueType >  
			
		
	
		
			
				
					                template < storm : : solver : : OptimizationDirection  Dir >  
			
		
	
		
			
				
					                ValueType  UpperBound Iterator< ValueType > : : multiplyRowGroup ( IndexType  const &  rowGroupIndex ,  std : : vector < ValueType >  const &  b ,  std : : vector < ValueType >  const &  x )  {  
			
		
	
		
			
				
					                ValueType  Iterati onHelpe r < ValueType > : : multiplyRowGroup ( IndexType  const &  rowGroupIndex ,  std : : vector < ValueType >  const &  b ,  std : : vector < ValueType >  const &  x )  {  
			
		
	
		
			
				
					                    STORM_LOG_ASSERT ( rowGroupIndices  ! =  nullptr ,  " No row group indices available. " ) ;  
			
		
	
		
			
				
					                    auto  row  =  ( * rowGroupIndices ) [ rowGroupIndex ] ;  
			
		
	
		
			
				
					                    auto  const &  groupEnd  =  ( * rowGroupIndices ) [ rowGroupIndex  +  1 ] ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -180,24 +272,21 @@ namespace storm { 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					             
			
		
	
		
			
				
					            template < typename  ValueType >  
			
		
	
		
			
				
					            OptimisticValueIterationHelper < ValueType > : : OptimisticValueIterationHelper ( storm : : storage : : SparseMatrix < ValueType >  const &  matrix )  :  upperBoundIterato r( matrix )  {  
			
		
	
		
			
				
					            OptimisticValueIterationHelper < ValueType > : : OptimisticValueIterationHelper ( storm : : storage : : SparseMatrix < ValueType >  const &  matrix )  :  iterationHelpe r( matrix )  {  
			
		
	
		
			
				
					                    // Intentionally left empty.
  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					            template < typename  ValueType >  
			
		
	
		
			
				
					                std : : pair < SolverStatus ,  uint64_t >  OptimisticValueIterationHelper < ValueType > : : solveEquationsOptimisticValueIteration  ( Environment  const &  env ,  std : : vector < ValueType > *  lowerX ,  std : : vector < ValueType > *  upperX ,  std : : vector < ValueType > *  auxVector ,  std : : vector < ValueType > const &  b ,  ValueIterationCallBackType  const &  valueIterationCallback ,  SingleIterationCallBackType  const &  singleIterationCallback ,  bool  relative ,  ValueType  precision ,  uint64_t  maxOverallIterations ,  boost : : optional < storm : : solver : : OptimizationDirection >  dir ,  boost : : optional < storm : : storage : : BitVector > relevantValues )  {  
			
		
	
		
			
				
					                std : : pair < SolverStatus ,  uint64_t >  OptimisticValueIterationHelper < ValueType > : : solveEquations ( Environment  const &  env ,  std : : vector < ValueType > *  lowerX ,  std : : vector < ValueType > *  upperX ,  std : : vector < ValueType >  const &  b ,  bool  relative ,  ValueType  precision ,  uint64_t  maxOverallIterations ,  boost : : optional < storm : : solver : : OptimizationDirection >  dir ,  boost : : optional < storm : : storage : : BitVector >  const & relevantValues )  {  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( lowerX - > size ( )  = =  upperX - > size ( ) ,  " Dimension missmatch. " ) ;  
			
		
	
		
			
				
					                STORM_LOG_ASSERT ( lowerX - > size ( )  = =  auxVector - > size ( ) ,  " Dimension missmatch. " ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // As we will shuffle pointers around, let's store the original positions here.
  
			
		
	
		
			
				
					                std : : vector < ValueType > *  initLowerX  =  lowerX ;  
			
		
	
		
			
				
					                std : : vector < ValueType > *  initUpperX  =  upperX ;  
			
		
	
		
			
				
					                std : : vector < ValueType > *  initAux  =  auxVector ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                uint64_t  overallIterations  =  0 ;  
			
		
	
		
			
				
					                uint64_t  lastValueIterationIterations  =  0 ;  
			
		
	
		
			
				
					                uint64_t  currentVerificationIterations  =  0 ;  
			
		
	
		
			
				
					                uint64_t  valueIterationInvocations  =  0 ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Get some parameters for the algorithm
  
			
		
	
		
			
				
					                // 2
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -215,16 +304,10 @@ namespace storm { 
			
		
	
		
			
				
					                SolverStatus  status  =  SolverStatus : : InProgress ;  
			
		
	
		
			
				
					     
			
		
	
		
			
				
					                while  ( status  = =  SolverStatus : : InProgress  & &  overallIterations  <  maxOverallIterations )  {  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    // Perform value iteration until convergence
  
			
		
	
		
			
				
					                    + + valueIterationInvocations ;  
			
		
	
		
			
				
					                    auto  result  =  valueIterationCallback ( lowerX ,  auxVector ,  iterationPrecision ,  relative ,  overallIterations ,  maxOverallIterations ) ;  
			
		
	
		
			
				
					                    lastValueIterationIterations  =  result . first ;  
			
		
	
		
			
				
					                    overallIterations  + =  result . first ;  
			
		
	
		
			
				
					                    lastValueIterationIterations  =  dir  ?  iterationHelper . repeatedIterate ( dir . get ( ) ,  * lowerX ,  b ,  precision ,  relative )  :  iterationHelper . repeatedIterate ( * lowerX ,  b ,  precision ,  relative ) ;  
			
		
	
		
			
				
					                    overallIterations  + =  lastValueIterationIterations ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    if  ( result . second  ! =  SolverStatus : : Converged )  {  
			
		
	
		
			
				
					                        status  =  result . second ;  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                    bool  intervalIterationNeeded  =  false ;  
			
		
	
		
			
				
					                    currentVerificationIterations  =  0 ;  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -241,17 +324,18 @@ namespace storm { 
			
		
	
		
			
				
					                        // Perform value iteration stepwise for lower bound and guessed upper bound
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        // Upper bound iteration
  
			
		
	
		
			
				
					                             auto  upperBoundIterResult  =  dir  ?  upperBoundIterato r. iterate ( dir . get ( ) ,  * upperX ,  b ,  ! noTerminationGuarantee )  :  upperBoundIterato r. iterate ( * upperX ,  b ,  ! noTerminationGuarantee ) ;  
			
		
	
		
			
				
					                        auto  upperBoundIterResult  =  dir  ?  iterationHelpe r. iterateUpper  ( dir . get ( ) ,  * upperX ,  b ,  ! noTerminationGuarantee )  :  iterationHelpe r. iterateUpper  ( * upperX ,  b ,  ! noTerminationGuarantee ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                             if  ( upperBoundIterResult  = =  oviinternal : : UpperBound Iterator< ValueType > : : IterateResult : : AlwaysHigherOrEqual )  {  
			
		
	
		
			
				
					                        if  ( upperBoundIterResult  = =  oviinternal : : Iterati onHelpe r < ValueType > : : IterateResult : : AlwaysHigherOrEqual )  {  
			
		
	
		
			
				
					                            // All values moved up (and did not stay the same)
  
			
		
	
		
			
				
					                            // That means the guess for an upper bound is actually a lower bound
  
			
		
	
		
			
				
					                                iterationPrecision  =  oviinternal : : updateIterationPrecision ( env ,  * auxVector ,  * upperX ,  relative ,  relevantValues ) ;  
			
		
	
		
			
				
					                            auto  diff  =  dir  ?  iterationHelper . singleIterationWithDiff ( dir . get ( ) ,  * upperX ,  b ,  relative )  :  iterationHelper . singleIterationWithDiff ( * upperX ,  b ,  relative ) ;  
			
		
	
		
			
				
					                            iterationPrecision  =  oviinternal : : updateIterationPrecision ( env ,  diff ) ;  
			
		
	
		
			
				
					                            // We assume to have a single fixed point. We can thus safely set the new lower bound, to the wrongly guessed upper bound
  
			
		
	
		
			
				
					                            // Set lowerX to the upper bound candidate
  
			
		
	
		
			
				
					                            std : : swap ( lowerX ,  upperX ) ;  
			
		
	
		
			
				
					                            break ;  
			
		
	
		
			
				
					                             }  else  if  ( upperBoundIterResult  = =  oviinternal : : UpperBound Iterator< ValueType > : : IterateResult : : AlwaysLowerOrEqual )  {  
			
		
	
		
			
				
					                        }  else  if  ( upperBoundIterResult  = =  oviinternal : : Iterati onHelpe r < ValueType > : : IterateResult : : AlwaysLowerOrEqual )  {  
			
		
	
		
			
				
					                            // All values moved down (and stayed not the same)
  
			
		
	
		
			
				
					                            // This is a valid upper bound. We still need to check the precision.
  
			
		
	
		
			
				
					                            // We can safely use twice the requested precision, as we calculate the center of both vectors
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -271,10 +355,9 @@ namespace storm { 
			
		
	
		
			
				
					                        // The following case below covers that both vectors (old and new) are equal.
  
			
		
	
		
			
				
					                        // Theoretically, this means that the precise fixpoint has been reached. However, numerical instabilities can be tricky and this detection might be incorrect (see the haddad-monmege model).
  
			
		
	
		
			
				
					                        // We therefore disable it. It is very unlikely that we guessed the right fixpoint anyway.
  
			
		
	
		
			
				
					                             //} else if (upperBoundIterResult == oviinternal::UpperBound Iterator<ValueType>::IterateResult::Equal) {
  
			
		
	
		
			
				
					                        //} else if (upperBoundIterResult == oviinternal::Iterati onHelpe r<ValueType>::IterateResult::Equal) {
  
			
		
	
		
			
				
					                            // In this case, the guessed upper bound is the precise fixpoint
  
			
		
	
		
			
				
					                        //    status = SolverStatus::Converged;
  
			
		
	
		
			
				
					                            //    std::swap(lowerX, auxVector);
  
			
		
	
		
			
				
					                        //    break;
  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -287,8 +370,7 @@ namespace storm { 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        // Lower bound iteration (only if needed)
  
			
		
	
		
			
				
					                        if  ( cancelGuess  | |  intervalIterationNeeded  | |  currentVerificationIterations  >  upperBoundOnlyIterations )  {  
			
		
	
		
			
				
					                                singleIterationCallback ( lowerX ,  auxVector ,  overallIterations ) ;  
			
		
	
		
			
				
					                                // At this point, auxVector contains the old values for the lower bound whereas lowerX contains the new ones.
  
			
		
	
		
			
				
					                            auto  diff  =  dir  ?  iterationHelper . singleIterationWithDiff ( dir . get ( ) ,  * lowerX ,  b ,  relative )  :  iterationHelper . singleIterationWithDiff ( * lowerX ,  b ,  relative ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            // Check whether the upper and lower bounds have crossed, i.e., the upper bound is smaller than the lower bound.
  
			
		
	
		
			
				
					                            bool  valuesCrossed  =  false ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -301,7 +383,7 @@ namespace storm { 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            if  ( cancelGuess  | |  valuesCrossed )  {  
			
		
	
		
			
				
					                                // A new guess is needed.
  
			
		
	
		
			
				
					                                     iterationPrecision  =  oviinternal : : updateIterationPrecision ( env ,  * auxVector ,  * lowerX ,  relative ,  relevantValues ) ;  
			
		
	
		
			
				
					                                iterationPrecision  =  oviinternal : : updateIterationPrecision ( env ,  diff ) ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -309,41 +391,14 @@ namespace storm { 
			
		
	
		
			
				
					                    if  ( storm : : utility : : resources : : isTerminate ( ) )  {  
			
		
	
		
			
				
					                        status  =  SolverStatus : : Aborted ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  // end while
  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                // Swap the results into the output vectors.
  
			
		
	
		
			
				
					                if  ( initLowerX  = =  lowerX )  {  
			
		
	
		
			
				
					                    // lowerX is already at the correct position. We still have to care for upperX
  
			
		
	
		
			
				
					                    if  ( initUpperX  ! =  upperX )  {  
			
		
	
		
			
				
					                        // UpperX is not at the correct position. It has to be at the auxVector
  
			
		
	
		
			
				
					                        assert ( initAux  = =  upperX ) ;  
			
		
	
		
			
				
					                        std : : swap ( * initUpperX ,  * initAux ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  else  if  ( initUpperX  = =  upperX )  {  
			
		
	
		
			
				
					                    // UpperX is already at the correct position.
  
			
		
	
		
			
				
					                    // We already know that lowerX is at the wrong position. It has to be at the auxVector
  
			
		
	
		
			
				
					                    assert ( initAux  = =  lowerX ) ;  
			
		
	
		
			
				
					                    std : : swap ( * initLowerX ,  * initAux ) ;  
			
		
	
		
			
				
					                }  else  if  ( initAux  = =  auxVector )  {  
			
		
	
		
			
				
					                    // We know that upperX and lowerX are swapped.
  
			
		
	
		
			
				
					                    assert ( initLowerX  = =  upperX ) ;  
			
		
	
		
			
				
					                    assert ( initUpperX  = =  lowerX ) ;  
			
		
	
		
			
				
					                    std : : swap ( * initUpperX ,  * initLowerX ) ;  
			
		
	
		
			
				
					                }  else  {  
			
		
	
		
			
				
					                    // Now we know that all vectors are at the wrong position. There are only two possibilities left
  
			
		
	
		
			
				
					                    if  ( initLowerX  = =  upperX )  {  
			
		
	
		
			
				
					                        assert ( initUpperX  = =  auxVector ) ;  
			
		
	
		
			
				
					                        assert ( initAux  = =  lowerX ) ;  
			
		
	
		
			
				
					                        std : : swap ( * initLowerX ,  * initAux ) ;  
			
		
	
		
			
				
					                        std : : swap ( * initUpperX ,  * initAux ) ;  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                        assert ( initLowerX  = =  auxVector ) ;  
			
		
	
		
			
				
					                // Swap the results into the output vectors (if necessary).
  
			
		
	
		
			
				
					                assert ( initLowerX  ! =  lowerX  | |  ( initLowerX  = =  lowerX  & &  initUpperX  = =  upperX ) ) ;  
			
		
	
		
			
				
					                if  ( initLowerX  ! =  lowerX )  {  
			
		
	
		
			
				
					                    assert ( initUpperX  = =  lowerX ) ;  
			
		
	
		
			
				
					                        assert  ( initAux  = =  upperX ) ;  
			
		
	
		
			
				
					                        std : : swap ( * initUpperX ,  * initAux ) ;  
			
		
	
		
			
				
					                        std : : swap ( * initLowerX ,  * initAux ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    assert ( initLowerX  = =  upperX ) ;  
			
		
	
		
			
				
					                    lowerX - > swap ( * upperX ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                if  ( overallIterations  >  maxOverallIterations )  {