Esempio 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 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);
        }