Exemplo n.º 1
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 DiscreteDistributionAndValue(DiscreteDistribution dpdf, double value, DistributionsOperation action)
        {
            int length = dpdf.InnerSamples;

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

            double[] yCoordinates = new double[length];
            double[] xCoordinates = new double[length];

            switch (action)
            {
            case DistributionsOperation.Add:
            {
                for (int i = 0; i < length; i++)
                {
                    yCoordinates[i] = leftY[i];
                    xCoordinates[i] = leftX[i] + value;
                }
                break;
            }

            case DistributionsOperation.Sub:
            {
                for (int i = 0; i < length; i++)
                {
                    yCoordinates[i] = leftY[i];
                    xCoordinates[i] = leftX[i] - value;
                }
                break;
            }

            case DistributionsOperation.SubInv:
            {
                for (int i = 0; i < length; i++)
                {
                    yCoordinates[length - i - 1] = leftY[i];
                    xCoordinates[length - i - 1] = value - leftX[i];
                }
                break;
            }

            case DistributionsOperation.Muliply:
            {
                if (value == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.MultiplyRandomByZero);
                }

                if (value < 0)
                {
                    for (int i = 0; i < length; i++)
                    {
                        yCoordinates[length - i - 1] = leftY[i] / Math.Abs(value);
                        xCoordinates[length - i - 1] = leftX[i] * value;
                    }
                }
                else
                {
                    for (int i = 0; i < length; i++)
                    {
                        yCoordinates[i] = leftY[i] / Math.Abs(value);
                        xCoordinates[i] = leftX[i] * value;
                    }
                }
                break;
            }

            case DistributionsOperation.Divide:
            {
                if (value == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.DivisionByZero);
                }

                if (value < 0)
                {
                    for (int i = 0; i < length; i++)
                    {
                        yCoordinates[length - i - 1] = leftY[i] * Math.Abs(value);
                        xCoordinates[length - i - 1] = leftX[i] / value;
                    }
                }
                else
                {
                    for (int i = 0; i < length; i++)
                    {
                        yCoordinates[i] = leftY[i] * Math.Abs(value);
                        xCoordinates[i] = leftX[i] / value;
                    }
                }
                break;
            }

            default:
            {
                throw new NotImplementedException();
            }
            }

            return(new DiscreteDistribution(xCoordinates, yCoordinates));
        }
        private static DiscreteDistribution[] Swap(DiscreteDistribution dpdfLeft, DiscreteDistribution dpdfRight, DistributionsOperation action, out DistributionsOperation newAction)
        {
            double stepX = dpdfLeft.Step;
            double stepY = dpdfRight.Step;

            switch (action)
            {
            case DistributionsOperation.Add:
            {
                newAction = action;

                if (stepX < stepY)
                {
                    return(new DiscreteDistribution[] { dpdfRight, dpdfLeft });
                }
                else
                {
                    return(new DiscreteDistribution[] { dpdfLeft, dpdfRight });
                }
            }

            case DistributionsOperation.Sub:
            {
                if (stepX < stepY)
                {
                    newAction = DistributionsOperation.Add;
                    return(new DiscreteDistribution[] { Multiply(dpdfRight, -1), dpdfLeft });
                }
                else
                {
                    newAction = action;
                    return(new DiscreteDistribution[] { dpdfLeft, dpdfRight });
                }
            }

            case DistributionsOperation.Muliply:
            {
                newAction = action;

                // When one of distributions crossing Oy we need to exact locate them to eliminate 1/0 error on numerical integration
                if (dpdfRight.MinX <= 0 && dpdfRight.MaxX >= 0 && !(dpdfLeft.MinX <= 0 && dpdfLeft.MaxX >= 0))
                {
                    return(new DiscreteDistribution[] { dpdfRight, dpdfLeft });
                }
                else if (dpdfLeft.MinX <= 0 && dpdfLeft.MaxX >= 0 && !(dpdfRight.MinX <= 0 && dpdfRight.MaxX >= 0))
                {
                    return(new DiscreteDistribution[] { dpdfLeft, dpdfRight });
                }
                else
                {
                    if (stepX < stepY)
                    {
                        return(new DiscreteDistribution[] { dpdfRight, dpdfLeft });
                    }
                    else
                    {
                        return(new DiscreteDistribution[] { dpdfLeft, dpdfRight });
                    }
                }
            }

            default:
            {
                newAction = action;
                return(new DiscreteDistribution[] { dpdfLeft, dpdfRight });
            }
            }
        }
        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);
        }
