예제 #1
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="PowerOp"]/message_doc[@name="XAverageConditional(Pareto, Gamma, double)"]/*'/>
        public static Gamma XAverageConditional(Pareto pow, Gamma x, double y)
        {
            // factor is delta(pow - x^y)
            // marginal for x is Pareto(x^y; s,L) Ga(x; a,b)
            // =propto x^(a-1-y(s+1)) exp(-bx)   for x >= L^(1/y)
            // we can compute moments via the incomplete Gamma function.
            // change variables to: z=bx,  dz=b dx
            // int_LL^inf x^(c-1) exp(-bx) dx = int_(bLL)^inf z^(c-1)/b^c exp(-z) dz = gammainc(c,bLL,inf)/b^c
            double lowerBound = System.Math.Pow(pow.LowerBound, 1 / y);
            double b = x.Rate;
            double c = x.Shape - y * (pow.Shape + 1);
            double bL = b * lowerBound;
            double m, m2;

            if (y > 0)
            {
                // note these ratios can be simplified
                double z = MMath.GammaUpper(c, bL);
                m  = MMath.GammaUpper(c + 1, bL) * c / z / b;
                m2 = MMath.GammaUpper(c + 2, bL) * c * (c + 1) / z / (b * b);
            }
            else
            {
                double z = MMath.GammaLower(c, bL);
                m  = MMath.GammaLower(c + 1, bL) * c / z / b;
                m2 = MMath.GammaLower(c + 2, bL) * c * (c + 1) / z / (b * b);
            }
            double v      = m2 - m * m;
            Gamma  xPost  = Gamma.FromMeanAndVariance(m, v);
            Gamma  result = new Gamma();

            result.SetToRatio(xPost, x, true);
            return(result);
        }
예제 #2
0
 /// <summary>
 /// Get the mean and variance after truncation.
 /// </summary>
 /// <param name="mean"></param>
 /// <param name="variance"></param>
 public void GetMeanAndVariance(out double mean, out double variance)
 {
     if (this.Gamma.IsPointMass)
     {
         mean     = this.Gamma.Point;
         variance = 0.0;
     }
     else if (!IsProper())
     {
         throw new ImproperDistributionException(this);
     }
     else
     {
         double Z = GetNormalizer();
         if (Z == 0)
         {
             mean     = Math.Min(UpperBound, Math.Max(LowerBound, this.Gamma.GetMean()));
             variance = 0.0;
             return;
         }
         double m   = this.Gamma.Shape / this.Gamma.Rate;
         double sum = m * (MMath.GammaLower(this.Gamma.Shape + 1, this.Gamma.Rate * UpperBound) - MMath.GammaLower(this.Gamma.Shape + 1, this.Gamma.Rate * LowerBound));
         mean = sum / Z;
         double sum2 = m * (this.Gamma.Shape + 1) / this.Gamma.Rate * (MMath.GammaLower(this.Gamma.Shape + 2, this.Gamma.Rate * UpperBound) - MMath.GammaLower(this.Gamma.Shape + 2, this.Gamma.Rate * LowerBound));
         variance = sum2 / Z - mean * mean;
     }
 }
예제 #3
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="IsGreaterThanOp"]/message_doc[@name="IsGreaterThanAverageConditional(Poisson, int)"]/*'/>
 public static Bernoulli IsGreaterThanAverageConditional([Proper] Poisson a, int b)
 {
     if (a.IsPointMass)
     {
         return(Bernoulli.PointMass(a.Point > b));
     }
     if (a.Precision == 1)
     {
         if (b < 0)
         {
             return(Bernoulli.PointMass(true));
         }
         else
         {
             return(new Bernoulli(MMath.GammaLower(b + 1, a.Rate)));
         }
     }
     else
     {
         double sum = 0;
         for (int i = 0; i <= b; i++)
         {
             sum += Math.Exp(a.GetLogProb(i));
         }
         if (sum > 1)
         {
             sum = 1; // this can happen due to round-off errors
         }
         return(new Bernoulli(1 - sum));
     }
 }
예제 #4
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));
            }
        }
예제 #5
0
 /// <summary>
 /// Computes E[x^power]
 /// </summary>
 /// <returns></returns>
 public double GetMeanPower(double power)
 {
     if (power == 0.0)
     {
         return(1.0);
     }
     else if (IsPointMass)
     {
         return(Math.Pow(Point, power));
     }
     //else if (Rate == 0.0) return (power > 0) ? Double.PositiveInfinity : 0.0;
     else if (!IsProper())
     {
         throw new ImproperDistributionException(this);
     }
     else if (this.Gamma.Shape <= -power && LowerBound == 0)
     {
         throw new ArgumentException("Cannot compute E[x^" + power + "] for " + this + " (shape <= " + (-power) + ")");
     }
     else
     {
         double Z = GetNormalizer();
         double shapePlusPower = this.Gamma.Shape + power;
         double Z1;
         bool   regularized = shapePlusPower >= 1;
         if (regularized)
         {
             Z1 = Math.Exp(MMath.GammaLn(shapePlusPower) - MMath.GammaLn(this.Gamma.Shape)) *
                  (MMath.GammaLower(shapePlusPower, this.Gamma.Rate * UpperBound) - MMath.GammaLower(shapePlusPower, this.Gamma.Rate * LowerBound));
         }
         else
         {
             Z1 = Math.Exp(-MMath.GammaLn(this.Gamma.Shape)) *
                  (MMath.GammaUpper(shapePlusPower, this.Gamma.Rate * LowerBound, regularized) - MMath.GammaUpper(shapePlusPower, this.Gamma.Rate * UpperBound, regularized));
         }
         return(Math.Pow(this.Gamma.Rate, -power) * Z1 / Z);
     }
 }
예제 #6
0
파일: Gamma.cs 프로젝트: 0xCM/arrows
 /// <summary>
 /// Compute the probability that a sample from this distribution is less than x.
 /// </summary>
 /// <param name="x">Any real number.</param>
 /// <returns>The cumulative gamma distribution at <paramref name="x"/></returns>
 public double GetProbLessThan(double x)
 {
     if (x < 0.0)
     {
         return(0.0);
     }
     else if (double.IsPositiveInfinity(x))
     {
         return(1.0);
     }
     else if (this.IsPointMass)
     {
         return((this.Point < x) ? 1.0 : 0.0);
     }
     else if (this.IsUniform())
     {
         throw new ImproperDistributionException(this);
     }
     else
     {
         return(MMath.GammaLower(Shape, x * Rate));
     }
 }
예제 #7
0
 /// <summary>
 /// Returns the mean (first moment) of the distribution
 /// </summary>
 /// <returns></returns>
 public double GetMean()
 {
     if (this.Gamma.IsPointMass)
     {
         return(this.Gamma.Point);
     }
     else if (!IsProper())
     {
         throw new ImproperDistributionException(this);
     }
     else
     {
         double Z = GetNormalizer();
         if (Z == 0)
         {
             double mean = this.Gamma.GetMean();
             return(Math.Min(UpperBound, Math.Max(LowerBound, mean)));
         }
         // if Z is not zero, then Z1 cannot be zero.
         double Z1  = MMath.GammaLower(this.Gamma.Shape + 1, this.Gamma.Rate * UpperBound) - MMath.GammaLower(this.Gamma.Shape + 1, this.Gamma.Rate * LowerBound);
         double sum = this.Gamma.Shape / this.Gamma.Rate * Z1;
         return(sum / Z);
     }
 }