@@ -96,4 +96,240 @@ Prove the following using induction. You might need previously proven results.
96
96
> plus_comm : (n, m : Nat ) -> n + m = m + n
97
97
> plus_comm n m = ? plus_comm_rhs
98
98
99
+ > plus_assoc : (n, m, p : Nat ) -> n + (m + p) = (n + m) + p
100
+ > plus_assoc n m p = ? plus_assoc_rhs
101
+
102
+ $\ square$
103
+
104
+
105
+ === Exercise : 2 stars, (double_plus)
106
+
107
+ Consider the following function, which doubles its argument :
108
+
109
+ > double : (n : Nat ) -> Nat
110
+ > double Z = Z
111
+ > double (S k) = S (S (double k))
112
+
113
+ Use induction to prove this simple fact about `double` :
114
+
115
+ > double_plus : (n : Nat ) -> double n = n + n
116
+ > double_plus n = ? double_plus_rhs
117
+
118
+ $\ square$
119
+
120
+
121
+ === Exercise : 2 stars, optional (evenb_S)
122
+
123
+ One inconveninent aspect of our definition of `evenb n` is that it may need to
124
+ perform a recursive call on `n - 2 `. This makes proofs about `evenb n` harder
125
+ when done by induction on `n` , since we may need an induction hypothesis about
126
+ `n - 2 `. The following lemma gives a better characterization of `evenb (S n)`:
127
+
128
+ > evenb_S : (n : Nat ) -> evenb (S n) = negb (evenb n)
129
+ > evenb_S n = ? evenb_S_rhs
130
+
131
+ $\ square$
132
+
133
+
134
+ == Proofs Within Proofs
135
+
136
+ In Coq , as in informal mathematics, large proofs are often broken into a
137
+ sequence of theorems, with later proofs referring to earlier theorems. But
138
+ sometimes a proof will require some miscellaneous fact that is too trivial and
139
+ of too little general interest to bother giving it its own top- level name. In
140
+ such cases, it is convenient to be able to simply state and prove the needed
141
+ " sub-theorem" right at the point where it is used. The `assert` tactic allows us
142
+ to do this. For example, our earlier proof of the `mult_0_plus` theorem referred
143
+ to a previous theorem named `plus_Z_n` . We could instead use `assert` to state
144
+ and prove `plus_Z_n` in - line :
145
+
146
+ > mult_0_plus' : (n, m : Nat ) -> (0 + n) * m = n * m
147
+ > mult_0_plus' n m = Refl
148
+
149
+ The `assert` tactic introduces two sub- goals. The first is the assertion itself;
150
+ by prefixing it with `H : ` we name the assertion `H`. (We can also name the
151
+ assertion with `as` just as we did above with `destruct` and `induction`, i.e.,
152
+ `assert (0 + n = n) as H `.) Note that we surround the proof of this assertion
153
+ with curly braces `{ ... }`, both for readability and so that , when using Coq
154
+ interactively, we can see more easily when we have finished this sub-proof. The
155
+ second goal is the same as the one at the point where we invoke `assert` except
156
+ that, in the context, we now have the assumption `H` that `0 + n = n`. That is ,
157
+ `assert` generates one subgoal where we must prove the asserted fact and a
158
+ second subgoal where we can use the asserted fact to make progress on whatever
159
+ we were trying to prove in the first place.
160
+
161
+ The `assert` tactic is handy in many sorts of situations . For example , suppose
162
+ we want to prove that `(n + m) + (p + q) = (m + n) + (p + q)`. The only
163
+ difference between the two sides of the `=` is that the arguments `m` and `n` to
164
+ the first inner `+` are swapped , so it seems we should be able to use the
165
+ commutativity of addition (`plus_comm`) to rewrite one into the other . However,
166
+ the `rewrite` tactic is a little stupid about _where_ it applies the rewrite.
167
+ There are three uses of `+` here, and it turns out that doing `rewrite ->
168
+ plus_comm` will affect only the _outer_ one ...
169
+
170
+ ```idris
171
+ plus_rearrange_firsttry : (n, m, p, q : Nat) ->
172
+ (n + m) + (p + q) = (m + n) + (p + q)
173
+ plus_rearrange_firsttry n m p q = rewrite plus_comm in Refl
174
+ ```
175
+ ```
176
+ When checking right hand side of plus_rearrange_firsttry with expected type
177
+ n + m + (p + q) = m + n + (p + q)
178
+
179
+ _ does not have an equality type ((n1 : Nat) ->
180
+ (n1 : Nat) -> plus n1 m1 = plus m1 n1)
181
+ ```
182
+
183
+ To get `plus_comm` to apply at the point where we want it to , we can introduce a
184
+ local lemma stating that `n + m = m + n` (for the particular `m` and `n` that we
185
+ are talking about here ), prove this lemma using `plus_comm`, and then use it to
186
+ do the desired rewrite .
187
+
188
+ > plus_rearrange_lemma : (n, m : Nat) -> n + m = m + n
189
+ > plus_rearrange_lemma = plus_comm
190
+
191
+ > plus_rearrange : (n, m, p, q : Nat) ->
192
+ > (n + m) + (p + q) = (m + n) + (p + q)
193
+ > plus_rearrange n m p q = rewrite plus_rearrange_lemma n m in Refl
194
+
195
+
196
+ == More Exercises
197
+
198
+ === Exercise: 3 stars , recommended (mult_comm)
199
+
200
+ Use `rewrite` to help prove this theorem. You shouldn't need to use induction on
201
+ `plus_swap`.
202
+
203
+ > plus_swap : (n, m, p : Nat) -> n + (m + p) = m + (n + p)
204
+ > plus_swap n m p = ?plus_swap_rhs
205
+
206
+ Now prove commutativity of multiplication. (You will probably need to define and
207
+ prove a separate subsidiary theorem to be used in the proof of this one . You may
208
+ find that `plus_swap` comes in handy.)
209
+
210
+ > mult_comm : (m, n : Nat) -> m * n = n * m
211
+ > mult_comm m n = ?mult_comm_rhs
212
+
213
+ $\square$
214
+
215
+
216
+ === Exercise: 3 stars , optional (more_exercises)
217
+
218
+ Take a piece of paper. For each of the following theorems , first _think_ about
219
+ whether (a) it can be proved using only simplification and rewriting, (b) it
220
+ also requires case analysis (`destruct`), or (c) it also requires induction .
221
+ Write down your prediction . Then fill in the proof. (There is no need to turn in
222
+ your piece of paper ; this is just to encourage you to reflect before you hack!)
223
+
224
+ > leb_refl : (n : Nat) -> True = leb n n
225
+ > leb_refl n = ?leb_refl_rhs
226
+
227
+ > zero_nbeq_S : (n : Nat) -> beq_nat 0 (S n ) = False
228
+ > zero_nbeq_S n = ?zero_nbeq_S_rhs
229
+
230
+ > andb_false_r : (b : Bool) -> andb b False = False
231
+ > andb_false_r b = ?andb_false_r_rhs
232
+
233
+ > plus_ble_compat_l : (n, m, p : Nat) ->
234
+ > leb n m = True -> leb (p + n) (p + m) = True
235
+ > plus_ble_compat_l n m p prf = ?plus_ble_compat_l_rhs
236
+
237
+ > S_nbeq_0 : (n : Nat) -> beq_nat (S n ) 0 = False
238
+ > S_nbeq_0 n = ?S_nbeq_0_rhs
239
+
240
+ > mult_1_l : (n : Nat) -> 1 * n = n
241
+ > mult_1_l n = ?mult_1_l_rhs
242
+
243
+ > all3_spec : (b, c : Bool) ->
244
+ > orb (andb b c)
245
+ > (orb (negb b )
246
+ > (negb c ))
247
+ > = True
248
+ > all3_spec b c = ?all3_spec_rhs
249
+
250
+ > mult_plus_distr_r : (n, m, p : Nat) -> (n + m) * p = (n * p) + (m * p)
251
+ > mult_plus_distr_r n m p = ?mult_plus_distr_r_rhs
252
+
253
+ > mult_assoc : (n, m, p : Nat) -> n * (m * p) = (n * m) * p
254
+ > mult_assoc n m p = ?mult_assoc_rhs
255
+
256
+ $\square$
257
+
258
+
259
+ === Exercise: 2 stars , optional (beq_nat_refl)
260
+
261
+ Prove the following theorem . (Putting the `True` on the left-hand side of the
262
+ equality may look odd , but this is how the theorem is stated in the Coq standard
263
+ library, so we follow suit . Rewriting works equally well in either direction, so
264
+ we will have no problem using the theorem no matter which way we state it.)
265
+
266
+ > beq_nat_refl : (n : Nat) -> True = beq_nat n n
267
+ > beq_nat_refl n = ?beq_nat_refl_rhs
268
+
269
+ $\square$
270
+
271
+
272
+ === Exercise: 2 stars , optional (plus_swap')
273
+
274
+ The `replace` tactic allows you to specify a particular subterm to rewrite and
275
+ what you want it rewritten to : `replace (t) with (u)` replaces (all copies of)
276
+ expression `t` in the goal by expression `u`, and generates `t = u` as an
277
+ additional subgoal . This is often useful when a plain `rewrite` acts on the
278
+ wrong part of the goal.
279
+
280
+ Use the `replace` tactic to do a proof of `plus_swap'`, just like `plus_swap`
281
+ but without needing `assert (n + m = m + n)`.
282
+
283
+ > plus_swap' : (n, m, p : Nat) -> n + (m + p) = m + (n + p)
284
+ > plus_swap' n m p = ?plus_swap'_rhs
285
+
286
+ $\square$
287
+
288
+
289
+ === Exercise: 3 stars , recommended (binary_commute)
290
+
291
+ Recall the `incr` and `bin_to_nat` functions that you wrote for the `binary`
292
+ exercise in the `Basics` chapter. Prove that the following diagram commutes :
293
+
294
+ bin --------- incr -------> bin
295
+ | |
296
+ bin_to_nat bin_to_nat
297
+ | |
298
+ v v
299
+ nat ---------- S ---------> nat
300
+
301
+ That is , incrementing a binary number and then converting it to a (unary)
302
+ natural number yields the same result as first converting it to a natural number
303
+ and then incrementing. Name your theorem `bin_to_nat_pres_incr` ("pres" for
304
+ "preserves").
305
+
306
+ Before you start working on this exercise, please copy the definitions from your
307
+ solution to the `binary` exercise here so that this file can be graded on its
308
+ own. If you find yourself wanting to change your original definitions to make
309
+ the property easier to prove, feel free to do so!
310
+
311
+ $\square$
312
+
313
+
314
+ === Exercise: 5 stars , advanced (binary_inverse)
315
+
316
+ This exercise is a continuation of the previous exercise about binary numbers .
317
+ You will need your definitions and theorems from there to complete this one.
318
+
319
+ (a) First, write a function to convert natural numbers to binary numbers . Then
320
+ prove that starting with any natural number, converting to binary, then
321
+ converting back yields the same natural number you started with .
322
+
323
+ (b) You might naturally think that we should also prove the opposite direction :
324
+ that starting with a binary number , converting to a natural , and then back
325
+ to binary yields the same number we started with. However, this is not true !
326
+ Explain what the problem is.
327
+
328
+ (c) Define a "direct" normalization function -- i.e., a function `normalize`
329
+ from binary numbers to binary numbers such that , for any binary number b,
330
+ converting to a natural and then back to binary yields `(normalize b )`.
331
+ Prove it . (Warning: This part is tricky !)
332
+
333
+ Again, feel free to change your earlier definitions if this helps here.
334
+
99
335
$\square$
0 commit comments