Proof, Models and Mathematics
A short history of formal methods, from Turing's checked routine to Lean 4, read against the limits of verification

Table of Contents

Overview

corrected · claim-validator · 2026-11-13

Formal methods is three histories that share a vocabulary: proving that a program meets its specification, checking a model of a system against a property, and writing mathematics so that a machine can check every step. Each began with a paper that still reads well, each became practical decades later, and each is still bounded by the same results about what computation can decide.

This note dates the main steps in each strand and cites the source for each, then sets them against those bounds. The bounds come first; this note reads each strand as a way of living within them.

The site's working notes on the tools mentioned here: Alloy, TLA+ in a build pipeline, Lean 4 on FreeBSD, a Lean parity proof, Dafny and Clojure and the tools of Logic for Programmers.

The limits

corrected · citation-auditor · 2026-11-13

Ron Pressler's 2016 essay, "Why Writing Correct Software Is Hard", collects the results that bound every method below (Pressler 2016). Its argument, briefly: the difficulty of correct software is in the foundations of computation, not in poor tools.

  • Undecidability. Gödel's incompleteness theorems (Gödel 1931) end the hope of a complete, provably consistent foundation; Turing's halting result (Turing 1936) ends the hope of a general procedure for deciding whether a program terminates. Rice's theorem extends this to every non-trivial semantic property of programs (Rice 1953).
  • Complexity. Even where a question is decidable, it can be intractable. A proof system with short proofs of every tautology exists if and only if NP = coNP (Cook and Reckhow 1979). Model checking is linear in the size of the state space, with a factor linear in the formula for CTL and exponential in it for LTL; the trouble is the state space, which even a small program makes huge, and symbolic model checking is PSPACE-complete.
  • No free decomposition. Pressler cites Demri, Laroussinie and Schnoebelen (2005): verifying a system of k components is probably not fixed-parameter tractable in k, so splitting it into modules does not, in general, make verification cheaper.

His conclusion is that correctness comes at a significant cost, and that what helps is empirical study of real programs and partial techniques: local properties, heuristics, approximations. One study he cites found that 92% of catastrophic failures in distributed data systems came from mishandled non-fatal errors, and that in 58% simple tests of the error-handling code would have exposed the fault (Yuan et al. 2014).

This note reads each strand below as a different way of paying that cost: with human effort (proof), by limiting what is checked (models), or by working only in mathematics, where the statements are fixed and the proofs are worth the labour.

Proving programs

verified · citation-auditor · 2026-11-13
year step source
1949 Turing's "Checking a Large Routine": a program annotated with assertions about its state, and an argument that it terminates (Turing 1949)
1967 Floyd: assertions attached to the edges of a flowchart give a program its meaning, and verification conditions follow from them (Floyd 1967)
1969 Hoare: the triple, written P {Q} R in the paper (now {P} Q {R}), and an axiomatic system for reasoning about programs (Hoare 1969)
1975 Dijkstra: guarded commands and the weakest precondition, which turn verification into a calculus for deriving programs (Dijkstra 1975)
1979 Edinburgh LCF: a theorem prover whose theorems can be built only by a small kernel of inference rules, an abstract type in ML (Gordon, Milner, and Wadsworth 1979)
1988 The Calculus of Constructions, the type theory Coq first implemented, later extended with inductive types (Coq history) (Coquand and Huet 1988)
2009 CompCert: a C compiler proved in Coq to preserve the meaning of the programs it compiles (Leroy 2009)
2009 seL4: an operating-system microkernel with a machine-checked proof that its C implementation refines its specification (Klein et al. 2009)

LCF's idea lasted: whatever automation searches for a proof, only a small kernel can produce a theorem, so the trust rests on a small piece of code. HOL and Isabelle keep LCF's abstract type; Coq and Lean reach the same end differently, by rechecking proof terms, the de Bruijn criterion (Paulson on the two designs).

Checking models

verified · citation-auditor · 2026-11-13
year step source
1977 Pnueli: temporal logic as a language for the properties of programs that run forever (Pnueli 1977)
1981 Clarke and Emerson: branching-time temporal logic checked mechanically against a finite model (Clarke and Emerson 1982)
1982 Queille and Sifakis, independently: model checking in the CESAR system (Queille and Sifakis 1982)
1994 Lamport: the Temporal Logic of Actions, the basis of TLA+ (Lamport 1994)
2002 Jackson: Alloy, a lightweight relational modelling language checked within bounds (Jackson 2002)
2015 Amazon Web Services reports using TLA+ on production designs and finding serious bugs before release (Newcombe et al. 2015)

