Day20_translating.tex
How do we go from a proof in Coq to something we might write on paper, or even show to another person? That is, how do we take a formal proof with tactics, like:
Lemma complement_involutive : forall (b : base),
complement (complement b) = b.
Proof.
intros b. destruct b eqn:E.
- reflexivity.
- reflexivity.
- reflexivity.
- reflexivity.
Qed.
And generate a careful "paper" proof that a human might want to look at?
Theorem: complement
is involutive, i.e., $\forall b,~ \texttt{complement}(\texttt{complement}(b)) = b$.
Proof: Let a base $b$ be given; we go by cases on $b$.
($b = C$) We compute: $$\begin{array}{cl} & \texttt{complement}(\texttt{complement}(C)) \\ = & \texttt{complement}(G) \\ = & C \\ \end{array}$$
($b = G$) Similarly, $\texttt{complement}(\texttt{complement}(G)) = \texttt{complement}(C) = G$.
($b = A$) Similarly, $\texttt{complement}(\texttt{complement}(A)) = \texttt{complement}(T) = A$.
($b = T$) Similarly, $\texttt{complement}(\texttt{complement}(T)) = \texttt{complement}(A) = T$.
QED
In the long term, you'll want to be able to write proofs without any reference to Coq or tactics at all. In the near term, however, it'll be helpful to make explicit reference to the formal proof techniques you already know. The core ideas from formal proof are directly portable to an informal, paper-proof setting; many tactics have more or less direct translations.
Jewish prayer books often come with three kinds of text: the Hebrew text, its translation into English, and one more thing: a transliteration of the Hebrew into English phonetics. Transliteration lets those who can't read Hebrew sing along, even if they don't know what they're saying.
We are in the business of translation, not transliteration. There is no direct, one-to-one mapping of Coq concepts to informal proof, and Coq tactics do not belong in an informal proof. Your proof should not be a description of what happens to the context or goal, but rather some rigorous prose that should convince your readers.
We'll go through five proofs that we've done before in Coq, talking about how to translate from Coq tactics to proofs. In addition to what we show here, you should consider using the how to prove it sheet as a guide.
Unless we've defined it on paper, the definitions we're reasoning
about are the ones we gave in Coq. You're free to use whatever lemmas
we've proved (other than the one you might be translating, naturally),
but it's not okay to assert that, say, $n + S m = S (n + m)$ by
definition. That equality holds, but only because we proved it---with
plus_n_Sm
, so be sure to reference that lemma when you do that
reasoning.
If you're not sure if your reasoning is valid, please just ask!
From day 11:
Theorem trans_eq : forall (X:Type) (n m o : X),
n = m -> m = o -> n = o.
Proof.
intros X n m o eq1 eq2. rewrite -> eq1. rewrite -> eq2.
reflexivity. Qed.
Theorem: Equality is transitive, i.e., $\forall n m o, n = m \wedge m = o \Rightarrow n = o$.
Translated proof: Let $n$, $m$, and $o$ be given such that $n = m$ and $m = o$. We must show that $n = o$. But since $n = m$ by our first assumption, it suffices to show $m = o$---which we have immediately by our second assumption. QED
More idiomatic proof: Let $n$, $m$, and $o$ be given such that $n = m$ and $m = o$. We have to prove that $n = o$. Substituting $o$ for $m$ in the first equation yields $n = o$, as desired. QED
Coq manages your context and goal for you. In an informal proof, the reader will manage their own context and goal---but you should help them. Notice how we state the goal. It's often helpful to restate the goal every time it appears or changes.
intros
)Informal proofs manipulate propositions in different ways than they talk about variables.
First, note how intros
corresponds to "let such-and-such be given
such that so-and-so", where the "such-and-such" are the variables and
the "so-and-so" are any properties about them.
Second, note how we name the variables, but omit the type (it could be anything, so it's not necessarily worth mentioning). We also leave the assumptions anonymous, using the order they were mentioned rather than names.
rewrite
, apply
)The first proof follows the logic in Coq closely, using backward reasoning ("it suffices to show"). The second proof works by forward reasoning, manipulating the $n = m$ assumption directly.
It's nice to let your readers know when you're done. Writing QED or $\square$ at the end of the proof is helpful. It's also nice to use language that recalls the goal to the reader ("as desired").
complement
is involutiveFrom day 12:
Lemma complement_involutive : forall (b : base),
complement (complement b) = b.
Proof.
intros b. destruct b eqn:E.
- reflexivity.
- reflexivity.
- reflexivity.
- reflexivity.
Qed.
Theorem: complement
is involutive, i.e., $\forall b,~ \texttt{complement}(\texttt{complement}(b)) = b$.
Proof: Let a base $b$ be given; we go by cases on $b$.
($b = C$) We compute: $$\begin{array}{cl} & \texttt{complement}(\texttt{complement}(C)) \\ = & \texttt{complement}(G) \\ = & C \\ \end{array}$$
($b = G$) Similarly, $\texttt{complement}(\texttt{complement}(G)) = \texttt{complement}(C) = G$.
($b = A$) Similarly, $\texttt{complement}(\texttt{complement}(A)) = \texttt{complement}(T) = A$.
($b = T$) Similarly, $\texttt{complement}(\texttt{complement}(T)) = \texttt{complement}(A) = T$.
QED
Not a lot would make this more idiomatic. A mathematician might abbreviate the last three cases even more, writing "similar" or "as for $C$, mutatis mutandis". (Mutatis mutandis is Latin for "changing that which needs to be changed", which is... not wrong, but not always helpful.)
destruct
)Case analysis in proofs aligns neatly with Coq's destruct
tactic. One "goes by cases on $b$" or "by cases on how $b$ was
formed". If we were to test whether or not a number was even, (i.e.,
destruct (evenb n)
), we might say, "by cases on whether or not $n$
is even".
simpl
, unfold
, fold
, reflexivity
)Coq has a variety of tactics for computation... but that's about holding Coq's symbolic hand. Humans know what you mean much more clearly.
I particularly like the "chained equations" style used in this proof: start with a complex term, and then slowly rewrite to the thing you're interested in. Just be sure to show appropriate size steps, changing only one thing at a time in an equation.
Theorem plus_n_O : forall n:nat, n = n + 0.
Proof.
intros n. induction n as [| n' IHn'].
- (* n = 0 *) reflexivity.
- (* n = S n' *) simpl. rewrite <- IHn'. reflexivity. Qed.
Theorem: $\forall n \in \mathbb{N}, n = n + 0$
Proof: By induction on $n$.
($n = 0$) We have $0 = 0 + 0$ immediately.
($n = S(n')$) We must show that $S(n') = S(n') + 0$; our IH is that $n' = n' + 0$. We compute:
$$\begin{array}{rlr} & S(n') + 0 &\\ = & S(n' + 0) &\\ = & S(n') & \text{by IH} \\ \end{array}$$
QED
induction
)Induction in informal proof more or less follows the approach in Coq. Just like in Coq, it's quite common to not bother introducing a variable you're about to do induction on.
It's not in general necessary to use outlines, though I think they make for clear proofs. In any inductive case, it's important that early on you (a) state your goal, and (b) state your IH.
It's also important that you explicitly call out your IH when you use it. It helps us for grading, but it's also signaling a key moment in your proof.
Finally, notice that we write $n = S(n')$, but it's just as well to write $n = 1+n'$ or $n=n'+1$.
double
is injective
Theorem double_injective : forall n m,
double n = double m ->
n = m.
Proof.
intros n. induction n as [| n'].
- intros m eq. simpl in eq. destruct m as [| m'].
+ reflexivity.
+ discriminate eq.
- intros m eq. simpl in eq. destruct m as [| m'].
+ discriminate eq.
+ simpl in eq. injection eq as eq'. apply IHn' in eq'. rewrite eq'. reflexivity.
Qed.
Theorem: double
is injective, i.e., $\forall n m \in \mathbb{N},
\mathit{double}(n) = \mathit{double}(m) \Rightarrow n = m$.
Proof: By induction on $n$, leaving $m$ general.
($n = 0$) Suppose that $0 = \mathit{double}(m)$ for some $m$; we must show that $m$ is 0. Since $m \in \mathbb{N}$, we have $m = 0$ or $m = S(m')$ for some $m'$. In the former case we have $0 = m$ immediately. The latter case is impossible---we'd have $\mathit{double}(S(m')) = S(S(\mathit{double}(m'))) = 0$, which is impossible.
($n = S(n')$) We must show that $S(n') = m$ given that $S(S(\mathit{double}(n'))) = \mathit{double}(m)$. Our IH says that for any $m'$, if $\mathit{double}(n') = \mathit{double}(m')$ then $n' = m'$.
By cases on $m$.
($m = 0$) Contradictory: we would have $S(S(\mathit{double}(n'))) = \mathit{double}(m) = \mathit{double}(0) = 0$.
($m = S(m')$) We must show that $S(n') = S(m')$. We have $S(S(\mathit{double}(n'))) = \mathit{double}(S(m')) = S(S(\mathit{double}(m')))$.
It must be the case that $\mathit{double}(n') = \mathit{double}(m')$. We can therefore apply the IH (at $m'$) to find that $n' = m'$, and so $S(n') = S(m')$.
QED.
destruct
)Not every case needs outlines. The base case considers both possibilities for $m$, but keeps things short. The inductive case goes into more detail, but it could have dropped the outline too.
Continuing to outline is nice when there's a lot of structure in each case, but if some cases are simple (as is the case here), it's often better to keep it short.
generalize dependent
, intros
or the lack thereof)First, notice how we vary the IH: we simply say what we want to leave general. We introduce $m$ and the assumption explicitly in the base case, but less so in the inductive case. We are careful to state the general IH, though. Furthermore, we have the IH quantify over a variable name that suggests what we'll be doing later: applying the IH at $m'$.
Coq automatically infers instantiations for many of our quantifiers, but it's polite to help your readers out little when you can.
injection
, discriminate
, inversion
)Our proof freely talks about the consequences of various equalities: $0 = S(S(\dots))$ being contradictory in the base case, or canceling pairs of successors in the inductive case.
But, it's important to be careful with the phrase "it must be case": don't say it if isn't well and truly clear that it must be the case! Avoid words like "obvious" or "clearly": if it's not clear to your reader, they'll just be annoyed.
In_map_iff
From day 15:
Lemma In_map_iff :
forall (A B : Type) (f : A -> B) (l : list A) (y : B),
In y (map f l) <->
exists x, f x = y /\ In x l.
Proof.
intros A B f l y. split.
{ induction l as [|x l' IHl'].
- simpl. intros [].
- simpl. intros [H | H].
+ exists x. split.
* apply H.
* left. reflexivity.
+ assert (H' : exists x', f x' = y /\ In x' l').
{ apply IHl'. apply H. }
destruct H' as [x' [H1 H2]].
exists x'. split.
* apply H1.
* right. apply H2. }
{ intros [x [H1 H2]]. induction l as [|x' l' IHl'].
- destruct H2.
- simpl. destruct H2 as [Heq | Hin].
+ left. rewrite Heq. apply H1.
+ right. apply IHl'. apply Hin. }
Qed.
Theorem: $y$ is in the list $\texttt{map}(f, l)$ iff there exists some $x$ in $l$ such that $f(x) = y$.
Proof: We prove each direction separately.
($\Rightarrow$) Suppose $y$ is in the list $\texttt{map}(f, l)$; we must show that $\exists x, f(x) = y$ and $x$ is in $l$.
By induction on $l$.
($l = \texttt{[]}$) Contradictory: $\texttt{map}(f, \texttt{[]}) = \texttt{[]}$, and there is no $y$ in $\texttt{[]}$.
($l = (z :: l')$) We have $y$ in $\texttt{map}(f, z :: l')$. We must find some $x$ in $z :: l'$ such that $f(x) = y$. Our IH is that such an $x$ exists if $y$ is in $\texttt{map}(f, l')$.
We have $\texttt{map}(f, z :: l') = f(z) :: \texttt{map}(f, l')$. There are two cases:
($y = f(z)$) We choose $z$ itself as our $x$, since $z$ is in $z :: l'$ and $f(z) = y$.
($y$ is in $\texttt{map}(f, l')$) Here, our IH gives us an $x$ in $l'$ such that $f(x) = y$. But if $x$ is in $l'$, then $x$ is also in $z :: l'$, and we are done.
($\Leftarrow$) Suppose there is some $x$ in $l$ such that $f(x) = y$. We prove that $y$ is in $\texttt{map}(f,l)$ by induction on $l$.
($l = \texttt{[]}$) Contradictory: there's no way to have any $x$ in the empty list.
($l = z :: l'$) We have $x$ in $l = z :: l'$ and $f(x) = y$; we must show that $y$ is in $\texttt{map}(f, z :: l')$. Our IH says that if $x$ is in $l'$, then $y$ is in $\texttt{map}(f, l')$. There are two cases:
($x = z$) We have $\texttt{map}(f, z :: l') = \texttt{map}(f, x :: l') = f(x) :: \texttt{map}(f, l') = y :: \texttt{map}(f, l')$, so $y$ is in $\texttt{map}(f, z :: l')$ as desired.
($x$ is in $l'$) In this case, our IH says that $y$ is in $\texttt{map}(f, l')$, and so it must also be in $f(z) :: \texttt{map}(f, l')$.
QED.
I prefer to use []
over $\mathit{nil}$, but both are good. Notice
how I write $\texttt{map}$ like a more conventional math function,
taking both of its arguments at once. Mathematicians tend to not like
partial applications so much, instead opting to name whatever
intermediate function they might care about.
The Coq proof plays fast and loose with $x$ and $x'$, but it's good to be a bit more careful in informal proofs. For one, Coq isn't checking your work, and a tiny typo can cause a lot of confusion and frustration in your reader! Choose fresh names when you it's not intrusive: since the original existential uses $x$, I'm careful to continue calling it that throughout the proof.
Finally, we don't bother using In x l
at all, instead writing out
the explicit phrase "$x$ is in the list $l$". Choosing words over
notation leads to a proof that's a bit easier to read, but you must be
careful: even if the language is informal, the definition is
not. When we say "$x$ is in the list $z :: l$", we mean In x (z::l')
, which is just the same as z = x \/ In x l'
, i.e., "$z = x$
or $x$ is in the list $l'$.
destruct
, split
, left
, right
)Notice how various tactics play out in prose. The initial split
turns into "prove each direction separately". We casually break apart
existentials without much comment ("suppose there is some $x$"). We
never really make explicit left
or right
decisions, treating the
definition of In
implicitly. Similarly, we just prove both parts of
a conjunction as we go.
It's possible to do too little logical reasoning, though, and have your reader get confused. If you're not sure, maybe err on the side of explicitness, and we'll tell you when to back off.
exists
)While we aren't always explicit about logical reasoning, you must be
explicit about existentials. In the first subcase of the inductive
case of the left-to-right direction of the proof, the exists
shows
up as "we choose $z$ itself as our $x$". The second subcase is less
explicit, because it reuses the exists from the IH.
assert
, replace
, ... in ...
)The informal proof is almost entirely in a forward reasoning style,
while most of the Coq proof reasons backwards. Some of the explicit
forward reasoning that stands out in the Coq proof (assert
)
corresponds to entirely unremarkable phrasing in the informal proof
("our IH gives us").