Skip to content

Commit 93547ef

Browse files
hyperpolymathclaude
andcommitted
fix(coq/cno): discharge eval_respects_state_eq_{left,right} via existential reformulation
PR #25's Stage 3 left these two as Axiom after the agent discovered that the original universal form is unsound under the Stage-2 relaxed state_eq: the eval_empty base case requires s1 = s2 syntactically, but the hypothesis only provides s1 =st= s2 (pc-blind after Stage 2). The sound replacement uses an existential conclusion: forall p s1 s2 s', s1 =st= s2 -> eval p s1 s' -> exists s'', eval p s2 s'' /\ s' =st= s''. This is provable by induction on the eval derivation. The eval_empty case witnesses s'' = s2 directly. The eval_step case uses a new step_respects_state_eq helper that shows step preserves =st=-equivalence on inputs. Two callers updated to destructure the existential conclusion: - cno_eval_on_equal_states (in this file) - cno_logically_reversible (proofs/coq/physics/StatMech.v) The StatMech caller also required relaxing the logically_reversible definition: the inverse-run conclusion is now phrased modulo =st= rather than strict equality on the start state, since rerunning a CNO from its output can only recover the start state pc-modulo (state_pc is ignored by Stage-2 state_eq). The single downstream consumer bennett_logical_implies_thermodynamic does not use the hypothesis structurally, so it is unaffected. Net axiom count in proofs/coq/common/CNO.v: 2 -> 0. Stage 3 complete; the file is now Admitted-free AND Axiom-free. Note: physics/StatMech.v requires Coq.Reals which the local sandbox cannot exercise; the edit is CI-verifiable only (same pattern as prior PR's downstream files). common/CNO.v builds locally green. Refs hyperpolymath/standards#124, scoping doc standards#157 (Stage 3). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 8466ddc commit 93547ef

2 files changed

Lines changed: 170 additions & 67 deletions

File tree

proofs/coq/common/CNO.v

Lines changed: 142 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -766,45 +766,141 @@ Conjecture cno_verification_overhead :
766766

767767
(** ** State Equality and Evaluation *)
768768