Model checking pays the cost by checking a model rather than the program, and a bounded or finite one. Alloy makes the bound explicit (a scope); TLC explores the reachable states of a TLA+ specification. What it gives in exchange is automation: no proof to write, and a counterexample when the property fails.

Formalising mathematics

corrected · citation-auditor · 2026-11-13
year step source
1968 de Bruijn's Automath: a language in which mathematics can be written and its proofs checked by machine (de Bruijn 1970)
1973 Mizar begins under Andrzej Trybulec, at Płock and from 1976 at Białystok; its Mizar Mathematical Library collects formalised definitions and theorems (Grabowski, Korniłowicz, and Naumowicz 2010)
2005 Gonthier: the Four Colour Theorem formalised in Coq (Gonthier 2008)
2014 Flyspeck: a formal proof of the Kepler conjecture, in HOL Light and Isabelle (Hales and others 2017)
2015 The Lean theorem prover, from Microsoft Research (de Moura et al. 2015)
2020 mathlib, Lean's community library of mathematics (The mathlib Community 2020)
2021 Lean 4, a theorem prover that is also a programming language, its system largely written in Lean (de Moura and Ullrich 2021)
2021 The Liquid Tensor Experiment: the key step (Theorem 9.4) of a central theorem of Clausen and Scholze's condensed mathematics checked in Lean (Scholze, June 2021) (Castelvecchi 2021)

The site's Lean notes run Lean 4 and mathlib on FreeBSD and check one small proof against its generated code: Lean 4 on FreeBSD 15 and the parity proof.

The limits, again

corrected · claim-validator · 2026-11-13

None of the three strands escapes the results in the limits. On this note's reading, each chooses where to pay.

  • Proof pays with human effort. The kernel checks every step, but a person (or a search) has to find the steps, and the specification has to be the right one. CompCert and seL4 are the evidence that the cost can be paid for systems that matter.
  • Model checking pays by checking less: a model rather than the code, within a bound, with the state space as the constraint. It finds bugs in designs cheaply and proves nothing outside its bound.
  • Formalised mathematics pays where the statement is fixed and the proof is worth more than the labour.

Testing sits outside all three and pays in its own currency: it runs the program, so it sees only the runs it makes. The lab notes on this site measure that directly, with reach counts and planted faults: Harness first.

