/// <summary>
        ///   Estimates an Empirical Hazards distribution considering event times and the outcome of the
        ///   observed sample at the time of event, plus additional parameters for the hazard estimation.
        /// </summary>
        ///
        /// <param name="time">The time of occurrence for the event.</param>
        /// <param name="outcome">The outcome at the time of event (failure or censored).</param>
        /// <param name="weights">The weights associated with each event.</param>
        /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param>
        /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param>
        /// <param name="ties">The method for handling event ties. Default is <see cref="HazardTiesMethod.Efron"/>.</param>
        ///
        /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns>
        ///
        public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome,
                                                           double[] weights, SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties)
        {
            var dist = new EmpiricalHazardDistribution(survival);

            dist.Fit(time, weights, new EmpiricalHazardOptions
            {
                Outcome   = outcome,
                Estimator = hazard,
                Ties      = ties
            });

            return(dist);
        }
        void init(double[] times, double[] hazards, SurvivalEstimator estimator)
        {
            if (times == null)
            {
                times = new double[0];
            }

            if (hazards == null)
            {
                hazards = new double[0];
            }

            times   = (double[])times.Clone();
            hazards = (double[])hazards.Clone();

            Array.Sort(times, hazards);

            for (int i = 0; i < times.Length - 1; i++)
            {
                if (times[i] > times[i + 1])
                {
                    throw new Exception();
                }
            }

            if (times.Length > 0)
            {
                this.range = new DoubleRange(0, times[times.Length - 1]);

                this.survivals    = new double[times.Length];
                this.survivals[0] = 1;
                for (int i = 1; i < survivals.Length; i++)
                {
                    survivals[i] = survivals[i - 1] * (1.0 - hazards[i - 1]);
                }
            }

            this.times     = times;
            this.hazards   = hazards;
            this.estimator = estimator;

            this.mean     = null;
            this.variance = null;
        }
        /// <summary>
        ///   Initializes a new instance of the <see cref="EmpiricalHazardDistribution"/> class.
        /// </summary>
        ///
        /// <param name="times">The time steps.</param>
        /// <param name="lambdas">The hazard rates at the time steps.</param>
        /// <param name="estimator">The survival function estimator to be used. Default is
        ///   <see cref="SurvivalEstimator.FlemingHarrington"/></param>
        ///
        public EmpiricalHazardDistribution(double[] times, double[] lambdas, SurvivalEstimator estimator)
        {
            if (times == null)
            {
                throw new ArgumentNullException("time");
            }

            if (lambdas == null)
            {
                throw new ArgumentNullException("values");
            }

            if (times.Length != lambdas.Length)
            {
                throw new DimensionMismatchException("time",
                                                     "The time steps and value vectors must have the same length.");
            }

            init(times, lambdas, estimator);
        }
 /// <summary>
 ///   Estimates an Empirical Hazards distribution considering event times and the outcome of the
 ///   observed sample at the time of event, plus additional parameters for the hazard estimation.
 /// </summary>
 ///
 /// <param name="time">The time of occurrence for the event.</param>
 /// <param name="outcome">The outcome at the time of event (failure or censored).</param>
 /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param>
 /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param>
 ///
 /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns>
 ///
 public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome,
                                                    SurvivalEstimator survival, HazardEstimator hazard)
 {
     return(Estimate(time, outcome, survival, hazard, EmpiricalHazardOptions.DefaultTies));
 }
        /// <summary>
        ///   Fits the underlying distribution to a given set of observations.
        /// </summary>
        ///
        /// <param name="observations">The array of observations to fit the model against. The array
        /// elements can be either of type double (for univariate data) or
        /// type double[] (for multivariate data).</param>
        /// <param name="weights">The weight vector containing the weight for each of the samples.</param>
        /// <param name="options">Optional arguments which may be used during fitting, such
        /// as regularization constants and additional parameters.</param>
        ///
        public void Fit(double[] observations, double[] weights, SurvivalOptions options)
        {
            SurvivalOutcome[] outcome = null;
            double[]          output  = weights;
            var estimator             = HazardEstimator.BreslowNelsonAalen;
            var ties = HazardTiesMethod.Breslow;

            if (options != null)
            {
                outcome = options.Outcome;
                var hazardOps = options as EmpiricalHazardOptions;
                if (hazardOps != null)
                {
                    estimator = hazardOps.Estimator;
                    ties      = hazardOps.Ties;
                }
            }

            if (outcome == null)
            {
                outcome = Vector.Create(observations.Length, SurvivalOutcome.Failed);
            }

            if (output == null)
            {
                output = Vector.Create(observations.Length, 1.0);
            }



            if (estimator == HazardEstimator.KaplanMeier)
            {
                double[] times   = observations.Distinct();
                double[] hazards = new double[times.Length];
                hazards[hazards.Length - 1] = 1;

                Array.Sort(times);

                // Compute an estimate of the hazard function using
                // the Kaplan-Meier estimator for the survival function

                double r = observations.Length;
                double d = 0; // Number of deaths
                double c = 0; // Number of censor

                for (int j = 0; j < times.Length; j++)
                {
                    double t = times[j];

                    // Survivals until time t
                    r = r - d - c;
                    d = 0;
                    c = 0;

                    for (int i = 0; i < observations.Length; i++)
                    {
                        if (observations[i] == t)
                        {
                            if (outcome[i] == SurvivalOutcome.Failed)
                            {
                                d++; // Failure at time t
                            }
                            else
                            {
                                c++; // Censored at time t
                            }
                        }
                    }

                    hazards[j] = d / r;
                }

                this.init(times, hazards, this.estimator);
                return;
            }
            else if (estimator == HazardEstimator.BreslowNelsonAalen)
            {
                double[] survivals = new double[observations.Length];

                Sort(ref observations, ref outcome, ref output);

                // Compute an estimate of the cumulative Hazard
                // function using the Breslow-Nelson-Aalen estimator

                double sum = 0;
                double d   = 0;
                for (int i = 0; i < observations.Length; i++)
                {
                    survivals[i] = 1;
                    double t = observations[i];
                    double v = output[i];
                    var    o = outcome[i];

                    sum += v;

                    if (o == SurvivalOutcome.Censored)
                    {
                        d = 0;
                        continue;
                    }

                    if (i > 0 && t != observations[i - 1])
                    {
                        d = 0;
                    }

                    // Count the number of deaths at t
                    if (o == SurvivalOutcome.Failed)
                    {
                        d++; // Deaths at time t
                    }
                    if (i < observations.Length - 1 && t == observations[i + 1] && outcome[i + 1] == SurvivalOutcome.Failed)
                    {
                        continue;
                    }

                    if (ties == HazardTiesMethod.Breslow)
                    {
                        survivals[i] = Math.Exp(-d / sum);
                    }
                    else
                    {
                        if (d == 1)
                        {
                            survivals[i] = Math.Pow(1 - v / sum, 1 / v);
                        }
                        else
                        {
                            survivals[i] = Math.Exp(-d / sum);
                        }
                    }
                }

                // Transform to hazards
                double[] hazards = new double[observations.Length];
                for (int i = 0; i < hazards.Length; i++)
                {
                    hazards[i] = -Math.Log(survivals[i]);
                }

                Array.Sort(observations, hazards);

                this.init(observations, hazards, this.estimator);
                return;
            }

            throw new ArgumentException();
        }
 /// <summary>
 ///   Initializes a new instance of the <see cref="EmpiricalHazardDistribution"/> class.
 /// </summary>
 ///
 /// <param name="estimator">The survival function estimator to be used. Default is
 ///   <see cref="SurvivalEstimator.FlemingHarrington"/></param>
 ///
 public EmpiricalHazardDistribution(SurvivalEstimator estimator)
 {
     init(null, null, estimator);
 }
 /// <summary>
 ///   Estimates an Empirical Hazards distribution considering event times and the outcome of the
 ///   observed sample at the time of event, plus additional parameters for the hazard estimation.
 /// </summary>
 ///
 /// <param name="time">The time of occurrence for the event.</param>
 /// <param name="outcome">The outcome at the time of event (failure or censored).</param>
 /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param>
 /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param>
 /// <param name="ties">The method for handling event ties. Default is <see cref="HazardTiesMethod.Efron"/>.</param>
 ///
 /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns>
 ///
 public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome,
                                                    SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties)
 {
     return(Estimate(time, outcome, null, survival, hazard, ties));
 }
 /// <summary>
 ///   Estimates an Empirical Hazards distribution considering event times and the outcome of the
 ///   observed sample at the time of event, plus additional parameters for the hazard estimation.
 /// </summary>
 ///
 /// <param name="time">The time of occurrence for the event.</param>
 /// <param name="outcome">The outcome at the time of event (failure or censored).</param>
 /// <param name="weights">The weights associated with each event.</param>
 /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param>
 /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param>
 /// <param name="ties">The method for handling event ties. Default is <see cref="HazardTiesMethod.Efron"/>.</param>
 ///
 /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns>
 ///
 public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome,
                                                    double[] weights, SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties)
 {
     return(Estimate(time, outcome.To <SurvivalOutcome[]>(), weights, survival, hazard, ties));
 }
 /// <summary>
 ///   Estimates an Empirical Hazards distribution considering event times and the outcome of the
 ///   observed sample at the time of event, plus additional parameters for the hazard estimation.
 /// </summary>
 ///
 /// <param name="time">The time of occurrence for the event.</param>
 /// <param name="weights">The weights associated with each event.</param>
 /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param>
 /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param>
 /// <param name="ties">The method for handling event ties. Default is <see cref="HazardTiesMethod.Efron"/>.</param>
 ///
 /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns>
 ///
 public static EmpiricalHazardDistribution Estimate(double[] time, double[] weights = null,
                                                    SurvivalEstimator survival      = EmpiricalHazardOptions.DefaultSurvival,
                                                    HazardEstimator hazard          = EmpiricalHazardOptions.DefaultEstimator, HazardTiesMethod ties = EmpiricalHazardOptions.DefaultTies)
 {
     return(Estimate(time, (SurvivalOutcome[])null, weights, survival, hazard, ties));
 }