示例#1
0
 /// <summary>
 /// Gets log normalizer
 /// </summary>
 /// <returns></returns>
 public double GetLogNormalizer()
 {
     if (IsProper() && !IsPointMass)
     {
         return(MMath.GammaLn(Shape) - Shape * Math.Log(Rate));
     }
     else
     {
         return(0.0);
     }
 }
示例#2
0
 /// <summary>
 /// Gets log normalizer
 /// </summary>
 /// <returns></returns>
 public double GetLogNormalizer()
 {
     if (IsProper())
     {
         return(MMath.GammaLn(Shape) - Shape * Math.Log(Rate) + Math.Log(Math.Abs(Power)));
     }
     else
     {
         return(0.0);
     }
 }
示例#3
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="WishartFromShapeAndRateOp"]/message_doc[@name="LogAverageFactor(PositiveDefiniteMatrix, double, Wishart)"]/*'/>
        public static double LogAverageFactor(PositiveDefiniteMatrix sample, double shape, Wishart rate)
        {
            // f(X,a,B) = |X|^(a-c) |B|^a/Gamma_d(a) exp(-tr(BX)) = |X|^(-2c) Gamma_d(a+c)/Gamma_d(a) W(B; a+c, X)
            // p(B) = |B|^(a'-c) |B'|^(a')/Gamma_d(a') exp(-tr(BB'))
            // int_B f p(B) dB = |X|^(a-c) Gamma_d(a+a')/Gamma_d(a)/Gamma_d(a') |B'|^(a') |B'+X|^(-(a+a'))
            int     dimension = sample.Rows;
            double  c         = 0.5 * (dimension + 1);
            Wishart to_rate   = new Wishart(dimension);

            to_rate = RateAverageConditional(sample, shape, to_rate);
            return(rate.GetLogAverageOf(to_rate) - 2 * c * sample.LogDeterminant() + MMath.GammaLn(shape + c, dimension) - MMath.GammaLn(shape, dimension));
        }
示例#4
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MultinomialOp"]/message_doc[@name="LogAverageFactor(IList{int}, int, Dirichlet)"]/*'/>
        public static double LogAverageFactor(IList <int> sample, int trialCount, Dirichlet p)
        {
            double result = MMath.GammaLn(trialCount + 1);

            for (int i = 0; i < sample.Count; i++)
            {
                result += MMath.GammaLn(sample[i] + p.PseudoCount[i]) + MMath.GammaLn(p.PseudoCount[i])
                          - MMath.GammaLn(sample[i] + 1);
            }
            result += MMath.GammaLn(p.TotalCount) - MMath.GammaLn(p.TotalCount + trialCount);
            return(result);
        }
示例#5
0
 public double GetLogProb(int value)
 {
     if (value < 0 || value > TrialCount)
     {
         return(double.NegativeInfinity);
     }
     if (IsPointMass)
     {
         return((value == Point) ? 1.0 : 0.0);
     }
     return(MMath.GammaLn(TrialCount + 1) - A * MMath.GammaLn(value + 1) - B * MMath.GammaLn(TrialCount - value + 1) + value * LogOdds + TrialCount * MMath.LogisticLn(-LogOdds));
 }
示例#6
0
        /// <summary>
        /// Logarithm of the Gamma density function.
        /// </summary>
        /// <param name="x">Where to evaluate the density</param>
        /// <param name="shape">Shape parameter</param>
        /// <param name="rate">Rate parameter</param>
        /// <returns>log(Gamma(x;shape,rate))</returns>
        /// <remarks>
        /// The distribution is <c>p(x) = x^(a-1)*exp(-x*b)*b^a/Gamma(a)</c>.
        /// When a &lt;= 0 or b &lt;= 0 the <c>b^a/Gamma(a)</c> term is dropped.
        /// Thus if shape = 1 and rate = 0 the density is 1.
        /// </remarks>
        public static double GetLogProb(double x, double shape, double rate)
        {
            if (x < 0)
            {
                return(double.NegativeInfinity);
            }
            if (x > double.MaxValue) // Avoid subtracting infinities below
            {
                if (rate > 0)
                {
                    return(-x);
                }
                else if (rate < 0)
                {
                    return(x);
                }
                // fall through when rate == 0
            }
            if (shape > 1e10 && IsProper(shape, rate))
            {
                // In double precision, we can assume GammaLn(x) = (x-0.5)*log(x) - x for x > 1e10
                // Also log(1-1/x) = -1/x - 0.5/x^2  for x > 1e10
                // We compute the density in a way that ensures the maximum is at the mode returned by GetMode.
                double mode      = (shape - 1) / rate; // cannot be zero
                double xOverMode = x / mode;
                if (xOverMode > double.MaxValue)
                {
                    return(double.NegativeInfinity);
                }
                else
                {
                    return((shape - 1) * (Math.Log(xOverMode) + (1 - xOverMode)) + (0.5 + 0.5 / shape) / shape + Math.Log(rate) - 0.5 * Math.Log(shape));
                }
            }
            double result = 0;

            if (shape != 1)
            {
                result += (shape - 1) * Math.Log(x);
            }
            if (rate != 0 && x != 0)
            {
                result -= x * rate;
            }
            if (IsProper(shape, rate))
            {
                result += shape * Math.Log(rate) - MMath.GammaLn(shape);
            }
            return(result);
        }
示例#7
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="BinomialOp"]/message_doc[@name="LogAverageFactor(int, Beta, int)"]/*'/>
        public static double LogAverageFactor(int sample, Beta p, int trialCount)
        {
            if (trialCount < sample)
            {
                return(double.NegativeInfinity);
            }
            double a = p.TrueCount;
            double b = p.FalseCount;

            return(MMath.ChooseLn(trialCount, sample) +
                   MMath.GammaLn(a + sample) - MMath.GammaLn(a) +
                   MMath.GammaLn(b + trialCount - sample) - MMath.GammaLn(b) +
                   MMath.GammaLn(a + b) - MMath.GammaLn(a + b + trialCount));
        }
示例#8
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="WishartFromShapeAndRateOp_Laplace2"]/message_doc[@name="LogAverageFactor(Wishart, double, Wishart, Wishart)"]/*'/>
        public static double LogAverageFactor(Wishart sample, double shape, Wishart rate, [Fresh] Wishart to_sample)
        {
            // int_R f(Y,R) p(R) dR = |Y|^(a-c) |Y+B_r|^-(a+a_r) Gamma_d(a+a_r)/Gamma_d(a)/Gamma_d(a_r) |B_r|^a_r
            int     dim                    = sample.Dimension;
            double  c                      = 0.5 * (dim + 1);
            double  shape2                 = shape + rate.Shape;
            Wishart samplePost             = sample * to_sample;
            PositiveDefiniteMatrix y       = samplePost.GetMean();
            PositiveDefiniteMatrix yPlusBr = y + rate.Rate;
            double result                  = (shape - c) * y.LogDeterminant() - shape2 * yPlusBr.LogDeterminant() + sample.GetLogProb(y) - samplePost.GetLogProb(y);

            result += MMath.GammaLn(shape2, dim) - MMath.GammaLn(shape, dim) - MMath.GammaLn(rate.Shape, dim);
            result += rate.Shape * rate.Rate.LogDeterminant();
            return(result);
        }
示例#9
0
 /// <summary>
 /// Computes (sum_{x=0..infinity} log(x!) Rate^x / x!^Precision) / (sum_{x=0..infinity} Rate^x / x!^Precision )
 /// </summary>
 /// <returns></returns>
 public double GetMeanLogFactorial()
 {
     if (IsPointMass)
     {
         return(MMath.GammaLn(Point + 1));
     }
     else if (!IsProper())
     {
         throw new ImproperDistributionException(this);
     }
     else
     {
         return(GetSumLogFactorial(Rate, Precision) / Math.Exp(GetLogNormalizer(Rate, Precision)));
     }
 }
示例#10
0
        public static double NormalCdfMomentDyRatio(int n, double x, double y, double r)
        {
            double omr2 = 1 - r * r;

            if (omr2 == 0)
            {
                throw new ArgumentException();
            }
            else
            {
                double diff = (x - r * y) / System.Math.Sqrt(omr2);
                //return Math.Exp(MMath.GammaLn(n + 1) + 0.5 * n * Math.Log(omr2)) * MMath.NormalCdfMomentRatio(n, diff);
                return(System.Math.Exp(MMath.GammaLn(n + 1) + 0.5 * n * System.Math.Log(omr2) + System.Math.Log(MMath.NormalCdfMomentRatio(n, diff))));
            }
        }
示例#11
0
        /// <summary>
        /// Logarithm of the density function.
        /// </summary>
        /// <param name="x">Where to evaluate the density</param>
        /// <param name="shape">Shape parameter</param>
        /// <param name="rate">Rate parameter</param>
        /// <param name="power">Power parameter</param>
        /// <returns>log(GammaPower(x;shape,rate,power))</returns>
        /// <remarks>
        /// The distribution is <c>p(x) = x^(a/c-1)*exp(-b*x^(1/c))*b^a/Gamma(a)/abs(c)</c>.
        /// When a &lt;= 0 or b &lt;= 0 or c = 0 the <c>b^a/Gamma(a)/abs(c)</c> term is dropped.
        /// Thus if shape = 1 and rate = 0 the density is 1.
        /// </remarks>
        public static double GetLogProb(double x, double shape, double rate, double power)
        {
            if (power == 0.0)
            {
                return((x == 1.0) ? 0.0 : Double.NegativeInfinity);
            }
            double invPower = 1.0 / power;
            double result   = (shape * invPower - 1) * Math.Log(x) - Math.Pow(x, invPower) * rate;

            if (IsProper(shape, rate))
            {
                result += shape * Math.Log(rate) - MMath.GammaLn(shape) - Math.Log(Math.Abs(power));
            }
            return(result);
        }
示例#12
0
        public static double NormalCdfMomentDy(int n, double x, double y, double r)
        {
            double omr2 = 1 - r * r;

            if (omr2 == 0)
            {
                return(System.Math.Pow(x - r * y, n) * System.Math.Exp(Gaussian.GetLogProb(y, 0, 1)));
            }
            else
            {
                double diff = (x - r * y) / System.Math.Sqrt(omr2);
                return(System.Math.Exp(MMath.GammaLn(n + 1) + Gaussian.GetLogProb(y, 0, 1)
                                       + Gaussian.GetLogProb(diff, 0, 1)
                                       + 0.5 * n * System.Math.Log(omr2)) * MMath.NormalCdfMomentRatio(n, diff));
            }
        }
        // returns (E[x],var(x)) where p(x) =propto VG(x;a) N(x;m,v).
        public static void VarianceGammaTimesGaussianMoments3(double a, double m, double v, out double mu, out double vu)
        {
            // compute weights
            // termMoments[i,j] is the ith moment of the jth term
            Matrix      termMoments  = new Matrix(nWeights, nWeights);
            DenseVector exactMoments = DenseVector.Constant(termMoments.Rows, 1.0);

            for (int i = 0; i < exactMoments.Count; i++)
            {
                // ii is half of the exponent
                int    ii        = i;
                double logMoment = MMath.GammaLn(ii + a) - MMath.GammaLn(a) - MMath.GammaLn(ii + 1);
                for (int j = 0; j < termMoments.Cols; j++)
                {
                    // jj is the term shape
                    int jj = j + 1;
                    termMoments[i, j] = Math.Exp(MMath.GammaLn(ii + jj) - MMath.GammaLn(ii + 1) - MMath.GammaLn(jj) - logMoment);
                }
            }
            //Console.WriteLine("exactMoments = {0}, termMoments = ", exactMoments);
            //Console.WriteLine(termMoments);
            (new LuDecomposition(termMoments)).Solve(exactMoments);
            DenseVector weights = exactMoments;

            Console.WriteLine("weights = {0}", weights);
            double Z0Plus = 0, Z1Plus = 0, Z2Plus = 0;
            double Z0Minus = 0, Z1Minus = 0, Z2Minus = 0;

            for (int j = 0; j < weights.Count; j++)
            {
                int jj = j + 1;
                Z0Plus  += weights[j] * NormalVGMomentRatio(0, jj, m - v, v);
                Z1Plus  += weights[j] * NormalVGMomentRatio(1, jj, m - v, v);
                Z2Plus  += weights[j] * NormalVGMomentRatio(2, jj, m - v, v);
                Z0Minus += weights[j] * NormalVGMomentRatio(0, jj, -m - v, v);
                Z1Minus += weights[j] * NormalVGMomentRatio(1, jj, -m - v, v);
                Z2Minus += weights[j] * NormalVGMomentRatio(2, jj, -m - v, v);
            }
            double Z0 = Z0Plus + Z0Minus;
            double Z1 = Z1Plus - Z1Minus;
            double Z2 = Z2Plus + Z2Minus;

            mu = Z1 / Z0;
            vu = Z2 / Z0 - mu * mu;
            //Console.WriteLine("mu = {0}, vu = {1}", mu, vu);
        }
        /// <summary>
        /// EP message to 'trialCount'
        /// </summary>
        /// <param name="sample">Constant value for 'sample'.</param>
        /// <param name="p">Incoming message from 'p'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'trialCount' as the random arguments are varied.
        /// The formula is <c>proj[p(trialCount) sum_(p) p(p) factor(sample,trialCount,p)]/p(trialCount)</c>.
        /// </para></remarks>
        public static Discrete TrialCountAverageConditional(int sample, Beta p, Discrete result)
        {
            if (p.IsPointMass)
            {
                return(TrialCountAverageConditional(sample, p.Point, result));
            }
            Vector probs = result.GetWorkspace();
            double a     = p.TrueCount;
            double b     = p.FalseCount;

            // p(n) = nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                probs[n] = Math.Exp(MMath.ChooseLn(n, sample) + MMath.GammaLn(b + n - sample) - MMath.GammaLn(a + b + n));
            }
            result.SetProbs(probs);
            return(result);
        }
示例#15
0
#pragma warning disable 162
#endif

        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MultinomialOp"]/message_doc[@name="AverageLogFactor(IList{int}, int, Dirichlet, Vector)"]/*'/>
        public static double AverageLogFactor(IList <int> sample, int trialCount, Dirichlet p, [Fresh] Vector MeanLog)
        {
            double result = MMath.GammaLn(trialCount + 1);

            if (true)
            {
                result += sample.Inner(MeanLog);
                result -= sample.ListSum(x => MMath.GammaLn(x + 1));
            }
            else
            {
                for (int i = 0; i < sample.Count; i++)
                {
                    result += sample[i] * MeanLog[i] - MMath.GammaLn(sample[i] + 1);
                }
            }
            return(result);
        }
示例#16
0
        internal static void GammaSpeedTest()
        {
            Stopwatch watch = new Stopwatch();

            MMath.GammaLn(0.1);
            MMath.GammaLn(3);
            MMath.GammaLn(20);
            for (int i = 0; i < 100; i++)
            {
                double x = (i + 1) * 0.1;
                watch.Restart();
                for (int trial = 0; trial < 1000; trial++)
                {
                    MMath.GammaLn(x);
                }
                watch.Stop();
                Console.WriteLine($"{x} {watch.ElapsedTicks}");
            }
        }
示例#17
0
        /// <summary>
        /// Gets the normalizer for a Wishart density function specified by shape and rate matrix
        /// </summary>
        /// <param name="shape">Shape parameter</param>
        /// <param name="rate">rate matrix</param>
        /// <returns></returns>
        public static double GetLogNormalizer(double shape, PositiveDefiniteMatrix rate)
        {
            int dimension = rate.Rows;

            // inline call to IsProper()
            if (!(shape > 0.5 * (dimension - 1)))
            {
                return(0.0);
            }
            LowerTriangularMatrix rateChol = new LowerTriangularMatrix(dimension, dimension);
            bool isPosDef = rateChol.SetToCholesky(rate);

            if (!isPosDef)
            {
                return(0.0);
            }
            // LogDeterminant(rate) = 2*L.TraceLn()
            return(MMath.GammaLn(shape, dimension) - shape * 2 * rateChol.TraceLn());
        }
示例#18
0
 /// <summary>
 /// Computes <c>log(n!!)</c> where n!! = n(n-2)(n-4)...2 (if n even) or n(n-2)...1 (if n odd)
 /// </summary>
 /// <param name="n">An integer &gt;= 0</param>
 /// <returns></returns>
 public static double DoubleFactorialLn(int n)
 {
     if (n < 0)
     {
         throw new ArgumentException("n < 0");
     }
     else if (n == 0)
     {
         return(0);
     }
     else if (n % 2 == 0)
     {
         int h = n / 2;
         return(h * System.Math.Log(2) + MMath.GammaLn(h + 1));
     }
     else
     {
         int h = (n + 1) / 2;
         return(h * System.Math.Log(2) + MMath.GammaLn(h + 0.5) - MMath.GammaLn(0.5));
     }
 }
示例#19
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);
     }
 }
示例#20
0
文件: Gamma.cs 项目: 0xCM/arrows
 /// <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 (Shape <= -power)
     {
         throw new ArgumentException("Cannot compute E[x^" + power + "] for " + this + " (shape <= " + (-power) + ")");
     }
     else
     {
         return(Math.Exp(MMath.GammaLn(Shape + power) - MMath.GammaLn(Shape) - power * Math.Log(Rate)));
     }
 }
示例#21
0
 /// <summary>
 /// Evaluates the log of of the density function of this COM-Poisson at the given value
 /// </summary>
 /// <param name="value">The value at which to calculate the density</param>
 /// <returns>log p(x=value)</returns>
 /// <remarks>
 /// The formula for the distribution is <c>p(x) = rate^x exp(-rate) / x!</c>
 /// when nu=1.  In the general case, it is <c>p(x) =propto rate^x / x!^nu</c>.
 /// If the distribution is improper, the normalizer is omitted.
 /// </remarks>
 public double GetLogProb(int value)
 {
     if (IsPointMass)
     {
         return((value == Point) ? 0.0 : Double.NegativeInfinity);
     }
     else if (value < 0)
     {
         return(Double.NegativeInfinity);
     }
     else if (IsUniform())
     {
         return(0.0);
     }
     else if (Precision == 1)
     {
         // we know that Rate > 0
         return(value * Math.Log(Rate) - MMath.GammaLn(value + 1) - Rate);
     }
     else
     {
         return(value * Math.Log(Rate) - Precision * MMath.GammaLn(value + 1) - GetLogNormalizer(Rate, Precision));
     }
 }
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="GammaPowerProductOp_Laplace"]/message_doc[@name="LogAverageFactor(GammaPower, GammaPower, GammaPower, Gamma)"]/*'/>
        public static double LogAverageFactor(GammaPower product, GammaPower A, GammaPower B, Gamma q)
        {
            if (B.Shape < A.Shape)
            {
                return(LogAverageFactor(product, B, A, q));
            }
            if (B.IsPointMass)
            {
                return(GammaProductOp.LogAverageFactor(product, A, B.Point));
            }
            if (A.IsPointMass)
            {
                return(GammaProductOp.LogAverageFactor(product, A.Point, B));
            }
            double qPoint = q.GetMean();
            double logf;

            if (product.IsPointMass)
            {
                // Ga(y/q; s, r)/q
                if (qPoint == 0)
                {
                    if (product.Point == 0)
                    {
                        logf = A.GetLogProb(0);
                    }
                    else
                    {
                        logf = double.NegativeInfinity;
                    }
                }
                else
                {
                    logf = A.GetLogProb(product.Point / qPoint) - Math.Log(qPoint);
                }
            }
            else
            {
                // int Ga^y_p(a^pa b^pb; y_s, y_r) Ga(a; s, r) da = q^(y_s-y_p) / (r + q y_r)^(y_s + s-pa)  Gamma(y_s+s-pa)
                double shape  = product.Shape - product.Power;
                double shape2 = GammaFromShapeAndRateOp_Slow.AddShapesMinus1(product.Shape, A.Shape) + (1 - A.Power);
                if (IsProper(product) && product.Shape > A.Shape)
                {
                    // same as below but product.GetLogNormalizer() is inlined and combined with other terms
                    double AShapeMinusPower = A.Shape - A.Power;
                    logf = shape * Math.Log(qPoint)
                           - Gamma.FromShapeAndRate(A.Shape, A.Rate).GetLogNormalizer()
                           - product.Shape * Math.Log(A.Rate / product.Rate + qPoint)
                           - Math.Log(Math.Abs(product.Power));
                    if (AShapeMinusPower != 0)
                    {
                        logf += AShapeMinusPower * (MMath.RisingFactorialLnOverN(product.Shape, AShapeMinusPower) - Math.Log(A.Rate + qPoint * product.Rate));
                    }
                }
                else
                {
                    logf = shape * Math.Log(qPoint)
                           - shape2 * Math.Log(A.Rate + qPoint * product.Rate)
                           + MMath.GammaLn(shape2)
                           - Gamma.FromShapeAndRate(A.Shape, A.Rate).GetLogNormalizer()
                           - product.GetLogNormalizer();
                    // normalizer is -MMath.GammaLn(Shape) + Shape * Math.Log(Rate) - Math.Log(Math.Abs(Power))
                }
            }
            double logz = logf + Gamma.FromShapeAndRate(B.Shape, B.Rate).GetLogProb(qPoint) - q.GetLogProb(qPoint);

            return(logz);
        }
示例#23
0
 public static int Poisson(double mean)
 {
     // TODO: There are more efficient samplers
     if (mean < 0)
     {
         throw new ArgumentException("mean < 0");
     }
     else if (mean == 0.0)
     {
         return(0);
     }
     else if (mean < 10)
     {
         double L = System.Math.Exp(-mean);
         double p = 1.0;
         int    k = 0;
         do
         {
             k++;
             p *= Rand.Double();
         } while (p > L);
         return(k - 1);
     }
     else
     {
         // mean >= 10
         // Devroye ch10.3, with corrections
         // Reference: "Non-Uniform Random Variate Generation" by Luc Devroye (1986)
         double mu        = System.Math.Floor(mean);
         double muLogFact = MMath.GammaLn(mu + 1);
         double logMeanMu = System.Math.Log(mean / mu);
         double delta     = System.Math.Max(6, System.Math.Min(mu, System.Math.Sqrt(2 * mu * System.Math.Log(128 * mu / System.Math.PI))));
         double c1        = System.Math.Sqrt(System.Math.PI * mu / 2);
         double c2        = c1 + System.Math.Sqrt(System.Math.PI * (mu + delta / 2) / 2) * System.Math.Exp(1 / (2 * mu + delta));
         double c3        = c2 + 2;
         double c4        = c3 + System.Math.Exp(1.0 / 78);
         double c         = c4 + 2 / delta * (2 * mu + delta) * System.Math.Exp(-delta / (2 * mu + delta) * (1 + delta / 2));
         while (true)
         {
             double u = Rand.Double() * c;
             double x, w;
             if (u <= c1)
             {
                 double n = Rand.Normal();
                 double y = -System.Math.Abs(n) * System.Math.Sqrt(mu) - 1;
                 x = System.Math.Floor(y);
                 if (x < -mu)
                 {
                     continue;
                 }
                 w = -n * n / 2;
             }
             else if (u <= c2)
             {
                 double n = Rand.Normal();
                 double y = 1 + System.Math.Abs(n) * System.Math.Sqrt(mu + delta / 2);
                 x = System.Math.Ceiling(y);
                 if (x > delta)
                 {
                     continue;
                 }
                 w = (2 - y) * y / (2 * mu + delta);
             }
             else if (u <= c3)
             {
                 x = 0;
                 w = 0;
             }
             else if (u <= c4)
             {
                 x = 1;
                 w = 0;
             }
             else
             {
                 double v = -System.Math.Log(Rand.Double());
                 double y = delta + v * 2 / delta * (2 * mu + delta);
                 x = System.Math.Ceiling(y);
                 w = -delta / (2 * mu + delta) * (1 + y / 2);
             }
             double e = -System.Math.Log(Rand.Double());
             w -= e + x * logMeanMu;
             double qx = x * System.Math.Log(mu) - MMath.GammaLn(mu + x + 1) + muLogFact;
             if (w <= qx)
             {
                 return((int)System.Math.Round(x + mu));
             }
         }
     }
 }
        public static void VarianceGammaTimesGaussianMoments2(double a, double m, double v, out double mu, out double vu)
        {
            // compute weights
            Matrix      laplacianMoments = new Matrix(nWeights, nWeights);
            DenseVector exactMoments     = DenseVector.Constant(laplacianMoments.Rows, 1.0);
            // a=10: 7-1
            // a=15: 8-1
            // a=20: 10-1
            // a=21: 10-1
            // a=30: 12-1
            // get best results if the lead term has flat moment ratio
            int jMax = Math.Max(laplacianMoments.Cols, (int)Math.Round(a - 10)) - 1;

            jMax = laplacianMoments.Cols - 1;
            for (int i = 0; i < exactMoments.Count; i++)
            {
                //int ii = jMax-i;
                int    ii        = i;
                double logMoment = MMath.GammaLn(ii + a) - MMath.GammaLn(a) - MMath.GammaLn(ii + 1);
                for (int j = 0; j < laplacianMoments.Cols; j++)
                {
                    int jj = jMax - j;
                    laplacianMoments[i, j] = Math.Exp(MMath.GammaLn(2 * ii + jj + 1) - MMath.GammaLn(2 * ii + 1) - MMath.GammaLn(jj + 1) - logMoment);
                }
            }
            //Console.WriteLine("exactMoments = {0}, laplacianMoments = ", exactMoments);
            //Console.WriteLine(laplacianMoments);
            (new LuDecomposition(laplacianMoments)).Solve(exactMoments);
            DenseVector weights = exactMoments;

            Console.WriteLine("weights = {0}", weights);
            double Z0Plus = 0, Z1Plus = 0, Z2Plus = 0;
            double Z0Minus = 0, Z1Minus = 0, Z2Minus = 0;
            double sqrtV    = Math.Sqrt(v);
            double InvSqrtV = 1 / sqrtV;
            double mPlus    = (m - v) * InvSqrtV;
            double mMinus   = (-m - v) * InvSqrtV;

            for (int j = 0; j < weights.Count; j++)
            {
                int jj = jMax - j;
                Z0Plus  += weights[j] * MMath.NormalCdfMomentRatio(0 + jj, mPlus) * Math.Pow(sqrtV, 0 + jj);
                Z1Plus  += weights[j] * MMath.NormalCdfMomentRatio(1 + jj, mPlus) * (1 + jj) * Math.Pow(sqrtV, 1 + jj);
                Z2Plus  += weights[j] * MMath.NormalCdfMomentRatio(2 + jj, mPlus) * (1 + jj) * (2 + jj) * Math.Pow(sqrtV, 2 + jj);
                Z0Minus += weights[j] * MMath.NormalCdfMomentRatio(0 + jj, mMinus) * Math.Pow(sqrtV, 0 + jj);
                Z1Minus += weights[j] * MMath.NormalCdfMomentRatio(1 + jj, mMinus) * (1 + jj) * Math.Pow(sqrtV, 1 + jj);
                Z2Minus += weights[j] * MMath.NormalCdfMomentRatio(2 + jj, mMinus) * (1 + jj) * (2 + jj) * Math.Pow(sqrtV, 2 + jj);
            }
            double Z0 = Z0Plus + Z0Minus;
            double Z1 = Z1Plus - Z1Minus;
            double Z2 = Z2Plus + Z2Minus;

            mu = Z1 / Z0;
            vu = Z2 / Z0 - mu * mu;
        }
        /// <summary>
        /// Find a Beta distribution with given integral and mean times a Beta weight function.
        /// </summary>
        /// <param name="mean">The desired value of the mean</param>
        /// <param name="logZ">The desired value of the integral</param>
        /// <param name="a">trueCount-1 of the weight function</param>
        /// <param name="b">falseCount-1 of the weight function</param>
        /// <returns></returns>
        private static Beta BetaFromMeanAndIntegral(double mean, double logZ, double a, double b)
        {
            // The constraints are:
            // 1. int_p to_p(p) p^a (1-p)^b dp = exp(logZ)
            // 2. int_p to_p(p) p p^a (1-p)^b dp = mean*exp(logZ)
            // Let to_p(p) = Beta(p; af, bf)
            // The LHS of (1) is gamma(af+bf)/gamma(af+bf+a+b) gamma(af+a)/gamma(af) gamma(bf+b)/gamma(bf)
            // The LHS of (2) is gamma(af+bf)/gamma(af+bf+a+b+1) gamma(af+a+1)/gamma(af) gamma(bf+b)/gamma(bf)
            // The ratio of (2)/(1) is gamma(af+a+1)/gamma(af+a) gamma(af+bf+a+b)/gamma(af+bf+a+b+1) = (af+a)/(af+bf+a+b) = mean
            // Solving for bf gives bf = (af+a)/mean - (af+a+b).
            // To solve for af, we apply a generalized Newton algorithm to solve equation (1) with bf substituted.
            // af0 is the smallest value of af that ensures (af >= 0, bf >= 0).
            if (mean <= 0)
            {
                throw new ArgumentException("mean <= 0");
            }
            if (mean >= 1)
            {
                throw new ArgumentException("mean >= 1");
            }
            if (double.IsNaN(mean))
            {
                throw new ArgumentException("mean is NaN");
            }
            // bf = (af+bx)*(1-m)/m
            double bx = -(mean * (a + b) - a) / (1 - mean);
            // af0 is the lower bound for af
            // we need both af>0 and bf>0
            double af0     = Math.Max(0, -bx);
            double x       = Math.Max(0, bx);
            double af      = af0 + 1;      // initial guess for af
            double invMean = 1 / mean;
            double bf      = (af + a) * invMean - (af + a + b);

            for (int iter = 0; iter < 20; iter++)
            {
                double old_af = af;
                double f      = (MMath.GammaLn(af + bf) - MMath.GammaLn(af + bf + a + b)) + (MMath.GammaLn(af + a) - MMath.GammaLn(af)) + (MMath.GammaLn(bf + b) - MMath.GammaLn(bf));
                double g      = (MMath.Digamma(af + bf) - MMath.Digamma(af + bf + a + b)) * invMean + (MMath.Digamma(af + a) - MMath.Digamma(af)) + (MMath.Digamma(bf + b) - MMath.Digamma(bf)) * (invMean - 1);
                // fit a fcn of the form: s*log((af-af0)/(af+x)) + c
                // whose deriv is s/(af-af0) - s/(af+x)
                double s            = g / (1 / (af - af0) - 1 / (af + x));
                double c            = f - s * Math.Log((af - af0) / (af + x));
                bool   isIncreasing = (x > -af0);
                if ((!isIncreasing && c >= logZ) || (isIncreasing && c <= logZ))
                {
                    // the approximation doesn't fit; use Gauss-Newton instead
                    af += (logZ - f) / g;
                }
                else
                {
                    // now solve s*log((af-af0)/(af+x))+c = logz
                    // af-af0 = exp((logz-c)/s) (af+x)
                    af = af0 + (x + af0) / MMath.ExpMinus1((c - logZ) / s);
                    if (af == af0)
                    {
                        throw new ArgumentException("logZ is out of range");
                    }
                }
                if (double.IsNaN(af))
                {
                    throw new ApplicationException("af is nan");
                }
                bf = (af + a) / mean - (af + a + b);
                if (Math.Abs(af - old_af) < 1e-8)
                {
                    break;
                }
            }
            if (false)
            {
                // check that integrals are correct
                double f = (MMath.GammaLn(af + bf) - MMath.GammaLn(af + bf + a + b)) + (MMath.GammaLn(af + a) - MMath.GammaLn(af)) + (MMath.GammaLn(bf + b) - MMath.GammaLn(bf));
                if (Math.Abs(f - logZ) > 1e-6)
                {
                    throw new ApplicationException("wrong f");
                }
                double f2 = (MMath.GammaLn(af + bf) - MMath.GammaLn(af + bf + a + b + 1)) + (MMath.GammaLn(af + a + 1) - MMath.GammaLn(af)) + (MMath.GammaLn(bf + b) - MMath.GammaLn(bf));
                if (Math.Abs(f2 - (Math.Log(mean) + logZ)) > 1e-6)
                {
                    throw new ApplicationException("wrong f2");
                }
            }
            return(new Beta(af, bf));
        }
示例#26
0
#pragma warning disable 162
#endif

        /// <summary>
        /// Find a Beta distribution with given integral and mean times a Beta weight function.
        /// </summary>
        /// <param name="mean">The desired value of the mean</param>
        /// <param name="logZ">The desired value of the integral</param>
        /// <param name="a">trueCount-1 of the weight function</param>
        /// <param name="b">falseCount-1 of the weight function</param>
        /// <returns></returns>
        private static Beta BetaFromMeanAndIntegral(double mean, double logZ, double a, double b)
        {
            // The constraints are:
            // 1. int_p to_p(p) p^a (1-p)^b dp = exp(logZ)
            // 2. int_p to_p(p) p p^a (1-p)^b dp = mean*exp(logZ)
            // Let to_p(p) = Beta(p; af, bf)
            // The LHS of (1) is gamma(af+bf)/gamma(af+bf+a+b) gamma(af+a)/gamma(af) gamma(bf+b)/gamma(bf)
            // The LHS of (2) is gamma(af+bf)/gamma(af+bf+a+b+1) gamma(af+a+1)/gamma(af) gamma(bf+b)/gamma(bf)
            // The ratio of (2)/(1) is gamma(af+a+1)/gamma(af+a) gamma(af+bf+a+b)/gamma(af+bf+a+b+1) = (af+a)/(af+bf+a+b) = mean
            // Solving for bf gives bf = (af+a)/mean - (af+a+b).
            // To solve for af, we apply a generalized Newton algorithm to solve equation (1) with bf substituted.
            // af0 is the smallest value of af that ensures (af >= 0, bf >= 0).
            if (mean <= 0)
            {
                throw new ArgumentException("mean <= 0");
            }
            if (mean >= 1)
            {
                throw new ArgumentException("mean >= 1");
            }
            if (double.IsNaN(mean))
            {
                throw new ArgumentException("mean is NaN");
            }
            // If exp(logZ) exceeds the largest possible value of (1), then we return a point mass.
            // gammaln(x) =approx (x-0.5)*log(x) - x + 0.5*log(2pi)
            // (af+x)*log(af+x) =approx (af+x)*log(af) + x + 0.5*x*x/af
            // For large af, logZ = (af+bf-0.5)*log(af+bf) - (af+bf+a+b-0.5)*log(af+bf+a+b) +
            //                      (af+a-0.5)*log(af+a) - (af-0.5)*log(af) +
            //                      (bf+b-0.5)*log(bf+b) - (bf-0.5)*log(bf)
            // =approx (af+bf-0.5)*log(af+bf) - ((af+bf+a+b-0.5)*log(af+bf) + (a+b) + 0.5*(a+b)*(a+b)/(af+bf) -0.5*(a+b)/(af+bf)) +
            //   ((af+a-0.5)*log(af) + a + 0.5*a*a/af - 0.5*a/af) - (af-0.5)*log(af) +
            //   ((bf+b-0.5)*log(bf) + b + 0.5*b*b/bf - 0.5*b/bf) - (bf-0.5)*log(bf)
            // = -(a+b)*log(af+bf) - 0.5*(a+b)*(a+b-1)/(af+bf) + a*log(af) + 0.5*a*(a-1)/af + b*log(bf) + 0.5*b*(b-1)/bf
            // =approx (a+b)*log(m) + b*log((1-m)/m) + 0.5*(a+b)*(a+b-1)*m/af - 0.5*a*(a+1)/af - 0.5*b*(b+1)*m/(1-m)/af
            // =approx (a+b)*log(mean) + b*log((1-mean)/mean)
            double maxLogZ = (a + b) * Math.Log(mean) + b * Math.Log((1 - mean) / mean);
            // slope determines whether maxLogZ is the maximum or minimum possible value of logZ
            double slope = (a + b) * (a + b - 1) * mean - a * (a + 1) - b * (b + 1) * mean / (1 - mean);

            if ((slope <= 0 && logZ >= maxLogZ) || (slope > 0 && logZ <= maxLogZ))
            {
                // optimal af is infinite
                return(Beta.PointMass(mean));
            }
            // bf = (af+bx)*(1-m)/m
            double bx = -(mean * (a + b) - a) / (1 - mean);
            // af0 is the lower bound for af
            // we need both af>0 and bf>0
            double af0      = Math.Max(0, -bx);
            double x        = Math.Max(0, bx);
            double af       = af0 + 1; // initial guess for af
            double invMean  = 1 / mean;
            double bf       = (af + a) * invMean - (af + a + b);
            int    numIters = 20;

            for (int iter = 0; iter < numIters; iter++)
            {
                double old_af = af;
                double f      = (MMath.GammaLn(af + bf) - MMath.GammaLn(af + bf + a + b)) + (MMath.GammaLn(af + a) - MMath.GammaLn(af)) +
                                (MMath.GammaLn(bf + b) - MMath.GammaLn(bf));
                double g = (MMath.Digamma(af + bf) - MMath.Digamma(af + bf + a + b)) * invMean + (MMath.Digamma(af + a) - MMath.Digamma(af)) +
                           (MMath.Digamma(bf + b) - MMath.Digamma(bf)) * (invMean - 1);
                // fit a fcn of the form: s*log((af-af0)/(af+x)) + c
                // whose deriv is s/(af-af0) - s/(af+x)
                double s            = g / (1 / (af - af0) - 1 / (af + x));
                double c            = f - s * Math.Log((af - af0) / (af + x));
                bool   isIncreasing = (x > -af0);
                if ((!isIncreasing && c >= logZ) || (isIncreasing && c <= logZ))
                {
                    // the approximation doesn't fit; use Gauss-Newton instead
                    af += (logZ - f) / g;
                }
                else
                {
                    // now solve s*log((af-af0)/(af+x))+c = logz
                    // af-af0 = exp((logz-c)/s) (af+x)
                    af = af0 + (x + af0) / MMath.ExpMinus1((c - logZ) / s);
                    //if (af == af0)
                    //    throw new ArgumentException("logZ is out of range");
                }
                if (double.IsNaN(af))
                {
                    throw new InferRuntimeException("af is nan");
                }
                bf = (af + a) / mean - (af + a + b);
                if (Math.Abs(af - old_af) < 1e-8 || af == af0)
                {
                    break;
                }
                //if (iter == numIters-1)
                //    throw new Exception("not converging");
            }
            if (false)
            {
                // check that integrals are correct
                double f = (MMath.GammaLn(af + bf) - MMath.GammaLn(af + bf + a + b)) + (MMath.GammaLn(af + a) - MMath.GammaLn(af)) +
                           (MMath.GammaLn(bf + b) - MMath.GammaLn(bf));
                if (Math.Abs(f - logZ) > 1e-6)
                {
                    throw new InferRuntimeException("wrong f");
                }
                double f2 = (MMath.GammaLn(af + bf) - MMath.GammaLn(af + bf + a + b + 1)) + (MMath.GammaLn(af + a + 1) - MMath.GammaLn(af)) +
                            (MMath.GammaLn(bf + b) - MMath.GammaLn(bf));
                if (Math.Abs(f2 - (Math.Log(mean) + logZ)) > 1e-6)
                {
                    throw new InferRuntimeException("wrong f2");
                }
            }
            return(new Beta(af, bf));
        }
示例#27
0
 /// <summary>
 /// Gets the log of the normalizer for the truncated Gamma density function
 /// </summary>
 /// <returns></returns>
 public double GetLogNormalizer()
 {
     if (IsProper() && !IsPointMass)
     {
         if (this.Gamma.Shape < 1 && (double)(this.Gamma.Rate * LowerBound) > 0)
         {
             // When Shape < 1, Gamma(Shape) > 1 so use the unregularized version to avoid underflow.
             return(Math.Log(GammaProbBetween(this.Gamma.Shape, this.Gamma.Rate, LowerBound, UpperBound, false)) - MMath.GammaLn(this.Gamma.Shape));
         }
         else
         {
             return(Math.Log(GammaProbBetween(this.Gamma.Shape, this.Gamma.Rate, LowerBound, UpperBound)));
         }
     }
     else
     {
         return(0.0);
     }
 }
        /// <summary>
        /// EP message to 'trialCount'
        /// </summary>
        /// <param name="sample">Incoming message from 'sample'.</param>
        /// <param name="p">Incoming message from 'p'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'trialCount' as the random arguments are varied.
        /// The formula is <c>proj[p(trialCount) sum_(sample,p) p(sample,p) factor(sample,trialCount,p)]/p(trialCount)</c>.
        /// </para></remarks>
        public static Discrete TrialCountAverageConditional(Discrete sample, Beta p, Discrete result)
        {
            if (p.IsPointMass)
            {
                return(TrialCountAverageConditional(sample, p.Point, result));
            }
            if (sample.IsPointMass)
            {
                return(TrialCountAverageConditional(sample.Point, p, result));
            }
            // n must range from 0 to sampleMax
            if (result.Dimension < sample.Dimension)
            {
                throw new ArgumentException("result.Dimension (" + result.Dimension + ") < sample.Dimension (" + sample.Dimension + ")");
            }
            Vector probs = result.GetWorkspace();
            double a     = p.TrueCount;
            double b     = p.FalseCount;

            // p(n) = sum_(k<=n) p(k) nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                double s = 0.0;
                for (int k = 0; k <= n; k++)
                {
                    s += sample[k] * Math.Exp(MMath.ChooseLn(n, k) + MMath.GammaLn(a + k) + MMath.GammaLn(b + n - k));
                }
                probs[n] = Math.Exp(-MMath.GammaLn(a + b + n)) * s;
            }
            result.SetProbs(probs);
            return(result);
        }
示例#29
0
        //-- VMP -------------------------------------------------------------------------------------------

        /// <summary>Evidence message for VMP.</summary>
        /// <param name="sample">Constant value for <c>sample</c>.</param>
        /// <param name="mean">Incoming message from <c>mean</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
        /// <returns>Average of the factor's log-value across the given argument distributions.</returns>
        /// <remarks>
        ///   <para>The formula for the result is <c>sum_(mean) p(mean) log(factor(sample,mean))</c>. Adding up these values across all factors and variables gives the log-evidence estimate for VMP.</para>
        /// </remarks>
        /// <exception cref="ImproperMessageException">
        ///   <paramref name="mean" /> is not a proper distribution.</exception>
        public static double AverageLogFactor(int sample, [Proper] Gamma mean)
        {
            return(sample * mean.GetMeanLog() - MMath.GammaLn(sample + 1) - mean.GetMean());
        }
示例#30
0
 /// <summary>
 /// Computes E[x^power]
 /// </summary>
 /// <returns></returns>
 public double GetMeanPower(double power)
 {
     if (power == 0.0)
     {
         return(1.0);
     }
     else if (power == 1.0)
     {
         return(GetMean());
     }
     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 if (power != 1)
     {
         // Large powers lead to overflow
         power = Math.Min(Math.Max(power, -1e300), 1e300);
         double logZ = GetLogNormalizer();
         if (logZ < double.MinValue)
         {
             return(Math.Pow(GetMode(), power));
         }
         double shapePlusPower = this.Gamma.Shape + power;
         double logZ1;
         bool   regularized = shapePlusPower >= 1;
         if (regularized)
         {
             // This formula cannot be used when shapePlusPower <= 0
             logZ1 = (power * MMath.RisingFactorialLnOverN(this.Gamma.Shape, power)) +
                     Math.Log(GammaProbBetween(shapePlusPower, this.Gamma.Rate, LowerBound, UpperBound, regularized));
         }
         else
         {
             logZ1 = -MMath.GammaLn(this.Gamma.Shape) +
                     Math.Log(GammaProbBetween(shapePlusPower, this.Gamma.Rate, LowerBound, UpperBound, regularized));
         }
         return(Math.Exp(-power * Math.Log(this.Gamma.Rate) + logZ1 - logZ));
     }
     else
     {
         double Z = GetNormalizer();
         if (Z == 0.0)
         {
             return(Math.Pow(GetMode(), power));
         }
         double shapePlusPower = this.Gamma.Shape + power;
         double Z1;
         double gammaLnShapePlusPower = MMath.GammaLn(shapePlusPower);
         double gammaLnShape          = MMath.GammaLn(this.Gamma.Shape);
         bool   regularized           = true; // (gammaLnShapePlusPower - gammaLnShape <= 700);
         if (regularized)
         {
             // If shapePlusPower is large and Gamma.Rate * UpperBound is small, then this can lead to Inf * 0
             Z1 = Math.Exp(power * MMath.RisingFactorialLnOverN(this.Gamma.Shape, power)) *
                  GammaProbBetween(shapePlusPower, this.Gamma.Rate, LowerBound, UpperBound, regularized);
         }
         else
         {
             Z1 = Math.Exp(-gammaLnShape) *
                  GammaProbBetween(shapePlusPower, this.Gamma.Rate, LowerBound, UpperBound, regularized);
         }
         return(Z1 / (Math.Pow(this.Gamma.Rate, power) * Z));
     }
 }