Exemple #1
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DoublePlusOp"]/message_doc[@name="AAverageConditional(Gaussian, Gaussian)"]/*'/>
        public static Gaussian AAverageConditional([SkipIfUniform] Gaussian Sum, [SkipIfUniform] Gaussian b)
        {
            if (Sum.IsPointMass)
            {
                return(AAverageConditional(Sum.Point, b));
            }
            if (b.IsPointMass)
            {
                return(AAverageConditional(Sum, b.Point));
            }
            if (Sum.IsUniform() || b.IsUniform())
            {
                return(Gaussian.Uniform());
            }
            if (Sum.Precision == b.Precision)
            {
                // This formula works even when Precision == 0
                return(Gaussian.FromNatural(MMath.Average(Sum.MeanTimesPrecision, -b.MeanTimesPrecision), Sum.Precision / 2));
            }
            double prec = Sum.Precision + b.Precision;

            if (prec == 0)
            {
                throw new ImproperDistributionException(Sum.IsProper() ? b : Sum);
            }
            return(Gaussian.FromNatural((Sum.MeanTimesPrecision * b.Precision - b.MeanTimesPrecision * Sum.Precision) / prec, Sum.Precision * b.Precision / prec));
        }
Exemple #2
0
 /// <summary>
 /// Returns the value x such that GetProbLessThan(x) == probability.
 /// </summary>
 /// <param name="probability">A real number in [0,1].</param>
 /// <returns></returns>
 public double GetQuantile(double probability)
 {
     if (probability < 0)
     {
         throw new ArgumentOutOfRangeException("probability < 0");
     }
     if (probability > 1)
     {
         throw new ArgumentOutOfRangeException("probability > 1");
     }
     if (this.IsPointMass)
     {
         return((probability == 1.0) ? MMath.NextDouble(this.Point) : this.Point);
     }
     else if (!IsProper())
     {
         throw new ImproperDistributionException(this);
     }
     else if (MMath.AreEqual(probability, 0))
     {
         return(0);
     }
     else if (MMath.AreEqual(probability, 1))
     {
         return(double.PositiveInfinity);
     }
     else if (Shape == 1)
     {
         // cdf is 1 - exp(-x*rate)
         return(-Math.Log(1 - probability) / Rate);
     }
     else
     {
         // Binary search
         double lowerBound = 0;
         double upperBound = double.MaxValue;
         while (lowerBound < upperBound)
         {
             double average = MMath.Average(lowerBound, upperBound);
             double p       = GetProbLessThan(average);
             if (p == probability)
             {
                 return(average);
             }
             else if (p < probability)
             {
                 lowerBound = MMath.NextDouble(average);
             }
             else
             {
                 upperBound = MMath.PreviousDouble(average);
             }
         }
         return(lowerBound);
     }
 }
