4. Generating Random Variates

How to turn i.i.d. U(0,1) random numbers into observations from the distributions a model actually needs — the inverse transform and composition methods, and what makes a variate-generation algorithm good.

Goal. Study algorithms that produce observations (realizations) from some desired input distribution, given a stream of i.i.d. U(0,1)U(0,1) random numbers.

Chapter 3 produced the raw material: uniform random numbers. This chapter turns them into random variates from whatever distribution the model calls for — e.g. the exponential interarrival and service times of an M/M/1M/M/1 queue.

4.1. Structure

  • It is essential to have a statistically reliable underlying RNG. Every algorithm below assumes its input really is i.i.d. U(0,1)U(0,1); a defective generator corrupts every variate built from it.

Factors in choosing an algorithm.

1. Exactness. An algorithm is exact if the variates it produces have exactly the desired distribution, not merely approximately.

Example of an inexact method. To generate Z∼N(0,1)Z \sim N(0,1):

  1. Generate u1,…,u12u_1, \dots, u_{12} i.i.d. U(0,1)U(0,1).
  2. Return Z=u1+u2+⋯+u12−6Z = u_1 + u_2 + \cdots + u_{12} - 6.

The moments come out right:

E[Z]=12⋅12−6=0,Var⁡(Z)=12⋅112=1,\mathbf{E}[Z] = 12 \cdot \tfrac{1}{2} - 6 = 0, \qquad \operatorname{Var}(Z) = 12 \cdot \tfrac{1}{12} = 1,

and by the CLT the sum is approximately normal. But it is not exact. Since each ui∈[0,1]u_i \in [0,1], the output always satisfies

Z∈[−6,6],Z \in [-6, 6],

whereas a true N(0,1)N(0,1) variable has range (−∞,∞)(-\infty, \infty). The algorithm can never produce a value beyond ±6\pm 6, so it truncates both tails — exactly the region that matters most in reliability, risk, and rare-event studies. It is also wasteful: 12 random numbers per variate. Avoid it; use an exact method (§4.2.5) instead.

2. Efficiency.

  • memory usage;
  • execution time, including setup time (some algorithms precompute tables; that cost is paid once but must be counted).

3. Simplicity: easy to understand, implement, and debug. There is a trade-off between efficiency and simplicity — the fastest algorithm is rarely the clearest.

4. If possible, use exactly one random number per random variate. Reasons:

  • Simplicity.
  • Synchronization. When comparing two systems with common random numbers (§3.3, practical issue 3), we want the ii-th variate in system A to be built from the same uiu_i as in system B. If one system consumes a variable number of uniforms per variate, the two streams drift out of step and the comparison loses its sharpness.
  • Monotonicity. With one uniform per variate and X=F−1(u)X = F^{-1}(u), the variate is a monotone function of uu. This is what makes variance-reduction techniques such as antithetic variates work.

4.2. RVG Algorithms

Direct methods — build the variate straight from the definition of the distribution:

  1. Inverse transform — universally applicable in principle, but may be hard to implement.
  2. Composition ⎫
  3. Convolution ⎭ — apply only to input distributions of a specific form (mixtures and sums, respectively).

When these fail — that is, when F−1F^{-1} has no usable closed form and the distribution is neither a convenient mixture nor a convenient sum (the normal, gamma, and beta distributions are the standard examples) — fall back on:

  1. Acceptance–rejection method.
  2. Special techniques, e.g. for normal random variables.

4.2.1. Inverse Transform Method

Continuous case. Let XX be a continuous r.v. with c.d.f. FF.

Algorithm.

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=F−1(u)X = F^{-1}(u).
u 1 0 X = F⁻¹(u) F(x) x draw u on the vertical axis, read X off the horizontal axis

The catch is step 2: F−1F^{-1} must be computed, and for many distributions (normal, gamma, beta) it has no closed form.

Proof that the output has c.d.f. FF.

P(X≤x)=P(F−1(u)≤x)=P(F(F−1(u))≤F(x))applying F to both sides; valid since F is non-decreasing=P(u≤F(x))=F(x)since u∼U(0,1).\begin{aligned} P(X \le x) &= P\left(F^{-1}(u) \le x\right) \\ &= P\left(F(F^{-1}(u)) \le F(x)\right) && \text{applying } F \text{ to both sides; valid since } F \text{ is non-decreasing} \\ &= P\left(u \le F(x)\right) \\ &= F(x) && \text{since } u \sim U(0,1). \end{aligned}

The last step is the definition of the uniform distribution: P(u≤a)=aP(u \le a) = a for any a∈[0,1]a \in [0,1], and here a=F(x)a = F(x) is indeed in [0,1][0,1] because it is a probability. So the c.d.f. of the generated XX is FF, exactly — the method is exact.

Example: X∼Exp(λ)X \sim \text{Exp}(\lambda). Here F(x)=1−e−λxF(x) = 1 - e^{-\lambda x} for x>0x > 0. Set u=F(x)u = F(x) and solve:

u=1−e−λx  ⟹  e−λx=1−u  ⟹  x=−1λln⁡(1−u).u = 1 - e^{-\lambda x} \;\Longrightarrow\; e^{-\lambda x} = 1 - u \;\Longrightarrow\; x = -\frac{1}{\lambda}\ln(1 - u).

Algorithm.

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=−1λln⁡(1−u)X = -\dfrac{1}{\lambda}\ln(1-u).

Variant. Replace step 2 by “2′. Return X=−1λln⁡uX = -\dfrac{1}{\lambda}\ln u.”

This is valid because 1−u∼U(0,1)1 - u \sim U(0,1) whenever u∼U(0,1)u \sim U(0,1), so the two versions produce the same distribution. It saves one subtraction per variate — a genuine but small gain in a tight loop.

Two cautions, though:

  • Monotonicity is lost. Version 2 is increasing in uu; version 2′ is decreasing. Under 2, a large uu gives a long interarrival time in both of two systems being compared; under 2′ the correspondence is reversed. Where synchronization or antithetic variates matter, prefer 2.
  • The value u=0u = 0. An LCG can output u=0u = 0 (when zi=0z_i = 0), and ln⁡0\ln 0 is undefined. Version 2 never has this problem, since 1−u∈(0,1]1 - u \in (0, 1]. If 2′ is used, u=0u = 0 must be screened out.

Efficiency problem. The number of comparisons the chain performs equals II, the index it returns. Since the algorithm returns xix_i exactly when I=iI = i, and P(I=i)=P(X=xi)=p(xi)P(I = i) = P(X = x_i) = p(x_i), the number of comparisons NN is a random variable with the same distribution as the index, so by the definition of expectation,

E[N]=∑i=1ni⋅P(N=i)=∑i=1ni p(xi).\mathbf{E}[N] = \sum_{i=1}^{n} i \cdot P(N = i) = \sum_{i=1}^{n} i\, p(x_i).

If the probable values sit late in the list, this is close to nn: tiny jumps at x1,x2,…x_1, x_2, \dots and the big jumps only at the end.

1 u 0 x₁ x₁₀ x₁₂ tiny jumps early, big jumps late ⇒ most u's need many comparisons x

Two fixes.

  1. Binary search. Since F(x1)≤F(x2)≤⋯≤F(xn)F(x_1) \le F(x_2) \le \cdots \le F(x_n) is a sorted array, locate uu by bisection instead of scanning: O(log⁡2n)O(\log_2 n) comparisons instead of O(n)O(n), whatever the probabilities.

  2. Reorder the comparisons. Test the values in decreasing order of probability. Relabel so that p(1)≥p(2)≥⋯≥p(n)p_{(1)} \ge p_{(2)} \ge \cdots \ge p_{(n)} and build the cumulative sums for that new order; then E[N]=∑ii p(i)\mathbf{E}[N] = \sum_i i\, p_{(i)} is as small as possible. The reordering is done once in setup, so it costs nothing at run time.

Example. n=6n = 6 with p=(0.05, 0.05, 0.10, 0.10, 0.20, 0.50)p = (0.05,\, 0.05,\, 0.10,\, 0.10,\, 0.20,\, 0.50):

order of testing E[comparisons]\mathbf{E}[\text{comparisons}]
as given: x1,x2,…,x6x_1, x_2, \dots, x_6 ∑ii pi=4.85\sum_i i\,p_i = 4.85
decreasing probability: x6,x5,x3,x4,x1,x2x_6, x_5, x_3, x_4, x_1, x_2 ∑ii p(i)=2.15\sum_i i\,p_{(i)} = 2.15

More than twice as fast, for no cost beyond sorting once.

Does reordering change the simulation? No. The output distribution is exactly the same — each xix_i is still returned with probability p(xi)p(x_i), because the intervals of (0,1](0,1] assigned to the values have the same widths p(xi)p(x_i); only their positions along (0,1](0,1] are permuted. The only thing that changes is the expected number of comparisons, i.e. the run time.

The one side effect: reordering destroys the monotone relationship between uu and XX, so the output is no longer F−1(u)F^{-1}(u) as a function of uu. If synchronization or antithetic variates matter (see “Advantages” below), keep the natural order or use binary search, which preserves it.

Example: discrete uniform. X∼DU(1,100)X \sim DU(1,100), i.e. X∈{1,2,…,100}X \in \{1, 2, \dots, 100\} with p(i)=1100p(i) = \frac{1}{100} for every ii, so F(i)=i100F(i) = \frac{i}{100}.

The general algorithm becomes:

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. if u ≤ 0.01 return X = 1; else if u ≤ 0.02 return X = 2; … ; else return X = 100

But here the chain can be replaced by a formula. The first ii with u≤i/100u \le i/100 is characterized by

i−1100<u≤i100⟺i−1<100u≤i⟺i=⌈100u⌉,\frac{i-1}{100} < u \le \frac{i}{100} \quad\Longleftrightarrow\quad i - 1 < 100u \le i \quad\Longleftrightarrow\quad i = \lceil 100u \rceil,

so step 2 collapses to

  X=⌈100u⌉  \boxed{\;X = \lceil 100 u \rceil\;}

— one multiplication and one ceiling, instead of up to 100 comparisons. (Equal probabilities are what make this possible; unequal ones need the search.)

Generalized inverse transform. To cover continuous, discrete, and mixed distributions in one statement:

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=min⁡{x:F(x)≥u}X = \min\{x : F(x) \ge u\}.

This is the same rule as before, written so it always makes sense. An ordinary inverse F−1F^{-1} requires FF to be strictly increasing and continuous; a discrete FF is flat in places (so no unique inverse) and jumps in places (so some values of uu have no xx with F(x)=uF(x) = u at all). Taking the smallest xx whose F(x)F(x) has reached uu handles both defects, and reduces to the usual F−1(u)F^{-1}(u) when FF is continuous and strictly increasing.

Advantages and disadvantages of the inverse transform method.

Disadvantages.

  1. Must invert the c.d.f., which may have no closed form (normal, gamma, beta).
  2. May not be the most efficient approach even when the inverse exists.

Advantages.

  1. Easy to generate from truncated distributions. Truncating means restricting XX to an interval [a,b][a,b] and renormalizing:

    F∗(x)=F(x)−F(a)F(b)−F(a),a≤x≤b,F^*(x) = \frac{F(x) - F(a)}{F(b) - F(a)}, \qquad a \le x \le b,

    which is the original density chopped off outside [a,b][a,b] and scaled up so the area is again 1.

    a b keep only this part, rescaled to total area 1 original f(x)

    Inverting F∗F^* costs nothing extra: generate u∼U(0,1)u \sim U(0,1) and return

    X=F−1(F(a)+u [F(b)−F(a)]).X = F^{-1}\Big(F(a) + u\,\big[F(b) - F(a)\big]\Big).

    In words: instead of drawing uu uniformly over all of (0,1)(0,1), draw it uniformly over the slice (F(a),F(b))\big(F(a), F(b)\big) of the vertical axis. Every draw is usable — no rejection, one uniform per variate.

  2. Facilitates variance reduction when comparing alternative systems. Let X1∼F1X_1 \sim F_1 be the output of system 1 and X2∼F2X_2 \sim F_2 that of system 2, and suppose we want the difference in mean cost,

    E[X1]−E[X2]=E[X1−X2],\mathbf{E}[X_1] - \mathbf{E}[X_2] = \mathbf{E}[X_1 - X_2],

    so that X1−X2X_1 - X_2 is an unbiased estimator of the gap. Generate both by inverse transform, X1=F1−1(u1)X_1 = F_1^{-1}(u_1) and X2=F2−1(u2)X_2 = F_2^{-1}(u_2). Since

    Var⁡(X1−X2)=Var⁡(X1)+Var⁡(X2)−2cov⁡(X1,X2),\operatorname{Var}(X_1 - X_2) = \operatorname{Var}(X_1) + \operatorname{Var}(X_2) - 2\operatorname{cov}(X_1, X_2),

    the precision of the comparison is controlled entirely by how we couple u1u_1 and u2u_2:

coupling cov⁡(X1,X2)\operatorname{cov}(X_1, X_2) Var⁡(X1−X2)\operatorname{Var}(X_1 - X_2)
1. u1⊥u2u_1 \perp u_2 (independent) 00 Var⁡(X1)+Var⁡(X2)\operatorname{Var}(X_1) + \operatorname{Var}(X_2)
2. u1=u2u_1 = u_2 (common random numbers) >0> 0 smaller
3. u1=1−u2u_1 = 1 - u_2 (antithetic) <0< 0 larger

Case 2 is the useful one. Both F1−1F_1^{-1} and F2−1F_2^{-1} are non-decreasing, so a large uu pushes both X1X_1 and X2X_2 up and a small uu pushes both down: the two outputs move together, cov⁡(X1,X2)>0\operatorname{cov}(X_1,X_2) > 0, and the variance of the difference drops. Note X1≠X2X_1 \ne X_2 still, since F1≠F2F_1 \ne F_2. Monotonicity is exactly what the inverse transform provides and what a rejection-based method does not — hence “facilitates”.

