参考文档 / ZLIB × LEAN
trees.c.heap.pqrun.lean
此页源文件快照 ·
3212fafe40a976e4 · 对应提交的原文 ↗本页保留 Lean 源码及行号。点击行号可定位语句,点击 import 中的模块名可查看依赖。
1import ZlibF.Proof.«trees.c.heap.pq»
2import ZlibF.Proof.«trees.c.heap.ord»
3
4/-!
5# trees.c: `pqdownheap` keeps the heap order
6
7The loop invariant and the hole lemmas (`HoleInv`, `hole_step`, ...) are those of the earlier attempt
8(`Proofs/trees/PqDownHeapOrd.lean`), restated for the record `d` of the new heap model.
9-/
10
11namespace Zlib.Trees.Proofs
12open C Zlib.Trees
13
14theorem sm_eq (T : Array CtData) (D : Array UInt8) :
15 sm T D = smallerB (fun n => (T[n]!).fc) (fun n => D[n]!) := rfl
16
17theorem sm_ok (T : Array CtData) (D : Array UInt8) : KeyOK (sm T D) := by
18 rw [sm_eq]; exact smallerB_ok _ _
19
20/-- The heap array with the pending value `v` in the hole `K`. -/
21def wh (hp : Array Int32) (K : Nat) (v : Int32) : Nat → Int32 := fun i => if i = K then v else hp[i]!
22
23theorem ws_pqdownheap {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (kk : Int32) (k0 len : Nat)
24 (hk : kk.toInt = k0) (hk1 : 1 ≤ k0) (hk2 : k0 ≤ len) (hlen : d.heap_len.toInt = len)
25 (hsz : len < d.heap.size) (hbig : d.heap.size ≤ 1000000)
26 (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
27 (hheap : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len k0) :
28 WS h0 id (pqdownheap (Sp id) (Ptr.ref (tk.ref id) 0) kk) d (fun _ d' =>
29 ∃ hp', d' = { d with heap := hp' } ∧ hp'.size = d.heap.size ∧
30 (∀ i, ¬ (1 ≤ i ∧ i ≤ len) → hp'[i]! = d.heap[i]!) ∧
31 PermOn (fun i => hp'[i]!) (fun i => d.heap[i]!) len ∧
32 HeapOK (sm (tk.arr d) d.depth) (fun i => hp'[i]!) len (k0 - 1)) := by
33 have kOK := sm_ok (tk.arr d) d.depth
34 unfold pqdownheap
35 simp only []
36 refine WS.bind' (ws_heapAt kk (by omega) (by omega)) fun v d1 ⟨hv, hd1⟩ => ?_
37 subst d1
38 refine WS.bind' (ws_shl1 kk (by omega) (by omega)) fun j d1 ⟨hj, hd1⟩ => ?_
39 subst d1
40 have hv' : v = d.heap[k0]! := by rw [hv]; congr 1; omega
41 have hnv : NV (tk.arr d) d.depth v := by rw [hv']; exact hval k0 hk1 hk2
42 let H : Nat → Int32 := fun i => d.heap[i]!
43 let Inv : Int32 × Int32 × Bool → DeflateState → Prop := fun st e => ∃ (K : Nat) (hpc : Array Int32),
44 e = { d with heap := hpc } ∧ hpc.size = d.heap.size ∧ (∀ i, ¬ (1 ≤ i ∧ i ≤ len) → hpc[i]! = d.heap[i]!) ∧
45 st.1.toInt = K ∧ k0 ≤ K ∧ K ≤ len ∧ (st.2.2 = false → st.2.1.toInt = 2 * K) ∧
46 PermOn (wh hpc K v) H len ∧ HoleInv (sm (tk.arr d) d.depth) (wh hpc K v) len k0 K ∧
47 (st.2.2 = true → ∃ j', MinChild (sm (tk.arr d) d.depth) (wh hpc K v) len K j' ∧
48 sm (tk.arr d) d.depth (wh hpc K v K) (wh hpc K v j') = true)
49 let Q : Int32 × Int32 × Bool → DeflateState → Prop := fun st e => ∃ (K : Nat) (hpc : Array Int32),
50 e = { d with heap := hpc } ∧ hpc.size = d.heap.size ∧ (∀ i, ¬ (1 ≤ i ∧ i ≤ len) → hpc[i]! = d.heap[i]!) ∧
51 st.1.toInt = K ∧ k0 ≤ K ∧ K ≤ len ∧ PermOn (wh hpc K v) H len ∧
52 HeapOK (sm (tk.arr d) d.depth) (wh hpc K v) len (k0 - 1)
53 let μ : Int32 × Int32 × Bool → DeflateState → Nat := fun st _ => if st.2.2 then 0 else 4000000 - st.2.1.toInt.toNat
54 have hf : ∀ st e, μ st e < fuel := fun st e => by
55 unfold μ; split <;> simp only [fuel] <;> omega
56 have hwh0 : wh d.heap k0 v = H := by
57 funext i; simp only [wh, H]; split <;> simp_all
58 have hI0 : Inv (kk, j, false) d :=
59 ⟨k0, d.heap, rfl, rfl, fun _ _ => rfl, hk, Nat.le_refl _, hk2, fun _ => by simp only; omega,
60 by rw [hwh0]; exact PermOn.refl _ _, by rw [hwh0]; exact hole_init hheap, fun e => by simp at e⟩
61 refine WS.bind' (Q := Q) (WS.cwhile2 (id := id) Inv μ Q ?_ hI0 (hf _ d)) ?_
62 · -- one step
63 rintro ⟨kk', jj, bb⟩ e ⟨K, hpc, he, hsz', hfr, hK, hK1, hK2, hj', hp, hhole, hbrk⟩
64 subst he
65 simp only at hK hj' hbrk
66 have hvalA : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth (wh hpc K v i) := by
67 obtain ⟨σ, hr, -, hee⟩ := hp
68 intro i h1 h2
69 have := hee i h1 h2
70 have h3 : wh hpc K v i = d.heap[σ i]! := this
71 rw [h3]; exact hval _ (hr i h1 h2).1 (hr i h1 h2).2
72 cases bb with
73 | true =>
74 refine WS.pure' (Or.inl ⟨rfl, ?_⟩)
75 obtain ⟨j', hm, hkey⟩ := hbrk rfl
76 exact ⟨K, hpc, rfl, hsz', hfr, hK, hK1, hK2, hp, hole_break kOK ⟨hk1, hK1⟩ hhole hm hkey⟩
77 | false =>
78 have hj'' : jj.toInt = 2 * K := hj' rfl
79 refine WS.bind' ws_rd fun l e1 ⟨hl, he1⟩ => ?_
80 subst e1; subst hl
81 by_cases hleaf : 2 * K ≤ len
82 · -- the body runs
83 refine WS.pure' (Or.inr ⟨?_, ?_⟩)
84 · simp only [decide_eq_true_eq]
85 show jj.toInt ≤ d.heap_len.toInt
86 omega
87 refine WS.bind' ws_rd fun l e1 ⟨hl, he1⟩ => ?_
88 subst e1; subst hl
89 dsimp only
90 have hK573 : K < hpc.size := by omega
91 have hvK : NV (tk.arr d) d.depth v := hnv
92 -- the common tail, for the chosen child `j1 = J`
93 have tail : ∀ (j1 : Int32) (J : Nat), j1.toInt = J → MinChild (sm (tk.arr d) d.depth) (wh hpc K v) len K J →
94 WS h0 id (do
95 let hj ← heapAt (Sp id) j1
96 let dp ← pDepth (Sp id)
97 let b ← smaller (Ptr.ref (tk.ref id) 0) v hj dp
98 if b = true then pure (kk', j1, true) else do
99 heapSet (Sp id) kk' hj
100 let j2 ← shl1 j1
101 pure (j1, j2, false)) { d with heap := hpc }
102 (fun st e2 => Inv st e2 ∧ μ st e2 < μ (kk', jj, false) { d with heap := hpc }) := by
103 intro j1 J hJ hm
104 have hJK : J ≠ K := by have := hm.1; omega
105 have hJ1 : 1 ≤ J ∧ J ≤ len := ⟨by have := hm.2.1; omega, hm.2.2.1⟩
106 have hK1' : 1 ≤ K := by omega
107 have hJsz : J < hpc.size := by omega
108 have hJv : (wh hpc K v J) = hpc[J]! := by simp [wh, hJK]
109 have hnJ : NV (tk.arr d) d.depth hpc[J]! := by rw [← hJv]; exact hvalA J hJ1.1 hJ1.2
110 have hjtn : j1.toInt.toNat = J := by omega
111 have hnJ' : NV (tk.arr { d with heap := hpc }) ({ d with heap := hpc }).depth
112 (({ d with heap := hpc }).heap[j1.toInt.toNat]!) := by
113 rw [tk_arr_heap]; show NV (tk.arr d) d.depth hpc[j1.toInt.toNat]!; rw [hjtn]; exact hnJ
114 have hnv' : NV (tk.arr { d with heap := hpc }) ({ d with heap := hpc }).depth v := by
115 rw [tk_arr_heap]; exact hnv
116 refine WS.mono (ws_pq_cont (h0 := h0) (id := id) tk kk' j1 v { d with heap := hpc }
117 (by show 1 ≤ kk'.toInt; omega) (by show kk'.toInt < hpc.size; omega)
118 (by show 1 ≤ j1.toInt; omega) (by show j1.toInt < hpc.size; omega) (by omega) hnJ' hnv') ?_
119 intro st e2 hq
120 rcases hq with ⟨hsm, hst, he2⟩ | ⟨hsm, hst1, hst2, hst3, he2⟩
121 · subst hst; subst he2
122 simp only [hjtn] at hsm
123 refine ⟨⟨K, hpc, rfl, hsz', hfr, hK, hK1, hK2, fun e => by simp at e, hp, hhole,
124 fun _ => ⟨J, hm, ?_⟩⟩, ?_⟩
125 · simpa [wh, hJK] using hsm
126 · simp only [μ, ite_true, Bool.false_eq_true, ite_false, Int32.toNatClampNeg]; omega
127 · have hkK : kk'.toInt.toNat = K := by omega
128 simp only [hjtn, hkK] at he2
129 subst he2
130 simp only [hjtn] at hsm
131 have hsw : wh (hpc.set! K hpc[J]!) J v = swapAt (wh hpc K v) K J := by
132 funext i
133 simp only [wh, swapAt, getD_set hpc K i _ hK573]
134 by_cases e1 : i = J
135 · subst e1; simp [hJK]
136 · by_cases e2 : i = K
137 · subst e2; simp [e1]; intro h; omega
138 · simp [e1, e2]
139 have hkey : sm (tk.arr d) d.depth (wh hpc K v K) (wh hpc K v J) = false := by
140 simpa [wh, hJK] using hsm
141 refine ⟨⟨J, hpc.set! K hpc[J]!, rfl, by rw [size_set!]; exact hsz', ?_, by rw [hst1]; exact hJ, by have := hm.1; omega, hJ1.2,
142 fun _ => by omega, ?_, ?_, fun e => by rw [hst3] at e; simp at e⟩, ?_⟩
143 · intro i hi
144 rw [getD_set hpc K i _ hK573, ite_eq_right (by omega)]; exact hfr i hi
145 · rw [hsw]; exact hp.swap ⟨hK1', hK2⟩ hJ1
146 · rw [hsw]
147 exact hole_step kOK ⟨hk1, hK1⟩ hhole hm hkey
148 · simp only [μ, hst3, ite_true, Bool.false_eq_true, ite_false, Int32.toNatClampNeg]
149 have := hm.1
150 have h1 : st.2.1.toInt = 2 * (J : Int) := by omega
151 omega
152 have hNVe : ∀ x, NV (tk.arr d) d.depth x →
153 NV (tk.arr { d with heap := hpc }) ({ d with heap := hpc }).depth x :=
154 fun x hx => by rw [tk_arr_heap]; exact hx
155 have hAe : ∀ i, i ≠ K → wh hpc K v i = hpc[i]! := fun i hi => by simp [wh, hi]
156 have h1i : (1 : Int32).toInt = 1 := rfl
157 have refl : ∀ x, sm (tk.arr d) d.depth x x = true := fun x => (kOK.total x x).elim (fun h => h) (fun h => h)
158 by_cases h2 : 2 * K < len
159 · have hlt : jj.toInt < d.heap_len.toInt := by omega
160 refine WS.ite' (fun _ => ?_) (fun hn => absurd hlt hn)
161 refine WS.bind' (ws_iadd jj 1 (by rw [h1i]; omega) (by rw [h1i]; omega)) fun j1 e1 ⟨hj1, he1⟩ => ?_
162 subst e1
163 have hi1 : j1.toInt.toNat = 2 * K + 1 := by rw [h1i] at hj1; omega
164 have hi0 : jj.toInt.toNat = 2 * K := by omega
165 refine WS.bind' (ws_heapAt j1 (by rw [h1i] at hj1; omega) (by show j1.toInt < (hpc.size : Int); rw [h1i] at hj1; omega))
166 fun a e1 ⟨ha, he1⟩ => ?_
167 subst e1
168 refine WS.bind' (ws_heapAt jj (by omega) (by show jj.toInt < (hpc.size : Int); omega)) fun b e1 ⟨hb, he1⟩ => ?_
169 subst e1
170 refine WS.bind' ws_pDepth fun dp e1 ⟨hdp, he1⟩ => ?_
171 subst e1; subst hdp
172 have hv1 : NV (tk.arr d) d.depth hpc[2 * K + 1]! := by
173 rw [← hAe _ (by omega)]; exact hvalA _ (by omega) (by omega)
174 have hv0 : NV (tk.arr d) d.depth hpc[2 * K]! := by
175 rw [← hAe _ (by omega)]; exact hvalA _ (by omega) (by omega)
176 have ha' : a = hpc[2 * K + 1]! := by rw [ha]; show hpc[j1.toInt.toNat]! = _; rw [hi1]
177 have hb' : b = hpc[2 * K]! := by rw [hb]; show hpc[jj.toInt.toNat]! = _; rw [hi0]
178 subst ha'; subst hb'
179 refine WS.bind' (ws_smaller tk _ _ (hNVe _ hv1) (hNVe _ hv0)) fun s1 e1 ⟨hs1, he1⟩ => ?_
180 subst e1
181 by_cases hs : sm (tk.arr d) d.depth hpc[2 * K + 1]! hpc[2 * K]! = true
182 · have hs1' : s1 = true := by rw [hs1]; simpa using hs
183 subst hs1'
184 simp only [ite_true]
185 refine WS.bind' (ws_iadd jj 1 (by rw [h1i]; omega) (by rw [h1i]; omega)) fun j1' e1 ⟨hj1', he1⟩ => ?_
186 subst e1
187 refine tail j1' (2 * K + 1) (by rw [h1i] at hj1'; omega) ⟨by omega, by omega, by omega, ?_⟩
188 intro c hc h2c hlc
189 have : c = 2 * K ∨ c = 2 * K + 1 := by omega
190 rcases this with rfl | rfl
191 · rw [hAe _ (by omega), hAe _ (by omega)]; exact hs
192 · exact refl _
193 · have hs1' : s1 = false := by rw [hs1]; simpa using hs
194 subst hs1'
195 simp only [Bool.false_eq_true, ite_false]
196 refine tail jj (2 * K) (by omega) ⟨by omega, by omega, by omega, ?_⟩
197 intro c hc h2c hlc
198 have : c = 2 * K ∨ c = 2 * K + 1 := by omega
199 rcases this with rfl | rfl
200 · exact refl _
201 · rcases kOK.total (wh hpc K v (2 * K)) (wh hpc K v (2 * K + 1)) with e | e
202 · exact e
203 · rw [hAe _ (by omega), hAe _ (by omega)] at e; exact absurd e hs
204 · have hnlt : ¬ jj.toInt < d.heap_len.toInt := by omega
205 refine WS.ite' (fun hn => absurd hn hnlt) (fun _ => ?_)
206 refine tail jj (2 * K) (by omega) ⟨by omega, by omega, by omega, ?_⟩
207 intro c hc h2c hlc
208 have : c = 2 * K := by omega
209 subst this
210 exact refl _
211 · refine WS.pure' (Or.inl ⟨?_, ?_⟩)
212 · simp only [decide_eq_false_iff_not]
213 show ¬ (jj.toInt ≤ d.heap_len.toInt)
214 omega
215 · exact ⟨K, hpc, rfl, hsz', hfr, hK, hK1, hK2, hp, hole_leaf ⟨hk1, hK1⟩ hhole (by omega)⟩
216 · rintro ⟨kk', jj, bb⟩ e ⟨K, hpc, he, hsz', hfr, hK, hK1, hK2, hp, hok⟩
217 subst he
218 simp only at hK
219 have hKs : K < hpc.size := by omega
220 refine WS.mono (ws_heapSet kk' v (by omega) (by show kk'.toInt < (hpc.size : Int); omega)) ?_
221 intro _ e2 he2
222 have hkn : kk'.toInt.toNat = K := by omega
223 simp only [hkn] at he2
224 subst he2
225 have hw : (fun i => (hpc.set! K v)[i]!) = wh hpc K v := by
226 funext i; simp only [wh, getD_set hpc K i v hKs]
227 refine ⟨hpc.set! K v, rfl, by rw [size_set!]; exact hsz', ?_, by rw [hw]; exact hp, by rw [hw]; exact hok⟩
228 intro i hi
229 rw [getD_set hpc K i v hKs, ite_eq_right (by omega)]; exact hfr i hi
230
231@[simp] theorem tk_arr_heap_len (tk : TK) (d : DeflateState) (a : Int32) : tk.arr { d with heap_len := a } = tk.arr d := by
232 cases tk <;> rfl
233
234/-- `pqremove`: the smallest node is returned and the heap, one shorter, has its order again. `Hm H len` is the heap
235with its last entry moved to the top, which `pqdownheap` then repairs. -/
236def Hm (H : Nat → Int32) (len : Nat) : Nat → Int32 := fun i => if i = 1 then H len else H i
237
238theorem ws_pqremove {h0 : Heap} {id : Nat} (tk : TK) (d : DeflateState) (len : Nat)
239 (hlen : d.heap_len.toInt = len) (h2 : 2 ≤ len) (hsz : len < d.heap.size) (hbig : d.heap.size ≤ 1000000)
240 (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
241 (hheap : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len 0) :
242 WS h0 id (pqremove (Sp id) (Ptr.ref (tk.ref id) 0)) d (fun top d' =>
243 top = d.heap[1]! ∧ ∃ (hl' : Int32) (hp' : Array Int32), hl'.toInt = (len : Int) - 1 ∧
244 d' = { d with heap := hp', heap_len := hl' } ∧ hp'.size = d.heap.size ∧
245 (∀ i, ¬ (1 ≤ i ∧ i ≤ len - 1) → hp'[i]! = d.heap[i]!) ∧
246 PermOn (fun i => hp'[i]!) (Hm (fun i => d.heap[i]!) len) (len - 1) ∧
247 HeapOK (sm (tk.arr d) d.depth) (fun i => hp'[i]!) (len - 1) 0) := by
248 have kOK := sm_ok (tk.arr d) d.depth
249 unfold pqremove
250 refine WS.bind' (ws_heapAt 1 (by decide) (by show (1 : Int) < d.heap.size; omega)) fun top d1 ⟨htop, hd1⟩ => ?_
251 subst d1
252 refine WS.bind' ws_rd fun l d1 ⟨hl, hd1⟩ => ?_
253 subst d1; subst l
254 refine WS.bind' (ws_heapAt d.heap_len (by omega) (by omega)) fun v d1 ⟨hv, hd1⟩ => ?_
255 subst d1
256 refine WS.bind' (ws_isub d.heap_len 1 (by have : (1 : Int32).toInt = 1 := rfl; omega)
257 (by have : (1 : Int32).toInt = 1 := rfl; omega)) fun hl' d1 ⟨hhl', hd1⟩ => ?_
258 subst d1
259 have h1i : (1 : Int32).toInt = 1 := rfl
260 refine WS.bind' (ws_md (fun e => { e with heap_len := hl' })) fun _ d1 hd1 => ?_
261 subst hd1
262 refine WS.bind' (ws_heapSet 1 v (by decide) (by show (1 : Int) < d.heap.size; omega)) fun _ d1 hd1 => ?_
263 subst hd1
264 have hvi : v = d.heap[len]! := by rw [hv]; congr 1; omega
265 have hhl' : hl'.toInt = (len : Int) - 1 := by omega
266 have hnode : ∀ i, 1 ≤ i → i ≤ len - 1 → NV (tk.arr d) d.depth
267 ({ ({ d with heap_len := hl' } : DeflateState) with heap := d.heap.set! (1 : Int32).toInt.toNat v }).heap[i]! := by
268 intro i h1 h3
269 show NV (tk.arr d) d.depth (d.heap.set! (1 : Int32).toInt.toNat v)[i]!
270 rw [getD_set _ _ _ _ (by rw [h1i]; show 1 < d.heap.size; omega)]
271 split
272 · rw [hvi]; exact hval len (by omega) (Nat.le_refl _)
273 · exact hval i h1 (by omega)
274 have e1n : (1 : Int32).toInt.toNat = 1 := rfl
275 have hheap2 : HeapOK (sm (tk.arr d) d.depth) (fun i => (d.heap.set! 1 v)[i]!) (len - 1) 1 := by
276 intro c h2c hlc hc
277 have hs1 : 1 < d.heap.size := by omega
278 simp only [getD_set d.heap 1 _ v hs1]
279 rw [ite_eq_right (by omega), ite_eq_right (by omega)]
280 exact hheap c h2c (by omega) (by omega)
281 have key := ws_pqdownheap (h0 := h0) (id := id) tk
282 { ({ d with heap_len := hl' } : DeflateState) with heap := d.heap.set! (1 : Int32).toInt.toNat v } 1 1 (len - 1)
283 (by rw [h1i]; rfl) (Nat.le_refl _) (by omega) (by show hl'.toInt = _; omega)
284 (by show len - 1 < (d.heap.set! _ v).size; rw [size_set!]; omega)
285 (by show (d.heap.set! _ v).size ≤ _; rw [size_set!]; omega)
286 (fun i h1 h3 => by rw [tk_arr_heap, tk_arr_heap_len]; exact hnode i h1 h3)
287 (by rw [tk_arr_heap, tk_arr_heap_len, e1n]; exact hheap2)
288 refine WS.bind' key fun _ d1 ⟨hp', hd1, hsz', hfr, hperm, hok⟩ => ?_
289 subst hd1
290 refine WS.pure' ⟨?_, hl', hp', ?_, rfl, ?_, ?_, ?_, ?_⟩
291 · rw [htop, e1n]
292 · omega
293 · simpa using hsz'
294 · intro i hi
295 have := hfr i hi
296 simp only [e1n, getD_set d.heap 1 i v (by omega : 1 < d.heap.size)] at this
297 rw [this, ite_eq_right (by omega)]
298 · have hw : (fun i => (d.heap.set! 1 v)[i]!) = Hm (fun i => d.heap[i]!) len := by
299 funext i; simp only [Hm]; rw [getD_set d.heap 1 i v (by omega : 1 < d.heap.size), hvi]
300 have hperm' : PermOn (fun i => hp'[i]!) (fun i => (d.heap.set! 1 v)[i]!) (len - 1) := hperm
301 rw [hw] at hperm'; exact hperm'
302 · rw [tk_arr_heap, tk_arr_heap_len] at hok; exact hok
303
304/-! ### Heap-level statements -/
305
306/-- **`pqdownheap`, correct and safe.** Called on the heap `heap[1 .. len]`, `len = heap_len`, with the hole at
307`k0 ∈ [1, len]`. Precondition: `len` is the current `heap_len`, the heap array has more than `len` entries (the C
308array has `HEAP_SIZE = 573`), the nodes `heap[1..len]` index `tree` and `depth` (in `build_tree` they are below
309`2 * elems + 1 ≤ 573`), and the heap order holds for every parent `> k0` (`build_tree` calls it for `k0 = heap_len/2`
310down to 1, and for `k0 = 1` after replacing the root). Result: no fault; only `heap[1..len]` changes; the new
311heap is a permutation of the old one and the order holds for every parent `> k0 - 1`. `tk` says which tree array
312`tree` points to (`dyn_ltree`, `dyn_dtree` or `bl_tree` of the same state). -/
313theorem pqdownheap_correct {h : Heap} {id : Nat} {d : DeflateState} (hd : h.dstates id = some d) (tk : TK)
314 (kk : Int32) (k0 len : Nat) (hk : kk.toInt = k0) (hk1 : 1 ≤ k0) (hk2 : k0 ≤ len) (hlen : d.heap_len.toInt = len)
315 (hsz : len < d.heap.size) (hbig : d.heap.size ≤ 1000000)
316 (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
317 (hheap : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len k0) :
318 ∃ hp', pqdownheap (Sp id) (Ptr.ref (tk.ref id) 0) kk h = .ok ((), setD h id { d with heap := hp' }) ∧
319 hp'.size = d.heap.size ∧ (∀ i, ¬ (1 ≤ i ∧ i ≤ len) → hp'[i]! = d.heap[i]!) ∧
320 PermOn (fun i => hp'[i]!) (fun i => d.heap[i]!) len ∧
321 HeapOK (sm (tk.arr d) d.depth) (fun i => hp'[i]!) len (k0 - 1) := by
322 have := ws_pqdownheap (h0 := h) (id := id) tk d kk k0 len hk hk1 hk2 hlen hsz hbig hval hheap
323 obtain ⟨_, d', e, hp', rfl, hr⟩ := this
324 rw [setD_self hd] at e
325 exact ⟨hp', e, hr⟩
326
327/-- **`pqdownheap` does not fault**: the preconditions of `pqdownheap_correct` (hole `k0 ∈ [1, heap_len]`, nodes of
328`heap[1..heap_len]` inside `tree` and `depth`, heap order for parents `> k0`) give a run to the end; every index is
329inside the arrays. -/
330theorem pqdownheap_safe {h : Heap} {id : Nat} {d : DeflateState} (hd : h.dstates id = some d) (tk : TK)
331 (kk : Int32) (k0 len : Nat) (hk : kk.toInt = k0) (hk1 : 1 ≤ k0) (hk2 : k0 ≤ len) (hlen : d.heap_len.toInt = len)
332 (hsz : len < d.heap.size) (hbig : d.heap.size ≤ 1000000)
333 (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
334 (hheap : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len k0) :
335 ∃ h', pqdownheap (Sp id) (Ptr.ref (tk.ref id) 0) kk h = .ok ((), h') := by
336 obtain ⟨hp', e, -⟩ := pqdownheap_correct hd tk kk k0 len hk hk1 hk2 hlen hsz hbig hval hheap
337 exact ⟨_, e⟩
338
339/-- **`pqremove`, correct and safe.** Called with `heap_len = len ≥ 2` (the loop of `build_tree` runs while
340`heap_len ≥ 2`), the heap order holding everywhere. It returns `heap[1]`, the smallest node, sets `heap_len` to
341`len - 1`, and leaves `heap[1 .. len-1]` a heap, a permutation of the old `heap[2..len]`. -/
342theorem pqremove_correct {h : Heap} {id : Nat} {d : DeflateState} (hd : h.dstates id = some d) (tk : TK) (len : Nat)
343 (hlen : d.heap_len.toInt = len) (h2 : 2 ≤ len) (hsz : len < d.heap.size) (hbig : d.heap.size ≤ 1000000)
344 (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
345 (hheap : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len 0) :
346 ∃ (hl' : Int32) (hp' : Array Int32), hl'.toInt = (len : Int) - 1 ∧
347 pqremove (Sp id) (Ptr.ref (tk.ref id) 0) h = .ok (d.heap[1]!, setD h id { d with heap := hp', heap_len := hl' }) ∧
348 hp'.size = d.heap.size ∧ (∀ i, ¬ (1 ≤ i ∧ i ≤ len - 1) → hp'[i]! = d.heap[i]!) ∧
349 PermOn (fun i => hp'[i]!) (Hm (fun i => d.heap[i]!) len) (len - 1) ∧
350 HeapOK (sm (tk.arr d) d.depth) (fun i => hp'[i]!) (len - 1) 0 := by
351 have := ws_pqremove (h0 := h) (id := id) tk d len hlen h2 hsz hbig hval hheap
352 obtain ⟨top, d', e, htop, hl', hp', hh, rfl, hr⟩ := this
353 rw [setD_self hd] at e
354 subst htop
355 exact ⟨hl', hp', hh, e, hr⟩
356
357/-- **`pqremove` does not fault**: `heap_len ≥ 2`, the nodes of `heap[1..heap_len]` inside `tree` and `depth`, the
358heap order everywhere (see `pqremove_correct`). -/
359theorem pqremove_safe {h : Heap} {id : Nat} {d : DeflateState} (hd : h.dstates id = some d) (tk : TK) (len : Nat)
360 (hlen : d.heap_len.toInt = len) (h2 : 2 ≤ len) (hsz : len < d.heap.size) (hbig : d.heap.size ≤ 1000000)
361 (hval : ∀ i, 1 ≤ i → i ≤ len → NV (tk.arr d) d.depth d.heap[i]!)
362 (hheap : HeapOK (sm (tk.arr d) d.depth) (fun i => d.heap[i]!) len 0) :
363 ∃ (top : Int32) (h' : Heap), pqremove (Sp id) (Ptr.ref (tk.ref id) 0) h = .ok (top, h') := by
364 obtain ⟨_, _, _, e, -⟩ := pqremove_correct hd tk len hlen h2 hsz hbig hval hheap
365 exact ⟨_, _, e⟩
366
367end Zlib.Trees.Proofs