Signal Box — the domain
We're going to use as an example a common, real-world, life-or-death situation: train switching systems.
Our world is a passing loop on a single-track railway — the arrangement that lets two trains travelling in opposite directions get past each other. This is what it looks like when everything is working:
These are the failure states a real interlocking exists to prevent:
There's a fourth family, green into occupied track (a signal clearing a train toward a segment that already has one on it), and a zeroth: states so malformed they don't describe a railway at all. Throughout the site, the verdicts are colour-coded:
Simplifications, so the whole state space stays countable on one page: two trains, four track segments, one safety rule-set (the oracle), and — since strings are infinite — wherever a field is a String we audit a small bounded slice of it: five plausible aspect spellings, six plausible positions. Everything else is exhaustive.
-- v0 state
type State =
{ sa :: String
, sl :: String
, se :: String
, sm :: String
, p1 :: Boolean
, p2 :: Boolean
, t1 :: String
, t2 :: String
}
The two obvious problems here are:
true here means what? "towards the loop"?But what does it mean in practice? Let's generate the counter-examples:
There are a LOT of ways this can go wrong! Many, many states that would result in disaster, derailment and death in the real world if they occurred. Of the 90,000 values in our bounded slice, 88,400 don't even describe a railway, and another 1,398 describe one in the process of having an accident. The 202 states we actually mean are outnumbered roughly 450 to 1 — and remember, the slice is a courtesy; the real space is infinite.
On the next page we'll start refining this.