internal override BaseDistribution InnerGetLog(BaseDistribution nBase)
        {
            switch (nBase.InnerDistributionType)
            {
            case DistributionType.Number:
            {
                return(CommonRandomMath.Log(this, (double)nBase));
            }

            case DistributionType.Continious:
            {
                return(DiscreteRandomMath.Log(Discretize(), (DiscreteDistribution)(ContinuousDistribution)nBase));
            }

            case DistributionType.Discrete:
            {
                return(DiscreteRandomMath.Log(Discretize(), (DiscreteDistribution)nBase));
            }

            default:
            {
                throw new DistributionsInvalidOperationException();
            }
            }
        }
        private static PrivateCoordinates DiscretizeContinious(ContinuousDistribution continiousDistribution, int samples)
        {
            if (samples < 2)
            {
                throw new DistributionsArgumentException(DistributionsArgumentExceptionType.SamplesNumberMustBeGreaterThenTwo);
            }

            if (continiousDistribution == null)
            {
                throw new ArgumentNullException(nameof(continiousDistribution));
            }

            double[] xAxis = CommonRandomMath.GenerateXAxis(continiousDistribution.InnerMinX, continiousDistribution.InnerMaxX, samples, out _);

            double[] pdf = new double[samples];

            for (int i = 0; i < samples; i++)
            {
                double x = xAxis[i];
                pdf[i] = continiousDistribution.InnerGetPDFYbyX(x);
            }

            return(new PrivateCoordinates {
                XCoordinates = xAxis, PDFCoordinates = pdf, FromContinuous = true
            });
        }
        internal override double InnerQuantile(double p)
        {
            double[] cdf          = CDFCoordinatesInternal;
            double[] xCoordinates = XCoordinatesInternal;

            if (p < cdf[0])
            {
                return(double.NegativeInfinity);
            }
            else if (p > cdf[length - 1])
            {
                return(double.PositiveInfinity);
            }
            else
            {
                for (int i = 0; i < length - 1; i++)
                {
                    double x0 = cdf[i];
                    double x1 = cdf[i + 1];

                    if (x0 <= p && x1 >= p)
                    {
                        double y0     = xCoordinates[i];
                        double y1     = xCoordinates[i + 1];
                        double result = CommonRandomMath.InterpolateLinear(x0, x1, y0, y1, p);
                        return(result);
                    }
                }

                return(double.NaN);
            }
        }
        private static BasicDistributionData GenerateBasicData(DistributionsEvaluator evaluator, Dictionary <string, DistributionSettings> univariateDistributions, Dictionary <string[], MultivariateDistributionSettings> multivariateDistributions, int samples, int pockets)
        {
            if (evaluator == null)
            {
                throw new ArgumentNullException(nameof(evaluator));
            }

            if (univariateDistributions == null)
            {
                throw new ArgumentNullException(nameof(univariateDistributions));
            }

            if (samples < 3)
            {
                throw new DistributionsArgumentException(DistributionsArgumentExceptionType.NumberOfExperimentsMustBeGreaterThenTwo);
            }

            if (pockets < 3)
            {
                throw new DistributionsArgumentException(DistributionsArgumentExceptionType.NumberOfPocketsMustBeGreaterThenTwo);
            }

            BasicDistributionData data = new BasicDistributionData();

            double[] random;

            if (multivariateDistributions == null)
            {
                random = GenerateRandom(evaluator, univariateDistributions, samples);
            }
            else
            {
                random = GenerateRandom(evaluator, univariateDistributions, multivariateDistributions, samples);
            }

            Array.Sort(random);

            double[] xAxis = CommonRandomMath.GenerateXAxis(random[0], random[samples - 1], pockets, out _);

            double[] cdf = GenerateCDF(xAxis, random);

            data.RandomSorted = random;
            data.XAxis        = xAxis;
            data.CDF          = cdf;
            data.PDF          = Derivate(cdf, xAxis[pockets - 1] - xAxis[0]);

            return(data);
        }
        internal override BaseDistribution InnerGetPower(BaseDistribution value)
        {
            switch (value.InnerDistributionType)
            {
            case DistributionType.Number:
            {
                return(Math.Pow(Mean, (double)value));
            }

            case DistributionType.Discrete:
            case DistributionType.Continious:
            {
                return(CommonRandomMath.Power(Mean, value));
            }

            default:
            {
                throw new DistributionsInvalidOperationException();
            }
            }
        }
        internal override BaseDistribution InnerGetRatio(BaseDistribution value)
        {
            switch (value.InnerDistributionType)
            {
            case DistributionType.Number:
            {
                return(Mean / value.InnerMean);
            }

            case DistributionType.Continious:
            case DistributionType.Discrete:
            {
                return(CommonRandomMath.Divide(Mean, value));
            }

            default:
            {
                throw new DistributionsInvalidOperationException();
            }
            }
        }
        private double[] GetDiscretizationSupport()
        {
            bool minInfinite = double.IsInfinity(BaseDistribution.Support.Min);
            bool maxInfinite = double.IsInfinity(BaseDistribution.Support.Max);

            double tolerance = CommonRandomMath.GetTolerance(InnerSamples);
            double min       = minInfinite ? GetSupport(true, tolerance) : BaseDistribution.Support.Min;
            double max       = maxInfinite ? GetSupport(false, tolerance) : BaseDistribution.Support.Max;

            min = (min * Coefficient) + Offset;
            max = (max * Coefficient) + Offset;

            if (min > max)
            {
                double temp = min;
                min = max;
                max = temp;
            }

            return(new double[] { min, max });
        }
