public void EmpiricalHazardConstructorTest3()
        {
            double[] times  = { 11, 10, 9, 8, 6, 5, 4, 2 };
            double[] values = { 0.22, 0.67, 1.00, 0.18, 1.00, 1.00, 1.00, 0.55 };


            EmpiricalHazardDistribution distribution = new EmpiricalHazardDistribution(times, values);


            double mean   = distribution.Mean;                                      // 0.93696461879063664
            double median = distribution.Median;                                    // 3.9999999151458066
            double var    = distribution.Variance;                                  // 2.0441627748096289
            double chf    = distribution.CumulativeHazardFunction(x: 4.2);          // 1.55
            double cdf    = distribution.DistributionFunction(x: 4.2);              // 0.7877520261732569
            double pdf    = distribution.ProbabilityDensityFunction(x: 4.2);        // 0.046694554241883471
            double lpdf   = distribution.LogProbabilityDensityFunction(x: 4.2);     // -3.0641277326297756
            double hf     = distribution.HazardFunction(x: 4.2);                    // 0.22
            double ccdf   = distribution.ComplementaryDistributionFunction(x: 4.2); // 0.21224797382674304
            double icdf   = distribution.InverseDistributionFunction(p: cdf);       // 4.3483975243778978

            string str = distribution.ToString();                                   // H(x; v, t)

            Assert.AreEqual(0.93696461879063664, mean);
            Assert.AreEqual(3.9999999151458066, median, 1e-6);
            Assert.AreEqual(2.0441627748096289, var);
            Assert.AreEqual(1.55, chf);
            Assert.AreEqual(0.7877520261732569, cdf);
            Assert.AreEqual(0.046694554241883471, pdf);
            Assert.AreEqual(-3.0641277326297756, lpdf);
            Assert.AreEqual(0.22, hf);
            Assert.AreEqual(0.21224797382674304, ccdf);
            Assert.AreEqual(4.3483975243778978, icdf, 1e-8);
            Assert.AreEqual("H(x; v, t)", str);
        }
        public void EmpiricalHazardConstructorTest3()
        {
            double[] times = { 11, 10, 9, 8, 6, 5, 4, 2 };
            double[] values = { 0.22, 0.67, 1.00, 0.18, 1.00, 1.00, 1.00, 0.55 };
            

            EmpiricalHazardDistribution distribution = new EmpiricalHazardDistribution(times, values);


            double mean = distribution.Mean; // 0.93696461879063664
            double median = distribution.Median; // 3.9999999151458066
            double var = distribution.Variance; // 2.0441627748096289
            double chf = distribution.CumulativeHazardFunction(x: 4.2); // 1.55
            double cdf = distribution.DistributionFunction(x: 4.2); // 0.7877520261732569
            double pdf = distribution.ProbabilityDensityFunction(x: 4.2); // 0.046694554241883471
            double lpdf = distribution.LogProbabilityDensityFunction(x: 4.2); // -3.0641277326297756
            double hf = distribution.HazardFunction(x: 4.2); // 0.22
            double ccdf = distribution.ComplementaryDistributionFunction(x: 4.2); // 0.21224797382674304
            double icdf = distribution.InverseDistributionFunction(p: cdf); // 4.3483975243778978

            string str = distribution.ToString(); // H(x; v, t)

            Assert.AreEqual(0.93696461879063664, mean);
            Assert.AreEqual(3.9999999151458066, median, 1e-6);
            Assert.AreEqual(2.0441627748096289, var);
            Assert.AreEqual(1.55, chf);
            Assert.AreEqual(0.7877520261732569, cdf);
            Assert.AreEqual(0.046694554241883471, pdf);
            Assert.AreEqual(-3.0641277326297756, lpdf);
            Assert.AreEqual(0.22, hf);
            Assert.AreEqual(0.21224797382674304, ccdf);
            Assert.AreEqual(4.3483975243778978, icdf, 1e-8);
            Assert.AreEqual("H(x; v, t)", str);
        }
        public void inverse_cdf()
        {
            // Consider the following hazard rates, occurring at the given time steps
            double[] times = { 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21 };

            double[] hazards =
            {
                0,                  0.111111111111111, 0.0625, 0.0714285714285714, 0.0769230769230769,
                0,                 0.0909090909090909,      0,  0.111111111111111,              0.125,0,
                0.166666666666667,                0.2,      0,                0.5, 0
            };

            var distribution = new EmpiricalHazardDistribution(times, hazards);

            Assert.AreEqual(0, distribution.Support.Min);
            Assert.AreEqual(22, distribution.Support.Max);

            Assert.AreEqual(0, distribution.InverseDistributionFunction(0));
            Assert.AreEqual(22, distribution.InverseDistributionFunction(1));
            Assert.AreEqual(22, distribution.InverseDistributionFunction(0.999));

            Assert.AreEqual(0, distribution.DistributionFunction(0));
            Assert.AreEqual(0.1051606831856301d, distribution.DistributionFunction(1));
            Assert.AreEqual(0.1593762566654946d, distribution.DistributionFunction(2));
            Assert.AreEqual(0.78033456236530996d, distribution.DistributionFunction(20));

            Assert.AreEqual(0.78033456236530996d, distribution.DistributionFunction(21));
            Assert.AreEqual(0.78033456236530996d, distribution.InnerDistributionFunction(21));

            Assert.AreEqual(1.0, distribution.DistributionFunction(22));
            Assert.AreEqual(1.0, distribution.InnerDistributionFunction(22));

            Assert.AreEqual(1.0, distribution.InnerDistributionFunction(23));
            Assert.AreEqual(1.0, distribution.InnerDistributionFunction(24));
            Assert.AreEqual(1.0, distribution.DistributionFunction(22));

            double[] percentiles = Vector.Interval(0.0, 1.0, stepSize: 0.1);

            for (int i = 0; i < percentiles.Length; i++)
            {
                double p    = percentiles[i];
                double icdf = distribution.InverseDistributionFunction(p);
                double cdf  = distribution.DistributionFunction(icdf);
                Assert.AreEqual(cdf, p, 0.1);
            }
        }
        public void DocumentationExample_Aalen()
        {
            // Consider the following hazard rates, occurring at the given time steps
            double[] times = { 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21 };

            double[] hazards =
            {
                0,                  0.111111111111111, 0.0625, 0.0714285714285714, 0.0769230769230769,
                0,                 0.0909090909090909,      0,  0.111111111111111,              0.125,0,
                0.166666666666667,                0.2,      0,                0.5, 0
            };

            // Create a new distribution given the observations and event times
            var distribution = new EmpiricalHazardDistribution(times, hazards);

            // Common measures
            double mean   = distribution.Mean;     // 6.1658527179584119
            double median = distribution.Median;   // 11.999999704601453
            double var    = distribution.Variance; // 44.101147497430993

            // Cumulative distribution functions
            double cdf  = distribution.DistributionFunction(x: 4);              //  0.275274821017619
            double ccdf = distribution.ComplementaryDistributionFunction(x: 4); //  0.724725178982381
            double icdf = distribution.InverseDistributionFunction(p: cdf);     //  4.4588994137113307

            // Probability density functions
            double pdf  = distribution.ProbabilityDensityFunction(x: 4);        //  0.055748090690952365
            double lpdf = distribution.LogProbabilityDensityFunction(x: 4);     // -2.8869121169242962

            // Hazard (failure rate) functions
            double hf  = distribution.HazardFunction(x: 4);           //  0.0769230769230769
            double chf = distribution.CumulativeHazardFunction(x: 4); //  0.32196275946275932

            string str = distribution.ToString();                     // H(x; v, t)

            try { double mode = distribution.Mode; Assert.Fail(); }
            catch { }

            Assert.AreEqual(SurvivalEstimator.FlemingHarrington, distribution.Estimator);
            Assert.AreEqual(1, distribution.ComplementaryDistributionFunction(0));
            Assert.AreEqual(0, distribution.ComplementaryDistributionFunction(Double.PositiveInfinity));

            Assert.AreEqual(6.1658527179584119, mean);
            Assert.AreEqual(11.999999704601453, median, 1e-6);
            Assert.AreEqual(44.101147497430993, var);
            Assert.AreEqual(0.32196275946275932, chf);
            Assert.AreEqual(0.275274821017619, cdf);
            Assert.AreEqual(0.055748090690952365, pdf);
            Assert.AreEqual(-2.8869121169242962, lpdf);
            Assert.AreEqual(0.0769230769230769, hf);
            Assert.AreEqual(0.724725178982381, ccdf);
            Assert.AreEqual(4.4588994137113307, icdf, 1e-8);
            Assert.AreEqual("H(x; v, t)", str);

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

            Assert.AreEqual(1, range1.Min, 1e-3);
            Assert.AreEqual(20.562, range1.Max, 1e-3);
            Assert.AreEqual(1, range2.Min, 1e-3);
            Assert.AreEqual(20.562, range2.Max, 1e-3);
            Assert.AreEqual(1, range3.Min, 1e-3);
            Assert.AreEqual(20.562, range3.Max, 1e-3);

            for (int i = 0; i < hazards.Length; i++)
            {
                Assert.AreEqual(hazards[i], distribution.HazardFunction(times[i]));
            }
        }
        public void DocumentationExample_KaplanMeier()
        {
            // Consider the following hazard rates, occurring at the given time steps
            double[] times = { 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21 };

            double[] hazards =
            {
                0,                  0.111111111111111, 0.0625, 0.0714285714285714, 0.0769230769230769,
                0,                 0.0909090909090909,      0,  0.111111111111111,              0.125,0,
                0.166666666666667,                0.2,      0,                0.5, 0
            };


            // Create a new distribution given the observations and event times
            var distribution = new EmpiricalHazardDistribution(times, hazards, SurvivalEstimator.KaplanMeier);

            // Common measures
            double mean   = distribution.Mean;     // 5.49198237428757
            double median = distribution.Median;   // 11.999999704601453
            double var    = distribution.Variance; // 39.83481657555663

            // Cumulative distribution functions
            double cdf  = distribution.DistributionFunction(x: 4);              //  0.275274821017619
            double ccdf = distribution.ComplementaryDistributionFunction(x: 4); //  0.018754904264376961
            double icdf = distribution.InverseDistributionFunction(p: cdf);     //  4.4588994137113307

            // Probability density functions
            double pdf  = distribution.ProbabilityDensityFunction(x: 4);        //  0.055748090690952365
            double lpdf = distribution.LogProbabilityDensityFunction(x: 4);     // -2.8869121169242962

            // Hazard (failure rate) functions
            double hf  = distribution.HazardFunction(x: 4);           //  0.0769230769230769
            double chf = distribution.CumulativeHazardFunction(x: 4); //  0.32196275946275932

            string str = distribution.ToString();                     // H(x; v, t)

            try { double mode = distribution.Mode; Assert.Fail(); }
            catch { }

            Assert.AreEqual(SurvivalEstimator.KaplanMeier, distribution.Estimator);
            Assert.AreEqual(1, distribution.ComplementaryDistributionFunction(0));
            Assert.AreEqual(0, distribution.ComplementaryDistributionFunction(Double.PositiveInfinity));

            Assert.AreEqual(5.49198237428757, mean);
            Assert.AreEqual(11.999999704601453, median, 1e-6);
            Assert.AreEqual(39.83481657555663, var);
            Assert.AreEqual(0.33647223662121273, chf);
            Assert.AreEqual(0.28571428571428559, cdf);
            Assert.AreEqual(0.054945054945054937, pdf);
            Assert.AreEqual(-2.9014215940827497, lpdf);
            Assert.AreEqual(0.0769230769230769, hf);
            Assert.AreEqual(0.71428571428571441, ccdf);
            Assert.AreEqual(5.8785425101214548, icdf, 1e-8);
            Assert.AreEqual("H(x; v, t)", str);

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

            Assert.AreEqual(1, range1.Min, 1e-3);
            Assert.AreEqual(20.562, range1.Max, 1e-3);
            Assert.AreEqual(1, range2.Min, 1e-3);
            Assert.AreEqual(20.562, range2.Max, 1e-3);
            Assert.AreEqual(1, range3.Min, 1e-3);
            Assert.AreEqual(20.562, range3.Max, 1e-3);

            for (int i = 0; i < hazards.Length; i++)
            {
                Assert.AreEqual(hazards[i], distribution.HazardFunction(times[i]));
            }
        }
        public void DocumentationExample_Aalen()
        {
            // Consider the following hazard rates, occurring at the given time steps
            double[] times = { 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21 };

            double[] hazards = 
            { 
                0, 0.111111111111111, 0.0625, 0.0714285714285714, 0.0769230769230769,
                0, 0.0909090909090909, 0, 0.111111111111111, 0.125, 0, 
                0.166666666666667, 0.2, 0, 0.5, 0 
            };

            // Create a new distribution given the observations and event times
            var distribution = new EmpiricalHazardDistribution(times, hazards);

            // Common measures
            double mean = distribution.Mean;     // 6.1658527179584119
            double median = distribution.Median; // 11.999999704601453
            double var = distribution.Variance;  // 44.101147497430993

            // Cumulative distribution functions
            double cdf = distribution.DistributionFunction(x: 4);               //  0.275274821017619
            double ccdf = distribution.ComplementaryDistributionFunction(x: 4); //  0.724725178982381
            double icdf = distribution.InverseDistributionFunction(p: cdf);     //  4.4588994137113307

            // Probability density functions
            double pdf = distribution.ProbabilityDensityFunction(x: 4);         //  0.055748090690952365
            double lpdf = distribution.LogProbabilityDensityFunction(x: 4);     // -2.8869121169242962

            // Hazard (failure rate) functions
            double hf = distribution.HazardFunction(x: 4);                      //  0.0769230769230769
            double chf = distribution.CumulativeHazardFunction(x: 4);           //  0.32196275946275932

            string str = distribution.ToString(); // H(x; v, t)

            try { double mode = distribution.Mode; Assert.Fail(); }
            catch { }

            Assert.AreEqual(SurvivalEstimator.FlemingHarrington, distribution.Estimator);
            Assert.AreEqual(1, distribution.ComplementaryDistributionFunction(0));
            Assert.AreEqual(0, distribution.ComplementaryDistributionFunction(Double.PositiveInfinity));

            Assert.AreEqual(6.1658527179584119, mean);
            Assert.AreEqual(11.999999704601453, median, 1e-6);
            Assert.AreEqual(44.101147497430993, var);
            Assert.AreEqual(0.32196275946275932, chf);
            Assert.AreEqual(0.275274821017619, cdf);
            Assert.AreEqual(0.055748090690952365, pdf);
            Assert.AreEqual(-2.8869121169242962, lpdf);
            Assert.AreEqual(0.0769230769230769, hf);
            Assert.AreEqual(0.724725178982381, ccdf);
            Assert.AreEqual(4.4588994137113307, icdf, 1e-8);
            Assert.AreEqual("H(x; v, t)", str);

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

            Assert.AreEqual(1, range1.Min, 1e-3);
            Assert.AreEqual(20.562, range1.Max, 1e-3);
            Assert.AreEqual(1, range2.Min, 1e-3);
            Assert.AreEqual(20.562, range2.Max, 1e-3);
            Assert.AreEqual(1, range3.Min, 1e-3);
            Assert.AreEqual(20.562, range3.Max, 1e-3);

            for (int i = 0; i < hazards.Length; i++)
                Assert.AreEqual(hazards[i], distribution.HazardFunction(times[i]));
        }
        public void DocumentationExample_KaplanMeier()
        {
            // Consider the following hazard rates, occurring at the given time steps
            double[] times = { 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21 };

            double[] hazards = 
            { 
                0, 0.111111111111111, 0.0625, 0.0714285714285714, 0.0769230769230769,
                0, 0.0909090909090909, 0, 0.111111111111111, 0.125, 0, 
                0.166666666666667, 0.2, 0, 0.5, 0 
            };


            // Create a new distribution given the observations and event times
            var distribution = new EmpiricalHazardDistribution(times, hazards, SurvivalEstimator.KaplanMeier);

            // Common measures
            double mean = distribution.Mean;     // 5.49198237428757
            double median = distribution.Median; // 11.999999704601453
            double var = distribution.Variance;  // 39.83481657555663

            // Cumulative distribution functions
            double cdf = distribution.DistributionFunction(x: 4);               //  0.275274821017619
            double ccdf = distribution.ComplementaryDistributionFunction(x: 4); //  0.018754904264376961
            double icdf = distribution.InverseDistributionFunction(p: cdf);     //  4.4588994137113307

            // Probability density functions
            double pdf = distribution.ProbabilityDensityFunction(x: 4);         //  0.055748090690952365
            double lpdf = distribution.LogProbabilityDensityFunction(x: 4);     // -2.8869121169242962

            // Hazard (failure rate) functions
            double hf = distribution.HazardFunction(x: 4);                      //  0.0769230769230769
            double chf = distribution.CumulativeHazardFunction(x: 4);           //  0.32196275946275932

            string str = distribution.ToString(); // H(x; v, t)

            try { double mode = distribution.Mode; Assert.Fail(); }
            catch { }

            Assert.AreEqual(SurvivalEstimator.KaplanMeier, distribution.Estimator);
            Assert.AreEqual(1, distribution.ComplementaryDistributionFunction(0));
            Assert.AreEqual(0, distribution.ComplementaryDistributionFunction(Double.PositiveInfinity));

            Assert.AreEqual(5.49198237428757, mean);
            Assert.AreEqual(11.999999704601453, median, 1e-6);
            Assert.AreEqual(39.83481657555663, var);
            Assert.AreEqual(0.33647223662121273, chf);
            Assert.AreEqual(0.28571428571428559, cdf);
            Assert.AreEqual(0.054945054945054937, pdf);
            Assert.AreEqual(-2.9014215940827497, lpdf);
            Assert.AreEqual(0.0769230769230769, hf);
            Assert.AreEqual(0.71428571428571441, ccdf);
            Assert.AreEqual(5.8785425101214548, icdf, 1e-8);
            Assert.AreEqual("H(x; v, t)", str);

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

            Assert.AreEqual(1, range1.Min, 1e-3);
            Assert.AreEqual(20.562, range1.Max, 1e-3);
            Assert.AreEqual(1, range2.Min, 1e-3);
            Assert.AreEqual(20.562, range2.Max, 1e-3);
            Assert.AreEqual(1, range3.Min, 1e-3);
            Assert.AreEqual(20.562, range3.Max, 1e-3);

            for (int i = 0; i < hazards.Length; i++)
                Assert.AreEqual(hazards[i], distribution.HazardFunction(times[i]));
        }