Exemplo n.º 5
0
        private static DiscreteDistribution Operation(BaseDistribution dpdf, double value, DistributionsOperation action)
        {
            int length = dpdf.InnerSamples;

            double[] yCoordinates = new double[length];
            double[] xCoordinates;

            switch (action)
            {
            case DistributionsOperation.DivideInv:
            {
                if (value == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.DivisionOfZero);
                }

                if ((dpdf.InnerMinX < 0 && dpdf.InnerMaxX > 0) || dpdf.InnerMinX == 0 || dpdf.InnerMaxX == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.DivisionByZeroCrossingRandom);
                }

                double r1 = value / dpdf.InnerMinX;
                double r2 = value / dpdf.InnerMaxX;
                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                for (int i = 0; i < length; i++)
                {
                    double z = xCoordinates[i];
                    double d = value / z;
                    double k = Math.Abs(value) / Math.Pow(z, 2);

                    yCoordinates[i] = dpdf.InnerGetPDFYbyX(d) * k;
                }

                break;
            }

            case DistributionsOperation.Power:
            {
                if (value == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.ExponentialOfRandomInZeroPower);
                }

                if (value < 0 && ((dpdf.InnerMinX < 0 && dpdf.InnerMaxX > 0) || dpdf.InnerMinX == 0 || dpdf.InnerMaxX == 0))
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.ExponentialOfZeroCrossingRandomInNegativePower);
                }

                bool evenPower    = Math.Abs(value % 2) == 0;
                bool naturalPower = value - (int)value == 0;

                if (dpdf.InnerMinX < 0 && !naturalPower)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.ExponentialOfNotPositiveRandomInIrrationalPower);
                }

                double r1 = Math.Pow(dpdf.InnerMinX, value);
                double r2 = Math.Pow(dpdf.InnerMaxX, value);

                if (dpdf.InnerMinX < 0 && dpdf.InnerMaxX > 0 && evenPower)
                {
                    r2 = Math.Max(r1, r2);
                    r1 = 0;
                }

                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                for (int i = 0; i < length; i++)
                {
                    double d = Math.Sign(xCoordinates[i]) * Math.Pow(Math.Abs(xCoordinates[i]), 1d / value);
                    double k = Math.Abs(Math.Pow(Math.Abs(xCoordinates[i]), (1d - value) / value) / value);

                    yCoordinates[i] = dpdf.InnerGetPDFYbyX(d) * k;

                    if (evenPower)
                    {
                        yCoordinates[i] += dpdf.InnerGetPDFYbyX(-d) * k;
                    }
                }

                break;
            }

            case DistributionsOperation.PowerInv:
            {
                if (value == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.ExponentialOfZeroInRandomPower);
                }
                else if (value < 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.ExponentialOfNegativeInRandomPower);
                }
                else if (value == 1)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.ExponentialOfOneInRandomPower);
                }

                double r1 = Math.Pow(value, dpdf.InnerMinX);
                double r2 = Math.Pow(value, dpdf.InnerMaxX);

                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                for (int i = 0; i < length; i++)
                {
                    double d = Math.Log(xCoordinates[i], value);
                    double k = Math.Abs(Math.Log(value) * xCoordinates[i]);

                    yCoordinates[i] = dpdf.InnerGetPDFYbyX(d) / k;
                }

                break;
            }

            case DistributionsOperation.Log:
            {
                if (value == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmWithZeroBase);
                }
                else if (value < 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmWithNegativeBase);
                }
                else if (value == 1)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmWithOneBase);
                }

                if (dpdf.InnerMinX <= 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmOfNotPositiveRandom);
                }

                double r1 = Math.Log(dpdf.InnerMinX, value);
                double r2 = Math.Log(dpdf.InnerMaxX, value);

                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                for (int i = 0; i < length; i++)
                {
                    double d = Math.Pow(value, xCoordinates[i]);
                    double k = Math.Abs(Math.Log(value) * d);

                    yCoordinates[i] = dpdf.InnerGetPDFYbyX(d) * k;
                }
                break;
            }

            case DistributionsOperation.LogInv:
            {
                if (dpdf.InnerMinX <= 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmWithNotPositiveRandomBase);
                }

                if ((dpdf.InnerMinX < 1 && dpdf.InnerMaxX > 1) || dpdf.InnerMinX == 1 || dpdf.InnerMaxX == 1)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmWithOneCrossingRandomBase);
                }

                if (value == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmOfZeroValue);
                }

                if (value < 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmOfNegativeValue);
                }

                double r1 = Math.Log(value, dpdf.InnerMaxX);
                double r2 = Math.Log(value, dpdf.InnerMinX);

                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                for (int i = 0; i < length; i++)
                {
                    double d = Math.Pow(value, 1d / xCoordinates[i]);

                    double k = Math.Abs((d * Math.Log(value)) / Math.Pow(xCoordinates[i], 2));
                    yCoordinates[i] = dpdf.InnerGetPDFYbyX(d) * k;
                }

                break;
            }

            case DistributionsOperation.Abs:
            {
                double r1 = Math.Abs(dpdf.InnerMinX);
                double r2 = Math.Abs(dpdf.InnerMaxX);

                if (dpdf.InnerMinX <= 0 && dpdf.InnerMaxX >= 0)
                {
                    r2 = Math.Max(r1, r2);
                    r1 = 0;
                }

                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                for (int i = 0; i < length; i++)
                {
                    double zPow = xCoordinates[i];

                    yCoordinates[i] = dpdf.InnerGetPDFYbyX(zPow) + dpdf.InnerGetPDFYbyX(-zPow);
                }

                break;
            }

            case DistributionsOperation.Sin:
            {
                double r1 = -1;
                double r2 = 1;

                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                // Max asin [-PI/2, PI/2]
                int minJ = (int)(dpdf.MinX / (2 * Math.PI)) - 1;
                int maxJ = (int)(dpdf.MaxX / (2 * Math.PI)) + 1;

                for (int i = 0; i < length; i++)
                {
                    double z = xCoordinates[i];

                    double arcsin = Math.Asin(z);
                    double k      = 1d / Math.Sqrt(1 - Math.Pow(z, 2));

                    for (double j = minJ; j <= maxJ; j++)
                    {
                        double v = dpdf.InnerGetPDFYbyX((Math.PI * 2 * j) - (Math.PI + arcsin)) +
                                   dpdf.InnerGetPDFYbyX((Math.PI * 2 * j) + arcsin);

                        if (v != 0)
                        {
                            yCoordinates[i] += k * v;
                        }
                    }
                }

                break;
            }

            case DistributionsOperation.Cos:
            {
                // https://mathoverflow.net/questions/35260/resultant-probability-distribution-when-taking-the-cosine-of-gaussian-distribute
                // TODO: Verify for trigonometric functions work properly. And remove range?
                _ = GetTrigonometricRange(-1, 1, dpdf);

                double r1 = -1;
                double r2 = 1;

                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                // Max acos [0, PI]
                int minJ = (int)(dpdf.MinX / (2 * Math.PI)) - 1;
                int maxJ = (int)(dpdf.MaxX / (2 * Math.PI)) + 1;

                for (int i = 0; i < length; i++)
                {
                    double z = xCoordinates[i];

                    double acos = Math.Acos(z);
                    double k    = 1d / Math.Sqrt(1 - Math.Pow(z, 2));

                    for (double j = minJ; j <= maxJ; j++)
                    {
                        double v = dpdf.InnerGetPDFYbyX((2 * (j + 1) * Math.PI) - acos) +
                                   dpdf.InnerGetPDFYbyX((2 * j * Math.PI) + acos);

                        if (v != 0)
                        {
                            yCoordinates[i] += k * v;
                        }
                    }
                }

                break;
            }

            case DistributionsOperation.Tan:
            {
                if (dpdf.MaxX - dpdf.MinX >= Math.PI ||
                    dpdf.MinX % Math.PI <= -Math.PI / 2 ||
                    dpdf.MaxX % Math.PI >= Math.PI / 2)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.TangentOfValueCrossingAsymptote);
                }

                double r1 = Math.Tan(dpdf.MinX);
                double r2 = Math.Tan(dpdf.MaxX);

                xCoordinates = GenerateXAxis(r1, r2, length, out _);

                int j = dpdf.Mean < 0 ? (int)(dpdf.MinX / Math.PI) : (int)(dpdf.MaxX / Math.PI);

                for (int i = 0; i < length; i++)
                {
                    double z = xCoordinates[i];

                    double atan = Math.Atan(z);
                    double k    = 1d / (Math.Pow(z, 2) + 1);

                    double v = dpdf.InnerGetPDFYbyX((-Math.PI / 2d) + (Math.PI * j)) +
                               dpdf.InnerGetPDFYbyX(atan + (j * Math.PI));

                    if (v != 0)
                    {
                        yCoordinates[i] = k * v;
                    }
                }

                break;
            }

            default:
            {
                throw new NotImplementedException();
            }
            }

            return(new DiscreteDistribution(xCoordinates, yCoordinates));
        }
