Download rocq/Recipe.v from phanerozoic/threshold-computers: direct link, hf CLI and curl.
- Browser
- Download file 19.3 kB
-
https://huggingface.co/phanerozoic/threshold-computers/resolve/main/rocq/Recipe.v
- Command line
-
hf download hf://phanerozoic/threshold-computers/rocq/Recipe.v
-
curl -L -o Recipe.v https://huggingface.co/phanerozoic/threshold-computers/resolve/main/rocq/Recipe.v
19.3 kB
| (* Recipes (Section 6): the encoder describe of Lemma 6.7, as src/host.py computes it, with its decoding, its | |
| length bound and the case of equality; the optimality of the bound for strings with no two equal adjacent | |
| bytes (Proposition 6.6); and the completeness of the recipe language (Lemma 6.5). *) | |
| From Stdlib Require Import List Bool Arith Lia. | |
| Import ListNotations. | |
| From TH Require Import Net Host HostWF HostSem Device Pstar. | |
| Lemma nu_nu : forall b, b < 256 -> nu (nu b) = b. | |
| Proof. | |
| intros b Hb. unfold nu. destruct (Nat.eq_dec b 0) as [->|E]; [reflexivity|]. | |
| rewrite (Nat.mod_small (256 - b)) by lia. rewrite Nat.mod_small by lia. lia. | |
| Qed. | |
| Lemma nu_lt : forall b, nu b < 256. | |
| Proof. intro b. unfold nu. apply Nat.mod_upper_bound. lia. Qed. | |
| (* ---- the encoder ------------------------------------------------------------------------------------------ *) | |
| (* the length of the run of bytes equal to x at the head of f *) | |
| Fixpoint run_len (x : nat) (f : list nat) : nat := | |
| match f with [] => 0 | y :: f' => if Nat.eqb y x then S (run_len x f') else 0 end. | |
| (* four equal bytes begin at the head of f *) | |
| Definition four_at (f : list nat) : bool := | |
| match f with a :: b :: c :: d :: _ => Nat.eqb b a && Nat.eqb c a && Nat.eqb d a | _ => false end. | |
| (* the bytes before the first position at which four equal bytes begin, at most cap of them *) | |
| Fixpoint lit_scan (cap : nat) (f : list nat) : nat := | |
| match cap with | |
| | O => 0 | |
| | S c => match f with [] => 0 | _ :: f' => if four_at f then 0 else S (lit_scan c f') end | |
| end. | |
| Fixpoint desc (fuel : nat) (f : list nat) : list token := | |
| match fuel with | |
| | O => [] | |
| | S fu => | |
| match f with | |
| | [] => [] | |
| | x :: _ => | |
| let l := Nat.min (run_len x f) 127 in | |
| if Nat.leb 4 l then Rep (256 - l) (nu x) :: desc fu (skipn l f) | |
| else let k := lit_scan 127 f in Lit (map nu (firstn k f)) :: desc fu (skipn k f) | |
| end | |
| end. | |
| Definition describe (f : list nat) : list token := desc (length f) f. | |
| (* the bound of Lemmas 6.5 and 6.7: |f| + ceil(|f| / 127) + 1 *) | |
| Definition bound (n : nat) : nat := n + (n + 126) / 127 + 1. | |
| Definition nofour (f : list nat) : Prop := forall p, four_at (skipn p f) = false. | |
| (* ---- runs and scans ------------------------------------------------------------------------------------- *) | |
| Lemma firstn_run : forall x f l, l <= run_len x f -> firstn l f = repeat x l. | |
| Proof. | |
| intros x f. induction f as [|y f IH]; intros l Hl; cbn [run_len] in Hl. | |
| - assert (l = 0) by lia. subst. reflexivity. | |
| - destruct l as [|l]; [reflexivity|]. destruct (Nat.eqb_spec y x) as [->|E]; [|lia]. | |
| cbn [firstn repeat]. rewrite IH by lia. reflexivity. | |
| Qed. | |
| Lemma run_le : forall x f, run_len x f <= length f. | |
| Proof. intros x f. induction f as [|y f IH]; cbn [run_len length]; [lia|]. destruct (Nat.eqb y x); lia. Qed. | |
| Lemma four_run : forall x f, four_at (x :: f) = Nat.leb 4 (run_len x (x :: f)). | |
| Proof. | |
| intros x [|b [|c [|d f]]]; cbn [four_at run_len]; rewrite Nat.eqb_refl; try reflexivity. | |
| - destruct (Nat.eqb b x); reflexivity. | |
| - destruct (Nat.eqb b x), (Nat.eqb c x); reflexivity. | |
| - destruct (Nat.eqb b x), (Nat.eqb c x), (Nat.eqb d x); reflexivity. | |
| Qed. | |
| Lemma lit_scan_le : forall cap f, lit_scan cap f <= cap /\ lit_scan cap f <= length f. | |
| Proof. | |
| induction cap as [|c IH]; intros f; cbn [lit_scan]; [lia|]. destruct f as [|y f']; cbn [length]; [lia|]. | |
| destruct (four_at (y :: f')); [lia|]. specialize (IH f'). lia. | |
| Qed. | |
| Lemma lit_scan_none : forall cap f p, p < lit_scan cap f -> four_at (skipn p f) = false. | |
| Proof. | |
| induction cap as [|c IH]; intros f p Hp; cbn [lit_scan] in Hp; [lia|]. destruct f as [|y f']; [lia|]. | |
| destruct (four_at (y :: f')) eqn:E; [lia|]. destruct p as [|p]; [exact E|]. cbn [skipn]. apply (IH f'). lia. | |
| Qed. | |
| Lemma lit_scan_stop : forall cap f, lit_scan cap f = cap \/ lit_scan cap f = length f | |
| \/ four_at (skipn (lit_scan cap f) f) = true. | |
| Proof. | |
| induction cap as [|c IH]; intros f; cbn [lit_scan]; [left; reflexivity|]. destruct f as [|y f']; [right; left; reflexivity|]. | |
| destruct (four_at (y :: f')) eqn:E; [right; right; exact E|]. cbn [skipn length]. | |
| destruct (IH f') as [H|[H|H]]; [left; lia | right; left; lia | right; right; exact H]. | |
| Qed. | |
| Lemma lit_scan_pos : forall cap f, 1 <= cap -> f <> [] -> four_at f = false -> 1 <= lit_scan cap f. | |
| Proof. intros [|c] [|y f] Hc Hf E; [lia | lia | contradiction Hf; reflexivity | cbn [lit_scan]; rewrite E; lia]. Qed. | |
| Lemma nofour_skipn : forall f k, nofour f -> nofour (skipn k f). | |
| Proof. intros f k H p. rewrite skipn_skipn. apply H. Qed. | |
| Lemma Forall_take : forall (T : Type) (P : T -> Prop) l k, Forall P l -> Forall P (firstn k l). | |
| Proof. intros T P l k H. rewrite <- (firstn_skipn k l) in H. apply Forall_app in H. exact (proj1 H). Qed. | |
| Lemma Forall_drop : forall (T : Type) (P : T -> Prop) l k, Forall P l -> Forall P (skipn k l). | |
| Proof. intros T P l k H. rewrite <- (firstn_skipn k l) in H. apply Forall_app in H. exact (proj2 H). Qed. | |
| (* ---- the recipe of a token list ---------------------------------------------------------------------------- *) | |
| Lemma length_recipe_cons : forall k ks, length (recipe (k :: ks)) = length (enc k) + length (recipe ks). | |
| Proof. intros k ks. unfold recipe. cbn [map concat]. rewrite <- app_assoc, length_app. reflexivity. Qed. | |
| Lemma delta_cons : forall k ks, delta (k :: ks) = dec k ++ delta ks. | |
| Proof. reflexivity. Qed. | |
| Lemma ceil_add : forall m, (127 + m + 126) / 127 = 1 + (m + 126) / 127. | |
| Proof. intro m. replace (127 + m + 126) with (1 * 127 + (m + 126)) by lia. rewrite Nat.div_add_l by lia. reflexivity. Qed. | |
| Lemma ceil_mono : forall a b, a <= b -> (a + 126) / 127 <= (b + 126) / 127. | |
| Proof. intros a b H. apply Nat.Div0.div_le_mono. lia. Qed. | |
| Lemma ceil_small : forall n, 1 <= n -> n <= 127 -> (n + 126) / 127 = 1. | |
| Proof. intros n H1 H2. symmetry. apply Nat.div_unique with (r := n + 126 - 127); lia. Qed. | |
| (* ---- Lemma 6.7 --------------------------------------------------------------------------------------------- *) | |
| Lemma desc_spec : forall fuel f, length f <= fuel -> Forall (fun x => x < 256) f -> | |
| let r := length (recipe (desc fuel f)) in | |
| delta (desc fuel f) = f /\ Forall tok_ok (desc fuel f) /\ r <= bound (length f) | |
| /\ (four_at f = true -> r + 2 <= bound (length f)) | |
| /\ (nofour f -> r = bound (length f)) /\ (r = bound (length f) -> nofour f). | |
| Proof. | |
| induction fuel as [|fu IH]; intros f Hl Hb r. | |
| - assert (f = []) by (destruct f; [reflexivity | cbn in Hl; lia]). subst f. unfold r. cbn. | |
| split; [reflexivity|]. split; [constructor|]. split; [lia|]. split; [discriminate|]. split; [reflexivity|]. | |
| intros _ p. destruct p; reflexivity. | |
| - destruct f as [|x f0]. | |
| + unfold r. cbn. | |
| split; [reflexivity|]. split; [constructor|]. split; [lia|]. split; [discriminate|]. split; [reflexivity|]. | |
| intros _ p. destruct p; reflexivity. | |
| + assert (Hx : x < 256) by (inversion Hb; assumption). | |
| unfold r. cbn [desc]. cbv zeta. | |
| remember (x :: f0) as f eqn:Ef. | |
| assert (Hfl : length f = S (length f0)) by (subst f; reflexivity). | |
| set (l := Nat.min (run_len x f) 127). | |
| assert (Hrun : run_len x f >= 1) by (subst f; cbn [run_len]; rewrite Nat.eqb_refl; lia). | |
| pose proof (run_le x f) as Hrl. | |
| destruct (Nat.leb_spec 4 l) as [H4|H4]. | |
| * (* a run of at least four: a repeat token *) | |
| set (f2 := skipn l f). | |
| assert (Hlf : length f = l + length f2) by (unfold f2; rewrite length_skipn; unfold l in *; lia). | |
| destruct (IH f2 ltac:(lia) ltac:(unfold f2; apply Forall_drop; exact Hb)) as (D & T & B & B2 & E1 & E2). | |
| cbv zeta in *. set (r2 := length (recipe (desc fu f2))) in *. | |
| assert (Hdec : dec (Rep (256 - l) (nu x)) = firstn l f). | |
| { cbn [dec]. rewrite nu_nu by exact Hx. replace (256 - (256 - l)) with l by (unfold l in *; lia). | |
| symmetry. apply firstn_run. unfold l. lia. } | |
| rewrite length_recipe_cons. cbn [enc length]. fold r2. | |
| assert (Hb2 : bound (length f2) + 4 <= bound (length f)). | |
| { unfold bound. rewrite Hlf. pose proof (ceil_mono (length f2) (l + length f2) ltac:(lia)). lia. } | |
| refine (conj _ (conj _ (conj _ (conj _ (conj _ _))))). | |
| -- rewrite delta_cons, D, Hdec. apply firstn_skipn. | |
| -- constructor; [|exact T]. cbn [tok_ok]. split; [unfold l in *; lia | apply nu_lt]. | |
| -- lia. | |
| -- intros _. lia. | |
| -- intro Hn. exfalso. specialize (Hn 0). cbn [skipn] in Hn. subst f. rewrite four_run in Hn. | |
| apply Nat.leb_gt in Hn. unfold l in *. lia. | |
| -- intro E. lia. | |
| * (* a literal token *) | |
| assert (Hf4 : four_at f = false). | |
| { subst f. rewrite four_run. apply Nat.leb_gt. unfold l in *. lia. } | |
| set (k := lit_scan 127 f). | |
| destruct (lit_scan_le 127 f) as [Hk1 Hk2]. fold k in Hk1, Hk2. | |
| assert (Hk0 : 1 <= k) by (apply lit_scan_pos; [lia | subst f; discriminate | exact Hf4]). | |
| set (f2 := skipn k f). | |
| assert (Hlf : length f = k + length f2) by (unfold f2; rewrite length_skipn; lia). | |
| destruct (IH f2 ltac:(lia) ltac:(unfold f2; apply Forall_drop; exact Hb)) as (D & T & B & B2 & E1 & E2). | |
| cbv zeta in *. set (r2 := length (recipe (desc fu f2))) in *. | |
| assert (Hg : Forall (fun x => x < 256) (firstn k f)) by (apply Forall_take; exact Hb). | |
| rewrite length_recipe_cons. cbn [enc length]. rewrite length_map, length_firstn, Nat.min_l by lia. fold r2. | |
| assert (Hnone : forall p, p < k -> four_at (skipn p f) = false) by (intros p Hp; apply (lit_scan_none 127); exact Hp). | |
| assert (Hnf : nofour f2 -> nofour f). | |
| { intros Hn p. destruct (Nat.lt_ge_cases p k) as [Hp|Hp]; [apply Hnone; exact Hp|]. | |
| replace p with ((p - k) + k) by lia. rewrite <- skipn_skipn. apply (Hn (p - k)). } | |
| refine (conj _ (conj _ (conj _ (conj _ (conj _ _))))). | |
| -- rewrite delta_cons, D. cbn [dec]. rewrite map_map. | |
| rewrite (map_ext_in _ (fun x => x)) by (intros y Hy; rewrite Forall_forall in Hg; apply nu_nu, Hg, Hy). | |
| rewrite map_id. apply firstn_skipn. | |
| -- constructor; [|exact T]. cbn [tok_ok]. rewrite length_map, length_firstn, Nat.min_l by lia. | |
| split; [lia|]. apply Forall_map, Forall_forall. intros y _. apply nu_lt. | |
| -- destruct (lit_scan_stop 127 f) as [S1|[S1|S1]]; fold k in S1. | |
| ++ assert (Hb' : bound (length f) = 128 + bound (length f2)) | |
| by (unfold bound; rewrite Hlf, S1, ceil_add; lia). lia. | |
| ++ assert (Hf2 : length f2 = 0) by lia. rewrite Hf2 in B. | |
| assert (Hc : (length f + 126) / 127 = 1) by (apply ceil_small; lia). | |
| unfold bound in *. rewrite Hc. cbn in B. lia. | |
| ++ destruct (Nat.eq_dec k 127) as [K7|K7]. | |
| ** assert (Hb' : bound (length f) = 128 + bound (length f2)) | |
| by (unfold bound; rewrite Hlf, K7, ceil_add; lia). lia. | |
| ** specialize (B2 S1). unfold bound in *. rewrite Hlf. pose proof (ceil_mono (length f2) (k + length f2) ltac:(lia)). lia. | |
| -- intro H. rewrite Hf4 in H. discriminate. | |
| -- intro Hn. assert (Hn2 : nofour f2) by (apply nofour_skipn; exact Hn). | |
| specialize (E1 Hn2). destruct (lit_scan_stop 127 f) as [S1|[S1|S1]]; fold k in S1. | |
| ++ assert (Hb' : bound (length f) = 128 + bound (length f2)) | |
| by (unfold bound; rewrite Hlf, S1, ceil_add; lia). lia. | |
| ++ assert (Hf2 : length f2 = 0) by lia. rewrite Hf2 in E1. | |
| assert (Hc : (length f + 126) / 127 = 1) by (apply ceil_small; lia). | |
| unfold bound in *. rewrite Hc. cbn in E1. lia. | |
| ++ exfalso. specialize (Hn k). rewrite S1 in Hn. discriminate. | |
| -- intro E. destruct (lit_scan_stop 127 f) as [S1|[S1|S1]]; fold k in S1. | |
| ++ assert (Hb' : bound (length f) = 128 + bound (length f2)) | |
| by (unfold bound; rewrite Hlf, S1, ceil_add; lia). | |
| apply Hnf, E2. lia. | |
| ++ apply Hnf. intro p. unfold f2. rewrite skipn_skipn, skipn_all2 by lia. reflexivity. | |
| ++ exfalso. specialize (B2 S1). unfold bound in *. rewrite Hlf in E. | |
| pose proof (ceil_mono (length f2) (k + length f2) ltac:(lia)). lia. | |
| Qed. | |
| Theorem describe_spec : forall f, Forall (fun x => x < 256) f -> | |
| delta (describe f) = f /\ Forall tok_ok (describe f) /\ length (recipe (describe f)) <= bound (length f) | |
| /\ (length (recipe (describe f)) = bound (length f) <-> nofour f). | |
| Proof. | |
| intros f Hb. destruct (desc_spec (length f) f (le_n _) Hb) as (D & T & B & _ & E1 & E2). | |
| unfold describe. refine (conj D (conj T (conj B (conj E2 E1)))). | |
| Qed. | |
| (* ---- the steps of P* on describe f (Theorem 7.5) ------------------------------------------------------------- *) | |
| (* the steps of Proposition 6.13 on the recipe of ks *) | |
| Definition psteps (ks : list token) : nat := dsteps ks + 7 + 1 + (6 * length (recipe ks) + 2). | |
| Lemma psteps_nil : psteps [] = 16. | |
| Proof. reflexivity. Qed. | |
| Lemma psteps_cons : forall k ks, psteps (k :: ks) = tsteps k + 6 * length (enc k) + psteps ks. | |
| Proof. intros k ks. unfold psteps. rewrite length_recipe_cons. cbn [dsteps fold_right]. fold (dsteps ks). lia. Qed. | |
| Lemma desc_steps : forall fuel f, length f <= fuel -> Forall (fun x => x < 256) f -> | |
| 2 * psteps (desc fuel f) <= 25 * length f + 58 | |
| /\ (four_at f = true -> 2 * psteps (desc fuel f) <= 25 * length f + 32) | |
| /\ (nofour f -> psteps (desc fuel f) = 11 * length f + 13 * ((length f + 126) / 127) + 16). | |
| Proof. | |
| induction fuel as [|fu IH]; intros f Hl Hb. | |
| - assert (f = []) by (destruct f; [reflexivity | cbn in Hl; lia]). subst f. cbn [desc length]. | |
| rewrite psteps_nil. split; [lia|]. split; [discriminate|]. intros _. reflexivity. | |
| - destruct f as [|x f0]. | |
| + cbn [desc length]. rewrite psteps_nil. split; [lia|]. split; [discriminate|]. intros _. reflexivity. | |
| + assert (Hx : x < 256) by (inversion Hb; assumption). | |
| cbn [desc]. cbv zeta. | |
| remember (x :: f0) as f eqn:Ef. | |
| set (l := Nat.min (run_len x f) 127). | |
| assert (Hrun : run_len x f >= 1) by (subst f; cbn [run_len]; rewrite Nat.eqb_refl; lia). | |
| pose proof (run_le x f) as Hrl. | |
| destruct (Nat.leb_spec 4 l) as [H4|H4]. | |
| * set (f2 := skipn l f). | |
| assert (Hlf : length f = l + length f2) by (unfold f2; rewrite length_skipn; unfold l in *; lia). | |
| destruct (IH f2 ltac:(lia) ltac:(unfold f2; apply Forall_drop; exact Hb)) as (B & _ & _). | |
| rewrite psteps_cons. cbn [tsteps enc length]. replace (256 - (256 - l)) with l by (unfold l in *; lia). | |
| split; [lia|]. split; [intros _; lia|]. | |
| intro Hn. exfalso. specialize (Hn 0). cbn [skipn] in Hn. subst f. rewrite four_run in Hn. | |
| apply Nat.leb_gt in Hn. unfold l in *. lia. | |
| * assert (Hf4 : four_at f = false). | |
| { subst f. rewrite four_run. apply Nat.leb_gt. unfold l in *. lia. } | |
| set (k := lit_scan 127 f). | |
| destruct (lit_scan_le 127 f) as [Hk1 Hk2]. fold k in Hk1, Hk2. | |
| assert (Hk0 : 1 <= k) by (apply lit_scan_pos; [lia | subst f; discriminate | exact Hf4]). | |
| set (f2 := skipn k f). | |
| assert (Hlf : length f = k + length f2) by (unfold f2; rewrite length_skipn; lia). | |
| destruct (IH f2 ltac:(lia) ltac:(unfold f2; apply Forall_drop; exact Hb)) as (B & B4 & E). | |
| rewrite psteps_cons. cbn [tsteps enc length]. rewrite length_map, length_firstn, Nat.min_l by lia. | |
| assert (Hd2 : length f2 = 0 -> psteps (desc fu f2) = 16). | |
| { intro H0. assert (Z : f2 = []) by (apply length_zero_iff_nil; exact H0). | |
| rewrite Z. destruct fu; reflexivity. } | |
| split; [|split; [intro H; rewrite Hf4 in H; discriminate|]]. | |
| -- destruct (lit_scan_stop 127 f) as [S1|[S1|S1]]; fold k in S1. | |
| ++ lia. | |
| ++ rewrite Hd2 by lia. lia. | |
| ++ specialize (B4 S1). lia. | |
| -- intro Hn. assert (Hn2 : nofour f2) by (apply nofour_skipn; exact Hn). | |
| specialize (E Hn2). destruct (lit_scan_stop 127 f) as [S1|[S1|S1]]; fold k in S1. | |
| ++ rewrite E, Hlf, S1, ceil_add. lia. | |
| ++ rewrite Hd2 by lia. rewrite (ceil_small (length f)) by lia. lia. | |
| ++ exfalso. specialize (Hn k). rewrite S1 in Hn. discriminate. | |
| Qed. | |
| (* every recipe of f takes at least 4 |f| steps *) | |
| Lemma psteps_lower : forall ks, Forall tok_ok ks -> 4 * length (delta ks) <= psteps ks. | |
| Proof. | |
| induction ks as [|k ks IH]; intros Hok; [cbn; lia|]. apply Forall_cons_iff in Hok as [Hk Hok]. | |
| rewrite psteps_cons, delta_cons, length_app. specialize (IH Hok). | |
| destruct k as [bs|t b]; cbn [tsteps enc dec length] in *; [rewrite length_map | rewrite repeat_length]; lia. | |
| Qed. | |
| Theorem describe_steps : forall f, Forall (fun x => x < 256) f -> | |
| 2 * psteps (describe f) <= 25 * length f + 58 | |
| /\ (nofour f -> psteps (describe f) = 11 * length f + 13 * ((length f + 126) / 127) + 16). | |
| Proof. | |
| intros f Hb. destruct (desc_steps (length f) f (le_n _) Hb) as (B & _ & E). exact (conj B E). | |
| Qed. | |
| (* ---- Lemma 6.5 --------------------------------------------------------------------------------------------- *) | |
| Corollary recipes_complete : forall f, Forall (fun x => x < 256) f -> | |
| exists ks, Forall tok_ok ks /\ delta ks = f /\ length (recipe ks) <= bound (length f). | |
| Proof. | |
| intros f Hb. destruct (describe_spec f Hb) as (D & T & B & _). exists (describe f). exact (conj T (conj D B)). | |
| Qed. | |
| (* ---- Proposition 6.6 --------------------------------------------------------------------------------------- *) | |
| Definition notwo (f : list nat) : Prop := forall p, S p < length f -> nth p f 0 <> nth (S p) f 0. | |
| Lemma notwo_app : forall a b, notwo (a ++ b) -> notwo a /\ notwo b. | |
| Proof. | |
| intros a b H. split. | |
| - intros p Hp. specialize (H p ltac:(rewrite length_app; lia)). rewrite !app_nth1 in H by lia. exact H. | |
| - intros p Hp. specialize (H (length a + p) ltac:(rewrite length_app; lia)). | |
| rewrite !app_nth2 in H by lia. replace (length a + p - length a) with p in H by lia. | |
| replace (S (length a + p) - length a) with (S p) in H by lia. exact H. | |
| Qed. | |
| Lemma token_cost : forall k, tok_ok k -> notwo (dec k) -> | |
| length (enc k) = length (dec k) + 1 /\ 1 <= length (dec k) <= 127. | |
| Proof. | |
| intros [bs|t b] Hk Hn; cbn [tok_ok] in Hk; destruct Hk as [Hk1 Hk2]; cbn [dec] in Hn; cbn [enc dec length]. | |
| - rewrite length_map. lia. | |
| - rewrite repeat_length. destruct (Nat.eq_dec (256 - t) 1) as [E|E]; [lia|]. | |
| exfalso. apply (Hn 0); rewrite ?repeat_length; [lia|]. rewrite !nth_repeat_lt by lia. reflexivity. | |
| Qed. | |
| Theorem recipe_optimal : forall ks, Forall tok_ok ks -> notwo (delta ks) -> | |
| bound (length (delta ks)) <= length (recipe ks). | |
| Proof. | |
| assert (G : forall ks, Forall tok_ok ks -> notwo (delta ks) -> | |
| length (recipe ks) = length (delta ks) + length ks + 1 /\ length (delta ks) <= 127 * length ks). | |
| { induction ks as [|k ks IH]; intros Hok Hn; [cbn; lia|]. | |
| apply Forall_cons_iff in Hok as [Hk Hok]. rewrite delta_cons in Hn. apply notwo_app in Hn as [Hn1 Hn2]. | |
| destruct (IH Hok Hn2) as [E1 E2]. destruct (token_cost k Hk Hn1) as [C1 C2]. | |
| rewrite length_recipe_cons, delta_cons, length_app, C1, E1. cbn [length]. lia. } | |
| intros ks Hok Hn. destruct (G ks Hok Hn) as [E1 E2]. rewrite E1. unfold bound. | |
| assert ((length (delta ks) + 126) / 127 < S (length ks)). | |
| { apply Nat.Div0.div_lt_upper_bound. lia. } | |
| lia. | |
| Qed. | |