threshold-computers / rocq /Abstract.v
phanerozoic's picture
Replace the two-bank machine with a K-bank ring, prove its reproduction in Rocq, and revise the paper
a9ea017
Raw History Blame Contribute Delete
24.9 kB
(* Within one pass, each head is seen through the cell under it when the pass starts and what the pass
does to it: the value it writes there, the cells it moves, whether it returns to its origin and
whether its bank or tape is cleared; the active bank through the index of the record at its head.
One step of the machine refines one step of this abstract machine. *)
From Stdlib Require Import List Bool Arith ZArith Lia.
Import ListNotations.
From TH Require Import TwoHead Net.
Record ahead := mkH { acur : bool; awr : option bool; amv : nat; arw : bool; acl : bool }.
(* the head is still on its first cell and its store is untouched but for its own write there *)
Definition hok (h : ahead) : bool := Nat.eqb (amv h) 0 && negb (arw h) && negb (acl h).
Definition hval (h : ahead) : bool := match awr h with Some v => v | None => acur h end.
Definition hwrite (h : ahead) (v : bool) : ahead := mkH (acur h) (Some v) (amv h) (arw h) (acl h).
Definition hadv (h : ahead) : ahead := mkH (acur h) (awr h) (S (amv h)) (arw h) (acl h).
Definition hrew (h : ahead) : ahead := mkH (acur h) (awr h) 0 true (acl h).
Definition hclr (h : ahead) : ahead := mkH (acur h) (awr h) (amv h) (arw h) true.
Record ast := mkAS { aw : list bool; aR : ahead; aA : ahead; aK : ahead; ai : nat; aho : bool; bad : bool }.
Definition acell (t : ast) (x : nat) : bool :=
if Nat.eqb x SINK then false
else if Nat.eqb x RD then hval (aR t)
else if Nat.eqb x ARM then hval (aA t)
else if Nat.eqb x CPY then hval (aK t)
else wget (aw t) x.
(* an operand with a nonzero weight on a head cell must find the head on its first cell *)
Definition opok (t : ast) (x : nat) (w : Z) : bool :=
if Z.eqb w 0 then true
else if Nat.eqb x RD then hok (aR t)
else if Nat.eqb x ARM then hok (aA t)
else if Nat.eqb x CPY then hok (aK t)
else true.
Definition astepres (rs : list rec) (t : ast) (a0 : nat) (w0 : Z) (a1 : nat) (w1 : Z) (ao : nat) (v : bool) : ast :=
let wn := wnext (aw t) ao v in
let A1 := if Nat.eqb ao ARM then hwrite (aA t) v else aA t in
let K1 := if Nat.eqb ao CPY then hwrite (aK t) v else aK t in
let okw := (if Nat.eqb ao ARM then hok (aA t) else true) && (if Nat.eqb ao CPY then hok (aK t) else true) in
let R2 := if wget wn RR then hrew (aR t) else if wget wn AR then hadv (aR t) else aR t in
let A1' := if wget wn CB then hclr A1 else A1 in
let A2 := if wget wn RA then hrew A1' else if wget wn AA then hadv A1' else A1' in
let K1' := if wget wn CT then hclr K1 else K1 in
let K2 := if wget wn RC then hrew K1' else if wget wn AC then hadv K1' else K1' in
let okho := negb (wget wn HO) || Nat.eqb (S (ai t)) (length rs) in
mkAS (clearq wn) R2 A2 K2 (S (ai t)) (aho t || wget wn HO)
(bad t || aho t || negb (opok t a0 w0 && opok t a1 w1 && okw && okho)).
Definition astep (rs : list rec) (t : ast) : ast :=
match nth_error rs (ai t) with
| None => mkAS (aw t) (aR t) (aA t) (aK t) (ai t) (aho t) true
| Some (Rec a0 w0 a1 w1 beta ao) =>
astepres rs t a0 w0 a1 w1 ao (Z.leb 0 (w0 * b2z (acell t a0) + w1 * b2z (acell t a1) + beta)%Z)
end.
Fixpoint aiter (n : nat) (rs : list rec) (t : ast) : ast :=
match n with O => t | S m => aiter m rs (astep rs t) end.
Definition enc (rs : list rec) : list bool := concat (map enc_rec rs).
(* ---- the effect of a pass on a tape and on a bank ---------------------------------------------- *)
Fixpoint iter {A : Type} (n : nat) (f : A -> A) (x : A) : A := match n with O => x | S m => f (iter m f x) end.
Definition tape_eff (L : nat) (h : ahead) (t : tape) : tape :=
mkT (if acl h then repeat false L else match awr h with Some v => upd (td t) (th t) v | None => td t end)
(iter (amv h) (succ_mod L) (if arw h then 0 else th t)).
Definition bank_eff (S0 b : nat) (h : ahead) (q : bank) : bank :=
iter (amv h) (advb S0 b)
(mkB (if acl h then repeat false (S0 * b) else
match awr h with Some v => upd (bq q) (bs q * b + bj q) v | None => bq q end)
(if arw h then 0 else bs q) (if arw h then 0 else bj q)).
(* ---- lists ------------------------------------------------------------------------------------- *)
Lemma upd_length : forall l i v, length (upd l i v) = length l.
Proof. induction l as [|x l IH]; intros [|i] v; cbn; auto. Qed.
Lemma nth_upd_same : forall l i v, i < length l -> nth i (upd l i v) false = v.
Proof. induction l as [|x l IH]; intros [|i] v Hi; cbn in *; try lia; auto. apply IH. lia. Qed.
Lemma nth_upd_other : forall l i j v, i <> j -> nth j (upd l i v) false = nth j l false.
Proof.
induction l as [|x l IH]; intros i j v Hij; [reflexivity|].
destruct i as [|i], j as [|j]; cbn; try reflexivity; [lia|]. apply IH. lia.
Qed.
Lemma upd_upd : forall l i v w, upd (upd l i v) i w = upd l i w.
Proof. induction l as [|x l IH]; intros [|i] v w; cbn; f_equal; auto. Qed.
Lemma upd_same : forall l i, upd l i (nth i l false) = l.
Proof. induction l as [|x l IH]; intros [|i]; cbn; f_equal; auto. Qed.
Lemma wget_upd : forall w i v x,
wget (upd w i v) x = if Nat.eqb x i && Nat.ltb i (length w) then v else wget w x.
Proof.
unfold wget. induction w as [|y w IH]; intros i v x.
- simpl. rewrite andb_false_r. destruct x; reflexivity.
- destruct i as [|i], x as [|x]; simpl; try reflexivity; rewrite IH; reflexivity.
Qed.
Lemma length_wnext : forall w ao v, length (wnext w ao v) = length w.
Proof. intros w ao v; unfold wnext. destruct (Nat.leb ao CPY); [reflexivity | apply upd_length]. Qed.
Lemma length_clearq : forall w, length (clearq w) = length w.
Proof. intro w; unfold clearq. rewrite !upd_length. reflexivity. Qed.
(* the cells from 4 on: two windows agree there *)
Definition agree (w w' : list bool) : Prop := forall x, 4 <= x -> wget w x = wget w' x.
Lemma agree_upd : forall w w' i v, agree w w' -> length w = length w' -> agree (upd w i v) (upd w' i v).
Proof.
intros w w' i v H Hl x Hx. rewrite !wget_upd, Hl.
destruct (Nat.eqb x i && Nat.ltb i (length w')); auto.
Qed.
Lemma agree_wnext : forall w w' ao v, agree w w' -> length w = length w' -> agree (wnext w ao v) (wnext w' ao v).
Proof. intros w w' ao v H Hl; unfold wnext. destruct (Nat.leb ao CPY); auto using agree_upd. Qed.
Lemma agree_clearq : forall w w', agree w w' -> length w = length w' -> agree (clearq w) (clearq w').
Proof.
intros w w' H Hl; unfold clearq.
repeat (apply agree_upd; [|rewrite ?upd_length; auto]). exact H.
Qed.
Lemma iter_advb_bq : forall S1 b' n q, bq (iter n (advb S1 b') q) = bq q.
Proof.
intros S1 b' n. induction n as [|n IH]; intro q; [reflexivity|].
change (bq (advb S1 b' (iter n (advb S1 b') q)) = bq q).
transitivity (bq (iter n (advb S1 b') q)); [|apply IH].
set (X := iter n (advb S1 b') q). unfold advb. destruct (Nat.eqb (S (bj X)) b'); reflexivity.
Qed.
(* the arm's moves do not depend on the bits of the bank *)
Lemma iter_advb_mkB : forall S1 b' n X Y s j,
iter n (advb S1 b') (mkB X s j) = mkB X (bs (iter n (advb S1 b') (mkB Y s j))) (bj (iter n (advb S1 b') (mkB Y s j))).
Proof.
intros S1 b' n. induction n as [|n IH]; intros X Y s j; [reflexivity|]. cbn [iter].
rewrite (IH X Y s j). set (Z := iter n (advb S1 b') (mkB Y s j)). unfold advb. cbn [bq bs bj].
destruct (Nat.eqb (S (bj Z)) b'); reflexivity.
Qed.
Lemma succ_mod_mod : forall n x, 1 <= n -> succ_mod n (x mod n) = S x mod n.
Proof.
intros n x Hn. pose proof (Nat.mod_upper_bound x n ltac:(lia)) as H.
rewrite <- Nat.add_1_r, <- Nat.Div0.add_mod_idemp_l. unfold succ_mod.
destruct (Nat.eqb_spec (S (x mod n)) n) as [E|E].
- rewrite Nat.add_1_r, E. symmetry. apply Nat.Div0.mod_same.
- rewrite Nat.add_1_r. symmetry. apply Nat.mod_small. lia.
Qed.
(* ---- one step of the machine, against one step of the abstract machine ------------------------ *)
Section Refine.
Variables (al K S0 L : nat) (rs : list rec) (s0 : st).
Hypotheses (HK : 2 <= K) (HS : 1 <= S0) (HL : 1 <= L) (Hfit : fits al K S0 L s0).
Let k0 := kap s0.
Let i0 := succ_mod K k0.
Let b := recw al.
(* the concrete state s and the abstract state t agree, from the state s0 that started the pass *)
Definition rel (s : st) (t : ast) : Prop :=
agree (win s) (aw t) /\ length (win s) = 2 ^ al /\ length (aw t) = 2 ^ al
/\ kap s = (if aho t then i0 else k0)
/\ length (banks s) = K /\ length (tapes s) = K
/\ nth k0 (banks s) bank0 = mkB (bq (nth k0 (banks s0) bank0)) (ai t) (bj (nth k0 (banks s0) bank0))
/\ nth i0 (banks s) bank0 = bank_eff S0 b (aA t) (nth i0 (banks s0) bank0)
/\ nth k0 (tapes s) tape0 = tape_eff L (aR t) (nth k0 (tapes s0) tape0)
/\ nth i0 (tapes s) tape0 = tape_eff L (aK t) (nth i0 (tapes s0) tape0)
/\ (forall x, x < K -> x <> k0 -> x <> i0 -> nth x (banks s) bank0 = nth x (banks s0) bank0)
/\ (forall x, x < K -> x <> k0 -> x <> i0 -> nth x (tapes s) tape0 = nth x (tapes s0) tape0)
/\ acur (aR t) = tget (nth k0 (tapes s0) tape0)
/\ acur (aA t) = bget al (nth i0 (banks s0) bank0)
/\ acur (aK t) = tget (nth i0 (tapes s0) tape0)
/\ awr (aR t) = None.
Lemma k0_lt : k0 < K.
Proof. destruct Hfit as (_ & H & _). exact H. Qed.
Lemma i0_lt : i0 < K.
Proof. unfold i0, succ_mod. pose proof k0_lt. destruct (Nat.eqb_spec (S k0) K); lia. Qed.
Lemma i0_k0 : i0 <> k0.
Proof. unfold i0, succ_mod. pose proof k0_lt. destruct (Nat.eqb_spec (S k0) K); lia. Qed.
Lemma bank0_ok : forall x, x < K -> length (bq (nth x (banks s0) bank0)) = S0 * b
/\ bs (nth x (banks s0) bank0) < S0 /\ bj (nth x (banks s0) bank0) < b.
Proof. intros x Hx. destruct Hfit as (_ & _ & _ & _ & H & _). apply H. exact Hx. Qed.
Lemma tape0_ok : forall x, x < K -> length (td (nth x (tapes s0) tape0)) = L /\ th (nth x (tapes s0) tape0) < L.
Proof. intros x Hx. destruct Hfit as (_ & _ & _ & _ & _ & H). apply H. exact Hx. Qed.
(* reading a head cell of a related state, the head being on its first cell *)
Lemma tget_eff : forall h t0, hok h = true -> th t0 < length (td t0) ->
tget (tape_eff L h t0) = match awr h with Some v => v | None => tget t0 end.
Proof.
intros h t0 Hok Ht. unfold hok in Hok. destruct h as [c w m r cl]. cbn [amv arw acl] in Hok.
destruct m; [|discriminate]. destruct r, cl; try discriminate.
unfold tape_eff, tget. cbn [acl awr amv arw iter td th]. destruct w; [apply nth_upd_same; exact Ht | reflexivity].
Qed.
Lemma bget_eff : forall h q, hok h = true -> bs q * b + bj q < length (bq q) ->
bget al (bank_eff S0 b h q) = match awr h with Some v => v | None => bget al q end.
Proof.
intros h q Hok Hq. unfold hok in Hok. destruct h as [c w m r cl]. cbn [amv arw acl] in Hok.
destruct m; [|discriminate]. destruct r, cl; try discriminate.
unfold bank_eff, bget, apos. cbn [acl awr amv arw iter bq bs bj]. fold b.
destruct w; [apply nth_upd_same; exact Hq | reflexivity].
Qed.
(* the concrete operations on the effect of a head *)
Lemma tape_eff_write : forall h t0 v, hok h = true ->
mkT (upd (td (tape_eff L h t0)) (th (tape_eff L h t0)) v) (th (tape_eff L h t0)) = tape_eff L (hwrite h v) t0.
Proof.
intros h t0 v Hok. unfold hok in Hok. destruct h as [c w m r cl]. cbn [amv arw acl] in Hok.
destruct m; [|discriminate]. destruct r, cl; try discriminate.
unfold tape_eff, hwrite. cbn [acl awr amv arw iter td th acur]. f_equal. destruct w; [apply upd_upd | reflexivity].
Qed.
Lemma tape_eff_adv : forall h t0, mkT (td (tape_eff L h t0)) (succ_mod L (th (tape_eff L h t0))) = tape_eff L (hadv h) t0.
Proof. intros. reflexivity. Qed.
Lemma tape_eff_rew : forall h t0, mkT (td (tape_eff L h t0)) 0 = tape_eff L (hrew h) t0.
Proof. intros. reflexivity. Qed.
Lemma tape_eff_clr : forall h t0, mkT (repeat false L) (th (tape_eff L h t0)) = tape_eff L (hclr h) t0.
Proof. intros. reflexivity. Qed.
Lemma bank_eff_write : forall h q v, hok h = true ->
mkB (upd (bq (bank_eff S0 b h q)) (apos al (bank_eff S0 b h q)) v) (bs (bank_eff S0 b h q)) (bj (bank_eff S0 b h q))
= bank_eff S0 b (hwrite h v) q.
Proof.
intros h q v Hok. unfold hok in Hok. destruct h as [c w m r cl]. cbn [amv arw acl] in Hok.
destruct m; [|discriminate]. destruct r, cl; try discriminate.
unfold bank_eff, hwrite, apos. cbn [acl awr amv arw iter bq bs bj acur]. fold b. f_equal.
destruct w; [apply upd_upd | reflexivity].
Qed.
Lemma bank_eff_adv : forall h q, advb S0 b (bank_eff S0 b h q) = bank_eff S0 b (hadv h) q.
Proof. intros. reflexivity. Qed.
Lemma bank_eff_rew : forall h q, mkB (bq (bank_eff S0 b h q)) 0 0 = bank_eff S0 b (hrew h) q.
Proof.
intros [c w m r cl] q. unfold bank_eff, hrew. cbn [acl awr amv arw iter bq bs bj acur].
rewrite iter_advb_bq. reflexivity.
Qed.
Lemma bank_eff_clr : forall h q,
mkB (repeat false (S0 * b)) (bs (bank_eff S0 b h q)) (bj (bank_eff S0 b h q)) = bank_eff S0 b (hclr h) q.
Proof.
intros [c w m r cl] q. unfold bank_eff, hclr. cbn [acl awr amv arw acur].
symmetry. apply (iter_advb_mkB S0 b m (repeat false (S0 * b))).
Qed.
Lemma eta_bank : forall q, mkB (bq q) (bs q) (bj q) = q.
Proof. intros [x y z]. reflexivity. Qed.
Lemma eta_tape : forall t, mkT (td t) (th t) = t.
Proof. intros [x y]. reflexivity. Qed.
(* the active bank holds the records rs from its first slot *)
Hypothesis Hdec : forall r, In r rs -> decodeA al (enc_recA al r) = r.
Hypothesis Hact : forall a r, nth_error rs a = Some r ->
firstn b (skipn (a * b) (bq (nth k0 (banks s0) bank0))) = enc_recA al r.
Hypothesis Hrs : length rs <= S0.
Definition relA (s : st) (t : ast) : Prop :=
agree (win s) (aw t) /\ length (win s) = 2 ^ al /\ length (aw t) = 2 ^ al
/\ kap s = (if aho t then i0 else k0)
/\ length (banks s) = K /\ length (tapes s) = K
/\ nth k0 (banks s) bank0 = mkB (bq (nth k0 (banks s0) bank0)) (ai t mod S0) (bj (nth k0 (banks s0) bank0))
/\ nth i0 (banks s) bank0 = bank_eff S0 b (aA t) (nth i0 (banks s0) bank0)
/\ nth k0 (tapes s) tape0 = tape_eff L (aR t) (nth k0 (tapes s0) tape0)
/\ nth i0 (tapes s) tape0 = tape_eff L (aK t) (nth i0 (tapes s0) tape0)
/\ (forall x, x < K -> x <> k0 -> x <> i0 -> nth x (banks s) bank0 = nth x (banks s0) bank0)
/\ (forall x, x < K -> x <> k0 -> x <> i0 -> nth x (tapes s) tape0 = nth x (tapes s0) tape0)
/\ acur (aR t) = tget (nth k0 (tapes s0) tape0)
/\ acur (aA t) = bget al (nth i0 (banks s0) bank0)
/\ acur (aK t) = tget (nth i0 (tapes s0) tape0)
/\ awr (aR t) = None.
Lemma head_ops_acur : forall h v,
acur (hwrite h v) = acur h /\ acur (hadv h) = acur h /\ acur (hrew h) = acur h /\ acur (hclr h) = acur h.
Proof. intros. repeat split. Qed.
Lemma step_refines : forall s t,
relA s t -> ai t < length rs -> aho t = false -> bad (astep rs t) = false ->
relA (step al K S0 L s) (astep rs t).
Proof.
intros s t Hrel Hi Hho Hbad. pose proof k0_lt as Hk0. pose proof i0_lt as Hi0. pose proof i0_k0 as Hik.
destruct Hrel as (Hw & Hlw & Hla & Hkap & HlB & HlT & HA & HI & HR & HC & HoB & HoT & cR & cA & cK & wR).
rewrite Hho in Hkap.
destruct (nth_error rs (ai t)) as [r|] eqn:Er; [|apply nth_error_None in Er; lia].
assert (Hdr : decodeA al (enc_recA al r) = r) by (apply Hdec; eapply nth_error_In; exact Er).
destruct r as [a0 w0 a1 w1 beta ao].
(* the abstract step and its checks *)
unfold astep in Hbad |- *. rewrite Er in Hbad |- *.
set (va := Z.leb 0 (w0 * b2z (acell t a0) + w1 * b2z (acell t a1) + beta)%Z) in *.
unfold astepres in Hbad. cbv zeta in Hbad. cbn [bad] in Hbad.
rewrite Hho in Hbad. apply orb_false_iff in Hbad as [Hb0 Hb]. apply orb_false_iff in Hb0 as [Hb0 _].
apply negb_false_iff in Hb.
apply andb_prop in Hb as [Hb Hokho]. apply andb_prop in Hb as [Hb Hokw]. apply andb_prop in Hb as [Hop0 Hop1].
assert (OkA : Nat.eqb ao ARM = true -> hok (aA t) = true)
by (intro E; rewrite E in Hokw; apply andb_prop in Hokw as [H _]; exact H).
assert (OkK : Nat.eqb ao CPY = true -> hok (aK t) = true)
by (intro E; rewrite E in Hokw; apply andb_prop in Hokw as [_ H]; exact H).
(* the concrete step reads the record at slot ai t of the active bank *)
destruct (bank0_ok k0 Hk0) as (Hq0 & _ & _). destruct (bank0_ok i0 Hi0) as (Hqi & Hsi & Hji).
destruct (tape0_ok k0 Hk0) as (Hd0 & Ht0). destruct (tape0_ok i0 Hi0) as (Hdi & Hti).
assert (Hslot : slot al (nth (kap s) (banks s) bank0) = enc_recA al (Rec a0 w0 a1 w1 beta ao)).
{ rewrite Hkap, HA. unfold slot. cbn [bq bs]. rewrite Nat.mod_small by lia. apply Hact. exact Er. }
(* the cells the record reads are those of the abstract state *)
assert (Hcell : forall a w, opok t a w = true -> (w * b2z (cellof al K s a) = w * b2z (acell t a))%Z).
{ intros a w Ho. unfold opok in Ho. unfold cellof, acell. rewrite Hkap. fold i0.
destruct (Z.eqb_spec w 0) as [Ew|Ew]; [rewrite Ew; reflexivity|].
destruct (Nat.eqb_spec a SINK); [reflexivity|].
destruct (Nat.eqb_spec a RD).
{ rewrite HR, (tget_eff (aR t) _ Ho) by lia. rewrite wR. unfold hval. rewrite wR, cR. reflexivity. }
destruct (Nat.eqb_spec a ARM).
{ rewrite HI, (bget_eff (aA t) _ Ho) by (rewrite Hqi; unfold b; nia).
unfold hval. destruct (awr (aA t)); [reflexivity|]. rewrite cA. reflexivity. }
destruct (Nat.eqb_spec a CPY).
{ rewrite HC, (tget_eff (aK t) _ Ho) by lia.
unfold hval. destruct (awr (aK t)); [reflexivity|]. rewrite cK. reflexivity. }
rewrite Hw by (unfold SINK, RD, ARM, CPY in *; lia). reflexivity. }
assert (Hv : Z.leb 0 (w0 * b2z (cellof al K s a0) + w1 * b2z (cellof al K s a1) + beta)%Z = va).
{ unfold va. rewrite (Hcell a0 w0 Hop0), (Hcell a1 w1 Hop1). reflexivity. }
unfold step. rewrite Hslot, Hdr. rewrite Hv.
(* the state after the step *)
assert (Hag : agree (wnext (win s) ao va) (wnext (aw t) ao va)) by (apply agree_wnext; [exact Hw | congruence]).
assert (Hq : forall c, 4 <= c -> wget (wnext (win s) ao va) c = wget (wnext (aw t) ao va) c) by (intros; apply Hag; lia).
unfold stepres, astepres. cbv zeta. rewrite Hkap. fold i0.
rewrite !Hq by (unfold AR, AA, AC, RR, RA, RC, CB, CT, HO; lia).
refine (conj _ (conj _ (conj _ (conj _ (conj _ (conj _ (conj _ (conj _ (conj _ (conj _ (conj _ (conj _ _)))))))))))).
- cbn [win aw]. apply agree_clearq; [exact Hag | rewrite !length_wnext; congruence].
- cbn [win]. rewrite length_clearq, length_wnext. exact Hlw.
- cbn [aw]. rewrite length_clearq, length_wnext. exact Hla.
- cbn [kap aho]. rewrite Hho. cbn [orb]. reflexivity.
- cbn [banks]. rewrite length_map, length_seq. reflexivity.
- cbn [tapes]. rewrite length_map, length_seq. reflexivity.
- (* the active bank *)
cbn [banks ai]. rewrite (nth_map_seq _ _ K k0 bank0 Hk0), Nat.eqb_refl. rewrite HA. cbn [bq bs bj].
rewrite succ_mod_mod by lia. reflexivity.
- (* the idle bank *)
cbn [banks aA]. rewrite (nth_map_seq _ _ K i0 bank0 Hi0), (proj2 (Nat.eqb_neq i0 k0) Hik), Nat.eqb_refl. rewrite HI.
assert (HI1 : (if Nat.eqb ao ARM
then mkB (upd (bq (bank_eff S0 b (aA t) (nth i0 (banks s0) bank0)))
(apos al (bank_eff S0 b (aA t) (nth i0 (banks s0) bank0))) va)
(bs (bank_eff S0 b (aA t) (nth i0 (banks s0) bank0)))
(bj (bank_eff S0 b (aA t) (nth i0 (banks s0) bank0)))
else bank_eff S0 b (aA t) (nth i0 (banks s0) bank0))
= bank_eff S0 b (if Nat.eqb ao ARM then hwrite (aA t) va else aA t) (nth i0 (banks s0) bank0)).
{ destruct (Nat.eqb ao ARM) eqn:E; [|reflexivity]. apply bank_eff_write. apply OkA. reflexivity. }
rewrite HI1. set (A1 := if Nat.eqb ao ARM then hwrite (aA t) va else aA t).
assert (HI1' : mkB (if wget (wnext (aw t) ao va) CB then repeat false (S0 * recw al) else bq (bank_eff S0 b A1 (nth i0 (banks s0) bank0)))
(bs (bank_eff S0 b A1 (nth i0 (banks s0) bank0))) (bj (bank_eff S0 b A1 (nth i0 (banks s0) bank0)))
= bank_eff S0 b (if wget (wnext (aw t) ao va) CB then hclr A1 else A1) (nth i0 (banks s0) bank0)).
{ destruct (wget (wnext (aw t) ao va) CB); [apply bank_eff_clr | apply eta_bank]. }
rewrite HI1'. set (A1' := if wget (wnext (aw t) ao va) CB then hclr A1 else A1).
destruct (wget (wnext (aw t) ao va) RA); [apply bank_eff_rew|].
destruct (wget (wnext (aw t) ao va) AA); [apply bank_eff_adv | reflexivity].
- (* the read tape *)
cbn [tapes aR]. rewrite (nth_map_seq _ _ K k0 tape0 Hk0), Nat.eqb_refl. rewrite HR.
destruct (wget (wnext (aw t) ao va) RR); [apply tape_eff_rew|].
destruct (wget (wnext (aw t) ao va) AR); [apply tape_eff_adv | apply eta_tape].
- (* the copy tape *)
cbn [tapes aK]. rewrite (nth_map_seq _ _ K i0 tape0 Hi0), (proj2 (Nat.eqb_neq i0 k0) Hik), Nat.eqb_refl. rewrite HC.
assert (HC1 : (if Nat.eqb ao CPY
then mkT (upd (td (tape_eff L (aK t) (nth i0 (tapes s0) tape0))) (th (tape_eff L (aK t) (nth i0 (tapes s0) tape0))) va)
(th (tape_eff L (aK t) (nth i0 (tapes s0) tape0)))
else tape_eff L (aK t) (nth i0 (tapes s0) tape0))
= tape_eff L (if Nat.eqb ao CPY then hwrite (aK t) va else aK t) (nth i0 (tapes s0) tape0)).
{ destruct (Nat.eqb ao CPY) eqn:E; [|reflexivity]. apply tape_eff_write. apply OkK. reflexivity. }
rewrite HC1. set (K1 := if Nat.eqb ao CPY then hwrite (aK t) va else aK t).
assert (HC1' : mkT (if wget (wnext (aw t) ao va) CT then repeat false L else td (tape_eff L K1 (nth i0 (tapes s0) tape0)))
(th (tape_eff L K1 (nth i0 (tapes s0) tape0)))
= tape_eff L (if wget (wnext (aw t) ao va) CT then hclr K1 else K1) (nth i0 (tapes s0) tape0)).
{ destruct (wget (wnext (aw t) ao va) CT); [apply tape_eff_clr | apply eta_tape]. }
transitivity (let C1' := tape_eff L (if wget (wnext (aw t) ao va) CT then hclr K1 else K1) (nth i0 (tapes s0) tape0) in
mkT (td C1') (if wget (wnext (aw t) ao va) RC then 0
else if wget (wnext (aw t) ao va) AC then succ_mod L (th C1') else th C1')).
{ cbv zeta. rewrite <- HC1'. cbn [td th]. reflexivity. }
cbv zeta. set (K1' := if wget (wnext (aw t) ao va) CT then hclr K1 else K1).
destruct (wget (wnext (aw t) ao va) RC); [apply tape_eff_rew|].
destruct (wget (wnext (aw t) ao va) AC); [apply tape_eff_adv | apply eta_tape].
- (* the other banks *)
intros x Hx E1 E2. cbn [banks]. rewrite (nth_map_seq _ _ K x bank0 Hx).
rewrite (proj2 (Nat.eqb_neq x k0) E1), (proj2 (Nat.eqb_neq x i0) E2). apply HoB; assumption.
- (* the other tapes *)
intros x Hx E1 E2. cbn [tapes]. rewrite (nth_map_seq _ _ K x tape0 Hx).
rewrite (proj2 (Nat.eqb_neq x k0) E1), (proj2 (Nat.eqb_neq x i0) E2). apply HoT; assumption.
- (* the cells under the heads when the pass started, and the read tape never written *)
cbn [aR aA aK]. refine (conj _ (conj _ (conj _ _))).
+ destruct (wget (wnext (aw t) ao va) RR); [|destruct (wget (wnext (aw t) ao va) AR)]; exact cR.
+ destruct (wget (wnext (aw t) ao va) RA), (wget (wnext (aw t) ao va) AA), (wget (wnext (aw t) ao va) CB),
(Nat.eqb ao ARM); exact cA.
+ destruct (wget (wnext (aw t) ao va) RC), (wget (wnext (aw t) ao va) AC), (wget (wnext (aw t) ao va) CT),
(Nat.eqb ao CPY); exact cK.
+ destruct (wget (wnext (aw t) ao va) RR); [|destruct (wget (wnext (aw t) ao va) AR)]; exact wR.
Qed.
Lemma bad_mono : forall n t, bad t = true -> bad (aiter n rs t) = true.
Proof.
induction n as [|n IH]; intros t H; cbn [aiter]; [exact H|].
apply IH. unfold astep. destruct (nth_error rs (ai t)) as [[a0 w0 a1 w1 beta ao]|]; [|reflexivity].
unfold astepres. cbv zeta. cbn [bad]. rewrite H. reflexivity.
Qed.
Lemma astep_clean : forall t, bad (astep rs t) = false -> bad t = false /\ aho t = false.
Proof.
intros t H. unfold astep in H. destruct (nth_error rs (ai t)) as [[a0 w0 a1 w1 beta ao]|]; [|discriminate].
unfold astepres in H. cbv zeta in H. cbn [bad] in H.
apply orb_false_iff in H as [H _]. apply orb_false_iff in H as [H1 H2]. split; assumption.
Qed.
Lemma astep_ai : forall t, ai t < length rs -> ai (astep rs t) = S (ai t).
Proof.
intros t H. unfold astep. destruct (nth_error rs (ai t)) as [[a0 w0 a1 w1 beta ao]|] eqn:E; [reflexivity|].
apply nth_error_None in E. lia.
Qed.
Lemma aiter_ai : forall n t, ai t + n <= length rs -> ai (aiter n rs t) = ai t + n.
Proof.
induction n as [|n IH]; intros t H; cbn [aiter]; [lia|]. rewrite IH; rewrite ?astep_ai; lia.
Qed.
(* a pass of the machine refines the abstract pass, as long as the abstract pass is not bad *)
Lemma pass_refines : forall n s t, relA s t -> ai t + n <= length rs -> bad (aiter n rs t) = false ->
relA (itern al K S0 L n s) (aiter n rs t).
Proof.
induction n as [|n IH]; intros s t Hrel Hn Hbad; [exact Hrel|].
cbn [itern aiter] in *.
assert (Hb1 : bad (astep rs t) = false).
{ destruct (bad (astep rs t)) eqn:E; [|reflexivity]. rewrite (bad_mono n _ E) in Hbad. discriminate. }
destruct (astep_clean t Hb1) as [_ Hho].
apply IH; [apply step_refines; auto; lia | rewrite astep_ai; lia | exact Hbad].
Qed.
End Refine.