Exemple #3
0
        public void WeightedAverageTest()
        {
            Assert.Equal(Environment.Is64BitProcess ? 3.86361619394904E-311 : 3.86361619394162E-311, MMath.WeightedAverage(0.82912896852490248, 2.5484859206000203E-311, 3.50752234977395E-313, 31.087830618727477));
            Assert.Equal(MMath.WeightedAverage(0.1, double.MinValue, 0.01, double.MinValue), double.MinValue);
            Assert.Equal(MMath.WeightedAverage(0.1, -double.Epsilon, double.MaxValue, -double.Epsilon), -double.Epsilon);
            Assert.Equal(MMath.WeightedAverage(1e-100, 2e-250, 1e-100, 4e-250), MMath.Average(2e-250, 4e-250));
            Assert.Equal(MMath.WeightedAverage(1e100, 2e250, 1e100, 4e250), MMath.Average(2e250, 4e250));
            Assert.Equal(MMath.WeightedAverage(0, 0, 0.1, -double.Epsilon), -double.Epsilon);
            Assert.Equal(MMath.WeightedAverage(0.1, -double.Epsilon, 0, double.NegativeInfinity), -double.Epsilon);
            Assert.False(double.IsNaN(MMath.WeightedAverage(1.7976931348623157E+308, double.NegativeInfinity, 4.94065645841247E-324, double.NegativeInfinity)));
            Assert.False(double.IsNaN(MMath.WeightedAverage(0.01, double.NegativeInfinity, double.MaxValue, double.MaxValue)));
            Assert.False(double.IsNaN(MMath.WeightedAverage(0.01, double.NegativeInfinity, double.Epsilon, double.NegativeInfinity)));
            Assert.Equal(double.MaxValue, MMath.WeightedAverage(double.MaxValue, double.MaxValue, double.MaxValue, double.MaxValue));
            const int limit = 2_000_000;
            int       count = 0;

            Parallel.ForEach(OperatorTests.DoublesAtLeastZero(), wa =>
            {
                Parallel.ForEach(OperatorTests.DoublesAtLeastZero(), wb =>
                {
                    if (count > limit)
                    {
                        return;
                    }
                    Trace.WriteLine($"wa = {wa}, wb = {wb}");
                    foreach (var a in OperatorTests.Doubles())
                    {
                        if (count > limit)
                        {
                            break;
                        }
                        foreach (var b in OperatorTests.Doubles())
                        {
                            if (count > limit)
                            {
                                break;
                            }
                            if (double.IsNaN(a + b))
                            {
                                continue;
                            }
                            double midpoint = MMath.WeightedAverage(wa, a, wb, b);
                            Assert.True(midpoint >= System.Math.Min(a, b), $"Failed assertion: MMath.WeightedAverage({wa:r}, {a:r}, {wb:r}, {b:r}) {midpoint} >= {System.Math.Min(a, b)}");
                            Assert.True(midpoint <= System.Math.Max(a, b), $"Failed assertion: MMath.WeightedAverage({wa:r}, {a:r}, {wb:r}, {b:r}) {midpoint} <= {System.Math.Max(a, b)}");
                            if (wa == wb)
                            {
                                Assert.Equal(MMath.Average(a, b), midpoint);
                            }
                            Interlocked.Add(ref count, 1);
                        }
                    }
                });
            });
        }
Exemple #4
0
        public void WeightedAverageTest()
        {
            Assert.Equal(MMath.WeightedAverage(0.1, double.MinValue, 0.01, double.MinValue), double.MinValue);
            Assert.Equal(MMath.WeightedAverage(0.1, -double.Epsilon, double.MaxValue, -double.Epsilon), -double.Epsilon);
            Assert.Equal(MMath.WeightedAverage(1e-100, 2e-250, 1e-100, 4e-250), MMath.Average(2e-250, 4e-250));
            Assert.Equal(MMath.WeightedAverage(1e100, 2e250, 1e100, 4e250), MMath.Average(2e250, 4e250));
            Assert.Equal(MMath.WeightedAverage(0, 0, 0.1, -double.Epsilon), -double.Epsilon);
            Assert.Equal(MMath.WeightedAverage(0.1, -double.Epsilon, 0, double.NegativeInfinity), -double.Epsilon);
            Assert.False(double.IsNaN(MMath.WeightedAverage(1.7976931348623157E+308, double.NegativeInfinity, 4.94065645841247E-324, double.NegativeInfinity)));
            Assert.False(double.IsNaN(MMath.WeightedAverage(0.01, double.NegativeInfinity, double.MaxValue, double.MaxValue)));
            Assert.False(double.IsNaN(MMath.WeightedAverage(0.01, double.NegativeInfinity, double.Epsilon, double.NegativeInfinity)));
            Assert.Equal(double.MaxValue, MMath.WeightedAverage(double.MaxValue, double.MaxValue, double.MaxValue, double.MaxValue));
            const int limit = 2_000_000;
            int       count = 0;

            Parallel.ForEach(OperatorTests.DoublesAtLeastZero(), wa =>
            {
                Parallel.ForEach(OperatorTests.DoublesAtLeastZero(), wb =>
                {
                    if (count > limit)
                    {
                        return;
                    }
                    Trace.WriteLine($"wa = {wa}, wb = {wb}");
                    foreach (var a in OperatorTests.Doubles())
                    {
                        if (count > limit)
                        {
                            break;
                        }
                        foreach (var b in OperatorTests.Doubles())
                        {
                            if (count > limit)
                            {
                                break;
                            }
                            if (double.IsNaN(a + b))
                            {
                                continue;
                            }
                            double midpoint = MMath.WeightedAverage(wa, a, wb, b);
                            Assert.True(midpoint >= System.Math.Min(a, b), $"Failed assertion: {midpoint} >= {System.Math.Min(a, b)}, wa={wa:r}, a={a:r}, wb={wb:r}, b={b:r}");
                            Assert.True(midpoint <= System.Math.Max(a, b), $"Failed assertion: {midpoint} <= {System.Math.Max(a, b)}, wa={wa:r}, a={a:r}, wb={wb:r}, b={b:r}");
                            if (wa == wb)
                            {
                                Assert.Equal(MMath.Average(a, b), midpoint);
                            }
                            Interlocked.Add(ref count, 1);
                        }
                    }
                });
            });
        }
Exemple #5
0
        public static double GetMidpoint(double lower, double upper)
        {
            double midpoint;

            if (double.IsNegativeInfinity(lower))
            {
                if (double.IsPositiveInfinity(upper))
                {
                    midpoint = 0.0;
                }
                else if (upper > 0)
                {
                    midpoint = -upper;
                }
                else if (upper < 0)
                {
                    midpoint = 2 * upper;
                }
                else
                {
                    midpoint = -1;
                }
            }
            else if (double.IsPositiveInfinity(upper))
            {
                if (lower > 0)
                {
                    midpoint = 2 * lower;
                }
                else if (lower < 0)
                {
                    midpoint = -lower;
                }
                else
                {
                    midpoint = 1;
                }
            }
            else
            {
                midpoint = MMath.Average(lower, upper);
            }
            return(midpoint);
        }
Exemple #6
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DoublePlusOp"]/message_doc[@name="AAverageConditional(Gaussian, Gaussian)"]/*'/>
        public static Gaussian AAverageConditional([SkipIfUniform] Gaussian Sum, [SkipIfUniform] Gaussian b)
        {
            if (Sum.IsPointMass)
            {
                return(AAverageConditional(Sum.Point, b));
            }
            if (b.IsPointMass)
            {
                return(AAverageConditional(Sum, b.Point));
            }
            if (Sum.IsUniform() || b.IsUniform())
            {
                return(Gaussian.Uniform());
            }
            if (Sum.Precision == b.Precision)
            {
                // This formula works even when Precision == 0
                return(Gaussian.FromNatural(MMath.Average(Sum.MeanTimesPrecision, -b.MeanTimesPrecision), Sum.Precision / 2));
            }
            double meanTimesPrec, prec;

            if (Sum.Precision >= b.Precision)
            {
                double precOverSumPrec = 1 + b.Precision / Sum.Precision; // can overflow if b.Precision > Sum.Precision
                if (precOverSumPrec == 0)
                {
                    throw new ImproperDistributionException(Sum.IsProper() ? b : Sum);
                }
                meanTimesPrec = (Sum.MeanTimesPrecision / Sum.Precision * b.Precision - b.MeanTimesPrecision) / precOverSumPrec;
                prec          = b.Precision / precOverSumPrec;
            }
            else // Sum.Precision < b.Precision
            {
                double precOverbPrec = Sum.Precision / b.Precision + 1; // can overflow if Sum.Precision > b.Precision
                if (precOverbPrec == 0)
                {
                    throw new ImproperDistributionException(Sum.IsProper() ? b : Sum);
                }
                meanTimesPrec = (Sum.MeanTimesPrecision - b.MeanTimesPrecision / b.Precision * Sum.Precision) / precOverbPrec;
                prec          = Sum.Precision / precOverbPrec;
            }
            return(Gaussian.FromNatural(meanTimesPrec, prec));
        }
Exemple #7
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="DoublePlusOp"]/message_doc[@name="SumAverageConditional(Gaussian, Gaussian)"]/*'/>
        public static Gaussian SumAverageConditional([SkipIfUniform] Gaussian a, [SkipIfUniform] Gaussian b)
        {
            if (a.IsPointMass)
            {
                return(SumAverageConditional(a.Point, b));
            }
            if (b.IsPointMass)
            {
                return(SumAverageConditional(a, b.Point));
            }
            if (a.IsUniform() || b.IsUniform())
            {
                return(Gaussian.Uniform());
            }
            if (a.Precision == b.Precision)
            {
                // This formula works even when Precision == 0
                return(Gaussian.FromNatural(MMath.Average(a.MeanTimesPrecision, b.MeanTimesPrecision), a.Precision / 2));
            }
            double meanTimesPrec, prec;

            if (a.Precision >= b.Precision)
            {
                double precOverAPrec = 1 + b.Precision / a.Precision;
                if (precOverAPrec == 0)
                {
                    throw new ImproperDistributionException(a.IsProper() ? b : a);
                }
                meanTimesPrec = (a.MeanTimesPrecision / a.Precision * b.Precision + b.MeanTimesPrecision) / precOverAPrec;
                prec          = b.Precision / precOverAPrec;
            }
            else
            {
                double precOverBPrec = a.Precision / b.Precision + 1;
                if (precOverBPrec == 0)
                {
                    throw new ImproperDistributionException(a.IsProper() ? b : a);
                }
                meanTimesPrec = (a.MeanTimesPrecision + b.MeanTimesPrecision / b.Precision * a.Precision) / precOverBPrec;
                prec          = a.Precision / precOverBPrec;
            }
            return(Gaussian.FromNatural(meanTimesPrec, prec));
        }
Exemple #8
0
        /// <summary>
        /// Returns the largest value x such that GetProbLessThan(x) &lt;= probability.
        /// </summary>
        /// <param name="probability">A real number in [0,1].</param>
        /// <returns></returns>
        public double GetQuantile(double probability)
        {
            if (probability < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(probability), "probability < 0");
            }
            if (probability > 1.0)
            {
                throw new ArgumentOutOfRangeException(nameof(probability), "probability > 1.0");
            }
            // compute the min and max of the retained items
            double lowerBound = double.PositiveInfinity, upperBound = double.NegativeInfinity;

            for (int bufferIndex = 0; bufferIndex < buffers.Length; bufferIndex++)
            {
                double[] buffer = buffers[bufferIndex];
                int      count  = countInBuffer[bufferIndex];
                for (int i = 0; i < count; i++)
                {
                    double item = buffer[i];
                    if (item < lowerBound)
                    {
                        lowerBound = item;
                    }
                    if (item > upperBound)
                    {
                        upperBound = item;
                    }
                }
            }
            if (probability == 1.0)
            {
                return(MMath.NextDouble(upperBound));
            }
            if (probability == 0.0)
            {
                return(lowerBound);
            }
            if (double.IsPositiveInfinity(lowerBound))
            {
                throw new Exception("QuantileEstimator has no data");
            }
            if (lowerBound == upperBound)
            {
                return(upperBound);
            }
            // use bisection
            while (true)
            {
                double x = MMath.Average(lowerBound, upperBound);
                double lowerItem;
                double upperItem;
                long   lowerRank;
                long   lowerWeight, minLowerWeight, upperWeight, minUpperWeight;
                long   itemCount;
                GetAdjacentItems(x, out lowerItem, out upperItem, out lowerRank, out lowerWeight, out upperWeight, out minLowerWeight, out minUpperWeight, out itemCount);
                if (InterpolationType == 0)
                {
                    double probabilityLessThanLowerItem = (double)(lowerRank - lowerWeight) / itemCount;
                    if (probability < probabilityLessThanLowerItem)
                    {
                        upperBound = MMath.PreviousDouble(lowerItem);
                    }
                    else
                    {
                        double probabilityLessThanUpperItem = (double)lowerRank / itemCount;
                        if (probability < probabilityLessThanUpperItem)
                        {
                            return(lowerItem);
                        }
                        double probabilityLessThanOrEqualUpperItem = (double)(lowerRank + upperWeight) / itemCount;
                        if (probability < probabilityLessThanOrEqualUpperItem)
                        {
                            return(upperItem);
                        }
                        lowerBound = MMath.NextDouble(upperItem);
                    }
                }
                else if (InterpolationType == 1)
                {
                    // Find frac such that (lowerRank - 0.5 + frac) / itemCount == probability
                    double scaledProbability = MMath.LargestDoubleProduct(itemCount, probability);
                    if (scaledProbability < 0.5)
                    {
                        return(lowerBound);
                    }
                    if (scaledProbability >= itemCount - 0.5)
                    {
                        return(upperBound);
                    }
                    // probability of lowerItem ranges from (lowerRank-lowerWeight+0.5) / itemCount
                    // to (lowerRank - 0.5) / itemCount
                    //if (scaledProbability == lowerRank - lowerWeight + 0.5) return lowerItem;
                    if ((scaledProbability > lowerRank - lowerWeight + 0.5) && (scaledProbability < lowerRank - 0.5))
                    {
                        return(lowerItem);
                    }
                    // probability of upperItem ranges from (lowerRank + 0.5) / itemCount
                    // to (lowerRank + upperWeight - 0.5) / itemCount
                    if (scaledProbability == lowerRank + 0.5)
                    {
                        return(upperItem);
                    }
                    if ((scaledProbability > lowerRank + 0.5) && (scaledProbability < lowerRank + upperWeight - 0.5))
                    {
                        return(upperItem);
                    }
                    double frac = scaledProbability - (lowerRank - 0.5);
                    if (frac < 0)
                    {
                        upperBound = MMath.PreviousDouble(x);
                    }
                    else if (frac > 1)
                    {
                        lowerBound = MMath.NextDouble(x);
                    }
                    else
                    {
                        return(OuterQuantiles.GetQuantile(probability, lowerRank - 0.5, lowerItem, upperItem, itemCount + 1));
                    }
                }
                else
                {
                    double scaledProbability = MMath.LargestDoubleProduct(itemCount - 1, probability);
                    // probability of lowerItem ranges from (lowerRank-lowerWeight) / (itemCount - 1)
                    // to (lowerRank - 1) / (itemCount - 1).
                    if (scaledProbability == lowerRank - lowerWeight)
                    {
                        return(lowerItem);
                    }
                    if ((scaledProbability > lowerRank - lowerWeight) && (scaledProbability < lowerRank - 1))
                    {
                        return(lowerItem);
                    }
                    // probability of upperItem ranges from lowerRank / (itemCount - 1)
                    // to (lowerRank + upperWeight-1) / (itemCount - 1)
                    if (scaledProbability == lowerRank)
                    {
                        return(upperItem);
                    }
                    if ((scaledProbability > lowerRank) && (scaledProbability < lowerRank + upperWeight - 1))
                    {
                        return(upperItem);
                    }
                    // solve for frac in (lowerRank-1 + frac) / (itemCount - 1) == probability
                    double frac = scaledProbability - (lowerRank - 1);
                    if (frac < 0)
                    {
                        upperBound = MMath.PreviousDouble(x);
                    }
                    else if (frac > 1)
                    {
                        lowerBound = MMath.NextDouble(x);
                    }
                    else
                    {
                        return(OuterQuantiles.GetQuantile(probability, lowerRank - 1, lowerItem, upperItem, itemCount));
                    }
                }
            }
        }