|  | @ -57,7 +57,7 @@ namespace storm { | 
		
	
		
			
				|  |  |                  |  |  |                  | 
		
	
		
			
				|  |  |             private: |  |  |             private: | 
		
	
		
			
				|  |  |                 template <typename ValueType, typename std::enable_if<storm::NumberTraits<ValueType>::SupportsExponential, int>::type=0> |  |  |                 template <typename ValueType, typename std::enable_if<storm::NumberTraits<ValueType>::SupportsExponential, int>::type=0> | 
		
	
		
			
				|  |  |                 static void calculateUnifPlusVector(uint64_t k, uint64_t node, uint64_t const kind, ValueType lambda, uint64_t probSize, std::vector<std::vector<ValueType>> const& relativeReachability, OptimizationDirection dir, std::vector<std::vector<std::vector<ValueType>>>& unifVectors, storm::storage::SparseMatrix<ValueType> const& fullTransitionMatrix, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> const& solver, std::ofstream& logfile); |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                 static void calculateUnifPlusVector(uint64_t k, uint64_t node, uint64_t const kind, ValueType lambda, uint64_t probSize, std::vector<std::vector<ValueType>> const& relativeReachability, OptimizationDirection dir, std::vector<std::vector<std::vector<ValueType>>>& unifVectors, storm::storage::SparseMatrix<ValueType> const& fullTransitionMatrix, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> const& solver, std::ofstream& logfile, std::vector<double> poisson); | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                 template <typename ValueType, typename std::enable_if<storm::NumberTraits<ValueType>::SupportsExponential, int>::type=0> |  |  |                 template <typename ValueType, typename std::enable_if<storm::NumberTraits<ValueType>::SupportsExponential, int>::type=0> | 
		
	
		
			
				|  |  |                 static void deleteProbDiagonals(storm::storage::SparseMatrix<ValueType>& transitionMatrix, storm::storage::BitVector const& markovianStates); |  |  |                 static void deleteProbDiagonals(storm::storage::SparseMatrix<ValueType>& transitionMatrix, storm::storage::BitVector const& markovianStates); | 
		
	
	
		
			
				|  | @ -80,6 +80,321 @@ namespace storm { | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                     template <typename ValueType, typename std::enable_if<storm::NumberTraits<ValueType>::SupportsExponential, int>::type=0> |  |  |                     template <typename ValueType, typename std::enable_if<storm::NumberTraits<ValueType>::SupportsExponential, int>::type=0> | 
		
	
		
			
				|  |  |                 static storm::storage::BitVector identifyProbCycles(storm::storage::SparseMatrix<ValueType> const& TransitionMatrix, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates); |  |  |                 static storm::storage::BitVector identifyProbCycles(storm::storage::SparseMatrix<ValueType> const& TransitionMatrix, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates); | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                 //TODO: move this | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                 typedef struct FoxGlynn | 
		
	
		
			
				|  |  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |  |                     int left; | 
		
	
		
			
				|  |  |  |  |  |                     int right; | 
		
	
		
			
				|  |  |  |  |  |                     double total_weight; | 
		
	
		
			
				|  |  |  |  |  |                     double *weights; | 
		
	
		
			
				|  |  |  |  |  |                 } FoxGlynn; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                 static std::vector<double> foxGlynnProb(double lambdaT, int N, double precision){ | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     FoxGlynn* fg = NULL; | 
		
	
		
			
				|  |  |  |  |  |                     if(!fox_glynn(lambdaT, DBL_MIN, DBL_MAX, precision, &fg)) { | 
		
	
		
			
				|  |  |  |  |  |                         printf("ERROR: fox-glynn failed\n"); | 
		
	
		
			
				|  |  |  |  |  |                         return std::vector<double>{}; | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     long double sumOfPoissonProbs = 0.0; | 
		
	
		
			
				|  |  |  |  |  |                     std::vector<double> poisson_p(N,0.0); | 
		
	
		
			
				|  |  |  |  |  |                     unsigned long iter_num; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     //for(int i=fg->left; i<=fg->right; i++) { | 
		
	
		
			
				|  |  |  |  |  |                     for (int i = 0; i<N ; i++){ | 
		
	
		
			
				|  |  |  |  |  |                         poisson_p[i] = fg->weights[i-fg->left]/fg->total_weight; | 
		
	
		
			
				|  |  |  |  |  |                         sumOfPoissonProbs+=poisson_p[i]; | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /*for(int i=fg->left-1; i>=0; i--) { | 
		
	
		
			
				|  |  |  |  |  |                         poisson_p[i] = poisson_p[i+1]*((i+1)/(lambdaT)); | 
		
	
		
			
				|  |  |  |  |  |                         sumOfPoissonProbs+=poisson_p[i]; | 
		
	
		
			
				|  |  |  |  |  |                     }*/ | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     iter_num = fg->right; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     freeFG(fg); | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     return poisson_p; | 
		
	
		
			
				|  |  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                 static bool finder(const int m, const double lambda, const double tau, const double omega, | 
		
	
		
			
				|  |  |  |  |  |                                    const double epsilon, double * pw_m, FoxGlynn *pFG) | 
		
	
		
			
				|  |  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |  |                     /*The pi constant*/ | 
		
	
		
			
				|  |  |  |  |  |                     static const double pi = 3.14159265358979323846264; | 
		
	
		
			
				|  |  |  |  |  |                     static const double lambda_25 = 25.0; | 
		
	
		
			
				|  |  |  |  |  |                     static const double lambda_400 = 40; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     const double sqrt_2_pi = sqrt( 2.0 * pi ); | 
		
	
		
			
				|  |  |  |  |  |                     const double sqrt_2 = sqrt(2.0); | 
		
	
		
			
				|  |  |  |  |  |                     const double sqrt_lambda = sqrt(lambda); | 
		
	
		
			
				|  |  |  |  |  |                     double lambda_max, k, k_rtp = HUGE_VAL, k_prime, c_m_inf, result, al, dkl, bl; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /*Simple bad cases, when we quit*/ | 
		
	
		
			
				|  |  |  |  |  |                     if( lambda == 0.0 ) | 
		
	
		
			
				|  |  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |  |                         printf("ERROR: Fox-Glynn: lambda = 0, terminating the algorithm\n"); | 
		
	
		
			
				|  |  |  |  |  |                         return false; | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  |                     /* The requested error level must not be smaller than the minimum machine precision | 
		
	
		
			
				|  |  |  |  |  |                        (needed to guarantee the convergence of the error conditions) */ | 
		
	
		
			
				|  |  |  |  |  |                     if( epsilon < tau) | 
		
	
		
			
				|  |  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |  |                         printf("ERROR: Fox-Glynn: epsilon < tau, invalid error level, terminating the algorithm\n"); | 
		
	
		
			
				|  |  |  |  |  |                         printf("epsilon %f, tau %f\n",epsilon,tau); | 
		
	
		
			
				|  |  |  |  |  |                         return false; | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  |                     /* zero is used as left truncation point for lambda <= 25 */ | 
		
	
		
			
				|  |  |  |  |  |                     pFG->left = 0; | 
		
	
		
			
				|  |  |  |  |  |                     lambda_max = lambda; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /* for lambda below 25 the exponential can be smaller than tau */ | 
		
	
		
			
				|  |  |  |  |  |                     /* if that is the case we expect underflows and warn the user */ | 
		
	
		
			
				|  |  |  |  |  |                     if( 0.0 < lambda && lambda <= lambda_25 ) | 
		
	
		
			
				|  |  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |  |                         if( exp( -lambda ) <= tau ) | 
		
	
		
			
				|  |  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |  |                             printf("ERROR: Fox-Glynn: 0 < lambda < 25, underflow. The results are UNRELIABLE.\n"); | 
		
	
		
			
				|  |  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     bl = (1.0 + 1.0/lambda) * exp(1.0 / (8.0 * lambda)); | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /****Compute pFG->right truncation point****/ | 
		
	
		
			
				|  |  |  |  |  |                     /*According to Fox-Glynn, if lambda < 400 we should take lambda = 400, | 
		
	
		
			
				|  |  |  |  |  |                       otherwise use the original value. This is for computing the right truncation point*/ | 
		
	
		
			
				|  |  |  |  |  |                     if(lambda < lambda_400) | 
		
	
		
			
				|  |  |  |  |  |                         lambda_max = lambda_400; | 
		
	
		
			
				|  |  |  |  |  |                     k = 4; | 
		
	
		
			
				|  |  |  |  |  |                     al = (1.0+1.0/lambda_max) * exp(1.0/16.0) * sqrt_2; | 
		
	
		
			
				|  |  |  |  |  |                     dkl = exp(-2.0/9.0 * (k * sqrt(2.0 * lambda_max) + 1.5 )); | 
		
	
		
			
				|  |  |  |  |  |                     dkl = 1.0 / (1.0 - dkl); | 
		
	
		
			
				|  |  |  |  |  |                     /* find right truncation point */ | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /* This loop is a modification to the original Fox-Glynn paper. | 
		
	
		
			
				|  |  |  |  |  |                        The search for the right truncation point is only terminated by | 
		
	
		
			
				|  |  |  |  |  |                        the error condition and not by the stop index from the FG paper. | 
		
	
		
			
				|  |  |  |  |  |                        This can yield more accurate results if neccesary.*/ | 
		
	
		
			
				|  |  |  |  |  |                     while((epsilon/2.0) < ((al * dkl * exp(-(k*k)/2.0))/(k*sqrt_2_pi))) | 
		
	
		
			
				|  |  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |  |                         k++; | 
		
	
		
			
				|  |  |  |  |  |                         dkl = exp(-2.0/9.0 * (k * sqrt_2 * sqrt(lambda_max) + 1.5 )); | 
		
	
		
			
				|  |  |  |  |  |                         dkl = 1.0 / (1.0 - dkl); | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  |                     k_rtp = k; | 
		
	
		
			
				|  |  |  |  |  |                     pFG->right = (int)ceil(m + k_rtp * sqrt_2 * sqrt(lambda_max) + 1.5 ); | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /****Compute pFG->left truncation point****/ | 
		
	
		
			
				|  |  |  |  |  |                     /* compute the left truncation point for lambda > 25 */ | 
		
	
		
			
				|  |  |  |  |  |                     /* for lambda <= 25 we use zero as left truncation point */ | 
		
	
		
			
				|  |  |  |  |  |                     if(lambda > lambda_25) | 
		
	
		
			
				|  |  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |  |                         /*Start looking for the left truncation point*/ | 
		
	
		
			
				|  |  |  |  |  |                         /* start search at k=4 (taken from original Fox-Glynn paper */ | 
		
	
		
			
				|  |  |  |  |  |                         k = 4; | 
		
	
		
			
				|  |  |  |  |  |                         /* increase the left truncation point as long as we fulfill the error condition */ | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                         /* This loop is a modification to the original Fox-Glynn paper. | 
		
	
		
			
				|  |  |  |  |  |                            The search for the left truncation point is only terminated by | 
		
	
		
			
				|  |  |  |  |  |                            the error condition and not by the stop index from the FG paper. | 
		
	
		
			
				|  |  |  |  |  |                            This can yield more accurate results if neccesary.*/ | 
		
	
		
			
				|  |  |  |  |  |                         while((epsilon/2.0) < ((bl * exp(-(k*k)/2.0))/(k * sqrt_2_pi))) | 
		
	
		
			
				|  |  |  |  |  |                             k++; | 
		
	
		
			
				|  |  |  |  |  |                         /*Finally the left truncation point is found*/ | 
		
	
		
			
				|  |  |  |  |  |                         pFG->left = (int)floor(m - k*sqrt(lambda)- 1.5 ); | 
		
	
		
			
				|  |  |  |  |  |                         /* for small lambda the above calculation can yield negative truncation points, crop them here */ | 
		
	
		
			
				|  |  |  |  |  |                         if(pFG->left < 0) | 
		
	
		
			
				|  |  |  |  |  |                             pFG->left = 0; | 
		
	
		
			
				|  |  |  |  |  |                         /* perform underflow check */ | 
		
	
		
			
				|  |  |  |  |  |                         k_prime = k + 3.0 / (2.0 * sqrt_lambda); | 
		
	
		
			
				|  |  |  |  |  |                         /*We take the c_m_inf = 0.02935 / sqrt( m ), as for lambda >= 25 | 
		
	
		
			
				|  |  |  |  |  |                          c_m = 1 / ( sqrt( 2.0 * pi * m ) ) * exp( m - lambda - 1 / ( 12.0 * m ) ) => c_m_inf*/ | 
		
	
		
			
				|  |  |  |  |  |                         c_m_inf = 0.02935 / sqrt((double) m); | 
		
	
		
			
				|  |  |  |  |  |                         result = 0.0; | 
		
	
		
			
				|  |  |  |  |  |                         if( 0.0 < k_prime && k_prime <= sqrt_lambda / 2.0 ) | 
		
	
		
			
				|  |  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |  |                             result = c_m_inf * exp( - pow(k_prime,2.0) / 2.0 - pow(k_prime, 3.0) / (3.0 * sqrt_lambda) ); | 
		
	
		
			
				|  |  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |  |                         else | 
		
	
		
			
				|  |  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |  |                             if( k_prime <= sqrt( m + 1.0 ) / m ) | 
		
	
		
			
				|  |  |  |  |  |                             { | 
		
	
		
			
				|  |  |  |  |  |                                 double result_1 = c_m_inf * pow( | 
		
	
		
			
				|  |  |  |  |  |                                         1.0 - k_prime / sqrt((double) (m + 1)), | 
		
	
		
			
				|  |  |  |  |  |                                         k_prime * sqrt((double) (m + 1))); | 
		
	
		
			
				|  |  |  |  |  |                                 double result_2 = exp( - lambda ); | 
		
	
		
			
				|  |  |  |  |  |                                 /*Take the maximum*/ | 
		
	
		
			
				|  |  |  |  |  |                                 result = ( result_1 > result_2 ? result_1 : result_2); | 
		
	
		
			
				|  |  |  |  |  |                             } | 
		
	
		
			
				|  |  |  |  |  |                             else | 
		
	
		
			
				|  |  |  |  |  |                             { | 
		
	
		
			
				|  |  |  |  |  |                                 /*NOTE: It will be an underflow error*/; | 
		
	
		
			
				|  |  |  |  |  |                                 printf("ERROR: Fox-Glynn: lambda >= 25, underflow. The results are UNRELIABLE.\n"); | 
		
	
		
			
				|  |  |  |  |  |                             } | 
		
	
		
			
				|  |  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |  |                         if ( result * omega / ( 1.0e+10 * ( pFG->right - pFG->left ) ) <= tau ) | 
		
	
		
			
				|  |  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |  |                             printf("ERROR: Fox-Glynn: lambda >= 25, underflow. The results are UNRELIABLE.\n"); | 
		
	
		
			
				|  |  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /*We still have to perform an underflow check for the right truncation point when lambda >= 400*/ | 
		
	
		
			
				|  |  |  |  |  |                     if( lambda >= lambda_400 ) | 
		
	
		
			
				|  |  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |  |                         k_prime = k_rtp * sqrt_2 + 3.0 / (2.0 * sqrt_lambda); | 
		
	
		
			
				|  |  |  |  |  |                         /*We take the c_m_inf = 0.02935 / sqrt( m ), as for lambda >= 25 | 
		
	
		
			
				|  |  |  |  |  |                          c_m = 1 / ( sqrt( 2.0 * pi * m ) ) * exp( m - lambda - 1 / ( 12.0 * m ) ) => c_m_inf*/ | 
		
	
		
			
				|  |  |  |  |  |                         c_m_inf = 0.02935 / sqrt((double) m); | 
		
	
		
			
				|  |  |  |  |  |                         result = c_m_inf * exp( - pow( k_prime + 1.0 , 2.0 ) / 2.0 ); | 
		
	
		
			
				|  |  |  |  |  |                         if( result * omega / ( 1.0e+10 * ( pFG->right - pFG->left ) ) <= tau) | 
		
	
		
			
				|  |  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |  |                             printf("ERROR: Fox-Glynn: lambda >= 400, underflow. The results are UNRELIABLE.\n"); | 
		
	
		
			
				|  |  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  |                     /*Time to set the initial value for weights*/ | 
		
	
		
			
				|  |  |  |  |  |                     *pw_m = omega / ( 1.0e+10 * ( pFG->right - pFG->left ) ); | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     return true; | 
		
	
		
			
				|  |  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  | /***************************************************************************** | 
		
	
		
			
				|  |  |  |  |  | Name		: weighter | 
		
	
		
			
				|  |  |  |  |  | Role		: The WEIGHTER function from the Fox-Glynn algorithm | 
		
	
		
			
				|  |  |  |  |  | @param		: double lambda: (rate of uniformization)*(mission time) | 
		
	
		
			
				|  |  |  |  |  | @param		: double tau: underflow | 
		
	
		
			
				|  |  |  |  |  | @param		: double omega: overflow | 
		
	
		
			
				|  |  |  |  |  | @param		: double epsilon: error bound | 
		
	
		
			
				|  |  |  |  |  | @param		: FoxGlynn *: return by reference | 
		
	
		
			
				|  |  |  |  |  | @return		: TRUE if everything is fine, otherwise FALSE. | 
		
	
		
			
				|  |  |  |  |  |               This is the F parameter of Fox-Glynn finder function. | 
		
	
		
			
				|  |  |  |  |  | remark	    : | 
		
	
		
			
				|  |  |  |  |  | ******************************************************************************/ | 
		
	
		
			
				|  |  |  |  |  |                 static bool weighter(const double lambda, const double tau, const double omega, const double epsilon, FoxGlynn *pFG) | 
		
	
		
			
				|  |  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |  |                     static const double pi = 3.14159265358979323846264; | 
		
	
		
			
				|  |  |  |  |  |                     static const double lambda_25 = 25.0; | 
		
	
		
			
				|  |  |  |  |  |                     static const double lambda_400 = 40; | 
		
	
		
			
				|  |  |  |  |  |                     /*The magic m point*/ | 
		
	
		
			
				|  |  |  |  |  |                     const int m = (int)floor(lambda); | 
		
	
		
			
				|  |  |  |  |  |                     double w_m = 0; | 
		
	
		
			
				|  |  |  |  |  |                     int j, s, t; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     if( ! finder( m, lambda, tau, omega, epsilon, &w_m, pFG ) ) | 
		
	
		
			
				|  |  |  |  |  |                         return false; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /*Allocate space for weights*/ | 
		
	
		
			
				|  |  |  |  |  |                     pFG->weights = (double *) calloc((size_t) (pFG->right - pFG->left + 1), | 
		
	
		
			
				|  |  |  |  |  |                                                      sizeof(double)); | 
		
	
		
			
				|  |  |  |  |  |                     /*Set an initial weight*/ | 
		
	
		
			
				|  |  |  |  |  |                     pFG->weights[ m - pFG->left ] = w_m; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /*Fill the left side of the array*/ | 
		
	
		
			
				|  |  |  |  |  |                     for( j = m; j > pFG->left; j-- ) | 
		
	
		
			
				|  |  |  |  |  |                         pFG->weights[ ( j - pFG->left ) - 1  ] = ( j / lambda ) * pFG->weights[ j - pFG->left ]; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /*Fill the right side of the array, have two cases lambda < 400 & lambda >= 400*/ | 
		
	
		
			
				|  |  |  |  |  |                     if( lambda < lambda_400 ) | 
		
	
		
			
				|  |  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |  |                         /*Perform the underflow check, according to Fox-Glynn*/ | 
		
	
		
			
				|  |  |  |  |  |                         if( pFG->right > 600 ) | 
		
	
		
			
				|  |  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |  |                             printf("ERROR: Fox-Glynn: pFG->right > 600, underflow is possible\n"); | 
		
	
		
			
				|  |  |  |  |  |                             return false; | 
		
	
		
			
				|  |  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |  |                         /*Compute weights*/ | 
		
	
		
			
				|  |  |  |  |  |                         for( j = m; j < pFG->right; j++ ) | 
		
	
		
			
				|  |  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |  |                             double q = lambda / ( j + 1 ); | 
		
	
		
			
				|  |  |  |  |  |                             if( pFG->weights[ j - pFG->left ] > tau / q ) | 
		
	
		
			
				|  |  |  |  |  |                             { | 
		
	
		
			
				|  |  |  |  |  |                                 pFG->weights[ ( j - pFG->left ) + 1  ] = q * pFG->weights[ j - pFG->left ]; | 
		
	
		
			
				|  |  |  |  |  |                             }else{ | 
		
	
		
			
				|  |  |  |  |  |                                 pFG->right = j; | 
		
	
		
			
				|  |  |  |  |  |                                 break; /*It's time to compute W*/ | 
		
	
		
			
				|  |  |  |  |  |                             } | 
		
	
		
			
				|  |  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |  |                     }else{ | 
		
	
		
			
				|  |  |  |  |  |                         /*Compute weights*/ | 
		
	
		
			
				|  |  |  |  |  |                         for( j = m; j < pFG->right; j++ ) | 
		
	
		
			
				|  |  |  |  |  |                             pFG->weights[ ( j - pFG->left ) + 1  ] = ( lambda / ( j + 1 ) ) * pFG->weights[ j - pFG->left ]; | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /*It is time to compute the normalization weight W*/ | 
		
	
		
			
				|  |  |  |  |  |                     pFG->total_weight = 0.0; | 
		
	
		
			
				|  |  |  |  |  |                     s = pFG->left; | 
		
	
		
			
				|  |  |  |  |  |                     t = pFG->right; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     while( s < t ) | 
		
	
		
			
				|  |  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |  |                         if( pFG->weights[ s - pFG->left ] <= pFG->weights[ t - pFG->left ] ) | 
		
	
		
			
				|  |  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |  |                             pFG->total_weight += pFG->weights[ s - pFG->left ]; | 
		
	
		
			
				|  |  |  |  |  |                             s++; | 
		
	
		
			
				|  |  |  |  |  |                         }else{ | 
		
	
		
			
				|  |  |  |  |  |                             pFG->total_weight += pFG->weights[ t - pFG->left ]; | 
		
	
		
			
				|  |  |  |  |  |                             t--; | 
		
	
		
			
				|  |  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  |                     pFG->total_weight += pFG->weights[ s - pFG->left ]; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     /* printf("Fox-Glynn: ltp = %d, rtp = %d, w = %10.15le \n", pFG->left, pFG->right, pFG->total_weight); */ | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     return true; | 
		
	
		
			
				|  |  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  | /***************************************************************************** | 
		
	
		
			
				|  |  |  |  |  | Name		: fox_glynn | 
		
	
		
			
				|  |  |  |  |  | Role		: get poisson probabilities. | 
		
	
		
			
				|  |  |  |  |  | @param		: double lambda: (rate of uniformization)*(mission time) | 
		
	
		
			
				|  |  |  |  |  | @param		: double tau: underflow | 
		
	
		
			
				|  |  |  |  |  | @param		: double omega: overflow | 
		
	
		
			
				|  |  |  |  |  | @param		: double epsilon: error bound | 
		
	
		
			
				|  |  |  |  |  | @param		: FoxGlynn **: return a new FoxGlynn structure by reference | 
		
	
		
			
				|  |  |  |  |  | @return	: TRUE if it worked fine, otherwise false | 
		
	
		
			
				|  |  |  |  |  | remark		: | 
		
	
		
			
				|  |  |  |  |  | ******************************************************************************/ | 
		
	
		
			
				|  |  |  |  |  |                 static bool fox_glynn(const double lambda, const double tau, const double omega, const double epsilon, FoxGlynn **ppFG) | 
		
	
		
			
				|  |  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |  |                     /* printf("Fox-Glynn: lambda = %3.3le, epsilon = %1.8le\n",lambda, epsilon); */ | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     *ppFG = (FoxGlynn *) calloc((size_t) 1, sizeof(FoxGlynn)); | 
		
	
		
			
				|  |  |  |  |  |                     (*ppFG)->weights = NULL; | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                     return weighter(lambda, tau, omega, epsilon, *ppFG); | 
		
	
		
			
				|  |  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  | /** | 
		
	
		
			
				|  |  |  |  |  | * Fries the memory allocated for the FoxGlynn structure | 
		
	
		
			
				|  |  |  |  |  | * @param fg the structure to free | 
		
	
		
			
				|  |  |  |  |  | */ | 
		
	
		
			
				|  |  |  |  |  |                 static void freeFG(FoxGlynn * fg) | 
		
	
		
			
				|  |  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |  |                     if( fg ){ | 
		
	
		
			
				|  |  |  |  |  |                         if( fg->weights ) | 
		
	
		
			
				|  |  |  |  |  |                             free(fg->weights); | 
		
	
		
			
				|  |  |  |  |  |                         free(fg); | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |                 /*! | 
		
	
		
			
				|  |  |  |  |  |                  * Computes the poission-distribution | 
		
	
		
			
				|  |  |  |  |  |                  * | 
		
	
		
			
				|  |  |  |  |  |                  * | 
		
	
		
			
				|  |  |  |  |  |                  * @param parameter lambda to use | 
		
	
		
			
				|  |  |  |  |  |                  * @param point i | 
		
	
		
			
				|  |  |  |  |  |                  * TODO: replace with Fox-Lynn | 
		
	
		
			
				|  |  |  |  |  |                  * @return the probability | 
		
	
		
			
				|  |  |  |  |  |                  */ | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  |                 /*! |  |  |                 /*! | 
		
	
		
			
				|  |  |                  * Computes the poission-distribution |  |  |                  * Computes the poission-distribution | 
		
	
		
			
				|  |  |                  * |  |  |                  * | 
		
	
	
		
			
				|  | @ -100,7 +415,7 @@ namespace storm { | 
		
	
		
			
				|  |  |                  * |  |  |                  * | 
		
	
		
			
				|  |  |                  */ |  |  |                  */ | 
		
	
		
			
				|  |  |                 template <typename ValueType, typename std::enable_if<storm::NumberTraits<ValueType>::SupportsExponential, int>::type=0> |  |  |                 template <typename ValueType, typename std::enable_if<storm::NumberTraits<ValueType>::SupportsExponential, int>::type=0> | 
		
	
		
			
				|  |  |                 static void calculateVu(std::vector<std::vector<ValueType>> const& relativeReachability, OptimizationDirection dir, uint64_t k, uint64_t node, uint64_t const kind, ValueType lambda, uint64_t probSize, std::vector<std::vector<std::vector<ValueType>>>& unifVectors, storm::storage::SparseMatrix<ValueType> const& fullTransitionMatrix, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> const& solver, std::ofstream& logfile); |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                 static void calculateVu(std::vector<std::vector<ValueType>> const& relativeReachability, OptimizationDirection dir, uint64_t k, uint64_t node, uint64_t const kind, ValueType lambda, uint64_t probSize, std::vector<std::vector<std::vector<ValueType>>>& unifVectors, storm::storage::SparseMatrix<ValueType> const& fullTransitionMatrix, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> const& solver, std::ofstream& logfile, std::vector<double> poisson); | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
	
		
			
				|  | 
 |