@@ -643,32 +643,188 @@ Conjecture cno_verification_overhead :
643643
644644(** ** State Equality and Evaluation *)
645645
646- (** CRITICAL LEMMA: Evaluation respects state equality on the right
647-
648- This lemma is essential for proving CNO reversibility.
649- It states that if we can evaluate p from s to s', and s' is
650- state-equal to s'', then we can also evaluate p from s to s''.
651-
652- This is needed because the eval relation is defined inductively
653- on specific states, but CNO theory works with state equality (=st=).
654- *)
655- Axiom eval_respects_state_eq_right :
656- forall p s s' s'',
657- eval p s s' ->
658- s' =st= s'' ->
659- eval p s s''.
646+ (** Inversion helpers for [step], extracted so the [step_respects_state_eq]
647+ case-analysis below doesn't rely on Coq 8.18's positional [Hn]
648+ auto-naming. Each returns the explicit equations that the [step_*]
649+ constructor's premises imply about the post-state. *)
650+
651+ Lemma step_load_inv :
652+ forall s addr reg s',
653+ step s (Load addr reg) s' ->
654+ s' = mkState s.(state_memory)
655+ (set_reg s.(state_registers) reg (s.(state_memory) addr))
656+ s.(state_io)
657+ (S s.(state_pc)).
658+ Proof .
659+ intros s addr reg s' H.
660+ inversion H; subst.
661+ reflexivity.
662+ Qed .
660663
661- (** TODO: Prove this axiom by induction on eval structure.
662- This requires showing that each step constructor respects state equality.
663- For now, we axiomatize it to unblock cno_logically_reversible proof.
664- *)
664+ Lemma step_store_inv :
665+ forall s addr reg s',
666+ step s (Store addr reg) s' ->
667+ exists val, get_reg s.(state_registers) reg = Some val /\
668+ s' = mkState (mem_update s.(state_memory) addr val)
669+ s.(state_registers)
670+ s.(state_io)
671+ (S s.(state_pc)).
672+ Proof .
673+ intros s addr reg s' H.
674+ inversion H; subst.
675+ eexists. split; [ eassumption | reflexivity ].
676+ Qed .
665677
666- (** Similarly for the left side *)
667- Axiom eval_respects_state_eq_left :
668- forall p s s' s'',
669- eval p s s'' ->
670- s =st= s' ->
671- eval p s' s''.
678+ Lemma step_add_inv :
679+ forall s r1 r2 r3 s',
680+ step s (Add r1 r2 r3) s' ->
681+ exists v1 v2, get_reg s.(state_registers) r1 = Some v1 /\
682+ get_reg s.(state_registers) r2 = Some v2 /\
683+ s' = mkState s.(state_memory)
684+ (set_reg s.(state_registers) r3 (v1 + v2))
685+ s.(state_io)
686+ (S s.(state_pc)).
687+ Proof .
688+ intros s r1 r2 r3 s' H.
689+ inversion H; subst.
690+ do 2 eexists. split; [ eassumption | split; [ eassumption | reflexivity ] ].
691+ Qed .
692+
693+ (** [step] respects [state_eq] on inputs: if [s1 =st= s2] and
694+ [step s1 i sm], then there exists a post-state [sm'] with
695+ [step s2 i sm'] and [sm =st= sm'].
696+
697+ The witness for [sm'] is determined by case-analysis on [i] (since
698+ [step] is deterministic given [=st=]-equal inputs — registers and
699+ memory agree pointwise, and any read-out value from memory or
700+ registers matches). The conclusion uses [=st=] rather than
701+ syntactic equality because [Load]/[Store]/[Add] re-build records
702+ from [s2]'s components, which differ from [s1]'s on [state_pc] and
703+ are only [=mem=]-equal (not syntactically equal) on
704+ [state_memory]. *)
705+ Lemma step_respects_state_eq :
706+ forall s1 s2 i sm,
707+ s1 =st= s2 ->
708+ step s1 i sm ->
709+ exists sm', step s2 i sm' /\ sm =st= sm'.
710+ Proof .
711+ intros s1 s2 i sm Heq Hstep.
712+ destruct Heq as [Hmem [Hreg Hio]].
713+ destruct i.
714+ - (* Nop *)
715+ inversion Hstep; subst.
716+ exists (mkState s2.(state_memory) s2.(state_registers) s2.(state_io)
717+ (S s2.(state_pc))).
718+ split.
719+ + constructor.
720+ + unfold state_eq. simpl. split; [assumption | split; assumption].
721+ - (* Load addr reg *)
722+ apply step_load_inv in Hstep. subst sm.
723+ exists (mkState s2.(state_memory)
724+ (set_reg s2.(state_registers) n0
725+ (s2.(state_memory) n))
726+ s2.(state_io)
727+ (S s2.(state_pc))).
728+ split.
729+ + econstructor. reflexivity.
730+ + unfold state_eq. simpl. split; [assumption | split; [| assumption]].
731+ (* set_reg s1.regs n0 (s1.mem n) = set_reg s2.regs n0 (s2.mem n) *)
732+ rewrite Hreg.
733+ f_equal.
734+ apply Hmem.
735+ - (* Store addr reg *)
736+ apply step_store_inv in Hstep.
737+ destruct Hstep as [val [Hget Hsm]]. subst sm.
738+ exists (mkState (mem_update s2.(state_memory) n val)
739+ s2.(state_registers)
740+ s2.(state_io)
741+ (S s2.(state_pc))).
742+ split.
743+ + econstructor. rewrite <- Hreg. exact Hget.
744+ + unfold state_eq, mem_eq. simpl.
745+ split; [| split; assumption].
746+ (* mem_update s1.mem n val =mem= mem_update s2.mem n val *)
747+ intros addr.
748+ unfold mem_update.
749+ destruct (Nat.eqb addr n); [reflexivity | apply Hmem].
750+ - (* Add r1 r2 r3 *)
751+ apply step_add_inv in Hstep.
752+ destruct Hstep as [v1 [v2 [Hg1 [Hg2 Hsm]]]]. subst sm.
753+ exists (mkState s2.(state_memory)
754+ (set_reg s2.(state_registers) n1 (v1 + v2))
755+ s2.(state_io)
756+ (S s2.(state_pc))).
757+ split.
758+ + econstructor; rewrite <- Hreg; eassumption.
759+ + unfold state_eq. simpl. split; [assumption | split; [| assumption]].
760+ rewrite Hreg. reflexivity.
761+ - (* Jump target *)
762+ inversion Hstep; subst.
763+ exists (mkState s2.(state_memory) s2.(state_registers) s2.(state_io) n).
764+ split.
765+ + constructor.
766+ + unfold state_eq. simpl. split; [assumption | split; assumption].
767+ - (* Halt *)
768+ inversion Hstep; subst.
769+ exists s2.
770+ split.
771+ + constructor.
772+ + unfold state_eq. split; [assumption | split; assumption].
773+ Qed .
774+
775+ (** CRITICAL LEMMA: Evaluation respects state equality on the input side.
776+
777+ The original universal form
778+ [s =st= s' -> eval p s s'' -> eval p s' s'']
779+ is unsound under the relaxed 3-clause [state_eq] from Stage 2: the
780+ [eval_empty] base case would need [s = s'] syntactically, but
781+ [s =st= s'] only constrains memory + registers + I/O (not
782+ [state_pc]). Stage 3 (standards#157) accordingly reformulates the
783+ conclusion existentially: from [s1 =st= s2] and [eval p s1 s'] we
784+ obtain *some* [s''] reached by [p] starting from [s2], with
785+ [s' =st= s''] (i.e. final states agree modulo [state_pc]).
786+
787+ The proof is by induction on the [eval] derivation, using
788+ [step_respects_state_eq] to advance the witness one instruction at
789+ a time. *)
790+ Theorem eval_respects_state_eq_left :
791+ forall p s1 s2 s',
792+ s1 =st= s2 ->
793+ eval p s1 s' ->
794+ exists s'', eval p s2 s'' /\ s' =st= s''.
795+ Proof .
796+ intros p s1 s2 s' Heq Heval.
797+ generalize dependent s2.
798+ induction Heval as [s | i is sa sb sc Hstep_a Heval_rest IH];
799+ intros s2 Heq.
800+ - (* eval_empty: p = [], s' = s, witness s'' = s2 *)
801+ exists s2. split.
802+ + constructor.
803+ + assumption.
804+ - (* eval_step: step sa i sb, eval is sb sc *)
805+ destruct (step_respects_state_eq _ _ _ _ Heq Hstep_a)
806+ as [sb' [Hstep_b Heq_b]].
807+ destruct (IH sb' Heq_b) as [sc' [Heval_rest' Heq_c]].
808+ exists sc'. split.
809+ + eapply eval_step; eassumption.
810+ + assumption.
811+ Qed .
812+
813+ (** Symmetric form on the output side.
814+
815+ The output-side version is trivial under the existential
816+ reformulation: simply witness [s'' := s1]. We retain the
817+ statement (now a [Theorem] rather than an [Axiom]) so that
818+ downstream files have the symmetric API available. *)
819+ Theorem eval_respects_state_eq_right :
820+ forall p s s1 s2,
821+ eval p s s1 ->
822+ s1 =st= s2 ->
823+ exists s'', eval p s s'' /\ s'' =st= s2.
824+ Proof .
825+ intros p s s1 s2 Heval Heq.
826+ exists s1. split; assumption.
827+ Qed .
672828
673829(** For CNOs specifically, if s =st= s', then eval p s s evaluates the same as eval p s' s' *)
674830Lemma cno_eval_on_equal_states :
@@ -678,16 +834,19 @@ Lemma cno_eval_on_equal_states :
678834 (exists s1, eval p s s1) <-> (exists s2, eval p s' s2).
679835Proof .
680836 intros p s s' H_cno H_eq.
681- split; intros [sx H_eval].
682- - (* Forward: eval p s sx and s =st= s' ==> eval p s' sx *)
683- exists sx.
684- eapply eval_respects_state_eq_left.
685- + eassumption.
686- + assumption.
687- - (* Backward: eval p s' sx and s =st= s' ==> eval p s sx *)
688- exists sx.
689- eapply eval_respects_state_eq_left.
690- + eassumption.
691- + apply state_eq_sym. assumption.
837+ split.
838+ { (* Forward direction *)
839+ intros [sx H_eval].
840+ destruct (eval_respects_state_eq_left _ _ _ _ H_eq H_eval)
841+ as [sx' [H_eval' _]].
842+ exists sx'. assumption.
843+ }
844+ { (* Backward direction *)
845+ intros [sx H_eval].
846+ destruct (eval_respects_state_eq_left _ _ _ _
847+ (state_eq_sym _ _ H_eq) H_eval)
848+ as [sx' [H_eval' _]].
849+ exists sx'. assumption.
850+ }
692851Qed .
693852
0 commit comments