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

trees.c.build.complete.lean

此页源文件快照 · 8d37978b235be1a5 · 对应提交的原文 ↗

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

1import ZlibF.Proof.«trees.c.build.tail»
2import ZlibF.Proof.«trees.c.build.forest»
3
4/-! # trees.c: deriving the code-generation context from actual tree building -/
5
6namespace Zlib.Trees.Proofs
7open C Zlib.Trees
8
9/-- Readable static descriptor data for tree construction. These are storage
10and table-value facts for all symbols in the alphabet. No execution or
11called-function specification is a field of this representation. -/
12structure BTBuildStatic (h0 : Heap) (id : Nat) (sd : StaticTreeDesc)
13    (xb : Nat → Nat) (slOpt : Option (Nat → Nat)) : Prop where
14  base_nonneg : 0 ≤ sd.extra_base.toInt
15  length_pos : 1 ≤ sd.max_length.toInt
16  length_limit : sd.max_length.toInt ≤ 15
17  length_capacity : sd.elems.toInt.toNat ≤ 2 ^ sd.max_length.toInt.toNat
18  extra : ∀ n < sd.elems.toInt.toNat,
19    (sd.extra_base.toInt.toNat ≤ n → ∃ (r : IRef) (ex : Array Int32), sd.extra_bits = .ref r 0 ∧
20      (∀ e, Space.get (setD h0 id e) r = some ex) ∧ n - sd.extra_base.toInt.toNat < ex.size ∧
21      0 ≤ ex[n - sd.extra_base.toInt.toNat]!.toInt ∧ ex[n - sd.extra_base.toInt.toNat]!.toInt ≤ 1000 ∧
22      xb n = ex[n - sd.extra_base.toInt.toNat]!.toInt.toNat) ∧
23    (n < sd.extra_base.toInt.toNat → xb n = 0)
24  static : (sd.static_tree = .null ∧ slOpt = none) ∨
25    ∃ (r : CtDataRef) (st : Array CtData) (sl : Nat → Nat), sd.static_tree = .ref r 0 ∧ slOpt = some sl ∧
26      (∀ e, Space.get (setD h0 id e) r = some st) ∧
27      ∀ n < sd.elems.toInt.toNat, n < st.size ∧ st[n]!.dl.toNat ≤ 15 ∧ sl n = st[n]!.dl.toNat
28
29/-- The static table facts also supply the representation used by the actual
30two-leaf repair. Its source reads 16-bit lengths without changing the table. -/
31theorem BTBuildStatic.repair {h0 : Heap} {id : Nat} {sd : StaticTreeDesc}
32    {xb : Nat → Nat} {slOpt : Option (Nat → Nat)} (hs : BTBuildStatic h0 id sd xb slOpt) :
33    ∃ sl : Option (Nat → UInt16), BTStatic h0 id sd.static_tree sd.elems.toInt.toNat sl := by
34  rcases hs.static with ⟨ht, hsl⟩ | ⟨r, st, sl, ht, hsl, hr, hvals⟩
35  · exact ⟨none, Or.inl ⟨ht, rfl⟩⟩
36  · exact ⟨some (fun n => st[n]!.dl), Or.inr ⟨r, st, (fun n => st[n]!.dl), ht, rfl, hr,
37      fun n hn => ⟨(hvals n hn).1, rfl⟩⟩⟩
38
39/-- The precise bit-length context is derived from the built tree layout and
40static table data. All dynamic shape, parent and maximum-symbol facts come
41from actual tree building. -/
42theorem BTBuilt.bitlen_ctx {h0 : Heap} {id : Nat} {tk : TK} {d0 d : DeflateState}
43    {N K : Nat} {mc : Int32} {sd : StaticTreeDesc} {xb : Nat → Nat} {slOpt : Option (Nat → Nat)}
44    (hi : BTBuilt tk N K mc d0 d) (hs : BTBuildStatic h0 id sd xb slOpt)
45    (hN : sd.elems.toInt.toNat = N) (hB : d.bl_count.size = 16) (hT : (tk.arr d).size ≤ 600) :
46    P1Ctx h0 id tk d sd.static_tree sd.extra_bits mc sd.extra_base sd.max_length
47      (574 - 2 * K) (K - 1) N mc.toInt.toNat sd.max_length.toInt.toNat sd.extra_base.toInt.toNat xb slOpt := by
48  have hL1 := hs.length_pos
49  have hL15 := hs.length_limit
50  have hb := hs.base_nonneg
51  have hmc := hi.shape.maxc_lt
52  have hK2 := hi.k2
53  refine ⟨hi.heap, hB, hi.nonneg, hi.shape, by have := hi.capacity; omega, hT,
54    by have := hi.max_nonneg; omega, by omega, by omega, by omega, by omega, ?_, ?_, ?_⟩
55  · intro i hiB
56    exact hi.parent (574 - 2 * K + 1 + i) (by omega) (by have := hi.shape.hm_eq; omega)
57  · intro n hn
58    exact hs.extra n (by omega)
59  · rcases hs.static with hnull | ⟨r, st, sl, ht, hsl, hr, hv⟩
60    · exact Or.inl hnull
61    · exact Or.inr ⟨r, st, sl, ht, hsl, hr, fun n hn => hv n (by omega)⟩
62
63/-- The scan preserves the bit-count array in addition to its recorded sizes. -/
64theorem BTScanInv.bl_count {tk : TK} {d e : DeflateState} {N : Nat} {mc : Int32}
65    (hi : BTScanInv tk d N mc e) : e.bl_count = d.bl_count := by
66  obtain ⟨T, H, D, hl, rfl, rest⟩ := hi
67  cases tk <;> rfl
68
69/-- Every actual repair update preserves the bit-count array. -/
70theorem BTForceTrace.bl_count {tk : TK} {sl : Option (Nat → UInt16)}
71    {k : Nat} {mc0 mc : Int32} {d0 d : DeflateState} (hi : BTForceTrace tk sl k mc0 d0 mc d) :
72    d.bl_count = d0.bl_count := by
73  obtain ⟨T, H, D, hl, O, S, rfl⟩ := hi.frame
74  cases tk <;> rfl
75
76/-- The complete actual leaf preparation and heapify retain the bit-count
77array. This supplements the checked prefix with a separate frame property. -/
78theorem ws_btSortedStart_bl_count {h0 : Heap} {id : Nat} {tk dk : TK} {d : DeflateState}
79    {sref : StaticTreeDescRef} {dd : TreeDesc} {sd : StaticTreeDesc} {sl : Option (Nat → UInt16)}
80    (hdd : (dk.descRef id).get (setD h0 id d) = some dd)
81    (hsd : StaticTreeDescRef.get h0 sref = some sd)
82    (hstat : dd.stat_desc = some sref) (htree : dd.dyn_tree = .ref (tk.ref id) 0)
83    (he3 : 3 ≤ sd.elems.toInt) (he286 : sd.elems.toInt ≤ 286)
84    (hT : sd.elems.toInt ≤ (tk.arr d).size) (hD : sd.elems.toInt ≤ d.depth.size)
85    (hH : d.heap.size = 573) (hs : BTStatic h0 id sd.static_tree sd.elems.toInt.toNat sl) :
86    WS h0 id (btSortedStart (Sp id) (some (dk.descRef id))) d (fun _ e => e.bl_count = d.bl_count) := by
87  unfold btSortedStart
88  refine WS.bind' (ws_btLeavesStart hdd hsd hstat htree he3 he286 hT hD hH hs)
89    fun a mid ⟨ht, hst, he, hleaf, scan, scanMc, k, hscan, hlen, hk, hkexact, htrace⟩ => ?_
90  rcases a with ⟨tree, stree, elems, mc⟩
91  dsimp only at ht hst he hleaf htrace ⊢
92  subst tree; subst stree; subst elems
93  have hB : mid.bl_count = d.bl_count := htrace.bl_count.trans hscan.bl_count
94  refine WS.bind' (ws_btOrder_leaf tk dk mid sd.elems.toInt.toNat mc hleaf)
95    fun _ e ⟨hleaf', H, he, hsH, hf, hp, ho, hdesc', hmin⟩ => ?_
96  subst e
97  refine WS.pure' ?_
98  cases dk <;> exact hB
99
100/-- A descriptor field read is its record projection on this heap. -/
101theorem bt_desc_get (dk : TK) (h0 : Heap) (id : Nat) (d : DeflateState) :
102    (dk.descRef id).get (setD h0 id d) = some (dk.getDesc d) := by
103  cases dk <;> simp [TK.descRef, TK.getDesc, TreeDescRef.get, setD]
104
105/-- Complete actual heap construction establishes the retained tree layout
106and keeps the descriptor maximum and count-array storage. All dynamic
107representation premises for merging come from actual leaf preparation. -/
108theorem ws_btHeap_built {h0 : Heap} {id : Nat} {tk dk : TK} {d : DeflateState}
109    {sref : StaticTreeDescRef} {dd : TreeDesc} {sd : StaticTreeDesc} {sl : Option (Nat → UInt16)}
110    (hdd : (dk.descRef id).get (setD h0 id d) = some dd)
111    (hsd : StaticTreeDescRef.get h0 sref = some sd)
112    (hstat : dd.stat_desc = some sref) (htree : dd.dyn_tree = .ref (tk.ref id) 0)
113    (he3 : 3 ≤ sd.elems.toInt) (he286 : sd.elems.toInt ≤ 286)
114    (hT : 2 * sd.elems.toInt.toNat - 1 ≤ (tk.arr d).size) (hTbig : (tk.arr d).size ≤ 600)
115    (hD : 2 * sd.elems.toInt.toNat - 1 ≤ d.depth.size)
116    (hH : d.heap.size = 573) (hB : d.bl_count.size = 16)
117    (hs : BTStatic h0 id sd.static_tree sd.elems.toInt.toNat sl) :
118    WS h0 id (btHeap (Sp id) (some (dk.descRef id))) d (fun a e =>
119      a.1 = .ref (tk.ref id) 0 ∧ ∃ (prepared : DeflateState) (K : Nat),
120        BTBuilt tk sd.elems.toInt.toNat K a.2 prepared e ∧
121        (dk.descRef id).get (setD h0 id e) = some { dd with max_code := a.2 } ∧
122        e.bl_count.size = 16 ∧ (tk.arr e).size ≤ 600) := by
123  have hT0 : sd.elems.toInt ≤ (tk.arr d).size := by omega
124  have hD0 : sd.elems.toInt ≤ d.depth.size := by omega
125  unfold btHeap btMergedStart
126  simp only [M_bind_assoc, M_pure_bind]
127  refine WS.bind' (merge_ws_and (merge_ws_and
128    (ws_btSortedStart hdd hsd hstat htree he3 he286 hT0 hD0 hH hs)
129    (ws_btSortedStart_sizes hdd hsd hstat htree he3 he286 hT0 hD0 hH hs))
130    (ws_btSortedStart_bl_count hdd hsd hstat htree he3 he286 hT0 hD0 hH hs))
131    fun a prepared ⟨⟨⟨ht, hst, he, hleaf, h2, hm, hdesc, ho, hmin⟩, hTs, hDs⟩, hBs⟩ => ?_
132  rcases a with ⟨tree, stree, elems, mc⟩
133  dsimp only at ht hst he hleaf hdesc ⊢
134  subst tree; subst stree; subst elems
135  have hcnt := hleaf.count
136  have hKN := Math.scanCount_le (btFreq tk prepared) sd.elems.toInt.toNat
137  have hI := BTForest.of_leaf hleaf h2 hm (node := sd.elems) (by omega)
138    (by rw [hTs]; omega) (by rw [hDs]; omega) ho
139  refine WS.bind' (ws_btMergeLoop_forest hI) fun next merged ⟨hforest, hframe, hlen⟩ => ?_
140  refine WS.bind' (ws_btSaveRoot_forest hforest hframe) fun _ e hbuilt => ?_
141  have hmeta := hbuilt.frame.metadata dk
142  have hDesc : dk.getDesc prepared = { dd with max_code := mc } :=
143    Option.some.inj ((bt_desc_get dk h0 id prepared).symm.trans hdesc)
144  have hDesc' : (dk.descRef id).get (setD h0 id e) = some { dd with max_code := mc } := by
145    rw [bt_desc_get, hmeta.1, hDesc]
146  have heB : e.bl_count.size = 16 := by rw [hmeta.2, hBs]; exact hB
147  have heT : (tk.arr e).size = (tk.arr prepared).size := by
148    obtain ⟨T, H, D, hl, hm, he, hT, hH, hD⟩ := hbuilt.frame
149    rw [he]
150    cases tk <;> exact hT
151  exact WS.pure' ⟨rfl, prepared, prepared.heap_len.toInt.toNat, hbuilt, hDesc', heB, by rw [heT, hTs]; exact hTbig⟩
152
153/-- The complete actual build_tree executes through length limiting and
154canonical code assignment. Its dynamic tree context is established by the
155actual prefix. Preconditions concern explicit internal storage and static
156tables, not assumed specifications of any called function. This is a local
157construction result; public caller reachability, emission and compression
158correctness are separate obligations. -/
159theorem ws_build_tree_complete {h0 : Heap} {id : Nat} {tk dk : TK} {d : DeflateState}
160    {sref : StaticTreeDescRef} {dd : TreeDesc} {sd : StaticTreeDesc}
161    {xb : Nat → Nat} {slOpt : Option (Nat → Nat)}
162    (hdd : (dk.descRef id).get (setD h0 id d) = some dd)
163    (hsd : StaticTreeDescRef.get h0 sref = some sd)
164    (hstat : dd.stat_desc = some sref) (htree : dd.dyn_tree = .ref (tk.ref id) 0)
165    (he3 : 3 ≤ sd.elems.toInt) (he286 : sd.elems.toInt ≤ 286)
166    (hT : 2 * sd.elems.toInt.toNat - 1 ≤ (tk.arr d).size) (hTbig : (tk.arr d).size ≤ 600)
167    (hD : 2 * sd.elems.toInt.toNat - 1 ≤ d.depth.size)
168    (hH : d.heap.size = 573) (hB : d.bl_count.size = 16)
169    (hs : BTBuildStatic h0 id sd xb slOpt) :
170    WS h0 id (build_tree (Sp id) (some (dk.descRef id))) d (fun _ e =>
171      ∃ (prepared built mid : DeflateState) (mc : Int32) (K : Nat),
172        BTBuilt tk sd.elems.toInt.toNat K mc prepared built ∧
173        GBDone tk built (574 - 2 * K) (K - 1) mc.toInt.toNat sd.max_length.toInt.toNat xb slOpt mid ∧
174        ∃ a : Array CtData, e = tk.setArr mid a ∧ a.size = (tk.arr mid).size ∧
175          ∀ i < a.size, a[i]! =
176            if i < (mc.toInt + 1).toNat ∧ (tk.arr mid)[i]!.dl ≠ 0 then
177              { (tk.arr mid)[i]! with fc := UInt16.ofNat (Math.storedCode
178                (fun b => mid.bl_count[b]!.toNat) (fun v => (tk.arr mid)[v]!.dl.toNat) i) }
179            else (tk.arr mid)[i]!) := by
180  obtain ⟨sl, hsRepair⟩ := hs.repair
181  rw [build_tree_eq_heap_codes]
182  refine WS.bind' (ws_btHeap_built hdd hsd hstat htree he3 he286 hT hTbig hD hH hB hsRepair)
183    fun a built ⟨ht, prepared, K, hbuilt, hdesc, hBs, hTs⟩ => ?_
184  rcases a with ⟨tree, mc⟩
185  dsimp only at ht hbuilt hdesc ⊢
186  subst tree
187  have hctx := hbuilt.bitlen_ctx hs rfl hBs hTs
188  have hcodes := ws_btCodes (h0 := h0) (id := id) (tk := tk) (d := built)
189    (r := dk.descRef id) (sref := sref) (dd := { dd with max_code := mc }) (sd := sd)
190    (hm := 574 - 2 * K) (J := K - 1) (elems := sd.elems.toInt.toNat) (maxc := mc.toInt.toNat)
191    (L := sd.max_length.toInt.toNat) (baseN := sd.extra_base.toInt.toNat) (xb := xb) (slOpt := slOpt)
192    hdesc hsd hstat htree hctx hbuilt.heap_max hs.length_capacity (by omega) hbuilt.unused
193  refine WS.mono hcodes ?_
194  intro _ e ⟨mid, hdone, hcode⟩
195  exact ⟨prepared, built, mid, mc, K, hbuilt, hdone, hcode⟩
196
197end Zlib.Trees.Proofs
ZLIB × LEAN

全局目录

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