Appendix A describes four basic methods for generating random variates:
Consider a random variable, \(X\), that represents the time until failure for a machine tool. Suppose \(X\) is exponentially distributed with an expected value of \(1.\overline{33}\). Generate a random variate for the time until the first failure using a uniformly distributed value of \(u = 0.7\).
Use the following pseudo-random numbers \(u_{1} = 0.35\), \(u_{2} = 0.64\), \(u_{3} = 0.14\), generate a random variate from a shifted negative binomial distribution having parameters \(r=3\) and \(p= 0.3\).
ksl.utilities.random.rvariable package supports this functionality.d is a reference to an instance of a sub-class of type RVariable, then d.value generates a random value via the GetValueIfc interface.RVariableIfc interface implements the RandomIfc interface, which provides stream control of the underlying random number stream.SampleIfc interface provides a set of methods for sampling 1 or more values.BernoulliRV(probOfSuccess)BinomialRV(pSucces, numTrials)ConstantRV(constVal) a degenerate probability mass on a single value that cannot be changedDEmpiricalRV(values, cdf) values is an array of numbers and cdf is an array representing the cumulative distribution function over the valuesDUniformRV(min, max)GeometricRV(probOfSucces) with range is 0 to infinityNegativeBinomialRV(probOfSuccess, numSuccess) with range is 0 to infinity. The number of failures before the \(r^{th}\) success.PoissonRV(mean)ShiftedGeometricRV(probOfSucces) range is 1 to infinityVConstantRV(constVal) a degenerate probability mass on a single value that can be changedBetaRV(alpha1, alpha2)ChiSquaredRV(degreesOfFreedom)ExponentialRV(mean)GammaRV(shape, scale)GeneralizedBetaRV(alpha1, alpha2, min, max)JohnsonBRV(alpha1, alpha2, min, max)LaplaceRV(mean scale)LogLogisticRV(shape, scale)LognormalRV(mean, variance)NormalRV(mean, variance)PearsonType5RV(shape, scale)PearsonType6RV(alpha1, alpha2, beta)StudentTRV(degreesOfFreedom)TriangularRV(min, mode, max)UniformRV(min, max)WeibullRV(shape, scale)RVarable class, which implements the RVariableIfc interface.generate() method, which should return the generated random value according to some algorithm.AcceptanceRejectionRV and ratio of uniforms RatioOfUniformsRV classes.MixtureRv class, which requires the random variables being mixed and the mixing distribution.ShiftedRV class.TruncatedRV class.value property or value() function to get new values of the variatefun main() {
// create a normal mean = 20.0, variance = 4.0 random variable,
// using stream number 1
val n = NormalRV(20.0, 4.0, streamNum = 1)
print(String.format("%3s %15s %n", "n", "Values"))
// generate some values
for (i in 1..5) {
// the value property returns a generated value
val x = n.value
print(String.format("%3d %15f %n", i, x))
}
} n Values
1 17.718732
2 19.056360
3 19.003682
4 21.875759
5 18.466600
SampleIfc Interfacesample() returns a new valuesample(sampleSize: Int) returns an array of valuessampleInto(values: DoubleArray) fills an array with valuessampleAsRows(sampleSize: Int, nRows: Int = 1) makes a 2-D array with samples in the rowssampleAsColumns(sampleSize: Int, nRows: Int = 1) makes a 2-D array with samples in the columnssampleInto(matrix: Array<DoubleArray>) fills a 2-D array with samplesfun main() {
// create a triangular random variable with min = 2.0, mode = 5.0, max = 10.0
val t = TriangularRV(2.0, 5.0, 10.0, streamNum = 1)
// sample 5 values
val sample = t.sample(5)
print(String.format("%3s %15s %n", "n", "Values"))
for (i in sample.indices) {
print(String.format("%3d %15f %n", i + 1, sample[i]))
}
}The values are provided via an array and the probabilities must be specified in the form of the cumulative probabilities, such that the last element is 1.0.
fun main() {
// values is the set of possible values
val values = doubleArrayOf(1.0, 2.0, 3.0, 4.0)
// cdf is the cumulative distribution function over the values
val cdf = doubleArrayOf(1.0 / 6.0, 3.0 / 6.0, 5.0 / 6.0, 1.0)
//create a discrete empirical random variable
val n1 = DEmpiricalRV(values, cdf, streamNum = 1)
println(n1)
print(String.format("%3s %15s %n", "n", "Values"))
for (i in 1..5) {
print(String.format("%3d %15f %n", i, n1.value))
}
println()
println(n1.probabilityPoints)
}Suppose the time that it takes to pay with a credit card, \(X_{1}\), is exponentially distributed with a mean of \(1.5\) minutes and the time that it takes to pay with cash, \(X_{2}\), is exponentially distributed with a mean of \(1.1\) minutes. In addition, suppose that the chance that a person pays with credit is 70%. Then, the overall distribution representing the payment service time, \(X\), has an hyper-exponential distribution with parameters \(\omega_{1} = 0.7\), \(\omega_{2} = 0.3\), \(\lambda_{1} = 1/1.5\), and \(\lambda_{2} = 1/1.1\). Generate 5 random variates from this distribution.
fun main() {
// rvs is the list of random variables for the mixture
val rvs = listOf(ExponentialRV(1.5), ExponentialRV(1.1))
// cdf is the cumulative distribution function over the random variables
val cdf = doubleArrayOf(0.7, 1.0)
//create a mixture random variable
val he = MixtureRV(rvs, cdf, streamNum = 1)
print(String.format("%3s %15s %n", "n", "Values"))
for (i in 1..5) {
print(String.format("%3d %15f %n", i, he.value))
}
}Suppose \(X\) represents the distance between two cracks in highway. Suppose that \(X\) has an exponential distribution with a mean of 10 meters. Generate 5 random distance values restricted between 3 and 6 meters.
Suppose \(X\) represents the time to setup a machine for production. From past time studies, we know that it cannot take any less than 5.5 minutes to prepare for the setup and that the time after the 5.5 minutes is random with a Weibull distribution with shape parameter \(\alpha = 3\) and scale parameter \(\beta = 5\). Generate 5 random observations of the setup time.
Consider the following PDF over the range \(\left[-1,1\right]\). Generate 1000 random variates from this distribution. \[ f(x) = \begin{cases} \frac{3}{4}\left( 1 - x^2 \right) & -1 \leq x \leq 1\\ 0 & \text{otherwise}\\ \end{cases} \]
\[ w(x) = \begin{cases} \frac{1}{2} & -1 \leq x \leq 1\\ 0 & \text{otherwise}\\ \end{cases} \]
fun main() {
// proposal distribution
val wx = Uniform(-1.0, 1.0)
// majorizing constant, if g(x) is majorizing function, then g(x) = w(x)*c
val c = 3.0 / 2.0
val rv = AcceptanceRejectionRV(wx, c, fOfx, streamNum = 1)
val h = Histogram.create(-1.0, 1.0, 100)
for (i in 1..1000) {
h.collect(rv.value)
}
println(h)
val hp = h.histogramPlot()
hp.showInBrowser()
val dp = DensityPlot(h) { x -> fOfx.pdf(x) }
dp.showInBrowser()
}
object fOfx : PDFIfc {
override fun pdf(x: Double): Double {
if ((x < -1.0) || (x > 1))
return 0.0
return (0.75 * (1.0 - x * x))
}
override fun domain(): Interval {
return Interval(-1.0, 1.0)
}
}KSLRandom object has functions defined for many of the distributions.KSLRandom functions, users can more conveniently call these methods.KSLRandom has functions for sampling from arrays and lists without replacement.A
B
B
D
A
fun main() {
// create an array to hold a population of values
val y = DoubleArray(10)
for (i in 0..9) {
y[i] = (i + 1).toDouble()
}
// create the population
val p = DPopulation(y, streamNum = 1)
println(p.contentToString())
println("Print the permuted population")
// permute the population
p.permute()
println(p.contentToString())[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
Print the permuted population
[8.0, 10.0, 2.0, 4.0, 3.0, 5.0, 1.0, 6.0, 9.0, 7.0]
Permuting y
[2.0, 4.0, 5.0, 9.0, 6.0, 8.0, 3.0, 1.0, 7.0, 10.0]
Sampling 5 from the population
[2.0, 4.0, 4.0, 9.0, 5.0]
// create a string list and permute it
val strList: MutableList<String> = ArrayList()
strList.add("a")
strList.add("b")
strList.add("c")
strList.add("d")
println("The mutable list")
println(strList)
KSLRandom.permute(strList)
println("The permuted list")
println(strList)
println("Permute using extension function")
strList.permute()
println(strList)
}The mutable list
[a, b, c, d]
The permuted list
[c, a, b, d]
Permute using extension function
[b, d, c, a]
fun main(){
var erlang: RVariableIfc = ExponentialRV(10.0, streamNum = 1)
for(i in 1..4) {
erlang = erlang + ExponentialRV(10.0)
}
println("stream number = ${erlang.streamNumber}")
val sample = erlang.sample(1000)
val stats = Statistic(sample)
println()
print(stats)
sample.writeToFile("erlang.txt")
}RVariableIfc and base class RVariable provides the ability to construct new random variables that are functions of other random variables by overriding the \((+, -, \times, \div)\) operators.fun main(){
// define a beta random variable in terms of gamma
val alpha1 = 2.0
val alpha2 = 5.0
val y1 = GammaRV(alpha1, 1.0, streamNum = 2)
val y2 = GammaRV(alpha2, 1.0)
val betaRV = y1/(y1+y2)
val betaSample = betaRV.sample(500)
println("stream number = ${betaRV.streamNumber}")
println(betaSample.statistics())
}The ksl.utilities.distributions package facilitates computing from distributions.
The DistributionIfc interface requires the following functions.
cdf(b: Double) - computes the cumulative probability, \(F(b) = P(X \leq b)\)
cdf(a: Double, b: Double) - computes the cumulative probability, \(P( a \leq X \leq b)\)
complementaryCDF(b: Double) - computes the cumulative probability, \(1-F(b) = P(X > b)\)
mean() - returns the expected value (mean) of the distribution
variance() - returns the variance of the distribution
standardDeviation() - returns the standard deviation of the distribution
invCDF(p: Double) - returns the inverse of the cumulative distribution function \(F^{-1}(p)\). This is performed by numerical search if necessary
DiscreteDistributionIfc and PMFIfc interfaces.Binomial distribution and use it to compute some probability values.fun main() {
// make and use a Binomial(p, n) distribution
val n = 10
val p = 0.8
println("n = $n")
println("p = $p")
val bnDF = Binomial(p, n)
println("mean = " + bnDF.mean())
println("variance = " + bnDF.variance())
// compute some values
print(String.format("%3s %15s %15s %n", "k", "p(k)", "cdf(k)"))
for (i in 0..10) {
print(String.format("%3d %15.10f %15.10f %n", i, bnDF.pmf(i), bnDF.cdf(i)))
}
println()n = 10
p = 0.8
mean = 8.0
variance = 1.5999999999999996
k p(k) cdf(k)
0 0.0000001024 0.0000001024
1 0.0000040960 0.0000041984
2 0.0000737280 0.0000779264
3 0.0007864320 0.0008643584
4 0.0055050240 0.0063693824
5 0.0264241152 0.0327934976
6 0.0880803840 0.1208738816
7 0.2013265920 0.3222004736
8 0.3019898880 0.6241903616
9 0.2684354560 0.8926258176
10 0.1073741824 1.0000000000
RVariable cannot be mutated. However, instances of distributions, for example Binomial can have their parameters mutated. // change the probability and number of trials
bnDF.probOfSuccess = 0.5
bnDF.numTrials = 20
println("mean = " + bnDF.mean())
println("variance = " + bnDF.variance())
// make random variables based on the distributions
val brv = bnDF.randomVariable(1)
print(String.format("%3s %15s %n", "n", "Values"))
// generate some values
for (i in 1..5) {
// value property returns generated values
val x = brv.value.toInt()
print(String.format("%3d %15d %n", i, x))
}
}binomialPMF(j: Int, n: Int, p: Double) - directly computes the probability for the value \(j\)binomialCDF(j: Int, n: Int, p: Double) - directly computes the cumulative distribution function for the value \(j\)binomialCCDF(j: Int, n: Int, p: Double)- directly computes the complementary cumulative distribution function for the value of \(j\)binomialInvCDF(x: Double, n: Int, p: Double) - directly computes the inverse cumulative distribution functionstdNormalCDF(z: Double) - the cumulative probability for a \(Z ~ N(0,1)\) random variable, i.e. \(F(z) = P(Z \leq z)\)stdNormalComplementaryCDF(z: Double) - returns \(1-P(Z \leq z)\)stdNormalInvCDF(p: Double) - returns \(z = F^{-1}(p)\) the inverse of the cumulative distribution functioncdf(dof: Double, x: Double) - computes the cumulative distribution function for \(x\) given the degrees of freedominvCDF(dof: Double, p: Double) - computes the inverse cumulative distribution function or t-value for the supplied probability given the degrees of freedom.RArrays - defines extension functions for randomly sampling from arrays and some listsMVSampleIfc - defines the interface for generating random arrays of dataMVRVariableIfc - the multi-variate analog for the RVariableIfcMVRVariable - an abstract base class for defining multi-variate random variablesMVIndependentMarginals - a concrete implementation for generating independent vectors that have specified random variates for each coordinate of the vector.