comparison src/Large.v @ 238:0a2146dafa8e

Start of maint & debug
author Adam Chlipala <adamc@hcoop.net>
date Mon, 07 Dec 2009 16:15:08 -0500
parents 91eed1e3e3a4
children a3f0cdcb09c3
comparison
equal deleted inserted replaced
237:91eed1e3e3a4 238:0a2146dafa8e
200 200
201 (** Now we are in a position to see how much nicer is the style of proof that we have followed in most of this book. *) 201 (** Now we are in a position to see how much nicer is the style of proof that we have followed in most of this book. *)
202 202
203 Reset eval_times. 203 Reset eval_times.
204 204
205 Theorem eval_times : forall k e, 205 Hint Rewrite mult_plus_distr_l : cpdt.
206 eval (times k e) = k * eval e. 206
207 Hint Rewrite mult_plus_distr_l mult_assoc : cpdt. 207 Theorem eval_times : forall k e,
208 208 eval (times k e) = k * eval e.
209 induction e; crush. 209 induction e; crush.
210 Qed. 210 Qed.
211 211
212 (** This style is motivated by a hard truth: one person's manual proof script is almost always mostly inscrutable to most everyone else. I claim that step-by-step formal proofs are a poor way of conveying information. Thus, we had might as well cut out the steps and automate as much as possible. 212 (** This style is motivated by a hard truth: one person's manual proof script is almost always mostly inscrutable to most everyone else. I claim that step-by-step formal proofs are a poor way of conveying information. Thus, we had might as well cut out the steps and automate as much as possible.
213 213
274 (** In the limit, a complicated inductive proof might rely on one hint for each inductive case. The lemma for each hint could restate the associated case. Compared to manual proof scripts, we arrive at more readable results. Scripts no longer need to depend on the order in which cases are generated. The lemmas are easier to digest separately than are fragments of tactic code, since lemma statements include complete proof contexts. Such contexts can only be extracted from monolithic manual proofs by stepping through scripts interactively. 274 (** In the limit, a complicated inductive proof might rely on one hint for each inductive case. The lemma for each hint could restate the associated case. Compared to manual proof scripts, we arrive at more readable results. Scripts no longer need to depend on the order in which cases are generated. The lemmas are easier to digest separately than are fragments of tactic code, since lemma statements include complete proof contexts. Such contexts can only be extracted from monolithic manual proofs by stepping through scripts interactively.
275 275
276 The more common situation is that a large induction has several easy cases that automation makes short work of. In the remaining cases, automation performs some standard simplification. Among these cases, some may require quite involved proofs; such a case may deserve a hint lemma of its own, where the lemma statement may copy the simplified version of the case. Alternatively, the proof script for the main theorem may be extended with some automation code targeted at the specific case. Even such targeted scripting is more desirable than manual proving, because it may be read and understood without knowledge of a proof's hierarchical structure, case ordering, or name binding structure. *) 276 The more common situation is that a large induction has several easy cases that automation makes short work of. In the remaining cases, automation performs some standard simplification. Among these cases, some may require quite involved proofs; such a case may deserve a hint lemma of its own, where the lemma statement may copy the simplified version of the case. Alternatively, the proof script for the main theorem may be extended with some automation code targeted at the specific case. Even such targeted scripting is more desirable than manual proving, because it may be read and understood without knowledge of a proof's hierarchical structure, case ordering, or name binding structure. *)
277 277
278 278
279 (** * Debugging and Maintaining Automation *)
280
281 (** Fully-automated proofs are desirable because they open up possibilities for automatic adaptation to changes of specification. A well-engineered script within a narrow domain can survive many changes to the formulation of the problem it solves. Still, as we are working with higher-order logic, most theorems fall within no obvious decidable theories. It is inevitable that most long-lived automated proofs will need updating.
282
283 Before we are ready to update our proofs, we need to write them in the first place. While fully-automated scripts are most robust to changes of specification, it is hard to write every new proof directly in that form. Instead, it is useful to begin a theorem with exploratory proving and then gradually refine it into a suitable automated form.
284
285 Consider this theorem from Chapter 7, which we begin by proving in a mostly manual way, invoking [crush] after each steop to discharge any low-hanging fruit. Our manual effort involves choosing which expressions to case-analyze on. *)
286
287 (* begin hide *)
288 Require Import MoreDep.
289 (* end hide *)
290
291 Theorem cfold_correct : forall t (e : exp t), expDenote e = expDenote (cfold e).
292 induction e; crush.
293
294 dep_destruct (cfold e1); crush.
295 dep_destruct (cfold e2); crush.
296
297 dep_destruct (cfold e1); crush.
298 dep_destruct (cfold e2); crush.
299
300 dep_destruct (cfold e1); crush.
301 dep_destruct (cfold e2); crush.
302
303 dep_destruct (cfold e1); crush.
304 dep_destruct (expDenote e1); crush.
305
306 dep_destruct (cfold e); crush.
307
308 dep_destruct (cfold e); crush.
309 Qed.
310
311 (** In this complete proof, it is hard to avoid noticing a pattern. We rework the proof, abstracting over the patterns we find. *)
312
313 Reset cfold_correct.
314
315 Theorem cfold_correct : forall t (e : exp t), expDenote e = expDenote (cfold e).
316 induction e; crush.
317
318 (** The expression we want to destruct here turns out to be the discriminee of a [match], and we can easily enough write a tactic that destructs all such expressions. *)
319
320 Ltac t :=
321 repeat (match goal with
322 | [ |- context[match ?E with NConst _ => _ | Plus _ _ => _
323 | Eq _ _ => _ | BConst _ => _ | And _ _ => _
324 | If _ _ _ _ => _ | Pair _ _ _ _ => _
325 | Fst _ _ _ => _ | Snd _ _ _ => _ end] ] =>
326 dep_destruct E
327 end; crush).
328
329 t.
330
331 (** This tactic invocation discharges the whole case. It does the same on the next two cases, but it gets stuck on the fourth case. *)
332
333 t.
334
335 t.
336
337 t.
338
339 (** The subgoal's conclusion is:
340 [[
341 ============================
342 (if expDenote e1 then expDenote (cfold e2) else expDenote (cfold e3)) =
343 expDenote (if expDenote e1 then cfold e2 else cfold e3)
344
345 ]]
346
347 We need to expand our [t] tactic to handle this case. *)
348
349 Ltac t' :=
350 repeat (match goal with
351 | [ |- context[match ?E with NConst _ => _ | Plus _ _ => _
352 | Eq _ _ => _ | BConst _ => _ | And _ _ => _
353 | If _ _ _ _ => _ | Pair _ _ _ _ => _
354 | Fst _ _ _ => _ | Snd _ _ _ => _ end] ] =>
355 dep_destruct E
356 | [ |- (if ?E then _ else _) = _ ] => destruct E
357 end; crush).
358
359 t'.
360
361 (** Now the goal is discharged, but [t'] has no effect on the next subgoal. *)
362
363 t'.
364
365 (** A final revision of [t] finishes the proof. *)
366
367 Ltac t'' :=
368 repeat (match goal with
369 | [ |- context[match ?E with NConst _ => _ | Plus _ _ => _
370 | Eq _ _ => _ | BConst _ => _ | And _ _ => _
371 | If _ _ _ _ => _ | Pair _ _ _ _ => _
372 | Fst _ _ _ => _ | Snd _ _ _ => _ end] ] =>
373 dep_destruct E
374 | [ |- (if ?E then _ else _) = _ ] => destruct E
375 | [ |- context[match pairOut ?E with Some _ => _
376 | None => _ end] ] =>
377 dep_destruct E
378 end; crush).
379
380 t''.
381
382 t''.
383 Qed.
384
385 (** We can take the final tactic and move it into the initial part of the proof script, arriving at a nicely-automated proof. *)
386
387 Reset t.
388
389 Theorem cfold_correct : forall t (e : exp t), expDenote e = expDenote (cfold e).
390 induction e; crush;
391 repeat (match goal with
392 | [ |- context[match ?E with NConst _ => _ | Plus _ _ => _
393 | Eq _ _ => _ | BConst _ => _ | And _ _ => _
394 | If _ _ _ _ => _ | Pair _ _ _ _ => _
395 | Fst _ _ _ => _ | Snd _ _ _ => _ end] ] =>
396 dep_destruct E
397 | [ |- (if ?E then _ else _) = _ ] => destruct E
398 | [ |- context[match pairOut ?E with Some _ => _
399 | None => _ end] ] =>
400 dep_destruct E
401 end; crush).
402 Qed.
403
404
279 (** * Modules *) 405 (** * Modules *)
280 406
281 Module Type GROUP. 407 Module Type GROUP.
282 Parameter G : Set. 408 Parameter G : Set.
283 Parameter f : G -> G -> G. 409 Parameter f : G -> G -> G.