Feb 2026 – Jun 2026
AI · CSLast edited
Scenario-Based Compositional Statistical Model Checking for Safety Specifications
This project extends compositional statistical model checking for autonomous vehicles from Markovian to non-Markovian safety specifications, covering safety requirements for self-driving cars that the prior framework could not express. Published with UC Berkeley faculty at the International Conference on Runtime Verification 2026.
The core idea is to augment simulation states with DFA states that encode the temporal logic of the specification, then propagate the DFA distribution across primitive scenario traces. This makes it possible to verify safety properties that depend on the history of events (not just the current state) while preserving the compositional structure that keeps large-scale verification tractable.
By reusing simulation results across driving scenarios, the method runs up to 32.3× more test simulations in the same time budget and cuts estimation error from 0.275 to 0.014 in the hardest case. Evaluated on the MetaDrive driving simulator, with support from DARPA, NSF, Nissan, and California PATH.
Affiliation
UC Berkeley
Report
- International Conference on Runtime Verification 2026
Keywords
- Compositional Analysis
- Statistical Model Checking
- DFA
- Automata Theory
- Markov Chains
- Python
- VerifAI
- MetaDrive
- Scenic
Testing a self-driving car in every scenario without re-driving each one
To show an autonomous car merely matches the human fatality rate, a fleet of 100 cars would have to drive 275 million miles without a single fatality — about 12.5 years, around the clock. To show it is 20 % safer: 8.8 billion miles, roughly 400 years. So the field tests in simulation instead, across thousands of scenarios — each a specific arrangement of road, traffic, and events — and every scenario is run thousands of times.

The tool for turning those runs into a number you can trust is statistical model checking (SMC): treat the car as a black box, run it many times, and estimate the probability that it satisfies a safety property, with a confidence bound attached. This project makes SMC compositional — scenarios sharing structure share simulation work — and extends it to properties that depend on the history of a drive, not just its final state. It started as a class project in Berkeley’s EECS 219C (Formal Methods) and became a paper with Berkeley faculty at the International Conference on Runtime Verification (RV) 2026.


The redundancy monolithic SMC can’t see
Scenarios are rarely atomic. A realistic one is a composite built from a small vocabulary of primitives — a straight road, an intersection, a roundabout, a curve — glued end to end. The same primitives recur constantly, and every combination is a scenario the car should be checked against.

S, X, O, C), and a composite made by gluing them at their terminal states — exactly how a Scenic program writes it. The seams are where the interesting work happens.Monolithic SMC treats each composite as its own sealed problem: a fresh batch of long simulations per scenario–specification pair. Swap an intersection for a roundabout and everything is thrown away and redone, even though most of the drive is identical to one already simulated. On a corpus of overlapping composites, that waste compounds.

S → X), choose (pick a branch at random), and shuffle (random order). They mirror Scenic’s own composition clauses, so the decomposition is already in the source.How it works
The idea is to shift the cost onto the primitives: simulate each one once into a shared trace pool, and answer any composite by composing statistics instead of running new simulations. Two things make that non-trivial.
Carrying history across primitives. The interesting properties are about the sequence — “never four consecutive slow steps” — and cannot be decided from a final state alone, which is what broke the earlier Markovian estimator. The framework writes each specification as an automaton and carries a distribution over its states, μ, from one primitive to the next. Each primitive’s traces say how often they move the automaton from state q to q′; propagate μ through S, then X, then S, and the satisfaction probability is whatever mass never reached the violating state. A non-Markovian property becomes a chain of Markovian updates.

moving; each primitive redistributes it using that primitive’s own traces, and the mass that ends in violated is the failure probability.
Correcting the seams. When S and X are each simulated alone, the states S ends in do not match the states X was started from, so stitching their traces together gives a biased answer. The fix is self-normalized importance sampling: fit a Gaussian kernel density estimate to the boundary features (position, speed, heading) on each side, and reweight X’s traces by how likely their starting state is under S’s exit distribution. The propagation rule stays the same — one extra weight per trace.

Choice and shuffle fall out as algebra on the per-branch estimates: a choose is a mixture, a shuffle is the average over orderings, and both cost nothing on top of the shared pool.

Results
Built as a prototype inside VerifAI, Berkeley’s toolkit for analysing AI-based systems, with MetaDrive as simulator and Scenic as scenario language. The system under test is MetaDrive’s built-in expert policy — a placeholder, so the comparison measures the verifier, not the driver. Seven composites (five sequential, one choose, one shuffle) against four specifications — two safety (2-Stop, Tollgate), two co-safety (V-Shaped, Sustained) — for 28 pairs, under both a matched trace budget and a matched time budget.
Accuracy holds. At a matched trace budget — 1000 composite traces for the baseline versus 1000 per primitive reused everywhere — the compositional estimates track the monolithic ground truth across nearly all pairs.
| Composite | Monolithic ρ̂ | Compositional ρ̂ | Δ |
|---|---|---|---|
| S → X | 0.6750 | 0.7074 | +0.0324 |
| S → X → S | 0.6520 | 0.6898 | +0.0378 |
| S → O → C | 0.4310 | 0.4740 | +0.0430 |
| C → S → X → S | 0.5670 | 0.6206 | +0.0536 |
| C → X → S → X → C | 0.3820 | 0.3819 | −0.0001 |
| S → choose(C, X, O) | 0.9800 | 0.9584 | −0.0216 |
| S → shuffle(C, X, O) | 0.9150 | 0.8941 | −0.0209 |
S → shuffle(C, X, O) (Δ = +0.1162), where the mismatch between primitives’ initial-state distributions is largest — exactly the overlap the seam correction depends on.Efficiency is where it pays off. Given the same 15-minute wall-clock budget, the compositional method generates 14,871 primitive traces against 753 monolithic — 14.6× more on average, up to 32.3× — and converges closer to the reference: mean deviation 0.029 versus 0.039.

S → shuffle(C, X, O)⟩, the error is 0.014 against the baseline’s 0.275 — a gap the baseline cannot close even with four times the budget.
Why it works. A compute-matched ablation makes the mechanism explicit: give the compositional method the same total budget split across the four primitives, and the two methods tie (0.038 versus 0.039). Strip away the extra trace count and the advantage disappears — the win comes from one place, sample reuse.
What I took away
Less about model checking than about the shape of the redundancy. The moment a verification target is built from reusable parts, re-verifying the whole from scratch each time is the real waste. The engineering is in composing the pieces back together at the seams without letting the statistics drift — and the seams are where the method’s one weak spot lives too.