Exemplo n.º 8
0
        private static DiscreteDistribution Bivariate(BivariateContinuousDistribution distribution, DistributionsOperation operation)
        {
            if (operation == DistributionsOperation.PowerInv)
            {
                distribution = distribution.Rotate();
            }

            int samples = distribution.Samples;

            double[] range = CommonRandomMath.GetRange(distribution.SupportMinLeft, distribution.SupportMaxLeft, distribution.SupportMinRight, distribution.SupportMaxRight, operation);

            double[] rightAxis = CommonRandomMath.GenerateXAxis(distribution.SupportMinRight, distribution.SupportMaxRight, samples, out double rightStep);
            double[] xAxis     = CommonRandomMath.GenerateXAxis(range[0], range[1], samples, out double step);

            double[] result = new double[samples];

            switch (operation)
            {
            case DistributionsOperation.Add:
            {
                Parallel.For(0, xAxis.Length, i =>
                    {
                        double x   = xAxis[i];
                        double sum = 0;

                        // Trap rule is useless because both normal and t-distributions are smoooth.
                        for (int j = 1; j < samples; j++)
                        {
                            double m = rightAxis[j];

                            sum += distribution.ProbabilityDensityFunction(x - m, m);
                        }

                        result[i] = sum * rightStep;
                    });

                break;
            }

            case DistributionsOperation.Sub:
            {
                Parallel.For(0, xAxis.Length, i =>
                    {
                        double x   = xAxis[i];
                        double sum = 0;

                        for (int j = 1; j < samples; j++)
                        {
                            double m = rightAxis[j];
                            sum     += distribution.ProbabilityDensityFunction(x + m, m);
                        }

                        result[i] = sum * rightStep;
                    });

                break;
            }

            case DistributionsOperation.Muliply:
            {
                Parallel.For(0, xAxis.Length, i =>
                    {
                        double x   = xAxis[i];
                        double sum = 0;

                        for (int j = 1; j < samples; j++)
                        {
                            double m = rightAxis[j];

                            if (m != 0)
                            {
                                sum += distribution.ProbabilityDensityFunction(x / m, m) / Math.Abs(m);
                            }
                        }

                        result[i] = sum * rightStep;
                    });

                break;
            }

            case DistributionsOperation.Divide:
            {
                Parallel.For(0, xAxis.Length, i =>
                    {
                        double x   = xAxis[i];
                        double sum = 0;

                        for (int j = 1; j < samples; j++)
                        {
                            double m = rightAxis[j];

                            if (m != 0)
                            {
                                sum += distribution.ProbabilityDensityFunction(x * m, m) * Math.Abs(m);
                            }
                        }

                        result[i] = sum * rightStep;
                    });

                break;
            }

            case DistributionsOperation.PowerInv:
            {
                Parallel.For(0, xAxis.Length, i =>
                    {
                        double m   = 0;
                        double sum = 0;
                        double x   = xAxis[i];
                        double d   = 0;
                        double k   = 0;
                        for (int j = 1; j < samples; j++)
                        {
                            m = rightAxis[j];

                            d = Math.Log(x, m);
                            k = Math.Abs(Math.Log(m) * x);

                            sum += distribution.ProbabilityDensityFunction(d, m) / k;
                        }

                        result[i] = sum * rightStep;
                    });

                break;
            }

            case DistributionsOperation.Log:
            {
                Parallel.For(0, xAxis.Length, i =>
                    {
                        double m   = 0;
                        double sum = 0;
                        double x   = xAxis[i];
                        double d   = 0;
                        double k   = 0;

                        for (int j = 1; j < samples; j++)
                        {
                            m = rightAxis[j];

                            d    = Math.Pow(m, x);
                            k    = Math.Abs(Math.Log(m) * d);
                            sum += distribution.ProbabilityDensityFunction(d, m) * k;
                        }

                        result[i] = sum * rightStep;
                    });

                break;
            }

            default:
            {
                throw new DistributionsInvalidOperationException();
            }
            }

            return(new DiscreteDistribution(xAxis, result));
        }
        private static DiscreteDistribution TwoDiscreteDistributions(DiscreteDistribution dpdfLeft, DiscreteDistribution dpdfRight, DistributionsOperation action)
        {
            var exchange = Swap(dpdfLeft, dpdfRight, action, out DistributionsOperation newAction);

            action = newAction;

            dpdfLeft  = exchange[0];
            dpdfRight = exchange[1];

            int lengthLeft  = dpdfLeft.InnerSamples;
            int lengthRight = dpdfRight.InnerSamples;

            double stepRight = dpdfRight.Step;
            double stepLeft  = dpdfLeft.Step;

            double leftMinX = dpdfLeft.MinX;
            double leftMaxX = dpdfLeft.MaxX;

            double[] leftX = dpdfLeft.XCoordinatesInternal;
            double[] leftY = dpdfLeft.YCoordinatesInternal;

            double[] rightX = dpdfRight.XCoordinatesInternal;
            double[] rightY = dpdfRight.YCoordinatesInternal;

            double[] yCoordinates = new double[lengthRight];

            double[] range = CommonRandomMath.GetRange(dpdfLeft.InnerMinX, dpdfLeft.InnerMaxX, dpdfRight.InnerMinX, dpdfRight.InnerMaxX, action);

            double[] xCoordinates = CommonRandomMath.GenerateXAxis(range[0], range[1], lengthRight, out double stepX0);

            switch (action)
            {
            case DistributionsOperation.Add:
            {
                List <int> operations = new List <int>();

                Parallel.For(0, lengthRight, i =>
                    {
                        double m   = 0;
                        double x   = xCoordinates[i];
                        double sum = 0;
                        double y   = 0;
                        double r   = 0;

                        for (int j = 0; j < lengthRight; j++)
                        {
                            m = rightX[j];
                            y = rightY[j];

                            r = y * GetYByX(x - m, leftY, leftMinX, leftMaxX, stepLeft, lengthLeft);

                            if (j == 0 || j == lengthRight - 1)
                            {
                                r /= 2;
                            }

                            sum += r;
                        }
                        yCoordinates[i] = sum * stepRight;
                    });

                break;
            }

            case DistributionsOperation.Sub:
            {
                Parallel.For(0, lengthRight, i =>
                    {
                        double m   = 0;
                        double x   = xCoordinates[i];
                        double sum = 0;
                        double r   = 0;
                        double y   = 0;

                        for (int j = 0; j < lengthRight; j++)
                        {
                            m = rightX[j];
                            y = rightY[j];

                            r = y * GetYByX(x + m, leftY, leftMinX, leftMaxX, stepLeft, lengthLeft);

                            if (j == 0 || j == lengthRight - 1)
                            {
                                r /= 2;
                            }

                            sum += r;
                        }

                        yCoordinates[i] = sum * stepRight;
                    });

                break;
            }

            case DistributionsOperation.Muliply:
            {
                Parallel.For(0, lengthRight, i =>
                    {
                        double m   = 0;
                        double sum = 0;
                        double x   = xCoordinates[i];
                        double k   = 0;
                        double r   = 0;
                        double y   = 0;

                        for (int j = 0; j < lengthRight; j++)
                        {
                            m = rightX[j];
                            y = rightY[j];
                            k = Math.Abs(m);

                            if (k != 0)
                            {
                                r = y * GetYByX(x / m, leftY, leftMinX, leftMaxX, stepLeft, lengthLeft) / k;

                                if (j == 0 || j == lengthRight - 1)
                                {
                                    r /= 2;
                                }

                                sum += r;
                            }
                        }

                        yCoordinates[i] = sum * stepRight;
                    });

                // in case when both of distributions cross Oy it is inf in zero
                if (dpdfLeft.MinX <= 0 && dpdfLeft.MaxX >= 0 && dpdfRight.MinX <= 0 && dpdfRight.MaxX >= 0)
                {
                    for (int i = 0; i < lengthRight - 1; i++)
                    {
                        if (xCoordinates[i] <= 0 && xCoordinates[i + 1] > 0)
                        {
                            yCoordinates[i] = double.PositiveInfinity;
                            break;
                        }
                    }
                }

                break;
            }

            case DistributionsOperation.Divide:
            {
                Parallel.For(0, lengthRight, i =>
                    {
                        double m   = 0;
                        double sum = 0;
                        double x   = xCoordinates[i];
                        double k   = 0;
                        double r   = 0;
                        double y   = 0;

                        for (int j = 0; j < lengthRight; j++)
                        {
                            m = rightX[j];
                            y = rightY[j];
                            k = Math.Abs(m);

                            if (k != 0)
                            {
                                r = y * GetYByX(x * m, leftY, leftMinX, leftMaxX, stepLeft, lengthLeft) * k;

                                if (j == 0 || j == lengthRight - 1)
                                {
                                    r /= 2;
                                }

                                sum += r;
                            }
                        }

                        yCoordinates[i] = sum * stepRight;
                    });

                break;
            }

            case DistributionsOperation.PowerInv:
            {
                Parallel.For(0, lengthRight, i =>
                    {
                        double m   = 0;
                        double sum = 0;
                        double x   = xCoordinates[i];
                        double k   = 0;
                        double r   = 0;
                        double y   = 0;

                        for (int j = 0; j < lengthRight; j++)
                        {
                            m = rightX[j];
                            y = rightY[j];
                            k = Math.Abs(Math.Log(m) * x);

                            if (k != 0)
                            {
                                r = y * GetYByX(Math.Log(x, m), leftY, leftMinX, leftMaxX, stepLeft, lengthLeft) / k;

                                if (j == 0 || j == lengthRight - 1)
                                {
                                    r /= 2;
                                }

                                sum += r;
                            }
                        }

                        yCoordinates[i] = sum * stepRight;
                    });

                break;
            }

            case DistributionsOperation.Log:
            {
                Parallel.For(0, lengthRight, i =>
                    {
                        double m   = 0;
                        double sum = 0;
                        double x   = xCoordinates[i];
                        double d   = 0;
                        double k   = 0;
                        double r   = 0;
                        double y   = 0;

                        for (int j = 0; j < lengthRight; j++)
                        {
                            m = rightX[j];
                            y = rightY[j];
                            d = Math.Pow(m, x);
                            k = Math.Abs(Math.Log(m) * d);

                            if (k != 0)
                            {
                                r = y * GetYByX(d, leftY, leftMinX, leftMaxX, stepLeft, lengthLeft) * k;

                                if (j == 0 || j == lengthRight - 1)
                                {
                                    r /= 2;
                                }

                                sum += r;
                            }
                        }

                        yCoordinates[i] = sum * stepRight;
                    });

                break;
            }

            default:
            {
                throw new NotImplementedException();
            }
            }
            var result = new DiscreteDistribution(xCoordinates, yCoordinates);

            return(result);
        }
 internal override BaseDistribution InnerGetAbs()
 {
     return(CommonRandomMath.Abs(this));
 }
        private static PrivateCoordinates Resample(PrivateCoordinates coordinates)
        {
            var pdf    = coordinates.PDFCoordinates;
            int length = coordinates.XCoordinates.Length;

            double min = coordinates.XCoordinates[0];
            double max = coordinates.XCoordinates[length - 1];

            double step = (max - min) / (length - 1);

            AnalyzeInfinities(pdf, step);
            Normalize(pdf, step);

            double[] cdf       = GetCDF(pdf, step);
            double   tolerance = CommonRandomMath.GetTolerance(length);

            var minI = 0;
            var maxI = length - 1;

            for (int i = 0; i < length - 1; i++)
            {
                var c = cdf[i];

                if (c < tolerance)
                {
                    if (pdf[i] == 0)
                    {
                        minI = i + 1;
                    }
                    else
                    {
                        minI = i;
                    }
                }
                if (c > 1 - tolerance)
                {
                    if (pdf[i] == 0)
                    {
                        maxI = i - 1;
                    }
                    else
                    {
                        maxI = i;
                    }
                    break;
                }
            }

            min = coordinates.XCoordinates[minI];
            max = coordinates.XCoordinates[maxI];

            int r = maxI - minI + 1;

            if (r != length)
            {
                double[] newX = CommonRandomMath.GenerateXAxis(min, max, length, out _);
                double[] newY = new double[r];

                for (int i = 0; i < r; i++)
                {
                    newY[i] = coordinates.PDFCoordinates[i + minI];
                }
                newY = CommonRandomMath.Resample(newY, length);

                return(new PrivateCoordinates {
                    XCoordinates = newX, PDFCoordinates = newY
                });
            }
            else
            {
                return(coordinates);
            }
        }