@ -3,32 +3,29 @@ 
			
		
	
		
			
				
					# include  <cmath>  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					# include  "src/utility/macros.h"  
			
		
	
		
			
				
					# include  "src/utility/ConstantsComparator .h"  
			
		
	
		
			
				
					# include  "src/utility/constants .h"  
			
		
	
		
			
				
					# include  "src/exceptions/InvalidArgumentException.h"  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					namespace  storm  {  
			
		
	
		
			
				
					    namespace  utility  {  
			
		
	
		
			
				
					        namespace  numerical  {  
			
		
	
		
			
				
					            template < typename  ValueType >  
			
		
	
		
			
				
					            std : : tuple < uint_fast64_t ,  uint_fast64_t ,  ValueType ,  std : : vector < ValueType > >  getFoxGlynnCutoff ( ValueType  lambda ,  )  {  
			
		
	
		
			
				
					            std : : tuple < uint_fast64_t ,  uint_fast64_t ,  ValueType ,  std : : vector < ValueType > >  getFoxGlynnCutoff ( ValueType  lambda ,  ValueType  underflow ,  ValueType  overflow ,  ValueType  accuracy )  {  
			
		
	
		
			
				
					                storm : : utility : : ConstantsComparator < ValueType >  comparator ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                ValueType  underflow ,  overflow ,  accuracy  =  0 ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                STORM_LOG_THROW ( ! comparator . isZero ( lambda ) ,  storm : : exceptions : : InvalidArgumentException ,  " Error in Fox-Glynn algorithm: lambda must not be zero. " ) ;  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                / /  This  code  is  more  or  less  taken  from PRISM .  According  to  their  implementation ,  for  lambda  smaller  than   
			
		
	
		
			
				
					                / /  400 ,  we  compute  the  result  using  the  naive  method .  
			
		
	
		
			
				
					                if  ( lambda  <  400 )  {  
			
		
	
		
			
				
					                / /  This  code  is  a  modified  version  of  the  one  in  PRISM .  According  to  their  implementation ,  for  lambda  
			
		
	
		
			
				
					                / /  smaller  than  400 ,  we  compute  the  result  using  the  naive  method .  
			
		
	
		
			
				
					                if  ( lambda  <  25 )  {  
			
		
	
		
			
				
					                    ValueType  eToPowerMinusLambda  =  std : : exp ( - lambda ) ;  
			
		
	
		
			
				
					                    ValueType  targetValue  =  ( 1  -  ( this - > accuracy  /  2.0 )  )  /  eToPowerMinusLambda ;  
			
		
	
		
			
				
					                    ValueType  targetValue  =  ( 1  -  accuracy )  /  eToPowerMinusLambda ;  
			
		
	
		
			
				
					                    std : : vector < ValueType >  weights ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    ValueType  exactlyKEvents  =  1 ;  
			
		
	
		
			
				
					                    ValueType  atMostKEvents  =  exactlyKEvents ;  
			
		
	
		
			
				
					                    weights . push_back ( exactlyKEvents  *  eToPowerMinusLambda ) ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    uint_fast64_t  currentK =  1 ;  
			
		
	
		
			
				
					                    uint_fast64_t  k =  1 ;  
			
		
	
		
			
				
					                    do  {  
			
		
	
		
			
				
					                        exactlyKEvents  * =  lambda  /  k ;  
			
		
	
		
			
				
					                        atMostKEvents  + =  exactlyKEvents ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -40,118 +37,94 @@ namespace storm { 
			
		
	
		
			
				
					                }  else  {  
			
		
	
		
			
				
					                    STORM_LOG_THROW ( accuracy  > =  1e-10 ,  storm : : exceptions : : InvalidArgumentException ,  " Error in Fox-Glynn algorithm: the accuracy must not be below 1e-10. " ) ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    / /  Factor  from  Fox & Glynn ' s  paper .  The  paper  does  not  explain  where  it  comes  from .  
			
		
	
		
			
				
					                    ValueType  factor  =  1e+10 ;  
			
		
	
		
			
				
					                    ValueType  m  =  std : : floor ( lambda ) ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    / /  Now  start  the  Finder  algorithm  to  find  the  truncation  points .  
			
		
	
		
			
				
					                    ValueType  m  =  std : : floor ( lambda ) ;  
			
		
	
		
			
				
					                    uint_fast64_t  leftTruncationPoint  =  0 ,  rightTruncationPoint  =  0 ;  
			
		
	
		
			
				
					                    {  
			
		
	
		
			
				
					                        / /  Factors  used  by  the  corollaries  explained  in  Fox  &  Glynns  paper .  
			
		
	
		
			
				
					                        / /  Square  root  of  pi .  
			
		
	
		
			
				
					                        Type  sqrtpi  =  1.77245385090551602729 ;  
			
		
	
		
			
				
					                        Value Typesqrtpi  =  1.77245385090551602729 ;  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        / /  Square  root  of  2.  
			
		
	
		
			
				
					                        Type  sqrt2  =  1.41421356237309504880 ;  
			
		
	
		
			
				
					                        Value Typesqrt2  =  1.41421356237309504880 ;  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        / /  Square  root  of  lambda .  
			
		
	
		
			
				
					                        Type  sqrtLambda  =  std : : sqrt ( lambda ) ;  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        Type  a_Lambda  =  ( 1.0  +  1.0  /  lambda )  *  exp ( 0.0625 )  *  sqrt2 ;  / /  a_ \ lambda .  
			
		
	
		
			
				
					                        Type  b_Lambda  =  ( 1.0  +  1.0  /  lambda )  *  exp ( 0.125  /  lambda ) ;  / /  b_ \ lambda .  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					                    / /  Use  Fox  Glynn  algorithm  for  lambda > 400.  
			
		
	
		
			
				
					                    if  ( accuracy  <  1e-10 )  {  
			
		
	
		
			
				
					                        LOG4CPLUS_ERROR ( logger ,  " Given Value accuracy must at least be 1e-10. " ) ;  
			
		
	
		
			
				
					                        throw  storm : : exceptions : : InvalidArgumentException ( " Error while computing FoxGlynn values. accuracy < 1e-10. " ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    / /  Factor  from  Fox & Glynns  paper .  The  paper  does  not  explain  where  it  comes  from .  
			
		
	
		
			
				
					                    Type  factor  =  1e+10 ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    / /  Run  the  FINDER  algorithm .  
			
		
	
		
			
				
					                    Type  m  =  floor ( lambda ) ;  
			
		
	
		
			
				
					                    {  
			
		
	
		
			
				
					                        / /  Factores  used  by  the  corollaries  explained  in  Fox & Glynns  paper .  
			
		
	
		
			
				
					                        Type  sqrtpi  =  1.77245385090551602729 ;  / /  Squareroot  of  PI .  
			
		
	
		
			
				
					                        Type  sqrt2  =  1.41421356237309504880 ;  / /  Squareroot  of  2.  
			
		
	
		
			
				
					                        Type  sqrtLambda  =  sqrt ( lambda ) ;  / /  Sqareroot  of  Lambda .  
			
		
	
		
			
				
					                        Type  a_Lambda  =  ( 1.0  +  1.0  /  lambda )  *  exp ( 0.0625 )  *  sqrt2 ;  / /  a_ \ lambda .  
			
		
	
		
			
				
					                        Type  b_Lambda  =  ( 1.0  +  1.0  /  lambda )  *  exp ( 0.125  /  lambda ) ;  / /  b_ \ lambda .  
			
		
	
		
			
				
					                        / /  Set  up  a_ \ lambda ,  b_ \ lambda ,  and  the  square  root  of  lambda .  
			
		
	
		
			
				
					                        ValueType  aLambda  =  0 ,  bLambda  =  0 ,  sqrtLambda  =  0 ;  
			
		
	
		
			
				
					                        if  ( m  <  400 )  {  
			
		
	
		
			
				
					                            sqrtLambda  =  std : : sqrt ( 400.0 ) ;  
			
		
	
		
			
				
					                            aLambda  =  ( 1.0  +  1.0  /  400.0 )  *  exp ( 0.0625 )  *  sqrt2 ;  
			
		
	
		
			
				
					                            bLambda  =  ( 1.0  +  1.0  /  400.0 )  *  exp ( 0.125  /  400.0 ) ;  
			
		
	
		
			
				
					                        }  else  {  
			
		
	
		
			
				
					                            sqrtLambda  =  std : : sqrt ( lambda ) ;  
			
		
	
		
			
				
					                            aLambda  =  ( 1.0  +  1.0  /  lambda )  *  exp ( 0.0625 )  *  sqrt2 ;  
			
		
	
		
			
				
					                            bLambda  =  ( 1.0  +  1.0  /  lambda )  *  exp ( 0.125  /  lambda ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        / /  Use  Corollary  1  from  the  paper  to  find  the  right  truncation  point .  
			
		
	
		
			
				
					                        Type  k  =  4 ;  
			
		
	
		
			
				
					                        res  =  a_Lambda * dkl * exp ( - k * k  /  2.0 )  /  ( k * sqrt2 * sqrtpi ) ;  
			
		
	
		
			
				
					                        /* Normally: Iterate between the bounds stated above to find the right truncationpoint.  
			
		
	
		
			
				
					                         *  This  is  a  modification  to  the  Fox - Glynn  paper .  The  search  for  the  right  truncationpoint  is  only  
			
		
	
		
			
				
					                         *  terminated  by  the  error  condition  and  not  by  the  upper  bound .  Thus  the  calculation  can  be  more  accurate .  
			
		
	
		
			
				
					                         */  
			
		
	
		
			
				
					                        while  ( res  >  accuracy  /  2.0 )  
			
		
	
		
			
				
					                        {  
			
		
	
		
			
				
					                            k + + ;  
			
		
	
		
			
				
					                            Type  dkl  =  1.0  /  ( 1  -  exp ( - ( 2.0  /  9.0 ) * ( k * sqrt2 * sqrtLambda  +  1.5 ) ) ) ;  / /  d ( k , Lambda )  from  the  paper .  
			
		
	
		
			
				
					                            Type  res  =  a_Lambda * dkl * exp ( - k * k  /  2.0 )  /  ( k * sqrt2 * sqrtpi ) ;  / /  Right  hand  side  of  the  equation  in  Corollary  1.  
			
		
	
		
			
				
					                        uint_fast64_t  k  =  3 ;  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        ValueType  dkl  =  1.0  /  ( 1  -  std : : exp ( - ( 2.0  /  9.0 )  *  ( k  *  sqrt2  *  sqrtLambda  +  1.5 ) ) ) ;  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        / /  According  to  David  Jansen  the  upper  bound  can  be  ignored  to  achieve  more  accurate  results .  
			
		
	
		
			
				
					                        / /  Right  hand  side  of  the  equation  in  Corollary  1.  
			
		
	
		
			
				
					                        while  ( ( accuracy  /  2.0 )  <  ( aLambda  *  dkl  *  std : : exp ( - ( k * k  /  2.0 ) )  /  ( k  *  sqrt2  *  sqrtpi ) ) )  {  
			
		
	
		
			
				
					                            + + k ;  
			
		
	
		
			
				
					                             
			
		
	
		
			
				
					                            / /  d ( k , Lambda )  from  the  paper .  
			
		
	
		
			
				
					                            dkl  =  1.0  /  ( 1  -  std : : exp ( - ( 2.0  /  9.0 ) * ( k  *  sqrt2  *  sqrtLambda  +  1.5 ) ) ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        / /  Left  hand  side  of  the  equation  in  Corollary  1.  
			
		
	
		
			
				
					                        this - > rightTrunk  =  ( int ) ceil ( m  +  k * sqrt2 * sqrtLambda  +  1.5 ) ;  
			
		
	
		
			
				
					                        rightTruncationPoint  =  static_cast < uint_fast64_t > ( std : : ceil ( ( m  +  k   *   sqrt2   *   sqrtLambda  +  1.5 ) ) ) ;  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        / /  Use  Corollary  2  to  find  left  truncation  point .  
			
		
	
		
			
				
					                        Type  res ;  
			
		
	
		
			
				
					                        k  =  4 ;  
			
		
	
		
			
				
					                        k  =  3 ;  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        do  
			
		
	
		
			
				
					                        {  
			
		
	
		
			
				
					                            res  =  b_Lambda * exp ( - k * - k  /  2.0 )  /  ( k * sqrt2 * sqrtpi ) ;  / /  Right  hand  side  of  the  equation  in  Corollary  2  
			
		
	
		
			
				
					                            k + + ;  
			
		
	
		
			
				
					                        }  while  ( res  >  accuracy  /  2.0 ) ;  
			
		
	
		
			
				
					                        / /  Right  hand  side  of  the  equation  in  Corollary  2.  
			
		
	
		
			
				
					                        while  ( ( accuracy  /  2.0 )  <  ( ( bLambda  *  exp ( - ( k * k  /  2.0 ) ) )  /  ( k  *  sqrt2  *  sqrtpi ) ) )  {  
			
		
	
		
			
				
					                            + + k ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        this - > leftTrunk  =  ( int ) ( m  -  k * sqrtLambda  -  1.5 ) ;  / /  Left  hand  side  of  the  equation  in  Corollary  2.  
			
		
	
		
			
				
					                        / /  Left  hand  side  of  the  equation  in  Corollary  2.  
			
		
	
		
			
				
					                        leftTruncationPoint  =  std : : max ( static_cast < uint_fast64_t > ( std : : trunc ( m  -  k  *  sqrtLambda  -  1.5 ) ) ,  uint_fast64_t ( 0 ) ) ;  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        / /  Check  for  underflow .  
			
		
	
		
			
				
					                        if  ( ( int ) ( m  -  k * sqrtLambda  -  1.5 )  <  0.0 )  {  
			
		
	
		
			
				
					                            LOG4CPLUS_ERROR ( logger ,  " Underflow while computing left truncation point. " ) ;  
			
		
	
		
			
				
					                            throw  storm : : exceptions : : OutOfRangeException ( " Error while computing FoxGlynn values. Underflow of left Truncation point. " ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                         
			
		
	
		
			
				
					                        STORM_LOG_THROW ( static_cast < uint_fast64_t > ( std : : trunc ( ( m  -  k  *  sqrtLambda  -  1.5 ) ) )  > =  0 ,  storm : : exceptions : : OutOfRangeException ,  " Error in Fox-Glynn algorithm: Underflow of left truncation point. " ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    / / End  of  FINDER  algorithm .  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    / /  Use  WEIGHTER  algorithm  to  determine  weights .  
			
		
	
		
			
				
					                    / /  Down  from  m  
			
		
	
		
			
				
					                    for  ( Type  j  =  m ;  j  >  this - > leftTrunk ;  j - - )  
			
		
	
		
			
				
					                        this - > weights . at ( j  -  1  -  this - > leftTrunk )  =  ( j  /  lambda ) * this - > weights . at ( j  -  this - > leftTrunk ) ;  
			
		
	
		
			
				
					                    / /  Up  from  m  
			
		
	
		
			
				
					                    for  ( Type  j  =  m ;  j  <  this - > rightTrunk ;  j + + )  
			
		
	
		
			
				
					                        this - > weights . at ( j  +  1  -  this - > leftTrunk )  =  ( lambda  /  ( j  +  1 ) ) * this - > weights . at ( j  -  this - > leftTrunk ) ;  
			
		
	
		
			
				
					                    std : : vector < ValueType >  weights ( rightTruncationPoint  -  leftTruncationPoint  +  1 ) ;  
			
		
	
		
			
				
					                    weights [ m  -  leftTruncationPoint ]  =  overflow  /  ( factor  *  ( rightTruncationPoint  -  leftTruncationPoint ) ) ;  
			
		
	
		
			
				
					                    for  ( uint_fast64_t  j  =  m ;  j  >  leftTruncationPoint ;  - - j )  {  
			
		
	
		
			
				
					                        weights [ j  -  1  -  leftTruncationPoint ]  =  ( j  /  lambda )  *  weights [ j  -  leftTruncationPoint ] ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    / /  Compute  total  weight .  
			
		
	
		
			
				
					                    / /  Add  up  weights  from  smallest  to  largest  to  avoid  roundoff  errors .  
			
		
	
		
			
				
					                    this - > totalWeight  =  0.0 ;  
			
		
	
		
			
				
					                    Type  s  =  this - > leftTrunk ;  
			
		
	
		
			
				
					                    Type  t  =  this - > rightTrunk ;  
			
		
	
		
			
				
					                    while  ( s  <  t )  
			
		
	
		
			
				
					                    {  
			
		
	
		
			
				
					                        if  ( this - > weights . at ( s  -  this - > leftTrunk )  < =  this - > weights . at ( t  -  this - > leftTrunk ) )  
			
		
	
		
			
				
					                        {  
			
		
	
		
			
				
					                            this - > totalWeight  + =  this - > weights . at ( s  -  this - > leftTrunk ) ;  
			
		
	
		
			
				
					                            s + + ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        else  
			
		
	
		
			
				
					                        {  
			
		
	
		
			
				
					                            this - > totalWeight  + =  this - > weights . at ( t  -  this - > leftTrunk ) ;  
			
		
	
		
			
				
					                            t - - ;  
			
		
	
		
			
				
					                    for  ( uint_fast64_t  j  =  m ;  j  <  rightTruncationPoint ;  + + j )  {  
			
		
	
		
			
				
					                        weights [ j  +  1  -  leftTruncationPoint ]  =  ( lambda  /  ( j  +  1 ) )  *  weights [ j  -  leftTruncationPoint ] ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    / /  Compute  the  total  weight  and  start  with  smallest  to  avoid  roundoff  errors .  
			
		
	
		
			
				
					                    ValueType  totalWeight  =  storm : : utility : : zero < ValueType > ( ) ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    uint_fast64_t  s  =  leftTruncationPoint ;  
			
		
	
		
			
				
					                    uint_fast64_t  t  =  rightTruncationPoint ;  
			
		
	
		
			
				
					                    while  ( s  <  t )  {  
			
		
	
		
			
				
					                        if  ( weights [ s  -  leftTruncationPoint ]  < =  weights [ t  -  leftTruncationPoint ] )  {  
			
		
	
		
			
				
					                            totalWeight  + =  weights [ s  -  leftTruncationPoint ] ;  
			
		
	
		
			
				
					                            + + s ;  
			
		
	
		
			
				
					                        }  else  {  
			
		
	
		
			
				
					                            totalWeight  + =  weights [ t  -  leftTruncationPoint ] ;  
			
		
	
		
			
				
					                            - - t ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    this - > t otalWeight  + =  this - > weights . at ( s  -  this - > leftTrunk ) ;  
			
		
	
		
			
				
					                    totalWeight  + =  weights [ s  -  leftTruncationPoint ] ;  
			
		
	
		
			
				
					                     
			
		
	
		
			
				
					                    LOG4CPLUS_INFO ( logger ,  " Left truncationpoint:  "  < <  this - > leftTrunk  < <  " . " ) ;  
			
		
	
		
			
				
					                    LOG4CPLUS_INFO ( logger ,  " Right truncationpoint:  "  < <  this - > rightTrunk  < <  " . " ) ;  
			
		
	
		
			
				
					                    LOG4CPLUS_INFO ( logger ,  " Total Weight: "  < <  this - > totalWeight  < <  " . " ) ;  
			
		
	
		
			
				
					                    LOG4CPLUS_INFO ( logger ,  " 10. Weight:  "  < <  this - > weights . at ( 9 )  < <  " . " ) ;  
			
		
	
		
			
				
					                    return  std : : make_tuple ( leftTruncationPoint ,  rightTruncationPoint ,  totalWeight ,  weights ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }