public void WeightedSampleTest()
        {
            var random = new Random(42);
            var values = new GumbelDistribution().Random(random).Next(30).Concat(
                new GumbelDistribution(10).Random(random).Next(30)).ToList();

            double[] weights = ExponentialDecaySequence.CreateFromHalfLife(10).GenerateReverseArray(values.Count);
            var      sample  = new Sample(values, weights);

            var simpleModalityData = detector.DetectModes(values);

            output.WriteLine("SimpleModalityData.Modes:");
            output.WriteLine(Present(simpleModalityData));
            output.WriteLine();
            output.WriteLine(simpleModalityData.DensityHistogram.Present());
            output.WriteLine("------------------------------");

            var weightedModalityData = detector.DetectModes(sample);

            output.WriteLine("WeightedModalityData.Modes:");
            output.WriteLine(Present(weightedModalityData));
            output.WriteLine();
            output.WriteLine(weightedModalityData.DensityHistogram.Present());

            Assert.Equal(2, simpleModalityData.Modality);
            Assert.Equal(1, weightedModalityData.Modality);
        }
Пример #2
0
        public void GumbelFit()
        {
            GumbelDistribution d = new GumbelDistribution(-1.0, 2.0);

            MultivariateSample parameters = new MultivariateSample(2);
            MultivariateSample variances  = new MultivariateSample(3);

            // Do a bunch of fits, record reported parameters and variances
            for (int i = 0; i < 32; i++)
            {
                Sample s = SampleTest.CreateSample(d, 64, i);

                GumbelFitResult r = GumbelDistribution.FitToSample(s);
                parameters.Add(r.Location.Value, r.Scale.Value);
                variances.Add(r.Parameters.CovarianceMatrix[0, 0], r.Parameters.CovarianceMatrix[1, 1], r.Parameters.CovarianceMatrix[0, 1]);

                Assert.IsTrue(r.GoodnessOfFit.Probability > 0.01);
            }

            // The reported parameters should agree with the underlying parameters
            Assert.IsTrue(parameters.Column(0).PopulationMean.ConfidenceInterval(0.99).ClosedContains(d.Location));
            Assert.IsTrue(parameters.Column(1).PopulationMean.ConfidenceInterval(0.99).ClosedContains(d.Scale));

            // The reported covariances should agree with the observed covariances
            Assert.IsTrue(parameters.Column(0).PopulationVariance.ConfidenceInterval(0.99).ClosedContains(variances.Column(0).Mean));
            Assert.IsTrue(parameters.Column(1).PopulationVariance.ConfidenceInterval(0.99).ClosedContains(variances.Column(1).Mean));
            Assert.IsTrue(parameters.TwoColumns(0, 1).PopulationCovariance.ConfidenceInterval(0.99).ClosedContains(variances.Column(2).Mean));
        }
Пример #3
0
        public void GumbelDistributionTest2()
        {
            var gumbel = new GumbelDistribution(1, 2);

            AssertEqual("Location", 1, gumbel.Location);
            AssertEqual("Scale", 2, gumbel.Scale);
            AssertEqual("Mean", 2.1544313298030655, gumbel.Mean);
            AssertEqual("Median", 1.7330258411633288, gumbel.Median);
            AssertEqual("Variance", 6.579736267392906, gumbel.Variance);

            var x           = new[] { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 };
            var expectedPdf = new[]
            {
                0.163415479697888, 0.167801779821723, 0.171664252678358, 0.174993580579211, 0.177786373690972, 0.180044733644614,
                0.181775762939958, 0.182991038252879, 0.183706064004954
            };
            var expectedCdf = new[]
            {
                0.2083966205323, 0.224961793549918, 0.241939508585805, 0.259276865990828, 0.276920334099909, 0.294816320729158,
                0.312911698166345, 0.331154277152909, 0.349493227081447
            };
            var expectedQuantile = new[]
            {
                -0.668064890495911, 0.0482300093457789, 0.628746482275269, 1.17484314358151, 1.73302584116333, 2.34345398418424,
                3.06186086631745, 3.99987997351903, 5.50073465462489
            };

            Check(gumbel, x, expectedPdf, expectedCdf, expectedQuantile);
        }
Пример #4
0
        public void GumbelDistributionTest1()
        {
            var gumbel = new GumbelDistribution();

            AssertEqual("Location", 0, gumbel.Location);
            AssertEqual("Scale", 1, gumbel.Scale);
            AssertEqual("Mean", 0.5772156649015329, gumbel.Mean);
            AssertEqual("Median", 0.36651292058166435, gumbel.Median);
            AssertEqual("Variance", 1.6449340668482264, gumbel.Variance);

            var x           = new[] { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 };
            var expectedPdf = new[]
            {
                0.36610415189774, 0.36105291477093, 0.353165596312007, 0.342898756467732, 0.330704298890418, 0.31701327275429,
                0.302224456630968, 0.286697116378904, 0.270747220321608
            };
            var expectedCdf = new[]
            {
                0.404607661664132, 0.440991025942983, 0.476723690714594, 0.511544833689042, 0.545239211892605, 0.577635844258916,
                0.608605317804406, 0.638056166582019, 0.665930705440122
            };
            var expectedQuantile = new[]
            {
                -0.834032445247956, -0.475884995327111, -0.185626758862366, 0.0874215717907552, 0.366512920581664, 0.671726992092122,
                1.03093043315872, 1.49993998675952, 2.25036732731245
            };

            Check(gumbel, x, expectedPdf, expectedCdf, expectedQuantile);
        }
Пример #5
0
        public void ConstructorTest1()
        {
            var gumbel = new GumbelDistribution(location: 4.795, scale: 1 / 0.392);

            double mean   = gumbel.Mean;                                    // 6.2674889410753387
            double median = gumbel.Median;                                  // 5.7299819402593481
            double mode   = gumbel.Mode;                                    // 4.7949999999999999
            double var    = gumbel.Variance;                                // 10.704745853604138

            double cdf  = gumbel.DistributionFunction(x: 3.4);              // 0.17767760424788051
            double pdf  = gumbel.ProbabilityDensityFunction(x: 3.4);        // 0.12033954114322486
            double lpdf = gumbel.LogProbabilityDensityFunction(x: 3.4);     // -2.1174380222001519

            double ccdf = gumbel.ComplementaryDistributionFunction(x: 3.4); // 0.82232239575211952
            double icdf = gumbel.InverseDistributionFunction(p: cdf);       // 3.3999999904866245

            double hf  = gumbel.HazardFunction(x: 1.4);                     // 0.03449691276402958
            double chf = gumbel.CumulativeHazardFunction(x: 1.4);           // 0.022988793482259906

            string str = gumbel.ToString(CultureInfo.InvariantCulture);     // Gumbel(x; μ = 4.795, β = 2.55)

            Assert.AreEqual(6.2674889410753387, mean);
            Assert.AreEqual(5.7299819402593481, median);
            Assert.AreEqual(10.704745853604138, var);
            Assert.AreEqual(0.022988793482259906, chf);
            Assert.AreEqual(0.17767760424788051, cdf);
            Assert.AreEqual(0.12033954114322486, pdf);
            Assert.AreEqual(-2.1174380222001519, lpdf);
            Assert.AreEqual(0.03449691276402958, hf);
            Assert.AreEqual(0.82232239575211952, ccdf);
            Assert.AreEqual(3.3999999904866245, icdf);
            Assert.AreEqual("Gumbel(x; μ = 4.795, β = 2.55102040816327)", str);
        }
Пример #6
0
        public void ConstructorTest1()
        {
            var gumbel = new GumbelDistribution(location: 4.795, scale: 1 / 0.392);

            double mean   = gumbel.Mean;                                    // 6.2674889410753387
            double median = gumbel.Median;                                  // 5.7299819402593481
            double mode   = gumbel.Mode;                                    // 4.7949999999999999
            double var    = gumbel.Variance;                                // 10.704745853604138

            double cdf  = gumbel.DistributionFunction(x: 3.4);              // 0.17767760424788051
            double pdf  = gumbel.ProbabilityDensityFunction(x: 3.4);        // 0.12033954114322486
            double lpdf = gumbel.LogProbabilityDensityFunction(x: 3.4);     // -2.1174380222001519

            double ccdf = gumbel.ComplementaryDistributionFunction(x: 3.4); // 0.82232239575211952
            double icdf = gumbel.InverseDistributionFunction(p: cdf);       // 3.3999999904866245

            double hf  = gumbel.HazardFunction(x: 1.4);                     // 0.03449691276402958
            double chf = gumbel.CumulativeHazardFunction(x: 1.4);           // 0.022988793482259906

            string str = gumbel.ToString(CultureInfo.InvariantCulture);     // Gumbel(x; μ = 4.795, β = 2.55)

            Assert.AreEqual(6.2674889410753387, mean);
            Assert.AreEqual(5.7299819402593481, median);
            Assert.AreEqual(4.7949999999999999, mode);
            Assert.AreEqual(10.704745853604138, var);
            Assert.AreEqual(0.022988793482259906, chf);
            Assert.AreEqual(0.17767760424788051, cdf);
            Assert.AreEqual(0.12033954114322486, pdf);
            Assert.AreEqual(-2.1174380222001519, lpdf);
            Assert.AreEqual(0.034496912764029573, hf);
            Assert.AreEqual(0.82232239575211952, ccdf);
            Assert.AreEqual(3.3999999999999999, icdf);
            Assert.AreEqual("Gumbel(x; μ = 4.795, β = 2.55102040816327)", str);

            var range1 = gumbel.GetRange(0.95);
            var range2 = gumbel.GetRange(0.99);
            var range3 = gumbel.GetRange(0.01);

            Assert.AreEqual(1.9960492163695556, range1.Min, 1e-6);
            Assert.AreEqual(12.37202869894511, range1.Max, 1e-6);
            Assert.AreEqual(0.89913343799046785, range2.Min, 1e-6);
            Assert.AreEqual(16.530074551002095, range2.Max, 1e-6);
            Assert.AreEqual(0.8991334379904673, range3.Min, 1e-6);
            Assert.AreEqual(16.530074551002095, range3.Max, 1e-6);


            /* Tested against R's package QRM:
             *
             *  > pGumbel(3.4,  4.795, 1 / 0.392)
             *  [1] 0.1776776
             *
             *  > dGumbel(3.4,  4.795, 1 / 0.392)
             *  [1] 0.1203395
             *
             */
        }
Пример #7
0
        private void SetDistributionFunctionFromString()
        {
            if (DistributionfunctionString.StartsWith("N"))
            {
                DistributionFunction = new NormalDistribution(Mean, StDeviation);
            }
            else if (DistributionfunctionString.StartsWith("Poisson"))
            {
                DistributionfunctionString = EnsureOnlyOneComma(DistributionfunctionString, 1);

                var lambda = double.Parse((DistributionfunctionString.Split('=')[1]).Replace(")", "").Trim(), CultureInfo.InvariantCulture);
                DistributionFunction = new PoissonDistribution(lambda);
            }
            else if (DistributionfunctionString.StartsWith("U"))
            {
                DistributionfunctionString = EnsureOnlyOneComma(DistributionfunctionString, 2);

                var a = double.Parse((DistributionfunctionString.Split('=')[1]).Split(',')[0].Trim(), CultureInfo.InvariantCulture);
                var b = double.Parse((DistributionfunctionString.Split('=')[2]).Split(')')[0].Trim(), CultureInfo.InvariantCulture);

                DistributionFunction = new UniformContinuousDistribution(a, b);
            }
            else if (DistributionfunctionString.Contains("x; k ="))
            {
                DistributionfunctionString = EnsureOnlyOneComma(DistributionfunctionString, 2);

                var k    = double.Parse((DistributionfunctionString.Split('=')[1]).Split(',')[0].Trim(), CultureInfo.InvariantCulture);
                var teta = double.Parse((DistributionfunctionString.Split('=')[2]).Split(')')[0].Trim(), CultureInfo.InvariantCulture);

                DistributionFunction = new GammaDistribution(teta, k);
            }
            else if (DistributionfunctionString.Contains("Gumbel"))
            {
                DistributionfunctionString = EnsureOnlyOneComma(DistributionfunctionString, 2);

                var u = double.Parse((DistributionfunctionString.Split('=')[1]).Split(',')[0].Trim(), CultureInfo.InvariantCulture);
                var b = double.Parse((DistributionfunctionString.Split('=')[2]).Split(')')[0].Trim(), CultureInfo.InvariantCulture);

                DistributionFunction = new GumbelDistribution(u, b);
            }

            else
            {
                throw new Exception("Unregnoized disitrubtionfunction " + DistributionfunctionString);
            }
        }