Bruijn, N. G. de. 1970. “The Mathematical Language AUTOMATH, Its Usage, and Some of Its Extensions.” In Symposium on Automatic Demonstration, 125:29–61. Lecture Notes in Mathematics. Springer. https://doi.org/10.1007/BFb0060623.
Castelvecchi, Davide. 2021. “Mathematicians Welcome Computer-Assisted Proof in `Grand Unification’ Theory.” Nature 595 (7865): 18–19. https://doi.org/10.1038/d41586-021-01627-2.
Clarke, Edmund M., and E. Allen Emerson. 1982. “Design and Synthesis of Synchronization Skeletons Using Branching Time Temporal Logic.” In Logics of Programs, edited by Dexter Kozen, 131:52–71. Lecture Notes in Computer Science. Springer. https://doi.org/10.1007/BFb0025774.
Cook, Stephen A., and Robert A. Reckhow. 1979. “The Relative Efficiency of Propositional Proof Systems.” Journal of Symbolic Logic 44 (1): 36–50. https://doi.org/10.2307/2273702.
Coquand, Thierry, and Gérard Huet. 1988. “The Calculus of Constructions.” Information and Computation 76 (2--3): 95–120. https://doi.org/10.1016/0890-5401(88)90005-3.
Dijkstra, Edsger W. 1975. “Guarded Commands, Nondeterminacy and Formal Derivation of Programs.” Communications of the Acm 18 (8): 453–57. https://doi.org/10.1145/360933.360975.
Floyd, Robert W. 1967. “Assigning Meanings to Programs.” In Mathematical Aspects of Computer Science, 19:19–32. Proceedings of Symposia in Applied Mathematics. American Mathematical Society. https://doi.org/10.1090/psapm/019/0235771.
Gonthier, Georges. 2008. “Formal Proof–-the Four-Color Theorem.” Notices of the American Mathematical Society 55 (11): 1382–93.
Gordon, Michael J., Robin Milner, and Christopher P. Wadsworth. 1979. Edinburgh LCF: A Mechanised Logic of Computation. Vol. 78. Lecture Notes in Computer Science. Springer. https://doi.org/10.1007/3-540-09724-4.
Grabowski, Adam, Artur Korniłowicz, and Adam Naumowicz. 2010. “Mizar in a Nutshell.” Journal of Formalized Reasoning 3 (2): 153–245. https://doi.org/10.6092/issn.1972-5787/1980.
Gödel, Kurt. 1931. “Über Formal Unentscheidbare Sätze Der Principia Mathematica Und Verwandter Systeme I.” Monatshefte Für Mathematik Und Physik 38: 173–98. https://doi.org/10.1007/BF01700692.
Hales, Thomas, and others. 2017. “A Formal Proof of the Kepler Conjecture.” Forum of Mathematics, Pi 5: e2. https://doi.org/10.1017/fmp.2017.1.
Hoare, C. A. R. 1969. “An Axiomatic Basis for Computer Programming.” Communications of the Acm 12 (10): 576–80. https://doi.org/10.1145/363235.363259.
Jackson, Daniel. 2002. “Alloy: A Lightweight Object Modelling Notation.” Acm Transactions on Software Engineering and Methodology 11 (2): 256–90. https://doi.org/10.1145/505145.505149.
Klein, Gerwin, Kevin Elphinstone, Gernot Heiser, June Andronick, David Cock, Philip Derrin, Dhammika Elkaduwe, et al. 2009. “seL4: Formal Verification of an OS Kernel.” In Proceedings of the 22nd Acm Symposium on Operating Systems Principles (Sosp), 207–20. https://doi.org/10.1145/1629575.1629596.
Lamport, Leslie. 1994. “The Temporal Logic of Actions.” Acm Transactions on Programming Languages and Systems 16 (3): 872–923. https://doi.org/10.1145/177492.177726.
Leroy, Xavier. 2009. “Formal Verification of a Realistic Compiler.” Communications of the Acm 52 (7): 107–15. https://doi.org/10.1145/1538788.1538814.
Moura, Leonardo de, Soonho Kong, Jeremy Avigad, Floris van Doorn, and Jakob von Raumer. 2015. “The Lean Theorem Prover (System Description).” In Automated Deduction – Cade-25, 9195:378–88. Lecture Notes in Computer Science. Springer. https://doi.org/10.1007/978-3-319-21401-6_26.
Moura, Leonardo de, and Sebastian Ullrich. 2021. “The Lean 4 Theorem Prover and Programming Language.” In Automated Deduction – Cade 28, 12699:625–35. Lecture Notes in Computer Science. Springer. https://doi.org/10.1007/978-3-030-79876-5_37.
Newcombe, Chris, Tim Rath, Fan Zhang, Bogdan Munteanu, Marc Brooker, and Michael Deardeuff. 2015. “How Amazon Web Services Uses Formal Methods.” Communications of the Acm 58 (4): 66–73. https://doi.org/10.1145/2699417.
Pnueli, Amir. 1977. “The Temporal Logic of Programs.” In 18Th Annual Symposium on Foundations of Computer Science (Focs), 46–57. https://doi.org/10.1109/SFCS.1977.32.
Pressler, Ron. 2016. “Why Writing Correct Software Is Hard.” https://pron.github.io/posts/correctness-and-complexity.
Queille, Jean-Pierre, and Joseph Sifakis. 1982. “Specification and Verification of Concurrent Systems in CESAR.” In International Symposium on Programming, 137:337–51. Lecture Notes in Computer Science. Springer. https://doi.org/10.1007/3-540-11494-7_22.
Rice, H. Gordon. 1953. “Classes of Recursively Enumerable Sets and Their Decision Problems.” Transactions of the American Mathematical Society 74 (2): 358–66. https://doi.org/10.1090/S0002-9947-1953-0053041-6.
The mathlib Community. 2020. “The Lean Mathematical Library.” In Proceedings of the 9th Acm Sigplan International Conference on Certified Programs and Proofs (Cpp), 367–81. https://doi.org/10.1145/3372885.3373824.
Turing, Alan M. 1936. “On Computable Numbers, with an Application to the Entscheidungsproblem.” Proceedings of the London Mathematical Society s2-42 (1): 230–65. https://doi.org/10.1112/plms/s2-42.1.230.
———. 1949. “Checking a Large Routine.” In Report of a Conference on High Speed Automatic Calculating Machines, 67–69. University Mathematical Laboratory, Cambridge.
Yuan, Ding, Yu Luo, Xin Zhuang, Guilherme Renna Rodrigues, Xu Zhao, Yongle Zhang, Pranay U. Jain, and Michael Stumm. 2014. “Simple Testing Can Prevent Most Critical Failures: An Analysis of Production Failures in Distributed Data-Intensive Systems.” In 11Th Usenix Symposium on Operating Systems Design and Implementation (Osdi), 249–65. USENIX Association. https://www.usenix.org/conference/osdi14/technical-sessions/presentation/yuan.