Mercurial > cpdt > repo
comparison src/Predicates.v @ 52:ce0c9d481ee3
What could go wrong; some exercises
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sun, 28 Sep 2008 12:42:59 -0400 |
parents | a21eb02cc7c6 |
children | 422865e240b1 |
comparison
equal
deleted
inserted
replaced
50:a21eb02cc7c6 | 52:ce0c9d481ee3 |
---|---|
209 | 209 |
210 (* begin hide *) | 210 (* begin hide *) |
211 (* In-class exercises *) | 211 (* In-class exercises *) |
212 | 212 |
213 Theorem contra : P -> ~P -> R. | 213 Theorem contra : P -> ~P -> R. |
214 (* begin thide *) | |
215 unfold not. | |
216 intros. | |
217 elimtype False. | |
218 apply H0. | |
219 assumption. | |
220 (* end thide *) | |
214 Admitted. | 221 Admitted. |
215 | 222 |
216 Theorem and_assoc : (P /\ Q) /\ R -> P /\ (Q /\ R). | 223 Theorem and_assoc : (P /\ Q) /\ R -> P /\ (Q /\ R). |
224 (* begin thide *) | |
225 intros. | |
226 destruct H. | |
227 destruct H. | |
228 split. | |
229 assumption. | |
230 split. | |
231 assumption. | |
232 assumption. | |
233 (* end thide *) | |
217 Admitted. | 234 Admitted. |
218 | 235 |
219 Theorem or_assoc : (P \/ Q) \/ R -> P \/ (Q \/ R). | 236 Theorem or_assoc : (P \/ Q) \/ R -> P \/ (Q \/ R). |
237 (* begin thide *) | |
238 intros. | |
239 destruct H. | |
240 destruct H. | |
241 left. | |
242 assumption. | |
243 right. | |
244 left. | |
245 assumption. | |
246 right. | |
247 right. | |
248 assumption. | |
249 (* end thide *) | |
220 Admitted. | 250 Admitted. |
221 | 251 |
222 (* end hide *) | 252 (* end hide *) |
223 | 253 |
224 | 254 |
346 (* begin hide *) | 376 (* begin hide *) |
347 (* In-class exercises *) | 377 (* In-class exercises *) |
348 | 378 |
349 Theorem forall_exists_commute : forall (A B : Type) (P : A -> B -> Prop), | 379 Theorem forall_exists_commute : forall (A B : Type) (P : A -> B -> Prop), |
350 (exists x : A, forall y : B, P x y) -> (forall y : B, exists x : A, P x y). | 380 (exists x : A, forall y : B, P x y) -> (forall y : B, exists x : A, P x y). |
381 (* begin thide *) | |
382 intros. | |
383 destruct H. | |
384 exists x. | |
385 apply H. | |
386 (* end thide *) | |
351 Admitted. | 387 Admitted. |
352 | 388 |
353 (* end hide *) | 389 (* end hide *) |
354 | 390 |
355 | 391 |
435 | 471 |
436 (* begin hide *) | 472 (* begin hide *) |
437 (* In-class exercises *) | 473 (* In-class exercises *) |
438 | 474 |
439 (* EX: Define an inductive type capturing when a list has exactly two elements. Prove that your predicate does not hold of the empty list, and prove that, whenever it holds of a list, the length of that list is two. *) | 475 (* EX: Define an inductive type capturing when a list has exactly two elements. Prove that your predicate does not hold of the empty list, and prove that, whenever it holds of a list, the length of that list is two. *) |
476 | |
477 (* begin thide *) | |
478 Section twoEls. | |
479 Variable A : Type. | |
480 | |
481 Inductive twoEls : list A -> Prop := | |
482 | TwoEls : forall x y, twoEls (x :: y :: nil). | |
483 | |
484 Theorem twoEls_nil : twoEls nil -> False. | |
485 inversion 1. | |
486 Qed. | |
487 | |
488 Theorem twoEls_two : forall ls, twoEls ls -> length ls = 2. | |
489 inversion 1. | |
490 reflexivity. | |
491 Qed. | |
492 End twoEls. | |
493 (* end thide *) | |
440 | 494 |
441 (* end hide *) | 495 (* end hide *) |
442 | 496 |
443 | 497 |
444 (** * Recursive Predicates *) | 498 (** * Recursive Predicates *) |
658 [crush] uses the tactic [intuition], which, when it runs out of tricks to try using only propositional logic, by default tries the tactic [auto], which we saw in an earlier example. [auto] attempts Prolog-style logic programming, searching through all proof trees up to a certain depth that are built only out of hints that have been registered with [Hint] commands. Compared to Prolog, [auto] places an important restriction: it never introduces new unification variables during search. That is, every time a rule is applied during proof search, all of its arguments must be deducible by studying the form of the goal. [eauto] relaxes this restriction, at the cost of possibly exponentially greater running time. In this particular case, we know that [eauto] has only a small space of proofs to search, so it makes sense to run it. It is common in effectively-automated Coq proofs to see a bag of standard tactics applied to pick off the "easy" subgoals, finishing off with [eauto] to handle the tricky parts that can benefit from ad-hoc exhaustive search. | 712 [crush] uses the tactic [intuition], which, when it runs out of tricks to try using only propositional logic, by default tries the tactic [auto], which we saw in an earlier example. [auto] attempts Prolog-style logic programming, searching through all proof trees up to a certain depth that are built only out of hints that have been registered with [Hint] commands. Compared to Prolog, [auto] places an important restriction: it never introduces new unification variables during search. That is, every time a rule is applied during proof search, all of its arguments must be deducible by studying the form of the goal. [eauto] relaxes this restriction, at the cost of possibly exponentially greater running time. In this particular case, we know that [eauto] has only a small space of proofs to search, so it makes sense to run it. It is common in effectively-automated Coq proofs to see a bag of standard tactics applied to pick off the "easy" subgoals, finishing off with [eauto] to handle the tricky parts that can benefit from ad-hoc exhaustive search. |
659 | 713 |
660 The original theorem now follows trivially from our lemma. *) | 714 The original theorem now follows trivially from our lemma. *) |
661 | 715 |
662 Theorem even_contra : forall n, even (S (n + n)) -> False. | 716 Theorem even_contra : forall n, even (S (n + n)) -> False. |
663 intros; apply even_contra' with (S (n + n)) n; trivial. | 717 intros; eapply even_contra'; eauto. |
664 Qed. | 718 Qed. |
719 | |
720 (** We use a variant [eapply] of [apply] which has the same relationship to [apply] as [eauto] has to [auto]. [apply] only succeeds if all arguments to the rule being used can be determined from the form of the goal, whereas [eapply] will introduce unification variables for undetermined arguments. [eauto] is able to determine the right values for those unification variables. | |
721 | |
722 By considering an alternate attempt at proving the lemma, we can see another common pitfall of inductive proofs in Coq. Imagine that we had tried to prove [even_contra'] with all of the [forall] quantifiers moved to the front of the lemma statement. *) | |
723 | |
724 Lemma even_contra'' : forall n' n, even n' -> n' = S (n + n) -> False. | |
725 induction 1; crush; | |
726 match goal with | |
727 | [ H : S ?N = ?N0 + ?N0 |- _ ] => destruct N; destruct N0 | |
728 end; crush; eauto. | |
729 | |
730 (** One subgoal remains: *) | |
731 | |
732 (** [[ | |
733 | |
734 n : nat | |
735 H : even (S (n + n)) | |
736 IHeven : S (n + n) = S (S (S (n + n))) -> False | |
737 ============================ | |
738 False | |
739 ]] *) | |
740 | |
741 (** We are out of luck here. The inductive hypothesis is trivially true, since its assumption is false. In the version of this proof that succeeded, [IHeven] had an explicit quantification over [n]. This is because the quantification of [n] %\textit{%#<i>#appeared after the thing we are inducting on#</i>#%}% in the theorem statement. In general, quantified variables and hypotheses that appear before the induction object in the theorem statement stay fixed throughout the inductive proof. Variables and hypotheses that are quantified after the induction object may be varied explicitly in uses of inductive hypotheses. | |
742 | |
743 Why should Coq implement [induction] this way? One answer is that it avoids burdening this basic tactic with additional heuristic smarts, but that is not the whole picture. Imagine that [induction] analyzed dependencies among variables and reordered quantifiers to preserve as much freedom as possible in later uses of inductive hypotheses. This could make the inductive hypotheses more complex, which could in turn cause particular automation machinery to fail when it would have succeeded before. In general, we want to avoid quantifiers in our proofs whenever we can, and that goal is furthered by the refactoring that the [induction] tactic forces us to do. *) | |
744 | |
745 | |
746 (* begin hide *) | |
747 (* In-class exercises *) | |
748 | |
749 (* EX: Define a type [prop] of simple boolean formulas made up only of truth, falsehood, binary conjunction, and binary disjunction. Define an inductive predicate [holds] that captures when [prop]s are valid, and define a predicate [falseFree] that captures when a [prop] does not contain the "false" formula. Prove that every false-free [prop] is valid. *) | |
750 | |
751 (* begin thide *) | |
752 Inductive prop : Set := | |
753 | Tru : prop | |
754 | Fals : prop | |
755 | And : prop -> prop -> prop | |
756 | Or : prop -> prop -> prop. | |
757 | |
758 Inductive holds : prop -> Prop := | |
759 | HTru : holds Tru | |
760 | HAnd : forall p1 p2, holds p1 -> holds p2 -> holds (And p1 p2) | |
761 | HOr1 : forall p1 p2, holds p1 -> holds (Or p1 p2) | |
762 | HOr2 : forall p1 p2, holds p2 -> holds (Or p1 p2). | |
763 | |
764 Inductive falseFree : prop -> Prop := | |
765 | FFTru : falseFree Tru | |
766 | FFAnd : forall p1 p2, falseFree p1 -> falseFree p2 -> falseFree (And p1 p2) | |
767 | FFNot : forall p1 p2, falseFree p1 -> falseFree p2 -> falseFree (Or p1 p2). | |
768 | |
769 Hint Constructors holds. | |
770 | |
771 Theorem falseFree_holds : forall p, falseFree p -> holds p. | |
772 induction 1; crush. | |
773 Qed. | |
774 (* end thide *) | |
775 | |
776 | |
777 (* EX: Define an inductive type [prop'] that is the same as [prop] but omits the possibility for falsehood. Define a proposition [holds'] for [prop'] that is analogous to [holds]. Define a function [propify] for translating [prop']s to [prop]s. Prove that, for any [prop'] [p], if [propify p] is valid, then so is [p]. *) | |
778 | |
779 (* begin thide *) | |
780 Inductive prop' : Set := | |
781 | Tru' : prop' | |
782 | And' : prop' -> prop' -> prop' | |
783 | Or' : prop' -> prop' -> prop'. | |
784 | |
785 Inductive holds' : prop' -> Prop := | |
786 | HTru' : holds' Tru' | |
787 | HAnd' : forall p1 p2, holds' p1 -> holds' p2 -> holds' (And' p1 p2) | |
788 | HOr1' : forall p1 p2, holds' p1 -> holds' (Or' p1 p2) | |
789 | HOr2' : forall p1 p2, holds' p2 -> holds' (Or' p1 p2). | |
790 | |
791 Fixpoint propify (p : prop') : prop := | |
792 match p with | |
793 | Tru' => Tru | |
794 | And' p1 p2 => And (propify p1) (propify p2) | |
795 | Or' p1 p2 => Or (propify p1) (propify p2) | |
796 end. | |
797 | |
798 Hint Constructors holds'. | |
799 | |
800 Lemma propify_holds' : forall p', holds p' -> forall p, p' = propify p -> holds' p. | |
801 induction 1; crush; destruct p; crush. | |
802 Qed. | |
803 | |
804 Theorem propify_holds : forall p, holds (propify p) -> holds' p. | |
805 intros; eapply propify_holds'; eauto. | |
806 Qed. | |
807 (* end thide *) | |
808 | |
809 (* end hide *) |