@ -35,7 +35,7 @@ namespace storm { 
		
	
		
			
				                template < typename  ValueType >                 template < typename  ValueType >  
		
	
		
			
				                ValueType  computeMaxRelDiff ( std : : vector < ValueType >  const &  allOldValues ,  std : : vector < ValueType >  const &  allNewValues ,  storm : : storage : : BitVector  const &  relevantValues )  {                 ValueType  computeMaxRelDiff ( std : : vector < ValueType >  const &  allOldValues ,  std : : vector < ValueType >  const &  allNewValues ,  storm : : storage : : BitVector  const &  relevantValues )  {  
		
	
		
			
				                    ValueType  result  =  storm : : utility : : zero < ValueType > ( ) ;                     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. " ) ;                         STORM_LOG_ASSERT ( ! storm : : utility : : isZero ( allNewValues [ i ] )  | |  storm : : utility : : isZero ( allOldValues [ i ] ) ,  " Unexpected entry in iteration vector. " ) ;  
		
	
		
			
				                        if  ( ! storm : : utility : : isZero ( allNewValues [ i ] ) )  {                         if  ( ! storm : : utility : : isZero ( allNewValues [ i ] ) )  {  
		
	
		
			
				                            result  =  storm : : utility : : max < ValueType > ( result ,  storm : : utility : : abs < ValueType > ( allNewValues [ i ]  -  allOldValues [ i ] )  /  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  computeMaxRelDiff ( std : : vector < ValueType >  const &  allOldValues ,  std : : vector < ValueType >  const &  allNewValues )  {  
		
	
		
			
				                    ValueType  result  =  storm : : utility : : zero < ValueType > ( ) ;                     ValueType  result  =  storm : : utility : : zero < ValueType > ( ) ;  
		
	
		
			
				                    for  ( uint64_t  i  =  0 ;  i  <  allOldValues . size ( ) ;  + + i )  {                     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 ] ) )  {                         if  ( ! storm : : utility : : isZero ( allNewValues [ i ] ) )  {  
		
	
		
			
				                            result  =  storm : : utility : : max < ValueType > ( result ,  storm : : utility : : abs < ValueType > ( allNewValues [ i ]  -  allOldValues [ i ] )  /  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 >                 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 ( ) ) ;                     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 >                 template < typename  ValueType >  
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -78,7 +73,7 @@ namespace storm { 
		
	
		
			
				                }                 }  
		
	
		
			
				                                 
		
	
		
			
				                template  < typename  ValueType >                 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 . 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. " ) ;                     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 ( ) ) ;                     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  < 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 ) ;  
		
	
		
			
				                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 >  
		
	
		
			
				                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 >                 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 ) )  {                     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  {                     }  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  < typename  ValueType >  
		
	
		
			
				                template < bool  HasRowGroups ,  storm : : solver : : OptimizationDirection  Dir >                 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
                     // For each row compare the new upper bound candidate with the old one
  
		
	
		
			
				                    bool  newUpperBoundAlwaysHigherEqual  =  true ;                     bool  newUpperBoundAlwaysHigherEqual  =  true ;  
		
	
		
			
				                    bool  newUpperBoundAlwaysLowerEqual  =  true ;                     bool  newUpperBoundAlwaysLowerEqual  =  true ;  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -150,7 +242,7 @@ namespace storm { 
		
	
		
			
				                }                 }  
		
	
		
			
				                                 
		
	
		
			
				                template  < typename  ValueType >                 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 ( ) ) ;                     assert ( rowIndex  <  rowIndications . size ( ) ) ;  
		
	
		
			
				                    ValueType  xRes  =  bi ;                     ValueType  xRes  =  bi ;  
		
	
		
			
				                                         
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -165,7 +257,7 @@ namespace storm { 
		
	
		
			
				                                 
		
	
		
			
				                template  < typename  ValueType >                 template  < typename  ValueType >  
		
	
		
			
				                template < storm : : solver : : OptimizationDirection  Dir >                 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. " ) ;                     STORM_LOG_ASSERT ( rowGroupIndices  ! =  nullptr ,  " No row group indices available. " ) ;  
		
	
		
			
				                    auto  row  =  ( * rowGroupIndices ) [ rowGroupIndex ] ;                     auto  row  =  ( * rowGroupIndices ) [ rowGroupIndex ] ;  
		
	
		
			
				                    auto  const &  groupEnd  =  ( * rowGroupIndices ) [ rowGroupIndex  +  1 ] ;                     auto  const &  groupEnd  =  ( * rowGroupIndices ) [ rowGroupIndex  +  1 ] ;  
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -180,24 +272,21 @@ namespace storm { 
		
	
		
			
				            }             }  
		
	
		
			
				                         
		
	
		
			
				            template < typename  ValueType >             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.
                     // Intentionally left empty.
  
		
	
		
			
				                }                 }  
		
	
		
			
				                                 
		
	
		
			
				            template < typename  ValueType >             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 ( )  = =  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.
                 // As we will shuffle pointers around, let's store the original positions here.
  
		
	
		
			
				                std : : vector < ValueType > *  initLowerX  =  lowerX ;                 std : : vector < ValueType > *  initLowerX  =  lowerX ;  
		
	
		
			
				                std : : vector < ValueType > *  initUpperX  =  upperX ;                 std : : vector < ValueType > *  initUpperX  =  upperX ;  
		
	
		
			
				                std : : vector < ValueType > *  initAux  =  auxVector ;  
		
	
		
			
				                                 
		
	
		
			
				                uint64_t  overallIterations  =  0 ;                 uint64_t  overallIterations  =  0 ;  
		
	
		
			
				                uint64_t  lastValueIterationIterations  =  0 ;                 uint64_t  lastValueIterationIterations  =  0 ;  
		
	
		
			
				                uint64_t  currentVerificationIterations  =  0 ;                 uint64_t  currentVerificationIterations  =  0 ;  
		
	
		
			
				                uint64_t  valueIterationInvocations  =  0 ;  
		
	
		
			
				                                 
		
	
		
			
				                // Get some parameters for the algorithm
                 // Get some parameters for the algorithm
  
		
	
		
			
				                // 2
                 // 2
  
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -215,135 +304,101 @@ namespace storm { 
		
	
		
			
				                SolverStatus  status  =  SolverStatus : : InProgress ;                 SolverStatus  status  =  SolverStatus : : InProgress ;  
		
	
		
			
				         
		
	
		
			
				                while  ( status  = =  SolverStatus : : InProgress  & &  overallIterations  <  maxOverallIterations )  {                 while  ( status  = =  SolverStatus : : InProgress  & &  overallIterations  <  maxOverallIterations )  {  
		
	
		
			
				
 
		
	
		
			
				                    // Perform value iteration until convergence
                     // 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 ;  
		
	
		
			
				                    bool  intervalIterationNeeded  =  false ;  
		
	
		
			
				                    currentVerificationIterations  =  0 ;  
		
	
		
			
				
 
		
	
		
			
				                         if  ( relative )  {  
		
	
		
			
				                             oviinternal : : guessUpperBoundRelative ( * lowerX ,  * upperX ,  relativeBoundGuessingScaler ) ;  
		
	
		
			
				                         }  else  {  
		
	
		
			
				                             oviinternal : : guessUpperBoundAbsolute ( * lowerX ,  * upperX ,  precision ) ;  
		
	
		
			
				                         }  
		
	
		
			
				                    if  ( relative )  {  
		
	
		
			
				                        oviinternal : : guessUpperBoundRelative ( * lowerX ,  * upperX ,  relativeBoundGuessingScaler ) ;  
		
	
		
			
				                    }  else  {  
		
	
		
			
				                        oviinternal : : guessUpperBoundAbsolute ( * lowerX ,  * upperX ,  precision ) ;  
		
	
		
			
				                    }  
		
	
		
			
				
 
		
	
		
			
				                         bool  cancelGuess  =  false ;  
		
	
		
			
				                         while  ( status  = =  SolverStatus : : InProgress  & &  overallIterations  <  maxOverallIterations )  {  
		
	
		
			
				                             + + overallIterations ;  
		
	
		
			
				                             + + currentVerificationIterations ;  
		
	
		
			
				                             // Perform value iteration stepwise for lower bound and guessed upper bound
  
		
	
		
			
				                    bool  cancelGuess  =  false ;  
		
	
		
			
				                    while  ( status  = =  SolverStatus : : InProgress  & &  overallIterations  <  maxOverallIterations )  {  
		
	
		
			
				                        + + overallIterations ;  
		
	
		
			
				                        + + currentVerificationIterations ;  
		
	
		
			
				                        // 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 ) ;  
		
	
		
			
				                        // Upper bound iteration
  
		
	
		
			
				                        auto  upperBoundIterResult  =  dir  ?  iterationHelpe r. iterateUpper  ( dir . get ( ) ,  * upperX ,  b ,  ! noTerminationGuarantee )  :  iterationHelpe r. iterateUpper  ( * upperX ,  b ,  ! noTerminationGuarantee ) ;  
		
	
		
			
				
 
		
	
		
			
				                            if  ( upperBoundIterResult  = =  oviinternal : : UpperBoundIterator < 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 ) ;  
		
	
		
			
				                                // 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 : : UpperBoundIterator < 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
  
		
	
		
			
				                                bool  reachedPrecision ;  
		
	
		
			
				                                if  ( relevantValues )  {  
		
	
		
			
				                                    reachedPrecision  =  storm : : utility : : vector : : equalModuloPrecision ( * lowerX ,  * upperX ,  relevantValues . get ( ) ,  doublePrecision ,  relative ) ;  
		
	
		
			
				                                }  else  {  
		
	
		
			
				                                    reachedPrecision  =  storm : : utility : : vector : : equalModuloPrecision ( * lowerX ,  * upperX ,  doublePrecision ,  relative ) ;  
		
	
		
			
				                                }  
		
	
		
			
				                                if  ( reachedPrecision )  {  
		
	
		
			
				                                    status  =  SolverStatus : : Converged ;  
		
	
		
			
				                                    break ;  
		
	
		
			
				                                }  else  {  
		
	
		
			
				                                    // From now on, we keep updating both bounds
  
		
	
		
			
				                                    intervalIterationNeeded  =  true ;  
		
	
		
			
				                                }  
		
	
		
			
				                            // 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::UpperBoundIterator<ValueType>::IterateResult::Equal) {
  
		
	
		
			
				                                // In this case, the guessed upper bound is the precise fixpoint
  
		
	
		
			
				                            //    status = SolverStatus::Converged;
  
		
	
		
			
				                            //    std::swap(lowerX, auxVector);
  
		
	
		
			
				                            //    break;
  
		
	
		
			
				                        if  ( upperBoundIterResult  = =  oviinternal : : IterationHelper < 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
  
		
	
		
			
				                            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 : : IterationHelper < 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
  
		
	
		
			
				                            bool  reachedPrecision ;  
		
	
		
			
				                            if  ( relevantValues )  {  
		
	
		
			
				                                reachedPrecision  =  storm : : utility : : vector : : equalModuloPrecision ( * lowerX ,  * upperX ,  relevantValues . get ( ) ,  doublePrecision ,  relative ) ;  
		
	
		
			
				                            }  else  {  
		
	
		
			
				                                reachedPrecision  =  storm : : utility : : vector : : equalModuloPrecision ( * lowerX ,  * upperX ,  doublePrecision ,  relative ) ;  
		
	
		
			
				                            }                             }  
		
	
		
			
				
  
		
	
		
			
				                            // Check whether we tried this guess for too long
  
		
	
		
			
				                            ValueType  scaledIterationCount  =  storm : : utility : : convertNumber < ValueType > ( currentVerificationIterations )  *  storm : : utility : : convertNumber < ValueType > ( env . solver ( ) . ovi ( ) . getMaxVerificationIterationFactor ( ) ) ;  
		
	
		
			
				                            if  ( ! intervalIterationNeeded  & &  scaledIterationCount  > =  storm : : utility : : convertNumber < ValueType > ( lastValueIterationIterations ) ) {  
		
	
		
			
				                                cancelGuess  =  true ;  
		
	
		
			
				                                // In this case we will make one more iteration on the lower bound (mainly to obtain a new iterationPrecision)
  
		
	
		
			
				                            if  ( reachedPrecision )  {  
		
	
		
			
				                                status  =  SolverStatus : : Converged ;  
		
	
		
			
				                                break ;  
		
	
		
			
				                            }  else  {  
		
	
		
			
				                                // From now on, we keep updating both bounds
  
		
	
		
			
				                                intervalIterationNeeded  =  true ;  
		
	
		
			
				                            }                             }  
		
	
		
			
				                        // 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::IterationHelper<ValueType>::IterateResult::Equal) {
  
		
	
		
			
				                            // In this case, the guessed upper bound is the precise fixpoint
  
		
	
		
			
				                        //    status = SolverStatus::Converged;
  
		
	
		
			
				                        //    break;
  
		
	
		
			
				                        }  
		
	
		
			
				
 
		
	
		
			
				                            // 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.
  
		
	
		
			
				                        // Check whether we tried this guess for too long
  
		
	
		
			
				                        ValueType  scaledIterationCount  =  storm : : utility : : convertNumber < ValueType > ( currentVerificationIterations )  *  storm : : utility : : convertNumber < ValueType > ( env . solver ( ) . ovi ( ) . getMaxVerificationIterationFactor ( ) ) ;  
		
	
		
			
				                        if  ( ! intervalIterationNeeded  & &  scaledIterationCount  > =  storm : : utility : : convertNumber < ValueType > ( lastValueIterationIterations ) )  {  
		
	
		
			
				                            cancelGuess  =  true ;  
		
	
		
			
				                            // In this case we will make one more iteration on the lower bound (mainly to obtain a new iterationPrecision)
  
		
	
		
			
				                        }  
		
	
		
			
				
 
		
	
		
			
				                                // Check whether the upper and lower bounds have crossed, i.e., the upper bound is smaller than the lower bound.
  
		
	
		
			
				                                bool  valuesCrossed  =  false ;  
		
	
		
			
				                                for  ( uint64_t  i  =  0 ;  i  <  lowerX - > size ( ) ;  + + i )  {  
		
	
		
			
				                                    if  ( ( * upperX ) [ i ]  <  ( * lowerX ) [ i ] )  {  
		
	
		
			
				                                        valuesCrossed  =  true ;  
		
	
		
			
				                                        break ;  
		
	
		
			
				                                    }  
		
	
		
			
				                                }  
		
	
		
			
				                        // Lower bound iteration (only if needed)
  
		
	
		
			
				                        if  ( cancelGuess  | |  intervalIterationNeeded  | |  currentVerificationIterations  >  upperBoundOnlyIterations )  {  
		
	
		
			
				                            auto  diff  =  dir  ?  iterationHelper . singleIterationWithDiff ( dir . get ( ) ,  * lowerX ,  b ,  relative )  :  iterationHelper . singleIterationWithDiff ( * lowerX ,  b ,  relative ) ;  
		
	
		
			
				
 
		
	
		
			
				                                if  ( cancelGuess  | |  valuesCrossed )  {  
		
	
		
			
				                                    // A new guess is needed.
  
		
	
		
			
				                                    iterationPrecision  =  oviinternal : : updateIterationPrecision ( env ,  * auxVector ,  * lowerX ,  relative ,  relevantValues ) ;  
		
	
		
			
				                            // Check whether the upper and lower bounds have crossed, i.e., the upper bound is smaller than the lower bound.
  
		
	
		
			
				                            bool  valuesCrossed  =  false ;  
		
	
		
			
				                            for  ( uint64_t  i  =  0 ;  i  <  lowerX - > size ( ) ;  + + i )  {  
		
	
		
			
				                                if  ( ( * upperX ) [ i ]  <  ( * lowerX ) [ i ] )  {  
		
	
		
			
				                                    valuesCrossed  =  true ;  
		
	
		
			
				                                    break ;                                     break ;  
		
	
		
			
				                                }                                 }  
		
	
		
			
				                            }                             }  
		
	
		
			
				
 
		
	
		
			
				                            if  ( cancelGuess  | |  valuesCrossed )  {  
		
	
		
			
				                                // A new guess is needed.
  
		
	
		
			
				                                iterationPrecision  =  oviinternal : : updateIterationPrecision ( env ,  diff ) ;  
		
	
		
			
				                                break ;  
		
	
		
			
				                            }  
		
	
		
			
				                        }                         }  
		
	
		
			
				                        if  ( storm : : utility : : resources : : isTerminate ( ) )  {  
		
	
		
			
				                            status  =  SolverStatus : : Aborted ;  
		
	
		
			
				                        }  
		
	
		
			
				                    }  
		
	
		
			
				                    if  ( storm : : utility : : resources : : isTerminate ( ) )  {  
		
	
		
			
				                        status  =  SolverStatus : : Aborted ;  
		
	
		
			
				                    }                     }  
		
	
		
			
				                }  // end while
                 }  // 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 ) ;  
		
	
		
			
				                // Swap the results into the output vectors (if necessary).
  
		
	
		
			
				                assert ( initLowerX  ! =  lowerX  | |  ( initLowerX  = =  lowerX  & &  initUpperX  = =  upperX ) ) ;  
		
	
		
			
				                if  ( initLowerX  ! =  lowerX )  {  
		
	
		
			
				                    assert ( initUpperX  = =  lowerX ) ;                     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 ) ;  
		
	
		
			
				                        assert ( initUpperX  = =  lowerX ) ;  
		
	
		
			
				                        assert  ( initAux  = =  upperX ) ;  
		
	
		
			
				                        std : : swap ( * initUpperX ,  * initAux ) ;  
		
	
		
			
				                        std : : swap ( * initLowerX ,  * initAux ) ;  
		
	
		
			
				                    }  
		
	
		
			
				                    assert ( initLowerX  = =  upperX ) ;  
		
	
		
			
				                    lowerX - > swap ( * upperX ) ;  
		
	
		
			
				                }                 }  
		
	
		
			
				                                 
		
	
		
			
				                if  ( overallIterations  >  maxOverallIterations )  {                 if  ( overallIterations  >  maxOverallIterations )  {