internal override BaseDistribution InnerGetRatio(BaseDistribution value) { switch (value.InnerDistributionType) { case DistributionType.Number: { return(DiscreteRandomMath.Divide(this, (double)value)); } case DistributionType.Discrete: { return(DiscreteRandomMath.Divide(this, (DiscreteDistribution)value)); } case DistributionType.Continious: { return(DiscreteRandomMath.Divide(this, (DiscreteDistribution)(ContinuousDistribution)value)); } default: { throw new DistributionsInvalidOperationException(); } } }
internal override BaseDistribution InnerGetSumm(BaseDistribution value) { switch (value.InnerDistributionType) { case DistributionType.Continious: { var right = (ContinuousDistribution)value; if (BaseDistribution is NormalDistribution && right.BaseDistribution is NormalDistribution) { return(ContinuousRandomMath.ConvolutionOfNormalAndNormal(this, right)); } else if (BaseDistribution is UniformContinuousDistribution && right.BaseDistribution is UniformContinuousDistribution) { return(ContinuousRandomMath.ConvolutionOfUniformAndUniform(this, right)); } else if (BaseDistribution is NormalDistribution && right.BaseDistribution is UniformContinuousDistribution) { return(ContinuousRandomMath.ConvolutionOfNormalAndUniform(this, right)); } else if (BaseDistribution is UniformContinuousDistribution && right.BaseDistribution is NormalDistribution) { return(ContinuousRandomMath.ConvolutionOfNormalAndUniform(right, this)); } else if (BaseDistribution is NormalDistribution && right.BaseDistribution is BhattacharjeeDistribution) { return(ContinuousRandomMath.ConvolutionOfNormalAndBhattacharjee(this, right)); } else if (BaseDistribution is BhattacharjeeDistribution && right.BaseDistribution is NormalDistribution) { return(ContinuousRandomMath.ConvolutionOfNormalAndBhattacharjee(right, this)); } else if (BaseDistribution is StudentGeneralizedDistribution && right.BaseDistribution is UniformContinuousDistribution) { return(ContinuousRandomMath.ConvolutionOfStudentAndUniform(this, right)); } else if (BaseDistribution is UniformContinuousDistribution && right.BaseDistribution is StudentGeneralizedDistribution) { return(ContinuousRandomMath.ConvolutionOfStudentAndUniform(right, this)); } else { return(Discretize() + right.Discretize()); } } case DistributionType.Discrete: { return(Discretize() + value); } case DistributionType.Number: { return(ContinuousRandomMath.Add(this, (double)value)); } default: throw new DistributionsInvalidOperationException(); } }
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(); } } }
internal override double InnerGetPDFYbyX(double x) { try { if (x < InnerMinX || x > InnerMaxX) { return(0); } else if (Coefficient == 1 && Offset == 0) { return(BaseDistribution.ProbabilityDensityFunction(x)); } else if (Coefficient == 1) { return(BaseDistribution.ProbabilityDensityFunction(x - Offset)); } else { return(BaseDistribution.ProbabilityDensityFunction((x - Offset) / Coefficient) / Math.Abs(Coefficient)); } } catch { return(0); } }
internal override BaseDistribution InnerGetSumm(BaseDistribution value) { switch (value.InnerDistributionType) { case DistributionType.Number: { return(Mean + value.InnerMean); } case DistributionType.Continious: { return(ContinuousRandomMath.Add((ContinuousDistribution)value, Mean)); } case DistributionType.Discrete: { return(DiscreteRandomMath.Add((DiscreteDistribution)value, Mean)); } default: { throw new DistributionsInvalidOperationException(); } } }
private double GetSupport(bool min, double tolerance) { if (min) { return(BaseDistribution.InverseDistributionFunction(tolerance)); } else { return(BaseDistribution.InverseDistributionFunction(1 - tolerance)); } }
internal override double InnerGetCDFYbyX(double x) { try { if (x < InnerMinX || x > InnerMaxX) { return(0); } else { return(BaseDistribution.DistributionFunction((x - Offset) / Coefficient)); } } catch { return(0); } }
internal bool CheckDistributions(BaseDistribution left, BaseDistribution right) { var leftCont = left as ContinuousDistribution; var rightCont = right as ContinuousDistribution; if (BaseLeft.BaseDistribution == leftCont?.BaseDistribution && BaseRight.BaseDistribution == rightCont?.BaseDistribution) { return(true); } else if (BaseLeft.BaseDistribution == rightCont?.BaseDistribution && BaseRight.BaseDistribution == leftCont?.BaseDistribution) { return(true); } else { return(false); } }
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(); } } }
public CorrelatedPair(BaseDistribution left, BaseDistribution right, double rho) { if (left == null) { throw new ArgumentNullException(nameof(left)); } if (right == null) { throw new ArgumentNullException(nameof(right)); } if (left.DistributionType != DistributionType.Continious || right.DistributionType != DistributionType.Continious) { throw new DistributionsArgumentException(DistributionsArgumentExceptionType.ForCorrelationPairBothOfDistributionsMustBeContinuous); } BaseLeft = (ContinuousDistribution)left; BaseRight = (ContinuousDistribution)right; Correlation = rho; }
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 InnerGetDifference(BaseDistribution value) { switch (value.InnerDistributionType) { case DistributionType.Continious: { return(this + (value * -1)); } case DistributionType.Discrete: { return(Discretize() - value); } case DistributionType.Number: { return(ContinuousRandomMath.Sub(this, (double)value)); } default: throw new DistributionsInvalidOperationException(); } }
private static double[] GetTrigonometricRange(double min, double max, BaseDistribution dpdf) { double[] range = new double[2]; if (dpdf.MinX >= min && dpdf.MinX <= max) { range[0] = dpdf.MinX; } else { range[0] = min; } if (dpdf.MaxX >= min && dpdf.MaxX <= max) { range[1] = dpdf.MaxX; } else { range[1] = max; } return(range); }
internal BivariateContinuousDistribution GetBivariate(BaseDistribution left, BaseDistribution right) { if (CheckDistributions(left, right)) { Used = true; var contLeft = (ContinuousDistribution)left; var contRight = (ContinuousDistribution)right; var samples = Math.Max(contLeft.Samples, contRight.Samples); if (contLeft.BaseDistribution is NormalDistribution && contRight.BaseDistribution is NormalDistribution) { return(new BivariateNormalDistribution(left.Mean, right.Mean, left.StandardDeviation, right.StandardDeviation, Correlation * Math.Sign(contRight.Coefficient), samples)); } else if (contLeft.BaseDistribution is StudentGeneralizedDistribution && contRight.BaseDistribution is StudentGeneralizedDistribution) { var leftT = (StudentGeneralizedDistribution)contLeft.BaseDistribution; var rightT = (StudentGeneralizedDistribution)contRight.BaseDistribution; if (leftT.DegreesOfFreedom != rightT.DegreesOfFreedom) { throw new ArgumentException(); } return(new BivariateTDistribution(left.Mean, right.Mean, leftT.ScaleCoefficient * contLeft.Coefficient, rightT.ScaleCoefficient * contRight.Coefficient, Correlation * Math.Sign(contRight.Coefficient), leftT.DegreesOfFreedom, samples)); } else { throw new NotImplementedException(); } } else { throw new DistributionsInvalidOperationException(); } }
internal override BaseDistribution InnerGetRatio(BaseDistribution value) { switch (value.InnerDistributionType) { case DistributionType.Continious: case DistributionType.Discrete: { return(Discretize() / value); } case DistributionType.Number: { if (value.InnerMean == 0) { throw new DistributionsInvalidOperationException(DistributionsInvalidOperationExceptionType.DivisionByZero); } return(ContinuousRandomMath.Divide(this, (double)value)); } default: throw new DistributionsInvalidOperationException(); } }
public static DiscreteDistribution Power(double value, BaseDistribution dpdf) { return(Operation(dpdf, value, DistributionsOperation.PowerInv)); }
internal abstract BaseDistribution InnerGetRatio(BaseDistribution value);
internal abstract BaseDistribution InnerGetPower(BaseDistribution value);
internal abstract BaseDistribution InnerGetLog(BaseDistribution nBase);
public static BaseDistribution Power(BaseDistribution dpdf, double value) { return(Operation(dpdf, value, DistributionsOperation.Power)); }
public static DiscreteDistribution Cos(BaseDistribution distribution) { return(Operation(distribution, 0, DistributionsOperation.Cos)); }
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)); }
public static DiscreteDistribution Tan(BaseDistribution distribution) { return(Operation(distribution, 0, DistributionsOperation.Tan)); }
public static DiscreteDistribution Log(BaseDistribution dpdf, double nBase) { return(Operation(dpdf, nBase, DistributionsOperation.Log)); }
internal abstract BaseDistribution InnerGetProduct(BaseDistribution value);
public static DiscreteDistribution Abs(BaseDistribution dpdf) { return(Operation(dpdf, 0, DistributionsOperation.Abs)); }
internal override double InnerQuantile(double p) { return((BaseDistribution.InverseDistributionFunction(p) * Coefficient) + Offset); }
public static DiscreteDistribution Log(double value, BaseDistribution nBase) { return(Operation(nBase, value, DistributionsOperation.LogInv)); }
public static DiscreteDistribution Divide(double value, BaseDistribution dpdf) { return(Operation(dpdf, value, DistributionsOperation.DivideInv)); }
internal abstract BaseDistribution InnerGetDifference(BaseDistribution value);