예제 #1
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="GammaRatioOp"]/message_doc[@name="RatioAverageConditional(Gamma, double)"]/*'/>
 public static Gamma RatioAverageConditional([SkipIfUniform] Gamma A, double B)
 {
     if (A.IsPointMass)
     {
         return(Gamma.PointMass(A.Point / B));
     }
     if (B == 0)
     {
         return(Gamma.PointMass(double.PositiveInfinity));
     }
     return(GammaProductOp.AAverageConditional(A, B));
 }
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="GammaPowerProductOp_Laplace"]/message_doc[@name="AAverageConditional(GammaPower, GammaPower, GammaPower, Gamma, GammaPower)"]/*'/>
        public static GammaPower AAverageConditional([SkipIfUniform] GammaPower product, GammaPower A, [SkipIfUniform] GammaPower B, Gamma q, GammaPower result)
        {
            if (B.Shape < A.Shape)
            {
                return(BAverageConditional(product, B, A, q, result));
            }
            if (B.IsPointMass)
            {
                return(GammaProductOp.AAverageConditional(product, B.Point, result));
            }
            if (A.IsPointMass)
            {
                return(GammaPower.Uniform(A.Power)); // TODO
            }
            if (product.IsUniform())
            {
                return(product);
            }
            double     qPoint = q.GetMean();
            GammaPower aMarginal;

            if (product.IsPointMass)
            {
                // Z = int Ga(y/q; s, r)/q Ga(q; q_s, q_r) dq
                // E[a] = E[product/q]
                // E[a^2] = E[product^2/q^2]
                // aVariance = E[a^2] - aMean^2
                double productPoint = product.Point;
                if (productPoint == 0)
                {
                    aMarginal = GammaPower.PointMass(0, result.Power);
                }
                else
                {
                    double iqMean, iqVariance;
                    GetIQMoments(product, A, q, qPoint, out iqMean, out iqVariance);
                    double aMean     = productPoint * iqMean;
                    double aVariance = productPoint * productPoint * iqVariance;
                    aMarginal = GammaPower.FromGamma(Gamma.FromMeanAndVariance(aMean, aVariance), result.Power);
                }
            }
            else
            {
                if (double.IsPositiveInfinity(product.Rate))
                {
                    return(GammaPower.PointMass(0, result.Power));
                }
                if (A.Power != product.Power)
                {
                    throw new NotSupportedException($"A.Power ({A.Power}) != product.Power ({product.Power})");
                }
                if (B.Power != product.Power)
                {
                    throw new NotSupportedException($"B.Power ({B.Power}) != product.Power ({product.Power})");
                }
                double r      = product.Rate;
                double g      = 1 / (qPoint * r + A.Rate);
                double g2     = g * g;
                double shape2 = GammaFromShapeAndRateOp_Slow.AddShapesMinus1(product.Shape, A.Shape) + (1 - A.Power);
                // From above:
                // a^(y_s-pa + a_s-1) exp(-(y_r b + a_r)*a)
                if (shape2 > 2)
                {
                    // Compute the moments of a^(-1/a.Power)
                    // Here q = b^(1/b.Power)
                    // E[a^(-1/a.Power)] = E[(q r + a_r)/(shape2-1)]
                    // var(a^(-1/a.Power)) = E[(q r + a_r)^2/(shape2-1)/(shape2-2)] - E[a^(-1/a.Power)]^2
                    //          = (var(q r + a_r) + E[(q r + a_r)]^2)/(shape2-1)/(shape2-2) - E[(q r + a_r)]^2/(shape2-1)^2
                    //          = var(q r + a_r)/(shape2-1)/(shape2-2) + E[(q r + a_r)/(shape2-1)]^2/(shape2-2)
                    // TODO: share this computation with BAverageConditional
                    double qMean, qVariance;
                    GetQMoments(product, A, q, qPoint, out qMean, out qVariance);
                    double iaMean = (qMean * r + A.Rate) / (shape2 - 1);
                    //double iaVariance = (qVariance * r2 / (shape2 - 1) + iaMean * iaMean) / (shape2 - 2);
                    // shape = mean^2/variance + 2
                    //double iaVarianceOverMeanSquared = (qVariance / (shape2 - 1) * r / iaMean * r / iaMean + 1) / (shape2 - 2);
                    double iaVarianceOverMeanSquared = (qVariance * (shape2 - 1) / (qMean + A.Rate / r) / (qMean + A.Rate / r) + 1) / (shape2 - 2);
                    //GammaPower iaMarginal = GammaPower.FromMeanAndVariance(iaMean, iaVariance, -1);
                    GammaPower iaMarginal = InverseGammaFromMeanAndVarianceOverMeanSquared(iaMean, iaVarianceOverMeanSquared);
                    if (iaMarginal.IsUniform())
                    {
                        if (result.Power > 0)
                        {
                            return(GammaPower.PointMass(0, result.Power));
                        }
                        else
                        {
                            return(GammaPower.Uniform(result.Power));
                        }
                    }
                    else
                    {
                        aMarginal = GammaPower.FromShapeAndRate(iaMarginal.Shape, iaMarginal.Rate, result.Power);
                    }
                    bool check = false;
                    if (check)
                    {
                        // Importance sampling
                        MeanVarianceAccumulator mvaB    = new MeanVarianceAccumulator();
                        MeanVarianceAccumulator mvaInvA = new MeanVarianceAccumulator();
                        Gamma bPrior = Gamma.FromShapeAndRate(B.Shape, B.Rate);
                        q = bPrior;
                        double shift = (product.Shape - product.Power) * Math.Log(qPoint) - shape2 * Math.Log(A.Rate + qPoint * r) + bPrior.GetLogProb(qPoint) - q.GetLogProb(qPoint);
                        for (int i = 0; i < 1000000; i++)
                        {
                            double bSample = q.Sample();
                            // logf = (y_s-y_p)*log(b) - (s+y_s-pa)*log(r + b*y_r)
                            double logf   = (product.Shape - product.Power) * Math.Log(bSample) - shape2 * Math.Log(A.Rate + bSample * r) + bPrior.GetLogProb(bSample) - q.GetLogProb(bSample);
                            double weight = Math.Exp(logf - shift);
                            mvaB.Add(bSample, weight);
                            double invA = (bSample * r + A.Rate) / (shape2 - 1);
                            mvaInvA.Add(invA, weight);
                        }
                        Trace.WriteLine($"b = {mvaB}, {qMean}, {qVariance}");
                        Trace.WriteLine($"invA = {mvaInvA} {mvaInvA.Variance * (shape2 - 1) / (shape2 - 2) + mvaInvA.Mean * mvaInvA.Mean / (shape2 - 2)}, {iaMean}, {iaVarianceOverMeanSquared * iaMean * iaMean}");
                        Trace.WriteLine($"aMarginal = {aMarginal}");
                    }
                }
                else
                {
                    // Compute the moments of a^(1/a.Power)
                    // aMean = shape2/(b y_r + a_r)
                    // aVariance = E[shape2*(shape2+1)/(b y_r + a_r)^2] - aMean^2 = var(shape2/(b y_r + a_r)) + E[shape2/(b y_r + a_r)^2]
                    //           = shape2^2*var(1/(b y_r + a_r)) + shape2*(var(1/(b y_r + a_r)) + (aMean/shape2)^2)
                    double   r2 = r * r;
                    double[] gDerivatives = new double[] { g, -r * g2, 2 * g2 * g * r2, -6 * g2 * g2 * r2 * r };
                    double   gMean, gVariance;
                    GaussianOp_Laplace.LaplaceMoments(q, gDerivatives, dlogfs(qPoint, product, A), out gMean, out gVariance);
                    double aMean     = shape2 * gMean;
                    double aVariance = shape2 * shape2 * gVariance + shape2 * (gVariance + gMean * gMean);
                    aMarginal = GammaPower.FromGamma(Gamma.FromMeanAndVariance(aMean, aVariance), result.Power);
                }
            }
            result.SetToRatio(aMarginal, A, GammaProductOp_Laplace.ForceProper);
            if (double.IsNaN(result.Shape) || double.IsNaN(result.Rate))
            {
                throw new InferRuntimeException("result is nan");
            }
            return(result);
        }
예제 #3
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="GammaProductVmpOp"]/message_doc[@name="AAverageLogarithm(double, double, GammaPower)"]/*'/>
 public static GammaPower AAverageLogarithm(double Product, double B, GammaPower result)
 {
     return(GammaProductOp.AAverageConditional(Product, B, result));
 }
예제 #4
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="GammaProductVmpOp"]/message_doc[@name="AAverageLogarithm(double, double)"]/*'/>
 public static Gamma AAverageLogarithm(double Product, double B)
 {
     return(GammaProductOp.AAverageConditional(Product, B));
 }
예제 #5
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="GammaProductVmpOp"]/message_doc[@name="AAverageLogarithm(Gamma, double)"]/*'/>
 public static Gamma AAverageLogarithm([SkipIfUniform] Gamma Product, double B)
 {
     return(GammaProductOp.AAverageConditional(Product, B));
 }
예제 #6
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="GammaRatioOp"]/message_doc[@name="BAverageConditional(double, double)"]/*'/>
 public static Gamma BAverageConditional(double ratio, double A)
 {
     return(GammaProductOp.AAverageConditional(A, ratio));
 }