After a corner-case bug escapes, a team over-corrects: every random length is now 0, 1 or 15, because "bugs live at the boundaries". Their next regression hammers the boundaries thousands of times. It never sends a packet of length 7. When a bug turns up in the CRC of mid-length packets, the regression that was meant to be thorough has not sent a single packet that could reveal it.
How do you shape random stimulus toward corners without losing everything else?
Two obvious answers pull in opposite directions. Uniform random is fair to every value, so it reaches the middle quickly and the corners rarely, and corners need several rare values at once (lesson 4.5). Pure corner bias does the reverse: it reaches the corners constantly and never visits the middle. Bugs live in both places. The question is not uniform or biased but how much weight each region gets.
Mostly broad: most draws spread over the whole legal range, so every value is reached eventually.
Extra weight on boundaries: minimum, maximum, zero and full get far more than their uniform share, so corners built from several boundary values become reachable.
Corners multiply: raising one boundary value's probability by a factor k raises a corner needing it on four inputs by k⁴.
In SystemVerilog the mixture is one dist (fact V6):
// snippet: the mixed length distribution, as in lesson 4.10 (weights are percent)
constraint c_len { len dist {0 := 2, 1 := 10, [2:14] :/ 70, 15 := 18}; }The model compares three length distributions for DCRouter packets, with destination and priority uniform. Breadth is how many of the 128 header kinds are seen after N packets. The corner is lesson 4.5's: four inputs sending length 15 to the same output in one group, tried 100,000 times. Here uniform covers all 16 lengths, including 0.
"""Distributions and bias: reaching corners without losing breadth.
Three ways to choose a DCRouter packet length (destination and priority stay uniform):
uniform every length 0-15 equally likely
corners only the boundary lengths 0, 1 and 15, a third each (bias taken too far)
mixed 0: 2%, 1: 10%, 15: 18%, 2-14: 70% spread evenly (the distribution of lesson 4.10)
Breadth: the expected number of the 128 header kinds (4 dst x 2 prio x 16 len) seen after N
packets, the sum over kinds of 1 - (1 - p_kind)^N. Corner: the chance that, in 100,000
groups of four packets (one per input), all four go to the same output with length 15 at
least once (lesson 4.5's corner). A Monte Carlo run checks the mixed breadth at N = 500.
"""
import random
def mixed(l):
return {0: 0.02, 1: 0.10, 15: 0.18}.get(l, 0.70 / 13)
dists = {
"uniform": lambda l: 1 / 16,
"corners": lambda l: 1 / 3 if l in (0, 1, 15) else 0.0,
"mixed": mixed,
}
Ns = [100, 200, 500, 1000, 2000, 5000]
print("packets N: " + " ".join(f"{n:>6d}" for n in Ns) + " corner in 100k groups")
rows = {}
for name, pl in dists.items():
assert abs(sum(pl(l) for l in range(16)) - 1) < 1e-9
kinds = [pl(l) / 8 for l in range(16) for _ in range(8)]
rows[name] = [sum(1 - (1 - p) ** n for p in kinds) for n in Ns]
corner = 4 * (pl(15) / 4) ** 4
hit = 1 - (1 - corner) ** 100_000
print(f"{name:8s} kinds seen " + " ".join(f"{v:6.1f}" for v in rows[name]) + f" {hit:.3f}")
rng = random.Random(11)
lens = list(range(16))
w = [mixed(l) for l in lens]
runs, n = 400, 500
sim = sum(len({(rng.randrange(4), rng.randrange(2), rng.choices(lens, w)[0]) for _ in range(n)}) for _ in range(runs)) / runs
print(f"Monte Carlo, mixed, N = {n}: {sim:.1f} kinds seen (formula {rows['mixed'][2]:.1f})")
assert abs(sim - rows["mixed"][2]) < 1.5
assert max(rows["corners"]) <= 24.0 + 1e-9 and rows["mixed"][-1] > 127
print("PASS: corners-only never sees more than 24 of 128 kinds; mixed sees all 128 by 5,000 packets and hits the corner far more often than uniform")It prints:
packets N: 100 200 500 1000 2000 5000 corner in 100k groups
uniform kinds seen 69.6 101.3 125.5 127.9 128.0 128.0 0.024
corners kinds seen 23.7 24.0 24.0 24.0 24.0 24.0 1.000
mixed kinds seen 65.7 95.5 122.1 127.2 127.9 128.0 0.806
Monte Carlo, mixed, N = 500: 122.1 kinds seen (formula 122.1)
PASS: corners-only never sees more than 24 of 128 kinds; mixed sees all 128 by 5,000 packets and hits the corner far more often than uniformHow to read it: corners-only hits the four-way corner with certainty but can never see more than 24 of the 128 header kinds, because lengths 2 to 14 never occur. Uniform sees every kind fastest but has only a 2.4% chance of the corner in 100,000 groups. The mixture is a little slower to full breadth (127.2 against 127.9 kinds at 1,000 packets) and has an 81% chance of the corner: most of both benefits. The Monte Carlo line checks the breadth formula.
Guideline | Reason |
|---|---|
Keep most of the weight broad (60 to 80% is common) | Middle values must still appear often enough to reach every kind |
Put boundary weight on values that start corners (0, 1, max, full) | Corners are products of boundary values |
Different tests can use different mixes | A corner-hunting test and a breadth test complement each other |
Let coverage decide | Weights are a guess; coverage shows what they actually reached (Part 6) |
Practice | Purpose |
|---|---|
Default distributions with boundary weight in the base class | Every test gets corner pressure without asking |
Test-specific overrides | Stress tests push harder on boundaries; soak tests stay broad |
Weights tuned from coverage results | Spend probability where bins are still empty |
The opening story is the corners-only row of the model: a regression that hits its chosen corners every run and has never sent a mid-length packet. The opposite failure is just as common and quieter: a uniform regression that runs for months without hitting a four-way corner it would reach in one night with boundary weight.
Only lengths 0, 1 and 15 occur: 4 destinations × 2 priorities × 3 lengths = 24 kinds.
(0.18 × 16)⁴ ≈ 2.88⁴ ≈ 69 times more likely per group.
Uniform random gives breadth but rarely corners; corner-only bias gives corners but loses breadth.
A mixture (mostly broad, extra weight on boundary values) gets most of both.
Corners multiply boundary probabilities, so modest bias has a large effect; let coverage tune the weights.