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