I have two comments, first, your statement about "register number 2" seems a bit adhoc. Why 2? What happens if the number or registers is 1?
Trying to prove this kind of too-specific lemmas usually complicate proofs in Coq. You would do better trying to prove a more general lemma, such as "for a n-register machine, setting the k < n register twice is idempotent." A proof of that result is in the library as set_set_nth
. You could combine setting with a "set zero" register operation. I did the proof as you stated it you can compare how the arbitrary 2 complicates size reasoning here:
From mathcomp
Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Implicit Type (reg : seq nat).
(* You could also use take/drop to perform surgery *)
Definition clear_regs reg :=
set_nth 0 (nseq (size reg) 0) 2 (nth 0 reg 2).
Definition idem A (f : A -> A) := forall x, f (f x) = f x.
Lemma clear_regs_idem : idem clear_regs.
Proof.
(* We reduce equality of lists to equality of their elements, `eq_from_nth` *)
move=> reg; apply: (@eq_from_nth _ 0).
by rewrite !size_set_nth !size_nseq maxnA maxnn.
(* Now we need to use the fact that nth (set s x) = x, plus a bit of case reasoning *)
move=> i i_sz; rewrite !nth_set_nth /=; case: eqP => [//|].
by rewrite !nth_nseq; case: ifP; case: ifP.
Qed.
Note that the proof is induction-free as all the needed induction is encapsulated in the higher-level seq lemmas! I guess you may have had a hard time doing a single induction to prove this lemma as you would likely need to setup a quite complicated induction hypothesis. Thus, it is better to compose several smaller ones.
A different and likely better approach is to use a stronger representation for your registers. In particular, I've chosen to use a nice datatype mathcomp has which is called "finitely supported functions", that is, a map from a finite datatype. The, we represent n registers by a map 'I_n.+1 -> nat
where 'I_n
is the type of natural numbers less than n. Even in your adhoc case, you can see that it works quite well:
From mathcomp
Require Import choice fintype finfun.
Section Regs.
Variable k : nat.
Definition reg := {ffun 'I_k.+1 -> nat}.
Implicit Type (r : reg).
Definition clearr r : reg :=
[ffun idx => if idx == (inord 2) then r (inord 2) else 0].
Lemma clearr_idem : idem clearr.
Proof. by move=> x; apply/ffunP=> j; rewrite !ffunE eqxx. Qed.
The ffunP
lemma is map extensionality: two maps are equal iff they map to the same elements, the rest is routine (eqxx will rewrite x == x
to true
.
Here you have runnable code: https://x80.org/collacoq/omemesamoy.coq let me know of any questions.
Regards, E.