| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -57,7 +57,7 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            private: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                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> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                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> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                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 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 * | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -100,7 +415,7 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 * | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                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); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |