-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBTree.lean
353 lines (292 loc) · 10.5 KB
/
BTree.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
import Std.Data.List.Lemmas
namespace List
theorem Mem.of_mem_head : x ∈ head? l → x ∈ l := by
intro; cases l <;> simp_all
theorem Mem.of_mem_last : x ∈ last' l → x ∈ l := by
match l with
| [] => simp
| [_] => intro; simp_all
| _ :: _ :: l => intro h; have := of_mem_last (l := _ :: l) h; simp_all
@[simp]
theorem last'_append_cons : (l ++ x :: r).last' = (x :: r).last' :=
match l with
| [] => rfl
| [_] => rfl
| _ :: _ :: l => last'_append_cons (l := _ :: l)
@[simp]
theorem head?_append_cons : (l ++ x :: r).head? = (l ++ [x]).head? := by
cases l <;> rfl
variable {α : Type u} {R : α → α → Prop}
@[simp] theorem Chain_nil_def : Chain R a [] ↔ True := ⟨λ | .nil => ⟨⟩, λ | ⟨⟩ => .nil⟩
@[simp] theorem Chain_cons_def : Chain R a (b :: l) ↔ R a b ∧ Chain R b l := ⟨λ | .cons h h' => ⟨h, h'⟩, λ ⟨h, h'⟩ => .cons h h'⟩
attribute [local simp] Chain'
theorem Chain'_cons : Chain' R (x :: l) ↔ (∀ y ∈ l.head?, R x y) ∧ Chain' R l := by
cases l <;> simp
theorem Chain'.cons (hx : ∀ y ∈ l.head?, R x y) (hl : Chain' R l) : Chain' R (x :: l) :=
Chain'_cons.mpr ⟨hx, hl⟩
theorem Chain'_append : Chain' R (l ++ r) ↔ Chain' R l ∧ (∀ x ∈ l.last', ∀ y ∈ r.head?, R x y) ∧ Chain' R r := by
match l with
| [] => simp
| [x] => simp; exact Chain'_cons
| x :: y :: l => simp [and_assoc]; intro; exact Chain'_append (l := y :: l)
theorem Chain'.append (hl : Chain' R l) (hlr : ∀ x ∈ l.last', ∀ y ∈ r.head?, R x y) (hr : Chain' R r) : Chain' R (l ++ r) :=
Chain'_append.mpr ⟨hl, hlr, hr⟩
end List
inductive BTree (α : Type u)
| leaf
| node (l : BTree α) (x : α) (r : BTree α)
namespace BTree
variable {α : Type u}
@[simp]
def toList : BTree α → List α
| leaf => []
| node l x r => toList l ++ x :: toList r
@[simp]
def size : BTree α → Nat
| leaf => 0
| node l _ r => size l + size r + 1
@[simp]
def height : BTree α → Nat
| leaf => 0
| node l _ r => max (height l) (height r) + 1
private def toList.impl : BTree α → List α :=
toList []
where
toList a
| leaf => a
| node l x r => toList (x :: toList a r) l
@[csimp]
private theorem toList.eq_impl : @toList = @impl := by
funext α t
suffices ∀ a t, toList t ++ a = impl.toList a t from
(List.append_nil .. ▸ this [] t :)
intro a t
induction t generalizing a with
| leaf => rfl
| node _ _ _ ihl ihr =>
dsimp [toList, impl.toList]
rw [← ihr, ← ihl, List.append_assoc]
rfl
@[simp]
def front? : BTree α → Option α
| leaf => none
| node leaf x _ => some x
| node l _ _ => front? l
@[simp]
def back? : BTree α → Option α
| leaf => none
| node _ x leaf => some x
| node _ _ r => back? r
theorem head?_toList : (t : BTree α) → t.toList.head? = t.front?
| leaf => rfl
| node leaf _ _ => rfl
| node (node ..) _ _ => by simp; rw [← List.head?_append_cons]; exact head?_toList (node ..)
theorem last'_toList : (t : BTree α) → t.toList.last' = t.back?
| leaf => rfl
| node _ _ leaf => by simp
| node _ _ (node ..) => by simp; rw [← List.last'_append_cons]; exact last'_toList (node ..)
variable [LT α]
theorem leaf_lt (x : α) : ∀ y ∈ leaf.back?, y < x := λ _ hy => nomatch hy
theorem leaf_gt (x : α) : ∀ y ∈ leaf.front?, x < y := λ _ hy => nomatch hy
inductive Bst : BTree α → Prop
| leaf : Bst leaf
| node {l x r} : (∀ y ∈ l.back?, y < x) → (∀ y ∈ r.front?, x < y) → Bst l → Bst r → Bst (node l x r)
theorem Bst_iff_Chain_toList {t : BTree α} : Bst t ↔ t.toList.Chain' LT.lt := by
constructor
. intro h
induction h with
| leaf => dsimp!
| node hlx hrx _ _ ihl ihr =>
dsimp
refine .append ihl ?_ <| .cons (head?_toList _ ▸ hrx) ihr
simp
exact last'_toList _ ▸ hlx
. intro h
induction t with
| leaf => constructor
| node _ _ _ ihl ihr =>
simp [List.Chain'_append, List.Chain'_cons] at h
constructor
. exact last'_toList _ ▸ h.2.1
. exact head?_toList _ ▸ h.2.2.1
. exact ihl h.1
. exact ihr h.2.2.2
variable [@DecidableRel α LT.lt]
instance instDecidableBst : (t : BTree α) → Decidable (Bst t)
| leaf => isTrue .leaf
| node l _ r =>
if hlx : _
then
if hrx : _
then
match instDecidableBst l with
| isTrue hl =>
match instDecidableBst r with
| isTrue hr => isTrue <| .node hlx hrx hl hr
| isFalse hr => isFalse λ | .node _ _ _ hr' => hr hr'
| isFalse hl => isFalse λ | .node _ _ hl' _ => hl hl'
else isFalse λ | .node _ hrx' _ _ => hrx hrx'
else isFalse λ | .node hlx' _ _ _ => hlx hlx'
@[simp]
def find (y : α) : BTree α → Bool
| leaf => false
| node l x r => if y < x then find y l else if x < y then find y r else true
def insert (y : α) : BTree α → BTree α
| leaf => node leaf y leaf
| node l x r => if y < x then node (insert y l) x r else if x < y then node l x (insert y r) else node l x r
theorem insert_lt {t : BTree α} (hyz : y < z) (hlz : ∀ x ∈ t.back?, x < z) : ∀ x ∈ (t.insert y).back?, x < z := by
induction t with
| leaf => simp [hyz]
| node _ _ r _ ihr =>
unfold insert
split
. cases r <;> exact hlz
. split
. cases r with
| leaf => simp [hyz]
| node =>
specialize ihr hlz
unfold insert at ihr ⊢
split
next h => rw [if_pos h] at ihr; exact ihr
next h =>
rw [if_neg h] at ihr; split
next h => rw [if_pos h] at ihr; exact ihr
next h => rw [if_neg h] at ihr; exact ihr
. exact hlz
theorem insert_gt {t : BTree α} (hyz : z < y) (hlz : ∀ x ∈ t.front?, z < x) : ∀ x ∈ (t.insert y).front?, z < x := by
induction t with
| leaf => simp [hyz]
| node l _ _ ihl =>
unfold insert
split
. cases l with
| leaf => simp [hyz]
| node =>
specialize ihl hlz
unfold insert at ihl ⊢
split
next h => rw [if_pos h] at ihl; exact ihl
next h =>
rw [if_neg h] at ihl; split
next h => rw [if_pos h] at ihl; exact ihl
next h => rw [if_neg h] at ihl; exact ihl
. split
. cases l <;> exact hlz
. exact hlz
theorem insert_Bst {t : BTree α} (h : Bst t) : Bst (t.insert y) := by
induction h with
| leaf =>
refine .node ?_ ?_ .leaf .leaf
. simp
. simp
| node hlx hrx hl hr =>
unfold insert
split
next h => exact .node (insert_lt h hlx) hrx (insert_Bst hl) hr
next =>
split
next h => exact .node hlx (insert_gt h hrx) hl (insert_Bst hr)
next => exact .node hlx hrx hl hr
theorem Bst.rotate_left {r : BTree α} : Bst (.node l x (.node c y r)) → Bst (.node (.node l x c) y r)
| .node hlx hcyrx hl (.node _ hry .leaf hr) => .node (by simp [*]) hry (.node hlx (leaf_gt x) hl .leaf) hr
| .node hlx hcyrx hl (.node hcy hry hc@(.node ..) hr) => .node hcy hry (.node hlx hcyrx hl hc ) hr
theorem Bst.rotate_right {r : BTree α} : Bst (.node (.node l x c) y r) → Bst (.node l x (.node c y r))
| .node hlxcy hry (.node hlx _ hl .leaf ) hr => .node hlx (by simp [*]) hl (.node (leaf_lt y) hry .leaf hr)
| .node hlxcy hry (.node hlx hcx hl hc@(.node ..)) hr => .node hlx hcx hl (.node hlxcy hry hc hr)
variable (l r : Nat) in
inductive Close : Prop
| balanced : l = r → Close
| left : l = r + 1 → Close
| right : l + 1 = r → Close
inductive Avl : BTree α → Prop
| leaf : Avl leaf
| node : Close l.height r.height → Avl l → Avl r → Avl (node l x r)
def rebalance (l : BTree α) (x : α) (r : BTree α) : BTree α × α × BTree α :=
if _ : r.height + 1 < l.height
then
match l with
| node l₁ x₁ r₁ =>
if _ : l₁.height < r₁.height
then
match r₁ with
| node l₂ x₂ r₂ => (node l₁ x₁ l₂, x₂, node r₂ x r)
else (l₁, x₁, node r₁ x r)
else
if _ : l.height + 1 < r.height
then
match r with
| node l₁ x₁ r₁ =>
if _ : r₁.height < l₁.height
then
match l₁ with
| node l₂ x₂ r₂ => (node l x l₂, x₂, node r₂ x₁ r₁)
else (node l x l₁, x₁, r₁)
else (l, x, r)
#check Nat.sub_le_sub_left
theorem Close_rebalance {l} {x : α} {r} : let (l', _, r') := rebalance l x r; Close l'.height r'.height := by
dsimp
unfold rebalance
split
case' inr =>
split
case inr h₁ h₂ =>
dsimp
generalize height l = l at h₁ h₂
generalize height r = r at h₁ h₂
cases Nat.le_of_not_lt h₁ with
| refl => exact .left rfl
| step h₁ =>
cases Nat.le_of_not_lt h₂ with
| refl => exact .right rfl
| step h₂ => exact .balanced (Nat.le_antisymm h₁ h₂)
. split
next l₁ x₁ r₁ _ _ =>
split
. sorry
. dsimp
sorry
. sorry
variable (y : α) in
def insertAvl' : BTree α → BTree α × α × BTree α
| leaf => (leaf, y, leaf)
| node l x r =>
if y < x
then
let (l', x', r') := insertAvl' l
rebalance (node l' x' r') x r
else
if x < y
then
let (l', x', r') := insertAvl' r
rebalance l x (node l' x' r')
else (l, x, r)
def insertAvl (y : α) (t : BTree α) : BTree α :=
let (l, x, r) := insertAvl' y t
node l x r
end BTree
variable (α : Type u) [LT α] in
def Bst := { t : BTree α // t.Bst }
namespace Bst
variable {α : Type u} [LT α]
def empty : Bst α := ⟨.leaf, .leaf⟩
def singleton (x : α) : Bst α := ⟨.node .leaf x .leaf, .node (BTree.leaf_lt x) (BTree.leaf_gt x) .leaf .leaf⟩
def size (t : Bst α) : Nat := t.val.size
variable [@DecidableRel α LT.lt]
def find (x : α) (t : Bst α) : Bool := t.val.find x
def insert (x : α) (t : Bst α) : Bst α := ⟨t.val.insert x, BTree.insert_Bst t.property⟩
end Bst
def foo : Bst Nat := ⟨.node (.node (.node .leaf 0 .leaf) 2 (.node .leaf 3 .leaf)) 4 (.node (.node .leaf 5 .leaf) 6 (.node .leaf 7 .leaf)), by decide⟩
#eval foo.1.toList
#eval foo.insert 1 |>.1.toList
#reduce BTree.leaf |>.insertAvl 0 |>.insertAvl 1 |>.insertAvl 2 |>.insertAvl 3 |>.insertAvl 4 |>.insertAvl 5 |>.insertAvl 6 |>.insertAvl 7
/-
@[simp]
def Bst' : BTree α → Prop
| leaf => True
| node l x r => l.lt x ∧ r.gt x ∧ Bst l ∧ Bst r
@[simp]
example : (t : BTree α) → Bst t ↔ Bst' t
| leaf => ⟨λ | .leaf => .intro, λ | .intro => .leaf⟩
| node .. => ⟨λ | .node hxl hxr hl hr => ⟨hxl, hxr, hl, hr⟩, λ | ⟨hxl, hxr, hl, hr⟩ => .node hxl hxr hl hr⟩
-/