Exemplo n.º 6
0
        public static double[] GetRange(double min1, double max1, double min2, double max2, DistributionsOperation action)
        {
            double[] allBounds = new double[4];
            allBounds[0] = min1;
            allBounds[1] = max1;
            allBounds[2] = min2;
            allBounds[3] = max2;

            double[] result = new double[2];

            switch (action)
            {
            case DistributionsOperation.Add:
            {
                result[0] = min1 + min2;
                result[1] = max1 + max2;

                break;
            }

            case DistributionsOperation.Sub:
            {
                result[0] = min1 - max2;
                result[1] = max1 - min2;
                break;
            }

            case DistributionsOperation.Muliply:
            {
                double[] variants = new double[4];
                variants[0] = min1 * min2;
                variants[1] = min1 * max2;
                variants[2] = max1 * min2;
                variants[3] = max1 * max2;

                result[0] = variants.Min();
                result[1] = variants.Max();

                break;
            }

            case DistributionsOperation.Divide:
            {
                if (min2 == 0 || max2 == 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.DivisionByZeroCrossingRandom);
                }

                if (min2 < 0 && max2 > 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.DivisionByZeroCrossingRandom);
                }

                double[] variants = new double[4];
                variants[0] = min1 / min2;
                variants[1] = min1 / max2;
                variants[2] = max1 / min2;
                variants[3] = max1 / max2;

                result[0] = variants.Min();
                result[1] = variants.Max();

                break;
            }

            case DistributionsOperation.PowerInv:
            {
                if (min2 < 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.ExponentialOfNotPositiveRandomInIrrationalPower);
                }

                double[] variants = new double[4];
                variants[0] = Math.Pow(min2, min1);
                variants[1] = Math.Pow(max2, min1);
                variants[2] = Math.Pow(min2, max1);
                variants[3] = Math.Pow(max2, max1);

                result[0] = variants.Min();
                result[1] = variants.Max();

                break;
            }

            case DistributionsOperation.Log:
            {
                if (min1 <= 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmOfNotPositiveRandom);
                }

                if (min2 <= 0)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmWithNotPositiveRandomBase);
                }

                if ((min2 < 1 && max2 > 1) || min2 == 1 || max2 == 1)
                {
                    throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.LogarithmWithOneCrossingRandomBase);
                }

                double[] variants = new double[4];
                variants[0] = Math.Log(min1, min2);
                variants[1] = Math.Log(max1, min2);
                variants[2] = Math.Log(min1, max2);
                variants[3] = Math.Log(max1, max2);

                result[0] = variants.Min();
                result[1] = variants.Max();

                break;
            }

            default:
            {
                throw new NotImplementedException();
            }
            }

            return(result);
        }