comparison src/Coinductive.v @ 384:eb0fa506d04c

Strengthen last theorem of Coinductive
author Adam Chlipala <adam@chlipala.net>
date Sun, 08 Apr 2012 11:11:27 -0400
parents d1276004eec9
children 4b1242b277b2
comparison
equal deleted inserted replaced
383:e2c88317611f 384:eb0fa506d04c
619 end; crush). 619 end; crush).
620 Qed. 620 Qed.
621 621
622 Hint Rewrite optExp_correct . 622 Hint Rewrite optExp_correct .
623 623
624 (** The final theorem is easy to establish, using our co-induction principle and a bit of Ltac smarts that we leave unexplained for now. Curious readers can consult the Coq manual, or wait for the later chapters of this book about proof automation. *) 624 (** The final theorem is easy to establish, using our co-induction principle and a bit of Ltac smarts that we leave unexplained for now. Curious readers can consult the Coq manual, or wait for the later chapters of this book about proof automation. At a high level, we show inclusions between behaviors, going in both directions between original and optimized programs. *)
625 625
626 Theorem optCmd_correct : forall vs1 c vs2, evalCmd vs1 c vs2 626 Ltac finisher := match goal with
627 | [ H : evalCmd _ _ _ |- _ ] => ((inversion H; [])
628 || (inversion H; [|])); subst
629 end; crush; eauto 10.
630
631 Lemma optCmd_correct1 : forall vs1 c vs2, evalCmd vs1 c vs2
627 -> evalCmd vs1 (optCmd c) vs2. 632 -> evalCmd vs1 (optCmd c) vs2.
628 intros; apply (evalCmd_coind (fun vs1 c' vs2 => exists c, evalCmd vs1 c vs2 633 intros; apply (evalCmd_coind (fun vs1 c' vs2 => exists c, evalCmd vs1 c vs2
629 /\ c' = optCmd c)); eauto; crush; 634 /\ c' = optCmd c)); eauto; crush;
630 match goal with 635 match goal with
631 | [ H : _ = optCmd ?E |- _ ] => destruct E; simpl in *; discriminate 636 | [ H : _ = optCmd ?E |- _ ] => destruct E; simpl in *; discriminate
632 || injection H; intros; subst 637 || injection H; intros; subst
633 end; match goal with 638 end; finisher.
634 | [ H : evalCmd _ _ _ |- _ ] => ((inversion H; []) 639 Qed.
635 || (inversion H; [|])); subst 640
636 end; crush; eauto 10. 641 Lemma optCmd_correct2 : forall vs1 c vs2, evalCmd vs1 (optCmd c) vs2
642 -> evalCmd vs1 c vs2.
643 intros; apply (evalCmd_coind (fun vs1 c vs2 => evalCmd vs1 (optCmd c) vs2));
644 crush; finisher.
645 Qed.
646
647 Theorem optCmd_correct : forall vs1 c vs2, evalCmd vs1 (optCmd c) vs2
648 <-> evalCmd vs1 c vs2.
649 intuition; apply optCmd_correct1 || apply optCmd_correct2; assumption.
637 Qed. 650 Qed.
638 (* end thide *) 651 (* end thide *)
639 652
640 (** In this form, the theorem tells us that the optimizer preserves observable behavior of both terminating and nonterminating programs, but we did not have to do more work than for the case of terminating programs alone. We merely took the natural inductive definition for terminating executions, made it co-inductive, and applied the appropriate co-induction principle. Curious readers might experiment with adding command constructs like %\texttt{%#<tt>#if#</tt>#%}%; the same proof should continue working, after the co-induction principle is extended to the new evaluation rules. *) 653 (** In this form, the theorem tells us that the optimizer preserves observable behavior of both terminating and nonterminating programs, but we did not have to do more work than for the case of terminating programs alone. We merely took the natural inductive definition for terminating executions, made it co-inductive, and applied the appropriate co-induction principle. Curious readers might experiment with adding command constructs like %\texttt{%#<tt>#if#</tt>#%}%; the same proof script should continue working, after the co-induction principle is extended to the new evaluation rules. *)