Beispiel #1
0
        /// <summary>
        /// Computes GammaLower(a, r*u) - GammaLower(a, r*l) to high accuracy.
        /// </summary>
        /// <param name="shape"></param>
        /// <param name="rate"></param>
        /// <param name="lowerBound"></param>
        /// <param name="upperBound"></param>
        /// <param name="regularized"></param>
        /// <returns></returns>
        public static double GammaProbBetween(double shape, double rate, double lowerBound, double upperBound, bool regularized = true)
        {
            double rl = rate * lowerBound;
            // Use the criterion from Gautschi (1979) to determine whether GammaLower(a,x) or GammaUpper(a,x) is smaller.
            bool lowerIsSmaller;

            if (rl > 0.25)
            {
                lowerIsSmaller = (shape > rl + 0.25);
            }
            else
            {
                lowerIsSmaller = (shape > -MMath.Ln2 / Math.Log(rl));
            }
            if (!lowerIsSmaller)
            {
                double logl = Math.Log(lowerBound);
                if (rate * upperBound < 1e-16 && shape < -1e-16 / (Math.Log(rate) + logl))
                {
                    double logu = Math.Log(upperBound);
                    return(shape * (logu - logl));
                }
                else
                {
                    // This is inaccurate when lowerBound is close to upperBound.  In that case, use a Taylor expansion of lowerBound around upperBound.
                    return(MMath.GammaUpper(shape, rl, regularized) - MMath.GammaUpper(shape, rate * upperBound, regularized));
                }
            }
            else
            {
                double diff = MMath.GammaLower(shape, rate * upperBound) - MMath.GammaLower(shape, rl);
                return(regularized ? diff : (MMath.Gamma(shape) * diff));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Computes <c>GammaUpper(s,x)/(x^(s-1)*exp(-x)) - 1</c> to high accuracy
        /// </summary>
        /// <param name="s"></param>
        /// <param name="x">A real number gt;= 45 and gt; <paramref name="s"/>/0.99</param>
        /// <param name="regularized"></param>
        /// <returns></returns>
        public static double GammaUpperRatio(double s, double x, bool regularized = true)
        {
            if (s >= x * 0.99)
            {
                throw new ArgumentOutOfRangeException(nameof(s), s, "s >= x*0.99");
            }
            if (x < 45)
            {
                throw new ArgumentOutOfRangeException(nameof(x), x, "x < 45");
            }
            double term = (s - 1) / x;
            double sum  = term;

            for (int i = 2; i < 1000; i++)
            {
                term *= (s - i) / x;
                double oldSum = sum;
                sum += term;
                if (MMath.AreEqual(sum, oldSum))
                {
                    return(regularized ? sum / MMath.Gamma(s) : sum);
                }
            }
            throw new Exception($"GammaUpperRatio not converging for s={s:g17}, x={x:g17}, regularized={regularized}");
        }
Beispiel #3
0
        private static void VarianceGammaTimesGaussianMoments(double a, double m, double v, out double sum, out double moment1, out double moment2)
        {
            int    n          = 1000000;
            double lowerBound = -20;
            double upperBound = 20;
            double range      = upperBound - lowerBound;

            sum = 0;
            double sumx = 0, sumx2 = 0;

            for (int i = 0; i < n; i++)
            {
                double x    = range * i / (n - 1) + lowerBound;
                double absx = System.Math.Abs(x);
                double diff = x - m;
                double logp = -0.5 * diff * diff / v - absx;
                double p    = System.Math.Exp(logp);
                if (a == 1)
                { // do nothing
                }
                else if (a == 2)
                {
                    p *= 1 + absx;
                }
                else if (a == 3)
                {
                    p *= 3 + 3 * absx + absx * absx;
                }
                else if (a == 4)
                {
                    p *= 15 + 15 * absx + 6 * absx * absx + absx * absx * absx;
                }
                else
                {
                    throw new ArgumentException("a is not in {1,2,3,4}");
                }
                sum   += p;
                sumx  += x * p;
                sumx2 += x * x * p;
            }
            moment1 = sumx / sum;
            moment2 = sumx2 / sum;
            sum    /= MMath.Gamma(a) * System.Math.Pow(2, a);
            sum    /= MMath.Sqrt2PI * System.Math.Sqrt(v);
            double inc = range / (n - 1);

            sum *= inc;
        }
Beispiel #4
0
 public static double[] xBesselKDerivativesAt0(int n, double a)
 {
     double[] derivs = new double[n + 1];
     derivs[0] = MMath.Gamma(System.Math.Abs(a)) * System.Math.Pow(2, a - 0.5) / System.Math.Sqrt(System.Math.PI);
     if (n > 0)
     {
         derivs[1] = derivs[0];
         if (n > 1)
         {
             double[] derivs2 = xBesselKDerivativesAt0(n - 2, a - 1);
             for (int i = 0; i < n - 2; i++)
             {
                 derivs[i + 2] = derivs[i + 1] - (i + 1) * derivs2[i];
             }
         }
     }
     return(derivs);
 }
Beispiel #5
0
        public void VarianceGammaTimesGaussianIntegralTest()
        {
            double logZ, mu, vu;

            GaussianFromMeanAndVarianceOp.LaplacianTimesGaussianMoments(-100, 1, out logZ, out mu, out vu);
            Console.WriteLine(logZ);
            //GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianMoments5(1, 1000, 1, out mu, out vu);
            Console.WriteLine(mu);
            Console.WriteLine(vu);
            double[][] vgmoments = GaussianFromMeanAndVarianceOp.NormalVGMomentRatios(10, 1, -6, 1);
            for (int i = 0; i < 10; i++)
            {
                double f = MMath.NormalCdfMomentRatio(i, -6) * MMath.Gamma(i + 1);
                Console.WriteLine("R({0}) = {1}, Zp = {2}", i, f, vgmoments[0][i]);
            }

            // true values computed by tex/factors/matlab/test_variance_gamma2.m
            double scale = 2 * System.Math.Exp(-Gaussian.GetLogProb(2 / System.Math.Sqrt(3), 0, 1));

            Assert.True(MMath.AbsDiff(0.117700554409044, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1, 2, 3) / scale, 1e-20) < 1e-5);
            Assert.True(MMath.AbsDiff(0.112933034747473, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(2, 2, 3) / scale, 1e-20) < 1e-5);
            Assert.True(MMath.AbsDiff(0.117331854901251, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.1, 2, 3) / scale, 1e-20) < 1e-5);
            Assert.True(MMath.AbsDiff(0.115563913123152, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.5, 2, 3) / scale, 1e-20) < 2e-5);

            scale = 2 * System.Math.Exp(-Gaussian.GetLogProb(20 / System.Math.Sqrt(0.3), 0, 1));
            Assert.True(MMath.AbsDiff(1.197359429038085e-009, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1, 20, 0.3) / scale, 1e-20) < 1e-5);
            Assert.True(MMath.AbsDiff(1.239267009054433e-008, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(2, 20, 0.3) / scale, 1e-20) < 1e-5);
            Assert.True(MMath.AbsDiff(1.586340098271600e-009, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.1, 20, 0.3) / scale, 1e-20) < 1e-4);
            Assert.True(MMath.AbsDiff(4.319412089896069e-009, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.5, 20, 0.3) / scale, 1e-20) < 1e-4);

            scale = 2 * System.Math.Exp(-Gaussian.GetLogProb(40 / System.Math.Sqrt(0.3), 0, 1));
            scale = 2 * System.Math.Exp(40 - 0.3 / 2);
            Assert.True(MMath.AbsDiff(2.467941724509690e-018, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1, 40, 0.3) / scale, 1e-20) < 1e-5);
            Assert.True(MMath.AbsDiff(5.022261409377230e-017, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(2, 40, 0.3) / scale, 1e-20) < 1e-5);
            Assert.True(MMath.AbsDiff(3.502361147666615e-018, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.1, 40, 0.3) / scale, 1e-20) < 1e-4);
            Assert.True(MMath.AbsDiff(1.252310352551344e-017, GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.5, 40, 0.3) / scale, 1e-20) < 1e-4);

            Assert.True(GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.138, 33.4, 0.187) > 0);
            Assert.True(GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.138, -33.4, 0.187) > 0);
            Assert.True(GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.138, 58.25, 0.187) > 0);
            Assert.True(GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.138, 50, 0.187) > 0);
            Assert.True(GaussianFromMeanAndVarianceOp.VarianceGammaTimesGaussianIntegral(1.138, 100, 0.187) > 0);
        }
 // returns int_0^Inf x^n VG(x;a) N(x;m,v) dx / (0.5*N(m;0,1))
 public static double NormalVGMomentRatio(int n, int a, double m, double v)
 {
     if (a < 1)
     {
         throw new ArgumentException("a < 1", "a");
     }
     if (a == 1)
     {
         double sqrtV = Math.Sqrt(v);
         return(MMath.Gamma(n + 1) * MMath.NormalCdfMomentRatio(n, m / sqrtV) * Math.Pow(sqrtV, n));
     }
     else if (a == 2)
     {
         double sqrtV = Math.Sqrt(v);
         return(0.5 * NormalVGMomentRatio(n, 1, m, v) + 0.5 * MMath.Gamma(n + 2) * MMath.NormalCdfMomentRatio(n + 1, m / sqrtV) * Math.Pow(sqrtV, n + 1));
     }
     else                 // a > 2
     {
         return(0.25 / ((a - 2) * (a - 1)) * NormalVGMomentRatio(n + 2, a - 2, m, v) + (a - 1.5) / (a - 1) * NormalVGMomentRatio(n, a - 1, m, v));
     }
 }
        /// <summary>
        /// Computes int_0^Inf x^n N(x;m,v) dx / N(m/sqrt(v);0,1)
        /// </summary>
        /// <param name="nMax"></param>
        /// <param name="m"></param>
        /// <param name="v"></param>
        /// <returns></returns>
        public static double[] NormalCdfMomentRatios(int nMax, double m, double v)
        {
            double[] result = new double[nMax + 1];
            double   sqrtV  = Math.Sqrt(v);

            for (int i = 0; i <= nMax; i++)
            {
                // NormalCdfMomentRatio(0,37.66) = infinity
                result[i] = MMath.NormalCdfMomentRatio(i, m / sqrtV) * Math.Pow(sqrtV, i) * MMath.Gamma(i + 1);
            }
            return(result);
        }