Machine Logic is Lawrence Paulson's blog on Isabelle/HOL and related topics.
https://lawrencecpaulson.github.io/
The End (?) of the ALEXANDRIA Project<p>Today marks the final day of the <a href="https://www.cl.cam.ac.uk/~lp15/Grants/Alexandria/">ALEXANDRIA</a> project.
I outlined a brief history of the project
<a href="/2023/04/27/ALEXANDRIA_outcomes.html">not long ago</a>.
It is nevertheless right to take a moment to thank
the European Research Council
<a href="https://cordis.europa.eu/project/id/742178">for funding it</a>
and to state, yet again, what the outcomes were.
Six years on, what have we learned?</p>
<h3 id="how-it-started">How it started</h3>
<p>A milestone for the start of the project is the <a href="https://www.newton.ac.uk/event/bpr/"><em>Big Proof</em> programme</a>,
organised by the Newton Institute in Cambridge. Its theme mentioned two then recent
and widely-admired achievements:</p>
<blockquote>
<p>Interactive proof assistants have been used to check complicated mathematical proofs such as those for the Kepler’s conjecture and the Feit-Thompson odd order theorem.</p>
</blockquote>
<p>It then refers to</p>
<blockquote>
<p>the challenges of bringing proof technology into mainstream mathematical practice</p>
</blockquote>
<p>and it lists specifically</p>
<ol>
<li>Novel pragmatic foundations for representing mathematical knowledge and vernacular inspired by set theory, category theory, and type theory.</li>
<li>Large-scale formal mathematical libraries that capture background knowledge spanning a range of domains</li>
</ol>
<p>A proposal for a programme
devoted entirely to <a href="https://homotopytypetheory.org">homotopy type theory</a> (HoTT)
had been rejected, but people from that community were invited to <em>Big Proof</em>.
Dependent type theory, whether HoTT or the already established type theory of Coq,
was widely assumed to be the future of the formalisation of mathematics.
I felt very lucky to get funding for a project involving simple type theory
and <a href="https://isabelle.in.tum.de">Isabelle/HOL</a>.</p>
<p>During the programme, prior formalisation efforts were criticised as lacking sophistication.
As Kevin Buzzard pointedly noted,
researchers had formalised long proofs about simple objects, but no one had formalised
<em>even the definitions</em> of more complicated objects used every day,
such as Grothendieck schemes.
Much existing work formalised 19th-century mathematics.</p>
<p>These complaints would have to be tackled.</p>
<h3 id="how-it-went">How it went</h3>
<p>I chronicled the project in my <a href="/2023/04/27/ALEXANDRIA_outcomes.html">previous post</a>.
Briefly: we formalised heaps of mathematics.
We also did groundbreaking work on applications of information retrieval and machine learning
to formalisation.
A longer and more formal account can be found <a href="https://arxiv.org/abs/2305.14407">on arXiv</a>.</p>
<h3 id="how-it-ended-formalisation-of-mathematics">How it ended (formalisation of mathematics)</h3>
<p>The sheer amount of new formalised material is impressive (and the quality is also high):</p>
<ul>
<li>formalisations of advanced mathematics, including the first ever on topics such as additive combinatorics, combinatorial block designs and ordinal partition theory</li>
<li>showing that dependent types aren’t necessary to have sophisticated objects like Grothendieck schemes or ω-categories</li>
<li>tens of thousands of lines of more basic but necessary library material, e.g. on metric and topological spaces (imported from HOL Light)</li>
<li>we formalised advanced work from some of the leading mathematicians of the age: Erdős, Gowers, Roth, Szemerédi</li>
</ul>
<p>We developed some highly fruitful techniques:</p>
<ul>
<li><a href="https://rdcu.be/dkoEr">locales</a> work exceptionally well for <a href="https://www.tandfonline.com/doi/full/10.1080/10586458.2022.2062073">structuring complicated hierarchies of definitions</a></li>
<li>“dependent” constructions can typically be formalised as families of (typed) sets</li>
</ul>
<p>We arrived at some surprising conclusions:</p>
<ul>
<li>Formalising even advanced mathematics is largely a matter of perseverance.</li>
<li>Combining material from different branches of mathematics, say probability theory and graph theory or complex analysis and set theory, works fine.</li>
<li>Dependent types aren’t necessary and probably aren’t even advantageous. We aren’t the ones fighting our formalism.</li>
</ul>
<p>To be fair, <a href="https://xenaproject.wordpress.com/2020/12/05/liquid-tensor-experiment/">astonishing progress</a> has also been made by the <a href="https://leanprover.github.io">Lean</a> community.
They have been extremely active over the same period
and formalised <a href="https://leanprover-community.github.io">mountains of material</a>.</p>
<p><strong>We can safely conclude that proof assistants already offer value to mathematicians.</strong>
Although full formalisation is still not really affordable,
neither is it necessary.
You can forego proving the results that you feel confident about,
focusing your formalisation efforts on the problematical parts.</p>
<h3 id="how-it-ended-ai-techniques">How it ended (AI techniques)</h3>
<p>The proposal included a lot of speculative ideas about search
and auto completion, in particular by somehow mining
the existing libraries for “proof idioms”.
Writing the proposal in 2016, I had no idea how such things could be done.
I was lucky to attract people who were prepared to apply their specialised knowledge.
That’s how we got</p>
<ul>
<li>the <a href="https://behemoth.cl.cam.ac.uk/search/">SErAPIS search engine</a>, a one-of-a-kind tool to search the libraries even on the basis of abstract mathematical concepts</li>
<li>a tremendous amount of infrastructure to analyse the Isabelle libraries and extract information</li>
<li>a string of advanced papers on proof synthesis, auto-formalisation, an Isabelle parallel corpus and more</li>
</ul>
<p>These projects are still at the research stage, but show great promise!</p>
<h3 id="spreading-the-word">Spreading the word</h3>
<p>For more detail and links relating to everything described above,
you can visit the <a href="https://www.cl.cam.ac.uk/~lp15/Grants/Alexandria/">ALEXANDRIA</a> webpage
or read the <a href="https://arxiv.org/abs/2305.14407">project summary</a>.</p>
<p>The team has worked hard to share the knowledge we discovered. We have written</p>
<ul>
<li>13 journal articles, including half (3 out of 6) of a special issue of <em>Experimental Mathematics</em></li>
<li>15 articles in conference proceedings</li>
<li>2 refereed chapters in a <a href="https://link.springer.com/book/10.1007/978-3-030-15655-8"><em>Synthese Library</em> volume</a></li>
<li>33 formal proof developments accepted to Isabelle’s <a href="https://www.isa-afp.org"><em>Archive of Formal Proofs</em></a></li>
</ul>
<p>More are forthcoming.
In addition, we’ve worked on formalisation projects with about two dozen interns and students,
many of whom have gone on to do PhD research. We’ve given dozens of talks at variety of venues. We are open to collaboration to take our work forward.</p>
Thu, 31 Aug 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/08/31/ALEXANDRIA_finished.html
https://lawrencecpaulson.github.io//2023/08/31/ALEXANDRIA_finished.htmlPropositions as types: explained (and debunked)<p>The principle of <em>propositions as types</em> (a.k.a. <a href="https://en.wikipedia.org/wiki/Curry–Howard_correspondence">Curry-Howard isomorphism</a>),
is much discussed, but there’s a lot of confusion and misinformation.
For example, it is widely believed that propositions as types is the basis of most modern proof assistants;
even, that it is necessary for any computer implementation of logic.
In fact, propositions as types was found to be unworkable
as the basis for conducting actual proofs
the first time it was tried, in the earliest days of the AUTOMATH system.
All of the main proof assistants in use today maintain a clear distinction
between propositions and types.
The principle is nevertheless elegant, beautiful and theoretically fruitful.</p>
<h3 id="material-implication-versus-intuitionistic-truth">Material implication versus intuitionistic truth</h3>
<p>The most natural route to propositions as types runs through <em>material implication</em>.
“If it rained then the path will be muddy” sounds like a reasonable instance
of logical implication.
“If Caesar was a chain-smoker then mice kill cats” does not sound reasonable, and yet it is deemed to be true,
at least in classical logic, where $A\to B$ is simply an abbreviation for
$\neg A\lor B$.</p>
<p>Many people have thought that $A\to B$ should hold only if there is some sort
of connection between $A$ and $B$, and many different interpretations of $\to$ have been tried.
The most convincing interpretation comes from the intuitionists,
specifically, from Heyting’s
<a href="https://plato.stanford.edu/entries/intuitionistic-logic-development/#ProoInte">conception of mathematical truth</a> itself:</p>
<blockquote>
<p>Here, then, is the Brouwerian assertion of $p$: It is known how to prove $p$. We will denote this by $\vdash p$. The words “to prove” must be taken in the sense of “to prove by construction”. … $\vdash \neg p$ will mean: “It is known how to reduce $p$ to a contradiction”.</p>
</blockquote>
<p>Propositions as types is already contained in this principle: we identify
each proposition with the set of the mathematical constructions that make it true.
The word <em>proof</em> is often used in place of <em>construction</em>,
but these constructions are not proofs in some formal calculus.</p>
<p>In the case of implication, we now have</p>
<ul>
<li>a construction of $A\to B$ is a function that effectively transforms a construction of $A$ into a construction of $B$</li>
</ul>
<p>This function surely is the sought-for connection between $A$ and $B$.</p>
<h3 id="prositions-as-types-in-action">Prositions as types in action</h3>
<p>We can codify the principle above by asserting a rule of inference that derives
\(\lambda x. b(x) : A\to B\)
provided $b(x):B$ for arbitrary $x:A$.
If we regard $A\to B$ as a type, then this is one of the typing rules
for the <a href="https://en.wikipedia.org/wiki/Simply_typed_lambda_calculus">λ-calculus</a>.
And if we regard $A\to B$ as a formula, then
(ignoring the constructions) this is the introduction rule for implication
in a standard system of <a href="https://plato.stanford.edu/entries/natural-deduction/">natural deduction</a>,
proving $A\to B$ provided that $B$ can be proved assuming $A$.</p>
<p>Setting aside natural deduction for the moment, we can codify
the intuitionistic idea of implication rather differently.
A simple proof system for intuitionistic propositional logic has just two axioms:</p>
<ul>
<li>axiom K: $\quad A\to(B\to A)$</li>
<li>axiom S: $\quad(A\to(B\to C))\to ((A\to B)\to(A\to C))$</li>
</ul>
<p>And it has one inference rule, <em>modus ponens</em>, which from $A\to B$ and $A$
infers $B$. Here is a proof of $A\to A$:</p>
\[\begin{align}
(A\to((D\to A)\to A))\to{} & \\
((A\to (D\to A))\to(A\to A)) & \quad\text{by S}\notag \\[1ex]
A\to((D\to A)\to A) & \quad\text{by K} \\
(A\to (D\to A))\to(A\to A) & \quad\text{by MP, (1), (2)} \\
A\to (D\to A) & \quad\text{by K} \\
A\to A & \quad\text{by MP, (3), (4)}
\end{align}\]
<p>As a proof system, it sucks. But the propositions as types principle holds: this is essentially the same as the <strong>S</strong>-<strong>K</strong> <a href="https://en.wikipedia.org/wiki/Combinatory_logic">system of combinators</a>.
Function application corresponds to modus ponens,
The combinators correspond to the axioms (which give their types),
and the derivation of the identity combinator
as <strong>SKK</strong> corresponds to the proof above (with $A\to A$ as the type of <strong>I</strong>). The system of combinators also sucks:
it can be used to translate any λ-calculus term into combinators, but the blowup is exponential (exactly as with the proof system).
These observations are Curry’s—except he thought combinators were rather good—and Howard would not come along for a couple of decades.</p>
<p>Note by the way that we have not used dependent types. They are only needed if we want to have quantifiers.
In a <a href="/2021/11/24/Intuitionism.html">prior post</a> I have described how other logical symbols are rendered as types, in the context of Martin-Löf type theory.
In particular, the type $(\Pi x:A) B(x)$ consists of functions $\lambda x. b(x)$ where $b(x):B(x)$ for all $x:A$. The function space $A\to B$ is the special case where $B$ does not depend on $x$.</p>
<p>We need further types, namely $(\Sigma x:A) B(x)$ and $A+B$,
to get the full intuitionistic predicate calculus.
AUTOMATH provided the $\Pi$ type alone,
and de Bruijn even <a href="https://pure.tue.nl/ws/files/4428179/597611.pdf">wrote a paper</a>
cautioning against building too much into the framework itself.</p>
<h3 id="automath-and-irrelevance-of-proofs">AUTOMATH and irrelevance of proofs</h3>
<p>AUTOMATH, which I have
<a href="/2021/11/03/AUTOMATH.html">written about earlier</a>,
is the first proof checker to actually implement propositions as types.
It did this in the literal sense of providing symbols TYPE and PROP,
which internally were synonymous—at first. However</p>
<blockquote>
<p>One of the forms of the logical double negation axiom, written by means of “prop”, turns into the axiom about Hilbert’s $\epsilon$-operator if we replace prop by type. So if we want to do classical logic and do not want to accept the axiom of choice, we need some distinction.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>
</blockquote>
<p>It’s not surprising that a primitive DN for double-negation,
mapping $\neg\neg A \to A$, would also map a proof that $A$
was nonempty into $A$ itself.
This is the contrapositive of <a href="https://doi.org/10.2307/2039868">Diaconescu’s result</a> that
the axiom of choice implies the excluded middle (and therefore DN).</p>
<p>De Bruijn mentions another solution to this problem: to declare a type of Booleans and to set up the entire system of predicate logic for this new type BOOL, rather than at the level of propositions.
It’s like how how predicate logic is
formalised <a href="/2022/07/13/Isabelle_influences.html">in Isabelle</a>:
separately from the logical framework.
This solution allows PROP and TYPE to be identified,
only then propositions actually have type BOOL.</p>
<p>A more compelling reason to distinguish PROP from TYPE
is <em>irrelevance of proofs</em>:</p>
<blockquote>
<p>If $x$ is a real number, then $P(x)$ stands for “proof of $x > 0$”. Now we define “$\log$” (the logarithm) in the context [x : real] [y : P(x)],and if we want to talk about $\log 3$ we have to write $\log(3,p)$, where $p$ is some proof for $3 > 0$. Now the $p$ is relevant, and we have some trouble in saying that $\log(3,p)$ does not depend on $p$. … Some time and some annoyance can be saved if we extend the language by proclaiming that proofs of one and the same proposition are always definitionally equal.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>
</blockquote>
<p>As de Bruijn and others comment, irrelevance of proofs is
mainly pertinent to classical reasoning. For constructivists, it
utterly destroys Heyting’s conception of intuitionistic truth.
But even proof assistants that are mostly used constructively, such as Agda and Coq, provide
<a href="https://agda.readthedocs.io/en/v2.6.3.20230805/language/prop.html">definitionally proof-irrelevant propositions</a>.</p>
<h3 id="intuitionistic-predicate-logic-continued">Intuitionistic predicate logic, continued</h3>
<p>Other logical connectives are easily represented by types.
First, the intuitionistic interpretation:</p>
<ul>
<li>a construction of $A\land B$ consists of a construction of $A$ paired with a construction of $B$</li>
<li>a construction of $\exists x. B(x)$ consists of a specific witnessing value $a$, paired with a construction of $B(a)$.</li>
<li>a construction of $A\lor B$ consists of a construction of $A$ or a construction of $B$ <em>along with an indication of which</em>. (So, we don’t have $A\lor\neg A$ when we don’t know which one holds.)</li>
</ul>
<p>The first two cases are handled by type $(\Sigma x:A) B(x)$,
which consists of pairs $\langle a,b \rangle$ where $a:A$ and $b:B(a)$, generalising the binary Cartesian product. The third case
is handled by type $A+B$, the binary disjoint sum.
The most faithful realisation of this scheme is
<a href="https://lawrencecpaulson.github.io/tag/Martin-Löf_type_theory">Martin-Löf type theory</a>.</p>
<p>As soon as we impose irrelevance of proofs, this beautiful scheme falls apart. The point of the intuitionist interpretation is to capture the structure of the constructions;
with irrelevance, all constructions are identical and even $A+B$ can have at most one element.</p>
<p>Proof assistants do not actually use propositions as types
for the same reason that functional programming languages do not
actually use the λ-calculus: because something that is beautiful in theory need not have any practical value whatever.
It is still possible to take inspiration from the theory.</p>
<h3 id="postscript">Postscript</h3>
<p>Two conclusions:</p>
<ol>
<li>You can have propositions as types without dependent types, but only for propositional logic.</li>
<li>You can have dependent types without propositions as types.</li>
</ol>
<p>And maybe a third: propositions as types can render type checking undecidable
unless you adopt a strict system of type uniqueness,
but then you can no longer infer $p(y)$ from $p(x)$ and $x=y$.
A decent notion of proposition ought to respect the substitution of equals for equals.</p>
<p>Phil Wadler has written a hagiographic but still useful
<a href="https://homepages.inf.ed.ac.uk/wadler/papers/propositions-as-types/propositions-as-types.pdf">article</a>
about the principle. See in particular the appendix
for its informative discussion with William Howard,
whose name is attached to the principle.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>NG de Bruijn, <a href="https://pure.tue.nl/ws/files/1892191/597622.pdf">A Survey of the Project Automath</a>, in: Seldin, J.P. and Hindley, J.R.,eds., To H.B. Curry: Esaays on Combinatory Logic, Lambda Calculus and Formalism (Academic Press, 1980), 152. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>Ibid, p. 159. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>
Wed, 23 Aug 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/08/23/Propositions_as_Types.html
https://lawrencecpaulson.github.io//2023/08/23/Propositions_as_Types.htmlWhen is a computer proof a proof?<p>In 1976, Appel and Haken caused delight mixed with consternation by proving
the celebrated four colour theorem, but with heavy reliance on a computer calculation.
An assembly language program was used to check 1936 “reducible configurations”;
people were rightly concerned about errors in the code.
However, the Appel–Haken proof also required “the investigation by hand
about ten thousand neighbourhoods of countries with positive charge”,<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>
much of which was done by Appel’s 13-year-old daughter,
and nobody seemed bothered about the possibility of errors there.
Computer algebra systems were emerging around that time and would eventually
become widely used in many branches of science and engineering,
although I can’t imagine a computer algebra calculation being uncritically accepted
by any mathematics journal.
Today, I and others hope to see mathematicians using proof assistants in their work.
Whether machine proofs will be accepted as valid requires serious thought
about the nature of mathematical proof.
We have come a long way since 1976, but many mathematicians still distrust computers,
and many struggle to agree on the computer’s precise role.</p>
<h3 id="the-idea-of-mathematical-certainty">The idea of mathematical certainty</h3>
<p>In a <a href="/2022/07/27/Truth_Models.html">previous post</a>, I’ve discussed the difference
between scientific knowledge, which sometimes needs to be revised
in the light of new evidence, as opposed to with mathematical truth,
which is not evidence-based. I also mentioned
the work of <a href="https://plato.stanford.edu/entries/lakatos/">Imre Lakatos</a>, a philosopher
who studied a particular theorem
(<a href="https://www.ams.org/publicoutreach/feature-column/fcarc-eulers-formula">Euler’s polyhedron formula</a>) for which counterexamples
were actually discovered. Lakatos’ discussion is largely focused on
strategies for dealing with counterexamples, e.g.</p>
<ul>
<li><em>monster-barring</em>: modifying your definition to exclude the counterexamples, regardless of how ad hoc it looks</li>
<li><em>exception-barring</em>: retreating to an overly conservative but completely safe definition</li>
</ul>
<p>And I have to remark, when you have one theorem and one definition that you are allowed to change at will, it looks like cheating. More commonly, errors are found in proofs (rather than in definitions) but can be fixed, with the theorem statement at worst marginally affected.</p>
<p>Perhaps we still have in mind a group of students watching Archimedes draw circles
in the sand and all agreeing that his proof is valid.
We don’t have that immediacy any more.
Today, doing mathematics necessarily requires trusting
tens of thousands of pages of other people’s work.
So, how about trusting some software?</p>
<h3 id="some-fundamental-desiderata-for-proofs">Some fundamental desiderata for proofs</h3>
<p>A <a href="https://www.degruyter.com/document/doi/10.1515/krt-2022-0015/html">recent paper</a><sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup>
discusses some widely accepted characteristics of mathematical proofs:</p>
<ol>
<li>Proofs are convincing.</li>
<li>Proofs are surveyable.</li>
<li>Proofs are formalisable.</li>
</ol>
<p>I like these because, ipso facto, any proof conducted using a proof assistant
is not merely formalisable but has literally just been formalised,
both in the sense of being expressed in some sort of high-level logical language
and in the sense of having been reduced to primitive logical inferences.
Not all formal proofs are surveyable but some certainly are,
with both Mizar and Isabelle/HOL’s Isar language specifically designed for legibility.
As for convincing: there can be no handwaving in a machine proof.
As a rule, machines are much harder to convince than a knowledgeable mathematician,
and machine proof contains not gaps but rather excessive detail.</p>
<p>Incidentally, and remarkably, the paper explains “convincing” as meaning
“convincing for mathematicians” and mere acceptance by the mathematical community
is sufficient (even if they cannot survey the proof itself).
It sounds a bit like “justification by faith”: all we need is for mathematicians to believe
in proof assistants!</p>
<p>In short, formal proofs, provided that they are written to be legible, easily satisfy
all three criteria. Unfortunately, the great majority of formal proofs are not legible.
But as I have shown by <a href="https://lawrencecpaulson.github.io/tag/examples">numerous examples</a>,
they can be.</p>
<h3 id="what-do-we-do-about-super-long-proofs">What do we do about super-long proofs?</h3>
<p>The Internet tells me that the millionth digit of Pi is 1, and I’m certain
there is no simple proof of that
(though similar claims would be trivial for rational numbers).
Similarly, <a href="https://en.wikipedia.org/wiki/Largest_known_prime_number">Wikipedia claims</a></p>
<blockquote>
<p>The largest known prime number (as of June 2023) is $2^{82,589,933} − 1$, a number which has 24,862,048 digits.</p>
</blockquote>
<p>To assert that this number is prime is essentially no different from asserting that
2 is prime, but the proof is rather longer.
It relies on the theory of Mersenne primes
and on an enormous computer calculation.
Any fact obtained by a calculation is a mathematical statement and it seems clear
that the vast majority of these do not have short proofs.
Fortunately, few of these claims have weighty implications, so it’s okay
if we can’t survey their proofs.</p>
<p>But not every fact obtained by a monster computation is mathematically trivial.</p>
<p>The <a href="https://www.cs.utexas.edu/~marijn/ptn/">largest ever proof</a>
is that of the Boolean Pythagorean Triples problem, which weighs in at 200 terabytes.
(Read the <a href="https://arxiv.org/abs/1605.00723">gory details</a>.)
This proof was generated by a SAT solver, a piece of software capable of
finding a model of a set of assertions written in Boolean logic,
or if no such model exists, proving that fact.
It is without doubt a mathematical proof, one that is overwhelmingly too large
for a human being to survey.
At most we can survey tiny but arbitrary parts of it,
which may be a means of establishing confidence in its correctness.</p>
<p>My favourite example though is the non-existence of a
<a href="/papers/Lam_finite_Proj_plane_order_10.pdf">projective plane of order 10</a>.
When I was an undergraduate at Caltech, Prof Herbert Ryser stressed the importance of
settling this question. What is strange is that such a plane could be represented
by an incidence matrix of zeros and ones, 111×111. A huge but finite search.
Such a search was carried out and the question settled negatively in 1989,
too late for Ryser, who had died in 1985.
The result has major implications for combinatorics despite the absence
of a surveyable proof.
It was <a href="https://arxiv.org/abs/2012.04715">confirmed recently</a> with the help of a SAT solver,
and therefore has been proved in logic, even though the proof is colossal.</p>
<p>People are legitimately uneasy about being wholly dependent on
a piece of software. This cannot be compared to astronomers using a powerful telescope
to observe stars far too faint for the human eye, because observational error
has always been an inherent part of all empirical science.
Mathematics is supposed to be different.
We have to take this proof at least somewhat on faith, and yet the theorem statement
cannot be dismissed as trivial.</p>
<p>It seems we are forced to be pragmatic and accept the amplification
of human reasoning by machine. This does not mean that mathematics has become empirical:
extensive numerical calculations suggest that the <a href="https://en.wikipedia.org/wiki/Riemann_hypothesis">Riemann hypothesis</a> is true,
but absolutely nobody accepts that as a proof.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>Robin Wilson, <em>Four Colours Suffice: How the Problem Was Solved</em> (Princeton, 2002) <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>Parshina, Katia. “Philosophical assumptions behind the rejection of computer-based proofs” <em>KRITERION – Journal of Philosophy</em>, 2023 <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>
Wed, 09 Aug 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/08/09/computer_proof.html
https://lawrencecpaulson.github.io//2023/08/09/computer_proof.htmlHao Wang on the formalisation of mathematics<p>Since I have already devoted a blog post to a
<a href="/2023/04/12/Wittgenstein.html">wildly overrated philosopher</a>
who barely understood logic, it’s time to pay tribute
to an underrated philosopher who wrote thoughtfully and presciently
on the formalisation of mathematics:
<a href="https://en.wikipedia.org/wiki/Hao_Wang_(academic)">Hao Wang</a>.
Wang must be seen primarily as a philosopher in the traditional sense,
who wrote essays and books, but he also wrote code.
He is the creator of the first truly powerful automatic theorem prover,
using what we now know as a <a href="https://en.wikipedia.org/wiki/Method_of_analytic_tableaux">tableau method</a>.
Indeed, most of today’s technology for automated deduction has its origins
in the work of philosophers — we can add <a href="https://en.wikipedia.org/wiki/Hilary_Putnam">Hilary Putnam</a> and <a href="https://en.wikipedia.org/wiki/John_Alan_Robinson">J Alan Robinson</a> –
who decided to write more than just words.</p>
<h3 id="wang-on-formalisation">Wang on formalisation</h3>
<p>Here is Hao Wang, writing in 1955 (!):<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>
<blockquote>
<p>We are led to believe that there is a fairly simple axiom system from which it is possible to derive almost all mathematical theorems and truths mechanically. This is at present merely a theoretical possibility, for no serious attempts seem to have been made to prove, for instance, all the theorems, of an elementary textbook of calculus.</p>
</blockquote>
<p>Of course, we are now well past that stage.</p>
<blockquote>
<p>Nevertheless, we seem to get a feeling of grandeur from the realization that a simple axiom system which we can quite easily memorize by heart embodies, in a sense, practically all the mathematical truths. It is not very hard to get to know the axiom system so well that people would say you understood the system.</p>
</blockquote>
<p>He was doubtless thinking of Zermelo Fraenkel set theory. Modern type theories are possibly a little too difficult for most people to memorise.</p>
<blockquote>
<p>Unfortunately just to be able thus to understand the system neither gives you very deep insight into the nature of mathematics nor makes you a very good mathematician.</p>
</blockquote>
<p>Very true. But we find ourselves asking again, how was he thinking about this back in 1955?
And his points are absolutely topical today. He considers what level of formality
is best for communication: an intuitive abstract, a more detailed exposition, and so on
leading ultimately to a formalisation in the style of Russell and Whitehead.
It’s clear that the increasing precision is not always beneficial!
But he continues</p>
<blockquote>
<p>To put thoughts on physics into mathematical symbols is one way of formalization. Through accumulation and tradition this way of formalization has also become a powerful way of communication: for those who understand the language, a short formula may express more precisely thought which could only be explained by many pages of ordinary words, and much less satisfactorily.</p>
</blockquote>
<p>The use of symbolism can be powerful and effective, but it needs to be done right.</p>
<p>Of course, he wrote much more. He described formalisation as a continuing process
dating back to Euclid, whose famous axiomatic system provided a common framework
for many schools of ancient Greek mathematics.
It continued with the 19th-century “arithmetisation of analysis”:</p>
<blockquote>
<p>There is the long story of how Lagrange, Cauchy, Weierstrass, and others strove to formalize exactly the basic notions of limits, continuity, derivatives, etc., providing thereby rigorous (though not necessarily reliable) foundations for mathematical analysis.</p>
</blockquote>
<p>And this continued into the 20th century with the origins of set theory, the paradoxes
and the promulgation of the seemingly consistent Zermelo-Fraenkel axioms.</p>
<p>Wang’s paper continues with insightful and relatively informal observations on many aspects
of formalisation and precision that are still relevant today.
He’s written a more technical paper:<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup>
covering similar themes, but which goes on to sketch an actual axiomatic framework
specifically designed for formalisation.</p>
<p>It begins in his usual lively style:</p>
<blockquote>
<p>Zest for both system and objectivity is the formal logician’s original sin. He pays for it by constant frustrations and by living ofttimes the life of an intellectual outcaste. The task of squeezing a large body of stubborn facts into a more or less rigid system can be a painful one, especially since the facts of mathematics are among the most stubborn of all facts. Moreover, the more general and abstract we get, the farther removed we are from the raw mathematical experience. As intuition ceases to operate effectively, we fall into many unexpected traps.</p>
</blockquote>
<p>And continues with remarks that are historically informed while at the same time intriguing:</p>
<blockquote>
<p>A field has often to be developed very thoroughly before it is ripe for a systematic and rigorous organization. The history of the calculus illustrates this point clearly: founded in the seventeenth century, rapidly expanded in the eighteenth, the calculus got acceptable foundations only in the nineteenth century and even today logicians generally have misgivings on the matter.</p>
</blockquote>
<p>This foundational development, Wang argues, also required a coherent treatment of set theory.
He notes how claims about “arbitrary curves” or “arbitrary functions” required elucidation.</p>
<blockquote>
<p>The problem is that of representing functions by trigonometric series which interested many a mathematician when Cantor began his research career around 1870. In trying to extend the uniqueness of representation to certain functions with infinitely many singular points, he was led to the notion of a derived set which not only marked the beginning of his study of the theory of point sets but led him later on to the construction of transfinite ordinal numbers.
Such historical facts ought to help combat the erroneous impression that Cantor invented, by one stroke of genius, a whole theory of sets which was entirely isolated from the main stream of mathematics at his time.</p>
</blockquote>
<p>The article goes on to discuss various aspects of Cantor’s set theory
and then start to speculate on how the formalisation of mathematics might be undertaken.
From today’s perspective, his focus looks excessively set-theoretic, with only hints
of a phenomenon that might have influenced today’s type theories:</p>
<blockquote>
<p>There are… numerous attempts to construct artificial systems which are both demonstrably consistent and also adequate to the development of the “ principal” (or “useful”) parts of mathematics. Most of these systems modify our basic logical principles such as the law of excluded middle and the principle of extensionality (for sets), and it is not easy to become familiar with them. So far as I know, none of these has been accepted widely.</p>
</blockquote>
<p>Wang then embarks on the development of a system he calls Σ, which he advocates as a basis
for formalising mathematics. He calls it “constructive” but this appears to be in the sense
of avoiding <a href="https://en.wikipedia.org/wiki/Impredicativity">impredicative definitions</a>
rather than banishing the law of excluded middle.
So it is a ramified type theory in the sense of Principia Mathematica.
I confess to having skipped the sequel at this point;
such a formalism is not attractive today.</p>
<p>Nevertheless, I am amazed at how Wang could see so far ahead, writing in the 1950s.
He wrote with fluency, clarity and wit, although his native language was Chinese.
Such a contrast with
<a href="/2023/04/12/Wittgenstein.html">that other person</a>,
whose gnomic writings on logic offer no insights and don’t appear to be informed
by any sort of reflection, knowledge, or even familiarity with the basic concepts of logic.</p>
<h3 id="wang-writing-actual-code">Wang writing actual code</h3>
<p>Wang appears to have been a true polymath, with his knowledge of the
history and philosophy of mathematics,
technical details of set theory (on which he has written at length)
while being at the same time a coder.
Programming an <a href="https://en.wikipedia.org/wiki/IBM_704">IBM 704</a> could not have been easy.
Fortran had been invented by 1960, but Wang does not mention it.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup>
He almost certainly wrote in assembly language.</p>
<p>Because I have mentioned this work in previous posts
(<a href="/2022/02/02/Formalising_Math_Set_theory.html">this one</a>
and <a href="/2023/01/11/AI_at_Stanford.html">that one</a>),
I will resist the temptation to repeat myself and instead refer you to
Martin Davis’s <a href="/papers/Early-History-of-ATP.pdf">chapter</a>
in the <em>Handbook of Automated Reasoning</em>
entitled “The Early History of Automated Deduction”, which is dedicated to Hao Wang.
There you will find many more technical details about Wang’s implementation of
Gentzen-style proof calculi and decision procedures for fragments of first-order logic.</p>
<p>In this post, I’ve only been able to touch on a few of Wang’s many contributions.
I can’t go into his discussions with Gödel and his communication of Gödel’s
philosophical views, for example. Fortunately, much can be found on-line and elsewhere.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>Hao Wang. <a href="https://www.jstor.org/stable/2251469">On Formalization</a>. <em>Mind</em> <strong>64</strong> (1955), 226–238 (also <a href="/papers/Wang-Formalisation.pdf">here</a>) <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>Hao Wang. <a href="https://doi.org/10.2307/2267732">The Formalization of Mathematics</a>. <em>Journal of Symbolic Logic</em> <strong>19</strong> (1954), 241–266 (also <a href="/papers/Wang-Orginal-Sin.pdf">here</a>) <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:3" role="doc-endnote">
<p>Hao Wang. <a href="https://doi.org/10.1147/rd.41.0002">Toward Mechanical Mathematics</a>. <em>IBM Journal of Research and Development</em> <strong>4</strong>:1 (1960), 15. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>
Wed, 26 Jul 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/07/26/Wang.html
https://lawrencecpaulson.github.io//2023/07/26/Wang.htmlPorting the HOL Light metric space library<p>I’m sorry that there have been no posts since April. I’ve been busy with a side project: porting the <a href="https://doi.org/10.1007/s10817-017-9412-x">HOL Light metric space library</a>
to Isabelle in time for the upcoming release. It was a big job: the chunk I grabbed initially comprised some 1335 lemmas, over 24K lines and nearly 1.2M bytes. Some of the lemmas turned out to have been ported previously, or otherwise turned out to be unnecessary; on the other hand, quite a few additional lemmas were needed. The material included metric spaces and many associated concepts, advanced material about toplogical spaces, the relationships among different kinds of spaces,
and finally closure properties, especially under general products.
Major contributions include Urysohn’s lemma and the <a href="https://en.wikipedia.org/wiki/Tietze_extension_theorem">Tietze extension theorem</a>,
the <a href="https://en.wikipedia.org/wiki/Baire_category_theorem">Baire Category Theorem</a>
and the Banach Fixed-Point Theorem.</p>
<h3 id="but-what-about-the-existing-typeclass-for-metric-spaces">But what about the existing typeclass for metric spaces?</h3>
<p>It’s worth recalling that Isabelle/HOL already includes a huge amount of material <a href="/2022/09/14/Libraries.html">ported from HOL Light</a>, a lot of it about metric spaces and including results bearing the names of Urysohn and Tietze. These relate to the metric space type class, which governs <strong>types</strong> that can be seen as metric spaces, including real norned vector spaces and Euclidean spaces, and in particular $\mathbb{R}^n$.
However, <a href="/2022/03/02/Type_classes.html">type classes</a> only work for types, and many interesting metric spaces cannot be expressed as types. By working more abstractly, we can work with metric spaces over arbitrary carrier sets.</p>
<h3 id="declaring-metric-spaces-as-a-locale">Declaring metric spaces as a locale</h3>
<p>The HOL Light version defines an abstract type of metric spaces, which is given as an argument to the numerous metric space operations.
This approach is flexible when we need to mix several metric space constructions. However, it’s clunky when working within a single metric space, which is so often done. The best way to handle that situation is through a <a href="/2022/03/23/Locales.html"><em>locale</em></a>:
a packaged context that can be re-entered at any time.
The metric space locale declares the carrier set (M) and the distance function (d).</p>
<pre class="source">
<span class="keyword1 command">locale</span> Metric_space <span class="main">=
</span><span class="keyword2 keyword">fixes</span> <span class="free">M</span> <span class="main">::</span> <span class="quoted"><span class="quoted"><span>"</span><span class="tfree">'a</span> set"</span></span> <span class="keyword2 keyword">and</span> <span class="free">d</span> <span class="main">::</span> <span class="quoted"><span class="quoted"><span>"</span><span class="tfree">'a</span> <span class="main">⇒</span> <span class="tfree">'a</span> <span class="main">⇒</span> real"</span>
</span><span class="keyword2 keyword">assumes</span> nonneg <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⋀</span><span class="bound">x</span> <span class="bound">y</span><span class="main">.</span> <span class="main">0</span></span> <span class="main">≤</span></span> <span class="free">d</span> <span class="bound">x</span> <span class="bound">y"
</span><span class="keyword2 keyword">assumes</span> commute<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⋀</span><span class="bound">x</span> <span class="bound">y</span><span class="main">.</span> <span class="free">d</span> <span class="bound">x</span> <span class="bound">y</span> <span class="main">=</span></span> <span class="free">d</span> <span class="bound">y</span> <span class="bound">x"</span>
</span><span class="keyword2 keyword">assumes</span> zero <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⋀</span><span class="bound">x</span> <span class="bound">y</span><span class="main">.</span> <span class="main">⟦</span><span class="bound">x</span> <span class="main">∈</span></span> <span class="free">M</span><span class="main">;</span> <span class="bound">y</span> <span class="main">∈</span></span> <span class="free">M</span><span class="main">⟧</span> <span class="main">⟹</span> <span class="free">d</span> <span class="bound">x</span> <span class="bound">y</span> <span class="main">=</span> <span class="main">0</span> <span class="main">⟷</span> <span class="bound">x</span><span class="main">=</span><span class="bound">y"
</span><span class="keyword2 keyword">assumes</span> triangle<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⋀</span><span class="bound">x</span> <span class="bound">y</span> <span class="bound">z</span><span class="main">.</span> <span class="main">⟦</span><span class="bound">x</span> <span class="main">∈</span></span> <span class="free">M</span><span class="main">;</span> <span class="bound">y</span> <span class="main">∈</span></span> <span class="free">M</span><span class="main">;</span> <span class="bound">z</span> <span class="main">∈</span> <span class="free">M</span><span class="main">⟧</span> <span class="main">⟹</span> <span class="free">d</span> <span class="bound">x</span> <span class="bound">z</span> <span class="main">≤</span> <span class="free">d</span> <span class="bound">x</span> <span class="bound">y</span> <span class="main">+</span> <span class="free">d</span> <span class="bound">y</span> <span class="bound">z"</span>
</pre>
<p>Working within the locale, declaring concepts such as open balls is straightforward.
We can treat <code class="language-plaintext highlighter-rouge">M</code> and <code class="language-plaintext highlighter-rouge">d</code> as constants, and their governing assumptions as axioms:</p>
<pre class="source">
<span class="keyword1 command">definition</span> <span class="entity">mball</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">mball</span> <span class="free bound entity">x</span> <span class="free bound entity">r</span> <span class="main">≡</span> <span class="main">{</span><span class="bound">y</span><span class="main">.</span> <span class="free bound entity">x</span> <span class="main">∈</span></span> <span class="free">M</span> <span class="main">∧</span></span> <span class="bound">y</span> <span class="main">∈</span> <span class="free">M</span> <span class="main">∧</span> <span class="free">d</span> <span class="free bound entity">x</span> <span class="bound">y</span> <span class="main"><</span> <span class="free bound entity">r</span>"
<span class="keyword1 command">lemma</span> centre_in_mball_iff <span class="main">[</span><span class="operator">iff</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">∈</span></span> mball</span> <span class="free">x</span> <span class="free">r</span> <span class="main">⟷</span> <span class="free">x</span> <span class="main">∈</span> <span class="free">M</span> <span class="main">∧</span> <span class="main">0</span> <span class="main"><</span> <span class="free">r"
</span><span class="keyword1 command">using</span> in_mball mdist_zero <span class="keyword1 command">by</span> <span class="operator">force</span>
<span class="keyword1 command">lemma</span> mball_subset_mspace<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>mball</span> <span class="free">x</span> <span class="free">r</span> <span class="main">⊆</span></span> <span class="free">M"
</span><span class="keyword1 command">by</span> <span class="operator">auto</span>
</pre>
<p>It also works for rather more sophisticated proofs, such as the uniqueness of fixed points of a contraction mapping.
The theorem statement is surprisingly natural, and the proof shown below
can be found (thanks to <a href="/2022/04/13/Sledgehammer.html">sledgehammer</a>)
by a single mouse click.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> <span class="main">(</span><span class="keyword2 keyword">in</span> Metric_space<span class="main">)</span> contraction_imp_unique_fixpoint<span class="main">:
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">f</span> <span class="free">x</span> <span class="main">=</span></span> <span class="free">x"</span></span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">f</span> <span class="free">y</span> <span class="main">=</span></span> <span class="free">y"</span>
</span><span class="keyword2 keyword">and</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">f</span> <span class="main">∈</span></span> <span class="free">M</span> <span class="main">→</span></span> <span class="free">M"
</span><span class="keyword2 keyword">and</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">k</span> <span class="main"><</span></span> <span class="main">1</span>"
</span><span class="keyword2 keyword">and</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⋀</span><span class="bound">x</span> <span class="bound">y</span><span class="main">.</span> <span class="main">⟦</span><span class="bound">x</span> <span class="main">∈</span></span> <span class="free">M</span><span class="main">;</span> <span class="bound">y</span> <span class="main">∈</span></span> <span class="free">M</span><span class="main">⟧</span> <span class="main">⟹</span> <span class="free">d</span> <span class="main">(</span><span class="free">f</span> <span class="bound">x</span><span class="main">)</span> <span class="main">(</span><span class="free">f</span> <span class="bound">y</span><span class="main">)</span> <span class="main">≤</span> <span class="free">k</span> <span class="main">*</span> <span class="free">d</span> <span class="bound">x</span> <span class="bound">y"
</span><span class="keyword2 keyword">and</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">∈</span></span> <span class="free">M"</span></span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">y</span> <span class="main">∈</span></span> <span class="free">M"</span>
</span><span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">=</span></span> <span class="free">y"</span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">smt</span> <span class="main main">(</span>verit<span class="main main">,</span> ccfv_SIG) mdist_pos_less mult_le_cancel_right1 assms<span class="main">)</span>
</pre>
<p>Locales nest naturally, as when we introduce the notion of a subspace of a metric space:</p>
<pre class="source">
<span class="keyword1 command">locale</span> Submetric <span class="main">=</span> Metric_space <span class="main">+
</span><span class="keyword2 keyword">fixes</span> <span class="free">A
</span><span class="keyword2 keyword">assumes</span> subset<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">A</span> <span class="main">⊆</span></span> <span class="free">M"</span>
</span><span class="keyword1 command">sublocale</span> Submetric <span class="main">⊆</span> sub<span class="main">:</span> Metric_space <span class="quoted free">A</span> <span class="quoted free">d
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> subset subspace<span class="main">)</span>
</pre>
<p>The declaration above state that every submetric can be viewed as a metric space in its own right.</p>
<h3 id="an-abstract-type-of-metric-spaces">An abstract type of metric spaces</h3>
<p>Although the locale-based approach is general – you work outside the locale merely by quoting the desired values of <code class="language-plaintext highlighter-rouge">M</code> and <code class="language-plaintext highlighter-rouge">d</code> every time – it can get tedious, especially when working with multiple metric spaces.
So it’s helpful to follow HOL Light in also declaring an <em>abstract type</em> of metric spaces.</p>
<pre class="source">
<span class="keyword1 command">typedef</span> <span class="tfree">'a</span> metric <span class="main">=</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">{</span><span class="main">(</span><span class="bound">M</span><span class="main">::</span><span class="tfree">'a</span> set</span><span class="main">,</span><span class="bound">d</span><span class="main">)</span><span class="main">.</span> Metric_space</span> <span class="bound">M</span> <span class="bound">d</span><span class="main">}"
</span><span class="keyword2 keyword">morphisms</span> <span class="quoted"><span>"</span>dest_metric"</span> <span class="quoted"><span>"</span>metric"
</span><span class="keyword1 command">proof</span> <span class="operator">-
</span><span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span>Metric_space</span> <span class="main">{}</span></span> <span class="main">(</span><span class="main">λ</span><span class="bound">x</span> <span class="bound">y</span><span class="main">.</span> <span class="main">0</span><span class="main">)"
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">auto</span> <span class="quasi_keyword">simp</span><span class="main main">:</span> Metric_space_def<span class="main">)
</span><span class="keyword1 command">then</span> <span class="keyword3 command">show</span> <span class="var quoted var">?thesis
</span><span class="keyword1 command">by</span> <span class="operator">blast
</span><span class="keyword1 command">qed
</span><span class="keyword1 command">definition</span> <span class="entity">mspace</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">mspace</span> <span class="free bound entity">m</span> <span class="main">≡</span> fst</span> <span class="main">(</span>dest_metric</span> <span class="free bound entity">m</span><span class="main">)"
</span><span class="keyword1 command">definition</span> <span class="entity">mdist</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">mdist</span> <span class="free bound entity">m</span> <span class="main">≡</span> snd</span> <span class="main">(</span>dest_metric</span> <span class="free bound entity">m</span><span class="main">)"</span>
</pre>
<p>We can prove a few results linking the two levels. It’s then easy
to switch back to the locale approach at any point in a proof,
starting with any available metric space.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> Metric_space_mspace_mdist <span class="main">[</span><span class="operator">iff</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>Metric_space</span> <span class="main">(</span>mspace</span> <span class="free">m</span><span class="main">)</span> <span class="main">(</span>mdist <span class="free">m</span><span class="main">)"
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> Product_Type.Collect_case_prodD dest_metric mdist_def mspace_def<span class="main">)
</span><span class="keyword1 command">lemma</span> <span class="main">(</span><span class="keyword2 keyword">in</span> Metric_space<span class="main">)</span> mspace_metric<span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:
</span><span class="quoted"><span class="quoted"><span>"</span>mspace</span> <span class="main">(</span>metric</span> <span class="main">(</span><span class="free">M</span><span class="main">,</span><span class="free">d</span><span class="main">)</span><span class="main">)</span> <span class="main">=</span> <span class="free">M"
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> mspace_def Metric_space_axioms metric_inverse<span class="main">)
</span><span class="keyword1 command">lemma</span> <span class="main">(</span><span class="keyword2 keyword">in</span> Metric_space<span class="main">)</span> mdist_metric<span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:
</span><span class="quoted"><span class="quoted"><span>"</span>mdist</span> <span class="main">(</span>metric</span> <span class="main">(</span><span class="free">M</span><span class="main">,</span><span class="free">d</span><span class="main">)</span><span class="main">)</span> <span class="main">=</span> <span class="free">d"
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> mdist_def Metric_space_axioms metric_inverse<span class="main">)</span>
</pre>
<p>Declaring a few of the most frequently used concepts (here, the associated topology) for the abstract type makes it even easier to work at the most appropriate level:</p>
<pre class="source">
<span class="keyword1 command">definition</span> <span class="entity">mtopology_of</span> <span class="main">::</span> <span class="quoted"><span class="quoted"><span>"</span><span class="tfree">'a</span> metric</span> <span class="main">⇒</span> <span class="tfree">'a</span> topology"
</span><span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">mtopology_of</span> <span class="main">≡</span> <span class="main">λ</span><span class="bound">m</span><span class="main">.</span> Metric_space.mtopology</span> <span class="main">(</span>mspace</span> <span class="bound">m</span><span class="main">)</span> <span class="main">(</span>mdist <span class="bound">m</span><span class="main">)"
</span><span class="keyword1 command">lemma</span> topspace_mtopology_of <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>topspace</span> <span class="main">(</span>mtopology_of</span> <span class="free">m</span><span class="main">)</span> <span class="main">=</span> mspace <span class="free">m"
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> Metric_space.topspace_mtopology Metric_space_mspace_mdist mtopology_of_def<span class="main">)</span>
</pre>
<p>I must confess, I was not always certain which way was best.
Fortunately, such decisions are not committal, and I frequently started by proving a theorem within the locale, from which the abstract type analogue could immediately be optained.</p>
<h3 id="interoperability-with-the-type-class-level">Interoperability with the type class level</h3>
<p>Having declared the <code class="language-plaintext highlighter-rouge">Metric_space</code> locale, my development immediately
interprets it using the type class version.
What’s going on not obvious; the clue is <code class="language-plaintext highlighter-rouge">dist</code>, which is the distance function for the
<code class="language-plaintext highlighter-rouge">metric_space</code> type class.
We’ve just established that anything involving the type class now applies as well to the more general locale framework.</p>
<pre class="source">
<span class="keyword1 command">interpretation</span> Met_TC<span class="main">:</span> Metric_space <span class="quoted">UNIV</span> <span class="quoted">dist
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> dist_commute dist_triangle Metric_space.intro<span class="main">)</span></pre>
<p>Now the equivalence between the type class and locale concepts is proved trivially:</p>
<pre class="source">
<span class="keyword1 command">lemma</span> mball_eq_ball <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>Met_TC.mball</span> <span class="main">=</span></span> ball<span>"
</span><span class="keyword1 command">by</span> <span class="operator">force
</span><span class="keyword1 command">lemma</span> mopen_eq_open <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>Met_TC.mopen</span> <span class="main">=</span></span> open<span>"
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">force</span> <span class="quasi_keyword">simp</span><span class="main main">:</span> open_contains_ball Met_TC.mopen_def<span class="main">)
</span><span class="keyword1 command">lemma</span> limitin_iff_tendsto <span class="main">[</span><span class="operator">iff</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>limitin</span> Met_TC.mtopology</span> <span class="free">σ</span> <span class="free">x</span> <span class="free">F</span> <span class="main">=</span> tendsto <span class="free">σ</span> <span class="free">x</span> <span class="free">F"
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> Met_TC.mtopology_def<span class="main">)
</span><span class="keyword1 command">lemma</span> mtopology_is_euclidean <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>Met_TC.mtopology</span> <span class="main">=</span></span> euclidean<span>"
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> Met_TC.mtopology_def<span class="main">)</span>
</pre>
<p>And so, simplification alone will drop us from the locale level to the type class level whenever this is possible: that is, whenever the carrier set is actually a type.</p>
<p>The role of type classes is a key difference between simply typed and dependent typed formalisms. Type classes play a bigger role in the latter (but with the risk of performance issues and the impossibility of multiple inheritance);
with the former, we may be stuck with having to duplicate some proofs.</p>
<h3 id="on-the-horrors-of-hol-light-proofs">On the horrors of HOL Light proofs</h3>
<p>I commented on the tribulations <a href="/2022/09/14/Libraries.html">last time</a>.
But seriously:</p>
<ul>
<li>Why would you use <code class="language-plaintext highlighter-rouge">x</code> as a Cauchy sequence and a real number in the same formula, just because you can?</li>
<li>Why would you generate an induction formula through an opaque series of transformations when you could simply type it in?</li>
<li>Why would you instantiate a lemma by applying syntactic functions to the current goal when you could simply type in the necessary terms?</li>
<li>Why unfold all definitions at once, turning your nice concise goal into a full page of formulas?</li>
</ul>
<p>Well, in HOL Light that’s how you roll.</p>
<p>A ubiquitous horror is <a href="https://www.cl.cam.ac.uk/~jrh13/hol-light/HTML/MP_TAC.html">MP_TAC</a>,
introduced by yours truly around 1984. It stuffs a given theorem $T$
into the current goal $G$ to create the implication $T\Longrightarrow G$.
Typically $T$ would have been produced from something else, by instantiation at least, and is about to undergo rewriting and other transformations.
(In HOL Light, as in its predecessors, the simplifier never alters a goal’s <em>assumptions</em>, which is why we want $T$ in the goal formula itself.)
Having simplified $T$ to say $T_1\land T_2$, the following tactic might move one of them to the assumptions (via <a href="https://www.cl.cam.ac.uk/~jrh13/hol-light/HTML/ASSUME_TAC.html">ASSUME_TAC</a>)
and put back the other, via another MP_TAC call, to work on some more.
It’s basically a stack machine computation, slowly massaging the goal into <code class="language-plaintext highlighter-rouge">T</code> (true).
Some of these proofs are grimly incomprehensible.
Then the next proof might consist of a pleasant string of <a href="https://www.cl.cam.ac.uk/~jrh13/hol-light/HTML/SUBGOAL_TAC.html">SUBGOAL_TAC</a> calls,
almost as nice as an Isabelle proof.</p>
<p>Sometimes I was able to port proofs just by eyeballing the HOL Light versions, but often I had to run them in a HOL Light session,
occasionally line by line.
Sledgehammer did most of the work, and half the time I had no idea what the actual argument was. Well, I don’t really need to know.</p>
Wed, 12 Jul 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/07/12/Metric_spaces.html
https://lawrencecpaulson.github.io//2023/07/12/Metric_spaces.htmlThe ALEXANDRIA Project: what has been accomplished?<p>One of the <a href="/2021/12/08/ALEXANDRIA.html">my first posts</a>
described <a href="https://www.cl.cam.ac.uk/~lp15/Grants/Alexandria/">ALEXANDRIA</a>,
my <a href="https://cordis.europa.eu/project/id/742178">ERC Advanced Grant</a> aiming to bring verification technology to professional mathematicians.
This project ends on 31 August 2023 (extended by a year on account of the pandemic),
so it’s surely time to update the community on what has been accomplished.
As outlined in the earlier post, our starting point was a growing acceptance
of the prevalence of errors in mathematics,
along with a small body of formal mathematical developments
that had been undertaken in a variety of proof assistants.
We would mainly be using <a href="https://isabelle.in.tum.de">Isabelle/HOL</a>, which had been
designed to be agnostic as to applications but strongly influenced
by the verification needs of computer scientists, not mathematicians.
There was a detailed <a href="https://www.cl.cam.ac.uk/%7Elp15/Grants/Alexandria/Part-B2.pdf">research proposal</a>, as is always required,
but our real strategy was simply to push things as hard as we could
to see what obstacles we would bump into.</p>
<h3 id="early-days-first-formalisations">Early days, first formalisations</h3>
<p><a href="https://www.cl.cam.ac.uk/~lp15/Grants/Alexandria/Part-B2.pdf">The proposal</a>
called for hiring research mathematicians, who would bring
their knowledge of mathematics as it was practised,
along with their <em>inexperience</em> of Isabelle/HOL. Their role would be
to formalise increasingly advanced mathematical material with the twin objectives of
developing formalisation methodologies and identifying deficiencies that might be remedied
by extending Isabelle/HOL somehow. The project started in September 2017.
We hired <a href="https://sites.google.com/site/anthonybordg/">Anthony Bordg</a>
and <a href="https://www.cl.cam.ac.uk/~ak2110/">Angeliki Koutsoukou-Argyraki</a>
(many thanks to <a href="https://www.cl.cam.ac.uk/~mj201/">Mateja Jamnik</a> for interviewing with me).
A third postdoc was required to undertake any necessary Isabelle engineering,
and <a href="https://www.cst.cam.ac.uk/people/wl302">Wenda Li</a> was hired.</p>
<p>One of the tasks for the first year was simply to reorganise and consolidate
the Isabelle/HOL analysis library, which had mostly been stolen from <a href="https://www.cl.cam.ac.uk/~jrh13/hol-light">HOL Light</a>.
But we were also supposed to conduct pilot studies.
The team set to work enthusiastically, and already in the first year
they created a number of impressive developments:</p>
<ul>
<li><a href="https://www.isa-afp.org/entries/Projective_Geometry.html">Projective Geometry</a>, including Hessenberg’s theorem and Desargues’s theorem</li>
<li><a href="https://www.isa-afp.org/entries/Quaternions.html">Quaternions</a> and <a href="https://www.isa-afp.org/entries/Octonions.html">Octonions</a></li>
<li><a href="https://www.isa-afp.org/entries/Irrationality_J_Hancl.html">Irrational rapidly convergent series</a>, formalising a proof by J. Hančl published in 2002</li>
<li>Effectively counting <a href="https://www.isa-afp.org/entries/Budan_Fourier.html">real</a> and <a href="https://www.isa-afp.org/entries/Count_Complex_Roots.html">complex</a> roots of polynomials, the Budan-Fourier theorem</li>
<li>The first formal proof that <a href="https://rdcu.be/cIK3W">every field contains an algebraically closed extension</a></li>
</ul>
<p>Some mathematical proofs rely on calculations, and these can be extremely difficult
to carry out formally. Mathematicians frequently rely on intuition
when calculating limits and integrals, for example.
The root-counting results mentioned above were an early focus of Wenda
(who actually joined in almost every task);
they belong to
<a href="https://en.wikipedia.org/wiki/Real_algebraic_geometry">real algebraic geometry</a>,
and one objective of that work is an efficient, verified decision procedure for deciding
equalities and inequalities between polynomials.</p>
<p>Angeliki wrote up her reactions to Isabelle/HOL from the perspective of a mathematician in her paper <a href="https://link.springer.com/article/10.1365/s13291-020-00221-1">Formalising Mathematics – in Praxis</a>.</p>
<h3 id="the-next-phase-advanced-formalisations-for-experimental-mathematics">The next phase: advanced formalisations for <em>Experimental Mathematics</em></h3>
<p>Around this time, Kevin Buzzard had launched
<a href="https://xenaproject.wordpress.com">his own project</a> on formalising mathematics
using Lean. As a number theorist, he brought his own perspective.
Earlier researchers had formalised huge proofs such as the
<a href="https://hal.inria.fr/hal-00816699/document">odd order theorem</a>,
but on the whole they had been working
with simple objects far removed from the sophistication of mathematical practice.
His paper <a href="https://arxiv.org/abs/1910.12320">Formalising perfectoid spaces</a>
took the viewpoint that before you can even think about proving theorems,
you need to show that you can capture some pretty intricate <em>definitions</em>.</p>
<p>We also understood the need to tackle difficult material, preferably from a wide range
of mathematical subdisciplines. Meanwhile, Angeliki noticed that that the journal
<em>Experimental Mathematics</em> had announced a special issue on formalisation. We decided to aim for that, with substantial projects:</p>
<ul>
<li><a href="https://doi.org/10.1080/10586458.2021.1980465">Irrationality and transcendence criteria for infinite series in Isabelle/HOL</a>, formalising material from three different research papers: by Erdős and Straus, Hančl, and Hančl and Rucki</li>
<li><a href="https://doi.org/10.1080/10586458.2021.1980464">Formalizing ordinal partition relations using Isabelle/HOL</a>, formalising papers by Erdős–Milner, and <a href="https://people.clas.ufl.edu/jal/">Jean Larson</a> on intricate constructions involving infinitary Ramsey theory.</li>
<li><a href="https://doi.org/10.1080/10586458.2022.2062073">Simple type theory is not too simple: Grothendieck’s schemes without dependent types</a></li>
</ul>
<p>We were delighted to see all three papers accepted to the special issue,
taking up fully half of the accepted submissions.</p>
<p><em>Schemes</em> are a fundamental construction used in number theory.
Buzzard had expressed astonishment that they had not been formalised
in any proof assistant. The problem was simply that a user community
consisting of computer scientists had never heard of schemes
and had no idea what they were for. (I still don’t.)
Buzzard’s <a href="https://doi.org/10.1080/10586458.2021.1983489">own paper</a>
in <em>Experimental Mathematics</em> described three separate
formalisations of schemes, all using Lean. The first definition had to be discarded
due to technical issues related to Lean’s type theory and in particular
the distinction it makes between equality and definitional equality.</p>
<p>Anthony led the formalisation of schemes in Isabelle, in which I took part.
I recall a great many definitions piled one atop the other,
but no technical issues at any point. What’s notable is that many well-informed people thought
that schemes could not possibly be formalised in Isabelle/HOL,
because it lacks dependent types.
The opposite is true: the issues with the first Lean formalisation
were caused by dependent types.</p>
<h3 id="advanced-library-search">Advanced library search</h3>
<p>ALEXANDRIA refers to the famous
<a href="https://en.wikipedia.org/wiki/Library_of_Alexandria">library of Alexandria</a>.
Even at the start of the project, Isabelle’s Archive of Formal Proofs (AFP)
held a substantial collection. At the moment there are nearly 4 million lines of formal proofs
and <a href="https://www.isa-afp.org/statistics/">741 separate entries</a>.
The proposal included the goal of supporting intelligent search of large proof repositories
and, more speculatively, somehow using the millions of lines of existing proofs
in conjunction with some sort of machine learning technology to assist in generating
new proofs.
In May 2019 we acquired a new postdoc, <a href="https://www.cl.cam.ac.uk/~yas23/">Yiannos Stathopoulos</a>,
who came with the perfect background to tackle these objectives.
After much labour, he and Angeliki produced the
<a href="https://behemoth.cl.cam.ac.uk/search/">SErAPIS search engine</a>, which searches
both the pre-installed Isabelle libraries and the AFP,
offering a <a href="https://www.researchgate.net/publication/341655872_SErAPIS_A_Concept-Oriented_Search_Engine_for_the_Isabelle_Libraries_Based_on_Natural_Language">great many search strategies</a>
based on anything from simple keywords
to abstract mathematical concepts. It is a complex area and we don’t claim to have solved
all the problems, but SErAPIS has quite a few users.
And Yiannos has much more in the pipeline.</p>
<h3 id="machine-learning-experiments">Machine learning experiments</h3>
<p>The proposal included the task of Intelligent User Support.
How this could be provided wasn’t clear from the outset,
but machine learning was already topical and we had millions of lines
of formal proofs to use as a starting point.</p>
<p>The team applied themselves to this task with great vigour,
aided by other members of the Laboratory,
notably <a href="https://www.cl.cam.ac.uk/~sbh11/">Sean Holden</a>
and <a href="https://albertqjiang.github.io">Albert Jiang</a> and by other collaborators outside Cambridge. It is now clear that language models can generate formal proof skeletons
and translate informal proofs into formal languages (<em>autoformalisation</em>).
One of the many outstanding efforts is reported in the paper
<a href="https://arxiv.org/abs/2210.12283">Draft, Sketch, and Prove</a>.
Wenda Li led a separate effort to <a href="https://openreview.net/forum?id=Pzj6fzU6wkj">generate intermediate assertions</a>,
for the automated generation of proofs by refinement.
These two papers are a mere foretaste of the tremendous developments now underway.</p>
<h3 id="more-and-more-formalisations">More and more formalisations</h3>
<p>Once you get the hang of it, the task of formalisation becomes routine.
Then the choice of the next project is a matter of asking whether one of us
understand the mathematics well enough and whether we have sufficient time.
It actually becomes tedious to list all the results proved.
(There is a complete list on the <a href="https://www.cl.cam.ac.uk/~lp15/Grants/Alexandria/">ALEXANDRIA website</a>.)
For example, we formalised <a href="https://doi.org/10.1007/s10817-022-09650-2">Szemerédi’s Regularity Lemma</a>
and the <a href="https://doi.org/10.1145/3573105.3575680">Balog–Szemerédi–Gowers</a> theorem
with the help of <a href="https://www.cst.cam.ac.uk/people/cle47">Chelsea Edmonds</a>, a PhD student.
She also formalised <a href="https://files.sketis.net/Isabelle_Workshop_2020/Isabelle_2020_paper_10.pdf">Lucas’s theorem</a>
and <a href="https://doi.org/10.4230/LIPIcs.ITP.2022.11">Fisher’s inequality</a>,
and has been building the first formalisation
of combinatorial block design theory.</p>
<p>Many of the projects described above (and others not mentioned) involved
the work of interns who visited the Computer Laboratory, financially supported by the project
and in many cases by <a href="https://www.maths.cam.ac.uk/opportunities/careers-for-mathematicians/summer-research-mathematics/cambridge-mathematics-placements-cmp">Cambridge Mathematics Placements</a>.</p>
<p>Angeliki has pointed out that “we have formalised results by two Fields medalists
(Roth and Gowers), an Abel prize winner (Szemerédi)
and of course <a href="https://doi.org/10.1016/j.apal.2023.103246">Erdős</a> too!”</p>
<h3 id="scientific-contributions">Scientific contributions</h3>
<p>The most striking and unexpected discovery was that there really seem to be
essentially no limits to what we can formalise.
I was sure we would run into no-go areas, but this never happened.
We aimed for breadth and found that we could handle combinatorics, extremal graph theory,
algebra, analytic number theory and everything else we tried.</p>
<p>One particular scientific question is the need for dependent types.
Anthony has shown that there are
<a href="https://doi.org/10.1145/3573105.3575679">arguments in both directions</a>,
presenting straightforward techniques for expressing dependent types
within the simply typed language of Isabelle/HOL.
Meanwhile, issues caused by intensional equality in Lean continued to show
the brittleness of that framework.</p>
<p>Our work also provides further evidence for the thesis that simple type theory
(and therefore, also <a href="https://en.wikipedia.org/wiki/Zermelo_set_theory">Zermelo set theory</a>) is adequate to formalise mathematics
excepting that part that refers to set theory explicitly.
Since simple type theory is essentially the <a href="/papers/Russells-mathematical-logic.pdf">formalism of
Whitehead and Russell</a>
in their <a href="https://plato.stanford.edu/entries/principia-mathematica/"><em>Principia Mathematica</em></a>,
we reach the surprising conclusion
that they were correct: their logic is indeed strong enough
to formalise more or less the <em>whole of mathematics</em>.</p>
<p>The field as a whole has advanced tremendously, driven also by the huge
and enthusiastic Lean community. One sign of progress is the
<a href="https://www.cs.ru.nl/~freek/100/">famous list</a> of 100 rather arbitrary
but notable theorems. It has taken a long time, but now 99 of the 100 theorems
have been formalised in one system or another, with Isabelle and HOL Light
tied at the top with 87. There’s only one left: Fermat’s Last Theorem.</p>
Thu, 27 Apr 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/04/27/ALEXANDRIA_outcomes.html
https://lawrencecpaulson.github.io//2023/04/27/ALEXANDRIA_outcomes.htmlWittgenstein on natural science, mathematics and logic<p>In a blog devoted to mathematics and logic, it’s hard to avoid Wittgenstein.
Wittgenstein saw his main contributions being to the philosophy of mathematics
and logic. I’m not sure that
he understood either of them. But let’s begin with natural science, since it touches on
topics relevant to this blog, such as the relationship between
<a href="/2022/07/27/Truth_Models.html">models and the real world</a>.
Natural science is another field where Wittgenstein indulged in his habit of obscurantism.
Since I don’t know much about philosophy, perhaps I have no business
criticising a famous philosopher.
But I have the right to judge whether he is basing his reasoning
on premises that are, if not correct, at least plausible.</p>
<h3 id="natural-science">Natural science</h3>
<p>The <em>Oxford Dictionary</em> defines natural science as “the branch of knowledge
that deals with the study of the physical world”.
Such studies have been going on forever. Ancient peoples observed the heavens,
watching the sun traverse the sky from east to west and the moon with its phases.
They saw the stars fixed in their constellations within the firmament,
which rotated as the night progressed,
and the strange wandering stars (“planets”) that followed mysterious paths.
They regarded the earth as stationary: a reasonable conclusion, trusting their sense of motion.</p>
<p>Over the centuries, astronomers made increasingly detailed observations,
somehow learning to predict eclipses and the motions of the planets.
The <a href="https://en.wikipedia.org/wiki/Antikythera_mechanism">Antikythera mechanism</a>,
which dates to no later than 100 BCE, could perform these functions mechanically.</p>
<p>Many centuries later came the realisation,
due to <a href="https://en.wikipedia.org/wiki/Nicolaus_Copernicus">Copernicus</a>,
<a href="https://en.wikipedia.org/wiki/Giordano_Bruno">Giordano Bruno</a>,
and <a href="https://en.wikipedia.org/wiki/Galileo_Galilei">Galileo</a>,
that Earth, like the other planets, orbited the Sun.
Observations by <a href="https://en.wikipedia.org/wiki/Tycho_Brahe">Tycho Brahe</a>
(working without a telescope)
and <a href="https://en.wikipedia.org/wiki/Johannes_Kepler">Johannes Kepler</a> led to Newton’s
promulgation of the <a href="https://en.wikipedia.org/wiki/Newton's_laws_of_motion">laws of motion</a> and
<a href="https://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation">of gravity</a>,
mathematical formulas precisely fitting the observed motions of the planets
(and still precise enough to take a spacecraft to Mars today).</p>
<p>We see different kinds of knowledge here:</p>
<ul>
<li>direct observations of specific events</li>
<li>reasonable conclusions that were wrong, or only partly right, whatever that might mean</li>
<li>adoption of models (the Copernican model preferred simply because of its greater elegance)</li>
<li>refinement of models (Newton’s laws are a quantitative refinement of the Copernican model)</li>
<li>rejection of models and even of observations</li>
</ul>
<p>And we see lots of issues that trouble real philosophers of science.
These include the difficulty of making accurate observations, of choosing among alternative models (what do we mean by elegance and why should a model be elegant?), of the role of predictions, how to deal with errors, and more fundamentally, the nature of reality
and how to distinguish it from illusion.
There is the problem of inferring natural laws from a finite number of observations:
so-called inductive inferences, which could be disproved by further observations tomorrow.
There is the question of why there should be any natural laws at all.</p>
<p>And then we have Wittgenstein, in his <em>Tractatus</em>:</p>
<blockquote>
<p>The world is all that is the case</p>
</blockquote>
<blockquote>
<p>The totality of true propositions is the whole of natural science</p>
</blockquote>
<p>He’s possibly trying to say something.
Certainly, many highly intelligent people have tried to clothe
this bare scaffold with meaning. If he has stimulated others to think original thoughts,
that’s something. But on to mathematics.</p>
<h3 id="mathematics">Mathematics</h3>
<p>It’s the easiest to quote from <a href="https://plato.stanford.edu/entries/wittgenstein-mathematics/">relevant entry</a>
of the <em>Stanford Encyclopaedia of Philosophy</em>:</p>
<blockquote>
<p>The <em>core idea</em> of Wittgenstein’s formalism from 1929 (if not 1918) through 1944 is that mathematics is essentially syntactical, devoid of reference and semantics. The most obvious aspect of this view, which has been noted by numerous commentators who do not refer to Wittgenstein as a ‘formalist’ … is that, <em>contra Platonism</em>, the signs and propositions of a mathematical calculus do not <em>refer</em> to anything. … When we prove a theorem or decide a proposition, we operate in a <em>purely formal</em>, syntactical manner.</p>
</blockquote>
<p>Although Wittgenstein’s view is particularly extreme, he’s not alone.
One of the main proponents of formalism was <a href="https://en.wikipedia.org/wiki/Haskell_Curry">Haskell B Curry</a>,
who had a point, because his own field of study — combinatorial logic —
was indeed concerned with meaningless symbol strings.
He might be compared to a ballerina declaring that work is nothing but dancing.</p>
<p>David Hilbert was also a proponent of formalism, in my opinion as a response
to the <a href="https://plato.stanford.edu/entries/settheory-early/#CritPeri">numerous paradoxes</a>
that had rocked mathematics since the beginning of the 20th century.
A hedgehog, confronted with mortal danger, rolls up into a ball,
but Hilbert was no hedgehog.
Having declared that Cantor had created paradise,
he obviously did find meaning in mathematics.
His formalism was a desperate attempt to
<a href="/2023/02/01/On-the-infinite.html">salvage from the wreckage</a>
as much mathematics as possible.
His chosen tool–<em>Hilbert’s programme</em>–was to
reduce everything to a formal, provably consistent axiom system.
But the very need for such a programme shows
that mathematics had not been conducted formally before.
How did Wittgenstein get the idea that it had?</p>
<p>It’s not too much to say that mathematics emerged from magic.
Isaac Newton, called the greatest ever scientist, was also committed to alchemy
and his version of the calculus, <em>fluxions</em>, relied on infinitesimals.
Leonhard Euler also used infinitesimals and regularly bent the rules, e.g.
manipulating infinite sums as if they were finite. He arrived at correct results
not by obeying the rules of a formal system but by breaking them.
There would be no rigorous (let alone formal) account of infinitesimals until the 1960s.
Unsound and intuitive techniques dominated until the mid-nineteenth century,
when a concentrated effort was undertaken by Cauchy and Weierstrass
(getting rid of infinitesimals) and later Frege, Whitehead, Russell
(the first serious effort at formalisation).
The 20th century saw a concerted effort to purge intuition from mathematics.
There is no need to purge something that never existed.</p>
<p>I have particular knowledge about the formalist philosphy: my field of research is the
formalisation of mathematics. I’m aware of many instances were a mathematical proof
was incorrect, yet the actual claim of the theorem still held. If proofs
are mere calculations, then how do mathematicians perceive the truth of of claims
for which they have no proof? If mathematics is meaningless,
then why have so many mathematical conceptions aroused such visceral emotions?</p>
<ul>
<li><a href="https://nrich.maths.org/2671">irrational numbers</a></li>
<li><a href="https://mathshistory.st-andrews.ac.uk/HistTopics/Non-Euclidean_geometry/">non-Euclidean geometry</a></li>
<li><a href="https://en.wikipedia.org/wiki/The_Analyst">infinitesimals</a>,</li>
<li><a href="https://infinityplusonemath.wordpress.com/2017/02/11/no-one-liked-cantor/">Cantor’s set theory</a></li>
<li><a href="https://plato.stanford.edu/entries/axiom-choice/">the axiom of choice</a></li>
</ul>
<p>The vivid language that mathematicians used to debate these points does not suggest
meaninglessness. Contrast with something that’s really meaningless, like a Sudoku;
try to imagine a Sudoku causing outrage or scandal.</p>
<p>But the really big problem with Wittgenstein’s calculational view
is his apparent belief that mathematics consists entirely of proving things.
First, you have to decide what to prove things about.</p>
<h3 id="creativity-in-mathematics">Creativity in mathematics</h3>
<p>Prime numbers lie at the heart of almost every big question in mathematics.
We don’t know who first identified the primes as interesting.
But we know who introduced group theory:
<a href="https://en.wikipedia.org/wiki/Évariste_Galois">Évariste Galois</a>.
Somehow he conceived the concept of a <em>group</em> and recognised its importance.
He identified the key concepts of group theory, notably
<em>normal subgroups</em>, which play a role somewhat analogous to prime numbers.
It is true, that Galois did all this in order to prove theorems and settle
the question of which polynomial equations were solvable by radicals.
But there was no calculation involved in arriving at the concept of a group.
The same could be said of many other mathematical conceptions that we take for granted,
such as measure theory or Latin squares.</p>
<p>One of the most intriguing of these is <a href="https://en.wikipedia.org/wiki/Conic_section">conic sections</a>.
These were central to Greek geometry, and we might well wonder why.
Certain kinds of mathematics were of obvious value to ancient people:
arithmetic, for counting; plane geometry, for land surveying;
three-dimensional geometry, for architecture. But what could possibly be the use of a cone?<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>
<p><img src="/images/TypesOfConicSections.jpg" alt="Types of conic sections" /></p>
<p>Somebody long ago fixated on cones and their sections: the circle, the ellipse, the parabola
and the hyperbola. We don’t know why, but we know it wasn’t a calculation.</p>
<p>Turning to the modern day, one of the most inventive mathematicians was John Conway.
His book <em>On Numbers and Games</em> begins with the definition of a new number system, as follows:</p>
<blockquote>
<p>If <em>L</em>, <em>R</em> are any two sets of numbers, and no member of <em>L</em> is ≥ any member of <em>R</em>, then there is a number {<em>L</em>|<em>R</em>}. Al numbers are constructed in this way.</p>
</blockquote>
<p>There is a fair bit more to this definition. Nevertheless, it does not directly conform
to any pre-existing definitional principle. It took a genius, Conway, to write this definition.
Others had to put in some effort to make it legitimate.
Conway wasn’t following the rules but breaking them, inspired by earlier (and also doubted)
work by Dedekind and Cantor.</p>
<h3 id="intuition-in-mathematics">Intuition in mathematics</h3>
<p>It’s impossible to deny that formal calculation plays a role in mathematical proofs.
But it plays much less of a role than some people imagine, as I discover every day
when carrying out the process of formalising mathematics for real.
Consider the statement “an eagle carried off a baby elephant”.
We could decide its truth through elaborate calculations involving the strength of the eagle’s wings and claws and the efficiency of its respiratory system, along with the likely weight of the baby elephant. But that’s not how we do it.
Similarly, mathematicians decide most mathematical questions using their intuition alone.
They know whether a function is likely to be continuous,
a polynomial is likely to have a real root, a set is likely to be countable.
Most importantly, they surprisingly often know whether a deep theorem is likely to be true
before undertaking the labour of proving it, and <strong>even if their proof is wrong</strong>.
These are judgements, not calculations. Those of us who formalise mathematics
are forced to come up with those omitted calculations
and to fix the broken proofs.</p>
<p>Perversely, the very use of proof assistants seems to promote the idea that mathematics
is inherently an exercise in formal calculation,
despite the extreme difficulty of doing mathematics using such tools.
Students say things like “mathematics is a formal system because mathematicians use set theory with its Zermelo–Fraenkel axioms.”
Guys, 99% of the time, not even set theorists refer to those axioms.
Their mode of working is as intuitive as anybody else’s.
Other mathematicians are unlikely to be thinking about set theory at all.</p>
<p>While on the subject of intuition, let’s have
<a href="/papers/Russells-mathematical-logic.pdf">Gödel describing Russell’s discovery</a> of his famous paradox:</p>
<blockquote>
<p>By analyzing the paradoxes to which Cantor’s set theory had led, [Russell] freed them from all mathematical technicalities, thus bringing to light the amazing fact that our logical intuitions (i.e., intuitions concerning such notions as: truth, concept, being, class, etc.) are self-contradictory.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>
</blockquote>
<p>And this was no meaningless calculation, but a cataclysm that seemed to threaten mathematics itself.</p>
<h3 id="postscript">Postscript</h3>
<p>Wittgenstein served in World War I. His diaries and letters are powerful:</p>
<blockquote>
<p>Life is a form of torture from which there is only temporary reprieve until one can be subjected to further torments. A terrible assortment of torments. An exhausting march, a cough-filled night, a company of drunks, a company of mean and stupid people. Do good and be happy about your virtue. I am sick and lead a bad life. God help me. I am a poor unlucky being. God deliver me and grant me peace! Amen.</p>
</blockquote>
<p>Without doubt, he could write clearly and in plain language when he had something to say.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>JensVyff, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>Kurt Gödel, <a href="https://doi.org/10.1017/CBO9781139171519.024">Russell’s mathematical logic</a>. <em>In</em>: P Benacerraf, H Putnam (eds), <em>Philosophy of Mathematics: Selected Readings</em> (CUP, 1984), 447-469 <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>
Wed, 12 Apr 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/04/12/Wittgenstein.html
https://lawrencecpaulson.github.io//2023/04/12/Wittgenstein.htmlSmall examples involving binomial coefficients<p>The <a href="https://en.wikipedia.org/wiki/Binomial_coefficient">binomial coefficients</a>,
which appear in the <a href="https://en.wikipedia.org/wiki/Binomial_theorem">binomial theorem</a>,
have numerous applications in combinatorics and the analysis of algorithms.
<a href="https://www-cs-faculty.stanford.edu/~knuth/">Donald E Knuth</a>
wrote extensively about them in the book
<a href="https://en.wikipedia.org/wiki/Concrete_Mathematics"><em>Concrete Mathematics</em></a>.
They are the elements of Pascal’s triangle and satisfy a great many mathematical identities.
Let’s prove some of them using Isabelle/HOL. These and many more
are available built-in.</p>
<h3 id="warming-up">Warming up</h3>
<p>Let’s recall the definition of the binomial coefficient “<em>n</em> choose <em>k</em>”, which denotes how many <em>k</em>-element subsets can be chosen from an <em>n</em>-element set:</p>
\[\begin{gather*} \binom{n}{k} = \frac{n!}{k!(n-k)!}. \end{gather*}\]
<p>There follow a number of trivial properties, such as</p>
\[\begin{gather*} (n-k)\binom{n}{k} = n\binom{n-1}{k}. \end{gather*}\]
<p>Slightly deeper is the following claim,
that the sum of a row of Pascal’s triangle is a power of 2:</p>
\[\begin{gather*} \sum_{k\le n} \binom{n}{k} = 2^n. \end{gather*}\]
<p>It’s trivial for us to prove because the binomial theorem—already available in Isabelle/HOL—expresses $(x+y)^n$ in terms of binomial coefficients.
We can express the desired sum by putting $x=y=1$ in that theorem.
Observe the syntax for instantiating variables in a theorem.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> choose_row_sum<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span><span class="free">n</span><span class="main">.</span> <span class="free">n</span> <span class="keyword1">choose</span></span> <span class="bound">k</span><span class="main">)</span> <span class="main">=</span></span> <span class="numeral">2</span><span class="main">^</span><span class="free">n</span><span>"</span><span>
</span><span class="keyword1 command">using</span> binomial <span class="main">[</span><span class="operator">of</span> <span class="quoted main">1</span> <span class="quoted"><span class="quoted"><span class="main">1</span></span></span> <span class="quoted free">n</span><span class="main">]</span> <span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> numeral_2_eq_2<span class="main">)</span>
</pre>
<p>Many other identities are trivial inductions. These two are hardly worth a discussion.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> sum_choose_lower<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span><span class="free">n</span><span class="main">.</span> <span class="main">(</span><span class="free">r</span><span class="main">+</span></span><span class="bound">k</span><span class="main">)</span> <span class="keyword1">choose</span></span> <span class="bound">k</span><span class="main">)</span> <span class="main">=</span> Suc <span class="main">(</span><span class="free">r</span><span class="main">+</span><span class="free">n</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="free">n</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">n</span><span class="main">)</span> <span class="operator">auto</span>
</pre>
<pre class="source">
<span class="keyword1 command">lemma</span> sum_choose_upper<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span><span class="free">n</span><span class="main">.</span> <span class="bound">k</span> <span class="keyword1">choose</span></span> <span class="free">m</span><span class="main">)</span> <span class="main">=</span></span> Suc <span class="free">n</span> <span class="keyword1">choose</span> Suc <span class="free">m</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">n</span><span class="main">)</span> <span class="operator">auto</span>
</pre>
<h3 id="manipulating-a-summation">Manipulating a summation</h3>
<p>The following little identity does not require induction, since it uses
one of the identities just proved. But its first step is a little tricky:
the index variable, $k$, is replaced by $m-k$. Such manipulations
frequently require the user to tear out their hair.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> sum_choose_diagonal<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">m</span><span class="main">≤</span></span><span class="free">n</span><span>"</span></span><span>
</span><span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span><span class="free">m</span><span class="main">.</span> <span class="main">(</span><span class="free">n</span><span class="main">-</span></span><span class="bound">k</span><span class="main">)</span> <span class="keyword1">choose</span></span> <span class="main">(</span><span class="free">m</span><span class="main">-</span><span class="bound">k</span><span class="main">)</span><span class="main">)</span> <span class="main">=</span> Suc <span class="free">n</span> <span class="keyword1">choose</span> <span class="free">m</span><span>"</span><span>
</span><span class="keyword1 command">proof</span> <span class="operator">-</span><span>
</span><span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span><span class="free">m</span><span class="main">.</span> <span class="main">(</span><span class="free">n</span><span class="main">-</span></span><span class="bound">k</span><span class="main">)</span> <span class="keyword1">choose</span></span> <span class="main">(</span><span class="free">m</span><span class="main">-</span><span class="bound">k</span><span class="main">)</span><span class="main">)</span> <span class="main">=</span> <span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span><span class="free">m</span><span class="main">.</span> <span class="main">(</span><span class="free">n</span><span class="main">-</span><span class="free">m</span><span class="main">+</span><span class="bound">k</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="bound">k</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">using</span> sum.atLeastAtMost_rev <span class="main">[</span><span class="operator">of</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">λ</span><span class="bound">k</span><span class="main">.</span> <span class="main">(</span><span class="free">n</span> <span class="main">-</span></span> <span class="bound">k</span><span class="main">)</span> <span class="keyword1">choose</span></span> <span class="main">(</span><span class="free">m</span> <span class="main">-</span> <span class="bound">k</span><span class="main">)</span><span>"</span> <span class="quoted main">0</span> <span class="quoted free">m</span><span class="main">]</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> atMost_atLeast0 <span class="quoted"><span class="quoted"><span>‹</span><span class="free">m</span><span class="main">≤</span></span><span class="free">n</span><span>›</span></span><span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> Suc</span> <span class="main">(</span><span class="free">n</span><span class="main">-</span><span class="free">m</span><span class="main">+</span><span class="free">m</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="free">m</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">rule</span> sum_choose_lower<span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> Suc</span> <span class="free">n</span> <span class="keyword1">choose</span> <span class="free">m</span><span>"</span> <span class="keyword1 command">using</span> assms<span>
</span><span class="keyword1 command">by</span> <span class="operator">simp</span><span>
</span><span class="keyword1 command">finally</span> <span class="keyword3 command">show</span> <span class="var quoted var">?thesis</span> <span class="keyword1 command">.</span><span>
</span><span class="keyword1 command">qed</span>
</pre>
<h3 id="proving-the-subset-of-a-subset-identity">Proving the <em>subset of a subset</em> identity</h3>
<p>Intuitively, the identity $\binom{n}{m} \binom{m}{k} = \binom{n}{k} \binom{n-k}{m-k}$
concerns the number of ways to choose $k$ elements out of $m$ elements
that were originally chosen out of $n$.
It’s equivalent to the number of ways of
immediately choosing $k$ out of $n$ times the number of ways of choosing the leftover $m-k$
elements out of the original, unwanted $n-k$ elements. Or something.
Such intuitive arguments are a nightmare to formalise, but fortunately
this proof is a fairly simple calculation.</p>
<p>It relies on a basic divisibility property:
that $k!(n-k)!$ divides $n!$ provided
$k\le n$. The divisor is precisely $\binom{n}{k}$, a fact proved
in the main library. (And it doesn’t follow from the definition
of $\binom{n}{k}$, but rather justifies that definition.)</p>
<p>Now we can prove our identity by expressing binomial coefficients in terms of factorials. It’s just a chain of identities, called in Isar a
<em>calculational proof</em>.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> choose_mult_lemma<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">(</span><span class="free">m</span><span class="main">+</span></span><span class="free">r</span><span class="main">+</span></span><span class="free">k</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">k</span><span class="main">)</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span><span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="free">k</span><span class="main">)</span> <span class="main">=</span> <span class="main">(</span><span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="free">k</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span><span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="free">m</span><span class="main">)</span><span>"</span><span>
</span><span class="main">(</span><span class="keyword2 keyword">is</span> <span class="quoted"><span class="quoted"><span>"</span><span class="var">?lhs</span> <span class="main">=</span></span> <span class="main">_</span><span>"</span></span><span class="main">)</span><span>
</span><span class="keyword1 command">proof</span> <span class="operator">-</span><span>
</span><span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="var">?lhs</span> <span class="main">=</span></span><span>
</span>fact</span><span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="keyword1">div</span> <span class="main">(</span>fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="main">*</span> fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">-</span><span class="free">m</span><span class="main">)</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span>fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="keyword1">div</span> <span class="main">(</span>fact <span class="free">k</span> <span class="main">*</span> fact <span class="free">m</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> binomial_altdef_nat<span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> fact</span><span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="main">*</span> fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="keyword1">div</span><span>
</span><span class="main">(</span>fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="main">*</span> fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">-</span><span class="free">m</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span>fact <span class="free">k</span> <span class="main">*</span> fact <span class="free">m</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> add_implies_diff add_le_mono1 choose_dvd diff_cancel2 div_mult_div_if_dvd<span>
</span>le_add1 le_add2<span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> fact</span><span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="keyword1">div</span> <span class="main">(</span>fact <span class="free">r</span> <span class="main">*</span> <span class="main">(</span>fact <span class="free">k</span> <span class="main">*</span> fact <span class="free">m</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">auto</span> <span class="quasi_keyword">simp</span><span class="main main">:</span> <span class="dynamic dynamic">algebra_simps</span> fact_fact_dvd_fact<span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> <span class="main">(</span>fact</span><span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="main">*</span> fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">)</span><span class="main">)</span> <span class="keyword1">div</span> <span class="main">(</span>fact <span class="free">r</span> <span class="main">*</span> <span class="main">(</span>fact <span class="free">k</span> <span class="main">*</span> fact <span class="free">m</span><span class="main">)</span> <span class="main">*</span> fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="operator">simp</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span><span>
</span><span class="main">(</span>fact</span><span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">+</span><span class="free">k</span><span class="main">)</span> <span class="keyword1">div</span> <span class="main">(</span>fact <span class="free">k</span> <span class="main">*</span> fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">)</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span>fact<span class="main">(</span><span class="free">m</span><span class="main">+</span><span class="free">r</span><span class="main">)</span> <span class="keyword1">div</span> <span class="main">(</span>fact <span class="free">r</span> <span class="main">*</span> fact <span class="free">m</span><span class="main">)</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">smt</span> <span class="main main">(</span>verit<span class="main main">)</span> fact_fact_dvd_fact div_mult_div_if_dvd mult.assoc mult.commute<span class="main">)</span><span>
</span><span class="keyword1 command">finally</span> <span class="keyword3 command">show</span> <span class="var quoted var">?thesis</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> binomial_altdef_nat mult.commute<span class="main">)</span><span>
</span><span class="keyword1 command">qed</span></pre>
<p>Above, we avoided subtraction in favour of addition,
a trick that frequently simplifies our work.
Now it’s trivial to derive the “subset of a subset” identity in its
traditional form,
$\binom{n}{m} \binom{m}{k} = \binom{n}{k} \binom{n-k}{m-k}$.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> choose_mult<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="free">k</span> <span class="main">≤</span></span> <span class="free">m</span> <span class="main">⟹</span> <span class="free">m</span> <span class="main">≤</span></span> <span class="free">n</span> <span class="main">⟹</span> <span class="main">(</span><span class="free">n</span> <span class="keyword1">choose</span> <span class="free">m</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span><span class="free">m</span> <span class="keyword1">choose</span> <span class="free">k</span><span class="main">)</span> <span class="main">=</span> <span class="main">(</span><span class="free">n</span> <span class="keyword1">choose</span> <span class="free">k</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span><span class="main">(</span><span class="free">n</span> <span class="main">-</span> <span class="free">k</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="main">(</span><span class="free">m</span> <span class="main">-</span> <span class="free">k</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">using</span> choose_mult_lemma <span class="main">[</span><span class="operator">of</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">m</span><span class="main">-</span></span><span class="free">k</span><span>"</span></span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">n</span><span class="main">-</span></span><span class="free">m</span><span>"</span></span> <span class="quoted free">k</span><span class="main">]</span> <span class="keyword1 command">by</span> <span class="operator">simp</span>
</pre>
<h3 id="an-easy-tricky-proof">An easy tricky proof</h3>
<p>In <em>Concrete Mathematics</em>, the authors remark</p>
<blockquote>
<p>There is a way to partially sum the row elements [of Pascal’s triangle] if they have been multiplied by their distance from the centre.</p>
</blockquote>
<p>They give the following formula (numbered 5.18):</p>
\[\begin{gather*}
\sum_{k\le m}\binom{r}{k}\left(\frac{r}{2}-k\right)
= \frac{m+1}{2}\binom{r}{m+1}.
\end{gather*}\]
<p>And they remark, “this formula is easily verified by induction on <em>m</em>”.
Dangerous words. They certainly provoked me to try formulaic
induction/simplification steps that exploded the formula into chaos.
When that happens, it’s best to try to work out the steps on paper
first. I eventually arrived at the following, which quite possibly
is the proof they omitted.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> choose_row_sum_weighted<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span><span class="free">m</span><span class="main">.</span> <span class="main">(</span><span class="free">r</span> <span class="keyword1">choose</span></span> <span class="bound">k</span><span class="main">)</span> <span class="main">*</span></span> <span class="main">(</span><span class="free">r</span><span class="main">/</span><span class="numeral">2</span> <span class="main">-</span> <span class="bound">k</span><span class="main">)</span><span class="main">)</span> <span class="main">=</span> <span class="main">(</span>Suc <span class="free">m</span><span class="main">)</span><span class="main">/</span><span class="numeral">2</span> <span class="main">*</span> <span class="main">(</span><span class="free">r</span> <span class="keyword1">choose</span> <span class="main">(</span>Suc <span class="free">m</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">m</span><span class="main">)</span><span>
</span><span class="keyword3 command">case</span> 0 <span class="keyword3 command">show</span> <span class="var quoted var">?case</span> <span class="keyword1 command">by</span> <span class="operator">simp</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>Suc <span class="skolem">m</span><span class="main">)</span><span>
</span><span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span>Suc</span> <span class="skolem">m</span><span class="main">.</span> real</span> <span class="main">(</span><span class="free">r</span> <span class="keyword1">choose</span> <span class="bound">k</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span><span class="free">r</span><span class="main">/</span><span class="numeral">2</span> <span class="main">-</span> <span class="bound">k</span><span class="main">)</span><span class="main">)</span><span>
</span><span class="main">=</span> <span class="main">(</span><span class="main">(</span><span class="free">r</span> <span class="keyword1">choose</span> Suc <span class="skolem">m</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span><span class="free">r</span><span class="main">/</span><span class="numeral">2</span> <span class="main">-</span> <span class="main">(</span>Suc <span class="skolem">m</span><span class="main">)</span><span class="main">)</span><span class="main">)</span> <span class="main">+</span> <span class="main">(</span>Suc <span class="skolem">m</span><span class="main">)</span> <span class="main">/</span> <span class="numeral">2</span> <span class="main">*</span> <span class="main">(</span><span class="free">r</span> <span class="keyword1">choose</span> Suc <span class="skolem">m</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> Suc<span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> <span class="main">(</span><span class="free">r</span> <span class="keyword1">choose</span></span> Suc <span class="skolem">m</span><span class="main">)</span> <span class="main">*</span> <span class="main">(</span>real <span class="free">r</span> <span class="main">-</span> <span class="main">(</span>Suc <span class="skolem">m</span><span class="main">)</span><span class="main">)</span> <span class="main">/</span> <span class="numeral">2</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> <span class="dynamic dynamic">field_simps</span><span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> Suc</span> <span class="main">(</span>Suc <span class="skolem">m</span><span class="main">)</span> <span class="main">/</span> <span class="numeral">2</span> <span class="main">*</span> <span class="main">(</span><span class="free">r</span> <span class="keyword1">choose</span> Suc <span class="main">(</span>Suc <span class="skolem">m</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">cases</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">r</span> <span class="main">≥</span></span> Suc</span> <span class="skolem">m</span><span>"</span><span class="main">)</span><span>
</span><span class="keyword3 command">case</span> True <span class="keyword1 command">with</span> binomial_absorb_comp<span class="main">[</span><span class="operator">of</span> <span class="quoted free">r</span> <span class="quoted"><span class="quoted"><span>"</span>Suc</span> <span class="skolem">m</span><span>"</span></span><span class="main">]</span> <span class="keyword3 command">show</span> <span class="var quoted var">?thesis</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> binomial_absorption mult.commute of_nat_diff of_nat_mult times_divide_eq_left<span class="main">)</span><span>
</span><span class="keyword1 command">qed</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> binomial_eq_0<span class="main">)</span><span>
</span><span class="keyword1 command">finally</span> <span class="keyword3 command">show</span> <span class="var quoted var">?case</span> <span class="keyword1 command">.</span><span>
</span><span class="keyword1 command">qed</span>
</pre>
<p>I can’t help but remark that with Certain Other Proof Assistants,
working out the proof first on paper is standard practice.
Then what value are they getting from their so-called assistant?</p>
<h3 id="an-identity-involving-fibonacci-numbers">An identity involving Fibonacci numbers</h3>
<p>Every time you turn around, the <a href="https://www.techtarget.com/whatis/definition/Fibonacci-sequence">Fibonacci numbers</a>
pop up again:</p>
\[\begin{gather*}
\sum_{k\le m}\binom{n-k}{k} = F_{n+1}
\end{gather*}\]
<p>We’ve seen Fibonacci numbers in a previous post.
Isabelle accepts the recursive definition,</p>
\[\begin{align} F_0 &= 0\\ F_1 &= 1\\ F_{n+2} &= F_n + F_{n+1}, \end{align}\]
<p><a href="/2021/10/13/Fib-example.html">more-or-less verbatim</a>.</p>
<p>We have also seen that when you have to prove something about a recursive function, it’s often best to use the induction rule that Isabelle supplies with your function definition. And that is the case here.</p>
<p>First, we need a couple of trivial lemmas to let us
adjust the upper bound of the sum,
deleting a null term and shifting everything down.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> sum_drop_zero<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span>Suc</span> <span class="free">n</span><span class="main">.</span> <span class="keyword1">if</span></span> <span class="main">0</span><span class="main"><</span><span class="bound">k</span> <span class="keyword1">then</span> <span class="main">(</span><span class="free">f</span> <span class="main">(</span><span class="bound">k</span> <span class="main">-</span> <span class="main">1</span><span class="main">)</span><span class="main">)</span> <span class="keyword1">else</span> <span class="main">0</span><span class="main">)</span> <span class="main">=</span> <span class="main">(</span><span class="main">∑</span><span class="bound">j</span><span class="main">≤</span><span class="free">n</span><span class="main">.</span> <span class="free">f</span> <span class="bound">j</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">n</span><span class="main">)</span> <span class="operator">auto</span>
</pre>
<pre class="source">
<span class="keyword1 command">lemma</span> sum_choose_drop_zero<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span>Suc</span> <span class="free">n</span><span class="main">.</span> <span class="keyword1">if</span></span> <span class="bound">k</span> <span class="main">=</span> <span class="main">0</span> <span class="keyword1">then</span> <span class="main">0</span> <span class="keyword1">else</span> <span class="main">(</span>Suc <span class="free">n</span> <span class="main">-</span> <span class="bound">k</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="main">(</span><span class="bound">k</span> <span class="main">-</span> <span class="main">1</span><span class="main">)</span><span class="main">)</span> <span class="main">=</span><span>
</span><span class="main">(</span><span class="main">∑</span><span class="bound">j</span><span class="main">≤</span><span class="free">n</span><span class="main">.</span> <span class="main">(</span><span class="free">n</span><span class="main">-</span><span class="bound">j</span><span class="main">)</span> <span class="keyword1">choose</span> <span class="bound">j</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">rule</span> trans <span class="main main">[</span><span class="operator">OF</span> sum.cong sum_drop_zero<span class="main main">]</span><span class="main">)</span> <span class="operator">auto</span>
</pre>
<p>Armed with this fact, the identity is easy to prove.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> ne_diagonal_fib<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span><span class="free">n</span><span class="main">.</span> <span class="main">(</span><span class="free">n</span><span class="main">-</span></span><span class="bound">k</span><span class="main">)</span> <span class="keyword1">choose</span></span> <span class="bound">k</span><span class="main">)</span> <span class="main">=</span> fib <span class="main">(</span>Suc <span class="free">n</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">n</span> <span class="quasi_keyword">rule</span><span class="main main">:</span> fib.induct<span class="main">)</span><span>
</span><span class="keyword3 command">case</span> 1 <span class="keyword3 command">show</span> <span class="var quoted var">?case</span> <span class="keyword1 command">by</span> <span class="operator">simp</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> 2 <span class="keyword3 command">show</span> <span class="var quoted var">?case</span> <span class="keyword1 command">by</span> <span class="operator">simp</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>3 <span class="skolem">n</span><span class="main">)</span><span>
</span><span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span>Suc</span> <span class="skolem">n</span><span class="main">.</span> Suc</span> <span class="main">(</span>Suc <span class="skolem">n</span><span class="main">)</span> <span class="main">-</span> <span class="bound">k</span> <span class="keyword1">choose</span> <span class="bound">k</span><span class="main">)</span> <span class="main">=</span><span>
</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span>Suc <span class="skolem">n</span><span class="main">.</span> <span class="main">(</span>Suc <span class="skolem">n</span> <span class="main">-</span> <span class="bound">k</span> <span class="keyword1">choose</span> <span class="bound">k</span><span class="main">)</span> <span class="main">+</span> <span class="main">(</span><span class="keyword1">if</span> <span class="bound">k</span><span class="main">=</span><span class="main">0</span> <span class="keyword1">then</span> <span class="main">0</span> <span class="keyword1">else</span> <span class="main">(</span>Suc <span class="skolem">n</span> <span class="main">-</span> <span class="bound">k</span> <span class="keyword1">choose</span> <span class="main">(</span><span class="bound">k</span> <span class="main">-</span> <span class="main">1</span><span class="main">)</span><span class="main">)</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">rule</span> sum.cong<span class="main">)</span> <span class="main">(</span><span class="operator">simp_all</span> <span class="quasi_keyword">add</span><span class="main main">:</span> choose_reduce_nat<span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> <span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span>Suc</span> <span class="skolem">n</span><span class="main">.</span> Suc <span class="skolem">n</span> <span class="main">-</span> <span class="bound">k</span> <span class="keyword1">choose</span> <span class="bound">k</span><span class="main">)</span> <span class="main">+</span><span>
</span><span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span>Suc <span class="skolem">n</span><span class="main">.</span> <span class="keyword1">if</span> <span class="bound">k</span><span class="main">=</span><span class="main">0</span> <span class="keyword1">then</span> <span class="main">0</span> <span class="keyword1">else</span> <span class="main">(</span>Suc <span class="skolem">n</span> <span class="main">-</span> <span class="bound">k</span> <span class="keyword1">choose</span> <span class="main">(</span><span class="bound">k</span> <span class="main">-</span> <span class="main">1</span><span class="main">)</span><span class="main">)</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> sum.distrib<span class="main">)</span><span>
</span><span class="keyword1 command">also</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">…</span> <span class="main">=</span></span> <span class="main">(</span><span class="main">∑</span><span class="bound">k</span><span class="main">≤</span>Suc</span> <span class="skolem">n</span><span class="main">.</span> Suc <span class="skolem">n</span> <span class="main">-</span> <span class="bound">k</span> <span class="keyword1">choose</span> <span class="bound">k</span><span class="main">)</span> <span class="main">+</span> <span class="main">(</span><span class="main">∑</span><span class="bound">j</span><span class="main">≤</span><span class="skolem">n</span><span class="main">.</span> <span class="skolem">n</span> <span class="main">-</span> <span class="bound">j</span> <span class="keyword1">choose</span> <span class="bound">j</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> sum_choose_drop_zero<span class="main">)</span><span>
</span><span class="keyword1 command">finally</span> <span class="keyword3 command">show</span> <span class="var quoted var">?case</span> <span class="keyword1 command">using</span> 3<span>
</span><span class="keyword1 command">by</span> <span class="operator">simp</span><span>
</span><span class="keyword1 command">qed</span>
</pre>
<h3 id="postscript">Postscript</h3>
<p>As usual, the Isabelle theory is <a href="/Isabelle-Examples/Binomial_Coeffs.thy">available to download</a>.</p>
<p>Knuth notes that we can generalise binomial coefficients so that the top number is real or complex.
This generalisation (accomplished via type classes)
is also available in Isabelle/HOL.</p>
<p>There’s even an <a href="https://nrich.maths.org/7713">introduction to binomial coefficients</a> aimed at younger mathematicians.</p>
Wed, 22 Mar 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/03/22/Binomial_Coeffs.html
https://lawrencecpaulson.github.io//2023/03/22/Binomial_Coeffs.htmlThe semantics of a simple functional language<p>The simplest way to precisely specify the meanings of programming language expressions
is through an <a href="https://en.wikipedia.org/wiki/Operational_semantics">operational semantics</a>.
Such a definition consists of a set of what look like the inference rules
of a logic, stating the conditions under which a given expression
can be reduced to a value, or at least evaluated one step more.
Formally, this sort of specification is an <em>inductive definition</em>,
equipped with an induction principle for proving that a property
holds for all executions.
Such proofs are conceptually trivial—they involve checking
that the property holds
initially and that it is preserved
by each execution step—but are extremely tedious to write out by hand.
Fortunately, they are often trivial with the help of a little automation.
Let’s prove a <a href="https://en.wikipedia.org/wiki/Church–Rosser_theorem">Church–Rosser property</a>:
that expression evaluation always leads to a unique final result.</p>
<h3 id="a-simple-functional-language">A simple functional language</h3>
<p>Our language is insufficient to write an airline reservation system—it isn’t even
Turing-complete—but it is sufficient to illustrate some of the core themes of operational semantics.</p>
<p>Let’s begin with the syntax. An expression can be a Boolean
(true or false), or a natural number given by zero or successor,
or a conditional expression, or an equality test:</p>
<pre class="source">
<span class="keyword1 command">datatype</span> exp <span class="main">=</span> T <span class="main">|</span> F <span class="main">|</span> Zero <span class="main">|</span> Succ <span class="quoted">exp</span> <span class="main">|</span> IF <span class="quoted">exp</span> <span class="quoted">exp</span> <span class="quoted">exp</span> <span class="main">|</span> EQ <span class="quoted">exp</span> <span class="quoted">exp</span>
</pre>
<p>Next we define the operational semantics itself, which takes the form
of a reduction relation (⇛). We use an Isabelle/HOL inductive definition.
The first two rules cover the true and false cases of a conditional expression,
while the third case takes care of a single reduction within the condition.
The fourth rule covers the evaluation of the argument of <code class="language-plaintext highlighter-rouge">Succ</code>.
So this is a <a href="https://en.wikipedia.org/wiki/Operational_semantics#Small-step_semantics">small-step semantics</a>;
in a big-step semantics, every rule would be formulated
to deliver the final result.</p>
<pre class="source">
<span class="keyword1 command">inductive</span> <span class="entity">Eval</span> <span class="main">::</span> <span class="quoted"><span class="quoted"><span>"</span>exp</span> <span class="main">⇒</span> exp</span> <span class="main">⇒</span> bool<span>"</span> <span class="main">(</span><span class="keyword2 keyword">infix</span> <span class="quoted"><span>"</span><span class="keyword1">⇛</span><span>"</span></span> 50<span class="main">)</span> <span class="keyword2 keyword">where</span><span>
</span>IF_T<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>IF</span> T</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span> <span class="main free">⇛</span> <span class="free bound entity">x</span><span>"</span><span>
</span><span class="main">|</span> IF_F<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>IF</span> F</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span> <span class="main free">⇛</span> <span class="free bound entity">y</span><span>"</span><span>
</span><span class="main">|</span> IF_Eval<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free bound entity">p</span> <span class="main free">⇛</span> <span class="free bound entity">q</span> <span class="main">⟹</span> IF</span> <span class="free bound entity">p</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span> <span class="main free">⇛</span> IF</span> <span class="free bound entity">q</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span><span>"</span><span>
</span><span class="main">|</span> Succ_Eval<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free bound entity">x</span> <span class="main free">⇛</span> <span class="free bound entity">y</span> <span class="main">⟹</span> Succ</span> <span class="free bound entity">x</span> <span class="main free">⇛</span> Succ</span> <span class="free bound entity">y</span><span>"</span><span>
</span><span class="main">|</span> EQ_same<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>EQ</span> <span class="free bound entity">x</span> <span class="free bound entity">x</span> <span class="main free">⇛</span> T</span><span>"</span><span>
</span><span class="main">|</span> EQ_S0<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>EQ</span> <span class="main">(</span>Succ</span> <span class="free bound entity">x</span><span class="main">)</span> Zero <span class="main free">⇛</span> F<span>"</span><span>
</span><span class="main">|</span> EQ_0S<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>EQ</span> Zero</span> <span class="main">(</span>Succ <span class="free bound entity">y</span><span class="main">)</span> <span class="main free">⇛</span> F<span>"</span><span>
</span><span class="main">|</span> EQ_SS<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>EQ</span> <span class="main">(</span>Succ</span> <span class="free bound entity">x</span><span class="main">)</span> <span class="main">(</span>Succ <span class="free bound entity">y</span><span class="main">)</span> <span class="main free">⇛</span> EQ <span class="free bound entity">x</span> <span class="free bound entity">y</span><span>"</span><span>
</span><span class="main">|</span> EQ_Eval1<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free bound entity">x</span> <span class="main free">⇛</span> <span class="free bound entity">z</span> <span class="main">⟹</span> EQ</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span> <span class="main free">⇛</span> EQ</span> <span class="free bound entity">z</span> <span class="free bound entity">y</span><span>"</span><span>
</span><span class="main">|</span> EQ_Eval2<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free bound entity">y</span> <span class="main free">⇛</span> <span class="free bound entity">z</span> <span class="main">⟹</span> EQ</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span> <span class="main free">⇛</span> EQ</span> <span class="free bound entity">x</span> <span class="free bound entity">z</span><span>"</span>
</pre>
<p>The remaining six rules concern the evaluation of equality tests.
I specifically designed them to be messy.</p>
<h3 id="rule-inversion">Rule inversion</h3>
<p>The language admits nonsensical terms such as <code class="language-plaintext highlighter-rouge">Succ T</code>, which cannot be reduced to anything.
How do we know that? Intuitively, it’s because there is only one rule for evaluating<code class="language-plaintext highlighter-rouge">Succ</code>;
that rule evaluates the argument, and there is no rule for evaluating <code class="language-plaintext highlighter-rouge">T</code>.
This straightforward reasoning can fortunately be automated.
The following declarations inform Isabelle’s simplifier about the possibilities of
various reductions occurring. In particular, the first three
generate theorems stating that the quoted reductions are impossible.
In other cases, the resulting theorems state conditions under which the reduction can take place,
e.g.</p>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">(Succ ?x ⇛ ?z) = (∃y. ?z = Succ y ∧ ?x ⇛ y)</code></p>
</blockquote>
<pre class="source">
<span class="keyword1 command">inductive_simps</span> T_simp <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>T</span> <span class="main">⇛</span></span> <span class="free">z</span><span>"</span><span>
</span><span class="keyword1 command">inductive_simps</span> F_simp <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>F</span> <span class="main">⇛</span></span> <span class="free">z</span><span>"</span><span>
</span><span class="keyword1 command">inductive_simps</span> Zero_simp <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>Zero</span> <span class="main">⇛</span></span> <span class="free">z</span><span>"</span><span>
</span><span class="keyword1 command">inductive_simps</span> Succ_simp <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>Succ</span> <span class="free">x</span> <span class="main">⇛</span></span> <span class="free">z</span><span>"</span><span>
</span><span class="keyword1 command">inductive_simps</span> IF_simp <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>IF</span> <span class="free">p</span> <span class="free">x</span> <span class="free">y</span> <span class="main">⇛</span></span> <span class="free">z</span><span>"</span><span>
</span><span class="keyword1 command">inductive_simps</span> EQ_simp <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>EQ</span> <span class="free">x</span> <span class="free">y</span> <span class="main">⇛</span></span> <span class="free">z</span><span>"</span>
</pre>
<p>Such declarations are useful in any inductive definition where the conclusions of the rules
allow most of the cases to be excluded on syntactic grounds.
If your proofs seem to require a lot of explicit case analysis,
see whether this sort of declaration could help you.</p>
<h3 id="types-and-type-preservation">Types and type preservation</h3>
<p>Our language has Booleans and natural numbers, so let’s define the corresponding type system.
(It will be simpler than Martin-Löf type theory.)</p>
<pre class="source">
<span class="keyword1 command">datatype</span> tp <span class="main">=</span> bool <span class="main">|</span> num
</pre>
<p>The great thing about operational semantics is its flexibility.
Above, we defined the evaluation of expressions, which is their dynamic behaviour;
now we can define their typing relation, which is static behaviour.
The same techniques work for both.</p>
<p>True and false have the Boolean type, while zero is a number.
<code class="language-plaintext highlighter-rouge">Succ</code> yields a number if its argument does.
For conditional expressions and equality, the use of types has to be consistent.</p>
<pre class="source">
<span class="keyword1 command">inductive</span> <span class="entity">TP</span> <span class="main">::</span> <span class="quoted"><span class="quoted"><span>"</span>exp</span> <span class="main">⇒</span> tp</span> <span class="main">⇒</span> bool<span>"</span> <span class="keyword2 keyword">where</span><span>
</span>T<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">TP</span> T</span> bool</span><span>"</span><span>
</span><span class="main">|</span> F<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">TP</span> F</span> bool</span><span>"</span><span>
</span><span class="main">|</span> Zero<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">TP</span> Zero</span> num</span><span>"</span><span>
</span><span class="main">|</span> IF<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⟦</span><span class="free">TP</span> <span class="free bound entity">p</span> bool</span><span class="main">;</span> <span class="free">TP</span> <span class="free bound entity">x</span> <span class="free bound entity">t</span><span class="main">;</span> <span class="free">TP</span> <span class="free bound entity">y</span> <span class="free bound entity">t</span><span class="main">⟧</span> <span class="main">⟹</span> <span class="free">TP</span> <span class="main">(</span>IF</span> <span class="free bound entity">p</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span><span class="main">)</span> <span class="free bound entity">t</span><span>"</span><span>
</span><span class="main">|</span> Succ<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">TP</span> <span class="free bound entity">x</span> num</span> <span class="main">⟹</span> <span class="free">TP</span> <span class="main">(</span>Succ</span> <span class="free bound entity">x</span><span class="main">)</span> num<span>"</span><span>
</span><span class="main">|</span> EQ<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⟦</span><span class="free">TP</span> <span class="free bound entity">x</span> <span class="free bound entity">t</span><span class="main">;</span> <span class="free">TP</span> <span class="free bound entity">y</span> <span class="free bound entity">t</span><span class="main">⟧</span> <span class="main">⟹</span> <span class="free">TP</span> <span class="main">(</span>EQ</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span><span class="main">)</span> bool</span><span>"</span>
</pre>
<p>Rule inversion for the above lets us reason easility about
the type-checking possibilities for expressions.</p>
<pre class="source">
<span class="keyword1 command">inductive_simps</span> TP_IF <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>TP</span> <span class="main">(</span>IF</span> <span class="free">p</span> <span class="free">x</span> <span class="free">y</span><span class="main">)</span> <span class="free">t</span><span>"</span><span>
</span><span class="keyword1 command">inductive_simps</span> TP_Succ <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>TP</span> <span class="main">(</span>Succ</span> <span class="free">x</span><span class="main">)</span> <span class="free">t</span><span>"</span><span>
</span><span class="keyword1 command">inductive_simps</span> TP_EQ <span class="main">[</span><span class="operator">simp</span><span class="main">]</span><span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>TP</span> <span class="main">(</span>EQ</span> <span class="free">x</span> <span class="free">y</span><span class="main">)</span> <span class="free">t</span><span>"</span>
</pre>
<p><a href="https://en.wikipedia.org/wiki/Subject_reduction"><em>Type preservation</em></a>
claims that the evaluation of an expression does not change its type.
Formally, we state that if <code class="language-plaintext highlighter-rouge">x ⇛ y</code> and <code class="language-plaintext highlighter-rouge">x</code> has some type <code class="language-plaintext highlighter-rouge">T</code>, then <code class="language-plaintext highlighter-rouge">y</code> will have the same type.
Induction on the assumption <code class="language-plaintext highlighter-rouge">x ⇛ y</code> produces 10 gruesome-looking subgoals:</p>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">1. ⋀x y t. TP (IF T x y) t ⟹ TP x t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">2. ⋀x y t. TP (IF F x y) t ⟹ TP y t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">3. ⋀p q x y t. ⟦p ⇛ q; ⋀t. TP p t ⟹ TP q t; TP (IF p x y) t⟧ ⟹ TP (IF q x y) t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">4. ⋀x y t. ⟦x ⇛ y; ⋀t. TP x t ⟹ TP y t; TP (Succ x) t⟧ ⟹ TP (Succ y) t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">5. ⋀x t. TP (EQ x x) t ⟹ TP T t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">6. ⋀x t. TP (EQ (Succ x) Zero) t ⟹ TP F t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">7. ⋀y t. TP (EQ Zero (Succ y)) t ⟹ TP F t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">8. ⋀x y t. TP (EQ (Succ x) (Succ y)) t ⟹ TP (EQ x y) t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">9. ⋀x z y t. ⟦x ⇛ z; ⋀t. TP x t ⟹ TP z t; TP (EQ x y) t⟧ ⟹ TP (EQ z y) t</code></p>
</blockquote>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">10. ⋀y z x t. ⟦y ⇛ z; ⋀t. TP y t ⟹ TP z t; TP (EQ x y) t⟧ ⟹ TP (EQ x z) t</code></p>
</blockquote>
<p>Some courses in operational semantics expect students to be able to carry out
such proofs by hand. But even writing out the subgoals perfectly by hand is next to impossible.
Fortunately they are trivial to prove, with the help of rule inversion.
The Isabelle/HOL proof takes a single line, which executes instantly:</p>
<pre class="source">
<span class="keyword1 command">proposition</span> type_preservation<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛</span></span> <span class="free">y</span><span>"</span></span> <span class="quoted"><span class="quoted"><span>"</span>TP</span> <span class="free">x</span> <span class="free">t</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span>TP</span> <span class="free">y</span> <span class="free">t</span><span>"</span></span><span>
</span><span class="keyword1 command">using</span> assms<span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">x</span> <span class="quoted free">y</span> <span class="quasi_keyword">arbitrary</span><span class="main main">:</span> <span class="quoted free">t</span> <span class="quasi_keyword">rule</span><span class="main main">:</span> Eval.induct<span class="main">)</span> <span class="main">(</span><span class="operator">auto</span> <span class="quasi_keyword">simp</span><span class="main main">:</span> TP.intros<span class="main">)</span>
</pre>
<p>A couple of fine points in the proof:</p>
<ul>
<li>designating the variable <code class="language-plaintext highlighter-rouge">t</code> as arbitrary allows for the type of subexpressions to differ from the type of the top expression</li>
<li>you can give two proof methods to the <span class="keyword1 command">by</span> command</li>
</ul>
<h3 id="values-and-value-preservation">Values and value preservation</h3>
<p>We can interpret the operators of our simple language in terms of the natural numbers.
In particular, true and false denote 1 and zero, respectively. We can also give the semantics
of conditional expressions and equality tests.
This is a trivial example of a <a href="https://en.wikipedia.org/wiki/Denotational_semantics">denotational semantics</a>.</p>
<pre class="source">
<span class="keyword1 command">fun</span> <span class="entity">evl</span> <span class="main">::</span> <span class="quoted"><span class="quoted"><span>"</span>exp</span> <span class="main">⇒</span> nat</span><span>"</span><span>
</span><span class="keyword2 keyword">where</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="free">evl</span> T</span> <span class="main">=</span></span> <span class="main">1</span><span>"</span><span>
</span><span class="main">|</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">evl</span> F</span> <span class="main">=</span></span> <span class="main">0</span><span>"</span><span>
</span><span class="main">|</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">evl</span> Zero</span> <span class="main">=</span></span> <span class="main">0</span><span>"</span><span>
</span><span class="main">|</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">evl</span> <span class="main">(</span>Succ</span> <span class="free bound entity">x</span><span class="main">)</span> <span class="main">=</span></span> <span class="free">evl</span> <span class="free bound entity">x</span> <span class="main">+</span> <span class="main">1</span><span>"</span><span>
</span><span class="main">|</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">evl</span> <span class="main">(</span>IF</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span> <span class="free bound entity">z</span><span class="main">)</span> <span class="main">=</span></span> <span class="main">(</span><span class="keyword1">if</span> <span class="free">evl</span> <span class="free bound entity">x</span> <span class="main">=</span> <span class="main">1</span> <span class="keyword1">then</span> <span class="free">evl</span> <span class="free bound entity">y</span> <span class="keyword1">else</span> <span class="free">evl</span> <span class="free bound entity">z</span><span class="main">)</span><span>"</span><span>
</span><span class="main">|</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">evl</span> <span class="main">(</span>EQ</span> <span class="free bound entity">x</span> <span class="free bound entity">y</span><span class="main">)</span> <span class="main">=</span></span> <span class="main">(</span><span class="keyword1">if</span> <span class="free">evl</span> <span class="free bound entity">x</span> <span class="main">=</span> <span class="free">evl</span> <span class="free bound entity">y</span> <span class="keyword1">then</span> <span class="main">1</span> <span class="keyword1">else</span> <span class="main">0</span><span class="main">)</span><span>"</span>
</pre>
<p>Value preservation is the claim that the evaluation of an expression does not change its value.</p>
<pre class="source">
<span class="keyword1 command">proposition</span> value_preservation<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛</span></span> <span class="free">y</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span>evl</span> <span class="free">x</span> <span class="main">=</span></span> evl <span class="free">y</span><span>"</span><span>
</span><span class="keyword1 command">using</span> assms <span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">x</span> <span class="quoted free">y</span><span class="main keyword3">;</span> <span class="operator">force</span><span class="main">)</span>
</pre>
<p>Here we relate types and values. The value of a Boolean expression is less than 2.</p>
<pre class="source">
<span class="keyword1 command">lemma</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span>TP</span> <span class="free">x</span> <span class="free">t</span><span>"</span></span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">t</span> <span class="main">=</span></span> bool</span><span>"</span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span>evl</span> <span class="free">x</span> <span class="main"><</span></span> <span class="numeral">2</span><span>"</span><span>
</span><span class="keyword1 command">using</span> assms <span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">x</span> <span class="quoted free">t</span><span class="main keyword3">;</span> <span class="operator">force</span><span class="main">)</span>
</pre>
<h3 id="proving-a-churchrosser-property">Proving a Church–Rosser property</h3>
<p>The Church–Rosser theorem concerns the λ-calculus and in effect states that multiple
evaluation routes cannot yield multiple final values. It’s necessary because
in the λ-calculus it’s possible to reduce some expressions in more than one way.
Our language has the same problem. For example, four different rules are applicable
to some expressions of the form <code class="language-plaintext highlighter-rouge">EQ (Succ x) (Succ y)</code>.</p>
<p>Some care is needed when expressing a Church–Rosser property.
The following does not hold:</p>
<pre class="source">
<span class="keyword1 command">lemma</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛</span></span> <span class="free">y</span><span>"</span></span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛</span></span> <span class="free">z</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">∃</span></span><span class="bound">u</span><span class="main">.</span></span> <span class="free">y</span> <span class="main">⇛</span> <span class="bound">u</span> <span class="main">∧</span> <span class="free">z</span> <span class="main">⇛</span> <span class="bound">u</span><span>"</span><span>
</span><span class="keyword1 command">nitpick</span>
</pre>
<p>The counterexample returned by <span class="keyword1 command">nitpick</span> is <code class="language-plaintext highlighter-rouge">IF F F F</code>.
The property fails simply because <code class="language-plaintext highlighter-rouge">F</code> cannot reduce, which is not really what we are worried about here.
To express Church–Rosser properly, we need the transitive closure of the reduction relation.
(We could also have used the built-in transitive closure operator.)</p>
<pre class="source">
<span class="keyword1 command">inductive</span> <span class="entity">EvalStar</span> <span class="main">::</span> <span class="quoted"><span class="quoted"><span>"</span>exp</span> <span class="main">⇒</span> exp</span> <span class="main">⇒</span> bool<span>"</span> <span class="main">(</span><span class="keyword2 keyword">infix</span> <span class="quoted"><span>"</span><span class="keyword1">⇛*</span><span>"</span></span> 50<span class="main">)</span> <span class="keyword2 keyword">where</span><span>
</span>Id<span class="main">:</span> <span class="quoted quoted"><span>"</span><span class="free bound entity">x</span> <span class="main free">⇛*</span> <span class="free bound entity">x</span><span>"</span></span><span>
</span><span class="main">|</span> Step<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free bound entity">x</span> <span class="main">⇛</span></span> <span class="free bound entity">y</span> <span class="main">⟹</span> <span class="free bound entity">y</span> <span class="main free">⇛*</span> <span class="free bound entity">z</span> <span class="main">⟹</span> <span class="free bound entity">x</span> <span class="main free">⇛*</span> <span class="free bound entity">z</span><span>"</span></span>
</pre>
<p>The following lemma is just a warmup.
We show that the type is preserved even over a string of evaluation steps.</p>
<pre class="source">
<span class="keyword1 command">proposition</span> type_preservation_Star<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛*</span></span> <span class="free">y</span><span>"</span></span> <span class="quoted"><span class="quoted"><span>"</span>TP</span> <span class="free">x</span> <span class="free">t</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span>TP</span> <span class="free">y</span> <span class="free">t</span><span>"</span></span><span>
</span><span class="keyword1 command">using</span> assms<span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">x</span> <span class="quoted free">y</span><span class="main">)</span> <span class="main">(</span><span class="operator">auto</span> <span class="quasi_keyword">simp</span><span class="main main">:</span> type_preservation<span class="main">)</span>
</pre>
<p>On the other hand, the following four lemmas are essential.
Each of them transforms a string of evaluation steps into the analogous string of steps
within an argument of some function.
All these proofs are trivial inductions.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> Succ_EvalStar<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛*</span></span> <span class="free">y</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span>Succ</span> <span class="free">x</span> <span class="main">⇛*</span></span> Succ <span class="free">y</span><span>"</span><span>
</span><span class="keyword1 command">using</span> assms <span class="keyword1 command">by</span> <span class="operator">induction</span> <span class="main">(</span><span class="operator">auto</span> <span class="quasi_keyword">intro</span><span class="main main">:</span> Succ_Eval EvalStar.intros<span class="main">)</span>
</pre>
<pre class="source">
<span class="keyword1 command">lemma</span> IF_EvalStar<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">p</span> <span class="main">⇛*</span></span> <span class="free">q</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span>IF</span> <span class="free">p</span> <span class="free">x</span> <span class="free">y</span> <span class="main">⇛*</span></span> IF <span class="free">q</span> <span class="free">x</span> <span class="free">y</span><span>"</span><span>
</span><span class="keyword1 command">using</span> assms <span class="keyword1 command">by</span> <span class="operator">induction</span> <span class="main">(</span><span class="operator">auto</span> <span class="quasi_keyword">intro</span><span class="main main">:</span> IF_Eval EvalStar.intros<span class="main">)</span>
</pre>
<pre class="source">
<span class="keyword1 command">lemma</span> EQ_EvalStar1<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛*</span></span> <span class="free">z</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span>EQ</span> <span class="free">x</span> <span class="free">y</span> <span class="main">⇛*</span></span> EQ <span class="free">z</span> <span class="free">y</span><span>"</span><span>
</span><span class="keyword1 command">using</span> assms <span class="keyword1 command">by</span> <span class="operator">induction</span> <span class="main">(</span><span class="operator">auto</span> <span class="quasi_keyword">intro</span><span class="main main">:</span> EQ_Eval1 EvalStar.intros<span class="main">)</span>
</pre>
<pre class="source">
<span class="keyword1 command">lemma</span> EQ_EvalStar2<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">y</span> <span class="main">⇛*</span></span> <span class="free">z</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span>EQ</span> <span class="free">x</span> <span class="free">y</span> <span class="main">⇛*</span></span> EQ <span class="free">x</span> <span class="free">z</span> <span>"</span><span>
</span><span class="keyword1 command">using</span> assms <span class="keyword1 command">by</span> <span class="operator">induction</span> <span class="main">(</span><span class="operator">auto</span> <span class="quasi_keyword">intro</span><span class="main main">:</span> EQ_Eval2 EvalStar.intros<span class="main">)</span>
</pre>
<p>Finally we reach our destination. The diamond property is not the full
Church–Rosser claim, but it captures the main point:
that if some <code class="language-plaintext highlighter-rouge">x</code> can be reduced either to <code class="language-plaintext highlighter-rouge">y</code> or <code class="language-plaintext highlighter-rouge">z</code> in a single step,
then the evaluation strings can be extended to reunite at some common <code class="language-plaintext highlighter-rouge">u</code>.</p>
<pre class="source">
<span class="keyword1 command">proposition</span> diamond<span class="main">:</span><span>
</span><span class="keyword2 keyword">assumes</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛</span></span> <span class="free">y</span><span>"</span></span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">⇛</span></span> <span class="free">z</span><span>"</span></span> <span class="keyword2 keyword">shows</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">∃</span></span><span class="bound">u</span><span class="main">.</span></span> <span class="free">y</span> <span class="main">⇛*</span> <span class="bound">u</span> <span class="main">∧</span> <span class="free">z</span> <span class="main">⇛*</span> <span class="bound">u</span><span>"</span><span>
</span><span class="keyword1 command">using</span> assms<span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">x</span> <span class="quoted free">y</span> <span class="quasi_keyword">arbitrary</span><span class="main main">:</span> <span class="quoted free">z</span><span class="main">)</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>IF_Eval <span class="skolem">p</span> <span class="skolem">q</span> <span class="skolem">x</span> <span class="skolem">y</span><span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">show</span> <span class="var quoted var">?case</span><span>
</span><span class="keyword1 command">by</span> <span class="operator">simp</span><span class="main keyword3">;</span> <span class="operator">meson</span> F_simp IF_EvalStar T_simp<span class="main">)</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>EQ_SS <span class="skolem">x</span> <span class="skolem">y</span><span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">show</span> <span class="var quoted var">?case</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span><span class="main keyword3">;</span> <span class="operator">meson</span> Eval.intros EvalStar.intros<span class="main">)</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>EQ_Eval1 <span class="skolem">x</span> <span class="skolem">u</span> <span class="skolem">y</span><span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">show</span> <span class="var quoted var">?case</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">auto</span><span class="main keyword3">;</span> <span class="operator">meson</span> EQ_EvalStar1 Eval.intros EvalStar.intros<span class="main">)</span><span class="main keyword3">+</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>EQ_Eval2 <span class="skolem">y</span> <span class="skolem">u</span> <span class="skolem">x</span><span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">show</span> <span class="var quoted var">?case</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">auto</span><span class="main keyword3">;</span> <span class="operator">meson</span> EQ_EvalStar2 Eval.intros EvalStar.intros<span class="main">)</span><span class="main keyword3">+</span><span>
</span><span class="keyword1 command">qed</span> <span class="main">(</span><span class="operator">force</span> <span class="quasi_keyword">intro</span><span class="main main">:</span> Succ_EvalStar Eval.intros EvalStar.intros<span class="main">)</span><span class="main keyword3">+</span>
</pre>
<p>Finally, a nontrivial proof! I’ve tried to make it neat, but it’s
a mess. You could download the
<a href="/Isabelle-Examples/Fun_Semantics.thy">Isabelle theory file</a>
and see if you can do it better.</p>
<h3 id="postscript">Postscript</h3>
<p>There is a myth that you need dependent types to do semantics.
This is ridiculous; the heyday of denotational semantics was the 1970s,
before most people had even heard of dependent types.
Tobias Nipkow and Gerwin Klein have written an entire book,
<a href="http://www.concrete-semantics.org"><em>Concrete Semantics</em></a>,
on how to do semantics in Isabelle/HOL. It has many advanced examples.
You can either <a href="https://link.springer.com/book/10.1007/978-3-319-10542-0">buy a copy</a>
or download it for free.</p>
<p>This is another example from my old MPhil course, <a href="https://www.cl.cam.ac.uk/teaching/2122/L21/">Interactive Formal Verification</a>.</p>
Wed, 08 Mar 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/03/08/Fun_Semantics.html
https://lawrencecpaulson.github.io//2023/03/08/Fun_Semantics.htmlVerifying the binary algorithm for greatest common divisors<p>The <a href="https://en.wikipedia.org/wiki/Euclidean_algorithm">Euclidean algorithm</a>
for the GCD is generally regarded as
one of the first algorithms worthy of the name ––
its main competitor perhaps the sieve of Eratosthenes,
for generating prime numbers.
Euclid’s algorithm requires repeated calculations
of integer remainders, which was a heavy operation on early computers.
(Some provided no hardware to perform multiplication and division.)
One can replace the remainder operation by subtraction.
That algorithm is far too slow, especially if one of the arguments
is much smaller than the other,
but it can be refined to achieve high performance by noting that
any binary computer can efficiently divide by two.
Let’s verify <a href="https://en.wikipedia.org/wiki/Binary_GCD_algorithm">this algorithm</a>,
and along the way see how inductive definitions are done in Isabelle/HOL.</p>
<h3 id="the-binary-gcd-algorithm">The binary GCD algorithm</h3>
<p>The greatest common divisor of two natural numbers satisfies
the following properties:</p>
<ul>
<li>The GCD of $x$ and 0 is $x$.</li>
<li>If the GCD of $x$ and $y$ is $z$, then the GCD of $2x$ and $2y$ is $2z$.</li>
<li>The GCD of $2x$ and $y$ is the same as that of $x$ and $y$ if $y$ is odd.</li>
<li>The GCD of $x$ and $y$ is the same as that of $x-y$ and $y$ if $y\le x$.</li>
<li>The GCD of $x$ and $y$ is the same as the GCD of $y$ and $x$.</li>
</ul>
<p>This system of rules corresponds precisely to an Isabelle/HOL inductive definition. Note that we are defining a 3-argument relation
rather than a 2-argument function.
That’s because frequently more than one of these cases is
applicable, so it is not immediately obvious that they express a
function.</p>
<pre class="source">
<span class="keyword1 command">inductive_set</span> <span class="entity">bgcd</span> <span class="main">::</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span>nat</span> <span class="main">×</span></span> nat <span class="main">×</span> nat<span class="main">)</span> set<span>"</span> <span class="keyword2 keyword">where</span><span>
</span>bgcdZero<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="free bound entity">u</span><span class="main">,</span> <span class="main">0</span></span><span class="main">,</span> <span class="free bound entity">u</span><span class="main">)</span> <span class="main">∈</span></span> <span class="free">bgcd</span><span>"</span><span>
</span><span class="main">|</span> bgcdEven<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⟦</span> <span class="main">(</span><span class="free bound entity">u</span><span class="main">,</span> <span class="free bound entity">v</span><span class="main">,</span> <span class="free bound entity">g</span><span class="main">)</span> <span class="main">∈</span></span> <span class="free">bgcd</span> <span class="main">⟧</span> <span class="main">⟹</span> <span class="main">(</span><span class="numeral">2</span><span class="main">*</span></span><span class="free bound entity">u</span><span class="main">,</span> <span class="numeral">2</span><span class="main">*</span><span class="free bound entity">v</span><span class="main">,</span> <span class="numeral">2</span><span class="main">*</span><span class="free bound entity">g</span><span class="main">)</span> <span class="main">∈</span> <span class="free">bgcd</span><span>"</span><span>
</span><span class="main">|</span> bgcdOdd<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⟦</span> <span class="main">(</span><span class="free bound entity">u</span><span class="main">,</span> <span class="free bound entity">v</span><span class="main">,</span> <span class="free bound entity">g</span><span class="main">)</span> <span class="main">∈</span></span> <span class="free">bgcd</span><span class="main">;</span> <span class="main">¬</span></span> <span class="numeral">2</span> <span class="keyword1">dvd</span> <span class="free bound entity">v</span> <span class="main">⟧</span> <span class="main">⟹</span> <span class="main">(</span><span class="numeral">2</span><span class="main">*</span><span class="free bound entity">u</span><span class="main">,</span> <span class="free bound entity">v</span><span class="main">,</span> <span class="free bound entity">g</span><span class="main">)</span> <span class="main">∈</span> <span class="free">bgcd</span><span>"</span><span>
</span><span class="main">|</span> bgcdStep<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⟦</span> <span class="main">(</span><span class="free bound entity">u</span> <span class="main">-</span></span> <span class="free bound entity">v</span><span class="main">,</span> <span class="free bound entity">v</span><span class="main">,</span> <span class="free bound entity">g</span><span class="main">)</span> <span class="main">∈</span></span> <span class="free">bgcd</span><span class="main">;</span> <span class="free bound entity">v</span> <span class="main">≤</span> <span class="free bound entity">u</span> <span class="main">⟧</span> <span class="main">⟹</span> <span class="main">(</span><span class="free bound entity">u</span><span class="main">,</span> <span class="free bound entity">v</span><span class="main">,</span> <span class="free bound entity">g</span><span class="main">)</span> <span class="main">∈</span> <span class="free">bgcd</span><span>"</span><span>
</span><span class="main">|</span> bgcdSwap<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">⟦</span> <span class="main">(</span><span class="free bound entity">v</span><span class="main">,</span> <span class="free bound entity">u</span><span class="main">,</span> <span class="free bound entity">g</span><span class="main">)</span> <span class="main">∈</span></span> <span class="free">bgcd</span> <span class="main">⟧</span> <span class="main">⟹</span> <span class="main">(</span><span class="free bound entity">u</span><span class="main">,</span> <span class="free bound entity">v</span><span class="main">,</span> <span class="free bound entity">g</span><span class="main">)</span> <span class="main">∈</span></span> <span class="free">bgcd</span><span>"</span>
</pre>
<p>The inductive definition is abstract, but the corresponding
algorithm isn’t hard to see.
If one operand is zero, then return the other;
if both operands are even, then divide by two, obtain the GCD recursively
and then double it;
if only one of the operands is even then divide it by 2;
if both of the operands are odd, then subtract the smaller from the larger. Testing whether an integer is even or odd, and dividing it by two,
is a trivial binary shift.</p>
<h3 id="proving-that-the-algorithm-is-correct">Proving that the algorithm is correct</h3>
<p>We must show that the computed “result”
($g$ in the triple $(x,y,g)$) really is the greatest common divisor.
First we simply prove that it is a common divisor.
The proof is by induction on the relation <code class="language-plaintext highlighter-rouge">bgcd</code>,
which means reasoning separately on each of the five rules shown above.
Note that four of the five cases are trivial enough to be covered
by a single call to <code class="language-plaintext highlighter-rouge">auto</code> at the end, with one case (subtraction)
handled specifically.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> bgcd_divides<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="free">x</span><span class="main">,</span><span class="free">y</span><span class="main">,</span><span class="free">g</span><span class="main">)</span> <span class="main">∈</span></span> bgcd</span> <span class="main">⟹</span> <span class="free">g</span> <span class="keyword1">dvd</span> <span class="free">x</span> <span class="main">∧</span> <span class="free">g</span> <span class="keyword1">dvd</span> <span class="free">y</span><span>"</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">induct</span> <span class="quasi_keyword">rule</span><span class="main main">:</span> bgcd.induct<span class="main">)</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>bgcdStep <span class="skolem">u</span> <span class="skolem">v</span> <span class="skolem">g</span><span class="main">)</span><span>
</span><span class="keyword1 command">with</span> dvd_diffD <span class="keyword3 command">show</span> <span class="var quoted var">?case</span><span>
</span><span class="keyword1 command">by</span> <span class="operator">blast</span><span>
</span><span class="keyword1 command">qed</span> <span class="operator">auto</span>
</pre>
<p>So, it yields a common divisor. Let’s show that it is the greatest.
And here it’s time to stress that <em>greatest</em> refers to <strong>divisibility</strong>,
not magnitude.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> bgcd_greatest<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="free">x</span><span class="main">,</span><span class="free">y</span><span class="main">,</span><span class="free">g</span><span class="main">)</span> <span class="main">∈</span></span> bgcd</span> <span class="main">⟹</span> <span class="free">d</span> <span class="keyword1">dvd</span> <span class="free">x</span> <span class="main">⟹</span> <span class="free">d</span> <span class="keyword1">dvd</span> <span class="free">y</span> <span class="main">⟹</span> <span class="free">d</span> <span class="keyword1">dvd</span> <span class="free">g</span><span>"</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">induct</span> <span class="quasi_keyword">arbitrary</span><span class="main main">:</span> <span class="quoted free">d</span> <span class="quasi_keyword">rule</span><span class="main main">:</span> bgcd.induct<span class="main">)</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>bgcdEven <span class="skolem">u</span> <span class="skolem">v</span> <span class="skolem">g</span> <span class="skolem">d</span><span class="main">)</span><span>
</span><span class="keyword3 command">show</span> <span class="var quoted var">?case</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">cases</span> <span class="quoted"><span class="quoted"><span>"</span><span class="numeral">2</span> <span class="keyword1">dvd</span></span> <span class="skolem">d</span><span>"</span></span><span class="main">)</span><span>
</span><span class="keyword3 command">case</span> True <span class="keyword3 command">thus</span> <span class="var quoted var">?thesis</span> <span class="keyword1 command">using</span> bgcdEven <span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">force</span> <span class="quasi_keyword">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> dvd_def<span class="main">)</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> False<span>
</span><span class="keyword3 command">thus</span> <span class="var quoted var">?thesis</span> <span class="keyword1 command">using</span> bgcdEven<span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> coprime_dvd_mult_right_iff<span class="main">)</span><span>
</span><span class="keyword1 command">qed</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>bgcdOdd <span class="skolem">u</span> <span class="skolem">v</span> <span class="skolem">g</span> <span class="skolem">d</span><span class="main">)</span><span>
</span><span class="keyword1 command">hence</span> <span class="quoted"><span class="quoted"><span>"</span>coprime</span> <span class="skolem">d</span> <span class="numeral">2</span><span>"</span></span><span>
</span><span class="keyword1 command">by</span> <span class="operator">fastforce</span><span>
</span><span class="keyword3 command">thus</span> <span class="var quoted var">?case</span> <span class="keyword1 command">using</span> bgcdOdd<span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">simp</span> <span class="quasi_keyword">add</span><span class="main main">:</span> coprime_dvd_mult_right_iff<span class="main">)</span><span>
</span><span class="keyword1 command">qed</span> <span class="operator">auto</span>
</pre>
<p>As with the previous proof, it’s by induction on the relation we defined,
and most of the cases are trivially solved by <code class="language-plaintext highlighter-rouge">auto</code>.
The case where both $u$ and $v$ are even is verified with separate cases
depending on whether $d$ (which is some other common divisor)
is even or not.</p>
<h4 id="proving-uniqueness-and-existence">Proving uniqueness and existence</h4>
<p>The two results just proved are enough to show that the relation <code class="language-plaintext highlighter-rouge">bgcd</code>
is indeed a function, in the sense that it yields at most one result:</p>
<pre class="source">
<span class="keyword1 command">lemma</span> bgcd_unique<span class="main">:</span><span>
</span><span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="free">x</span><span class="main">,</span><span class="free">y</span><span class="main">,</span><span class="free">g</span><span class="main">)</span> <span class="main">∈</span></span> bgcd</span> <span class="main">⟹</span> <span class="main">(</span><span class="free">x</span><span class="main">,</span><span class="free">y</span><span class="main">,</span><span class="free">g'</span><span class="main">)</span> <span class="main">∈</span> bgcd <span class="main">⟹</span> <span class="free">g</span> <span class="main">=</span> <span class="free">g'</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">meson</span> bgcd_divides bgcd_greatest gcd_nat.strict_iff_not<span class="main">)</span>
</pre>
<p>Our final task is to show that this function is total, that some result
is always determined.
(Strictly speaking, we don’t have an operational semantics,
so this is not quite the termination of an actual algorithm.)
The proof is by complete induction, using the observation that
the GCD of any given pair of values is ultimately determined
by that of a smaller pair of values, possibly with the help
of the swap rule. So when considering the GCD of $a$ and $b$,
the induction will be on their sum.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> bgcd_defined_aux<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">a</span><span class="main">+</span></span><span class="free">b</span> <span class="main">≤</span></span> <span class="free">n</span> <span class="main">⟹</span> <span class="main">∃</span> <span class="bound">g</span><span class="main">.</span> <span class="main">(</span><span class="free">a</span><span class="main">,</span> <span class="free">b</span><span class="main">,</span> <span class="bound">g</span><span class="main">)</span> <span class="main">∈</span> bgcd<span>"</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">induction</span> <span class="quoted free">n</span> <span class="quasi_keyword">arbitrary</span><span class="main main">:</span> <span class="quoted free">a</span> <span class="quoted free">b</span> <span class="quasi_keyword">rule</span><span class="main main">:</span> less_induct<span class="main">)</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>less <span class="skolem">n</span> <span class="skolem">a</span> <span class="skolem">b</span><span class="main">)</span><span>
</span><span class="keyword3 command">show</span> <span class="var quoted var">?case</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">cases</span> <span class="quoted skolem">b</span><span class="main">)</span><span>
</span><span class="keyword3 command">case</span> 0<span>
</span><span class="keyword3 command">thus</span> <span class="var quoted var">?thesis</span> <span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> bgcdZero<span class="main">)</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> <span class="main">(</span>Suc <span class="skolem">b'</span><span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> *<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">a</span> <span class="main">+</span></span> <span class="skolem">b'</span> <span class="main"><</span></span> <span class="skolem">n</span><span>"</span><span>
</span><span class="keyword1 command">using</span> Suc_le_eq add_Suc_right less.prems <span class="keyword1 command">by</span> <span class="operator">presburger</span><span>
</span><span class="keyword3 command">show</span> <span class="var quoted var">?thesis</span><span>
</span><span class="keyword1 command">proof</span> <span class="main">(</span><span class="operator">cases</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">b</span> <span class="main">≤</span></span> <span class="skolem">a</span><span>"</span></span><span class="main">)</span><span>
</span><span class="keyword3 command">case</span> True<span>
</span><span class="keyword3 command">thus</span> <span class="var quoted var">?thesis</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> bgcd.simps le_add1 le_add_diff_inverse less.IH <span class="main main">[</span><span class="operator">OF</span> *<span class="main main">]</span><span class="main">)</span><span>
</span><span class="keyword1 command">next</span><span>
</span><span class="keyword3 command">case</span> False<span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">show</span> <span class="var quoted var">?thesis</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> less.IH <span class="main main">[</span><span class="operator">OF</span> *<span class="main main">]</span> Suc Suc_leI bgcd.simps le_add_diff_inverse less_add_same_cancel2<span>
</span>nle_le zero_less_iff_neq_zero<span class="main">)</span><span>
</span><span class="keyword1 command">qed</span><span>
</span><span class="keyword1 command">qed</span><span>
</span><span class="keyword1 command">qed</span>
</pre>
<p>In the proof above, we reason by cases on whether $b=0$
or alternatively $b = b’+1$ for some $b’$
(where obviously $b’=b-1$, a fact that doesn’t need to be used).
We note that $a+b’<n$, allowing use of the induction hypothesis.
It’s reasonable to ask, why not just do mathematical induction on $b$?
And the answer is, I couldn’t get a proof that way, but maybe you will.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>
<pre class="source">
<span class="keyword1 command">lemma</span> bgcd_defined<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">∃!</span><span class="bound">g</span><span class="main">.</span> <span class="main">(</span><span class="free">a</span><span class="main">,</span> <span class="free">b</span><span class="main">,</span> <span class="bound">g</span><span class="main">)</span> <span class="main">∈</span></span> bgcd</span><span>"</span><span>
</span><span class="keyword1 command">using</span> bgcd_defined_aux bgcd_unique <span class="keyword1 command">by</span> <span class="operator">auto</span>
</pre>
<p>We have finally established that our inductive definition
uniquely identifies a result for every pair of operands.
And as noted above, that result is the GCD.</p>
<pre class="source">
<span class="keyword1 command">theorem</span> bgcd_defined<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">∃!</span><span class="bound">g</span><span class="main">.</span> <span class="main">(</span><span class="free">a</span><span class="main">,</span> <span class="free">b</span><span class="main">,</span> <span class="bound">g</span><span class="main">)</span> <span class="main">∈</span></span> bgcd</span><span>"</span><span>
</span><span class="keyword1 command">using</span> bgcd_defined_aux bgcd_unique <span class="keyword1 command">by</span> <span class="operator">auto</span>
</pre>
<p>This example is based on an assignment set in 2010 for my late,
lamented MPhil course, <a href="https://www.cl.cam.ac.uk/teaching/2122/L21/">Interactive Formal Verification</a>.
The Isabelle theory file <a href="/Isabelle-Examples/Binary_Euclidean_Algorithm.thy">can be downloaded</a>.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>See the comments below for a simplification suggested by YawarRaza7349. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>
Wed, 22 Feb 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/02/22/Binary_GCD.html
https://lawrencecpaulson.github.io//2023/02/22/Binary_GCD.html