Download rocq/Lev.v from phanerozoic/threshold-computers: direct link, hf CLI and curl.
- Browser
- Download file 39.8 kB
-
https://huggingface.co/phanerozoic/threshold-computers/resolve/main/rocq/Lev.v
- Command line
-
hf download hf://phanerozoic/threshold-computers/rocq/Lev.v
-
curl -L -o Lev.v https://huggingface.co/phanerozoic/threshold-computers/resolve/main/rocq/Lev.v
39.8 kB
| (* Levelization (Lemma 2.5): a clocked netlist whose units have maximal depth d >= 1 is computed by a layered map | |
| of depth d. Each unit that contributes to a next value occurs in it with its weights and bias, once if its | |
| depth is less than d and once for each state bit whose next value it is if its depth is d, and every other row | |
| is an identity unit. *) | |
| From Stdlib Require Import List Bool Arith ZArith Lia. | |
| Import ListNotations. | |
| From TH Require Import TwoHead Net. | |
| (* ---- layered maps (Definition 2.3) ----------------------------------------------------------------------- *) | |
| (* a layer: rows reading the outputs of the layer before by position *) | |
| Definition lfire (L : list tu) (y : list bool) : list bool := map (fun u => fire u (fun i => nth i y false)) L. | |
| Definition lmap (Ls : list (list tu)) (x : list bool) : list bool := fold_left (fun y L => lfire L y) Ls x. | |
| (* the rows of each layer read positions of the layer before, distinct ones, with weights -1 or 1 *) | |
| Definition rowok (w : nat) (u : tu) : Prop := | |
| NoDup (map fst (tin u)) /\ forall i z, In (i, z) (tin u) -> i < w /\ (z = 1 \/ z = -1)%Z. | |
| Fixpoint lwf (w : nat) (Ls : list (list tu)) : Prop := | |
| match Ls with [] => True | L :: t => Forall (rowok w) L /\ lwf (length L) t end. | |
| Lemma lmap_app : forall Ls L x, lmap (Ls ++ [L]) x = lfire L (lmap Ls x). | |
| Proof. intros Ls L x. unfold lmap. rewrite fold_left_app. reflexivity. Qed. | |
| (* ---- depth -------------------------------------------------------------------------------------------- *) | |
| Fixpoint maxl (l : list nat) : nat := match l with [] => 0 | x :: t => Nat.max x (maxl t) end. | |
| Lemma maxl_ge : forall l a, In a l -> a <= maxl l. | |
| Proof. induction l as [|x t IH]; intros a H; [destruct H|]. destruct H as [<-|H]; cbn [maxl]; [lia|]. specialize (IH a H). lia. Qed. | |
| Lemma maxl_le : forall l c, (forall a, In a l -> a <= c) -> maxl l <= c. | |
| Proof. | |
| induction l as [|x t IH]; intros c H; cbn [maxl]; [lia|]. | |
| pose proof (H x (or_introl eq_refl)). pose proof (IH c (fun a Ha => H a (or_intror Ha))). lia. | |
| Qed. | |
| Lemma maxl_pos : forall l, 1 <= maxl l -> exists a, In a l /\ 1 <= a. | |
| Proof. | |
| induction l as [|x t IH]; cbn [maxl]; intro H; [lia|]. | |
| destruct (Nat.le_gt_cases 1 x) as [Hx|Hx]; [exists x; split; [left; reflexivity | exact Hx]|]. | |
| destruct (IH ltac:(lia)) as (a & Ha & H1). exists a. split; [right; exact Ha | exact H1]. | |
| Qed. | |
| (* the depth of a signal: 0 for a state bit, one more than its deepest predecessor for a unit *) | |
| Fixpoint depf (us : list tu) (m : nat) (D : nat -> nat) : nat -> nat := | |
| match us with | |
| | [] => D | |
| | u :: t => depf t (S m) (fun i => if Nat.eqb i m then S (maxl (map (fun p => D (fst p)) (tin u))) else D i) | |
| end. | |
| Lemma depf_prefix : forall us m D i, i < m -> depf us m D i = D i. | |
| Proof. | |
| induction us as [|u t IH]; intros m D i H; cbn [depf]; [reflexivity|]. | |
| rewrite IH by lia. destruct (Nat.eqb_spec i m); [lia | reflexivity]. | |
| Qed. | |
| Lemma depf_at : forall us m D j, j < length us -> | |
| (forall k, k < length us -> reads_below (nth k us tu0) (m + k)) -> | |
| depf us m D (m + j) = S (maxl (map (fun p => depf us m D (fst p)) (tin (nth j us tu0)))). | |
| Proof. | |
| induction us as [|u t IH]; intros m D j Hj Hwf; cbn [length] in Hj, Hwf; [lia|]. | |
| destruct j as [|j]. | |
| - cbn [nth depf]. rewrite Nat.add_0_r, depf_prefix by lia. rewrite Nat.eqb_refl. f_equal. f_equal. | |
| apply map_ext_in. intros [i z] Hin. cbn [fst]. | |
| pose proof (Hwf 0 ltac:(lia) i z Hin) as Hi. cbn [nth] in Hi. | |
| rewrite depf_prefix by lia. destruct (Nat.eqb_spec i m); [lia | reflexivity]. | |
| - cbn [nth depf]. replace (m + S j) with (S m + j) by lia. apply IH; [lia|]. | |
| intros k Hk i z Hin. specialize (Hwf (S k) ltac:(lia) i z Hin). lia. | |
| Qed. | |
| Lemma map_nth_self : forall (l : list nat) d, map (fun i => nth i l d) (seq 0 (length l)) = l. | |
| Proof. | |
| induction l as [|a t IH]; intro d; [reflexivity|]. cbn [length seq map nth]. f_equal. | |
| rewrite <- seq_shift, map_map. apply IH. | |
| Qed. | |
| Section Lev. | |
| Variable n : nat. | |
| Variable us : list tu. | |
| Variable nx : list nat. | |
| Definition NS : nat := n + length us. | |
| Definition wfn : Prop := forall k, k < length us -> reads_below (nth k us tu0) (n + k). | |
| Definition dep : nat -> nat := depf us n (fun _ => 0). | |
| Definition dmax : nat := maxl (map (fun k => dep (n + k)) (seq 0 (length us))). | |
| (* unit k reads signal s *) | |
| Definition reads (k s : nat) : bool := existsb (fun p => Nat.eqb (fst p) s) (tin (nth k us tu0)). | |
| Lemma reads_in : forall k s, reads k s = true <-> exists z, In (s, z) (tin (nth k us tu0)). | |
| Proof. | |
| intros k s. unfold reads. rewrite existsb_exists. split. | |
| - intros ([i z] & Hin & E). cbn [fst] in E. apply Nat.eqb_eq in E. subst i. exists z. exact Hin. | |
| - intros (z & Hin). exists (s, z). split; [exact Hin | apply Nat.eqb_refl]. | |
| Qed. | |
| Lemma dep_state : forall i, i < n -> dep i = 0. | |
| Proof. intros i H. unfold dep. rewrite depf_prefix by exact H. reflexivity. Qed. | |
| Lemma dep_unit : wfn -> forall k, k < length us -> | |
| dep (n + k) = S (maxl (map (fun p => dep (fst p)) (tin (nth k us tu0)))). | |
| Proof. intros Hwf k Hk. unfold dep. apply depf_at; assumption. Qed. | |
| Lemma dep_pred : wfn -> forall k p z, k < length us -> In (p, z) (tin (nth k us tu0)) -> dep p < dep (n + k). | |
| Proof. | |
| intros Hwf k p z Hk Hin. rewrite dep_unit by assumption. apply Nat.lt_succ_r. | |
| apply maxl_ge. apply in_map_iff. exists (p, z). split; [reflexivity | exact Hin]. | |
| Qed. | |
| Lemma dep_le_dmax : forall k, k < length us -> dep (n + k) <= dmax. | |
| Proof. intros k Hk. apply maxl_ge. apply in_map_iff. exists k. split; [reflexivity | apply in_seq; lia]. Qed. | |
| Lemma dep_unit_pos : wfn -> forall k, k < length us -> 1 <= dep (n + k). | |
| Proof. intros Hwf k Hk. rewrite dep_unit by assumption. lia. Qed. | |
| Lemma dep_zero : wfn -> forall s, s < NS -> dep s = 0 -> s < n. | |
| Proof. | |
| intros Hwf s Hs H. destruct (Nat.lt_ge_cases s n) as [Hl|Hg]; [exact Hl|]. | |
| pose proof (dep_unit_pos Hwf (s - n) ltac:(unfold NS in Hs; lia)). replace (n + (s - n)) with s in H0 by lia. lia. | |
| Qed. | |
| Lemma dep_le : forall s, s < NS -> dep s <= dmax. | |
| Proof. | |
| intros s Hs. destruct (Nat.lt_ge_cases s n) as [Hl|Hg]; [rewrite dep_state by exact Hl; lia|]. | |
| replace s with (n + (s - n)) by lia. apply dep_le_dmax. unfold NS in Hs. lia. | |
| Qed. | |
| (* ---- the signals some next value depends on -------------------------------------------------------- *) | |
| Fixpoint needf (vs : list tu) (m : nat) (S0 : nat -> bool) : nat -> bool := | |
| match vs with | |
| | [] => S0 | |
| | u :: t => let N' := needf t (S m) S0 in | |
| fun i => N' i || (N' m && existsb (fun p => Nat.eqb (fst p) i) (tin u)) | |
| end. | |
| Definition need : nat -> bool := needf us n (fun i => existsb (Nat.eqb i) nx). | |
| Lemma needf_seed : forall vs m S0 i, S0 i = true -> needf vs m S0 i = true. | |
| Proof. induction vs as [|u t IH]; intros m S0 i H; cbn [needf]; [exact H|]. rewrite IH by exact H. reflexivity. Qed. | |
| Lemma needf_closed : forall vs m S0 k p z, k < length vs -> | |
| (forall j, j < length vs -> reads_below (nth j vs tu0) (m + j)) -> | |
| needf vs m S0 (m + k) = true -> In (p, z) (tin (nth k vs tu0)) -> needf vs m S0 p = true. | |
| Proof. | |
| induction vs as [|u t IH]; intros m S0 k p z Hk Hwf Hn Hin; cbn [length] in Hk; [lia|]. | |
| assert (Hu : forall i z', In (i, z') (tin u) -> i < m) by (intros i z' H; specialize (Hwf 0 ltac:(cbn; lia) i z' H); cbn [nth] in Hwf; lia). | |
| assert (Hm : existsb (fun p0 => Nat.eqb (fst p0) (m + k)) (tin u) = true -> False). | |
| { intro E. apply existsb_exists in E as ([i z'] & Hi & E). cbn [fst] in E. apply Nat.eqb_eq in E. subst i. | |
| specialize (Hu _ _ Hi). lia. } | |
| cbn [needf] in *. destruct k as [|k]. | |
| - cbn [nth] in Hin. rewrite Nat.add_0_r in Hn. apply orb_true_iff in Hn as [Hn|Hn]. | |
| + apply orb_true_iff. right. rewrite Hn. cbn [andb]. apply existsb_exists. exists (p, z). split; [exact Hin|]. | |
| apply Nat.eqb_refl. | |
| + apply andb_true_iff in Hn as [Hn _]. apply orb_true_iff. right. rewrite Hn. cbn [andb]. | |
| apply existsb_exists. exists (p, z). split; [exact Hin | apply Nat.eqb_refl]. | |
| - cbn [nth] in Hin. apply orb_true_iff in Hn as [Hn|Hn]. | |
| + apply orb_true_iff. left. replace (m + S k) with (S m + k) in Hn by lia. | |
| apply (IH (S m) S0 k p z); [lia | | exact Hn | exact Hin]. | |
| intros j Hj. specialize (Hwf (S j) ltac:(cbn; lia)). cbn [nth] in Hwf. replace (S m + j) with (m + S j) by lia. exact Hwf. | |
| + apply andb_true_iff in Hn as [_ Hn]. exfalso. apply Hm. replace (m + k) with (m + k) by lia. | |
| replace (m + S k) with (m + S k) in Hn by lia. apply existsb_exists in Hn as ([i z'] & Hi & E). | |
| cbn [fst] in E. apply Nat.eqb_eq in E. subst i. specialize (Hu _ _ Hi). lia. | |
| Qed. | |
| Lemma needf_step : forall vs m S0 i, needf vs m S0 i = true -> | |
| S0 i = true \/ exists k z, k < length vs /\ needf vs m S0 (m + k) = true /\ In (i, z) (tin (nth k vs tu0)). | |
| Proof. | |
| induction vs as [|u t IH]; intros m S0 i H; cbn [needf] in *; [left; exact H|]. | |
| apply orb_true_iff in H as [H|H]. | |
| - destruct (IH (S m) S0 i H) as [H0|(k & z & Hk & Hn & Hin)]; [left; exact H0|]. | |
| right. exists (S k), z. cbn [length nth]. split; [lia|]. split; [|exact Hin]. | |
| replace (m + S k) with (S m + k) by lia. rewrite Hn. reflexivity. | |
| - apply andb_true_iff in H as [H1 H2]. apply existsb_exists in H2 as ([i' z] & Hi & E). cbn [fst] in E. | |
| apply Nat.eqb_eq in E. subst i'. right. exists 0, z. cbn [length nth]. split; [lia|]. split; [|exact Hi]. | |
| rewrite Nat.add_0_r, H1. reflexivity. | |
| Qed. | |
| (* contributing to a next value: being one, or a predecessor of a unit that contributes *) | |
| Inductive contrib : nat -> Prop := | |
| | contrib_out : forall s, In s nx -> contrib s | |
| | contrib_pred : forall k s z, k < length us -> contrib (n + k) -> In (s, z) (tin (nth k us tu0)) -> contrib s. | |
| Lemma need_nx : forall s, In s nx -> need s = true. | |
| Proof. | |
| intros s H. apply needf_seed. apply existsb_exists. exists s. split; [exact H | apply Nat.eqb_refl]. | |
| Qed. | |
| Lemma need_pred : wfn -> forall k p z, k < length us -> need (n + k) = true -> In (p, z) (tin (nth k us tu0)) -> | |
| need p = true. | |
| Proof. intros Hwf k p z Hk Hn Hin. exact (needf_closed us n _ k p z Hk Hwf Hn Hin). Qed. | |
| Theorem need_contrib : wfn -> forall s, need s = true <-> contrib s. | |
| Proof. | |
| intros Hwf s. split. | |
| - (* by induction on the distance to the last signal *) | |
| assert (G : forall d s, NS - s <= d -> need s = true -> contrib s \/ NS <= s). | |
| { induction d as [|d IH]; intros s' Hd Hn. | |
| - right. lia. | |
| - destruct (needf_step us n _ s' Hn) as [H0|(k & z & Hk & Hk2 & Hin)]. | |
| + left. apply contrib_out. apply existsb_exists in H0 as (y & Hy & E). apply Nat.eqb_eq in E. subst. exact Hy. | |
| + assert (Hs : s' < n + k) by (exact (Hwf k Hk s' z Hin)). | |
| destruct (IH (n + k) ltac:(unfold NS in *; lia) Hk2) as [Hc|Hc]; [|unfold NS in Hc; lia]. | |
| left. exact (contrib_pred k s' z Hk Hc Hin). } | |
| intro Hn. destruct (Nat.lt_ge_cases s NS) as [Hl|Hg]. | |
| + destruct (G (NS - s) s (le_n _) Hn) as [Hc|Hc]; [exact Hc | lia]. | |
| + destruct (needf_step us n _ s Hn) as [H0|(k & z & Hk & _ & Hin)]. | |
| * apply contrib_out. apply existsb_exists in H0 as (y & Hy & E). apply Nat.eqb_eq in E. subst. exact Hy. | |
| * exfalso. specialize (Hwf k Hk s z Hin). unfold NS in Hg. lia. | |
| - intro Hc. induction Hc as [s Hs|k s z Hk Hc IH Hin]; [apply need_nx; exact Hs|]. | |
| exact (need_pred Hwf k s z Hk IH Hin). | |
| Qed. | |
| (* ---- the last layer that reads a signal ------------------------------------------------------------ *) | |
| Definition lam (s : nat) : nat := | |
| Nat.max (if existsb (Nat.eqb s) nx then S dmax else 0) | |
| (maxl (map (fun k => if need (n + k) && reads k s then dep (n + k) else 0) (seq 0 (length us)))). | |
| Lemma lam_nx : forall s, In s nx -> S dmax <= lam s. | |
| Proof. | |
| intros s H. unfold lam. replace (existsb (Nat.eqb s) nx) with true; [lia|]. | |
| symmetry. apply existsb_exists. exists s. split; [exact H | apply Nat.eqb_refl]. | |
| Qed. | |
| Lemma lam_reader : forall k s z, k < length us -> need (n + k) = true -> In (s, z) (tin (nth k us tu0)) -> | |
| dep (n + k) <= lam s. | |
| Proof. | |
| intros k s z Hk Hn Hin. unfold lam. apply Nat.max_le_iff. right. | |
| replace (dep (n + k)) with (if need (n + k) && reads k s then dep (n + k) else 0). | |
| - apply maxl_ge. apply in_map_iff. exists k. split; [reflexivity | apply in_seq; lia]. | |
| - rewrite Hn. replace (reads k s) with true; [reflexivity|]. symmetry. apply reads_in. exists z. exact Hin. | |
| Qed. | |
| Lemma lam_need : wfn -> forall s, 1 <= lam s -> need s = true. | |
| Proof. | |
| intros Hwf s H. unfold lam in H. destruct (existsb (Nat.eqb s) nx) eqn:E. | |
| - apply existsb_exists in E as (y & Hy & E). apply Nat.eqb_eq in E. subst. apply need_nx. exact Hy. | |
| - cbn [Nat.max] in H. destruct (maxl_pos _ H) as (a & Ha & H1). apply in_map_iff in Ha as (k & Ea & Hk). | |
| apply in_seq in Hk. destruct (need (n + k) && reads k s) eqn:F; [|lia]. | |
| apply andb_true_iff in F as [F1 F2]. apply reads_in in F2 as (z & Hin). | |
| exact (need_pred Hwf k s z ltac:(lia) F1 Hin). | |
| Qed. | |
| (* ---- the layers ----------------------------------------------------------------------------------- *) | |
| Definition isunit (l s : nat) : bool := (n <=? s) && (dep s =? l). | |
| Definition live (l s : nat) : bool := isunit l s && need s || (dep s <? l) && (l <? lam s). | |
| Definition pos (l s : nat) : nat := match l with O => s | _ => length (filter (live l) (seq 0 s)) end. | |
| Definition idr (p : nat) : tu := TU (-1) [(p, 1%Z)]. | |
| Definition reidx (l : nat) (u : tu) : tu := TU (tb u) (map (fun p => (pos l (fst p), snd p)) (tin u)). | |
| (* the source of a row: a copy of a signal, or a unit *) | |
| Inductive src := Cp (s : nat) | Un (s : nat). | |
| Definition srcof (l s : nat) : src := if isunit l s then Un s else Cp s. | |
| Definition srcs (l : nat) : list src := map (srcof l) (filter (live l) (seq 0 NS)). | |
| Definition srcd : list src := map (fun i => srcof dmax (nth i nx 0)) (seq 0 n). | |
| Definition mkrow (l : nat) (c : src) : tu := | |
| match c with Cp s => idr (pos (l - 1) s) | Un s => reidx (l - 1) (nth (s - n) us tu0) end. | |
| (* layers 1 .. d - 1 hold the live signals, layer d one row for each state bit *) | |
| Definition lsrc : list (nat * list src) := map (fun l => (l, srcs l)) (seq 1 (dmax - 1)) ++ [(dmax, srcd)]. | |
| Definition lev : list (list tu) := map (fun p => map (mkrow (fst p)) (snd p)) lsrc. | |
| (* ---- positions --------------------------------------------------------------------------------------- *) | |
| Lemma seq_split : forall s M, s < M -> seq 0 M = seq 0 s ++ s :: seq (S s) (M - S s). | |
| Proof. intros s M H. replace M with (s + S (M - S s)) at 1 by lia. rewrite seq_app. reflexivity. Qed. | |
| Lemma nth_filter_count : forall (f : nat -> bool) s M d, s < M -> f s = true -> | |
| nth (length (filter f (seq 0 s))) (filter f (seq 0 M)) d = s. | |
| Proof. | |
| intros f s M d Hs Hf. rewrite (seq_split s M Hs). | |
| rewrite filter_app. cbn [filter]. rewrite Hf. rewrite app_nth2 by lia. rewrite Nat.sub_diag. reflexivity. | |
| Qed. | |
| Lemma count_lt : forall (f : nat -> bool) s M, s < M -> f s = true -> | |
| length (filter f (seq 0 s)) < length (filter f (seq 0 M)). | |
| Proof. | |
| intros f s M Hs Hf. rewrite (seq_split s M Hs). | |
| rewrite filter_app, length_app. cbn [filter]. rewrite Hf. cbn [length]. lia. | |
| Qed. | |
| Lemma count_mono : forall (f : nat -> bool) a b, a <= b -> length (filter f (seq 0 a)) <= length (filter f (seq 0 b)). | |
| Proof. | |
| intros f a b H. replace b with (a + (b - a)) by lia. rewrite seq_app, filter_app, length_app. lia. | |
| Qed. | |
| Lemma pos_inj : forall l s1 s2, 1 <= l -> live l s1 = true -> live l s2 = true -> pos l s1 = pos l s2 -> s1 = s2. | |
| Proof. | |
| intros l s1 s2 Hl H1 H2 E. destruct l as [|l]; [lia|]. cbn [pos] in E. | |
| destruct (Nat.lt_trichotomy s1 s2) as [Hlt|[Heq|Hgt]]; [|exact Heq|]. | |
| - pose proof (count_lt (live (S l)) s1 s2 Hlt H1). lia. | |
| - pose proof (count_lt (live (S l)) s2 s1 Hgt H2). lia. | |
| Qed. | |
| (* ---- firing the rows ------------------------------------------------------------------------------ *) | |
| Lemma wsum_reidx : forall l ins E, | |
| wsum (map (fun p => (pos l (fst p), snd p)) ins) E = wsum ins (fun i => E (pos l i)). | |
| Proof. intros l ins E. induction ins as [|[i z] t IH]; cbn [map wsum fst snd]; [reflexivity|]. rewrite IH. reflexivity. Qed. | |
| Lemma fire_reidx : forall l u E, fire (reidx l u) E = fire u (fun i => E (pos l i)). | |
| Proof. intros l u E. unfold fire, reidx. cbn [tb tin]. rewrite wsum_reidx. reflexivity. Qed. | |
| Lemma fire_idr : forall p E, fire (idr p) E = E p. | |
| Proof. intros p E. unfold fire, idr. cbn [tb tin wsum]. destruct (E p); reflexivity. Qed. | |
| Lemma lfire_nth : forall L y r, r < length L -> nth r (lfire L y) false = fire (nth r L tu0) (fun i => nth i y false). | |
| Proof. | |
| intros L y r Hr. unfold lfire. rewrite (nth_indep _ false (fire tu0 (fun i => nth i y false))) by (rewrite length_map; exact Hr). | |
| exact (map_nth (fun u => fire u (fun i => nth i y false)) L tu0 r). | |
| Qed. | |
| (* a signal has a row in layer l, l <= d - 1 *) | |
| Definition at_layer (l s : nat) : Prop := s < NS /\ (match l with O => s < n | _ => live l s = true end). | |
| (* the predecessors of a unit of depth l + 1 that contributes, and a signal live at l + 1 or a next value of depth | |
| at most l, have rows in layer l *) | |
| Lemma pred_at : wfn -> forall l k p z, k < length us -> need (n + k) = true -> dep (n + k) = S l -> | |
| In (p, z) (tin (nth k us tu0)) -> at_layer l p. | |
| Proof. | |
| intros Hwf l k p z Hk Hn Hdk Hin. pose proof (dep_pred Hwf k p z Hk Hin) as Hlt. | |
| assert (Hp : p < NS) by (pose proof (Hwf k Hk p z Hin); unfold NS; lia). | |
| split; [exact Hp|]. destruct l as [|l]. | |
| - apply (dep_zero Hwf p Hp). lia. | |
| - unfold live. pose proof (lam_reader k p z Hk Hn Hin) as Hlam. | |
| destruct (Nat.eq_dec (dep p) (S l)) as [E|E]. | |
| + apply orb_true_iff. left. apply andb_true_iff. split; [|exact (need_pred Hwf k p z Hk Hn Hin)]. | |
| unfold isunit. apply andb_true_iff. split; [|apply Nat.eqb_eq; exact E]. | |
| apply Nat.leb_le. destruct (Nat.lt_ge_cases p n) as [Hl|Hg]; [rewrite dep_state in E by exact Hl; lia | exact Hg]. | |
| + apply orb_true_iff. right. apply andb_true_iff. split; apply Nat.ltb_lt; lia. | |
| Qed. | |
| Lemma copy_at : wfn -> forall l s, s < NS -> dep s <= l -> S l < lam s -> at_layer l s. | |
| Proof. | |
| intros Hwf l s Hs Hdl Hlam. split; [exact Hs|]. destruct l as [|l]. | |
| - apply (dep_zero Hwf s Hs). lia. | |
| - unfold live. destruct (Nat.eq_dec (dep s) (S l)) as [E|E]. | |
| + apply orb_true_iff. left. apply andb_true_iff. split; [|apply lam_need; [exact Hwf | lia]]. | |
| unfold isunit. apply andb_true_iff. split; [|apply Nat.eqb_eq; exact E]. | |
| apply Nat.leb_le. destruct (Nat.lt_ge_cases s n) as [Hl|Hg]; [rewrite dep_state in E by exact Hl; lia | exact Hg]. | |
| + apply orb_true_iff. right. apply andb_true_iff. split; apply Nat.ltb_lt; lia. | |
| Qed. | |
| Section Sem. | |
| Hypothesis Hwf : wfn. | |
| Hypothesis Hnx : Forall (fun s => s < NS) nx. | |
| Hypothesis Hlen : length nx = n. | |
| Hypothesis Hd : 1 <= dmax. | |
| Variable x : list bool. | |
| Hypothesis Hx : length x = n. | |
| Let F : nat -> bool := run us n (fun i => nth i x false). | |
| Lemma F_unit : forall k, k < length us -> F (n + k) = fire (nth k us tu0) F. | |
| Proof. intros k Hk. unfold F. apply run_at; [exact Hk | exact Hwf]. Qed. | |
| Lemma F_state : forall i, i < n -> F i = nth i x false. | |
| Proof. intros i Hi. unfold F. apply run_prefix. exact Hi. Qed. | |
| (* the outputs after the first l layers, 0 <= l <= d - 1 *) | |
| Definition yl (l : nat) : list bool := lmap (map (fun l' => map (mkrow l') (srcs l')) (seq 1 l)) x. | |
| (* firing a row from the outputs of the layer before *) | |
| Lemma fire_row : forall l (y : list bool) c, | |
| (forall s, at_layer l s -> nth (pos l s) y false = F s) -> | |
| (forall s, c = Un s -> exists k, k < length us /\ s = n + k /\ need s = true /\ dep s = S l) -> | |
| (forall s, c = Cp s -> at_layer l s) -> | |
| fire (mkrow (S l) c) (fun i => nth i y false) = F (match c with Cp s => s | Un s => s end). | |
| Proof. | |
| intros l y c Hy HU HC. destruct c as [s|s]; cbn [mkrow]; replace (S l - 1) with l by lia. | |
| - rewrite fire_idr. apply Hy. apply HC. reflexivity. | |
| - destruct (HU s eq_refl) as (k & Hk & -> & Hn & Hdk). replace (n + k - n) with k by lia. | |
| rewrite fire_reidx, F_unit by exact Hk. apply fire_ext. intros p z Hin. apply Hy. exact (pred_at Hwf l k p z Hk Hn Hdk Hin). | |
| Qed. | |
| Lemma yl_spec : forall l, l <= dmax - 1 -> | |
| length (yl l) = (match l with O => n | _ => length (filter (live l) (seq 0 NS)) end) | |
| /\ forall s, at_layer l s -> nth (pos l s) (yl l) false = F s. | |
| Proof. | |
| induction l as [|l IH]; intros Hl. | |
| - unfold yl. cbn. split; [exact Hx|]. intros s [Hs Hn]. symmetry. apply F_state. exact Hn. | |
| - destruct (IH ltac:(lia)) as [IL IY]. | |
| assert (E : yl (S l) = lfire (map (mkrow (S l)) (srcs (S l))) (yl l)). | |
| { unfold yl. rewrite seq_S, map_app. cbn [map]. replace (1 + l) with (S l) by lia. apply lmap_app. } | |
| rewrite E. unfold lfire, srcs. rewrite !length_map. split; [reflexivity|]. | |
| intros s [Hs Hlv]. cbn [pos]. fold (lfire (map (mkrow (S l)) (map (srcof (S l)) (filter (live (S l)) (seq 0 NS)))) (yl l)). | |
| pose proof (count_lt (live (S l)) s NS Hs Hlv) as Hc. | |
| rewrite lfire_nth by (rewrite !length_map; exact Hc). | |
| rewrite nth_map_d with (d' := Cp 0) by (rewrite length_map; exact Hc). | |
| rewrite nth_map_d with (d' := 0) by exact Hc. rewrite nth_filter_count by assumption. | |
| assert (Hfs : F s = F (match srcof (S l) s with Cp s' => s' | Un s' => s' end)) | |
| by (unfold srcof; destruct (isunit (S l) s); reflexivity). | |
| rewrite Hfs. apply fire_row; [exact IY | |]. | |
| + intros s' Hs'. unfold srcof in Hs'. destruct (isunit (S l) s) eqn:Hu; [|discriminate]. injection Hs' as <-. | |
| unfold isunit in Hu. apply andb_true_iff in Hu as [H1 H2]. apply Nat.leb_le in H1. apply Nat.eqb_eq in H2. | |
| exists (s - n). split; [unfold NS in Hs; lia|]. split; [lia|]. split; [|exact H2]. | |
| unfold live in Hlv. apply orb_true_iff in Hlv as [Hlv|Hlv]. | |
| * apply andb_true_iff in Hlv as [_ Hlv]. exact Hlv. | |
| * apply andb_true_iff in Hlv as [Hlv _]. apply Nat.ltb_lt in Hlv. lia. | |
| + intros s' Hs'. unfold srcof in Hs'. destruct (isunit (S l) s) eqn:Hu; [discriminate|]. injection Hs' as <-. | |
| unfold live in Hlv. rewrite Hu in Hlv. cbn [andb orb] in Hlv. apply andb_true_iff in Hlv as [H1 H2]. | |
| apply Nat.ltb_lt in H1, H2. apply (copy_at Hwf); [exact Hs | lia | lia]. | |
| Qed. | |
| Theorem lev_correct : lmap lev x = netstep n us nx x. | |
| Proof. | |
| unfold lev, lsrc. rewrite map_app. cbn [map fst snd]. rewrite lmap_app. | |
| fold (yl (dmax - 1)). destruct (yl_spec (dmax - 1) (le_n _)) as [_ IY]. | |
| unfold netstep. fold F. unfold lfire, srcd. rewrite !map_map. | |
| transitivity (map F (map (fun i => nth i nx 0) (seq 0 n))). | |
| 2: { f_equal. rewrite <- Hlen. apply map_nth_self. } | |
| rewrite map_map. apply map_ext_in. intros i Hi. apply in_seq in Hi. | |
| set (s := nth i nx 0). | |
| assert (Hs : s < NS) by (rewrite Forall_forall in Hnx; apply Hnx; apply nth_In; lia). | |
| assert (Hin : In s nx) by (apply nth_In; lia). | |
| assert (Hfs : F s = F (match srcof dmax s with Cp s' => s' | Un s' => s' end)) | |
| by (unfold srcof; destruct (isunit dmax s); reflexivity). | |
| rewrite Hfs. replace (mkrow dmax) with (mkrow (S (dmax - 1))) by (f_equal; lia). | |
| apply fire_row; [exact IY | |]. | |
| - intros s' Hs'. unfold srcof in Hs'. destruct (isunit dmax s) eqn:Hu; [|discriminate]. injection Hs' as <-. | |
| unfold isunit in Hu. apply andb_true_iff in Hu as [H1 H2]. apply Nat.leb_le in H1. apply Nat.eqb_eq in H2. | |
| exists (s - n). split; [unfold NS in Hs; lia|]. split; [lia|]. split; [apply need_nx; exact Hin | lia]. | |
| - intros s' Hs'. unfold srcof in Hs'. destruct (isunit dmax s) eqn:Hu; [discriminate|]. injection Hs' as <-. | |
| pose proof (lam_nx s Hin). pose proof (dep_le s Hs). | |
| assert (dep s <> dmax \/ s < n) as Hne. | |
| { unfold isunit in Hu. apply andb_false_iff in Hu as [Hu|Hu]; [right; apply Nat.leb_gt in Hu; exact Hu|]. | |
| left. apply Nat.eqb_neq in Hu. lia. } | |
| apply (copy_at Hwf); [exact Hs | | lia]. | |
| destruct Hne as [Hne|Hne]; [lia | rewrite dep_state by exact Hne; lia]. | |
| Qed. | |
| End Sem. | |
| (* ---- the shape of the layered map ----------------------------------------------------------------------- *) | |
| Lemma length_lev : 1 <= dmax -> length lev = dmax. | |
| Proof. intro H. unfold lev, lsrc. rewrite length_map, length_app, length_map, length_seq. cbn [length]. lia. Qed. | |
| (* the width of layer l, 0 <= l <= d - 1 *) | |
| Definition width (l : nat) : nat := match l with O => n | _ => length (filter (live l) (seq 0 NS)) end. | |
| Lemma pos_lt : forall l s, at_layer l s -> pos l s < width l. | |
| Proof. | |
| intros l s [Hs Hl]. destruct l as [|l]; cbn [pos width]; [exact Hl|]. apply count_lt; assumption. | |
| Qed. | |
| Lemma pos_inj_at : forall l s1 s2, at_layer l s1 -> at_layer l s2 -> pos l s1 = pos l s2 -> s1 = s2. | |
| Proof. | |
| intros l s1 s2 [_ H1] [_ H2] E. destruct l as [|l]; [exact E|]. apply (pos_inj (S l)); [lia | exact H1 | exact H2 | exact E]. | |
| Qed. | |
| Lemma nodup_map_inj : forall (f : nat -> nat) (P : nat -> Prop) l, NoDup l -> (forall a, In a l -> P a) -> | |
| (forall a b, P a -> P b -> f a = f b -> a = b) -> NoDup (map f l). | |
| Proof. | |
| intros f P l Hnd. induction Hnd as [|a t Ha Hnd IH]; intros HP Hinj; cbn [map]; constructor. | |
| - intro Hin. apply in_map_iff in Hin as (b & Eb & Hb). apply Ha. | |
| rewrite (Hinj b a (HP b (or_intror Hb)) (HP a (or_introl eq_refl)) Eb) in Hb. exact Hb. | |
| - apply IH; [intros b Hb; apply HP; right; exact Hb | exact Hinj]. | |
| Qed. | |
| (* a row built from a source of layer l + 1 reads distinct positions of layer l with weights -1 or 1 *) | |
| Lemma mkrow_ok : wfn -> Forall (fun u => NoDup (map fst (tin u)) /\ forall i z, In (i, z) (tin u) -> z = 1%Z \/ z = (-1)%Z) us -> | |
| forall l c, (forall s, c = Un s -> exists k, k < length us /\ s = n + k /\ need s = true /\ dep s = S l) -> | |
| (forall s, c = Cp s -> at_layer l s) -> rowok (width l) (mkrow (S l) c). | |
| Proof. | |
| intros Hwf Hus l c HU HC. destruct c as [s|s]; cbn [mkrow]; replace (S l - 1) with l by lia. | |
| - specialize (HC s eq_refl). unfold rowok, idr. cbn [tin map fst]. split; [constructor; [intros []|constructor]|]. | |
| intros i z [E|[]]. injection E as <- <-. split; [apply pos_lt; exact HC | left; reflexivity]. | |
| - destruct (HU s eq_refl) as (k & Hk & -> & Hn & Hdk). replace (n + k - n) with k by lia. | |
| rewrite Forall_forall in Hus. destruct (Hus (nth k us tu0) (nth_In _ _ Hk)) as [Hnd Hz]. | |
| unfold rowok, reidx. cbn [tin]. split. | |
| + rewrite map_map. cbn [fst]. rewrite <- (map_map fst (pos l)). | |
| apply (nodup_map_inj (pos l) (at_layer l) (map fst (tin (nth k us tu0)))); [exact Hnd | |]. | |
| * intros p Hp. apply in_map_iff in Hp as ([p' z] & <- & Hin). exact (pred_at Hwf l k p' z Hk Hn Hdk Hin). | |
| * intros a b Ha Hb E. exact (pos_inj_at l a b Ha Hb E). | |
| + intros i z Hin. apply in_map_iff in Hin as ([p z'] & E & Hin). cbn [fst snd] in E. injection E as <- <-. | |
| split; [apply pos_lt; exact (pred_at Hwf l k p z' Hk Hn Hdk Hin) | exact (Hz p z' Hin)]. | |
| Qed. | |
| Lemma srcs_spec : forall l c, In c (srcs l) -> | |
| (forall s, c = Un s -> exists k, k < length us /\ s = n + k /\ need s = true /\ dep s = l) | |
| /\ (forall s, c = Cp s -> s < NS /\ dep s < l < lam s). | |
| Proof. | |
| intros l c Hc. unfold srcs in Hc. apply in_map_iff in Hc as (s & <- & Hs). apply filter_In in Hs as [Hs Hlv]. | |
| apply in_seq in Hs. unfold srcof. destruct (isunit l s) eqn:Hu; split; intros s' E; try discriminate; injection E as <-. | |
| - unfold isunit in Hu. apply andb_true_iff in Hu as [H1 H2]. apply Nat.leb_le in H1. apply Nat.eqb_eq in H2. | |
| exists (s - n). split; [unfold NS in Hs; lia|]. split; [lia|]. split; [|exact H2]. | |
| unfold live in Hlv. apply orb_true_iff in Hlv as [Hlv|Hlv]. | |
| + apply andb_true_iff in Hlv as [_ Hlv]. exact Hlv. | |
| + apply andb_true_iff in Hlv as [Hlv _]. apply Nat.ltb_lt in Hlv. lia. | |
| - unfold live in Hlv. rewrite Hu in Hlv. cbn [andb orb] in Hlv. apply andb_true_iff in Hlv as [H1 H2]. | |
| apply Nat.ltb_lt in H1, H2. split; [lia | lia]. | |
| Qed. | |
| Lemma srcd_spec : Forall (fun s => s < NS) nx -> length nx = n -> 1 <= dmax -> forall c, In c srcd -> | |
| (forall s, c = Un s -> exists k, k < length us /\ s = n + k /\ need s = true /\ dep s = dmax) | |
| /\ (forall s, c = Cp s -> s < NS /\ dep s < dmax /\ S dmax <= lam s). | |
| Proof. | |
| intros Hnx Hlen Hd c Hc. unfold srcd in Hc. apply in_map_iff in Hc as (i & <- & Hi). apply in_seq in Hi. | |
| set (s := nth i nx 0). assert (Hs : s < NS) by (rewrite Forall_forall in Hnx; apply Hnx; apply nth_In; lia). | |
| assert (Hin : In s nx) by (apply nth_In; lia). | |
| unfold srcof. destruct (isunit dmax s) eqn:Hu; split; intros s' E; try discriminate; injection E as <-. | |
| - unfold isunit in Hu. apply andb_true_iff in Hu as [H1 H2]. apply Nat.leb_le in H1. apply Nat.eqb_eq in H2. | |
| exists (s - n). split; [unfold NS in Hs; lia|]. split; [lia|]. split; [apply need_nx; exact Hin | exact H2]. | |
| - split; [exact Hs|]. split; [|apply lam_nx; exact Hin]. pose proof (dep_le s Hs). | |
| unfold isunit in Hu. apply andb_false_iff in Hu as [Hu|Hu]. | |
| + apply Nat.leb_gt in Hu. rewrite dep_state by exact Hu. lia. | |
| + apply Nat.eqb_neq in Hu. lia. | |
| Qed. | |
| (* Lemma 2.5: the layered map has depth d, every row reads distinct rows of the layer before with weights -1 or 1, | |
| and it computes the next state of the netlist *) | |
| Theorem lev_ok : wfn -> Forall (fun s => s < NS) nx -> length nx = n -> 1 <= dmax -> | |
| Forall (fun u => NoDup (map fst (tin u)) /\ forall i z, In (i, z) (tin u) -> z = 1%Z \/ z = (-1)%Z) us -> | |
| length lev = dmax /\ lwf n lev /\ length (last lev []) = n | |
| /\ forall x, length x = n -> lmap lev x = netstep n us nx x. | |
| Proof. | |
| intros Hwf Hnx Hlen Hd Hus. split; [apply length_lev; exact Hd|]. split; [|split]. | |
| - (* layer l + 1 reads layer l *) | |
| assert (G : forall m, m <= dmax - 1 -> | |
| lwf (width m) (map (fun p => map (mkrow (fst p)) (snd p)) | |
| (map (fun l => (l, srcs l)) (seq (S m) (dmax - 1 - m)) ++ [(dmax, srcd)]))). | |
| { intros m Hm. remember (dmax - 1 - m) as c eqn:Ec. revert m Hm Ec. induction c as [|c IH]; intros m Hm Ec. | |
| - cbn [seq map app lwf fst snd]. split; [|exact I]. | |
| apply Forall_forall. intros r Hr. apply in_map_iff in Hr as (c & <- & Hc). | |
| destruct (srcd_spec Hnx Hlen Hd c Hc) as [HU HC]. | |
| replace dmax with (S m) by lia. apply mkrow_ok; [exact Hwf | exact Hus | |]. | |
| + intros s E. destruct (HU s E) as (k & Hk & Es & Hn & Hdk). exists k. repeat split; try assumption. lia. | |
| + intros s E. destruct (HC s E) as (Hs & Hdl & Hlam). apply copy_at; [exact Hwf | exact Hs | lia | lia]. | |
| - cbn [seq map app lwf fst snd]. split. | |
| + apply Forall_forall. intros r Hr. apply in_map_iff in Hr as (c' & <- & Hc). | |
| destruct (srcs_spec (S m) c' Hc) as [HU HC]. apply mkrow_ok; [exact Hwf | exact Hus | exact HU |]. | |
| intros s E. destruct (HC s E) as (Hs & Hdl & Hlam). apply copy_at; [exact Hwf | exact Hs | lia | lia]. | |
| + rewrite length_map. unfold srcs. rewrite length_map. | |
| replace (length (filter (live (S m)) (seq 0 NS))) with (width (S m)) by reflexivity. | |
| apply IH; lia. } | |
| specialize (G 0 ltac:(lia)). unfold lev, lsrc. replace (dmax - 1) with (dmax - 1 - 0) by lia. exact G. | |
| - unfold lev, lsrc. rewrite map_app. cbn [map fst snd]. rewrite last_last. unfold srcd. rewrite !length_map, length_seq. | |
| reflexivity. | |
| - intros x Hx. apply lev_correct; assumption. | |
| Qed. | |
| (* every row is an identity unit H(x - 1) or a unit of the netlist with its bias and weights *) | |
| Theorem lev_rows : forall l cs c, In (l, cs) lsrc -> In c cs -> | |
| match c with | |
| | Cp s => exists p, mkrow l c = idr p | |
| | Un s => tb (mkrow l c) = tb (nth (s - n) us tu0) /\ map snd (tin (mkrow l c)) = map snd (tin (nth (s - n) us tu0)) | |
| end. | |
| Proof. | |
| intros l cs c _ _. destruct c as [s|s]; cbn [mkrow]. | |
| - eexists. reflexivity. | |
| - unfold reidx. cbn [tb tin]. split; [reflexivity|]. rewrite map_map. reflexivity. | |
| Qed. | |
| (* the occurrences of unit s among the rows *) | |
| Definition isun (s : nat) (c : src) : bool := match c with Un s' => Nat.eqb s' s | Cp _ => false end. | |
| Lemma length_filter_map : forall (A B : Type) (p : B -> bool) (f : A -> B) (L : list A), | |
| length (filter p (map f L)) = length (filter (fun a => p (f a)) L). | |
| Proof. intros A B p f L. induction L as [|a t IH]; cbn [map filter]; [reflexivity|]. destruct (p (f a)); cbn [length]; lia. Qed. | |
| Lemma length_filter_filter : forall (A : Type) (p q : A -> bool) (L : list A), | |
| length (filter p (filter q L)) = length (filter (fun a => q a && p a) L). | |
| Proof. | |
| intros A p q L. induction L as [|a t IH]; [reflexivity|]. cbn [filter]. | |
| destruct (q a); cbn [andb filter]; [destruct (p a); cbn [length]; lia | exact IH]. | |
| Qed. | |
| Lemma filter_eqb_seq : forall (g : nat -> bool) M s, s < M -> | |
| length (filter (fun s' => g s' && Nat.eqb s' s) (seq 0 M)) = if g s then 1 else 0. | |
| Proof. | |
| intros g M s Hs. rewrite (seq_split s M Hs), filter_app, length_app. cbn [filter]. rewrite Nat.eqb_refl, andb_true_r. | |
| assert (Z : forall a k, (a > s \/ a + k <= s) -> length (filter (fun s' => g s' && Nat.eqb s' s) (seq a k)) = 0). | |
| { intros a k Hak. revert a Hak. induction k as [|k IH]; intros a Hak; [reflexivity|]. cbn [seq filter]. | |
| destruct (Nat.eqb_spec a s); [lia|]. rewrite andb_false_r. apply IH. lia. } | |
| rewrite (Z 0 s) by lia. destruct (g s); cbn [length]; rewrite (Z (S s) (M - S s)) by lia; reflexivity. | |
| Qed. | |
| Lemma count_srcs : forall l s, s < NS -> length (filter (isun s) (srcs l)) = if isunit l s && need s then 1 else 0. | |
| Proof. | |
| intros l s Hs. unfold srcs. rewrite length_filter_map, length_filter_filter. | |
| rewrite (filter_ext _ (fun a => (live l a && isunit l a) && Nat.eqb a s)). | |
| - rewrite filter_eqb_seq by exact Hs. destruct (isunit l s) eqn:Hu. | |
| + unfold live. rewrite Hu. unfold isunit in Hu. apply andb_true_iff in Hu as [_ Hu]. apply Nat.eqb_eq in Hu. | |
| rewrite Hu, Nat.ltb_irrefl. destruct (need s); reflexivity. | |
| + rewrite andb_false_r. reflexivity. | |
| - intro a. unfold srcof. destruct (isunit l a); cbn [isun]; [rewrite andb_true_r; reflexivity|]. | |
| rewrite !andb_false_r. reflexivity. | |
| Qed. | |
| Lemma count_map_srcof : forall d s (L : list nat), | |
| length (filter (fun a => isun s (srcof d a)) L) = if isunit d s then length (filter (fun a => Nat.eqb a s) L) else 0. | |
| Proof. | |
| intros d s L. induction L as [|a t IH]; [destruct (isunit d s); reflexivity|]. cbn [filter]. | |
| destruct (Nat.eqb_spec a s) as [->|E]. | |
| - assert (Hs : isun s (srcof d s) = isunit d s) | |
| by (unfold srcof; destruct (isunit d s); cbn [isun]; [apply Nat.eqb_refl | reflexivity]). | |
| rewrite Hs. destruct (isunit d s) eqn:Hu. | |
| + cbn [length]. rewrite IH. reflexivity. | |
| + exact IH. | |
| - assert (Hf : isun s (srcof d a) = false) | |
| by (unfold srcof; destruct (isunit d a); cbn [isun]; [apply Nat.eqb_neq; exact E | reflexivity]). | |
| rewrite Hf. exact IH. | |
| Qed. | |
| Lemma count_srcd : length nx = n -> forall s, | |
| length (filter (isun s) srcd) = if isunit dmax s then length (filter (fun a => Nat.eqb a s) nx) else 0. | |
| Proof. | |
| intros Hlen s. unfold srcd. rewrite <- (map_map (fun i => nth i nx 0) (srcof dmax)). | |
| rewrite <- Hlen, map_nth_self, length_filter_map. apply count_map_srcof. | |
| Qed. | |
| Lemma length_filter_concat : forall (A : Type) (p : A -> bool) (L : list (list A)), | |
| length (filter p (concat L)) = fold_right Nat.add 0 (map (fun l => length (filter p l)) L). | |
| Proof. | |
| intros A p L. induction L as [|l t IH]; [reflexivity|]. cbn [concat map fold_right]. rewrite filter_app, length_app, IH. | |
| reflexivity. | |
| Qed. | |
| Lemma sum_indicator : forall x a k, fold_right Nat.add 0 (map (fun l => if Nat.eqb x l then 1 else 0) (seq a k)) | |
| = if (a <=? x) && (x <? a + k) then 1 else 0. | |
| Proof. | |
| intros x a k. revert a. induction k as [|k IH]; intro a. | |
| - cbn [seq map fold_right]. destruct (Nat.leb_spec a x), (Nat.ltb_spec x (a + 0)); cbn [andb]; lia. | |
| - cbn [seq map fold_right]. rewrite IH. destruct (Nat.eqb_spec x a) as [->|E]. | |
| + rewrite Nat.leb_refl. destruct (Nat.leb_spec (S a) a); [lia|]. cbn [andb]. destruct (Nat.ltb_spec a (a + S k)); lia. | |
| + destruct (Nat.leb_spec (S a) x), (Nat.ltb_spec x (S a + k)), (Nat.leb_spec a x), (Nat.ltb_spec x (a + S k)); | |
| cbn [andb]; lia. | |
| Qed. | |
| Lemma sum_zero : forall (L : list nat) (f : nat -> nat), (forall l, In l L -> f l = 0) -> | |
| fold_right Nat.add 0 (map f L) = 0. | |
| Proof. | |
| intros L f H. induction L as [|a t IH]; [reflexivity|]. cbn [map fold_right]. | |
| rewrite (H a (or_introl eq_refl)), IH by (intros l Hl; apply H; right; exact Hl). reflexivity. | |
| Qed. | |
| Lemma filter_none : forall (L : list nat) s, (forall a, In a L -> a <> s) -> length (filter (fun a => Nat.eqb a s) L) = 0. | |
| Proof. | |
| intros L s H. induction L as [|a t IH]; [reflexivity|]. cbn [filter]. | |
| destruct (Nat.eqb_spec a s) as [E|E]; [exfalso; exact (H a (or_introl eq_refl) E)|]. | |
| apply IH. intros b Hb. apply H. right. exact Hb. | |
| Qed. | |
| (* each unit that contributes occurs once if its depth is less than d and once for each state bit whose next value it | |
| is if its depth is d; no other unit occurs *) | |
| Theorem lev_units : wfn -> length nx = n -> forall s, n <= s < NS -> | |
| length (filter (isun s) (concat (map snd lsrc))) | |
| = if need s then (if dep s <? dmax then 1 else length (filter (fun a => Nat.eqb a s) nx)) else 0. | |
| Proof. | |
| intros Hwf Hlen s Hs. unfold lsrc. rewrite map_app, concat_app, filter_app, length_app, map_map. cbn [map snd concat]. | |
| rewrite app_nil_r, count_srcd by exact Hlen. rewrite length_filter_concat, map_map. | |
| pose proof (dep_unit_pos Hwf (s - n) ltac:(unfold NS in Hs; lia)) as Hpos. replace (n + (s - n)) with s in Hpos by lia. | |
| pose proof (dep_le s (proj2 Hs)) as Hle. | |
| assert (Hu : forall l, isunit l s = Nat.eqb (dep s) l) | |
| by (intro l; unfold isunit; destruct (Nat.leb_spec n s); [reflexivity | lia]). | |
| rewrite Hu. destruct (need s) eqn:Hn. | |
| - rewrite (map_ext_in _ (fun l => if Nat.eqb (dep s) l then 1 else 0)). | |
| 2: { intros l Hl. rewrite count_srcs by lia. rewrite Hu, Hn, andb_true_r. reflexivity. } | |
| rewrite sum_indicator. destruct (Nat.ltb_spec (dep s) dmax) as [Hlt|Hge]. | |
| + replace ((1 <=? dep s) && (dep s <? 1 + (dmax - 1))) with true | |
| by (symmetry; apply andb_true_iff; split; [apply Nat.leb_le | apply Nat.ltb_lt]; lia). | |
| destruct (Nat.eqb_spec (dep s) dmax); [lia | reflexivity]. | |
| + replace ((1 <=? dep s) && (dep s <? 1 + (dmax - 1))) with false | |
| by (symmetry; apply andb_false_iff; right; apply Nat.ltb_ge; lia). | |
| destruct (Nat.eqb_spec (dep s) dmax); [reflexivity | lia]. | |
| - rewrite sum_zero by (intros l _; rewrite count_srcs by lia; rewrite Hn, andb_false_r; reflexivity). | |
| destruct (Nat.eqb (dep s) dmax); [|reflexivity]. rewrite filter_none; [reflexivity|]. | |
| intros a Ha E. subst a. rewrite (need_nx s Ha) in Hn. discriminate. | |
| Qed. | |
| (* the number of rows of each layer *) | |
| Theorem lev_widths : length nx = n -> map (@length tu) lev = map width (seq 1 (dmax - 1)) ++ [n]. | |
| Proof. | |
| intro Hlen. unfold lev, lsrc. rewrite map_app, map_app, !map_map. cbn [map fst snd]. f_equal. | |
| - apply map_ext_in. intros l Hl. apply in_seq in Hl. unfold srcs. rewrite !length_map. | |
| destruct l as [|l]; [lia | reflexivity]. | |
| - unfold srcd. rewrite !length_map, length_seq. reflexivity. | |
| Qed. | |
| (* the size of the layered map: its rows are those of the layers 1 .. d - 1 and one for each state bit *) | |
| Theorem lev_size : length nx = n -> | |
| fold_right Nat.add 0 (map (@length tu) lev) = fold_right Nat.add 0 (map width (seq 1 (dmax - 1))) + n. | |
| Proof. | |
| intro Hlen. unfold lev, lsrc. rewrite map_app, map_app, fold_right_app, !map_map. cbn [map fold_right fst snd]. | |
| unfold srcd. rewrite !length_map, length_seq. | |
| assert (G : forall (L : list nat) c, (forall l, In l L -> 1 <= l) -> | |
| fold_right Nat.add c (map (fun l => length (map (mkrow l) (srcs l))) L) = fold_right Nat.add 0 (map width L) + c). | |
| { intros L c HL. induction L as [|a t IH]; [reflexivity|]. cbn [map fold_right]. | |
| rewrite IH by (intros l Hl; apply HL; right; exact Hl). unfold srcs. rewrite !length_map. | |
| destruct a as [|a]; [specialize (HL 0 (or_introl eq_refl)); lia|]. cbn [width]. lia. } | |
| rewrite G by (intros l Hl; apply in_seq in Hl; lia). lia. | |
| Qed. | |
| End Lev. | |