(Case 3 is not useless in general; antithetic variates reduce variance when estimating a single mean by averaging X1X_1 and X2X_2, where the negative correlation helps. It is only harmful here, where we take a difference.)

4.2.2. Composition

The name. The target distribution is composed of simpler ones — the way a mixture’s chemical composition lists its ingredients. The method is also called the mixture method: decompose FF into pieces you know how to sample from, pick a piece at random, then sample from it.

Setup. Use this when FF can be written as a convex combination of other c.d.f.s F1,F2,…F_1, F_2, \dots (finitely or infinitely many):

F(x)=∑j≥1pjFj(x),∑j≥1pj=1,pj≥0.F(x) = \sum_{j \ge 1} p_j F_j(x), \qquad \sum_{j \ge 1} p_j = 1, \quad p_j \ge 0 .

Equivalently, in terms of densities or mass functions,

f(x)=∑j≥1pjfj(x)orp(x)=∑j≥1pj p(j)(x).f(x) = \sum_{j \ge 1} p_j f_j(x) \qquad\text{or}\qquad p(x) = \sum_{j \ge 1} p_j\, p^{(j)}(x).

Algorithm.

  1. Generate a positive random integer JJ with P(J=j)=pjP(J = j) = p_j (a discrete variate — use the inverse transform of §4.2.1).
  2. Return XX generated from the c.d.f. FJF_J.

Proof. Conditioning on JJ,

P(X≤x)=∑j≥1P(X≤x∣J=j) P(J=j)=∑j≥1Fj(x) pj=F(x).■P(X \le x) = \sum_{j \ge 1} P(X \le x \mid J = j)\, P(J = j) = \sum_{j \ge 1} F_j(x)\, p_j = F(x). \qquad \blacksquare

Example: right trapezoidal distribution.

