Machine Logic is Lawrence Paulson's blog on Isabelle/HOL and related topics.
https://lawrencecpaulson.github.io/
Small 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.htmlAn irrationality proof involving cube roots<p>According to myth, the discovery that √2 was irrational so horrified the students of Pythagoras
that it was kept secret <a href="https://nrich.maths.org/2671">upon pain of death</a>. Its irrationality was thought to be paradoxical
because √2 could be constructed as the hypotenuse of a right triangle,
and therefore definitely “existed”,
while all numbers were assumed to be rational.
A while back, I <a href="/2023/01/18/Sqrt2_irrational.html">formalised a new proof</a>
of the irrationality of √2. Just recently, I stumbled upon an exam question:
to prove the irrationality of ∛2+∛3.
Its proof uses different techniques, but it’s not at all hard.
Why not pause for a moment to prove it for yourself
before looking at the formal treatment below?</p>
<h3 id="the-informal-proof">The informal proof</h3>
<p>Let’s begin by defining $x = \sqrt[3]2+\sqrt[3]3$.
It’s natural to see what happens if we cube both sides.
Multiplying out and collecting the terms on the right hand side, we find that
$x^3 = 5 + 3x\sqrt[3]6$.
But this can’t be right: if $x$ is rational then so is $x^3$,
which equals the right hand side, which must also be rational.
In that case, $\sqrt[3]6$ is a rational number. It obviously isn’t.</p>
<p>Formalising this argument in Isabelle/HOL, we get a nice Isar proof.</p>
<h3 id="the-calculation">The calculation</h3>
<p>We begin by stating the desired claim. A rather obscure feature of Isar syntax
is the ability to make a definition right in the theorem statement.
Any such definitions will be expanded in the final theorem, once we have proved it.</p>
<pre class="source">
<span class="keyword1 command">lemma</span> cuberoot_irrational<span class="main">:</span><span>
</span><span class="keyword2 keyword">defines</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">≡</span> root</span> <span class="numeral">3</span> <span class="numeral">2</span> <span class="main">+</span></span> root <span class="numeral">3</span> <span class="numeral">3</span><span>"</span><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="main">ℚ</span></span><span>"</span>
</pre>
<p>Now we commence the proof. Another Isar fine point: omitting the proof method after the
<code class="language-plaintext highlighter-rouge">proof</code> keyword calls for the default method, which in this case
is to assume the formula, stripped of its initial negation.
In order to obtain the number 5 without complications, we pre-evaluate
the cube roots of 8 and 27.
As in the informal proof, we quickly deduce that the right-hand side is rational.</p>
<pre class="source">
<span class="keyword1 command">proof</span><span>
</span><span class="keyword3 command">assume</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span> <span class="main">∈</span></span> <span class="main">ℚ</span></span><span>"</span><span>
</span><span class="keyword1 command">moreover</span><span>
</span><span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span>root</span> <span class="numeral">3</span> <span class="numeral">8</span> <span class="main">=</span></span> <span class="numeral">2</span><span>"</span> <span class="quoted"><span class="quoted"><span>"</span>root</span> <span class="numeral">3</span> <span class="numeral">27</span> <span class="main">=</span></span> <span class="numeral">3</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="operator">auto</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> xcubed<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="free">x</span><span class="main">^</span></span><span class="numeral">3</span> <span class="main">=</span></span> <span class="numeral">5</span> <span class="main">+</span> <span class="numeral">3</span> <span class="main">*</span> <span class="free">x</span> <span class="main">*</span> root <span class="numeral">3</span> <span class="numeral">6</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> x_def <span class="dynamic dynamic">algebra_simps</span> eval_nat_numeral <span class="quasi_keyword">flip</span><span class="main main">:</span> real_root_mult<span class="main">)</span><span>
</span><span class="keyword1 command">ultimately</span> <span class="keyword1 command">have</span> Q<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="numeral">5</span> <span class="main">+</span></span> <span class="numeral">3</span> <span class="main">*</span></span> <span class="free">x</span> <span class="main">*</span> root <span class="numeral">3</span> <span class="numeral">6</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> Rats_power <span class="quoted"><span class="quoted"><span>‹</span><span class="free">x</span> <span class="main">∈</span></span> <span class="main">ℚ</span></span><span>›</span><span class="main">)</span>
</pre>
<h3 id="a-nested-proof">A nested proof</h3>
<p>We could have proved that $\sqrt[3]6$ is irrational separately,
but we can just as easily embed it in the larger proof.
The argument should be familiar: we write $\sqrt[3]6$ as $a/b$,
the ratio of two coprime integers. We then demonstrate that both $a$ and $b$
are divisible by two. See if you can follow the reasoning in the Isar text below.</p>
<pre class="source">
<span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span>root</span> <span class="numeral">3</span> <span class="numeral">6</span> <span class="main">∉</span></span> <span class="main">ℚ</span><span>"</span><span>
</span><span class="keyword1 command">proof</span><span>
</span><span class="keyword3 command">assume</span> <span class="quoted"><span class="quoted"><span>"</span>root</span> <span class="numeral">3</span> <span class="numeral">6</span> <span class="main">∈</span></span> <span class="main">ℚ</span><span>"</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">obtain</span> <span class="skolem skolem">a</span> <span class="skolem skolem">b</span> <span class="keyword2 keyword">where</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> root <span class="numeral">3</span> <span class="numeral">6</span><span>"</span> <span class="keyword2 keyword">and</span> cop<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>coprime</span> <span class="skolem">a</span> <span class="skolem">b</span><span>"</span></span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">b</span><span class="main">≠</span></span><span class="main">0</span></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> best<span class="main main">)</span> Rats_cases'<span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">(</span><span class="skolem">a</span><span class="main">/</span></span><span class="skolem">b</span><span class="main">)</span><span class="main">^</span></span><span class="numeral">3</span> <span class="main">=</span> <span class="numeral">6</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="operator">auto</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> eq<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">a</span><span class="main">^</span></span><span class="numeral">3</span> <span class="main">=</span></span> <span class="numeral">2</span><span class="main">*</span><span class="numeral">3</span> <span class="main">*</span> <span class="skolem">b</span><span class="main">^</span><span class="numeral">3</span><span>"</span><span>
</span><span class="keyword1 command">using</span> of_int_eq_iff <span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">fastforce</span> <span class="quasi_keyword">simp</span><span class="main main">:</span> <span class="dynamic dynamic">divide_simps</span> <span class="quoted"><span class="quoted"><span>‹</span><span class="skolem">b</span><span class="main">≠</span></span><span class="main">0</span></span><span>›</span><span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> p<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="numeral">2</span> <span class="keyword1">dvd</span></span> <span class="skolem">a</span><span>"</span></span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> coprime_left_2_iff_odd coprime_power_right_iff dvd_triv_left mult.assoc<span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">obtain</span> <span class="skolem skolem">c</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">a</span> <span class="main">=</span></span> <span class="numeral">2</span><span class="main">*</span></span><span class="skolem">c</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="operator">blast</span><span>
</span><span class="keyword1 command">with</span> eq <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="numeral">2</span> <span class="keyword1">dvd</span></span> <span class="skolem">b</span><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> eval_nat_numeral<span class="main">)</span> <span class="main">(</span><span class="operator">metis</span> even_mult_iff even_numeral odd_numeral<span class="main">)</span><span>
</span><span class="keyword1 command">with</span> p <span class="keyword2 keyword">and</span> cop <span class="keyword3 command">show</span> <span class="quoted">False</span><span>
</span><span class="keyword1 command">by</span> <span class="operator">fastforce</span><span>
</span><span class="keyword1 command">qed</span>
</pre>
<h3 id="finishing-up">Finishing up</h3>
<p>We know that the right side of our calculation above must be rational,
although $\sqrt[3]6$ is irrational.
Just a tiny bit more work remains.
We need to show that $3x$ is nonzero as well as rational.
Given that extra fact, the contradiction is found automatically,
thanks to <a href="/2022/04/13/Sledgehammer.html">Sledgehammer</a>.</p>
<pre class="source">
<span class="keyword1 command">moreover</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="numeral">3</span><span class="main">*</span></span><span class="free">x</span> <span class="main">∈</span></span> <span class="main">ℚ</span> <span class="main">-</span> <span class="main">{</span><span class="main">0</span><span class="main">}</span><span>"</span><span>
</span><span class="keyword1 command">using</span> xcubed <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> <span class="quoted"><span class="quoted"><span>‹</span><span class="free">x</span> <span class="main">∈</span></span> <span class="main">ℚ</span></span><span>›</span><span class="main">)</span><span>
</span><span class="keyword1 command">ultimately</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="numeral">3</span> <span class="main">*</span></span> <span class="free">x</span> <span class="main">*</span></span> root <span class="numeral">3</span> <span class="numeral">6</span> <span class="main">∉</span> <span class="main">ℚ</span><span>"</span><span>
</span><span class="keyword1 command">using</span> Rats_divide <span class="keyword1 command">by</span> <span class="operator">force</span><span>
</span><span class="keyword1 command">with</span> Q <span class="keyword3 command">show</span> <span class="quoted">False</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> Rats_diff Rats_number_of add.commute add_uminus_conv_diff diff_add_cancel<span class="main">)</span><span>
</span><span class="keyword1 command">qed</span>
</pre>
<p>Another Isar fine point: note how <code class="language-plaintext highlighter-rouge">moreover</code> is used to collect facts.
Each instance of <code class="language-plaintext highlighter-rouge">moreover</code> records the fact just proved, and this sequence terminates
with <code class="language-plaintext highlighter-rouge">ultimately</code>, when all the recorded facts are made available to the next proof method.
Above, <code class="language-plaintext highlighter-rouge">ultimately</code> delivers two facts (that $\sqrt[3]6$ is irrational and that $3x$
is a nonzero rational) to conclude that $3x\sqrt[3]6$ is irrational.
The point of moreover/ultimately is to reduce our reliance on labels.</p>
<p>The Isabelle theory file is <a href="/Isabelle-Examples/Cbrt23_Irrational.thy">available to download</a>.
You can also check out a much more sophisticated proof,
that <a href="/2022/02/16/Irrationals.html">exponentials are irrational</a>.</p>
Wed, 08 Feb 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/02/08/Cbrt23_Irrational.html
https://lawrencecpaulson.github.io//2023/02/08/Cbrt23_Irrational.htmlOn the infinite<p>One can’t do mathematics without thinking about
<a href="https://plato.stanford.edu/entries/infinity/">infinity</a>.
And yet infinity seems to lead to every sort of paradox.
One of these is <a href="https://plato.stanford.edu/entries/infinity/#ThomLamp">Thomson’s Lamp</a>
,
which is alternately switched on and off
at geometrically decreasing intervals, so that within two minutes
it has been switched on and off infinitely many times: after which, will it be on or off?
Ninety-nine years ago, <a href="https://en.wikipedia.org/wiki/David_Hilbert">David Hilbert</a>
delivered a lecture entitled “On the Infinite”,
which comes down to us <a href="/papers/on-the-infinite.pdf">as an essay</a>.
The famous Hilbert Hotel, with its infinitely many rooms, which even when full
can make space for infinitely many additional guests,
was <a href="https://arxiv.org/abs/1403.0059">apparently described</a>
in this lecture, although Hilbert left it out of his essay.
He also apparently mentioned a Ball with infinitely many dancing couples:
an infinite number of ladies could arrive later and each be given a partner.
I hope that the music was audible.
How can we make sense of all this?</p>
<h3 id="some-remarks-on-reality">Some remarks on reality</h3>
<p>We must immediately distinguish between infinity in physics and in mathematics.
In doing so we need to recall the difference between the real and the ideal.
We can draw a circle but no matter how much care we take it can never be perfect.
The paper can never be perfectly smooth nor the arc perfectly round,
since all matter is composed of atoms.
But we all know what a perfect circle is, though the status of such ideal objects
is a matter for philosophy: for realists such as Gödel, they enjoy independent existence;
for intuitionists, such as <a href="https://en.wikipedia.org/wiki/Arend_Heyting">Heyting</a>,
they exist in our minds alone.
But everyone must surely agree that perfect circles—however “real” we think they are—do not belong to Ken Kunen’s</p>
<blockquote>
<p>“real world” of cows and pigs.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>
</blockquote>
<p>I recently watched a Netflix documentary on Infinity, which prompted today’s post.
Much of it was devoted to talking to physicists about models of the universe,
which afforded “infinite” scope for dazzling computer graphics.
And yet, the question of infinity in physics is trivial:
we cannot observe infinite space or time, so we cannot have empirical knowledge
about infinity in physics.
Much of the discussion was about infinity in various physical theories,
but they are <em>mathematical models</em> of the universe.
Infinities in those models are actually infinities in mathematics.
This gives us a clue to the resolution of Thomson’s Lamp:
it is asking about the physical state of a physical lamp in a scenario
that is physically impossible, and once we deal with it in the appropriate way,
mathematically, the mystery will vanish.</p>
<h3 id="infinity-in-mathematics">Infinity in mathematics</h3>
<p>We’ve seen a foretaste of this topic in my <a href="/2022/08/10/Nonstandard_Analysis.html">previous post</a>
on nonstandard analysis.
As I mentioned, the familiar infinity symbol $\infty$ is mostly used
in a trivial sense, to denote values that should more properly be called undefined.
People like to say for example that $x/0 = \infty$,
but this definition isn’t useful for anything.
(Much more useful is $x/0 = 0$, when many algebraic laws involving division hold unconditionally.)
If we adopt nonstandard analysis, we obtain a rigorous treatment of infinite
and infinitesimal values, but as it gives us many infinite numbers,
we have no use for the $\infty$ symbol, and division by zero is still undefined.</p>
<p><a href="/papers/on-the-infinite.pdf">Hilbert’s essay</a><sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> is rewarding to read.
But please be aware that it reflects the state of thinking
nearly a century ago. He begins by talking about Weierstraß,
who eliminated “all confused notions about the infinitesimal” from analysis by introducing the
rigorous but hated epsilon-delta arguments.
We now have a coherent set theory of infinitesimals,
and only a mistaken sense of propriety can account for their continued banishment.
Hilbert refers to numerous paradoxes,
the most serious of which were <a href="https://plato.stanford.edu/entries/russell-paradox/">Russell’s</a>
and <a href="https://en.wikipedia.org/wiki/Burali-Forti_paradox">Burali-Forti’s</a>.
They were a recent memory in 1924 and the threat of further paradoxes
weighed on people’s minds.
Hilbert praises Cantor’s set theory.
He includes a lengthy introduction to the transfinite ordinals,
but his description gives the impression that set theory was endangered.
Many people are aware that he wrote</p>
<blockquote>
<p>No one shall drive us out of the paradise which Cantor has created for us.</p>
</blockquote>
<p>but who is aware that this paragraph began with these words?</p>
<blockquote>
<p>Wherever there is any hope of salvage…</p>
</blockquote>
<p>Zermelo–Fraenkel set theory would not emerge in its final form until 1930.
Hilbert rather pessimistically concluded,</p>
<blockquote>
<p>Our principal result is that the infinite is nowhere to be found in reality. It neither exists in nature nor provides a legitimate basis for rational thought - a remarkable harmony between being and thought.</p>
</blockquote>
<p>Today we can confidently affirm that infinite objects exist (as ideal mathematical objects)
every bit as much as, say, $\pi$ exists.
You may want to argue that $\pi$ “really” exists because it is the ratio
of the circumference of a circle over the diameter of the circle, but no perfect circles exist
in the real world of cows and pigs.
Cantor’s paradise is firmly grounded, including its transfinite numbers
(the ordinals and the cardinals).
They exist, as do the infinitesimals, every bit as much as $\pi$.</p>
<h3 id="cardinal-numbers-and-cantors-theorem">Cardinal numbers and Cantor’s theorem</h3>
<p>Our understanding of cardinality dates back to
<a href="https://plato.stanford.edu/entries/dedekind-foundations/">Dedekind</a>, who already postulated
the two sets should be regarded as equinumerous if their elements could be placed in
a one-to-one correspondence. Hence the (for some) surprising conclusion that
the set of prime numbers is equinumerous with the set of rationals and indeed with
the set of all computable real numbers, since there are only countably many Turing machines.</p>
<p>Anyone who has read this far has probably come across the Hilbert Hotel
already.
If you haven’t, there are many impressive videos on YouTube. I recommend
<a href="https://youtu.be/OxGsU8oIWjY">this one</a> because it also describes
the momentous arrival of a bus so large that its passengers could not be accommodated,
by <a href="https://en.wikipedia.org/wiki/Cantor's_diagonal_argument">Cantor’s diagonal argument</a>.</p>
<p>Unfortunately, most popular presentations of
<a href="https://platonicrealms.com/encyclopedia/Cantors-Theorem">Cantor’s theorem</a>
start with a countable set and show the existence of an uncountable set,
which may give the mistaken impression that there are only two “levels” of infinity.
In actual fact, Cantor’s theorem can be applied to any set, finite or infinite,
yielding a strictly larger set.
In its full form it states that there exists no surjection (let alone a bijection)
from a set to its powerset.
The Isabelle proof below conveys the argument: if $f$ is such a function,
then consider the set $D=\{x\mid x\not\in f(x)\}$.
Then $D$ cannot be in the range of $f$, and we recognise the diagonal argument.
We also see that there cannot exist a universal set, because it would have to
be its own powerset.</p>
<pre class="source">
<span class="keyword1 command">theorem</span> Cantor<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">∄</span><span class="bound">f</span> <span class="main">::</span> <span class="tfree">'a</span> <span class="main">⇒</span> <span class="tfree">'a</span> set</span><span class="main">.</span> <span class="main">∀</span></span><span class="bound">A</span><span class="main">.</span> <span class="main">∃</span><span class="bound">x</span><span class="main">.</span> <span class="bcardinalsspan> <span class="main">=</span> <span class="bound">f</span> <span class="bound">x</span><span>"</span><span>
</span><span class="keyword1 command">proof</span><span>
</span><span class="keytheir command">assume</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">∃</span></span><span class="bound">f</span> <span class="main">::</span> <span class="tfree">'a</span> <span class="main">⇒</span> <span class="tfree">'a</span> set</span><span class="main">.</span> <span class="main">∀</span><span class="bound">A</span><span class="main">.</span> <span class="main">∃</span><span class="bound">x</span><span class="main">.</span> <span class="bound">A</span> <span class="main">=</span> <span class="bound">f</span> <span class="bound">x</span><span>"</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">obtain</span> <span class="skolem skolem">f</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> set</span><span>"</span></span> <span class="keyword2 keyword">where</span> *<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">∀</span></span><span class="bound">A</span><span class="main">.</span></span> <span class="main">∃</span><span class="bound">x</span><span class="main">.</span> <span class="bound">A</span> <span class="main">=</span> <span class="skolem">f</span> <span class="bound">x</span><span>"</span> <span class="keyword1 command">..</span><span>
</span><span class="keyword1 command">let</span> <span class="var quoted var">?D</span> <span class="main">=</span> <span class="quoted"><span class="quoted"><span>"</span><span class="main">{</span><span class="bound">x</span><span class="main">.</span> <span class="bound">x</span> <span class="main">∉</span></span> <span class="skolem">f</span> <span class="bound">x</span><span class="main">}</span><span>"</span></span><span>
</span><span class="keyword1 command">from</span> * <span class="keyword3 command">obtain</span> <span class="skolem skolem">a</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="var">?D</span> <span class="main">=</span></span> <span class="skolem">f</span> <span class="skolem">a</span><span>"</span></span> <span class="keyword1 command">by</span> <span class="operator">blast</span>
<span class="keyword1 command">moreover</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">a</span> <span class="main">∈</span></span> <span class="var">?D</span> <span class="main">⟷</span></span> <span class="skolem">a</span> <span class="main">∉</span> <span class="skolem">f</span> <span class="skolem">a</span><span>"</span> <span class="keyword1 command">by</span> <span class="operator">blast</span>
<span class="keyword1 command">ultimately</span> <span class="keyword3 command">show</span> <span class="quoted">False</span> <span class="keyword1 command">by</span> <span class="operator">blast</span>
<span class="keyword1 command">qed</span>
</pre>
<p>Ordinary mathematics almost never concerns itself with cardinalities beyond
that of the set of real numbers, but the cardinals truly ascend
into the <a href="https://neugierde.github.io/cantors-attic/">stratosphere</a>.
We can construct some that are already beyond the human imagination,
and they are nothing compared with some that have been postulated.</p>
<h3 id="the-ordinal-numbers">The ordinal numbers</h3>
<p>Thomson’s Lamp is one way to imagine a process that executes infinitely many steps
within a finite time, raising the question of what happens afterwards.
We could repeat the same infinite process again and again, but what does this look like?
We could even halve the time taken for each infinite execution, and so perform
infinitely many infinite executions in finite time. The <em>transfinite ordinals</em> give us a way of labelling these steps. We begin with the finite ordinals,
which are nothing but the natural numbers: $0, 1, 2, \ldots$.
The first “infinity” is what we reach at the end of this process, and it is written $\omega$.
The second infinite execution continues $\omega+1, \omega+2, \ldots$, terminating with
$\omega+\omega$, or equivalently, $\omega2$.
This can continue “forever”,
as Hilbert outlines on page 189 of his paper.
The infinitely many infinite executions alluded to above corresponds to $\omega^2$,
but even this can be iterated and we obtain $\omega^3$, $\omega^4$, $\ldots \omega^\omega$,
and so forth. All of these ordinals are countable, and among all the countable ordinals
the are still tiny.</p>
<p>We are now equipped to solve the problem of Thomson’s Lamp.
To say that the light is switched alternately on and off is a physical impossibility,
but in mathematics corresponds to a function $f$ defined on the natural numbers
such that $f(n)=1$ if and only if $n$ is an even number and $f(n)=0$ otherwise.
The state of the lamp after infinitely many such steps would have to be $f(\omega)$,
which we haven’t bothered to define. We can define it to be whatever we please.
<a href="https://www.urbandictionary.com/define.php?term=BFD">BFD</a>.</p>
<p>One can go further and define addition, subtraction, multiplication and exponentiation
on transfinite ordinals. They can be regarded as abstractions of well ordered sets,
which gives them applications to the problem of program termination in computer science:
you may want to revisit my <a href="/2022/10/26/Multiset-Ordering.html">previous post</a>
on multisets.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>Kenneth Kunen. <em>Set Theory</em>. (North-Holland, 1980), 94. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>David Hilbert. On the infinite. Paul Benacerraf and Hilary Putnam (eds). <a href="https://doi.org/10.1017/CBO9781139171519">Philosophy of Mathematics: Selected Readings</a>. (Cambridge University press, 1984), 183–201. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>
Wed, 01 Feb 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/02/01/On-the-infinite.html
https://lawrencecpaulson.github.io//2023/02/01/On-the-infinite.htmlFormalising a new proof that the square root of two is irrational<p>Recently, somebody shared on Twitter a
<a href="https://theapproximatepresent.tumblr.com/post/51484587425/a-favourite-proof-of-mine-first-demonstrated-to">new proof</a>
of the irrationality of √2. Its claimed advantage is that “it requires no knowledge of mathematics above the definition of what it means for a number to be irrational, and can be written almost in one line.”
These claims are dubious: the
usual proof, which I’ve formalised in a <a href="/2022/05/04/baby-examples.html">previous post</a>,
requires only the natural numbers and
the notion of divisibility.
The “beautiful” proof involves real numbers,
potentially infinite sets and the nontrivial claim that the square root of two actually exists.
Nevertheless, formalising it in Isabelle/HOL is an interesting exercise.
In particular, it illustrates reasoning about the least element of a set. So here we go.</p>
<p><img src="/images/sqrt2-figure.jpg" alt="beautiful proof that sqrt 2 is irrational" width="800" /></p>
<h3 id="a-remark-about-numeric-types">A remark about numeric types</h3>
<p>Before we begin, it’s necessary to explain the meanings of the symbols ℕ, ℤ, ℚ, ℝ
in Isabelle/HOL. They denote sets, not types: namely, they denote the sets of natural numbers,
integers, rationals, real numbers (respectively) as <strong>images</strong> embedded in some larger type.
Here we are mostly going to work within type <code class="language-plaintext highlighter-rouge">real</code>, where ℕ and ℚ
will denote sets of real numbers. Through the magic of <a href="/2022/03/02/Type_classes.html">type classes</a>,
these symbols denote the right set for other types, such as <code class="language-plaintext highlighter-rouge">complex</code>,
<a href="https://www.isa-afp.org/entries/Quaternions.html">quaternions</a>
and any other types (including those yet to be defined) that inherit the necessary structure.</p>
<p>We need to be careful with types here. I’ve used the function <code class="language-plaintext highlighter-rouge">real</code>, which injects natural numbers into type <code class="language-plaintext highlighter-rouge">real</code>. Most numeric coercions can be omitted in Isabelle:
they are inserted automatically.
But things are delicate in this example, so it’s better to be explicit.</p>
<h3 id="defining-r-and-k">Defining $R$ and $k$</h3>
<p>We begin with the theorem statement and the two definitions shown in the blackboard figure:</p>
<pre class="source">
<span class="keyword1 command">proposition</span> <span class="quoted"><span class="quoted"><span>"</span>sqrt</span> <span class="numeral">2</span> <span class="main">∉</span></span> <span class="main">ℚ</span><span>"</span><span>
</span><span class="keyword1 command">proof</span><span>
</span><span class="keyword3 command">define</span> <span class="skolem skolem">R</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">R</span> <span class="main">≡</span> <span class="main">{</span><span class="bound">n</span><span class="main">.</span> <span class="bound">n</span> <span class="main">></span></span> <span class="main">0</span></span> <span class="main">∧</span> real <span class="bound">n</span> <span class="main">*</span> sqrt <span class="numeral">2</span> <span class="main">∈</span> <span class="main">ℕ</span><span class="main">}</span><span>"</span><span>
</span><span class="keyword3 command">define</span> <span class="skolem skolem">k</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">k</span> <span class="main">≡</span> Inf</span> <span class="skolem">R</span><span>"</span></span>
</pre>
<p>Already an error: 0 is a natural number,
but it needs to be excluded from the set $R$ because otherwise $k=0$
and the argument falls apart.</p>
<p>The traditional proof of irrationality begins by claiming
that there are no integers $p$ and $q$ such that $(\frac{p}{q})^2 = 2$.
The proof involves simply showing that both $p$ and $q$ would have to be even numbers,
while every rational number can be written in the form $\frac{p}{q}$ where $p$ and $q$
are coprime.
We could even make a distinction between the rational number $\frac{p}{q}$
and the real quotient $p/q$ in order to prove the theorem in the absence of the reals.</p>
<p>Our proof today begins by finding $p$ and $q$ such that $p/q = \sqrt2$.</p>
<pre class="source">
<span class="keyword3 command">assume</span> <span class="quoted"><span class="quoted"><span>"</span>sqrt</span> <span class="numeral">2</span> <span class="main">∈</span></span> <span class="main">ℚ</span><span>"</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">obtain</span> <span class="skolem skolem">p</span> <span class="skolem skolem">q</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">q</span><span class="main">≠</span></span><span class="main">0</span></span><span>"</span> <span class="quoted"><span class="quoted"><span>"</span>real</span> <span class="skolem">p</span> <span class="main">/</span></span> real <span class="skolem">q</span> <span class="main">=</span> <span class="main">¦</span>sqrt <span class="numeral">2</span><span class="main">¦</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="main">(</span><span class="operator">metis</span> Rats_abs_nat_div_natE<span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">R</span> <span class="main">≠</span></span> <span class="main">{}</span></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> R_def <span class="dynamic dynamic">field_simps</span><span class="main">)</span> <span class="main">(</span><span class="operator">metis</span> of_nat_in_Nats<span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">k</span> <span class="main">∈</span></span> <span class="skolem">R</span><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> Inf_nat_def1 k_def<span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> kR<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span>real</span> <span class="skolem">k</span> <span class="main">*</span></span> sqrt <span class="numeral">2</span> <span class="main">∈</span> <span class="main">ℕ</span><span>"</span> <span class="keyword2 keyword">and</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">k</span> <span class="main">></span></span> <span class="main">0</span></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="quasi_keyword">add</span><span class="main main">:</span> R_def<span class="main">)</span>
</pre>
<p>We have already defined $k$ to be the infimum of $R$, but for this to be useful
we need to show that the set $R$ is nonempty. It then follows that
$k$ belongs to $R$ and satisfies its characteristic properties.</p>
<h3 id="defining-k">Defining $k’$</h3>
<p>The informal proof takes advantage of the typelessness of traditional mathematics
(apologies to those offended) by writing the real number $k(\sqrt2-1)$
and showing it to be a natural number: a seamless transition.
The Isabelle script begins by calling this quantity $x$ and then,
having shown it to belong to ℕ, obtains the corresponding natural number: $k’$.
Looking at blackboard carefully, we can see that a few steps have been skipped.</p>
<pre class="source">
<span class="keyword3 command">define</span> <span class="skolem skolem">x</span> <span class="keyword2 keyword">where</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">x</span> <span class="main">≡</span> real</span> <span class="skolem">k</span> <span class="main">*</span></span> <span class="main">(</span>sqrt <span class="numeral">2</span> <span class="main">-</span> <span class="main">1</span><span class="main">)</span><span>"</span><span>
</span><span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">x</span> <span class="main">∈</span></span> <span class="main">ℕ</span></span><span>"</span><span>
</span><span class="keyword1 command">using</span> <span class="quoted"><span class="quoted"><span>‹</span><span class="main">0</span></span> <span class="main"><</span></span> <span class="skolem">k</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> kR right_diff_distrib' x_def<span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">obtain</span> <span class="skolem skolem">k'</span> <span class="keyword2 keyword">where</span> k'<span class="main">:</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">x</span> <span class="main">=</span></span> real</span> <span class="skolem">k'</span><span>"</span><span>
</span><span class="keyword1 command">using</span> Nats_cases <span class="keyword1 command">by</span> <span class="operator">blast</span><span>
</span><span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">k'</span> <span class="main">></span></span> <span class="main">0</span></span><span>"</span><span>
</span><span class="keyword1 command">using</span> <span class="quoted"><span class="quoted"><span>‹</span><span class="main">0</span></span> <span class="main"><</span></span> <span class="skolem">k</span><span>›</span> k' of_nat_eq_0_iff x_def <span class="keyword1 command">by</span> <span class="operator">fastforce</span>
</pre>
<h3 id="showing-kin-r">Showing $k’\in R$</h3>
<p>We have already shown that $k’>0$, but the nontrivial part of our task
is the third line of the blackboard proof. Breaking it up into stages as shown
keeps the proof justifications simple.
We could skip some steps, when <a href="/2022/04/13/Sledgehammer.html">Sledgehammer</a>
would obligingly find a monster proof.</p>
<pre class="source">
<span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span>real</span> <span class="skolem">k'</span> <span class="main">*</span></span> sqrt <span class="numeral">2</span> <span class="main">=</span> <span class="numeral">2</span> <span class="main">*</span> <span class="skolem">k</span> <span class="main">-</span> <span class="skolem">k</span> <span class="main">*</span> sqrt <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> x_def <span class="dynamic dynamic">algebra_simps</span> <span class="quasi_keyword">flip</span><span class="main main">:</span> k'<span class="main">)</span><span>
</span><span class="keyword1 command">moreover</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span>real</span> <span class="skolem">k'</span> <span class="main">*</span></span> sqrt <span class="numeral">2</span> <span class="main">≥</span> <span class="main">0</span><span>"</span><span>
</span><span class="keyword1 command">by</span> <span class="operator">simp</span><span>
</span><span class="keyword1 command">ultimately</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span>real</span> <span class="skolem">k'</span> <span class="main">*</span></span> sqrt <span class="numeral">2</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> kR<span class="main">)</span><span>
</span><span class="keyword1 command">with</span> R_def <span class="quoted"><span class="quoted"><span>‹</span><span class="main">0</span></span> <span class="main"><</span></span> <span class="skolem">k'</span><span>›</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">k'</span> <span class="main">∈</span></span> <span class="skolem">R</span><span>"</span></span><span>
</span><span class="keyword1 command">by</span> <span there="operator">blast</span>
</pre>
<h3 id="finishing-up">Finishing up</h3>
<p>Once we can show $k’<k$, the result follows by the minimality of $k$.</p>
<pre class="source">
<span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">x</span> <span class="main"><</span></span> real</span> <span class="skolem">k</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="quoted"><span class="quoted"><span>‹</span><span class="main">0</span></span> <span class="main"><</span></span> <span class="skolem">k</span><span>›</span> sqrt2_less_2 x_def<span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword1 command">have</span> <span class="quoted"><span class="quoted"><span>"</span><span class="skolem">k'</span> <span class="main"><</span></span> <span class="skolem">k</span><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> k'<span class="main">)</span><span>
</span><span class="keyword1 command">then</span> <span class="keyword3 command">show</span> <span class="quoted">False</span><span>
</span><span class="keyword1 command">using</span> <span class="quoted"><span class="quoted"><span>‹</span><span class="skolem">k'</span> <span class="main">∈</span></span> <span class="skolem">R</span><span>›</span></span> k_def linorder_not_less wellorder_Inf_le1 <span class="keyword1 command">by</span> <span class="operator">auto</span><span>
</span><span class="keyword1 command">qed</span>
</pre>
<p>The Isabelle theory file is <a href="/Isabelle-Examples/Sqrt2_Irrational.thy">available to download</a>.</p>
<h3 id="postscript">Postscript</h3>
<p>This proof assumes a more sophisticated background theory
than the traditional one, which would have been a problem 30 years ago
when few proof assistants supported the real numbers.
A couple of Isabelle formalisations of the traditional proof
<a href="https://isabelle.in.tum.de/dist/library/HOL/HOL-Examples/Sqrt.html">are available</a>
and it’s up to you to decide which approach is clearer.</p>
<p>A <a href="/2022/06/08/baby-descriptions.html">previous post</a>
discussed reasoning about the least element in the more general context
of descriptions, but this example came from the wild (Twitter, anyway).</p>
Wed, 18 Jan 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/01/18/Sqrt2_irrational.html
https://lawrencecpaulson.github.io//2023/01/18/Sqrt2_irrational.htmlMemories: artificial intelligence at Stanford in the 70s<p>These days, artificial intelligence (AI) is synonymous with neural networks
and machine learning (ML),
but old-timers can remember when symbolic approachs were king:
we now have the wonderful acronym <a href="https://en.wikipedia.org/wiki/GOFAI">GOFAI</a>.
I was at Stanford University from 1977 until 1982 and can vividly recall
the unique atmosphere of the Stanford Artificial Intelligence Laboratory.</p>
<h3 id="ai-in-the-1960s">AI in the 1960s</h3>
<p>My own interest in AI (as a high school student in the USA) arose
from references to some of MIT’s luminaries in Martin Gardner’s
“<a href="https://en.wikipedia.org/wiki/List_of_Martin_Gardner_Mathematical_Games_columns">Mathematical Games</a>” column
in <em>Scientific American</em>
and to a hagiographic article probably in <em>National Geographic</em>,
also focused on MIT.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> (Can’t find it, sorry.)
I also saw a <a href="https://youtu.be/bo4RvYJYOzI">filmed demo</a>
of Terry Winograd’s <a href="https://hci.stanford.edu/~winograd/shrdlu/">SHRDLU</a>.
The dialogue that Winograd carried out with his robot
about blocks in a virtual world gave a strong impression of sentience.
<a href="https://en.wikipedia.org/wiki/SHRDLU">Winograd himself later admitted</a>
that it was largely bogus:</p>
<blockquote>
<p>Pressure was for something you could demo. … I think AI suffered from that a lot, because it led to “Potemkin villages”, things which - for the things they actually did in the demo looked good, but when you looked behind that there wasn’t enough structure to make it really work more generally.</p>
</blockquote>
<p>The film <em>2001: A Space Odyssey</em> had come out in 1968, envisaging
that within 32 years, computers would be capable of carrying out intelligent dialogue
(and committing murder).
One of its scientific advisers was MIT’s
<a href="https://en.wikipedia.org/wiki/Marvin_Minsky">Marvin Minsky</a>,
the de facto leader of the global AI community.</p>
<p>I had the opportunity attend MIT, having been offered an
undergraduate place in 1973.
Bizarrely, given my enthusiasm for AI at that time, I instead took up
an offer from Caltech, where little AI was done.
The year 1973 also saw the highly critical
<a href="http://www.chilton-computing.org.uk/inf/literature/reports/lighthill_report/p001.htm">Lighthill Report</a>
in Britain,
which led to <a href="https://en.wikipedia.org/wiki/AI_winter">severe funding cuts</a> in both the USA and the UK.
MIT philosopher Hubert Dreyfus published his influential
<a href="https://en.wikipedia.org/wiki/Hubert_Dreyfus%27s_views_on_artificial_intelligence">critique of AI</a>
(at least, the prevailing practice of AI).</p>
<h3 id="stanford-ai-lab-1977">Stanford AI Lab, 1977</h3>
<p>In the 1970s, the <a href="https://web.stanford.edu/~learnest/sail/">Stanford AI Lab</a>
(SAIL) was located some distance
from the main campus, in the DC Power Building, a wooden semicircular structure that was slowly decaying. I can’t recall precisely why I used to
go there, since I wasn’t doing AI.
But it was well worth the half hour bike ride. It had a unique vibe.</p>
<p>It had one of the world’s first laser printers,<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup>
called the XGP (Xerox Graphics Printer).
It was the size of a refrigerator and printed
on thermal paper that came in rolls. It cut the paper
into pages using an automatic guillotine, and the last page was typically
a little strip (waste not want not). This printer supported Stanford’s
<a href="https://en.wikipedia.org/wiki/Stanford_Extended_ASCII">modified version</a> of the ASCII character set,
extended with logical and mathematical symbols.
An ancient line printer also supported this character set—its outstanding
quality can be seen in the text of <a href="https://apps.dtic.mil/sti/pdfs/AD0785072.pdf">this report</a>—and somehow the weird green terminals did too.</p>
<p>A PDP-10 ran a bespoke operating system based on an old version of DEC’s
<a href="https://en.wikipedia.org/wiki/TOPS-10">TOPS-10</a>.
Email pioneer <a href="https://en.wikipedia.org/wiki/Mark_Crispin">Mark Crispin</a>
looked after it.
MIT also used a heavily modified version,
the famous <a href="https://en.wikipedia.org/wiki/Incompatible_Timesharing_System">Incompatible Timesharing System</a>.
DEC’s OS presumably had been made available
in source form, unthinkable now.
The advantages of rolling your own OS
had to be weighed against the security updates they didn’t get,
which already in the 1970s left them vulnerable to hacker
attacks from across the ARPAnet. That’s another story.</p>
<p><a href="https://en.wikipedia.org/wiki/John_McCarthy_(computer_scientist)">John McCarthy</a>,
the legendary inventor of Lisp, was the scientific director,
with <a href="https://web.stanford.edu/~learnest/">Lester Earnest</a> as lab manager.
Strangely enough, McCarthy was only 50 when I arrived,
but seemed to have left research behind him,<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup>
and I was left with the impression that his main interest was
the promotion of nuclear power.
But exciting things were happening.
Donald Knuth released the <a href="/papers/Knuth-TEX.pdf">first version of TeX</a>,
written in <a href="https://exhibits.stanford.edu/ai/catalog/np036rx9092">SAIL’s eponymous programming language</a> (a heavily extended Algol).
Early <a href="https://news.stanford.edu/2019/01/16/stanfords-robotics-legacy/">robots</a>
were put through their paces.
Key verification researchers, including Mike Gordon and Robin Milner,
also spent time there.
Robin created <a href="https://apps.dtic.mil/sti/pdfs/AD0785072.pdf">Stanford LCF</a>,
which <a href="/2022/09/28/Cambridge_LCF.html">as described elsewhere</a> later became Edinburgh LCF,
the first modern proof assistant.
Robin returned to give a seminar on ML, which I attended, only to ask an extremely stupid question.</p>
<h3 id="expert-systems">Expert systems</h3>
<p>AI as a field seems particularly prone to schisms.
<a href="http://i.stanford.edu/pub/cstr/reports/cs/tr/81/837/CS-TR-81-837.pdf">Expert systems</a>
work at Stanford was, as far as I could tell,
entirely separate from McCarthy’s world, and not even conducted
at the AI Lab. Expert systems had somehow escaped the gloom
that had fallen over AI as a whole.
<a href="https://en.wikipedia.org/wiki/Mycin">MYCIN</a>, one of the earliest such,
diagnosed bacterial infections and recommended antibiotics
guided by approximately 600 rules that had been obtained by
interviewing doctors.
Entirely different in architecture from modern ML-based systems,
it was similar in that it used a body of knowledge to deal with
new situations.
Crucially, it could <strong>explain its answers</strong> in terms of those rules,
which in turn could be traced back to the doctors themselves.
With machine learning we do not need the laborious manual curation
and can work with vastly larger knowledge sources,
but lose this accountability.</p>
<h3 id="is-theorem-proving-ai">Is theorem proving AI?</h3>
<p><a href="https://en.wikipedia.org/wiki/Logic_Theorist">Logic Theorist</a>,
regarded by many as the very first AI program, was designed
to prove theorems from Whitehead and Russell’s <em><a href="https://www.cambridge.org/gb/academic/subjects/mathematics/logic-categories-and-sets/principia-mathematica-56-2nd-edition">Principia Mathematica</a></em>.
LT proved 38 theorems from the first two chapters.
Two years later, <a href="https://doi.org/10.1147/rd.41.0002">Hao Wang</a>
did rather better:</p>
<blockquote>
<p>the whole list of over 200 theorems of the first five chapters of <em>Principia Mathematica</em> were proved … the actual proving time for over 200 theorems was less than 3 minutes.</p>
</blockquote>
<p>It’s odd that LT is celebrated while the far superior
work of Wang is generally overlooked.
The reason perhaps is that LT was seen as a cognitive simulation,
while Wang merely used an algorithm. As it happens, algorithms often win.</p>
<p>The AI world at that time struggled over issues such as whether
knowledge was best captured procedurally (in the form of executable code),
or declaratively, and if the latter, in what sort of knowledge
representation language. John McCarthy was a fan of first-order logic.
For a time, the whole enterprise of automating logic,
such as the <a href="https://cadeinc.org">CADE conference series</a>, could be regarded as AI.</p>
<p>But human thought is not logical. People are spectacularly bad at logic.
Actually, Hubert Dreyfus said essentially the same thing.
But we have to say that theorem proving is AI,
with so many people applying machine learning to it.</p>
<h3 id="postscript">Postscript</h3>
<p>I was amused to stumble upon
<a href="http://www.chilton-computing.org.uk/inf/literature/reports/lighthill_report/p003.htm">Roger Needham’s response</a>
to the Lighthill Report.</p>
<blockquote>
<p>Artificial Intelligence is a rather pernicious label to attach to a very mixed bunch of activities, and one could argue that the sooner we forget it the better. It would be disastrous to conclude that AI was a Bad Thing and should not be supported, and it would be disastrous to conclude that it was a Good Thing and should have privileged access to the money tap. The former would tend to penalise well-based efforts to make computers do complicated things which had not been programmed before, and the latter would be a great waste of resources. AI does not refer to anything definite enough to have a coherent policy about in this way.</p>
</blockquote>
<p><a href="https://www.cl.cam.ac.uk/archive/ksj21/RogerNeedhamMemoir.pdf">Roger</a>
could always see to the heart of any matter.
“AI” still refers to a very mixed bunch of things.
This thoughtful
<a href="https://doi.org/10.1145/3271625">paper</a>
(also <a href="https://arxiv.org/abs/1707.04327">here</a>)
considers the relationship between the exciting progress
accomplished using neural networks and more classical AI techniques.
And there’s an interesting
<a href="https://projects.csail.mit.edu/films/aifilms/AIFilms.html">survey of early AI</a>.
See also this <a href="https://www.saildart.org/allow/saildart_pix_1974/">1969-1974 Stanford AI Lab photo album</a>.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>MIT’s computing department was at that time called <a href="https://en.wikipedia.org/wiki/MIT_Computer_Science_and_Artificial_Intelligence_Laboratory#Project_MAC">Project MAC</a>: it’s a mystery how they never heard from the McDonald’s legal department. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>But see the comments. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:3" role="doc-endnote">
<p>To be fair, his <a href="https://dblp.org/pid/m/JohnMcCarthy.html">DBLP page</a> shows a continuous record of publications up to 2009. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>
Wed, 11 Jan 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/01/11/AI_at_Stanford.html
https://lawrencecpaulson.github.io//2023/01/11/AI_at_Stanford.htmlMike Gordon and hardware verification<p>In the late 1960s, breakthrough papers by
<a href="https://people.eecs.berkeley.edu/~necula/Papers/FloydMeaning.pdf">Robert W Floyd</a>
and <a href="https://dl.acm.org/doi/10.1145/363235.363259">Tony Hoare</a>
seemed to herald the advent of fully-verified software.
Progress soon slowed however.
It became clear that once you went beyond
a simple flowchart program and had to deal with
the horrors of procedures, variable scopes
and aliasing, things were not so simple after all.
I vividly recall, while still a student at Stanford,
spotting a <a href="https://searchworks.stanford.edu/view/982736">PhD dissertation</a> boldly entitled <em>Hardware Verification</em>,
and thinking that the author (Todd Wagner) had to be out of his mind
to tackle something surely so difficult. Little did I suspect that
I was soon to acquire a friend and colleague,
<a href="https://www.cl.cam.ac.uk/archive/mjcg/">Mike Gordon</a>,
who would make hardware verification a reality, and even make it look easy.</p>
<h3 id="modelling-hardware">Modelling hardware</h3>
<p>Sometime early in the 1980s, after I had joined Mike Gordon’s
group at Cambridge, he popped into my office and left a preprint
entitled something like “A very simple model of CMOS”.
(Though I’ve been unable to locate any publication with a similar title.)
Shall we work together on this?, he asked. In a fateful decision,
I said I would prefer to follow my own path (which at the time meant
the automation of type theory), and it’s intriguing to speculate what
might have happened if I had said yes.
We never published a single joint paper.</p>
<p>Mike’s fundamental discovery, which he had <a href="https://arxiv.org/abs/1806.04002">worked towards methodically</a>
for a decade, was that hardware circuits could be modelled easily
<a href="https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-77.html">using higher order logic</a>.
And his approach worked exactly the same
whether the components being combined for individual transistors
or were built of thousands of transistors.</p>
<p>His idea was simply this:</p>
<ul>
<li>every device modelled by a <strong>relation</strong> on its ports, describing which combinations of port values were possible</li>
<li>no distinction between inputs and outputs</li>
<li>port values could be <strong>anything</strong>: bits, words, vectors, functions (for time-indexed signals)</li>
<li>all in a standard formalism, <strong>higher-order logic</strong></li>
</ul>
<p>Here is a device with four ports. We may imagine that $a$ and $b$ are the
inputs and $c$ and $d$ are the outputs, but this is not modelled.</p>
<p><img src="/images/hw-device.png" alt="hardware device" width="200" /></p>
<p>The simplest devices include power and ground (represented by T and F),
and transistors, such as the following N-channel:</p>
<p><img src="/images/transistor.png" alt="n-channel transistor" width="200" /></p>
<p>Here we see why the relational model is ideal. The formula for this
transistor is $g\to d=s$ and while $g$ is obviously an input,
$d$ and $s$ cannot be called either inputs or outputs.</p>
<h3 id="building-circuits-from-components">Building circuits from components</h3>
<p>The following figure shows two devices connected by a wire.
The connected ports must have the same value,
while the other ports of each device are constrained by that device alone;
we specify this by the conjunction of the two formulas, identifying the
connected ports.
Now suppose that we wish to hide the connected ports (or indeed any ports).
Hiding means the port is no longer available for connection.
It’s accomplished by
existential quantification over the corresponding variable
(since some value certainly “exists”).
Relational composition in mathematics is done in exactly the same way.</p>
<p><img src="/images/compose-devices.png" alt="composing devices" width="800" /></p>
<p>So here is the plan for verifying any hardware device.
We <em>specify</em> it by a formula Spec over the variables $a$, $b$, $c$, $d$
describing the behaviour we want.
We <em>implement</em> it by means of a circuit consisting of simpler components;
from this implementation and the specifications of the simpler components,
we obtain (as described above) a formula Imp for the behaviour delivered by the implementation.
Then the formula Imp$\to$Spec expresses (for $a$, $b$, $c$, $d$)
that every behaviour exhibited by the implementation is allowed by the
specification. Now, just prove it.
We can go on to implement the simpler components in terms of even simpler
ones, for development by refinement.</p>
<h3 id="short-circuits-and-other-issues">Short circuits and other issues</h3>
<p>This modelling approach is obviously simple, but is it too simple?
Mike called Imp$\to$Spec <em>partial correctness</em> (which for software
verification refers to correctness under the assumption of termination)
because it degenerates to triviality in the presence of a <em>short circuit</em>:
an implementation that connects power to ground (because Imp itself would
then be F). While nobody would create a short circuit on purpose, it’s not
hard to imagine a combination of transistors that could produce one for
certain inputs. Given such an input, a real-life implementation would melt,
but at least it wouldn’t deliver the wrong answer!
Mike Fourman suggests addressing this
issue by proving “termination” through some formula of the form $\forall\exists$Imp,
asserting that <strong>every</strong> combination of “inputs” (as we regard them)
can be satisfied by some values on the remaining ports.
An <a href="https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-91.html">early paper</a>
devotes its final section to this issue.</p>
<p>That aside, every hardware designer can easily see that these models
ignore many important design criteria: fan-out (the number of inputs that can be driven by an output), gate delays, capacitance effects, overheating.
Designers must continue to rely on their other tools to deal with those issues,
relying on verification for the logical functionality alone.
Mike’s models have held up well, while more elaborate models
such as
<a href="https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-105.html">Glynn Winskel’s</a>
(incorporating signal strength) seem not to have caught on.</p>
<p>In a <a href="/2022/07/27/Truth_Models.html">previous post</a>
I stated some general principles about modelling.
To repeat: models approximate reality, focussing on some particular aspect
(in this case, logic) that we need to reason about.
Models need to be simple enough that we can understand them, which
also means understanding what they can’t do.</p>
<h3 id="postscript">Postscript</h3>
<p>I have written a <a href="http://doi.org/10.1098/rsbm.2018.0019">scientific biography</a>
of Mike Gordon (also <a href="https://arxiv.org/abs/1806.04002">here</a>)
outlining the history of his work on hardware verification, among much else.
It’s interest that Todd Wagner also suggested using logic, but only
first-order logic. Mike never mentioned Wagner to me and
<a href="https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-91.html">doesn’t cite him</a> either.
And what about software verification?
Mike told me that it’s clearly much more difficult than hardware,
where interfaces are simple and large devices often consist of a few
component types, massively replicated.</p>
Wed, 04 Jan 2023 00:00:00 +0000
https://lawrencecpaulson.github.io//2023/01/04/Hardware_Verification.html
https://lawrencecpaulson.github.io//2023/01/04/Hardware_Verification.htmlMetiTarski: an automatic prover for real-valued special functions<p>Way back when I first discussed interactive theorem proving with Mike Gordon,
nearly 40 years ago, I wondered aloud whether we would ever see the formalisation
of a really deep result in mathematics, such as the prime number theorem.
It happened in 2004, when Jeremy Avigad
<a href="https://doi.org/10.1145/1297658.1297660">formalised</a> an elementary proof of the theorem
(meaning, a proof not reliant on complex analysis) using Isabelle/HOL.
(Paper <a href="https://arxiv.org/abs/cs/0509025">also on ArXiv</a>.)
Jeremy remarked that he had spent an inordinate amount of time proving
trivial inequalities involving the log function;
he wrote a <a href="https://arxiv.org/abs/cs/0601134">proposal</a>
on how such proofs might be automated, and eventually <a href="https://arxiv.org/abs/1404.4410">an implementation</a>.
I had my own ideas, and being lucky enough
to live in an era when research grants could be awarded for crazy ideas,
<a href="https://www.cl.cam.ac.uk/~lp15/Grants/BeyondLinArith/">got funding</a> to provide such automation as an extension to Isabelle/HOL.
But things turned out differently and we ended up with a stand-alone automatic theorem prover,
<a href="https://www.cl.cam.ac.uk/~lp15/papers/Arith/">MetiTarski</a>.</p>
<h3 id="upper-and-lower-bounds-for-special-functions">Upper and lower bounds for special functions</h3>
<p>Much of the groundwork was laid by my capable and dedicated postdoc, Behzad Akbarpour.
It was he, I believe, who stumbled upon <a href="https://rdcu.be/c112I">a paper</a> by César Muñoz and David Lester entitled “Real Number Calculations and Theorem Proving”.
This paper (and not the one with the same name that appeared in the same conference three years later)
outlined an approach to dealing with complicated arithmetic expressions
involving trigonometric functions and whatever, within automated theorem proving.
The idea was to reason about functions such as $\sin$ and $\ln$ in terms of
using interval arithmetic to bound their possible values.
Each occurrence of a function would be replaced by a polynomial approximation
that was either an upper bound or a lower bound.
The paper actually supplied systems of bounds for the most important of the so-called special functions: $\sin$, $\cos$, $\ln$, square roots and exponentials, etc.</p>
<p>Our first experiments were conducted through hand calculations.
We quickly discovered that interval arithmetic was too crude a tool
to solve our target problems (which at first were those suggested by Jeremy).
We needed a more powerful technology.</p>
<h3 id="real-closed-fields">Real-closed fields</h3>
<p>Most people in our field are aware that the theory of linear arithmetic is decidable:
algorithms exist to decide Boolean combinations of inequalities involving
addition and subtraction but with multiplication and division only by constants.
Actually, something much stronger is true: if all variables range over the real numbers,
<strong>arbitrary</strong> logical formulas with unrestricted multiplication and quantification
are decidable. Although the algorithms for this are necessarily hyper-exponential,
the worst case complexity of the decision procedures for linear arithmetic
isn’t great either.</p>
<p>Anyway, we decided to try our luck with some RCF decision procedures.
We first used <a href="https://rdcu.be/c117H">an implementation</a>
by McLaughlin and Harrison of a procedure due to Hörmander,
with <a href="https://rdcu.be/c118Y">some success</a>.
Further work showed the limitations of that decision procedure
because some of our polynomial approximations were of too high degree.
<a href="https://www.usna.edu/CS/qepcadweb/B/QEPCAD.html">QEPCAD</a>,
a stand-alone tool implementing a more powerful decision procedure
(cylindrical algebraic decomposition) gave much better results.
<a href="https://rdcu.be/c119i">We published</a> our findings using QEPCAD a year later (2008).</p>
<h3 id="resolution-theorem-proving">Resolution theorem proving</h3>
<p>As mentioned above, the basic approach was to take a given inequality
involving special functions and then</p>
<ul>
<li>replace function occurrences by polynomials (lower or upper bounds, as appropriate)</li>
<li>to eliminate any occurrences of division</li>
<li>to solve the remaining polynomial inequalities using QEPCAD.</li>
</ul>
<p>One could imagine writing a lot of code to perform these tasks.
Whether through laziness or inspiration, I decided to give the task
to a resolution theorem prover. Surrendering control over the heuristic process
to an automatic procedure has both advantages and drawbacks, but it meant that
the upper/lower bounds could be supplied in the form of axioms;
these could have arbitrary logical conditions to describe their domain of validity.
If a particular problem involved the use of multiple lower bounds for the same function
over partially overlapping domains,
dealing with such complications would be the responsibility of the general automation provided by resolution.
The elimination of division in favour of multiplication can also be performed
simply by stating the mathematical justification in the form of axioms.
And problems could involve logical connectives.</p>
<p>Nevertheless, the resolution prover would need to be augmented with problem specific
knowledge. In particular, arithmetic expressions would need to be simplified to
a canonical form since otherwise the numerous variants of any expression
would be overwhelming. It also need to be integrated with QEPCAD,
but that turned out to be easy: any clause that happened to contain a ground algebraic formula
could be converted into a QEPCAD problem such that if QEPCAD detected a contradiction,
the corresponding literal of that clause would be deleted.
Certain other low-level modifications of the proof process would guide its heuristics
to “zero in” on proofs in our particular domain.</p>
<p>Most resolution theorem provers are giant incomprehensible mountains of C or C++,
but luckily, I was able to use <a href="https://www.gilith.com/software/metis/">Metis</a>,
an exceptionally clean implementation of superposition
by <a href="https://www.gilith.com">Joe Leslie-Hurd</a> and coded in Standard ML.
My team modified Metis more and more over the years, especially with the award
of <a href="https://www.cl.cam.ac.uk/~lp15/Grants/AutoPolyFun/">a follow-up grant</a>.
Another postdoc, James Bridge, implemented some highly ambitious extensions,
including <a href="https://rdcu.be/bpgqJ">case splitting</a>,
which was appropriate because of the large numbers of ground literals
generated by our approach.
We repeatedly extended the set of special functions that we could support
and continued to improve the performance.</p>
<h3 id="examples">Examples</h3>
<p>For starters, let’s look at the proof of $\forall x\,\lvert e^x-1\rvert\le e^{\lvert x \rvert}-1$.
To keep the diagram small, many steps have been skipped, above all those in which
an axiom is used to replace a function by an upper/lower bound.
The absolute value function is dealt with by essentially a case analysis.</p>
<p><img src="/images/Metitarski-example.png" alt="Metitarski example proof" width="850" /></p>
<p>Here are the statements of four more small examples.</p>
<p><img src="/images/MT-examples.png" alt="Metitarski example proof" width="850" /></p>
<p>The generated proofs are typically on the order of hundreds of steps long
and one can work through them by hand, with patience. The reasoning is often
contorted, particularly in cases where multiple bounds need to be used
in order to cover the entire range of a given variable.</p>
<p>The problem set for MetiTarski gradually grew from a few dozen problems suggested by Jeremy
to a collection of hundreds drawn from various specialised handbooks of inequalities.
The main problem set now stands at nearly 900, but thousands of other problems been generated
in applications ranging from <a href="https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-910.pdf">hybrid systems</a>
to <a href="https://dl.acm.org/doi/10.1145/3543670">floating-point algorithms</a>.
The vast majority are solved in under a second, and MetiTarski outputs
a proof in its extended resolution calculus.</p>
<h3 id="continued-fractions">Continued fractions</h3>
<p>After presenting the <a href="https://rdcu.be/c119i">2008 paper</a> at CICM in Birmingham,
I met <a href="https://www.uantwerpen.be/en/staff/annie-cuyt/">Annie Cuyt</a>,
who stated that continued fractions would yield upper/lower bounds
far superior than the ones I was using, which were mostly based on Taylor expansions.
She referred me to her then recent <a href="https://link.springer.com/book/10.1007/978-1-4020-6949-9">Handbook of Continued Fractions</a>
and the <a href="https://dl.acm.org/doi/abs/10.1145/1527286.1527289">associated library</a>
for the computer algebra system Maple.
She was right: continued fraction bounds turned out to be much better
except for sines and cosines, for which Taylor series are best.
The <a href="https://rdcu.be/bpgqp">definitive paper</a> on MetiTarski, published in 2010,
presents the continued fraction bounds.</p>
<h3 id="the-future">The Future?</h3>
<p>I perhaps naïvely imagined that the capability to solve problems of the sort shown here
would have numerous applications. There have been a few, but MetiTarski has definitely
not caught on the way Isabelle has. Its most serious limitation perhaps
is that only a few variables can be allowed. This limitation is caused by
the RCF solvers; Mathematica and Z3 can be substituted for QEPCAD, each with their own
benefits and drawbacks.
I also had the idea of trying to integrate MetiTarski with Isabelle.
I have <a href="https://www.isa-afp.org/entries/Special_Function_Bounds.html">verified</a> all the upper and lower bounds using Isabelle.
Nevertheless, integrating the two systems would involve an enormous amount of work,
and the benefits would not be clear.</p>
<p>I still hope that somebody will find a terrific application of this technology.</p>
<p><em>Acknowledgement</em>.
My thanks to the <a href="https://www.ukri.org/councils/epsrc/">EPSRC</a> for funding this research.
It’s a pity that this sort of research doesn’t seem to attract funding any more.
And I’m grateful to my numerous colleagues who contributed so much.</p>
Wed, 21 Dec 2022 00:00:00 +0000
https://lawrencecpaulson.github.io//2022/12/21/MetiTarski.html
https://lawrencecpaulson.github.io//2022/12/21/MetiTarski.htmlThoughts on user interfaces for theorem provers<p>The era of the modern user interface can be dated from 1973, when the legendary
<a href="https://www.parc.com">Palo Alto Research Center</a> (PARC) announced the
<a href="https://www.computerhistory.org/revolution/input-output/14/347">Xerox Alto</a>.
Its unique combination of windows, icons, menus and a pointer (i.e. mouse)
would eventually become ubiquitous.
Suddenly everybody could master a computer, just as the rapidly shrinking cost of processors
put one on everybody’s desk.
When I joined the world of interactive theorem proving in 1982, there was much talk
how verification would be easy if only implementors would adopt WIMP interfaces.
Specific suggestions were made: above all, to let people select a subexpression
and a rewrite rule in order to transform it.
This is actually a dumb idea, since the computer can match rewrite rules to subexpressions
automatically and apply them a thousand times per second.
Verification is hard because specifications can be complex,
formal proofs tend to be extremely long
and the formalisation of intuitive mathematical ideas often requires great ingenuity.
It’s not obvious what a mouse can do for you here.
Forty years on, we have a clearer idea what a good user interface can do for verification,
but the situation is by no means settled.</p>
<h3 id="lcf-and-its-metalanguage">LCF and its metalanguage</h3>
<p>Robin Milner’s key insight in his design of Edinburgh LCF—as noted <a href="/2022/09/28/Cambridge_LCF.html">previously</a>—was that no fixed
set of commands could offer an adequate user experience.
Formal proofs tended to include “common patterns of inferences”
that couldn’t easily be captured by any fixed command set.
Hence, interaction with LCF should take place through a fully fledged programming language,
which Robin called ML to abbreviate “metalanguage”.
This metalanguage could itself be seen as a kind of user interface.</p>
<p>Actual interaction with LCF and its descendants such as HOL involved the crudest possible
user interface: a split <a href="https://en.wikipedia.org/wiki/Emacs">Emacs</a> window
with the top pane containing the proof being developed
and the bottom pane a UNIX shell running the theorem prover.
People wrote Emacs macros to streamline the step of copying material from the proof
into the prover and executing it.
Such habits persisted even after the
<a href="https://en.wikipedia.org/wiki/X_Window_System">X Window System</a> became available:
I can still remember Mike Gordon allowing a single Emacs window to take up his entire screen
(and he liked really big screens).
We got a lot of criticism from people who insisted that we should be using WIMP
ideas much more.</p>
<p>I have even heard people claim that doing a machine proof
should resemble playing a computer game. This is absolutely the wrong metaphor.
The killer apps of the modern WIMP interface involve the creation of <strong>documents</strong>:
spreadsheets and word processors are as valuable to Microsoft as Windows is.
User interaction with a proof assistant must likewise yield a document, namely a proof script.
This script needs to be at least maintainable, if not actually legible,
with no requirement to spend countless hours playing through the “game” all over again.</p>
<h3 id="proof-general">Proof General</h3>
<p><a href="https://proofgeneral.github.io">Proof General</a>, by <a href="https://homepages.inf.ed.ac.uk/da/">David Aspinall</a>,
is essentially a beefed up version of the Emacs interaction model outlined above.
The top pane holds a proof script while the bottom pane holds a running prover process.
The user can step through the proof script by clicking repeatedly on the “forward” button;
the cursor indicates the current location in the proof, which is actually executed below.
Crucially, there is also a “back” button, through which any step (including declarations)
can be undone. An internal protocol communicates between Proof General and the prover.
Access to other prover features can also be provided through menus.</p>
<p>The name Proof General emphasises that this interface is intended to work
with a variety of proof assistants. For years it was the only way
to use Isabelle, until jEdit came along.
It still supports Coq and has in the past supported a dozen other tools.</p>
<h3 id="isabellejedit">Isabelle/jEdit</h3>
<p>Support for Isabelle within Proof General was possible through the work of Makarius Wenzel,
whose structured proof language (Isar) required considerable sophistication from the interface.
An Isar text is not a list of commands but a structured document,
which for its execution requires the maintenance of certain state variables
that affect the display. These typically include the previous claim or possibly
a series of claims that have just been proved and are being supplied to the next proof.
Makarius eventually decided that Emacs was not the right basis for his vision of interaction.</p>
<p><a href="https://rdcu.be/c1xBk">Isabelle/jEdit</a> can be puzzling to a new user because, when you open a document,
nothing seems to be happening.
In fact, the entire visible proof text will have been given to Isabelle and processed.
As you edit it, it is reprocessed almost instantaneously, and with considerable parallelism.
It’s quite possible for an entire theory file to be processed
with the exception of a few lines need more time;
it is essential to check that all of them terminate!</p>
<p>An Isabelle/jEdit session offers a number of panes giving access to the prover state,
the theory structure and a variety of search/diagnostic tools.
It’s particularly productive in situations where you have a series of similar proofs
and can paste in chunks of copied material,
which is quickly checked and any errors flagged.
It also copes well with maintenance of existing proofs, where making a proposed change
at the top of a file immediately flags up all the places that need to be corrected,
and you can instantly jump from one to the next.</p>
<p>A <a href="https://rdcu.be/c1xIv">more recent article</a> by Makarius covers later
developments, including <a href="https://rdcu.be/c1xRF">Isabelle/Naproche</a>, where you do mathematics
with an English-like specification language, processed via jEdit.</p>
<h3 id="the-future">The future?</h3>
<p>Although early suggestions about pointing at subexpressions to rewrite them
were off target, recent advances in machine learning could lead to a useful version
of this idea. I would like to see a user interface that combined pointing
with a request expressed in natural language:</p>
<ul>
<li>“How can I move this variable outside the brackets?”</li>
<li>“Don’t these two occurrences of <em>x</em> cancel?”</li>
<li>“How can I make the indexing of these two summations match up?”</li>
<li>“How can I show that this function is continuous?”</li>
</ul>
<p>The reply might itself be in natural language, suggesting a proof strategy,
or perhaps it could be bit of proof script, or a skeleton.
AI-powered proof completion, analogous to
<a href="https://github.blog/2022-06-21-github-copilot-is-generally-available-to-all-developers/">GitHub Copilot</a>,
would make life much easier for us.
And there would be no need to trust any auto-completed material,
since it would all be checked by Isabelle.</p>
Wed, 14 Dec 2022 00:00:00 +0000
https://lawrencecpaulson.github.io//2022/12/14/User_interfaces.html
https://lawrencecpaulson.github.io//2022/12/14/User_interfaces.html