File size: 24,909 Bytes
a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 7e1c831 a9ea017 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 | (* 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.
|