f(x)={a+2(1−a)x,0≤x≤1(0<a<1),0,otherwise.f(x) = \begin{cases} a + 2(1-a)x, & 0 \le x \le 1 \quad (0 < a < 1), \\ 0, & \text{otherwise.}\end{cases}

Split the formula into its two terms and read off the weights:

f(x)=a⏟p1⋅1⏟f1(x)  +  (1−a)⏟p2⋅2x⏟f2(x),f(x) = \underbrace{a}_{p_1} \cdot \underbrace{1}_{f_1(x)} \;+\; \underbrace{(1-a)}_{p_2} \cdot \underbrace{2x}_{f_2(x)} ,

where f1f_1 is the U(0,1)U(0,1) density and f2(x)=2xf_2(x) = 2x on [0,1][0,1] is a triangular density with F2(x)=x2F_2(x) = x^2, so F2−1(u)=uF_2^{-1}(u) = \sqrt{u}.

Algorithm.

  1. Generate u1,u2u_1, u_2 independent U(0,1)U(0,1).
  2. If u1≤au_1 \le a, return X=u2X = u_2; else return X=u2X = \sqrt{u_2}.

Here u1u_1 chooses the component (J=1J = 1 with probability aa) and u2u_2 generates from it.

Example: symmetric triangular distribution on [−1,1][-1,1].

f(x)={1+x,−1≤x≤0,1−x,0≤x≤1,0,otherwise.f(x) = \begin{cases} 1 + x, & -1 \le x \le 0, \\ 1 - x, & 0 \le x \le 1, \\ 0, & \text{otherwise.}\end{cases}

each half has area ½ ⇒ toss a fair coin, then draw from that half −1 0 1 1 1+x 1−x area ½ area ½

Each half of the triangle has area 12\tfrac12, so take p1=p2=12p_1 = p_2 = \tfrac12 with

f1(x)=2(1+x)  on [−1,0],f2(x)=2(1−x)  on [0,1]f_1(x) = 2(1+x) \ \text{ on } [-1,0], \qquad f_2(x) = 2(1-x) \ \text{ on } [0,1]

(each doubled so that it integrates to 1 on its own half). For the right piece, F2(x)=2x−x2F_2(x) = 2x - x^2, and solving u=2x−x2u = 2x - x^2 gives x=1−1−ux = 1 - \sqrt{1-u}, i.e. 1−u1 - \sqrt{u} after replacing 1−u1-u by uu. The left piece is its mirror image.

Algorithm (composition).

  1. Generate u1,u2u_1, u_2 independent U(0,1)U(0,1).
  2. If u1≤12u_1 \le \tfrac12, return X=u2−1X = \sqrt{u_2} - 1; else return X=1−1−u2X = 1 - \sqrt{1 - u_2}.

The same distribution by inverse transform. The c.d.f. is

F(x)={(1+x)22,−1≤x≤0,1−(1−x)22,0≤x≤1,F(x) = \begin{cases} \dfrac{(1+x)^2}{2}, & -1 \le x \le 0, \\[6pt] 1 - \dfrac{(1-x)^2}{2}, & 0 \le x \le 1,\end{cases}

and F(0)=12F(0) = \tfrac12, so u<12u < \tfrac12 corresponds to the left half. Solving u=(1+x)22u = \frac{(1+x)^2}{2} gives x=−1+2ux = -1 + \sqrt{2u}; solving u=1−(1−x)22u = 1 - \frac{(1-x)^2}{2} gives x=1−2(1−u)x = 1 - \sqrt{2(1-u)}.

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. If u<12u < \tfrac12, return X=−1+2uX = -1 + \sqrt{2u}; else return X=1−2(1−u)X = 1 - \sqrt{2(1-u)}.

Efficiency comparison (expected operations per variate):

uu’s comparisons additions multiplications square roots
inverse 1 1 1.5 1 1
composition 2 1 1.5 0 1

How the counts are obtained. Each row averages the two branches, which are taken with probability 12\tfrac12 each; a subtraction counts as an addition. For the inverse method, the left branch −1+2u-1 + \sqrt{2u} uses one multiplication (2u2u), one square root and one addition, while the right branch 1−2(1−u)1 - \sqrt{2(1-u)} uses one multiplication (2×2 \times), one square root and two additions (1−u1-u and 1−⋅1 - \sqrt{\cdot}) — so the average is 12(1)+12(2)=1.5\tfrac12(1) + \tfrac12(2) = 1.5 additions, with 1 multiplication and 1 square root either way, plus the single comparison u<12u < \tfrac12 and the single uniform. For composition, u2−1\sqrt{u_2} - 1 has one addition and 1−1−u21 - \sqrt{1-u_2} has two, giving the same 1.51.5 average and the same one square root and one comparison, but no multiplication — the factor 2 never appears, because doubling the density was absorbed into choosing a half. The cost is that u1u_1 is spent on the coin toss and u2u_2 on the value, so two uniforms are consumed instead of one.

Conclusion. The two methods differ in exactly two places: composition saves one multiplication but spends one extra random number. Generating a random number is far more expensive than a multiplication, so the inverse transform is more efficient here. (It also keeps XX monotone in uu, which composition does not — see §4.2.1, advantage 4.)

4.2.3. Convolution

Setup. Let Y1,Y2,…,YmY_1, Y_2, \dots, Y_m be i.i.d. with common c.d.f. GG, and define

X=Y1+Y2+⋯+Ym.X = Y_1 + Y_2 + \cdots + Y_m .

The c.d.f. FF of XX is called the mm-fold convolution of GG with itself. Use this method whenever the target distribution is known to arise as such a sum.

Algorithm (to generate from FF):

  1. Generate Y1,…,YmY_1, \dots, Y_m independently from GG.
  2. Return X=Y1+Y2+⋯+YmX = Y_1 + Y_2 + \cdots + Y_m.

Why the proof is trivial. Unlike the inverse transform or composition, there is nothing to verify: FF was defined as the distribution of the sum, and the algorithm literally forms that sum from independent draws. Correctness is by construction. The work in this method lies elsewhere — in recognizing that the desired FF is a convolution of something samplable.

Example: sum of two exponentials. Let X1⊥X2∼Exp(λ)X_1 \perp X_2 \sim \text{Exp}(\lambda) and Z=X1+X2Z = X_1 + X_2. Then

FZ(z)=P(Z≤z)=P(X1+X2≤z)=∫0∞P ⁣(X1+X2≤z∣X2=x)fX2(x) dx(1)=∫0∞P ⁣(X1≤z−x)λe−λx dx(2)=∫0z(1−e−λ(z−x))λe−λx dx(3)=∫0zλe−λx dx  −  ∫0zλe−λz dx(4)=(1−e−λz)−λz e−λz(5)=1−∑i=01e−λz(λz)ii!.(6)\begin{aligned} F_Z(z) = P(Z \le z) &= P(X_1 + X_2 \le z) \\ &= \int_0^\infty P\!\left(X_1 + X_2 \le z \mid X_2 = x\right) f_{X_2}(x)\,dx && \text{(1)} \\ &= \int_0^\infty P\!\left(X_1 \le z - x\right) \lambda e^{-\lambda x}\,dx && \text{(2)} \\ &= \int_0^z \left(1 - e^{-\lambda(z-x)}\right) \lambda e^{-\lambda x}\,dx && \text{(3)} \\ &= \int_0^z \lambda e^{-\lambda x}\,dx \;-\; \int_0^z \lambda e^{-\lambda z}\,dx && \text{(4)} \\ &= \left(1 - e^{-\lambda z}\right) - \lambda z\, e^{-\lambda z} && \text{(5)} \\ &= 1 - \sum_{i=0}^{1} e^{-\lambda z}\frac{(\lambda z)^i}{i!} . && \text{(6)} \end{aligned}

Explanation of each step.

  1. Condition on X2X_2 (law of total probability, continuous version). To find P(A)P(A), split according to the value xx that X2X_2 takes, weight each case by the density fX2(x)f_{X_2}(x), and integrate over all xx — the continuous analogue of P(A)=∑jP(A∣Bj) P(Bj)P(A) = \sum_j P(A \mid B_j)\,P(B_j). The range is [0,∞)[0, \infty) because X2≥0X_2 \ge 0. The purpose is to turn a two-variable event into a one-variable one.
  2. Use the condition, then drop it. Given X2=xX_2 = x, the event X1+X2≤zX_1 + X_2 \le z is X1+x≤zX_1 + x \le z, i.e. X1≤z−xX_1 \le z - x. Then, because X1⊥X2X_1 \perp X_2, knowing X2=xX_2 = x says nothing about X1X_1, so P(X1≤z−x∣X2=x)=P(X1≤z−x)P(X_1 \le z - x \mid X_2 = x) = P(X_1 \le z - x) — the condition disappears. Also substitute fX2(x)=λe−λxf_{X_2}(x) = \lambda e^{-\lambda x}.
  3. Substitute the c.d.f. of X1X_1. P(X1≤z−x)=FX1(z−x)=1−e−λ(z−x)P(X_1 \le z - x) = F_{X_1}(z - x) = 1 - e^{-\lambda(z-x)}, valid when z−x≥0z - x \ge 0. When x>zx > z the argument is negative and FX1=0F_{X_1} = 0 (X1X_1 is never negative), so the integrand vanishes there; hence the upper limit drops from ∞\infty to zz.
  4. Expand and simplify. Multiply out (1−e−λ(z−x)) λe−λx(1 - e^{-\lambda(z-x)})\,\lambda e^{-\lambda x} and split into two integrals. In the second, e−λ(z−x)⋅e−λx=e−λz+λx−λx=e−λze^{-\lambda(z-x)} \cdot e^{-\lambda x} = e^{-\lambda z + \lambda x - \lambda x} = e^{-\lambda z}: the xx cancels, leaving a constant.
  5. Evaluate. First integral: ∫0zλe−λx dx=[−e−λx]0z=1−e−λz\int_0^z \lambda e^{-\lambda x}\,dx = \left[-e^{-\lambda x}\right]_0^z = 1 - e^{-\lambda z}. Second: the integrand is the constant λe−λz\lambda e^{-\lambda z}, so the integral is that constant times the interval length zz.
  6. Rewrite as a sum. Factor out e−λze^{-\lambda z}: 1−e−λz(1+λz)1 - e^{-\lambda z}(1 + \lambda z). The two terms in the bracket are (λz)00!=1\frac{(\lambda z)^0}{0!} = 1 and (λz)11!=λz\frac{(\lambda z)^1}{1!} = \lambda z, i.e. i=0,1i = 0, 1 of ∑i(λz)ii!\sum_i \frac{(\lambda z)^i}{i!}. Writing it this way exposes the pattern: for a sum of nn exponentials the same calculation, repeated, gives the terms i=0,…,n−1i = 0, \dots, n-1.

Generalization: the Erlang distribution. Let X1,…,XnX_1, \dots, X_n be i.i.d. Exp(λ)\text{Exp}(\lambda) and Z=X1+⋯+XnZ = X_1 + \cdots + X_n. Repeating the argument gives

FZ(z)=1−∑i=0n−1e−λz(λz)ii!,z≥0,F_Z(z) = 1 - \sum_{i=0}^{n-1} e^{-\lambda z}\frac{(\lambda z)^i}{i!}, \qquad z \ge 0,

and ZZ is called an Erlang(n,λ)(n, \lambda) variable — the special case of the Gamma(n,λ)(n, \lambda) distribution with integer shape parameter.

Reading the formula. The sum is exactly P(N(z)≤n−1)P(N(z) \le n-1) for a Poisson variable N(z)N(z) with mean λz\lambda z. This is the Poisson-process statement of §2.5: the nn-th arrival occurs by time zz if and only if at least nn arrivals have occurred by then. So “waiting for the nn-th event” and “counting events” are two views of the same process.

n = 1 (exponential) n = 2 (dashed) n = 3 (dotted) x adding more exponentials: mass shifts right and the shape becomes humped

Algorithm for Erlang(n,λ)(n, \lambda).

  1. Generate Y1,…,YnY_1, \dots, Y_n i.i.d. Exp(λ)\text{Exp}(\lambda) (each by inverse transform, §4.2.1).
  2. Return X=Y1+Y2+⋯+YnX = Y_1 + Y_2 + \cdots + Y_n.

This is exact and trivially correct, but it costs nn uniforms and nn logarithms per variate. One improvement is free:

X=∑i=1n(−1λln⁡ui)=−1λln⁡ ⁣(∏i=1nui),X = \sum_{i=1}^{n} \left(-\frac{1}{\lambda}\ln u_i\right) = -\frac{1}{\lambda}\ln\!\left(\prod_{i=1}^{n} u_i\right),

so multiply the uniforms first and take a single logarithm. The nn uniforms are still needed, which is why convolution becomes unattractive for large nn — and why the Gamma distribution with non-integer shape needs a different method (acceptance–rejection, §4.2.4).

Composition vs. convolution. Both write the target in terms of simpler distributions, but in opposite ways:

composition convolution
decomposition F=∑jpjFjF = \sum_j p_j F_j (weighted mixture) X=Y1+⋯+YmX = Y_1 + \cdots + Y_m (sum)
what you do pick one component at random, sample it sample all components, add them
uniforms used 1 for the choice + those for one component those for all mm components

Example: symmetric triangular distribution, third method. Recall (§4.2.2)

f(x)={x+1,−1≤x<0,−x+1,0≤x≤1,0,otherwise.f(x) = \begin{cases} x + 1, & -1 \le x < 0, \\ -x + 1, & 0 \le x \le 1, \\ 0, & \text{otherwise.} \end{cases}

Let u1⊥u2∼U(0,1)u_1 \perp u_2 \sim U(0,1) and Z=u1+u2Z = u_1 + u_2. The pair (u1,u2)(u_1, u_2) is uniform on the unit square (joint density =1= 1), so a probability is an area:

FZ(z)=P(Z≤z)=P(u1+u2≤z)=∬0≤u1≤1,0≤u2≤1u1+u2≤z1  du1 du2=area of the part of the square below the line u2=z−u1.F_Z(z) = P(Z \le z) = P(u_1 + u_2 \le z) = \iint\limits_{\substack{0 \le u_1 \le 1,\; 0 \le u_2 \le 1 \\ u_1 + u_2 \le z}} 1 \; du_1\, du_2 = \text{area of the part of the square below the line } u_2 = z - u_1 .

F_Z(z) = P(u₁ + u₂ ≤ z) = shaded area below the line u₁ + u₂ = z zzarea = z²/2011u₁u₂case 0 ≤ z ≤ 1 z−1z−1area = 1 − (2−z)²/2(2−z)²/2011u₁u₂case 1 ≤ z ≤ 2
  • Case 0≤z≤10 \le z \le 1. The line cuts off a right triangle at the origin with legs zz and zz:

    FZ(z)=12z2.F_Z(z) = \tfrac{1}{2} z^2 .

  • Case 1≤z≤21 \le z \le 2. Now the line cuts off the top-right corner, a right triangle with legs 2−z2 - z. Shaded area == whole square minus that corner:

    FZ(z)=1−12(2−z)2=−12z2+2z−1.F_Z(z) = 1 - \tfrac{1}{2}(2 - z)^2 = -\tfrac{1}{2}z^2 + 2z - 1 .

Differentiating gives the density of ZZ:

fZ(z)=FZ′(z)={z,0≤z≤1,−z+2,1≤z≤2,f_Z(z) = F_Z'(z) = \begin{cases} z, & 0 \le z \le 1, \\ -z + 2, & 1 \le z \le 2, \end{cases}

a triangle on [0,2][0, 2] with peak at z=1z = 1. Subtracting 1 slides it to [−1,1][-1, 1]: X=Z−1X = Z - 1 has fX(x)=fZ(x+1)f_X(x) = f_Z(x + 1), which is x+1x + 1 on [−1,0][-1, 0] and −(x+1)+2=1−x-(x+1) + 2 = 1 - x on [0,1][0, 1] — exactly the target.

0121f_Z(z): Z = u₁ + u₂ ⟶ subtract 1 −1011f_X(x): X = u₁ + u₂ − 1

Algorithm (convolution).

  1. Generate u1⊥u2∼U(0,1)u_1 \perp u_2 \sim U(0,1).
  2. Return X=u1+u2−1X = u_1 + u_2 - 1.

Why this beats both earlier methods. Add the new row to the table from §4.2.2:

uu’s comparisons additions multiplications square roots
inverse 1 1 1.5 1 1
composition 2 1 1.5 0 1
convolution 2 0 2 0 0

Convolution uses the same two uniforms as composition but eliminates the comparison, the multiplication, and above all the square root, at the price of half an extra addition. A square root is by far the most expensive operation in the table — many times the cost of an addition, and more than the cost of drawing a uniform — so removing it outweighs the second uniform, and convolution is the most efficient of the three for this distribution. (Against inverse transform, the trade is one extra uniform plus half an addition in exchange for dropping a comparison, a multiplication and a square root; the square root alone settles it.)

4.2.4. Acceptance–Rejection (AR)

Where it sits. Methods 1–3 (§4.2.1–4.2.3) are direct: they compute XX from the uniforms by a formula. Acceptance–rejection is the indirect method from the list in §4.2: it does not compute XX; it generates candidates from an easier distribution and keeps only some of them. The arrow in the lecture outline (“rejection → indirect”) just records that classification.

When to use it. When the desired p.d.f. ff has a form too complex to invert or decompose.

Idea. Use a simple, easy-to-sample p.d.f. — a surrogate — that approximates ff from above, then correct for the difference by discarding a fraction of the draws.

Y₁ Y₂ f(x) t(x) ≥ f(x) (dashed) accept Y with probability f(Y)/t(Y) = (thick bar) / (dashed bar): at Y₁, f ≈ t ⇒ almost always accepted; at Y₂, f ≪ t ⇒ usually rejected

Setup. Choose a majorizing function tt with

t(x)≥f(x)for all x.t(x) \ge f(x) \quad \text{for all } x .

Then

c=∫−∞∞t(x) dx  ≥  ∫−∞∞f(x) dx=1,c = \int_{-\infty}^{\infty} t(x)\,dx \;\ge\; \int_{-\infty}^{\infty} f(x)\,dx = 1,

so tt is not a density (its area exceeds 1), but its normalization

r(x)=t(x)cr(x) = \frac{t(x)}{c}

is a valid p.d.f. (r≥0r \ge 0 and ∫r=c/c=1\int r = c/c = 1). rr is the surrogate we actually sample from.

AR algorithm.

  1. Generate Y∼rY \sim r.
  2. Generate u∼U(0,1)u \sim U(0,1), independent of YY.
  3. If u≤f(Y)t(Y)u \le \dfrac{f(Y)}{t(Y)}, return X=YX = Y (accept).
  4. Otherwise discard YY and go back to step 1.

On step 1: YY is generated from the surrogate rr, not from ff — that is the whole point. Since rr was chosen to be simple, this is done by one of the direct methods (typically inverse transform). YY is only a candidate for XX; steps 3–4 decide whether it becomes one.

On step 3: the ratio f(Y)/t(Y)f(Y)/t(Y) lies in [0,1][0,1] because t≥ft \ge f. Comparing it with a uniform means: accept YY with probability f(Y)/t(Y)f(Y)/t(Y). Where tt hugs ff this is near 1 (almost always accept); where tt is far above ff it is small (usually reject). The rejections thin out exactly the regions where rr over-samples relative to ff.

Proof that the output has c.d.f. FF. The returned XX is a candidate YY given that it was accepted, so

P(X≤x)=P(Y≤x∣Y accepted)=P(Y≤x,  Y accepted)P(Y accepted).P(X \le x) = P(Y \le x \mid Y \text{ accepted}) = \frac{P(Y \le x,\; Y \text{ accepted})}{P(Y \text{ accepted})} .

We compute the denominator first (it is also the efficiency, comment 2 below):

P(Y accepted)=P ⁣(u≤f(Y)t(Y))=∫−∞∞P ⁣(u≤f(Y)t(Y)  |  Y=y)r(y) dy(condition on Y)=∫−∞∞P ⁣(u≤f(y)t(y))r(y) dy(u⊥Y, so the condition drops)=∫−∞∞f(y)t(y)⋅t(y)c dy(P(u≤a)=a;  r=t/c)=1c∫−∞∞f(y) dy=1c.\begin{aligned} P(Y \text{ accepted}) &= P\!\left(u \le \tfrac{f(Y)}{t(Y)}\right) \\ &= \int_{-\infty}^{\infty} P\!\left(u \le \tfrac{f(Y)}{t(Y)} \;\middle|\; Y = y\right) r(y)\,dy && \text{(condition on } Y\text{)} \\ &= \int_{-\infty}^{\infty} P\!\left(u \le \tfrac{f(y)}{t(y)}\right) r(y)\,dy && (u \perp Y \text{, so the condition drops}) \\ &= \int_{-\infty}^{\infty} \frac{f(y)}{t(y)} \cdot \frac{t(y)}{c}\,dy && (P(u \le a) = a;\; r = t/c) \\ &= \frac{1}{c}\int_{-\infty}^{\infty} f(y)\,dy = \frac{1}{c} . \end{aligned}

The numerator is the same calculation with the extra event Y≤xY \le x, which after conditioning on Y=yY = y just restricts the integral to y≤xy \le x:

P(Y≤x,  Y accepted)=∫−∞xf(y)t(y)⋅t(y)c dy=1c∫−∞xf(y) dy=F(x)c.P(Y \le x,\; Y \text{ accepted}) = \int_{-\infty}^{x} \frac{f(y)}{t(y)} \cdot \frac{t(y)}{c}\,dy = \frac{1}{c}\int_{-\infty}^{x} f(y)\,dy = \frac{F(x)}{c} .

Dividing,

P(X≤x)=F(x)/c1/c=F(x).■P(X \le x) = \frac{F(x)/c}{1/c} = F(x). \qquad\blacksquare

Note the mechanism: t(y)t(y) cancels between the acceptance probability f/tf/t and the surrogate density t/ct/c, and cc cancels between numerator and denominator. Whatever shape tt has, the output is exactly ff — the choice of tt affects only speed, never correctness.

Comments.

  1. Generating from rr must be much easier than generating from ff; otherwise there is no point in using a surrogate. In practice, choose simple majorizing functions — piecewise constant or piecewise linear.

  2. The algorithm loops until a pair (u,Y)(u, Y) with u≤f(Y)/t(Y)u \le f(Y)/t(Y) turns up. From the proof,

    P(Y accepted)=1c=1area under t,P(reject)=1−1c.P(Y \text{ accepted}) = \frac{1}{c} = \frac{1}{\text{area under } t}, \qquad P(\text{reject}) = 1 - \frac{1}{c}.

    Why the average number of trials is cc: each pass through steps 1–3 is an independent trial with success probability p=1/cp = 1/c (fresh YY and uu each time). The number of trials until the first success is therefore Geometric(p)(p), whose mean is 1/p=c1/p = c. So cc uniforms-pairs are consumed per variate on average — a large cc means a slow generator.

  3. P(Y accepted)=1/cP(Y \text{ accepted}) = 1/c is called the efficiency of the AR method. We want it as close to 1 as possible, i.e. tt as tight around ff as possible — but a tighter tt is usually a more complicated one, harder to sample from. This is the same simplicity vs. efficiency trade-off as in §4.1.

Example. f(x)=32x2f(x) = \frac{3}{2}x^2 on (−1,1)(-1, 1) (and 00 elsewhere). Check: ∫−1132x2 dx=1\int_{-1}^{1} \frac{3}{2}x^2\,dx = 1. The maximum of ff is 32\frac32, at x=±1x = \pm 1.

−1 0 1 3/2 f(x) = (3/2)x² t₁(x) = 3/2 (dashed): c = 3, efficiency 1/3 t₂(x) = (3/2)|x| (dotted): c = 3/2, efficiency 2/3

First attempt: a flat majorizing function. Take t(x)=32t(x) = \frac{3}{2} on (−1,1)(-1,1) — the smallest constant that stays above ff. Then c=32⋅2=3c = \frac{3}{2} \cdot 2 = 3 and r(x)=t(x)/3=12r(x) = t(x)/3 = \frac{1}{2} on (−1,1)(-1,1), i.e. rr is the U(−1,1)U(-1,1) density.

  1. Generate Y∼U(−1,1)Y \sim U(-1, 1) (e.g. Y=2u′−1Y = 2u' - 1 with u′∼U(0,1)u' \sim U(0,1)).
  2. Generate u∼U(0,1)u \sim U(0,1), independent of YY.
  3. If u≤Y2u \le Y^2, return X=YX = Y.   (f(Y)t(Y)=32Y232=Y2)\;\left(\dfrac{f(Y)}{t(Y)} = \dfrac{\frac32 Y^2}{\frac32} = Y^2\right)
  4. Otherwise go back to step 1.

Efficiency =1/c=1/3= 1/c = 1/3: on average three candidates (six uniforms) per accepted variate. The waste is visible in the figure — the rectangle under tt has area 3 while the bowl under ff has area 1, and everything in between is rejected.

Improvement: a tighter majorizing function. We need t≥ft \ge f but with less area. On [−1,1][-1,1] we have ∣x∣≥x2|x| \ge x^2, so

t(x)=32 ∣x∣  ≥  32 x2=f(x),t(x) = \tfrac{3}{2}\,|x| \;\ge\; \tfrac{3}{2}\,x^2 = f(x),

with equality at x=0,±1x = 0, \pm 1. Its area is c=∫−1132∣x∣ dx=32c = \int_{-1}^{1} \frac32|x|\,dx = \frac32, so the efficiency rises to 1/c=2/31/c = 2/3: on average 1.51.5 candidates per variate instead of 33. The surrogate is r(x)=t(x)/c=∣x∣r(x) = t(x)/c = |x| on (−1,1)(-1,1), a symmetric “V” density, easy to sample by inverse transform: its right half has c.d.f. x2x^2, so ∣Y∣=u′|Y| = \sqrt{u'}, and a fair coin picks the sign.

  1. Generate u1,u2∼U(0,1)u_1, u_2 \sim U(0,1); set Y=u2Y = \sqrt{u_2} if u1≤12u_1 \le \frac12, else Y=−u2Y = -\sqrt{u_2}. Then Y∼rY \sim r.
  2. Generate u∼U(0,1)u \sim U(0,1), independent of YY.
  3. If u≤∣Y∣u \le |Y|, return X=YX = Y.   (f(Y)t(Y)=32Y232∣Y∣=∣Y∣)\;\left(\dfrac{f(Y)}{t(Y)} = \dfrac{\frac32 Y^2}{\frac32 |Y|} = |Y|\right)
  4. Otherwise go back to step 1.

Each trial now costs three uniforms and a square root instead of two uniforms, but only 1.51.5 trials are needed on average instead of 33 — the trade-off of comment 3 in miniature.

4.2.5. Special Techniques

There is no general recipe here. A special technique exploits some property that the target distribution happens to have — a relation to another distribution we already know how to sample. Two small examples now; the big one (the normal distribution) gets its own treatment in §4.3.

Example: chi-square with one degree of freedom. Recall from §2.6.3 that if Y∼N(0,1)Y \sim N(0,1) then Y2∼χ12Y^2 \sim \chi^2_1. So:

  1. Generate Y∼N(0,1)Y \sim N(0,1) (§4.3).
  2. Return X=Y2X = Y^2.

Combining with convolution: χk2\chi^2_k is the sum of kk independent χ12\chi^2_1 variables, so X=Y12+⋯+Yk2X = Y_1^2 + \cdots + Y_k^2 with YiY_i i.i.d. N(0,1)N(0,1).

Example: geometric by Bernoulli trials. Let X∼Geo(p)X \sim \text{Geo}(p) be the number of trials needed until the first success, each trial succeeding with probability pp. Simulate the trials literally:

  1. Set X=1X = 1.
  2. Generate Y∼Bernoulli(p)Y \sim \text{Bernoulli}(p) (i.e. u∼U(0,1)u \sim U(0,1) and Y=1Y = 1 if u≤pu \le p).
  3. If Y=1Y = 1, return XX.
  4. Otherwise set X=X+1X = X + 1 and go back to step 2.

This is exact and transparent, but it consumes one uniform per trial, and the expected number of trials is E[X]=1/p\mathbf{E}[X] = 1/p. For p=0.01p = 0.01 that is 100 uniforms per variate. §4.4 gives a one-uniform formula instead.

4.3. Generating Continuous Random Variates

§4.2 presented the methods abstractly. This section collects the concrete algorithms actually used for the common continuous distributions.

Uniform U(a,b)U(a,b). Inverse transform: F(x)=x−ab−aF(x) = \frac{x-a}{b-a} on [a,b][a,b], so u=x−ab−a  ⟺  x=a+(b−a)uu = \frac{x-a}{b-a} \iff x = a + (b-a)u.

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=a+(b−a) uX = a + (b-a)\,u.

Exponential Exp(λ)\text{Exp}(\lambda). From §4.2.1:

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=−1λln⁡uX = -\dfrac{1}{\lambda}\ln u.

Erlang(m,λ)(m, \lambda). From §4.2.3, X=Y1+⋯+YmX = Y_1 + \cdots + Y_m with YiY_i i.i.d. Exp(λ)\text{Exp}(\lambda):

  1. Generate u1,…,um∼U(0,1)u_1, \dots, u_m \sim U(0,1).
  2. Return X=−1λln⁡ ⁣(∏i=1mui)X = -\dfrac{1}{\lambda}\ln\!\left(\prod_{i=1}^m u_i\right).

(Gamma with non-integer shape, Weibull, beta, etc. need special-purpose methods, mostly acceptance–rejection; not covered here.)

4.3.1. Normal distribution: the Box–Muller method

The normal c.d.f. has no closed-form inverse, so inverse transform is out. Composition and convolution do not apply. The trick is a special technique: look at two independent standard normals at once and switch to polar coordinates.

The key fact. Let X1⊥X2∼N(0,1)X_1 \perp X_2 \sim N(0,1) and write the point (X1,X2)(X_1, X_2) in polar form:

R2=X12+X22,Θ=tan⁡−1 ⁣(X2X1).R^2 = X_1^2 + X_2^2, \qquad \Theta = \tan^{-1}\!\left(\frac{X_2}{X_1}\right).

Then R2R^2 and Θ\Theta are independent, with

R2∼Exp ⁣(12) (rate 12, mean 2),Θ∼U(0,2π).R^2 \sim \text{Exp}\!\left(\tfrac12\right) \ \text{(rate } \tfrac12\text{, mean } 2), \qquad \Theta \sim U(0, 2\pi).

(X₁, X₂) R Θ x₁ x₂ X₁ = R cos Θ X₂ = R sin Θ If X₁, X₂ are i.i.d. N(0,1), then R² = X₁² + X₂² ~ Exp(rate ½) (mean 2) Θ ~ U(0, 2π), independent of R² Box–Muller runs this backwards: draw R² and Θ, convert to (X₁, X₂)

Why. The joint density of (X1,X2)(X_1, X_2) is the product of two N(0,1)N(0,1) densities:

fX1,X2(x1,x2)=12πe−x12/2⋅12πe−x22/2=12πexp⁡ ⁣(−x12+x222).f_{X_1,X_2}(x_1, x_2) = \frac{1}{\sqrt{2\pi}}e^{-x_1^2/2}\cdot\frac{1}{\sqrt{2\pi}}e^{-x_2^2/2} = \frac{1}{2\pi}\exp\!\left(-\frac{x_1^2 + x_2^2}{2}\right).

It depends on (x1,x2)(x_1, x_2) only through x12+x22=r2x_1^2 + x_2^2 = r^2 — the density is rotationally symmetric, which is why the angle will come out uniform. To change variables to (S,Θ)=(R2,Θ)(S, \Theta) = (R^2, \Theta) we need the Jacobian of the map g1(x1,x2)=x12+x22g_1(x_1,x_2) = x_1^2 + x_2^2, g2(x1,x2)=tan⁡−1(x2/x1)g_2(x_1,x_2) = \tan^{-1}(x_2/x_1). Using ddxtan⁡−1x=11+x2\frac{d}{dx}\tan^{-1}x = \frac{1}{1+x^2},

J=∣∂g1/∂x1∂g1/∂x2∂g2/∂x1∂g2/∂x2∣=∣2x12x2−x2x12+x22x1x12+x22∣=2x12+2x22x12+x22=2.J = \begin{vmatrix} \partial g_1/\partial x_1 & \partial g_1/\partial x_2 \\ \partial g_2/\partial x_1 & \partial g_2/\partial x_2 \end{vmatrix} = \begin{vmatrix} 2x_1 & 2x_2 \\ -\dfrac{x_2}{x_1^2+x_2^2} & \dfrac{x_1}{x_1^2+x_2^2} \end{vmatrix} = \frac{2x_1^2 + 2x_2^2}{x_1^2 + x_2^2} = 2 .

The change-of-variables formula gives fS,Θ(s,θ)=fX1,X2(x1,x2) ∣J∣−1f_{S,\Theta}(s,\theta) = f_{X_1,X_2}(x_1,x_2)\,|J|^{-1}, so

fS,Θ(s,θ)=12πe−s/2⋅12=12e−s/2⏟Exp(1/2) density in s  ⋅  12π⏟U(0,2π) density in θ,s≥0, 0≤θ<2π.f_{S,\Theta}(s, \theta) = \frac{1}{2\pi}e^{-s/2}\cdot\frac{1}{2} = \underbrace{\tfrac{1}{2}e^{-s/2}}_{\text{Exp}(1/2)\text{ density in } s}\;\cdot\;\underbrace{\tfrac{1}{2\pi}}_{U(0,2\pi)\text{ density in }\theta}, \qquad s \ge 0,\ 0 \le \theta < 2\pi .

The joint density factors into a function of ss alone times a function of θ\theta alone, which is exactly the statement that S=R2S = R^2 and Θ\Theta are independent with those marginals.

Run it backwards. We know how to generate both pieces: R2∼Exp(12)R^2 \sim \text{Exp}(\tfrac12) is −2ln⁡u1-2\ln u_1 by inverse transform (rate λ=12\lambda = \tfrac12 gives −1λln⁡u=−2ln⁡u-\frac{1}{\lambda}\ln u = -2\ln u), and Θ=2πu2\Theta = 2\pi u_2. Converting back from polar to Cartesian coordinates then yields two independent standard normals.

Algorithm (Box–Muller).

  1. Generate u1⊥u2∼U(0,1)u_1 \perp u_2 \sim U(0,1).
  2. Return

X1=−2ln⁡u1 cos⁡(2πu2),X2=−2ln⁡u1 sin⁡(2πu2).X_1 = \sqrt{-2\ln u_1}\,\cos(2\pi u_2), \qquad X_2 = \sqrt{-2\ln u_1}\,\sin(2\pi u_2).

Two uniforms in, two independent N(0,1)N(0,1) variates out — exact, no rejection.

Two cautions.

  • The uniforms must really be independent. If u1,u2u_1, u_2 are consecutive outputs of a poor LCG (recall RANDU, §3.2.3), the pairs (u1,u2)(u_1, u_2) lie on a few lines in the unit square, and after the transformation the points (X1,X2)(X_1, X_2) fall on a visible spiral in the plane. In practice one uses separate streams for u1u_1 and u2u_2 (§3.3, practical issue 3).
  • Cost. One logarithm, one square root, one sine and one cosine per pair. The trigonometric functions are expensive, which motivates the next algorithm.

4.3.2. Normal distribution: the polar method (acceptance–rejection)

The polar method avoids sin⁡\sin and cos⁡\cos by generating the angle geometrically instead of computing it.

Algorithm (polar method).

  1. Generate V1⊥V2∼U(−1,1)V_1 \perp V_2 \sim U(-1, 1) (i.e. Vi=2ui−1V_i = 2u_i - 1).
  2. Let S=V12+V22S = V_1^2 + V_2^2. If S>1S > 1 (or S=0S = 0), go back to step 1.
  3. Otherwise let

W=−2ln⁡SSW = \sqrt{\frac{-2\ln S}{S}}

and return X1=V1WX_1 = V_1 W, X2=V2WX_2 = V_2 W.

−1 1 1 −1 V₁ V₂ S ≤ 1: accept S > 1: reject (V₁, V₂) uniform on the square; keep it only if it lands in the disk. P(accept) = area(disk)/area(square) = π·1² / 2² = π/4 ≈ 0.785 Accepted points are uniform on the disk, so their angle is U(0,2π) and S = V₁²+V₂² is U(0,1), independently — no trig needed.

Why it works. The pair (V1,V2)(V_1, V_2) is uniform on the square [−1,1]2[-1,1]^2; conditioning on S≤1S \le 1 makes it uniform on the unit disk. For a uniform point in the disk, the angle Θ\Theta is U(0,2π)U(0,2\pi) and the squared radius SS is U(0,1)U(0,1) (because P(S≤s)=area of disk of radius s=πs/π=sP(S \le s) = \text{area of disk of radius }\sqrt{s} = \pi s / \pi = s), independently of each other. Now compare with Box–Muller: we need cos⁡Θ\cos\Theta, sin⁡Θ\sin\Theta, and −2ln⁡u\sqrt{-2\ln u} for a uniform uu. But

cos⁡Θ=V1S,sin⁡Θ=V2S,and S itself is the uniform we need, so R=−2ln⁡S.\cos\Theta = \frac{V_1}{\sqrt S}, \qquad \sin\Theta = \frac{V_2}{\sqrt S}, \qquad \text{and } S \text{ itself is the uniform we need, so } R = \sqrt{-2\ln S}.

Multiplying out,

X1=Rcos⁡Θ=−2ln⁡S⋅V1S=V1−2ln⁡SS=V1W,X_1 = R\cos\Theta = \sqrt{-2\ln S}\cdot\frac{V_1}{\sqrt S} = V_1\sqrt{\frac{-2\ln S}{S}} = V_1 W,

and likewise X2=V2WX_2 = V_2 W. The cosine and sine have been replaced by a division.

Efficiency. P(accept)=P(S≤1)=area of unit diskarea of square=π4≈0.785P(\text{accept}) = P(S \le 1) = \dfrac{\text{area of unit disk}}{\text{area of square}} = \dfrac{\pi}{4} \approx 0.785, so on average 4/π≈1.274/\pi \approx 1.27 attempts, i.e. about 2.552.55 uniforms per pair of normals. The price of avoiding trigonometry is that roughly one attempt in five is thrown away, and the method no longer uses a fixed number of uniforms per variate (bad for synchronization, §4.1).

Non-standard normal. If Y∼N(0,1)Y \sim N(0,1) then X=μ+σY∼N(μ,σ2)X = \mu + \sigma Y \sim N(\mu, \sigma^2). Generate YY by either method above and shift and scale.

4.3.3. Lognormal distribution

XX is lognormal, X∼LN(μ,σ2)X \sim LN(\mu, \sigma^2), if ln⁡X∼N(μ,σ2)\ln X \sim N(\mu, \sigma^2) — equivalently X=eYX = e^Y with Y∼N(μ,σ2)Y \sim N(\mu, \sigma^2). (Note μ,σ2\mu, \sigma^2 are the mean and variance of ln⁡X\ln X, not of XX.)

  1. Generate Y∼N(μ,σ2)Y \sim N(\mu, \sigma^2).
  2. Return X=eYX = e^Y.

4.3.4. Truncated distributions

Suppose we want XX restricted to an interval [a,b][a, b]. There are two different things “truncate” can mean:

  • Redistribute the mass that falls outside [a,b][a,b] proportionally over [a,b][a,b] — the conditional distribution of XX given a≤X≤ba \le X \le b.
  • Pile up the outside mass at the endpoints: values below aa become aa, values above bb become bb. This is clipping, X∗=min⁡(max⁡(X,a),b)X^* = \min(\max(X, a), b), and it creates atoms at aa and bb.

The first is the usual meaning. Its c.d.f. is

F~(x)=F(x)−F(a)F(b)−F(a),a≤x≤b,\tilde F(x) = \frac{F(x) - F(a)}{F(b) - F(a)}, \qquad a \le x \le b,

with density f~(x)=f(x)F(b)−F(a)\tilde f(x) = \dfrac{f(x)}{F(b) - F(a)} on [a,b][a,b] — the original density scaled up by the constant 1/(F(b)−F(a))1/(F(b)-F(a)) so that it integrates to 1 again. (Check: F~(x)=∫axf(y)F(b)−F(a) dy=F(x)−F(a)F(b)−F(a)\tilde F(x) = \int_a^x \frac{f(y)}{F(b)-F(a)}\,dy = \frac{F(x)-F(a)}{F(b)-F(a)}.)

Inverting F~\tilde F is one line:

u=F(x)−F(a)F(b)−F(a)  ⟹  F(x)=F(a)+u [F(b)−F(a)]  ⟹  x=F−1(F(a)+u [F(b)−F(a)]).u = \frac{F(x) - F(a)}{F(b) - F(a)} \;\Longrightarrow\; F(x) = F(a) + u\,[F(b) - F(a)] \;\Longrightarrow\; x = F^{-1}\big(F(a) + u\,[F(b)-F(a)]\big).

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=F−1(F(a)+u [F(b)−F(a)])X = F^{-1}\big(F(a) + u\,[F(b) - F(a)]\big).

This is the “advantage 3” of §4.2.1 in detail. The alternative — generate from FF and reject anything outside [a,b][a,b] — is acceptance–rejection with efficiency F(b)−F(a)F(b) - F(a), which can be tiny if the interval is in a tail; the inverse-transform version uses every uniform.

4.3.5. More continuous distributions

A short tour of the other continuous distributions the textbook covers.

Inverse transform, closed form.

  • Weibull(α,β)(\alpha, \beta): F(x)=1−e−(x/β)αF(x) = 1 - e^{-(x/\beta)^\alpha}, so F−1(u)=β [−ln⁡(1−u)]1/αF^{-1}(u) = \beta\,[-\ln(1-u)]^{1/\alpha}. Algorithm: generate uu, return X=β(−ln⁡u)1/αX = \beta(-\ln u)^{1/\alpha}. (Equivalently: an Exp\text{Exp} variable with mean βα\beta^\alpha, raised to the power 1/α1/\alpha.)

  • Log-logistic(α,β)(\alpha, \beta): F−1(u)=β [u/(1−u)]1/αF^{-1}(u) = \beta\,[u/(1-u)]^{1/\alpha}.

  • Triangular(0,1,m)(0, 1, m) (mode m∈(0,1)m \in (0,1)):

    F−1(u)={m u,0≤u≤m,1−(1−m)(1−u),m<u≤1.F^{-1}(u) = \begin{cases} \sqrt{m\,u}, & 0 \le u \le m, \\ 1 - \sqrt{(1-m)(1-u)}, & m < u \le 1. \end{cases}

    Generate uu; if u≤mu \le m return mu\sqrt{mu}, otherwise return 1−(1−m)(1−u)1 - \sqrt{(1-m)(1-u)}. For triang(a,b,m)\text{triang}(a, b, m) rescale: X′=a+(b−a)XX' = a + (b-a)X with mode (m−a)/(b−a)(m-a)/(b-a).

    The textbook’s “Why?”: in the second branch one may not replace 1−u1 - u by uu. The usual excuse — “uu and 1−u1-u have the same distribution” — applies to a uniform used on its own. Here the same uu also decides the branch: the second formula is only ever evaluated for u∈(m,1]u \in (m, 1], and on that set 1−u1 - u ranges over [0,1−m)[0, 1-m) while uu ranges over (m,1](m, 1] — different sets, different distributions. Making the swap gives the wrong answer (in a check with m=0.3m = 0.3, P(X≤m)P(X \le m) came out 0.600.60 instead of 0.300.30). To swap, you would have to swap in both places: test u≥1−mu \ge 1-m and use 1−u1-u in the first branch as well.

Special properties.

  • Student’s tkt_k: if Y∼N(0,1)Y \sim N(0,1) and Z∼χk2Z \sim \chi^2_k are independent, X=Y/Z/k∼tkX = Y/\sqrt{Z/k} \sim t_k. Generate YY (§4.3.1) and ZZ (§4.2.5) and combine.
  • Fk1,k2F_{k_1, k_2}: with independent Z1∼χk12Z_1 \sim \chi^2_{k_1}, Z2∼χk22Z_2 \sim \chi^2_{k_2}, X=(Z1/k1)/(Z2/k2)X = (Z_1/k_1)/(Z_2/k_2).
  • Beta(α1,α2)(\alpha_1, \alpha_2) on [0,1][0,1]: with independent Y1∼Gamma(α1,1)Y_1 \sim \text{Gamma}(\alpha_1, 1), Y2∼Gamma(α2,1)Y_2 \sim \text{Gamma}(\alpha_2, 1), X=Y1/(Y1+Y2)X = Y_1/(Y_1 + Y_2). Special cases need no gamma: Beta(α1,1)\text{Beta}(\alpha_1, 1) has F(x)=xα1F(x) = x^{\alpha_1}, so X=u1/α1X = u^{1/\alpha_1}; Beta(1,1)=U(0,1)\text{Beta}(1,1) = U(0,1); and 1−X∼Beta(α2,α1)1 - X \sim \text{Beta}(\alpha_2, \alpha_1).
  • Gamma(α,β)(\alpha, \beta) with non-integer α\alpha: no closed-form inverse; the textbook gives two acceptance–rejection algorithms (Ahrens–Dieter for 0<α<10 < \alpha < 1, Cheng for α>1\alpha > 1). Scale is free: Gamma(α,β)=β⋅Gamma(α,1)\text{Gamma}(\alpha, \beta) = \beta \cdot \text{Gamma}(\alpha, 1). The mm-Erlang algorithm of §4.3 is the integer case; for m≳10m \gtrsim 10 the general gamma generator is faster, and for large mm the product ∏ui\prod u_i can underflow toward 00 before its logarithm is taken.

Lognormal: matching a target mean and variance. The parameters μ,σ2\mu, \sigma^2 of LN(μ,σ2)LN(\mu, \sigma^2) are the mean and variance of ln⁡X\ln X, not of XX. If the model is specified by m′=E[X]m' = \mathbf{E}[X] and s′2=Var⁡(X)s'^2 = \operatorname{Var}(X), convert first:

μ=ln⁡m′2m′2+s′2,σ2=ln⁡ ⁣(1+s′2m′2),\mu = \ln\frac{m'^2}{\sqrt{m'^2 + s'^2}}, \qquad \sigma^2 = \ln\!\Big(1 + \frac{s'^2}{m'^2}\Big),

then generate Y∼N(μ,σ2)Y \sim N(\mu, \sigma^2) and return X=eYX = e^Y. (Check with m′=2m' = 2, s′2=1s'^2 = 1: simulated mean 2.002.00, variance 1.001.00.)

Empirical distributions. With raw observations X(1)≤⋯≤X(n)X_{(1)} \le \cdots \le X_{(n)} and the piecewise-linear empirical c.d.f. of §2, the inverse transform needs no search because the corners sit at levels 0,1n−1,2n−1,…,10, \frac{1}{n-1}, \frac{2}{n-1}, \dots, 1:

  1. Generate uu; let P=(n−1)uP = (n-1)u and I=⌊P⌋+1I = \lfloor P \rfloor + 1.
  2. Return X=X(I)+(P−I+1)(X(I+1)−X(I))X = X_{(I)} + (P - I + 1)\big(X_{(I+1)} - X_{(I)}\big).

The output always lies in [X(1),X(n)][X_{(1)}, X_{(n)}] — no values beyond the observed range can ever appear, which is the known limitation of empirical input modelling.

4.4. Generating Discrete Random Variates

Inverse transform works for every discrete distribution (§4.2.1), but is not always the fastest. Besides the specific formulas below, the section ends with two table-based methods — table lookup and the alias method — that trade setup and storage for speed.

Bernoulli(p)(p). X=1X = 1 with probability pp, 00 with probability 1−p1-p. Inverse transform with two values:

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. If u≤pu \le p, return X=1X = 1; otherwise return X=0X = 0.

Binomial(n,p)(n, p). The number of successes in nn independent Bernoulli(p)(p) trials is a sum, so use convolution:

  1. Generate Y1,…,YnY_1, \dots, Y_n i.i.d. Bernoulli(p)(p).
  2. Return X=Y1+⋯+YnX = Y_1 + \cdots + Y_n.

Costs nn uniforms per variate; fine for small nn.

Discrete uniform DU(i,j)DU(i, j). P(X=k)=1j−i+1P(X = k) = \dfrac{1}{j-i+1} for k=i,i+1,…,jk = i, i+1, \dots, j. Generalizing the ⌈100u⌉\lceil 100u \rceil trick of §4.2.1:

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=i+⌊(j−i+1) u⌋X = i + \lfloor (j - i + 1)\,u \rfloor.

Here ⌊x⌋\lfloor x \rfloor is the largest integer ≤x\le x. The product (j−i+1)u(j-i+1)u is uniform on [0,j−i+1)[0, j-i+1); its floor is uniform on {0,1,…,j−i}\{0, 1, \dots, j-i\}; adding ii shifts to {i,…,j}\{i, \dots, j\}. (The floor form is slightly safer than the ceiling form when uu can be exactly 00.)

Geometric(p)(p). p(k)=(1−p)k−1pp(k) = (1-p)^{k-1}p, k=1,2,…k = 1, 2, \dots — the number of trials up to and including the first success. Instead of simulating the trials (§4.2.5), invert the c.d.f. in closed form. The inverse-transform intervals are

0<u≤p⇒X=1,p<u≤p+(1−p)p⇒X=2,…0 < u \le p \Rightarrow X = 1, \qquad p < u \le p + (1-p)p \Rightarrow X = 2, \qquad \dots

and in general X=kX = k when

∑i=1k−1(1−p)i−1p  <  u  ≤  ∑i=1k(1−p)i−1p.\sum_{i=1}^{k-1}(1-p)^{i-1}p \;<\; u \;\le\; \sum_{i=1}^{k}(1-p)^{i-1}p .

Each side is a geometric series: ∑i=1k(1−p)i−1p=p 1−(1−p)k1−(1−p)=1−(1−p)k\sum_{i=1}^{k}(1-p)^{i-1}p = p\,\dfrac{1 - (1-p)^k}{1 - (1-p)} = 1 - (1-p)^k. So the condition is

1−(1−p)k−1<u≤1−(1−p)k⟺(1−p)k≤1−u<(1−p)k−1.1 - (1-p)^{k-1} < u \le 1 - (1-p)^{k} \quad\Longleftrightarrow\quad (1-p)^{k} \le 1 - u < (1-p)^{k-1}.

Take logarithms. Since 0<1−p<10 < 1-p < 1, ln⁡(1−p)<0\ln(1-p) < 0, so the inequalities flip:

kln⁡(1−p)≤ln⁡(1−u)<(k−1)ln⁡(1−p),k\ln(1-p) \le \ln(1-u) < (k-1)\ln(1-p),

and dividing by the negative number ln⁡(1−p)\ln(1-p) flips them back:

k≥ln⁡(1−u)ln⁡(1−p)>k−1.k \ge \frac{\ln(1-u)}{\ln(1-p)} > k - 1 .

The integer kk sitting just above ln⁡(1−u)ln⁡(1−p)\frac{\ln(1-u)}{\ln(1-p)} is its ceiling. Finally replace 1−u1-u by uu (same distribution):

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=⌈ln⁡uln⁡(1−p)⌉X = \left\lceil \dfrac{\ln u}{\ln(1-p)} \right\rceil.

One uniform and one logarithm, regardless of pp — compare 1/p1/p uniforms for the trial-by-trial method. The formula is the discrete twin of the exponential’s −1λln⁡u-\frac{1}{\lambda}\ln u: the geometric is the exponential’s discrete analogue (it has the same memoryless property), and the generators have the same shape.

Arbitrary discrete distribution. X∈{0,1,…,n}X \in \{0, 1, \dots, n\} with P(X=i)=p(i)P(X = i) = p(i). Inverse transform:

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=iX = i for the ii with ∑j=0i−1p(j)  ≤  u  <  ∑j=0ip(j)\displaystyle\sum_{j=0}^{i-1} p(j) \;\le\; u \;<\; \sum_{j=0}^{i} p(j).

This is the search of §4.2.1; for large nn it is slow, and the first improvement is to test the values in decreasing order of p(i)p(i). The two methods below go further.

4.4.1. Table lookup

Idea. If all probabilities are given to qq decimal places, then each p(i)p(i) is a whole number of units of size 10−q10^{-q}. Build a vector mm of length 10q10^q in which value ii appears 10q p(i)10^q\,p(i) times. Picking a uniformly random entry of mm then returns ii with exactly the right probability — no search at all.

Example. P(0)=0.15P(0) = 0.15, P(1)=0.20P(1) = 0.20, P(2)=0.37P(2) = 0.37, P(3)=0.28P(3) = 0.28, so q=2q = 2. Construct mm of length 100100:

m=[0,…,0⏟15,  1,…,1⏟20,  2,…,2⏟37,  3,…,3⏟28].m = [\underbrace{0, \dots, 0}_{15},\; \underbrace{1, \dots, 1}_{20},\; \underbrace{2, \dots, 2}_{37},\; \underbrace{3, \dots, 3}_{28}] .

  1. Generate J∼DU(1,100)J \sim DU(1, 100), i.e. J=1+⌊100u⌋J = 1 + \lfloor 100u \rfloor.
  2. Return X=mJX = m_J.

Check: P(X=2)=P(J lands on one of the 37 entries equal to 2)=37/100P(X = 2) = P(J \text{ lands on one of the 37 entries equal to } 2) = 37/100. ✓

Simple and very fast (one uniform, one index), but it needs setup and 10q10^q storage locations — q=6q = 6 already means a million entries.

4.4.2. Improved table lookup

Idea. Split each probability by decimal digit and keep one table per digit. Same example:

ii p(i)p(i) tenths digit hundredths digit
0 0.15 1 5
1 0.20 2 0
2 0.37 3 7
3 0.28 2 8
sum 8 20

Build one table from the tenths digits (value ii appears “tenths digit” times) and one from the hundredths digits:

m(1)=[0, 1,1, 2,2,2, 3,3](length 8),m(2)=[0,…,0⏟5, 2,…,2⏟7, 3,…,3⏟8](length 20).m^{(1)} = [0,\ 1, 1,\ 2, 2, 2,\ 3, 3] \quad (\text{length } 8), \qquad m^{(2)} = [\underbrace{0,\dots,0}_{5},\ \underbrace{2,\dots,2}_{7},\ \underbrace{3,\dots,3}_{8}] \quad (\text{length } 20).

Total storage 8+20=288 + 20 = 28 instead of 100100. (Value 1 is absent from m(2)m^{(2)} because its hundredths digit is 00.)

The tenths table carries total mass 8/10=0.88/10 = 0.8 and the hundredths table carries 20/100=0.220/100 = 0.2. So:

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. If u≤0.8u \le 0.8, generate J1∼DU(1,8)J_1 \sim DU(1, 8) and return X=mJ1(1)X = m^{(1)}_{J_1}.
  3. Otherwise generate J2∼DU(1,20)J_2 \sim DU(1, 20) and return X=mJ2(2)X = m^{(2)}_{J_2}.

Check: P(X=2)=P(X=2∣table 1) P(table 1)+P(X=2∣table 2) P(table 2)=38⋅810+720⋅210=0.30+0.07=0.37P(X = 2) = P(X = 2 \mid \text{table 1})\,P(\text{table 1}) + P(X = 2 \mid \text{table 2})\,P(\text{table 2}) = \frac{3}{8}\cdot\frac{8}{10} + \frac{7}{20}\cdot\frac{2}{10} = 0.30 + 0.07 = 0.37. ✓ The two terms are exactly the tenths and hundredths parts of 0.370.37.

This is composition (§4.2.2) in disguise: p=0.8 p(1)+0.2 p(2)p = 0.8\,p^{(1)} + 0.2\,p^{(2)}, where p(j)p^{(j)} is the uniform-pick distribution on table jj. It costs two uniforms per variate instead of one, in exchange for far less storage when qq is large.

4.4.3. The alias method

The alias method keeps table lookup’s speed — one uniform-pick plus one comparison — with only 2(n+1)2(n+1) storage locations, whatever the precision of the probabilities.

Setup. Two vectors of length n+1n+1:

  • cutoff values F0,F1,…,Fn∈[0,1]F_0, F_1, \dots, F_n \in [0,1],
  • aliases L0,L1,…,Ln∈{0,1,…,n}L_0, L_1, \dots, L_n \in \{0, 1, \dots, n\}.

Algorithm.

  1. Generate I∼DU(0,n)I \sim DU(0, n) and u∼U(0,1)u \sim U(0,1) independently.
  2. If u≤FIu \le F_I, return X=IX = I; otherwise return X=LIX = L_I.
pick a column I ~ DU(0,3); keep I if U ≤ Fᵢ, else return its alias 1 0 0alias 2I = 0F = 0.601alias 2I = 1F = 0.802alias 3I = 2F = 0.883I = 3F = 1.00

How to read it. Each value II is drawn with probability 1n+1\frac{1}{n+1} — an equal-size “column”. Inside column II, a fraction FIF_I of the column belongs to II itself and the remaining 1−FI1 - F_I belongs to one other value, its alias LIL_I. So

P(X=k)=1n+1[ Fk+∑i : Li=k(1−Fi)]:P(X = k) = \frac{1}{n+1}\Big[\,F_k + \sum_{i \,:\, L_i = k} (1 - F_i)\Big] :

kk’s own share of its column, plus whatever the other columns hand to it as an alias. The setup consists of choosing FF and LL so that this equals p(k)p(k) for every kk.

It resembles acceptance–rejection (draw a candidate, compare uu to a threshold), with one crucial difference: on “rejection” we do not start over — we return the alias. There is no loop, so exactly one II and one uu are consumed per variate.

Setup for the example p=(0.15,0.20,0.37,0.28)p = (0.15, 0.20, 0.37, 0.28), n+1=4n + 1 = 4. Scale by n+1n+1: q=4p=(0.60,0.80,1.48,1.12)q = 4p = (0.60, 0.80, 1.48, 1.12). Each column has capacity 11; values with qi<1q_i < 1 have spare room, values with qi>1q_i > 1 have excess. Repeatedly fill a “small” column from a “large” one:

step small column ii gets Fi=qiF_i = q_i alias LiL_i donor’s remaining qq
1 00 (0.600.60) 0.600.60 22 q2=1.48−0.40=1.08q_2 = 1.48 - 0.40 = 1.08
2 11 (0.800.80) 0.800.80 22 q2=1.08−0.20=0.88q_2 = 1.08 - 0.20 = 0.88
3 22 (0.880.88) 0.880.88 33 q3=1.12−0.12=1.00q_3 = 1.12 - 0.12 = 1.00
4 33 (1.001.00) 1.001.00 — (never used)

Result: F=(0.60, 0.80, 0.88, 1.00)F = (0.60,\ 0.80,\ 0.88,\ 1.00), L=(2, 2, 3, 3)L = (2,\ 2,\ 3,\ 3).

Check: P(X=2)=14[0.88+(1−0.60)+(1−0.80)]=14(1.48)=0.37P(X = 2) = \frac14\big[0.88 + (1 - 0.60) + (1 - 0.80)\big] = \frac14 (1.48) = 0.37 ✓, and P(X=3)=14[1.00+(1−0.88)]=14(1.12)=0.28P(X = 3) = \frac14\big[1.00 + (1 - 0.88)\big] = \frac14(1.12) = 0.28 ✓. (The table is not unique — a different pairing order gives different valid F,LF, L.)

Assessment. Very fast once set up; drawbacks are the setup computation and the 2(n+1)2(n+1) storage locations. For a fixed discrete distribution sampled millions of times, it is the method of choice.

Summary of the discrete methods.

method uniforms / variate time per variate storage setup
inverse transform 1 up to nn comparisons n+1n+1 sort (optional)
table lookup 1 O(1)O(1) 10q10^q build table
improved table lookup 2 O(1)O(1) sum of digits build tables
alias 2 (or 1 split in two) O(1)O(1) 2(n+1)2(n+1) build F,LF, L

4.5. Generating Random Vectors

Why a separate section. Everything so far produces one random variable at a time, and successive variates are independent. Many inputs come in correlated groups: a job’s processing times at two consecutive stations, a customer’s order size and service time, daily demands for related products. Generating each coordinate on its own throws the correlation away. We need a way to produce a whole vector X=(X1,…,Xd)TX = (X_1, \dots, X_d)^{\mathsf T} with a prescribed mean and a prescribed dependence structure.

4.5.1. Mean vector and covariance matrix

For a random vector X∈RdX \in \mathbb{R}^d:

μ=E[X]=(E[X1],…,E[Xd])T,Σ=cov⁡(X)=E[(X−μ)(X−μ)T],\mu = \mathbf{E}[X] = \big(\mathbf{E}[X_1], \dots, \mathbf{E}[X_d]\big)^{\mathsf T}, \qquad \Sigma = \operatorname{cov}(X) = \mathbf{E}\big[(X-\mu)(X-\mu)^{\mathsf T}\big],

so Σ\Sigma is d×dd \times d with entries Σij=cov⁡(Xi,Xj)\Sigma_{ij} = \operatorname{cov}(X_i, X_j) — variances on the diagonal, covariances off it (§2.3). Two facts about Σ\Sigma that the construction below relies on:

  • Σ\Sigma is symmetric, since cov⁡(Xi,Xj)=cov⁡(Xj,Xi)\operatorname{cov}(X_i, X_j) = \operatorname{cov}(X_j, X_i).
  • Σ\Sigma is positive semidefinite: for any constant vector aa, aTΣa=Var⁡(aTX)≥0a^{\mathsf T}\Sigma a = \operatorname{Var}(a^{\mathsf T}X) \ge 0. A variance cannot be negative.

Linear transformations. If Y=b+AXY = b + AX for a constant vector bb and constant matrix AA, then

E[Y]=b+Aμ,cov⁡(Y)=A Σ AT.\mathbf{E}[Y] = b + A\mu, \qquad \operatorname{cov}(Y) = A\,\Sigma\,A^{\mathsf T}.

(The second follows from Y−E[Y]=A(X−μ)Y - \mathbf{E}[Y] = A(X - \mu), so cov⁡(Y)=E[A(X−μ)(X−μ)TAT]=AΣAT\operatorname{cov}(Y) = \mathbf{E}[A(X-\mu)(X-\mu)^{\mathsf T}A^{\mathsf T}] = A\Sigma A^{\mathsf T}.) This is the whole trick: we can manufacture any covariance we like by applying a matrix to something simple.

4.5.2. The multivariate normal distribution

X∼Nd(μ,Σ)X \sim N_d(\mu, \Sigma) is the dd-dimensional normal with mean vector μ\mu and covariance matrix Σ\Sigma. Its one property we need: a linear transformation of a multivariate normal is again multivariate normal. Combined with the formulas above, if X∼Nd(μ,Σ)X \sim N_d(\mu, \Sigma) then b+AX∼N(b+Aμ,  AΣAT)b + AX \sim N(b + A\mu,\; A\Sigma A^{\mathsf T}).

The simplest member of the family is the standard one. Let Z1,…,ZdZ_1, \dots, Z_d be i.i.d. N(0,1)N(0,1) (§4.3.1) and Z=(Z1,…,Zd)TZ = (Z_1, \dots, Z_d)^{\mathsf T}. Then E[Z]=0\mathbf{E}[Z] = 0 and cov⁡(Z)=Id\operatorname{cov}(Z) = I_d (variances 1, covariances 0 by independence), so Z∼Nd(0,Id)Z \sim N_d(0, I_d).

The plan. Take X=μ+AZX = \mu + AZ. Then XX is multivariate normal with

E[X]=μ,cov⁡(X)=A I AT=AAT.\mathbf{E}[X] = \mu, \qquad \operatorname{cov}(X) = A\,I\,A^{\mathsf T} = AA^{\mathsf T}.

So all we need is a matrix AA with

AAT=Σ,AA^{\mathsf T} = \Sigma,

a “square root” of Σ\Sigma. There are two standard ways to get one; the lecture uses the second.

  1. Cholesky factorization. Any symmetric positive-definite Σ\Sigma can be written Σ=LLT\Sigma = LL^{\mathsf T} with LL lower-triangular. Take A=LA = L. Cheap to compute (O(d3/3)O(d^3/3)) and what most software does.
  2. Eigenvalue (spectral) decomposition — next.

4.5.3. Eigenvalue decomposition

Definitions. For a d×dd \times d matrix Σ\Sigma, if a constant λ\lambda and a non-zero vector vv satisfy

Σv=λv,\Sigma v = \lambda v,

then λ\lambda is an eigenvalue of Σ\Sigma and vv a corresponding eigenvector. (Geometrically: Σ\Sigma merely stretches vv by the factor λ\lambda without turning it.)

Facts for a real symmetric matrix (spectral theorem):

  • It has dd linearly independent eigenvectors, which can be chosen orthogonal and of unit length: v1,…,vdv_1, \dots, v_d with viTvj=0v_i^{\mathsf T}v_j = 0 for i≠ji \ne j and ∥vi∥=1\|v_i\| = 1.
  • Put them side by side in P=[v1  v2  ⋯  vd]P = [v_1 \; v_2 \; \cdots \; v_d]. Orthonormal columns mean PTP=IP^{\mathsf T}P = I, i.e. P−1=PTP^{-1} = P^{\mathsf T} — the inverse is free.
  • With Λ=diag⁡(λ1,…,λd)\Lambda = \operatorname{diag}(\lambda_1, \dots, \lambda_d),

Σ=P Λ PT.\Sigma = P\,\Lambda\,P^{\mathsf T}.

  • Because Σ\Sigma is positive semidefinite, every λi≥0\lambda_i \ge 0 (λi=viTΣvi≥0\lambda_i = v_i^{\mathsf T}\Sigma v_i \ge 0), so Λ1/2=diag⁡(λ1,…,λd)\Lambda^{1/2} = \operatorname{diag}(\sqrt{\lambda_1}, \dots, \sqrt{\lambda_d}) is a real matrix with Λ1/2Λ1/2=Λ\Lambda^{1/2}\Lambda^{1/2} = \Lambda.

The square root. Take A=PΛ1/2A = P\Lambda^{1/2}. Then

AAT=PΛ1/2 (PΛ1/2)T=PΛ1/2Λ1/2PT=PΛPT=Σ.  ✓AA^{\mathsf T} = P\Lambda^{1/2}\,(P\Lambda^{1/2})^{\mathsf T} = P\Lambda^{1/2}\Lambda^{1/2}P^{\mathsf T} = P\Lambda P^{\mathsf T} = \Sigma. \; \checkmark

(We used (Λ1/2)T=Λ1/2(\Lambda^{1/2})^{\mathsf T} = \Lambda^{1/2} since it is diagonal.)

Verification, step by step. Let Z=(Z1,…,Zd)TZ = (Z_1, \dots, Z_d)^{\mathsf T} with ZiZ_i i.i.d. N(0,1)N(0,1) and define

X=μ+PΛ1/2Z.X = \mu + P\Lambda^{1/2}Z .

Mean: E[X]=μ+PΛ1/2 E[Z]=μ+0=μ\mathbf{E}[X] = \mu + P\Lambda^{1/2}\,\mathbf{E}[Z] = \mu + 0 = \mu.

Covariance:

cov⁡(X)=E[(X−μ)(X−μ)T]=E[PΛ1/2Z ZTΛ1/2PT](X−μ=PΛ1/2Z; (ABC)T=CTBTAT)=PΛ1/2 E[ZZT] Λ1/2PT(constants come out of the expectation)=PΛ1/2 I Λ1/2PT(E[ZiZj]=1 if i=j, 0 otherwise)=PΛPT=Σ.\begin{aligned} \operatorname{cov}(X) &= \mathbf{E}\big[(X-\mu)(X-\mu)^{\mathsf T}\big] \\ &= \mathbf{E}\big[P\Lambda^{1/2}Z\,Z^{\mathsf T}\Lambda^{1/2}P^{\mathsf T}\big] && (X-\mu = P\Lambda^{1/2}Z;\ (ABC)^{\mathsf T} = C^{\mathsf T}B^{\mathsf T}A^{\mathsf T}) \\ &= P\Lambda^{1/2}\,\mathbf{E}[ZZ^{\mathsf T}]\,\Lambda^{1/2}P^{\mathsf T} && (\text{constants come out of the expectation}) \\ &= P\Lambda^{1/2}\,I\,\Lambda^{1/2}P^{\mathsf T} && (\mathbf{E}[Z_iZ_j] = 1 \text{ if } i=j,\ 0 \text{ otherwise}) \\ &= P\Lambda P^{\mathsf T} = \Sigma . \end{aligned}

And XX is normal because each coordinate is a linear combination of the independent normals Z1,…,ZdZ_1, \dots, Z_d plus a constant.

Algorithm (multivariate normal via eigen decomposition).

Setup (once): compute the eigenvalues λi\lambda_i and orthonormal eigenvectors viv_i of Σ\Sigma; form PP and Λ1/2\Lambda^{1/2}; store A=PΛ1/2A = P\Lambda^{1/2}.

  1. Generate Z1,…,ZdZ_1, \dots, Z_d i.i.d. N(0,1)N(0,1) (Box–Muller or polar method, §4.3).
  2. Return X=μ+PΛ1/2ZX = \mu + P\Lambda^{1/2}Z.

One matrix–vector multiplication per vector; the expensive part (the decomposition) is paid once.

Example (d=2d = 2). Two correlated standard normals with correlation ρ\rho:

μ=(μ1μ2),Σ=(1ρρ1).\mu = \begin{pmatrix}\mu_1\\ \mu_2\end{pmatrix}, \qquad \Sigma = \begin{pmatrix} 1 & \rho \\ \rho & 1\end{pmatrix}.

Eigenvalues and eigenvectors (check by multiplying out):

Σ(11)=(1+ρ)(11),Σ(1−1)=(1−ρ)(1−1),\Sigma\begin{pmatrix}1\\1\end{pmatrix} = (1+\rho)\begin{pmatrix}1\\1\end{pmatrix}, \qquad \Sigma\begin{pmatrix}1\\-1\end{pmatrix} = (1-\rho)\begin{pmatrix}1\\-1\end{pmatrix},

so λ1=1+ρ\lambda_1 = 1+\rho, λ2=1−ρ\lambda_2 = 1-\rho (both ≥0\ge 0 since ∣ρ∣≤1|\rho| \le 1), and after normalizing to unit length,

P=12(111−1),Λ1/2=(1+ρ001−ρ),A=PΛ1/2=12(1+ρ1−ρ1+ρ−1−ρ).P = \frac{1}{\sqrt2}\begin{pmatrix} 1 & 1 \\ 1 & -1\end{pmatrix}, \qquad \Lambda^{1/2} = \begin{pmatrix}\sqrt{1+\rho} & 0 \\ 0 & \sqrt{1-\rho}\end{pmatrix}, \qquad A = P\Lambda^{1/2} = \frac{1}{\sqrt2}\begin{pmatrix} \sqrt{1+\rho} & \sqrt{1-\rho} \\ \sqrt{1+\rho} & -\sqrt{1-\rho}\end{pmatrix}.

The algorithm therefore returns

X1=μ1+1+ρ Z1+1−ρ Z22,X2=μ2+1+ρ Z1−1−ρ Z22.X_1 = \mu_1 + \frac{\sqrt{1+\rho}\,Z_1 + \sqrt{1-\rho}\,Z_2}{\sqrt2}, \qquad X_2 = \mu_2 + \frac{\sqrt{1+\rho}\,Z_1 - \sqrt{1-\rho}\,Z_2}{\sqrt2}.

Check: Var⁡(X1)=(1+ρ)+(1−ρ)2=1\operatorname{Var}(X_1) = \frac{(1+\rho) + (1-\rho)}{2} = 1, and cov⁡(X1,X2)=(1+ρ)−(1−ρ)2=ρ\operatorname{cov}(X_1, X_2) = \frac{(1+\rho) - (1-\rho)}{2} = \rho. ✓

The same Σ\Sigma by Cholesky. L=(10ρ1−ρ2)L = \begin{pmatrix} 1 & 0 \\ \rho & \sqrt{1-\rho^2}\end{pmatrix} satisfies LLT=ΣLL^{\mathsf T} = \Sigma, giving

X1=μ1+Z1,X2=μ2+ρZ1+1−ρ2 Z2.X_1 = \mu_1 + Z_1, \qquad X_2 = \mu_2 + \rho Z_1 + \sqrt{1-\rho^2}\,Z_2 .

Different formulas, same distribution — both are valid square roots of Σ\Sigma. (For general variances σ12,σ22\sigma_1^2, \sigma_2^2: X1=μ1+σ1Z1X_1 = \mu_1 + \sigma_1 Z_1, X2=μ2+σ2(ρZ1+1−ρ2 Z2)X_2 = \mu_2 + \sigma_2(\rho Z_1 + \sqrt{1-\rho^2}\,Z_2).) The Cholesky form shows the mechanism plainly: X2X_2 borrows a share ρ\rho of X1X_1’s noise and tops up with fresh noise so that its variance is still 1.

Remarks.

  • The ZiZ_i must be independent — this is where the quality of the normal generator (§4.3.1’s spiral warning) matters doubly.
  • The construction only controls the first two moments. For a non-normal vector with prescribed marginals and correlation, transforming ZZ by a matrix destroys the marginals; one then uses ZZ only to carry the dependence and maps each coordinate through Fi−1(Φ(⋅))F_i^{-1}(\Phi(\cdot)) (the “NORTA” idea). Beyond the scope of this course.

4.6. Generating Stochastic Processes

A stochastic process (§2.5) is a whole family of random variables indexed by time. Generating one means generating a sample path. The workhorse is the Poisson process — the arrival process of almost every queueing model — and its time-varying generalization.

4.6.1. The Poisson process

Counting process. Let SnS_n be the time of the nn-th event (the nn-th arrival time), with S0=0S_0 = 0, and let

Xn=Sn−Sn−1X_n = S_n - S_{n-1}

be the nn-th interarrival time, so Sn=∑i=1nXiS_n = \sum_{i=1}^n X_i. Define

N(t)=max⁡{n:Sn≤t}=number of events that have occurred up to time t.N(t) = \max\{n : S_n \le t\} = \text{number of events that have occurred up to time } t .

{N(t):t≥0}\{N(t) : t \ge 0\} is a counting process: it starts at 00, is integer-valued, non-decreasing, and jumps by 11 at each SnS_n.

01234 N(t) S₀S₁S₂S₃S₄X₁X₂X₃X₄tN(t) = 2 (S₂ ≤ t < S₃) time

Definition. If the interarrival times X1,X2,…X_1, X_2, \dots are i.i.d. Exp(λ)\text{Exp}(\lambda), then {N(t)}\{N(t)\} is called a Poisson process with rate λ\lambda, written PP(λ)\text{PP}(\lambda).

Properties of PP(λ)\text{PP}(\lambda).

  1. Poisson counts. For every tt,

    P(N(t)=k)=e−λt(λt)kk!,k=0,1,2,…,P(N(t) = k) = e^{-\lambda t}\frac{(\lambda t)^k}{k!}, \qquad k = 0, 1, 2, \dots,

    i.e. N(t)∼Poisson(λt)N(t) \sim \text{Poisson}(\lambda t), so E[N(t)]=λt\mathbf{E}[N(t)] = \lambda t. Hence λ=E[N(t)]/t\lambda = \mathbf{E}[N(t)]/t: the rate (or arrival rate) is the expected number of events per unit time. More generally the number of events in any interval of length ss is Poisson(λs)\text{Poisson}(\lambda s), and counts in disjoint intervals are independent. (This is the Erlang formula of §4.2.3 read the other way: P(N(t)≥n)=P(Sn≤t)P(N(t) \ge n) = P(S_n \le t).)

  2. Arrival-time theorem. Given that N(t)=kN(t) = k, the kk arrival times (S1,…,Sk)(S_1, \dots, S_k) are distributed as the order statistics of kk i.i.d. U(0,t)U(0, t) random variables. That is: take U1,…,UkU_1, \dots, U_k i.i.d. U(0,t)U(0,t), sort them into ascending order Uˉ(1)<Uˉ(2)<⋯<Uˉ(k)\bar U_{(1)} < \bar U_{(2)} < \cdots < \bar U_{(k)}; then (S1,…,Sk)(S_1, \dots, S_k) has the same joint distribution as (Uˉ(1),…,Uˉ(k))(\bar U_{(1)}, \dots, \bar U_{(k)}). In words: given how many events occurred, they are scattered uniformly and independently over the interval — the Poisson process has no preferred times.

Bernoulli splitting. Let {N(t)}\{N(t)\} be PP(λ)\text{PP}(\lambda) and fix probabilities p1,…,pr>0p_1, \dots, p_r > 0 with ∑j=1rpj=1\sum_{j=1}^r p_j = 1. Assign each arrival, independently of everything else, to category ii with probability pip_i, and let Ni(t)N_i(t) count the category-ii arrivals, so N(t)=N1(t)+⋯+Nr(t)N(t) = N_1(t) + \cdots + N_r(t).

Theorem. Under Bernoulli splitting the rr processes {N1(t)},…,{Nr(t)}\{N_1(t)\}, \dots, \{N_r(t)\} are independent Poisson processes, with {Ni(t)}∼PP(λpi)\{N_i(t)\} \sim \text{PP}(\lambda p_i).

The case r=2r = 2, with probabilities pp and 1−p1-p, is the one we will use: the arrivals that pass a coin toss form PP(λp)\text{PP}(\lambda p), those that fail form PP(λ(1−p))\text{PP}(\lambda(1-p)), and the two streams are independent of each other. (The independence is the surprising part: knowing many arrivals went to stream 1 tells you nothing about stream 2.)

4.6.2. The nonhomogeneous Poisson process

Motivation: traffic on a highway. A PP(λ)\text{PP}(\lambda) has one constant rate for all time. Real arrival rates vary:

04am8amnoon5pm10pm λ(t) = arrival rate of cars morning rush evening rush a single constant λ cannot describe this ⇒ nonhomogeneous Poisson process

A single λ\lambda would average the rush hours and the quiet hours together and get both wrong. We need a process whose rate is a function of time.

Definition. A counting process {N(t)}\{N(t)\} is a nonhomogeneous Poisson process (NPP) with rate function λ(t)≥0\lambda(t) \ge 0 if

  1. N(0)=0N(0) = 0;
  2. {N(t)}\{N(t)\} has independent increments: counts in disjoint time intervals are independent;
  3. in a short window (t,t+h](t, t+h],

    P(N(t+h)=k∣N(t)=k)=1−λ(t)h+o(h)(no event)P(N(t+h)=k+1∣N(t)=k)=λ(t)h+o(h)(exactly one event)P(N(t+h)=k+j∣N(t)=k)=o(h),j≥2(two or more events)\begin{aligned} P\big(N(t+h) = k \mid N(t) = k\big) &= 1 - \lambda(t)h + o(h) && \text{(no event)} \\ P\big(N(t+h) = k+1 \mid N(t) = k\big) &= \lambda(t)h + o(h) && \text{(exactly one event)} \\ P\big(N(t+h) = k+j \mid N(t) = k\big) &= o(h), \quad j \ge 2 && \text{(two or more events)} \end{aligned}

    Here o(h)o(h) means a quantity that vanishes faster than hh as h→0h \to 0. In words: over a very short interval almost surely either 00 or 11 event happens, and the chance of 11 event is proportional to the length of the interval with proportionality constant λ(t)\lambda(t) — the current value of the rate.

Counts. Define the mean-value function m(t)=∫0tλ(s) dsm(t) = \int_0^t \lambda(s)\,ds. Then

P(N(t)=k)=e−m(t)m(t)kk!,k=0,1,2,…,P(N(t) = k) = e^{-m(t)}\frac{m(t)^k}{k!}, \qquad k = 0, 1, 2, \dots,

so N(t)∼Poisson(m(t))N(t) \sim \text{Poisson}\big(m(t)\big) and E[N(t)]=∫0tλ(s) ds\mathbf{E}[N(t)] = \int_0^t \lambda(s)\,ds — the area under the rate curve. More generally N(t+s)−N(t)∼Poisson(∫tt+sλ(u) du)N(t+s) - N(t) \sim \text{Poisson}\big(\int_t^{t+s}\lambda(u)\,du\big). With a constant rate λ(t)≡λ\lambda(t) \equiv \lambda we get m(t)=λtm(t) = \lambda t and recover PP(λ)\text{PP}(\lambda): the NPP is the generalization.

Nonhomogeneous Bernoulli splitting. Now let the coin be biased by time: fix a function p(t):[0,∞)→[0,1]p(t) : [0, \infty) \to [0,1] and assign an arrival occurring at time tt to stream 1 with probability p(t)p(t), to stream 2 with probability 1−p(t)1 - p(t).

Theorem. If {N(t)}∼PP(λ)\{N(t)\} \sim \text{PP}(\lambda) is split with time-dependent probability p(t)p(t), then {N1(t)}\{N_1(t)\} and {N2(t)}\{N_2(t)\} are independent nonhomogeneous Poisson processes with rate functions λ p(t)\lambda\,p(t) and λ (1−p(t))\lambda\,(1 - p(t)):

P(N1(t)=k)=exp⁡ ⁣(−λ ⁣∫0tp(s) ds)[λ∫0tp(s) ds]kk!,P(N2(t)=k)=exp⁡ ⁣(−λ ⁣∫0t(1−p(s)) ds)[λ∫0t(1−p(s)) ds]kk!.P(N_1(t) = k) = \exp\!\Big(-\lambda\!\int_0^t p(s)\,ds\Big)\frac{\big[\lambda\int_0^t p(s)\,ds\big]^k}{k!}, \qquad P(N_2(t) = k) = \exp\!\Big(-\lambda\!\int_0^t (1-p(s))\,ds\Big)\frac{\big[\lambda\int_0^t (1-p(s))\,ds\big]^k}{k!}.

(The same holds if the parent process is itself an NPP with rate λ(t)\lambda(t): the pieces are NPPs with rates λ(t)p(t)\lambda(t)p(t) and λ(t)(1−p(t))\lambda(t)(1-p(t)).) Thinning out a Poisson stream with a time-varying coin produces exactly an NPP — this is the key to generating one.

4.6.3. Generating a Poisson process on [0,T][0, T]

Approach 1: lay down the interarrival times. Since the gaps are i.i.d. Exp(λ)\text{Exp}(\lambda), generate them one at a time by inverse transform and accumulate. Set s0=0s_0 = 0, i=0i = 0.

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Set si+1=si−1λln⁡us_{i+1} = s_i - \dfrac{1}{\lambda}\ln u \quad(previous arrival plus an Exp(λ)\text{Exp}(\lambda) gap).
  3. Set i=i+1i = i + 1.
  4. If si≤Ts_i \le T, go back to step 1; otherwise stop. The arrival times are s1,…,si−1s_1, \dots, s_{i-1} and N(T)=i−1N(T) = i - 1.
T −ln u/λ−ln u/λ−ln u/λ−ln u/λ−ln u/λs₀s₁s₂s₃s₄s₅ > T: discard, stop gaps laid down one at a time; N(T) = number of sᵢ before T (here 4)

The last generated time, the one that overshoots TT, is discarded; it only serves to tell us we are done. This is the natural method inside a discrete-event simulation, where the next arrival is scheduled as soon as the current one occurs.

Approach 2: use the arrival-time theorem. Decide the count first, then place the points.

  1. Generate N(T)∼Poisson(λT)N(T) \sim \text{Poisson}(\lambda T) (a discrete variate — inverse transform with the p.m.f. computed recursively, p(k+1)=p(k)⋅λT/(k+1)p(k+1) = p(k)\cdot\lambda T/(k+1)).
  2. Generate u1,…,uN(T)u_1, \dots, u_{N(T)} i.i.d. U(0,T)U(0, T).
  3. Sort them; return uˉ(1)<uˉ(2)<⋯<uˉ(N(T))\bar u_{(1)} < \bar u_{(2)} < \cdots < \bar u_{(N(T))} as the arrival times s1,…,sN(T)s_1, \dots, s_{N(T)}.
0 0 T T s₁s₂s₃s₄s₅ steps 1–2: draw N(T) = 5 from Poisson(λT), then 5 i.i.d. U(0,T) points step 3: sort — the sorted points are the arrival times s₁ < ⋯ < s₅

By property 2 the output has exactly the distribution of a PP(λ)\text{PP}(\lambda) path on [0,T][0,T]. This approach generates the whole path at once (convenient for vectorized code) at the cost of a sort.

4.6.4. Generating a nonhomogeneous Poisson process

A tempting but wrong method. Mimic Approach 1 with the current rate: having generated ti−1t_{i-1}, draw the next gap from Exp(λ(ti−1))\text{Exp}(\lambda(t_{i-1})),

ti=ti−1−1λ(ti−1)ln⁡u.t_i = t_{i-1} - \frac{1}{\lambda(t_{i-1})}\ln u .

This uses the rate at the previous arrival for the entire gap, as if the rate stayed frozen until the next event. It does not: the rate may rise steeply right after ti−1t_{i-1}.

λ(t) tᵢ₋₁ λ(tᵢ₋₁) small tᵢ dashed arc: the gap is Exp(λ(tᵢ₋₁)) with mean 1/λ(tᵢ₋₁) — huge — so the rush hour is skipped

If λ(ti−1)\lambda(t_{i-1}) happens to be small, the gap has mean 1/λ(ti−1)1/\lambda(t_{i-1}), which is large, and the process can jump clean over a high-rate period in which many arrivals should have occurred. In a test with a rate function that dips to 0.250.25 and then peaks at 3.253.25, this method produced on average 3.93.9 arrivals on [0,10][0,10] where the true mean is 7.37.3, and only 1.51.5 arrivals in the rush-hour window where there should be 4.94.9. So this is not a correct way.

The correct way: the thinning method. Generate too many candidate arrivals from a homogeneous Poisson process whose rate is at least as large as λ(t)\lambda(t) everywhere, then keep each candidate at time tt with probability λ(t)/λ∗\lambda(t)/\lambda^*. Let

λ∗=max⁡0≤t≤Tλ(t).\lambda^* = \max_{0 \le t \le T}\lambda(t).

Algorithm (thinning), to generate tit_i given ti−1t_{i-1}:

  1. Set t=ti−1t = t_{i-1}.
  2. Generate u1⊥u2∼U(0,1)u_1 \perp u_2 \sim U(0,1).
  3. Set t=t−1λ∗ln⁡u1t = t - \dfrac{1}{\lambda^*}\ln u_1 \quad(advance by an Exp(λ∗)\text{Exp}(\lambda^*) gap: the next candidate).
  4. If u2≤λ(t)λ∗u_2 \le \dfrac{\lambda(t)}{\lambda^*}, accept: set ti=tt_i = t. Otherwise go back to step 2 and try again (keeping the advanced tt).

Repeat until t>Tt > T.

λ* λ(t) candidates from PP(λ*): | accepted (prob. λ(t)/λ*) ○ rejected many candidates survive under the peak, few where λ(t) is small

How to understand the algorithm. It is nonhomogeneous Bernoulli splitting run deliberately. The candidate times produced by steps 2–3 form a homogeneous PP(λ∗)\text{PP}(\lambda^*) — that is just Approach 1 with rate λ∗\lambda^*. Step 4 then assigns each candidate at time tt to one of two streams with a time-dependent coin:

N1(t)=number of candidates accepted by time t,N2(t)=number rejected,p(t)=λ(t)λ∗.N_1(t) = \text{number of candidates accepted by time } t, \qquad N_2(t) = \text{number rejected}, \qquad p(t) = \frac{\lambda(t)}{\lambda^*}.

By the splitting theorem, {N1(t)}\{N_1(t)\} is a nonhomogeneous Poisson process with rate function

λ∗⋅p(t)=λ∗⋅λ(t)λ∗=λ(t),\lambda^*\cdot p(t) = \lambda^*\cdot\frac{\lambda(t)}{\lambda^*} = \lambda(t),

exactly the target. (The rejected stream is an NPP with rate λ∗−λ(t)\lambda^* - \lambda(t), independent of the accepted one — we simply throw it away.) Note that p(t)≤1p(t) \le 1 precisely because λ∗\lambda^* was chosen as the maximum of λ\lambda; that is the only role λ∗\lambda^* plays. The analogy with acceptance–rejection (§4.2.4) is exact: λ∗\lambda^* is a flat majorizing function for λ(t)\lambda(t), and λ(t)/λ∗\lambda(t)/\lambda^* is the acceptance probability.

Checks. In the same test as above, thinning gave 7.297.29 arrivals on average against the true 7.327.32, and 4.894.89 in the rush-hour window against 4.884.88.

Efficiency. The expected fraction of candidates accepted is

∫0Tλ(t) dtλ∗T=area under λarea of the rectangle,\frac{\int_0^T \lambda(t)\,dt}{\lambda^* T} = \frac{\text{area under } \lambda}{\text{area of the rectangle}},

the same picture as the AR efficiency 1/c1/c. If λ(t)\lambda(t) has a sharp peak, λ∗\lambda^* is large and most candidates are rejected during the quiet periods. The standard fix is the AR fix: use a piecewise constant λ∗\lambda^* — split [0,T][0,T] into subintervals, each with its own local maximum — so the majorizing rectangle hugs the curve.

4.7. Example - generating the inputs of the inventory system

The inventory model of §1.3 needs three kinds of random input. Each one is generated from U(0,1)U(0,1) random numbers with a method of this chapter.

input distribution method formula
time between demands Exp\text{Exp} with mean 0.10.1 month inverse transform (§4.2.1) X=−0.1ln⁡uX = -0.1\ln u
demand size D∈{1,2,3,4}D \in \{1,2,3,4\} w.p. 16,13,13,16\frac16, \frac13, \frac13, \frac16 discrete inverse transform (§4.2.1) compare uu with 16,12,56\frac16, \frac12, \frac56
order lead time U(0.5,1)U(0.5, 1) inverse transform (§4.3) L=0.5+0.5 uL = 0.5 + 0.5\,u

4.7.1. Time between demands

The mean is 1/λ=0.11/\lambda = 0.1 month, so λ=10\lambda = 10 per month and F(x)=1−e−10xF(x) = 1 - e^{-10x}, x≥0x \ge 0. Set u=F(x)u = F(x) and solve:

u=1−e−10x  ⟹  e−10x=1−u  ⟹  x=−0.1ln⁡(1−u).u = 1 - e^{-10x} \;\Longrightarrow\; e^{-10x} = 1 - u \;\Longrightarrow\; x = -0.1\ln(1-u).

Since 1−u∼U(0,1)1 - u \sim U(0,1) as well:

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return X=−0.1ln⁡uX = -0.1\ln u.

(If the RNG can return u=0u = 0, use −0.1ln⁡(1−u)-0.1\ln(1-u) instead; see §4.2.1.)

4.7.2. Demand size

The c.d.f. is a staircase:

dd 1 2 3 4
p(d)p(d) 1/61/6 1/31/3 1/31/3 1/61/6
F(d)F(d) 1/61/6 1/21/2 5/65/6 11

Discrete inverse transform: return the smallest dd with u≤F(d)u \le F(d).

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. If u≤1/6u \le 1/6, return D=1D = 1; else if u≤1/2u \le 1/2, return D=2D = 2; else if u≤5/6u \le 5/6, return D=3D = 3; else return D=4D = 4.

The cut points 1/6,1/2,5/61/6, 1/2, 5/6 split (0,1](0,1] into four intervals whose widths are the probabilities, and uu falls into exactly one of them:

01/61/25/61D = 1width 1/6D = 2width 1/3D = 3width 1/3D = 4width 1/6u = 0.55 lands in (1/2, 5/6] ⇒ D = 3

Alternative: table lookup (§4.4.1). All the probabilities are multiples of 1/61/6, so store

m=[1,2,2,3,3,4]m = [1, 2, 2, 3, 3, 4]

(value dd appears 6 p(d)6\,p(d) times), generate J=1+⌊6u⌋J = 1 + \lfloor 6u \rfloor, and return D=mJD = m_J. Check: P(D=2)=P(J∈{2,3})=2/6=1/3P(D = 2) = P(J \in \{2, 3\}) = 2/6 = 1/3. Because mm is sorted, this returns the same DD as the search for every uu (up to the boundary points), just without any comparisons.

4.7.3. Order lead time

For U(0.5,1)U(0.5, 1), F(x)=x−0.50.5F(x) = \dfrac{x - 0.5}{0.5} on [0.5,1][0.5, 1]. Set u=F(x)u = F(x):

u=x−0.50.5  ⟹  x=0.5+0.5 u,u = \frac{x - 0.5}{0.5} \;\Longrightarrow\; x = 0.5 + 0.5\,u ,

which is the formula a+(b−a)ua + (b - a)u of §4.3.

  1. Generate u∼U(0,1)u \sim U(0,1).
  2. Return L=0.5+0.5 uL = 0.5 + 0.5\,u.

4.7.4. Worked example

Suppose the generator gives the following random numbers:

input uu variate
time to demand 1 0.81 −0.1ln⁡0.81=0.021-0.1\ln 0.81 = 0.021 month
size of demand 1 0.55 12<0.55≤56⇒D=3\tfrac12 < 0.55 \le \tfrac56 \Rightarrow D = 3
time to demand 2 0.17 −0.1ln⁡0.17=0.177-0.1\ln 0.17 = 0.177 month
size of demand 2 0.12 0.12≤16⇒D=10.12 \le \tfrac16 \Rightarrow D = 1
lead time 0.30 0.5+0.5⋅0.30=0.650.5 + 0.5 \cdot 0.30 = 0.65 month

Starting from I(0)=60I(0) = 60: the first demand comes at t=0.021t = 0.021 and takes 3 items (I=57I = 57); the second comes at t=0.021+0.177=0.198t = 0.021 + 0.177 = 0.198 and takes 1 item (I=56I = 56). If an order is placed at the review at t=1t = 1, with this lead time it arrives at t=1.65t = 1.65.

4.7.5. When each input is generated during the simulation

  • Demand at time tt: generate the size DD and set I←I−DI \leftarrow I - D; generate the next interdemand time XX and schedule the next demand at t+Xt + X.
  • Inventory evaluation (beginning of each month): if I<sI < s, order Z=S−IZ = S - I, generate the lead time LL, and schedule the order arrival at t+Lt + L. If I≥sI \ge s, nothing is generated.
  • Order arrival and end of simulation: no random input.
  • At t=0t = 0, generate the first interdemand time to schedule the first demand.

4.7.6. Use a separate stream for each input

Following §3.3 (practical issue 3), take interdemand times, demand sizes and lead times from three different streams. The reason is concrete here: how many lead times are consumed depends on the policy (s,S)(s, S), since a policy that orders more often uses more of them. With one shared stream, those extra draws would shift every later demand, and two policies would face different demand sequences. With separate streams, every (s,S)(s, S) pair sees exactly the same demands (common random numbers, §4.2.1 advantage 4), so the difference in average cost reflects the policies rather than luck.


4. Generating Random Variates
http://example.com/2026/09/08/2026-09-08-random-variate-generation/
Author
Wind_like
Posted on
September 8, 2026
Licensed under