Пример #8
0
        public static void DistributionFunctions()
        {
            ContinuousDistribution gumbel = new GumbelDistribution();

            // Use PDF to compute absolute deviation
            IntegrationResult r = FunctionMath.Integrate(
                z => gumbel.ProbabilityDensity(z) * Math.Abs(z - gumbel.Mean),
                gumbel.Support
                );

            Console.WriteLine($"mean absolute deviation = {r.Value}");

            // Shorter form
            double gumbelMad = gumbel.ExpectationValue(z => Math.Abs(z - gumbel.Mean));

            Console.WriteLine($"mean absolute deviation = {gumbelMad}");

            double x = 1.5;

            // PDF
            Console.WriteLine($"p({x}) = {gumbel.ProbabilityDensity(x)}");

            // CDF, aka percentile
            double P = gumbel.LeftProbability(x);

            Console.WriteLine($"P({x}) = {P}");

            // Right CDF
            double Q = gumbel.RightProbability(x);

            Console.WriteLine($"Q({x}) = {Q}");

            Console.WriteLine($"P + Q = {P + Q}");

            // Far tail
            double xt = 100.0;
            double qt = gumbel.RightProbability(xt);

            Console.WriteLine($"Q({xt}) = {qt}");

            // Inverse CDF, aka quantile
            Console.WriteLine($"PI({P}) = {gumbel.InverseLeftProbability(P)}");
            Console.WriteLine($"QI({qt} = {gumbel.InverseRightProbability(qt)}");


            DiscreteDistribution binomial = new BinomialDistribution(0.4, 8);

            Console.WriteLine($"support {binomial.Support}");

            int k = 4;

            Console.WriteLine($"P({k}) = {binomial.ProbabilityMass(k)}");

            double binomialMad = binomial.ExpectationValue(i => Math.Abs(i - binomial.Mean));

            Console.WriteLine($"mean absolute deviation = {binomialMad}");

            Console.WriteLine($"P(k < {k}) = {binomial.LeftExclusiveProbability(k)}");
            Console.WriteLine($"P(k <= {k}) = {binomial.LeftInclusiveProbability(k)}");
            Console.WriteLine($"P(k > {k}) = {binomial.RightExclusiveProbability(k)}");

            int k0 = binomial.InverseLeftProbability(0.5);

            Console.WriteLine($"min k0 to achieve P(k <= k0) > 0.5: {k0}");
            Console.WriteLine($"P(k < {k0}) = {binomial.LeftExclusiveProbability(k0)}");
            Console.WriteLine($"P(k <= {k0}) = {binomial.LeftInclusiveProbability(k0)}");
        }
