Snapshot / Computational Thinking Repo ↗

Reliability: when does a system fail?

A machine is built from many parts, and it keeps working only while every part still works — the parts are in series, like links in a chain. Each part fails at some random time. So when does the whole machine fail? At the moment its first part gives out.

This is a question you answer by simulation: build thousands of virtual machines, fail their parts at random, and look at the distribution of when each machine died. Slide the number of parts up and watch a sobering fact emerge — more parts means the system fails sooner, because there are more ways for it to break. All live in WebAssembly.

begin
    using PlutoUI, WasmMakie
end

number of parts (in series) = 4

per-part failure rate = 10 ÷100

number of machines simulated = 3000

let
    # one flat loop over every part of every machine. Each part's lifetime is an
    # exponential random variable, t = -ln(u)/rate; a machine fails at its EARLIEST
    # part failure. Histogram those system failure times.
    rate = Float64(ratei) / 100.0
    nbins = 40
    hi = 6.0 / (rate * Float64(nparts))     # a few mean-lifetimes wide
    counts = Vector{Float64}(undef, nbins)
    for b in 1:nbins
        counts[b] = 0.0
    end
    s = 99173
    mn = hi * 1000.0      # earliest failure so far in the current machine
    c = 0
    grand = nsims * nparts
    for t in 1:grand
        s = (s * 16807) % 2147483647
        u = Float64(s) / 2147483647.0
        if u < 0.0000001
            u = 0.0000001
        end
        life = -log(u) / rate          # this part's lifetime
        if life < mn
            mn = life
        end
        c += 1
        if c == nparts                 # the whole machine has now been assembled
            frac = mn / hi
            b = Int64(floor(frac * Float64(nbins))) + 1
            if b < 1
                b = 1
            end
            if b > nbins
                b = nbins
            end
            counts[b] += 1.0
            mn = hi * 1000.0
            c = 0
        end
    end
    fig = Figure(size = (600, 340))
    ax = Axis(fig[1, 1])
    for b in 1:nbins
        center = hi * (Float64(b) - 0.5) / Float64(nbins)
        lines!(ax, [center, center], [0.0, counts[b]])    # a histogram bar
    end
    fig
end
rel_stats = let
    # compute the readout numbers in a SEPARATE bond-dependent cell (returns a tuple)
    # so the markdown below interpolates them live — values buried inside a markdown
    # cell's own `let` get baked to the slider defaults by the render-once splice.
    rate = Float64(ratei) / 100.0
    s = 99173
    mn = 1.0e18
    c = 0
    total = 0.0
    done = 0
    grand = nsims * nparts
    for t in 1:grand
        s = (s * 16807) % 2147483647
        u = Float64(s) / 2147483647.0
        if u < 0.0000001
            u = 0.0000001
        end
        life = -log(u) / rate
        if life < mn
            mn = life
        end
        c += 1
        if c == nparts
            total += mn
            done += 1
            mn = 1.0e18
            c = 0
        end
    end
    (floor((total / Float64(done)) * 100.0) / 100.0, floor((1.0 / rate) * 100.0) / 100.0)
end;

Average time to first failure: about 2.47 (in the same units), versus 10.0 for a single part on its own. With 4 parts in series the machine fails roughly 4x sooner – its failure rate is the SUM of the parts' rates. Redundancy fights this; series chains make it worse.

The lesson of series systems

There is a clean law hiding in the histogram: when independent parts each fail at a constant rate, a series system's failure rate is the sum of the parts' rates. Ten parts that each last 100 hours on average give a machine that lasts only about 10. This is why complex hardware is hard to keep running, and why engineers add redundancy — parallel backups, so the system survives until the last copy fails instead of the first.

More broadly, this is reliability engineering by Monte Carlo: when the math of combining many random lifetimes gets hairy, simulate it. The same approach prices insurance, plans spare parts, and stress-tests power grids.

Appendix

The MIT lecture uses Distributions.jl / StatsBase / Plots.jl. WebAssembly can't run those in the browser, so part lifetimes come from an inline Park-Miller generator via t = -ln(u)/rate (the exponential distribution) and the histogram is drawn with WasmMakie. The series-failure law is exactly the textbook result.