跳到正文
参考文档 / ZLIB × LEAN

trees.c.build.merge.lean

此页源文件快照 · 74f587404c263dbc · 对应提交的原文 ↗

本页保留 Lean 源码及行号。点击行号可定位语句,点击 import 中的模块名可查看依赖。

1import ZlibF.Math.DeflateHeapRemove
2import ZlibF.Proof.«trees.c.build.heapify»
3
4/-! # trees.c: the actual node-merging loop and its two selected nodes -/
5
6namespace Zlib.Trees.Proofs
7open C Zlib.Trees
8
9/-- Naming a conditional source fragment distributes its following
10continuation over the unchanged decision. -/
11theorem merge_ite_bind {α β : Type} (p : Prop) [Decidable p] (a b : M α) (f : α → M β) :
12    ((if p then a else b) >>= f) = (if p then a >>= f else b >>= f) := by
13  split <;> rfl
14
15/-- The actual root removal and next-root read, in source order. -/
16def btPick2 (s : DeflateStatePtr) (tree : CtDataPtr) : M (Int32 × Int32) := do
17  let n ← pqremove s tree
18  let m ← heapAt s 1
19  pure (n, m)
20
21/-- The two descending heap-tail stores, each with its own checked decrement
22and state write, exactly as in the two C statements. -/
23def btKeepChildren (s : DeflateStatePtr) (n m : Int32) : M Unit := do
24  let hm ← isub (← rd s).heap_max 1
25  md s fun d => { d with heap_max := hm }
26  heapSet s hm n
27  let hm ← isub (← rd s).heap_max 1
28  md s fun d => { d with heap_max := hm }
29  heapSet s hm m
30
31/-- The actual selection and two tail stores before creating the parent. -/
32def btMergeOpen (s : DeflateStatePtr) (tree : CtDataPtr) : M (Int32 × Int32) := do
33  let (n, m) ← btPick2 s tree
34  btKeepChildren s n m
35  pure (n, m)
36
37/-- The actual child comparison, selected-child reload and parent-depth store. -/
38def btSetDepth (s : DeflateStatePtr) (n m node : Int32) : M Unit := do
39  let dp ← pDepth s
40  let dn ← Ptr.index dp n.toInt
41  let dm ← Ptr.index dp m.toInt
42  let mx ← if dn ≥ dm then Ptr.index dp n.toInt else Ptr.index dp m.toInt
43  setAt dp node.toInt (mx + 1)
44
45/-- The actual child-frequency reads and parent-frequency store. -/
46def btSetFreq (tree : CtDataPtr) (n m node : Int32) : M Unit := do
47  let fn ← getFc tree n.toInt
48  let fm ← getFc tree m.toInt
49  setFc tree node.toInt (fn + fm)
50
51/-- The right-to-left stores of the chained parent assignment. -/
52def btSetParents (tree : CtDataPtr) (n m node : Int32) : M Unit := do
53  setDl tree m.toInt (i2us node)
54  setDl tree n.toInt (i2us node)
55
56/-- The actual parent frequency, depth, and two right-to-left `Dad` stores. -/
57def btMakeParent (s : DeflateStatePtr) (tree : CtDataPtr) (n m node : Int32) : M Unit := do
58  btSetFreq tree n m node
59  btSetDepth s n m node
60  btSetParents tree n m node
61
62/-- The actual root replacement, checked local increment and sift-down. -/
63def btMergeClose (s : DeflateStatePtr) (tree : CtDataPtr) (node : Int32) : M Int32 := do
64  heapSet s 1 node
65  let node' ← iadd node 1
66  pqdownheap s tree 1
67  pure node'
68
69/-- One actual merge iteration, with only its two-node selection named. -/
70def btMergeBody (s : DeflateStatePtr) (tree : CtDataPtr) (node : Int32) : M Int32 := do
71  -- pqremove(s, tree, n);  m = s->heap[SMALLEST];
72  let (n, m) ← btMergeOpen s tree
73  -- tree[node].Freq = tree[n].Freq + tree[m].Freq;
74  btMakeParent s tree n m node
75  -- s->heap[SMALLEST] = node++;
76  btMergeClose s tree node
77
78/-- The actual do-while guard is checked after each completed merge. -/
79def btMergeLoop (s : DeflateStatePtr) (tree : CtDataPtr) (node : Int32) : M Int32 :=
80  cdoWhile (btMergeBody s tree)
81    (fun node => do pure (decide ((← rd s).heap_len.toInt ≥ 2), node)) node
82
83/-- The actual final root read and predecremented tail store. -/
84def btSaveRoot (s : DeflateStatePtr) : M Unit := do
85  let top ← heapAt s 1
86  let hm ← isub (← rd s).heap_max 1
87  md s fun d => { d with heap_max := hm }
88  heapSet s hm top
89
90/-- The actual removal followed by the second-root read selects two distinct
91nodes. The first is minimal in the original queue; the second is minimal in
92the remaining queue. Deletion preserves all other entries and their exact
93counts, without a callee contract premise. -/
94theorem ws_btPick2 {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (len : Nat)
95    (hlen : d.heap_len.toInt = len) (h2 : 2 ≤ len) (hsz : len < d.heap.size)
96    (hbig : d.heap.size ≤ 573)
97    (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
98    (hinj : ∀ i j, 1 ≤ i → i ≤ len → 1 ≤ j → j ≤ len → d.heap[i]! = d.heap[j]! → i = j)
99    (ho : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len 0) :
100    WS h0 id (btPick2 (Sp id) (.ref (tk.ref id) 0)) d (fun r e =>
101      ∃ (hl : Int32) (H : Array Int32), r.1 = d.heap[1]! ∧ r.2 = H[1]! ∧
102        hl.toInt = (len : Int) - 1 ∧ e = { d with heap := H, heap_len := hl } ∧
103        H.size = d.heap.size ∧
104        (∀ i, ¬ (1 ≤ i ∧ i ≤ len - 1) → H[i]! = d.heap[i]!) ∧
105        PermOn (fun i => H[i]!) (Hm (fun i => d.heap[i]!) len) (len - 1) ∧
106        HeapOK (sm (tk.arr d) d.depth) (fun i => H[i]!) (len - 1) 0 ∧
107        NV (tk.arr d) d.depth r.1 ∧ NV (tk.arr d) d.depth r.2 ∧ r.1 ≠ r.2 ∧
108        (∀ q, 1 ≤ q → q ≤ len → sm (tk.arr d) d.depth r.1 d.heap[q]! = true) ∧
109        (∀ q, 1 ≤ q → q ≤ len - 1 → sm (tk.arr d) d.depth r.2 H[q]! = true) ∧
110        (∀ q, 1 ≤ q → q ≤ len - 1 →
111          ∃ i : Nat, 2 ≤ i ∧ i ≤ len ∧ H[q]! = d.heap[i]!) ∧
112        (∀ i, 2 ≤ i → i ≤ len → ∃ q : Nat, 1 ≤ q ∧ q ≤ len - 1 ∧ H[q]! = d.heap[i]!) ∧
113        (∀ q, 1 ≤ q → q ≤ len - 1 → H[q]! ≠ r.1) ∧
114        (∀ q q', 1 ≤ q → q ≤ len - 1 → 1 ≤ q' → q' ≤ len - 1 → H[q]! = H[q']! → q = q') ∧
115        ∀ F : Int32 → Nat, GB.rs (fun q => F H[q + 1]!) (len - 1) + F r.1 =
116          GB.rs (fun q => F d.heap[q + 1]!) len) := by
117  unfold btPick2
118  refine WS.bind' (ws_pqremove tk d len hlen h2 hsz (by omega) hval ho)
119    fun n e1 ⟨hn, hl, H, hhl, he1, hsH, hframe, hp, horder⟩ => ?_
120  subst e1
121  refine WS.bind' (ws_heapAt 1 (by decide +kernel)
122    (by change (1 : Int) < H.size; omega)) fun m e1 ⟨hm, he1⟩ => ?_
123  subst e1
124  have hindex : (1 : Int32).toInt.toNat = 1 := rfl
125  change m = H[(1 : Int32).toInt.toNat]! at hm
126  rw [hindex] at hm
127  subst n; subst m
128  have hp' : PermOn (fun i => H[i]!) (Hm (fun i => d.heap[i]!) len) (len - 1) := hp
129  obtain ⟨hroot, hHinj⟩ := hp'.removed_injective h2 hinj
130  have hvH : ∀ q, 1 ≤ q → q ≤ len - 1 → NV (tk.arr d) d.depth H[q]! := by
131    intro q hq1 hq2
132    obtain ⟨i, hi1, hi2, hqi⟩ := hp'.removed_origin h2 q hq1 hq2
133    change H[q]! = d.heap[i]! at hqi
134    rw [hqi]
135    exact hval i (by omega) hi2
136  refine WS.pure' ⟨hl, H, rfl, rfl, hhl, rfl, hsH, hframe, hp', horder,
137    hval 1 (by omega) (by omega), ?_, ?_, ?_, ?_, ?_, ?_, hroot, hHinj, ?_⟩
138  · have hv := hvH 1 (by omega) (by omega)
139    exact hv
140  · have hr := hroot 1 (by omega) (by omega)
141    exact hr.symm
142  · exact ho.root_min (sm_ok (tk.arr d) d.depth)
143  · have hmin := horder.root_min (sm_ok (tk.arr d) d.depth)
144    exact hmin
145  · intro q hq1 hq2
146    exact hp'.removed_origin h2 q hq1 hq2
147  · intro i hi1 hi2
148    exact hp'.removed_preimage h2 i hi1 hi2
149  · intro F
150    exact hp'.removed_sum h2 F
151
152/-- The actual descending stores preserve both children in the correct
153order and leave every other heap cell untouched. Heap length and all fields
154outside the heap array and tail boundary are unchanged. -/
155theorem ws_btKeepChildren {h0 : Heap} {id : Nat} (d : DeflateState) (n m : Int32)
156    (hm2 : 2 ≤ d.heap_max.toInt) (hmH : d.heap_max.toInt ≤ d.heap.size) (hbig : d.heap.size ≤ 573) :
157    WS h0 id (btKeepChildren (Sp id) n m) d (fun _ e =>
158      ∃ hm1 hm2 : Int32, hm1.toInt = d.heap_max.toInt - 1 ∧ hm2.toInt = d.heap_max.toInt - 2 ∧
159        e = { d with heap_max := hm2, heap := (d.heap.set! hm1.toInt.toNat n).set! hm2.toInt.toNat m } ∧
160        e.heap.size = d.heap.size ∧ e.heap[hm1.toInt.toNat]! = n ∧ e.heap[hm2.toInt.toNat]! = m ∧
161        ∀ i, i ≠ hm1.toInt.toNat → i ≠ hm2.toInt.toNat → e.heap[i]! = d.heap[i]!) := by
162  have hi1 : (1 : Int32).toInt = 1 := rfl
163  unfold btKeepChildren
164  refine WS.bind' ws_rd fun dz e1 ⟨hdz, he1⟩ => ?_
165  subst e1; subst dz
166  refine WS.bind' (ws_isub d.heap_max 1 (by omega) (by omega)) fun hm1 e1 ⟨hh1, he1⟩ => ?_
167  subst e1
168  refine WS.bind' (ws_md _) fun _ e1 he1 => ?_
169  subst e1
170  unfold heapSet
171  simp only [M_bind_assoc]
172  refine WS.bind' ws_pHeap fun p e1 ⟨hp, he1⟩ => ?_
173  subst e1; subst p
174  refine WS.bind' (ws_setAt_heap hm1.toInt n (by omega) (by dsimp; omega)) fun _ e1 he1 => ?_
175  subst e1
176  refine WS.bind' ws_rd fun dz e1 ⟨hdz, he1⟩ => ?_
177  subst e1; subst dz
178  refine WS.bind' (ws_isub _ 1 (by dsimp; omega) (by dsimp; omega)) fun hm2 e1 ⟨hh2, he1⟩ => ?_
179  subst e1
180  refine WS.bind' (ws_md _) fun _ e1 he1 => ?_
181  subst e1
182  refine WS.bind' ws_pHeap fun p e1 ⟨hp, he1⟩ => ?_
183  subst e1; subst p
184  refine WS.mono (ws_setAt_heap hm2.toInt m (by dsimp at hh2; omega)
185    (by change hm2.toInt < ((d.heap.set! hm1.toInt.toNat n).size : Int); rw [size_set!]; dsimp at hh2; omega)) ?_
186  intro _ e1 he1
187  subst e1
188  have hh2 : hm2.toInt = d.heap_max.toInt - 2 := by dsimp at hh2; omega
189  have h1 : hm1.toInt.toNat < d.heap.size := by omega
190  have h2 : hm2.toInt.toNat < d.heap.size := by omega
191  have hne : hm1.toInt.toNat ≠ hm2.toInt.toNat := by omega
192  refine ⟨hm1, hm2, by omega, hh2, rfl, by simp only [size_set!], ?_, ?_, ?_⟩
193  · dsimp only
194    rw [getD_set _ hm2.toInt.toNat hm1.toInt.toNat m (by simpa only [size_set!] using h2), ite_eq_right hne,
195      getD_set _ hm1.toInt.toNat hm1.toInt.toNat n h1, ite_eq_left rfl]
196  · dsimp only
197    rw [getD_set _ hm2.toInt.toNat hm2.toInt.toNat m (by simpa only [size_set!] using h2), ite_eq_left rfl]
198  · intro i hi1 hi2
199    dsimp only
200    rw [getD_set _ hm2.toInt.toNat i m (by simpa only [size_set!] using h2), ite_eq_right hi2,
201      getD_set _ hm1.toInt.toNat i n h1, ite_eq_right hi1]
202
203/-- The complete opening of an actual merge keeps both selected nodes in
204the descending tail and preserves the remaining queue, its order, membership
205and counts. The queue/tail gap prevents overwriting any live queue entry. -/
206theorem ws_btMergeOpen {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (len : Nat)
207    (hlen : d.heap_len.toInt = len) (h2 : 2 ≤ len) (hsz : len < d.heap.size)
208    (hbig : d.heap.size ≤ 573) (hmH : d.heap_max.toInt ≤ d.heap.size)
209    (hgap : (len : Int) < d.heap_max.toInt - 1)
210    (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
211    (hinj : ∀ i j, 1 ≤ i → i ≤ len → 1 ≤ j → j ≤ len → d.heap[i]! = d.heap[j]! → i = j)
212    (ho : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len 0) :
213    WS h0 id (btMergeOpen (Sp id) (.ref (tk.ref id) 0)) d (fun r e =>
214      ∃ (hl hm1 hm2 : Int32) (H : Array Int32),
215        r.1 = d.heap[1]! ∧ r.2 = H[1]! ∧ r.1 ≠ r.2 ∧
216        hl.toInt = (len : Int) - 1 ∧ hm1.toInt = d.heap_max.toInt - 1 ∧ hm2.toInt = d.heap_max.toInt - 2 ∧
217        e = { d with heap := H, heap_len := hl, heap_max := hm2 } ∧ H.size = d.heap.size ∧
218        H[hm1.toInt.toNat]! = r.1 ∧ H[hm2.toInt.toNat]! = r.2 ∧
219        NV (tk.arr d) d.depth r.1 ∧ NV (tk.arr d) d.depth r.2 ∧
220        HeapOK (sm (tk.arr d) d.depth) (fun i => H[i]!) (len - 1) 0 ∧
221        (∀ q, 1 ≤ q → q ≤ len → sm (tk.arr d) d.depth r.1 d.heap[q]! = true) ∧
222        (∀ q, 1 ≤ q → q ≤ len - 1 → sm (tk.arr d) d.depth r.2 H[q]! = true) ∧
223        (∀ q, 1 ≤ q → q ≤ len - 1 → ∃ i : Nat, 2 ≤ i ∧ i ≤ len ∧ H[q]! = d.heap[i]!) ∧
224        (∀ i, 2 ≤ i → i ≤ len → ∃ q : Nat, 1 ≤ q ∧ q ≤ len - 1 ∧ H[q]! = d.heap[i]!) ∧
225        (∀ q, 1 ≤ q → q ≤ len - 1 → H[q]! ≠ r.1) ∧
226        (∀ q q', 1 ≤ q → q ≤ len - 1 → 1 ≤ q' → q' ≤ len - 1 → H[q]! = H[q']! → q = q') ∧
227        ∀ F : Int32 → Nat, GB.rs (fun q => F H[q + 1]!) (len - 1) + F r.1 =
228          GB.rs (fun q => F d.heap[q + 1]!) len) := by
229  unfold btMergeOpen
230  refine WS.bind' (ws_btPick2 tk d len hlen h2 hsz hbig hval hinj ho)
231    fun r e1 ⟨hl, H, hn, hm, hhl, he1, hsH, hframe, hp, horder, hnv, hmv, hnm,
232      hminn, hminm, horigin, hcomplete, hno, hHinj, hcount⟩ => ?_
233  subst e1
234  rcases r with ⟨n, m⟩
235  dsimp only at hn hm hnv hmv hnm hminn hminm hno hcount ⊢
236  refine WS.bind' (ws_btKeepChildren { d with heap := H, heap_len := hl } n m
237    (by change 2 ≤ d.heap_max.toInt; omega) (by change d.heap_max.toInt ≤ (H.size : Int); omega)
238    (by change H.size ≤ 573; omega))
239    fun _ e2 ⟨hm1, hm2, hh1, hh2, he2, hsH', hnKeep, hmKeep, hKeepFrame⟩ => ?_
240  subst e2
241  let H' := (H.set! hm1.toInt.toNat n).set! hm2.toInt.toNat m
242  have hh1 : hm1.toInt = d.heap_max.toInt - 1 := hh1
243  have hh2 : hm2.toInt = d.heap_max.toInt - 2 := hh2
244  have hqueue : ∀ q, 1 ≤ q → q ≤ len - 1 → H'[q]! = H[q]! := by
245    intro q hq1 hq2
246    exact hKeepFrame q (by omega) (by omega)
247  have hroot : H'[1]! = m := (hqueue 1 (by omega) (by omega)).trans hm.symm
248  refine WS.pure' ⟨hl, hm1, hm2, H', hn, hroot.symm, hnm, hhl, hh1, hh2, rfl,
249    by dsimp only [H']; simp only [size_set!]; exact hsH,
250    hnKeep, hmKeep, hnv, hmv, ?_, hminn, ?_, ?_, ?_, ?_, ?_, ?_⟩
251  · intro c hc2 hcl hcp
252    dsimp only
253    rw [hqueue c (by omega) hcl, hqueue (c / 2) (by omega) (by omega)]
254    exact horder c hc2 hcl hcp
255  · intro q hq1 hq2
256    rw [hqueue q hq1 hq2]
257    exact hminm q hq1 hq2
258  · intro q hq1 hq2
259    obtain ⟨i, hi1, hi2, hqi⟩ := horigin q hq1 hq2
260    exact ⟨i, hi1, hi2, (hqueue q hq1 hq2).trans hqi⟩
261  · intro i hi1 hi2
262    obtain ⟨q, hq1, hq2, hqi⟩ := hcomplete i hi1 hi2
263    exact ⟨q, hq1, hq2, (hqueue q hq1 hq2).trans hqi⟩
264  · intro q hq1 hq2
265    rw [hqueue q hq1 hq2]
266    exact hno q hq1 hq2
267  · intro q q' hq1 hq2 hq'1 hq'2 heq
268    rw [hqueue q hq1 hq2, hqueue q' hq'1 hq'2] at heq
269    exact hHinj q q' hq1 hq2 hq'1 hq'2 heq
270  · intro F
271    rw [show GB.rs (fun q => F H'[q + 1]!) (len - 1) = GB.rs (fun q => F H[q + 1]!) (len - 1) by
272      apply GB.rs_congr
273      intro q hq
274      rw [hqueue (q + 1) (by omega) (by omega)]]
275    exact hcount F
276
277/-- The corrected source expression, including its third read, stores the
278selected child depth plus one modulo 256. Every other depth and state field
279is unchanged. No non-wrapping-depth assumption is required. -/
280theorem ws_btSetDepth {h0 : Heap} {id : Nat} (d : DeflateState) (n m node : Int32)
281    (hn0 : 0 ≤ n.toInt) (hnD : n.toInt < d.depth.size)
282    (hm0 : 0 ≤ m.toInt) (hmD : m.toInt < d.depth.size)
283    (hp0 : 0 ≤ node.toInt) (hpD : node.toInt < d.depth.size) :
284    WS h0 id (btSetDepth (Sp id) n m node) d (fun _ e =>
285      e = { d with
286        depth := d.depth.set! node.toInt.toNat
287          ((if d.depth[n.toInt.toNat]! ≥ d.depth[m.toInt.toNat]! then
288            d.depth[n.toInt.toNat]! else d.depth[m.toInt.toNat]!) + 1) }) := by
289  unfold btSetDepth
290  refine WS.bind' ws_pDepth fun p e1 ⟨hp, he1⟩ => ?_
291  subst e1; subst p
292  refine WS.bind' (ws_index_depth n.toInt hn0 hnD) fun dn e1 ⟨hdn, he1⟩ => ?_
293  subst e1; subst dn
294  refine WS.bind' (ws_index_depth m.toInt hm0 hmD) fun dm e1 ⟨hdm, he1⟩ => ?_
295  subst e1; subst dm
296  by_cases hc : d.depth[n.toInt.toNat]! ≥ d.depth[m.toInt.toNat]!
297  · simp only [hc, ite_true]
298    refine WS.bind' (ws_index_depth n.toInt hn0 hnD) fun mx e1 ⟨hmx, he1⟩ => ?_
299    subst e1; subst mx
300    exact ws_setAt_depth node.toInt _ hp0 hpD
301  · simp only [hc, ite_false]
302    refine WS.bind' (ws_index_depth m.toInt hm0 hmD) fun mx e1 ⟨hmx, he1⟩ => ?_
303    subst e1; subst mx
304    exact ws_setAt_depth node.toInt _ hp0 hpD
305
306/-- Exact parent-creation record, retaining source order even if the three
307indices alias. Parent-index casts and both byte/word arithmetic operations
308keep their unsigned wrapping behavior. -/
309def btParentState (tk : TK) (d : DeflateState) (n m node : Int32) : DeflateState :=
310  let T := tk.arr d
311  let T1 := T.set! node.toInt.toNat { T[node.toInt.toNat]! with fc := T[n.toInt.toNat]!.fc + T[m.toInt.toNat]!.fc }
312  let T2 := T1.set! m.toInt.toNat { T1[m.toInt.toNat]! with dl := i2us node }
313  let T3 := T2.set! n.toInt.toNat { T2[n.toInt.toNat]! with dl := i2us node }
314  { tk.setArr d T3 with
315    depth := d.depth.set! node.toInt.toNat
316      ((if d.depth[n.toInt.toNat]! ≥ d.depth[m.toInt.toNat]! then
317        d.depth[n.toInt.toNat]! else d.depth[m.toInt.toNat]!) + 1) }
318
319/-- Exact frequency store, including unsigned 16-bit addition wrap. -/
320theorem ws_btSetFreq {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (n m node : Int32)
321    (hn0 : 0 ≤ n.toInt) (hnT : n.toInt < (tk.arr d).size)
322    (hm0 : 0 ≤ m.toInt) (hmT : m.toInt < (tk.arr d).size)
323    (hp0 : 0 ≤ node.toInt) (hpT : node.toInt < (tk.arr d).size) :
324    WS h0 id (btSetFreq (.ref (tk.ref id) 0) n m node) d (fun _ e =>
325      e = tk.setArr d ((tk.arr d).set! node.toInt.toNat
326        { (tk.arr d)[node.toInt.toNat]! with fc := ((tk.arr d)[n.toInt.toNat]!).fc + ((tk.arr d)[m.toInt.toNat]!).fc })) := by
327  unfold btSetFreq
328  refine WS.bind' (ws_getFc tk n.toInt hn0 hnT) fun fn e1 ⟨hfn, he1⟩ => ?_
329  subst e1; subst fn
330  refine WS.bind' (ws_getFc tk m.toInt hm0 hmT) fun fm e1 ⟨hfm, he1⟩ => ?_
331  subst e1; subst fm
332  exact ws_setFc tk node.toInt _ hp0 hpT
333
334/-- Exact parent stores, including aliases between the two child indices. -/
335theorem ws_btSetParents {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (n m node : Int32)
336    (hn0 : 0 ≤ n.toInt) (hnT : n.toInt < (tk.arr d).size)
337    (hm0 : 0 ≤ m.toInt) (hmT : m.toInt < (tk.arr d).size) :
338    WS h0 id (btSetParents (.ref (tk.ref id) 0) n m node) d (fun _ e =>
339      let T1 := (tk.arr d).set! m.toInt.toNat { (tk.arr d)[m.toInt.toNat]! with dl := i2us node }
340      e = tk.setArr d (T1.set! n.toInt.toNat { T1[n.toInt.toNat]! with dl := i2us node })) := by
341  unfold btSetParents
342  refine WS.bind' (ws_setDl tk m.toInt (i2us node) hm0 hmT) fun _ e1 he1 => ?_
343  subst e1
344  refine WS.mono (ws_setDl tk n.toInt (i2us node) hn0
345    (by rw [tk_arr_setArr, size_set!]; exact hnT)) ?_
346  intro _ e1 he1
347  subst e1
348  simp only [tk_arr_setArr]
349  cases tk <;> rfl
350
351set_option maxRecDepth 4096 in
352/-- The entire actual parent-creation fragment has these exact record effects.
353No acyclicity, freshness, distinctness, non-wrapping weight, or callee contract
354is assumed. Those structural facts are obligations of the merge invariant. -/
355theorem ws_btMakeParent {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (n m node : Int32)
356    (hn : NV (tk.arr d) d.depth n) (hm : NV (tk.arr d) d.depth m)
357    (hp : NV (tk.arr d) d.depth node) :
358    WS h0 id (btMakeParent (Sp id) (.ref (tk.ref id) 0) n m node) d
359      (fun _ e => e = btParentState tk d n m node) := by
360  let T1 := (tk.arr d).set! node.toInt.toNat
361    { (tk.arr d)[node.toInt.toNat]! with fc := ((tk.arr d)[n.toInt.toNat]!).fc + ((tk.arr d)[m.toInt.toNat]!).fc }
362  have hsT1 : T1.size = (tk.arr d).size := by dsimp only [T1]; rw [size_set!]
363  let D := d.depth.set! node.toInt.toNat
364    ((if d.depth[n.toInt.toNat]! ≥ d.depth[m.toInt.toNat]! then
365      d.depth[n.toInt.toNat]! else d.depth[m.toInt.toNat]!) + 1)
366  let d1 := tk.setArr d T1
367  let d2 := { d1 with depth := D }
368  unfold btMakeParent
369  refine WS.bind' (ws_btSetFreq tk d n m node hn.1 hn.2.1 hm.1 hm.2.1 hp.1 hp.2.1)
370    fun _ e1 he1 => ?_
371  change e1 = d1 at he1
372  subst e1
373  have hd1 : d1.depth = d.depth := by exact tk_setArr_depth tk T1
374  refine WS.bind' (ws_btSetDepth d1 n m node hn.1
375    (by rw [hd1]; exact hn.2.2) hm.1 (by rw [hd1]; exact hm.2.2) hp.1
376    (by rw [hd1]; exact hp.2.2)) fun _ e1 he1 => ?_
377  rw [hd1] at he1
378  change e1 = d2 at he1
379  subst e1
380  have hT1 : tk.arr d2 = T1 := by cases tk <;> rfl
381  refine WS.mono (ws_btSetParents tk d2 n m node hn.1
382    (by rw [hT1, hsT1]; exact hn.2.1) hm.1 (by rw [hT1, hsT1]; exact hm.2.1)) ?_
383  intro _ e1 he1
384  subst e1
385  unfold btParentState
386  dsimp only [d2, d1, T1, D]
387  cases tk <;> rfl
388
389/-- The actual closing statements re-establish a fully ordered queue.
390The source's signed counter increment is checked. The exact count equation
391accounts for removing the old root and inserting the new parent. -/
392theorem ws_btMergeClose {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (len : Nat) (node : Int32)
393    (hlen : d.heap_len.toInt = len) (h1 : 1 ≤ len) (hsz : len < d.heap.size)
394    (hbig : d.heap.size ≤ 573) (hnode : NV (tk.arr d) d.depth node) (hinc : node.toInt < 2147483647)
395    (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
396    (ho : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len 1) :
397    WS h0 id (btMergeClose (Sp id) (.ref (tk.ref id) 0) node) d (fun r e =>
398      r.toInt = node.toInt + 1 ∧ ∃ H : Array Int32, e = { d with heap := H } ∧ H.size = d.heap.size ∧
399        (∀ i, ¬ (1 ≤ i ∧ i ≤ len) → H[i]! = d.heap[i]!) ∧
400        PermOn (fun i => H[i]!) (fun i => if i = 1 then node else d.heap[i]!) len ∧
401        HeapOK (sm (tk.arr d) d.depth) (fun i => H[i]!) len 0 ∧
402        (∀ q, 1 ≤ q → q ≤ len → sm (tk.arr d) d.depth H[1]! H[q]! = true) ∧
403        ∀ F : Int32 → Nat, GB.rs (fun i => F H[i + 1]!) len + F d.heap[1]! =
404          GB.rs (fun i => F d.heap[i + 1]!) len + F node) := by
405  have hi1 : (1 : Int32).toInt = 1 := rfl
406  have hi1N : (1 : Int32).toInt.toNat = 1 := rfl
407  have hs1 : 1 < d.heap.size := by omega
408  unfold btMergeClose
409  refine WS.bind' (ws_heapSet 1 node (by decide +kernel) (by change (1 : Int) < d.heap.size; omega))
410    fun _ e1 he1 => ?_
411  simp only [hi1N] at he1
412  subst e1
413  refine WS.bind' (ws_iadd node 1 (by have := hnode.1; omega) (by omega)) fun next e1 ⟨hnxt, he1⟩ => ?_
414  subst e1
415  have hvals : ∀ i, 1 ≤ i → i ≤ len →
416      NV (tk.arr { d with heap := d.heap.set! 1 node }) d.depth (d.heap.set! 1 node)[i]! := by
417    intro i hi1 hi2
418    rw [tk_arr_heap, getD_set d.heap 1 i node hs1]
419    split
420    · exact hnode
421    · exact hval i hi1 hi2
422  have horder : HeapOK (sm (tk.arr { d with heap := d.heap.set! 1 node }) d.depth)
423      (fun i => (d.heap.set! 1 node)[i]!) len 1 := by
424    rw [tk_arr_heap]
425    intro c hc2 hcl hcp
426    dsimp only
427    rw [getD_set d.heap 1 (c / 2) node hs1, ite_eq_right (by omega),
428      getD_set d.heap 1 c node hs1, ite_eq_right (by omega)]
429    exact ho c hc2 hcl hcp
430  refine WS.bind' (ws_pqdownheap tk { d with heap := d.heap.set! 1 node } 1 1 len hi1
431    (by omega) h1 hlen (by dsimp only; rw [size_set!]; omega)
432    (by dsimp only; rw [size_set!]; omega) hvals horder)
433    fun _ e1 ⟨H, he1, hsH, hf, hp, hHeap⟩ => ?_
434  subst e1
435  simp only [tk_arr_heap] at hHeap
436  have hp' : PermOn (fun i => H[i]!) (fun i => if i = 1 then node else d.heap[i]!) len := by
437    have heq : (fun i => (d.heap.set! 1 node)[i]!) = (fun i => if i = 1 then node else d.heap[i]!) := by
438      funext i
439      exact getD_set d.heap 1 i node hs1
440    rwa [heq] at hp
441  refine WS.pure' ⟨by omega, H, rfl, by simpa only [size_set!] using hsH, ?_, hp', hHeap, ?_, ?_⟩
442  · intro i hi
443    have hfi := hf i hi
444    dsimp only at hfi
445    rw [hfi, getD_set d.heap 1 i node hs1, ite_eq_right (by omega)]
446  · exact hHeap.root_min (sm_ok (tk.arr d) d.depth)
447  · intro F
448    rw [hp'.sum F]
449    exact replace_root_sum (fun i => d.heap[i]!) node len h1 F
450
451
452/-- Updating the parent link does not change a frequency, including at the
453updated cell. -/
454theorem merge_setDad_fc (T : Array CtData) (k i : Nat) (dad : UInt16) (hk : k < T.size) :
455    ((T.set! k { T[k]! with dl := dad })[i]!).fc = T[i]!.fc := by
456  rw [getD_set T k i _ hk]
457  split <;> simp_all
458
459@[simp] theorem btParentState_heap (tk : TK) (d : DeflateState) (n m node : Int32) :
460    (btParentState tk d n m node).heap = d.heap := by cases tk <;> rfl
461
462@[simp] theorem btParentState_len (tk : TK) (d : DeflateState) (n m node : Int32) :
463    (btParentState tk d n m node).heap_len = d.heap_len := by cases tk <;> rfl
464
465@[simp] theorem btParentState_max (tk : TK) (d : DeflateState) (n m node : Int32) :
466    (btParentState tk d n m node).heap_max = d.heap_max := by cases tk <;> rfl
467
468@[simp] theorem btParentState_tree_size (tk : TK) (d : DeflateState) (n m node : Int32) :
469    (tk.arr (btParentState tk d n m node)).size = (tk.arr d).size := by
470  cases tk <;> simp only [btParentState, TK.arr, TK.setArr, size_set!]
471
472@[simp] theorem btParentState_depth_size (tk : TK) (d : DeflateState) (n m node : Int32) :
473    (btParentState tk d n m node).depth.size = d.depth.size := by
474  cases tk <;> simp only [btParentState, TK.arr, TK.setArr, size_set!]
475
476/-- All parent-link stores preserve frequencies. Only the fresh parent's
477frequency is replaced, with the source's wrapping sum. -/
478theorem btParentState_fc (tk : TK) (d : DeflateState) (n m node : Int32)
479    (hn : NV (tk.arr d) d.depth n) (hm : NV (tk.arr d) d.depth m)
480    (hp : NV (tk.arr d) d.depth node) (i : Nat) :
481    (tk.arr (btParentState tk d n m node))[i]!.fc =
482      if i = node.toInt.toNat then (tk.arr d)[n.toInt.toNat]!.fc + (tk.arr d)[m.toInt.toNat]!.fc
483      else (tk.arr d)[i]!.fc := by
484  have hnT : n.toInt.toNat < (tk.arr d).size := by have := hn.1; have := hn.2.1; omega
485  have hmT : m.toInt.toNat < (tk.arr d).size := by have := hm.1; have := hm.2.1; omega
486  have hpT : node.toInt.toNat < (tk.arr d).size := by have := hp.1; have := hp.2.1; omega
487  have harr : tk.arr (btParentState tk d n m node) =
488      let T := tk.arr d
489      let T1 := T.set! node.toInt.toNat { T[node.toInt.toNat]! with fc := T[n.toInt.toNat]!.fc + T[m.toInt.toNat]!.fc }
490      let T2 := T1.set! m.toInt.toNat { T1[m.toInt.toNat]! with dl := i2us node }
491      T2.set! n.toInt.toNat { T2[n.toInt.toNat]! with dl := i2us node } := by cases tk <;> rfl
492  rw [harr]
493  dsimp only
494  rw [merge_setDad_fc _ _ _ _ (by simp only [size_set!]; exact hnT),
495    merge_setDad_fc _ _ _ _ (by simp only [size_set!]; exact hmT), getD_set _ _ _ _ hpT]
496  split <;> rfl
497
498/-- Every old depth cell is unchanged when the fresh parent depth is written. -/
499theorem btParentState_depth (tk : TK) (d : DeflateState) (n m node : Int32)
500    (hp : NV (tk.arr d) d.depth node) (i : Nat) :
501    (btParentState tk d n m node).depth[i]! =
502      if i = node.toInt.toNat then
503        (if d.depth[n.toInt.toNat]! ≥ d.depth[m.toInt.toNat]! then
504          d.depth[n.toInt.toNat]! else d.depth[m.toInt.toNat]!) + 1
505      else d.depth[i]! := by
506  have hpD : node.toInt.toNat < d.depth.size := by have := hp.1; have := hp.2.2; omega
507  exact getD_set _ _ _ _ hpD
508
509/-- The ordering key of any two previously allocated nodes is preserved.
510Freshness is a numeric data condition, not a callee specification. -/
511theorem btParentState_sm (tk : TK) (d : DeflateState) (n m node a b : Int32)
512    (hn : NV (tk.arr d) d.depth n) (hm : NV (tk.arr d) d.depth m)
513    (hp : NV (tk.arr d) d.depth node)
514    (ha : 0 ≤ a.toInt) (hap : a.toInt < node.toInt)
515    (hb : 0 ≤ b.toInt) (hbp : b.toInt < node.toInt) :
516    sm (tk.arr (btParentState tk d n m node)) (btParentState tk d n m node).depth a b =
517      sm (tk.arr d) d.depth a b := by
518  have han : a.toInt.toNat ≠ node.toInt.toNat := by omega
519  have hbn : b.toInt.toNat ≠ node.toInt.toNat := by omega
520  simp only [sm, btParentState_fc tk d n m node hn hm hp, btParentState_depth tk d n m node hp,
521    han, hbn, ite_false]
522
523
524/-- One complete actual merge iteration terminates, creates its parent,
525retains both children in the tail and restores a distinct ordered queue.
526The explicit numeric freshness and queue/tail separation conditions are
527internal representation obligations; no called function's contract is a
528premise. The count equation holds for every node-counting function. -/
529theorem ws_btMergeBody {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (len : Nat) (node : Int32)
530    (hlen : d.heap_len.toInt = len) (h2 : 2 ≤ len) (hsz : len < d.heap.size)
531    (hbig : d.heap.size ≤ 573) (hmH : d.heap_max.toInt ≤ d.heap.size)
532    (hgap : (len : Int) < d.heap_max.toInt - 1)
533    (hp : NV (tk.arr d) d.depth node) (hinc : node.toInt < 2147483647)
534    (hbefore : ∀ i, 1 ≤ i → i ≤ len → 0 ≤ d.heap[i]!.toInt ∧ d.heap[i]!.toInt < node.toInt)
535    (hinj : ∀ i j, 1 ≤ i → i ≤ len → 1 ≤ j → j ≤ len → d.heap[i]! = d.heap[j]! → i = j)
536    (ho : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len 0) :
537    WS h0 id (btMergeBody (Sp id) (.ref (tk.ref id) 0) node) d (fun r e =>
538      r.toInt = node.toInt + 1 ∧ ∃ (n m hl hm1 hm2 : Int32) (H H' : Array Int32),
539        n = d.heap[1]! ∧ m = H[1]! ∧ n ≠ m ∧
540        hl.toInt = (len : Int) - 1 ∧ hm1.toInt = d.heap_max.toInt - 1 ∧ hm2.toInt = d.heap_max.toInt - 2 ∧
541        e = { btParentState tk { d with heap := H, heap_len := hl, heap_max := hm2 } n m node with heap := H' } ∧
542        H'.size = d.heap.size ∧ H'[hm1.toInt.toNat]! = n ∧ H'[hm2.toInt.toNat]! = m ∧
543        HeapOK (sm (tk.arr e) e.depth) (fun i => H'[i]!) (len - 1) 0 ∧
544        (∀ i, 1 ≤ i → i ≤ len - 1 → 0 ≤ H'[i]!.toInt ∧ H'[i]!.toInt ≤ node.toInt) ∧
545        (∀ i j, 1 ≤ i → i ≤ len - 1 → 1 ≤ j → j ≤ len - 1 → H'[i]! = H'[j]! → i = j) ∧
546        ∀ F : Int32 → Nat, GB.rs (fun i => F H'[i + 1]!) (len - 1) + F n + F m =
547          GB.rs (fun i => F d.heap[i + 1]!) len + F node) := by
548  have hv : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]! := by
549    intro i hi1 hi2
550    have hb := hbefore i hi1 hi2
551    exact ⟨hb.1, by have := hp.2.1; omega, by have := hp.2.2; omega⟩
552  unfold btMergeBody
553  refine WS.bind' (ws_btMergeOpen tk d len hlen h2 hsz hbig hmH hgap hv hinj ho)
554    fun pair e1 ⟨hl, hm1, hm2, H, hn, hm, hnm, hhl, hh1, hh2, he1, hsH, hkeepn, hkeepm,
555      hnv, hmv, horder, hminn, hminm, horigin, hcomplete, hno, hHi, hcount⟩ => ?_
556  rcases pair with ⟨n, m⟩
557  dsimp only at hn hm hnm hnv hmv hminn hminm hkeepn hkeepm hno hcount ⊢
558  subst e1
559  let d1 := { d with heap := H, heap_len := hl, heap_max := hm2 }
560  have hT1 : tk.arr d1 = tk.arr d := by cases tk <;> rfl
561  have hD1 : d1.depth = d.depth := rfl
562  have hp1 : NV (tk.arr d1) d1.depth node := by rw [hT1, hD1]; exact hp
563  have hn1 : NV (tk.arr d1) d1.depth n := by rw [hT1, hD1]; exact hnv
564  have hm1v : NV (tk.arr d1) d1.depth m := by rw [hT1, hD1]; exact hmv
565  have hB : ∀ i, 1 ≤ i → i ≤ len - 1 → 0 ≤ H[i]!.toInt ∧ H[i]!.toInt < node.toInt := by
566    intro i hi1 hi2
567    obtain ⟨j, hj1, hj2, heq⟩ := horigin i hi1 hi2
568    rw [heq]
569    exact hbefore j (by omega) hj2
570  refine WS.bind' (ws_btMakeParent tk d1 n m node hn1 hm1v hp1) fun _ e2 he2 => ?_
571  subst e2
572  let d2 := btParentState tk d1 n m node
573  have hp2 : NV (tk.arr d2) d2.depth node := by
574    simpa only [d2, NV, btParentState_tree_size, btParentState_depth_size] using hp1
575  have hv2 : ∀ i, 1 ≤ i → i ≤ len - 1 → NV (tk.arr d2) d2.depth d2.heap[i]! := by
576    intro i hi1 hi2
577    have hb := hB i hi1 hi2
578    simp only [d2, btParentState_heap, d1, NV, btParentState_tree_size, btParentState_depth_size, hT1]
579    exact ⟨hb.1, by have := hp.2.1; omega, by have := hp.2.2; omega⟩
580  have ho2 : HeapOK (sm (tk.arr d2) d2.depth) (fun i => d2.heap[i]!) (len - 1) 1 := by
581    intro c hc2 hcl hcp
582    have hb := hB c (by omega) hcl
583    have hb' := hB (c / 2) (by omega) (by omega)
584    dsimp only [d2]
585    rw [btParentState_heap]
586    change sm (tk.arr (btParentState tk d1 n m node)) (btParentState tk d1 n m node).depth H[c / 2]! H[c]! = true
587    rw [btParentState_sm tk d1 n m node _ _ hn1 hm1v hp1 hb'.1 hb'.2 hb.1 hb.2, hT1, hD1]
588    exact horder c hc2 hcl (by omega)
589  refine WS.mono (ws_btMergeClose tk d2 (len - 1) node
590    (by simpa only [d2, btParentState_len] using hhl.trans (by omega)) (by omega)
591    (by simpa only [d2, btParentState_heap] using (show len - 1 < H.size by omega))
592    (by simpa only [d2, btParentState_heap] using (show H.size ≤ 573 by omega)) hp2 hinc hv2 ho2) ?_
593  intro next e3 ⟨hnext, H', he3, hsH', hframe, hperm, horder', hmin', hcount'⟩
594  subst e3
595  have hHeap2 : d2.heap = H := by simp only [d2, btParentState_heap]; rfl
596  have hlen1 : 1 ≤ len - 1 := by omega
597  have hroot : d2.heap[1]! = m := by rw [hHeap2]; exact hm.symm
598  have hRep : ∀ i, 1 ≤ i → i ≤ len - 1 →
599      0 ≤ (if i = 1 then node else H[i]!).toInt ∧ (if i = 1 then node else H[i]!).toInt ≤ node.toInt := by
600    intro i hi1 hi2
601    split
602    · exact ⟨hp.1, by omega⟩
603    · have hb := hB i hi1 hi2; exact ⟨hb.1, by omega⟩
604  have hRepInj : ∀ i j, 1 ≤ i → i ≤ len - 1 → 1 ≤ j → j ≤ len - 1 →
605      (if i = 1 then node else H[i]!) = (if j = 1 then node else H[j]!) → i = j := by
606    intro i j hi1 hi2 hj1 hj2 heq
607    by_cases hi : i = 1 <;> by_cases hj : j = 1
608    · omega
609    · simp only [hi, hj, ite_true, ite_false] at heq
610      have hb := hB j hj1 hj2
611      rw [← heq] at hb
612      omega
613    · simp only [hi, hj, ite_true, ite_false] at heq
614      have hb := hB i hi1 hi2
615      rw [heq] at hb
616      omega
617    · simp only [hi, hj, ite_false] at heq
618      exact hHi i j hi1 hi2 hj1 hj2 heq
619  have hp' : PermOn (fun i => H'[i]!) (fun i => if i = 1 then node else H[i]!) (len - 1) := by
620    simpa only [hHeap2] using hperm
621  refine ⟨hnext, n, m, hl, hm1, hm2, H, H', hn, hm, hnm, hhl, hh1, hh2, rfl,
622    hsH'.trans (by rw [hHeap2]; exact hsH), ?_, ?_, ?_, ?_, hp'.injective hRepInj, ?_⟩
623  · rw [hframe _ (by omega), hHeap2]
624    exact hkeepn
625  · rw [hframe _ (by omega), hHeap2]
626    exact hkeepm
627  · simpa only [tk_arr_heap] using horder'
628  · intro i hi1 hi2
629    obtain ⟨σ, hr, hi, he⟩ := hp'
630    have hei := he i hi1 hi2
631    dsimp only at hei
632    rw [hei]
633    exact hRep (σ i) (hr i hi1 hi2).1 (hr i hi1 hi2).2
634  · intro F
635    have hc := hcount F
636    have hc' := hcount' F
637    rw [hroot, hHeap2] at hc'
638    omega
639
640
641/-- Queue representation during actual node merging. The stage counts
642completed merges. This records numeric geometry and actual data; it contains
643no assumed execution contract. Tail shape and parent links are separate
644obligations of the tree-layout proof. -/
645structure BTMergeQueue (tk : TK) (N K j : Nat) (node : Int32) (d : DeflateState) : Prop where
646  n3 : 3 ≤ N
647  n286 : N ≤ 286
648  k2 : 2 ≤ K
649  kN : K ≤ N
650  stage : j < K
651  counter : node.toInt = (N + j : Nat)
652  len : d.heap_len.toInt = (K - j : Nat)
653  max : d.heap_max.toInt + 2 * (j : Int) = 573
654  tree : N + K - 1 ≤ (tk.arr d).size
655  depth : N + K - 1 ≤ d.depth.size
656  heap : d.heap.size = 573
657  valid : ∀ i : Nat, 1 ≤ i → (i : Int) ≤ d.heap_len.toInt →
658    0 ≤ d.heap[i]!.toInt ∧ d.heap[i]!.toInt < node.toInt
659  injective : ∀ i i' : Nat, 1 ≤ i → (i : Int) ≤ d.heap_len.toInt →
660    1 ≤ i' → (i' : Int) ≤ d.heap_len.toInt → d.heap[i]! = d.heap[i']! → i = i'
661  order : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) (K - j) 0
662
663/-- Actual sorted leaves establish the initial queue representation.
664Internal-node array capacity is explicit; the old leaf-prefix theorem does
665not claim to supply that additional capacity. -/
666theorem BTMergeQueue.of_leaf {tk : TK} {d : DeflateState} {N : Nat} {mc node : Int32}
667    (hi : BTLeafInv tk N mc d) (h2 : 2 ≤ d.heap_len.toInt) (hm : d.heap_max = HEAP_SIZE)
668    (hn : node.toInt = N)
669    (hT : N + d.heap_len.toInt.toNat - 1 ≤ (tk.arr d).size)
670    (hD : N + d.heap_len.toInt.toNat - 1 ≤ d.depth.size)
671    (ho : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) d.heap_len.toInt.toNat 0) :
672    BTMergeQueue tk N d.heap_len.toInt.toNat 0 node d := by
673  have hc := hi.count
674  have hKN := Math.scanCount_le (btFreq tk d) N
675  refine ⟨hi.n3, hi.n286, by omega, by omega, by omega, by omega, by omega,
676    by rw [hm]; rfl, hT, hD, hi.heap, ?_, hi.injective, ?_⟩
677  · intro i hi1 hi2
678    have hv := hi.valid i hi1 hi2
679    exact ⟨hv.1, by omega⟩
680  · simpa only [Nat.sub_zero] using ho
681
682/-- The checked whole iteration preserves the queue representation and
683advances its stage by one. Every bound for the called fragments is derived
684from this representation. -/
685theorem ws_btMergeBody_queue {h0 : Heap} {id : Nat} {tk : TK} {d : DeflateState}
686    {N K j : Nat} {node : Int32} (hi : BTMergeQueue tk N K j node d) (hmore : j + 1 < K) :
687    WS h0 id (btMergeBody (Sp id) (.ref (tk.ref id) 0) node) d
688      (fun next e => BTMergeQueue tk N K (j + 1) next e) := by
689  have hNs := hi.n3
690  have hNb := hi.n286
691  have hK2 := hi.k2
692  have hKN := hi.kN
693  have hj := hi.stage
694  have hn := hi.counter
695  have hl := hi.len
696  have hm := hi.max
697  have hH := hi.heap
698  have hT := hi.tree
699  have hD := hi.depth
700  have hp : NV (tk.arr d) d.depth node := ⟨by omega, by omega, by omega⟩
701  refine WS.mono (ws_btMergeBody tk d (K - j) node hl (by omega) (by omega)
702    (by omega) (by omega) (by omega) hp (by omega)
703    (fun i hi1 hi2 => hi.valid i hi1 (by omega))
704    (fun i i' hi1 hi2 hi'1 hi'2 => hi.injective i i' hi1 (by omega) hi'1 (by omega)) hi.order) ?_
705  intro next e ⟨hnext, n, m, hlen, hm1, hm2, H, H', hn', hm', hnm, hlen', hm1', hm2', he,
706    hsize, htailn, htailm, horder, hvalid, hinj, hcount⟩
707  subst e
708  have hT' : (tk.arr { btParentState tk { d with heap := H, heap_len := hlen, heap_max := hm2 } n m node with heap := H' }).size = (tk.arr d).size := by
709    rw [tk_arr_heap, btParentState_tree_size]
710    cases tk <;> rfl
711  refine ⟨hNs, hNb, hK2, hKN, hmore, by omega, ?_, ?_, by rw [hT']; exact hT,
712    by simpa only [btParentState_depth_size] using hD, by exact hsize.trans hH, ?_, ?_, ?_⟩
713  · simp only [btParentState_len]
714    omega
715  · simp only [btParentState_max]
716    omega
717  · intro i hi1 hi2
718    simp only [btParentState_len] at hi2
719    have hv := hvalid i hi1 (by omega)
720    change 0 ≤ H'[i]!.toInt ∧ H'[i]!.toInt < next.toInt
721    exact ⟨hv.1, by omega⟩
722  · intro i i' hi1 hi2 hi'1 hi'2 heq
723    simp only [btParentState_len] at hi2 hi'2
724    exact hinj i i' hi1 (by omega) hi'1 (by omega) heq
725  · have heq : K - (j + 1) = K - j - 1 := by omega
726    rwa [heq]
727
728/-- The complete actual merge loop terminates after exactly K-1 iterations.
729Its queue has one valid root and its counter and tail boundary have their
730exact source values. This is queue safety and order, not yet tree-layout or
731code-emission correctness. -/
732theorem ws_btMergeLoop {h0 : Heap} {id : Nat} {tk : TK} {d : DeflateState}
733    {N K : Nat} {node : Int32} (hi : BTMergeQueue tk N K 0 node d) :
734    WS h0 id (btMergeLoop (Sp id) (.ref (tk.ref id) 0) node) d
735      (fun next e => BTMergeQueue tk N K (K - 1) next e ∧ e.heap_len.toInt = 1) := by
736  let Inv : Int32 → DeflateState → Prop := fun node e =>
737    ∃ j : Nat, BTMergeQueue tk N K j node e ∧ j + 1 < K
738  let Q : Int32 → DeflateState → Prop := fun node e =>
739    BTMergeQueue tk N K (K - 1) node e ∧ e.heap_len.toInt = 1
740  unfold btMergeLoop
741  refine WS.cdoWhile2 Inv (fun _ e => e.heap_len.toInt.toNat) Q ?_
742    ⟨0, hi, by have := hi.k2; omega⟩ (by have := hi.len; have := hi.kN; have := hi.n286; dsimp only [fuel]; omega)
743  intro current e ⟨j, hj, hmore⟩
744  refine WS.mono (ws_btMergeBody_queue hj hmore) ?_
745  intro next e' hj'
746  refine WS.bind' ws_rd fun got e'' ⟨hgot, he''⟩ => ?_
747  subst e''; subst got
748  have hlen := hj'.len
749  have hstage := hj'.stage
750  have hK := hj'.k2
751  by_cases hcontinue : e'.heap_len.toInt ≥ 2
752  · have hjnext : j + 1 + 1 < K := by omega
753    refine WS.pure' (Or.inr ⟨by simp only [hcontinue, decide_true], ⟨j + 1, hj', hjnext⟩, ?_⟩)
754    have hlen0 := hj.len
755    omega
756  · have hjend : j + 1 = K - 1 := by omega
757    refine WS.pure' (Or.inl ⟨by simp only [hcontinue, decide_false], ?_⟩)
758    change Q next e'
759    rw [hjend] at hj'
760    exact ⟨hj', by omega⟩
761
762
763/-- Deterministic executions of the same fragment have the same result and
764state. Thus separately proved data properties can be combined. -/
765theorem merge_ws_and {α : Type} {h0 : Heap} {id : Nat} {m : M α} {d : DeflateState}
766    {Q R : α → DeflateState → Prop} (hq : WS h0 id m d Q) (hr : WS h0 id m d R) :
767    WS h0 id m d (fun a e => Q a e ∧ R a e) := by
768  obtain ⟨a, e, he, hQ⟩ := hq
769  obtain ⟨b, f, hf, hR⟩ := hr
770  have hp := Except.ok.inj (he.symm.trans hf)
771  have hab : a = b := congrArg Prod.fst hp
772  have hef : e = f := by
773    have hh := congrArg (fun p => p.2.dstates id) hp
774    simp only [setD_dstates_same] at hh
775    exact Option.some.inj hh
776  subst b; subst f
777  exact ⟨a, e, he, hQ, hR⟩
778
779/-- The final root store executes its checked decrement and keeps every
780other heap cell. Its exact record effect also frames the tree and depth. -/
781theorem ws_btSaveRoot {h0 : Heap} {id : Nat} (d : DeflateState)
782    (hroot : 1 < d.heap.size) (hm1 : 1 ≤ d.heap_max.toInt)
783    (hmH : d.heap_max.toInt ≤ d.heap.size) (hbig : d.heap.size ≤ 573) :
784    WS h0 id (btSaveRoot (Sp id)) d (fun _ e => ∃ hm : Int32,
785      hm.toInt = d.heap_max.toInt - 1 ∧
786      e = { d with heap := d.heap.set! hm.toInt.toNat d.heap[1]!, heap_max := hm } ∧
787      e.heap.size = d.heap.size ∧ e.heap[hm.toInt.toNat]! = d.heap[1]! ∧
788      ∀ i : Nat, i ≠ hm.toInt.toNat → e.heap[i]! = d.heap[i]!) := by
789  unfold btSaveRoot
790  refine WS.bind' (ws_heapAt 1 (by decide +kernel) (by change (1 : Int) < d.heap.size; omega))
791    fun top e1 ⟨htop, he1⟩ => ?_
792  subst e1
793  have hi1 : (1 : Int32).toInt.toNat = 1 := rfl
794  change top = d.heap[(1 : Int32).toInt.toNat]! at htop
795  rw [hi1] at htop
796  subst top
797  refine WS.bind' ws_rd fun got e1 ⟨hgot, he1⟩ => ?_
798  subst e1; subst got
799  refine WS.bind' (ws_isub d.heap_max 1 (by omega) (by omega)) fun hm e1 ⟨hhm, he1⟩ => ?_
800  subst e1
801  refine WS.bind' (ws_md (fun e => { e with heap_max := hm })) fun _ e1 he1 => ?_
802  subst e1
803  refine WS.mono (ws_heapSet hm d.heap[1]! (by omega) (by dsimp only; omega)) ?_
804  intro _ e he
805  subst e
806  have hi : hm.toInt.toNat < d.heap.size := by omega
807  refine ⟨hm, by omega, rfl, size_set! _ _ _, ?_, ?_⟩
808  · rw [getD_set d.heap hm.toInt.toNat _ _ hi, ite_eq_left rfl]
809  · intro i hne
810    rw [getD_set d.heap hm.toInt.toNat i _ hi, ite_eq_right hne]
811
812
813/-- The exact selected-tree array after parent creation. -/
814theorem btParentState_arr (tk : TK) (d : DeflateState) (n m node : Int32) :
815    tk.arr (btParentState tk d n m node) =
816      let T := tk.arr d
817      let T1 := T.set! node.toInt.toNat { T[node.toInt.toNat]! with fc := T[n.toInt.toNat]!.fc + T[m.toInt.toNat]!.fc }
818      let T2 := T1.set! m.toInt.toNat { T1[m.toInt.toNat]! with dl := i2us node }
819      T2.set! n.toInt.toNat { T2[n.toInt.toNat]! with dl := i2us node } := by cases tk <;> rfl
820
821/-- A frequency store preserves every parent-link cell. -/
822theorem merge_setFreq_dad (T : Array CtData) (k i : Nat) (freq : UInt16) (hk : k < T.size) :
823    ((T.set! k { T[k]! with fc := freq })[i]!).dl = T[i]!.dl := by
824  rw [getD_set T k i _ hk]
825  split <;> simp_all
826
827/-- A parent-link store replaces precisely one parent-link value. -/
828theorem merge_setDad_dad (T : Array CtData) (k i : Nat) (dad : UInt16) (hk : k < T.size) :
829    ((T.set! k { T[k]! with dl := dad })[i]!).dl = if i = k then dad else T[i]!.dl := by
830  rw [getD_set T k i _ hk]
831  split <;> rfl
832
833/-- Both selected children receive the new parent index. Every other link
834is unchanged, even if it is the parent node's old link. This states the
835source's 16-bit cast; lossless numeric parent indices follow from bounds. -/
836theorem btParentState_dad (tk : TK) (d : DeflateState) (n m node : Int32)
837    (hn : NV (tk.arr d) d.depth n) (hm : NV (tk.arr d) d.depth m)
838    (hp : NV (tk.arr d) d.depth node) (i : Nat) :
839    (tk.arr (btParentState tk d n m node))[i]!.dl =
840      if i = n.toInt.toNat ∨ i = m.toInt.toNat then i2us node else (tk.arr d)[i]!.dl := by
841  have hnT : n.toInt.toNat < (tk.arr d).size := by have := hn.1; have := hn.2.1; omega
842  have hmT : m.toInt.toNat < (tk.arr d).size := by have := hm.1; have := hm.2.1; omega
843  have hpT : node.toInt.toNat < (tk.arr d).size := by have := hp.1; have := hp.2.1; omega
844  rw [btParentState_arr]
845  dsimp only
846  rw [merge_setDad_dad _ _ _ _ (by simp only [size_set!]; exact hnT),
847    merge_setDad_dad _ _ _ _ (by simp only [size_set!]; exact hmT), merge_setFreq_dad _ _ _ _ hpT]
848  by_cases hin : i = n.toInt.toNat <;> by_cases him : i = m.toInt.toNat <;> simp only [hin, him, ite_true, ite_false, or_self, true_or, false_or, or_true, ite_self]
849
850/-- The queue representation leaves room for the final checked root store.
851This includes the largest admitted alphabet and leaf count. -/
852theorem BTMergeQueue.tail_bounds {tk : TK} {d : DeflateState} {N K j : Nat} {node : Int32}
853    (hi : BTMergeQueue tk N K j node d) : 3 ≤ d.heap_max.toInt ∧ d.heap_max.toInt ≤ 573 := by
854  have := hi.n286
855  have := hi.kN
856  have := hi.stage
857  have := hi.max
858  omega
859
860end Zlib.Trees.Proofs
ZLIB × LEAN

全局目录

当前位置trees.c.build.merge.lean