Пример #9
0
        /// <summary>
        /// Find the Gumbel distribution that best fit the given sample.
        /// </summary>
        /// <param name="sample">The sample to fit.</param>
        /// <returns>The fit result.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="sample"/> is <see langword="null"/>.</exception>
        /// <exception cref="InsufficientDataException"><paramref name="sample"/> contains fewer than three values.</exception>
        public static GumbelFitResult FitToGumbel(this IReadOnlyList <double> sample)
        {
            if (sample == null)
            {
                throw new ArgumentNullException(nameof(sample));
            }
            if (sample.Count < 3)
            {
                throw new InsufficientDataException();
            }

            // To do a maximum likelihood fit, start from the log probability of each data point and aggregate to
            // obtain the log likelihood of the sample
            //   z_i = \frac{x_i - m}{s}
            //   -\ln p_i = \ln s + ( z_i + e^{-z_i})
            //   \ln L = \sum_i \ln p_i

            // Take derivatives wrt m and s.
            //   \frac{\partial \ln L}{\partial m} = \frac{1}{s} \sum_i ( 1 - e^{-z_i} )
            //   \frac{\partial \ln L}{\partial s} = \frac{1}{s} \sum_i ( -1 + z_i - z_i e^{-z_i} )

            // Set derivatives to zero to get a system of equations for the maximum.
            //    n = \sum_i e^{-z_i}
            //    n = \sum_i ( z_i - z_i e^{-z_i} )
            // that is, <e^z> = 1 and <z> - <z e^z> = 1.

            // To solve this system, pull e^{m/s} out of the sum in the first equation and solve for m
            //    n = e^{m / s} \sum_i e^{-x_i / s}
            //    m = -s \ln \left( \frac{1}{n} \sum_i e^{-x_i / s} \right) = -s \ln <e^{-x/s}>
            // Substituting this result into the second equation gets us to
            //    s = \bar{x} - \frac{ <x e^{-x/s}> }{ <e^{x/s}> }
            // which involves only s. We can use a one-dimensional root-finder to determine s, then determine m
            // from the first equation.

            // To avoid exponentiating potentially large x_i, it's better to write the problem in terms
            // of d_i, where x_i = \bar{x} + d_i.
            //    m = \bar{x} - s \ln <e^{-d/s}>
            //    s = -\frac{ <d e^{-d/s}> }{ <e^{-d/s}> }

            // To get the covariance matrix, we need the curvature matrix at the minimum, so take more derivatives
            //    \frac{\partial^2 \ln L}{\partial m^2} = - \frac{1}{s} \sum_i e^{-z_i} = - \frac{n}{s^2}
            //    \frac{\partial^2 \ln L}{\partial m \partial s} = - \frac{n}{s^2} <z e^{-z}>
            //    \frac{\partial^2 \ln L}{\partial s^2} = - \frac{n}{s^2} ( <z^2 e^{-z}> + 1 )

            // Several crucial pieces of this analysis are taken from Mahdi and Cenac, "Estimating Parameters of Gumbel Distribution
            // "using the method of moments, probability weighted moments, and maximum likelihood", Revista de Mathematica:
            // Teoria y Aplicaciones 12 (2005) 151-156 (http://revistas.ucr.ac.cr/index.php/matematica/article/viewFile/259/239)

            // We will be needed the sample mean and standard deviation
            int    n;
            double mean, stdDev;

            Univariate.ComputeMomentsUpToSecond(sample, out n, out mean, out stdDev);
            stdDev = Math.Sqrt(stdDev / n);

            // Use the method of moments to get an initial estimate of s.
            double s0 = Math.Sqrt(6.0) / Math.PI * stdDev;

            // Define the function to zero
            Func <double, double> fnc = (double s) => {
                double u, v;
                MaximumLikelihoodHelper(sample, n, mean, s, out u, out v);
                return(s + v / u);
            };

            // Zero it to compute the best-fit s
            double s1 = FunctionMath.FindZero(fnc, s0);

            // Compute the corresponding best-fit m
            double u1, v1;

            MaximumLikelihoodHelper(sample, n, mean, s1, out u1, out v1);
            double m1 = mean - s1 * Math.Log(u1);

            // Compute the curvature matrix
            double w1 = 0.0;
            double w2 = 0.0;

            foreach (double x in sample)
            {
                double z = (x - m1) / s1;
                double e = Math.Exp(-z);
                w1 += z * e;
                w2 += z * z * e;
            }
            w1 /= sample.Count;
            w2 /= sample.Count;
            SymmetricMatrix C = new SymmetricMatrix(2);

            C[0, 0] = (n - 2) / (s1 * s1);
            C[0, 1] = (n - 2) / (s1 * s1) * w1;
            C[1, 1] = (n - 2) / (s1 * s1) * (w2 + 1.0);
            SymmetricMatrix CI = C.CholeskyDecomposition().Inverse();
            // The use of (n-2) here in place of n is a very ad hoc attempt to increase accuracy.


            // Compute goodness-of-fit
            GumbelDistribution dist = new GumbelDistribution(m1, s1);
            TestResult         test = sample.KolmogorovSmirnovTest(dist);

            return(new GumbelFitResult(m1, s1, CI[0, 0], CI[1, 1], CI[0, 1], test));
        }