769-
(** CRITICAL LEMMA: Evaluation respects state equality on the right.
770-
771-
This axiom is essential for proving CNO reversibility.
772-
It states that if we can evaluate p from s to s', and s' is
773-
state-equal to s'', then we can also evaluate p from s to s''.
774-
775-
Stage 3 (standards#157) attempted to discharge this by induction
776-
but found it is unprovable as stated under the relaxed 3-clause
777-
[state_eq] (which ignores [state_pc] per Stage 2):
778-
779-
The [eval_empty] base case requires [s' = s''], but we only have
780-
[s' =st= s''], which allows them to differ in [state_pc].
781-
Constructing [eval [] s s''] would need [s = s''] strictly.
782-
783-
A sound existential reformulation
784-
[forall p s s', eval p s s' -> forall s_eq, s' =st= s_eq ->
785-
exists s'', eval p s s'' /\ s'' =st= s_eq]
786-
IS provable but changes the signature and breaks existing callers
787-
([cno_eval_on_equal_states] here, [cno_logically_reversible] in
788-
physics/StatMech.v). Discharging it that way is tracked for
789-
follow-up; the original statement is preserved as an [Axiom] for
790-
now to honour the Stage-3 "preserve theorem statements" rule. *)
791-
Axiom eval_respects_state_eq_right :
792-
forall p s s' s'',
793-
eval p s s' ->
794-
s' =st= s'' ->
795-
eval p s s''.
796-
797-
(** Similarly for the left side.
798-
799-
Same unprovability story as [eval_respects_state_eq_right]: the
800-
[eval_empty] base case demands [s = s'] strictly, but we only have
801-
[s =st= s']. Left as [Axiom] pending an existential reformulation
802-
(see comment on [eval_respects_state_eq_right]). *)
803-
Axiom eval_respects_state_eq_left :
804-
forall p s s' s'',
805-
eval p s s'' ->
806-
s =st= s' ->
807-
eval p s' s''.
769+
(** [step] respects [state_eq] on inputs: if [s1 =st= s2] and
770+
[step s1 i sm], then there exists a post-state [sm'] with
771+
[step s2 i sm'] and [sm =st= sm'].
772+
773+
The witness for [sm'] is determined by case-analysis on [i] (since
774+
[step] is deterministic given [=st=]-equal inputs — registers and
775+
memory agree pointwise, and any read-out value from memory or
776+
registers matches). The conclusion uses [=st=] rather than
777+
syntactic equality because [Load]/[Store]/[Add] re-build records
778+
from [s2]'s components, which differ from [s1]'s on [state_pc] and
779+
are only [=mem=]-equal (not syntactically equal) on
780+
[state_memory]. *)
781+
Lemma step_respects_state_eq :
782+
forall s1 s2 i sm,
783+
s1 =st= s2 ->
784+
step s1 i sm ->
785+
exists sm', step s2 i sm' /\ sm =st= sm'.
786+
Proof.
787+
intros s1 s2 i sm Heq Hstep.
788+
destruct Heq as [Hmem [Hreg Hio]].
789+
destruct i.
790+
- (* Nop *)
791+
inversion Hstep; subst.
792+
exists (mkState s2.(state_memory) s2.(state_registers) s2.(state_io)
793+
(S s2.(state_pc))).
794+
split.
795+
+ constructor.
796+
+ unfold state_eq. simpl. split; [assumption | split; assumption].
797+
- (* Load addr reg *)
798+
apply step_load_inv in Hstep. subst sm.
799+
exists (mkState s2.(state_memory)
800+
(set_reg s2.(state_registers) n0
801+
(s2.(state_memory) n))
802+
s2.(state_io)
803+
(S s2.(state_pc))).
804+
split.
805+
+ econstructor. reflexivity.
806+
+ unfold state_eq. simpl. split; [assumption | split; [| assumption]].
807+
(* set_reg s1.regs n0 (s1.mem n) = set_reg s2.regs n0 (s2.mem n) *)
808+
rewrite Hreg.
809+
f_equal.
810+
apply Hmem.
811+
- (* Store addr reg *)
812+
apply step_store_inv in Hstep.
813+
destruct Hstep as [val [Hget Hsm]]. subst sm.
814+
exists (mkState (mem_update s2.(state_memory) n val)
815+
s2.(state_registers)
816+
s2.(state_io)
817+
(S s2.(state_pc))).
818+
split.
819+
+ econstructor. rewrite <- Hreg. exact Hget.
820+
+ unfold state_eq, mem_eq. simpl.
821+
split; [| split; assumption].
822+
(* mem_update s1.mem n val =mem= mem_update s2.mem n val *)
823+
intros addr.
824+
unfold mem_update.
825+
destruct (Nat.eqb addr n); [reflexivity | apply Hmem].
826+
- (* Add r1 r2 r3 *)
827+
apply step_add_inv in Hstep.
828+
destruct Hstep as [v1 [v2 [Hg1 [Hg2 Hsm]]]]. subst sm.
829+
exists (mkState s2.(state_memory)
830+
(set_reg s2.(state_registers) n1 (v1 + v2))
831+
s2.(state_io)
832+
(S s2.(state_pc))).
833+
split.
834+
+ econstructor; rewrite <- Hreg; eassumption.
835+
+ unfold state_eq. simpl. split; [assumption | split; [| assumption]].
836+
rewrite Hreg. reflexivity.
837+
- (* Jump target *)
838+
inversion Hstep; subst.
839+
exists (mkState s2.(state_memory) s2.(state_registers) s2.(state_io) n).
840+
split.
841+
+ constructor.
842+
+ unfold state_eq. simpl. split; [assumption | split; assumption].
843+
- (* Halt *)
844+
inversion Hstep; subst.
845+
exists s2.
846+
split.
847+
+ constructor.
848+
+ unfold state_eq. split; [assumption | split; assumption].
849+
Qed.
850+
851+
(** CRITICAL LEMMA: Evaluation respects state equality on the input side.
852+
853+
The original universal form
854+
[s =st= s' -> eval p s s'' -> eval p s' s'']
855+
is unsound under the relaxed 3-clause [state_eq] from Stage 2: the
856+
[eval_empty] base case would need [s = s'] syntactically, but
857+
[s =st= s'] only constrains memory + registers + I/O (not
858+
[state_pc]). Stage 3 (standards#157) accordingly reformulates the
859+
conclusion existentially: from [s1 =st= s2] and [eval p s1 s'] we
860+
obtain *some* [s''] reached by [p] starting from [s2], with
861+
[s' =st= s''] (i.e. final states agree modulo [state_pc]).
862+
863+
The proof is by induction on the [eval] derivation, using
864+
[step_respects_state_eq] to advance the witness one instruction at
865+
a time. *)
866+
Theorem eval_respects_state_eq_left :
867+
forall p s1 s2 s',
868+
s1 =st= s2 ->
869+
eval p s1 s' ->
870+
exists s'', eval p s2 s'' /\ s' =st= s''.
871+
Proof.
872+
intros p s1 s2 s' Heq Heval.
873+
generalize dependent s2.
874+
induction Heval as [s | i is sa sb sc Hstep_a Heval_rest IH];
875+
intros s2 Heq.
876+
- (* eval_empty: p = [], s' = s, witness s'' = s2 *)
877+
exists s2. split.
878+
+ constructor.
879+
+ assumption.
880+
- (* eval_step: step sa i sb, eval is sb sc *)
881+
destruct (step_respects_state_eq _ _ _ _ Heq Hstep_a)
882+
as [sb' [Hstep_b Heq_b]].
883+
destruct (IH sb' Heq_b) as [sc' [Heval_rest' Heq_c]].
884+
exists sc'. split.
885+
+ eapply eval_step; eassumption.
886+
+ assumption.
887+
Qed.
888+
889+
(** Symmetric form on the output side.
890+
891+
The output-side version is trivial under the existential
892+
reformulation: simply witness [s'' := s1]. We retain the
893+
statement (now a [Theorem] rather than an [Axiom]) so that
894+
downstream files have the symmetric API available. *)
895+
Theorem eval_respects_state_eq_right :
896+
forall p s s1 s2,
897+
eval p s s1 ->
898+
s1 =st= s2 ->
899+
exists s'', eval p s s'' /\ s'' =st= s2.
900+
Proof.
901+
intros p s s1 s2 Heval Heq.
902+
exists s1. split; assumption.
903+
Qed.
808904

809905
(** For CNOs specifically, if s =st= s', then eval p s s evaluates the same as eval p s' s' *)
810906
Lemma cno_eval_on_equal_states :
@@ -817,15 +913,16 @@ Proof.
817913
split.
818914
{ (* Forward direction *)
819915
intros [sx H_eval].
820-
exists sx.
821-
eapply eval_respects_state_eq_left;
822-
[ eassumption | assumption ].
916+
destruct (eval_respects_state_eq_left _ _ _ _ H_eq H_eval)
917+
as [sx' [H_eval' _]].
918+
exists sx'. assumption.
823919
}
824920
{ (* Backward direction *)
825921
intros [sx H_eval].
826-
exists sx.
827-
eapply eval_respects_state_eq_left;
828-
[ eassumption | apply state_eq_sym; assumption ].
922+
destruct (eval_respects_state_eq_left _ _ _ _
923+
(state_eq_sym _ _ H_eq) H_eval)
924+
as [sx' [H_eval' _]].
925+
exists sx'. assumption.
829926
}
830927
Qed.
831928

proofs/coq/physics/StatMech.v

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,20 @@ Qed.
238238
(** Bennett (1973): Computation can be made thermodynamically reversible
239239
by never erasing information, only permuting it. *)
240240

241-
(** A program is logically reversible if it's bijective *)
241+
(** A program is logically reversible if it's bijective.
242+
243+
Stage 3 (standards#157) note: the conclusion is phrased modulo
244+
[=st=] (the relaxed Stage-2 state equality that ignores
245+
[state_pc]) rather than strict equality on [s]. This is necessary
246+
because [eval] from a re-entered state may differ from [s] only on
247+
the program counter, and Stage 2 explicitly chose to ignore that
248+
field in the semantic notion of state-equivalence. The
249+
[cno_logically_reversible] proof below witnesses this directly. *)
242250
Definition logically_reversible (p : Program) : Prop :=
243251
exists p_inv : Program,
244252
forall s s',
245253
eval p s s' ->
246-
eval p_inv s' s.
254+
exists s_inv, eval p_inv s' s_inv /\ s_inv =st= s.
247255

248256
(** Logical reversibility implies thermodynamic reversibility *)
249257

@@ -279,7 +287,13 @@ Proof.
279287
reflexivity.
280288
Qed.
281289

282-
(** CNOs are trivially logically reversible (identity is its own inverse) *)
290+
(** CNOs are trivially logically reversible (identity is its own inverse).
291+
292+
Stage 3 (standards#157) note: with [logically_reversible] now
293+
phrased existentially modulo [=st=], the proof no longer needs an
294+
[eval_respects_state_eq_*] coercion: we witness the inverse run
295+
directly from CNO termination, then use the CNO state-preservation
296+
property to discharge the [=st=] obligation by transitivity. *)
283297
Theorem cno_logically_reversible :
284298
forall p : Program,
285299
is_CNO p ->
@@ -290,36 +304,28 @@ Proof.
290304
exists p. (* CNO is its own inverse *)
291305
intros s s' H_eval.
292306

293-
(* Key insight: For a CNO, eval p s s' implies s =st= s'
294-
So "reversing" just means running p again on s', which maps back to s.
295-
Since s =st= s', running p on s' gives a result =st= to s'. *)
296-
297307
(* Step 1: CNO property gives us s =st= s' *)
298308
assert (s =st= s') as H_state_eq.
299309
{ apply cno_preserves_state with (p := p) (s := s) (s' := s').
300310
- assumption.
301311
- assumption. }
302312

303-
(* Step 2: By termination, eval p s' s'' for some s'' *)
304-
destruct (cno_terminates p H_cno s') as [s'' H_eval'].
313+
(* Step 2: By termination, eval p s' s_inv for some s_inv *)
314+
destruct (cno_terminates p H_cno s') as [s_inv H_eval'].
305315

306-
(* Step 3: By CNO identity property, s'' =st= s' *)
307-
assert (s'' =st= s') as H_s''_eq_s'.
308-
{ apply cno_preserves_state with (p := p) (s := s') (s' := s'').
316+
(* Step 3: By CNO identity property, s' =st= s_inv *)
317+
assert (s' =st= s_inv) as H_s'_eq_s_inv.
318+
{ apply cno_preserves_state with (p := p) (s := s') (s' := s_inv).
309319
- assumption.
310320
- assumption. }
311321

312-
(* Step 4: By transitivity, s'' =st= s *)
313-
assert (s'' =st= s) as H_s''_eq_s.
314-
{ apply state_eq_trans with (s2 := s').
315-
- apply state_eq_sym. assumption.
316-
- apply state_eq_sym. assumption. }
317-
318-
(* Step 5: We have eval p s' s'' and s'' =st= s
319-
Apply eval_respects_state_eq_right to get eval p s' s *)
320-
apply eval_respects_state_eq_right with (s' := s'').
322+
(* Step 4: Witness s_inv satisfies eval p s' s_inv and s_inv =st= s *)
323+
exists s_inv. split.
321324
- exact H_eval'.
322-
- exact H_s''_eq_s.
325+
- (* s_inv =st= s by transitivity: s_inv =st= s' =st= s *)
326+
apply state_eq_trans with (s2 := s').
327+
+ apply state_eq_sym. assumption.
328+
+ apply state_eq_sym. assumption.
323329
Qed.
324330

325331
(** ** Physical Implications *)

0 commit comments

Comments
 (0)