aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BinaryHeap.lean4
-rw-r--r--BinaryHeap/CompleteTree/AdditionalOperations.lean18
-rw-r--r--BinaryHeap/CompleteTree/AdditionalProofs.lean146
-rw-r--r--BinaryHeap/CompleteTree/HeapOperations.lean32
-rw-r--r--BinaryHeap/CompleteTree/HeapProofs.lean2
-rw-r--r--BinaryHeap/CompleteTree/Lemmas.lean23
6 files changed, 190 insertions, 35 deletions
diff --git a/BinaryHeap.lean b/BinaryHeap.lean
index 9d1da1b..779c3ed 100644
--- a/BinaryHeap.lean
+++ b/BinaryHeap.lean
@@ -54,11 +54,11 @@ def indexOf {α : Type u} {le : α → α → Bool} {n : Nat} : BinaryHeap α le
instance : GetElem (BinaryHeap α le n) (Nat) α (λ _ index ↦ index > 0 ∧ index < n) where
getElem := λ heap index h₁ ↦ match n, heap, index with
- | (_+1), {tree, ..}, index => tree.get ⟨index, h₁.right⟩
+ | (_+1), {tree, ..}, index => tree.get' ⟨index, h₁.right⟩
instance : GetElem (BinaryHeap α le n) (Fin n) α (λ _ _ ↦ n > 0) where
getElem := λ heap index _ ↦ match n, heap, index with
- | (_+1), {tree, ..}, index => tree.get index
+ | (_+1), {tree, ..}, index => tree.get' index
/--Helper for the common case of using natural numbers for sorting.-/
theorem nat_ble_to_heap_le_total : total_le Nat.ble := by
diff --git a/BinaryHeap/CompleteTree/AdditionalOperations.lean b/BinaryHeap/CompleteTree/AdditionalOperations.lean
index 3327e70..1caf47d 100644
--- a/BinaryHeap/CompleteTree/AdditionalOperations.lean
+++ b/BinaryHeap/CompleteTree/AdditionalOperations.lean
@@ -1,13 +1,13 @@
import BinaryHeap.CompleteTree.Basic
import BinaryHeap.CompleteTree.NatLemmas
-namespace BinaryHeap
+namespace BinaryHeap.CompleteTree
----------------------------------------------------------------------------------------------
-- indexOf
/--Helper function for CompleteTree.indexOf.-/
-private def CompleteTree.indexOfAux {α : Type u} (heap : CompleteTree α o) (pred : α → Bool) (currentIndex : Nat) : Option (Fin (o+currentIndex)) :=
+private def indexOfAux {α : Type u} (heap : CompleteTree α o) (pred : α → Bool) (currentIndex : Nat) : Option (Fin (o+currentIndex)) :=
match o, heap with
| 0, .leaf => none
| (n+m+1), .branch a left right _ _ _ =>
@@ -25,7 +25,7 @@ private def CompleteTree.indexOfAux {α : Type u} (heap : CompleteTree α o) (pr
found_right
/--Finds the first occurance of a given element in the heap and returns its index. Indices are depth first.-/
-def CompleteTree.indexOf {α : Type u} (heap : CompleteTree α o) (pred : α → Bool) : Option (Fin o) :=
+def indexOf {α : Type u} (heap : CompleteTree α o) (pred : α → Bool) : Option (Fin o) :=
indexOfAux heap pred 0
@@ -33,13 +33,13 @@ def CompleteTree.indexOf {α : Type u} (heap : CompleteTree α o) (pred : α →
-- get
/--Returns the lement at the given index. Indices are depth first.-/
-def CompleteTree.get {α : Type u} {n : Nat} (index : Fin (n+1)) (heap : CompleteTree α (n+1)) : α :=
+def get' {α : Type u} {n : Nat} (index : Fin (n+1)) (heap : CompleteTree α (n+1)) : α :=
match h₁ : index, h₂ : n, heap with
| 0, (_+_), .branch v _ _ _ _ _ => v
| ⟨j+1,h₃⟩, (o+p), .branch _ l r _ _ _ =>
if h₄ : j < o then
match o with
- | (oo+1) => get ⟨j, h₄⟩ l
+ | (oo+1) => get' ⟨j, h₄⟩ l
else
have h₅ : n - o = p := Nat.sub_eq_of_eq_add $ (Nat.add_comm o p).subst h₂
have : p ≠ 0 :=
@@ -48,12 +48,16 @@ def CompleteTree.get {α : Type u} {n : Nat} (index : Fin (n+1)) (heap : Complet
have h₆ : j - o < p := h₅.subst $ Nat.sub_lt_sub_right (Nat.ge_of_not_lt h₄) $ Nat.lt_of_succ_lt_succ h₃
have _termination : j - o < index.val := (Fin.val_inj.mpr h₁).substr (Nat.sub_lt_succ j o)
match p with
- | (pp + 1) => get ⟨j - o, h₆⟩ r
+ | (pp + 1) => get' ⟨j - o, h₆⟩ r
+
+def get {α : Type u} {n : Nat} (index : Fin n) (heap : CompleteTree α n) (_ : n > 0) : α :=
+ match n, index, heap with
+ | (_+1), index, heap => heap.get' index
----------------------------------------------------------------------------------------------
-- contains - implemented as decidable proposition
-def CompleteTree.contains {α : Type u} {n : Nat} (tree : CompleteTree α n) (element : α) : Prop :=
+def contains {α : Type u} {n : Nat} (tree : CompleteTree α n) (element : α) : Prop :=
match n, tree with
| 0, .leaf => False
| (_+_+1), .branch v l r _ _ _ => v = element ∨ (l.contains element) ∨ (r.contains element)
diff --git a/BinaryHeap/CompleteTree/AdditionalProofs.lean b/BinaryHeap/CompleteTree/AdditionalProofs.lean
index ad626e7..1b3ef50 100644
--- a/BinaryHeap/CompleteTree/AdditionalProofs.lean
+++ b/BinaryHeap/CompleteTree/AdditionalProofs.lean
@@ -2,17 +2,153 @@ import BinaryHeap.CompleteTree.Lemmas
import BinaryHeap.CompleteTree.AdditionalOperations
import BinaryHeap.CompleteTree.HeapOperations
-namespace BinaryHeap
+namespace BinaryHeap.CompleteTree.AdditionalProofs
+
+private theorem if_get_eq_contains {α : Type u} {o : Nat} (tree : CompleteTree α (o+1)) (element : α) (index : Fin (o+1)) : tree.get' index = element → tree.contains element := by
+ unfold get' contains
+ simp only [Nat.succ_eq_add_one, Fin.zero_eta, Nat.add_eq, ne_eq]
+ split
+ case h_1 p q v l r _ _ _ _ =>
+ intro h₁
+ split; omega
+ rename α => vv
+ rename_i hsum heq
+ have h₂ := heqSameRoot (hsum) (Nat.succ_pos (p+q)) heq
+ rw[root_unfold] at h₂
+ rw[root_unfold] at h₂
+ simp only [←h₂, h₁, true_or]
+ case h_2 index p q v l r _ _ _ _ h₃ =>
+ intro h₄
+ split ; rename_i hx _; exact absurd hx (Nat.succ_ne_zero _)
+ case h_2 pp qq vv ll rr _ _ _ h₅ heq =>
+ have : p = pp := heqSameLeftLen h₅ (Nat.succ_pos _) heq
+ have : q = qq := heqSameRightLen h₅ (Nat.succ_pos _) heq
+ subst pp qq
+ simp only [Nat.add_eq, Nat.succ_eq_add_one, heq_eq_eq, branch.injEq] at heq
+ have : v = vv := heq.left
+ have : l = ll := heq.right.left
+ have : r = rr := heq.right.right
+ subst vv ll rr
+ revert h₄
+ split
+ all_goals
+ split
+ intro h₄
+ right
+ case' isTrue => left
+ case' isFalse => right
+ all_goals
+ revert h₄
+ apply if_get_eq_contains
+ done
+
+private theorem if_contains_get_eq_auxl {α : Type u} {o : Nat} (tree : CompleteTree α (o+1)) (element : α) (h₁ : o > 0) :
+ have : tree.leftLen (Nat.lt_succ_of_lt h₁) > 0 := by
+ unfold leftLen;
+ split
+ unfold length
+ rename_i hx _ _
+ simp only [Nat.add_eq, Nat.succ_eq_add_one, Nat.reduceEqDiff] at hx
+ omega
+ ∀(indexl : Fin (tree.leftLen (Nat.succ_pos o))), (tree.left _).get indexl this = element → ∃(index : Fin (o+1)), tree.get index (Nat.lt_succ_of_lt h₁) = element
+:= by
+ simp
+ intro indexl
+ let index : Fin (o+1) := indexl.succ.castLT (by
+ simp only [Nat.succ_eq_add_one, Fin.val_succ, Nat.succ_lt_succ_iff, gt_iff_lt]
+ exact Nat.lt_of_lt_of_le indexl.isLt $ Nat.le_of_lt_succ $ leftLenLtN tree (Nat.succ_pos o)
+ )
+ intro prereq
+ exists index
+ unfold get
+ simp
+ unfold get'
+ generalize hindex : index = i
+ split
+ case h_1 =>
+ have : index.val = 0 := Fin.val_eq_of_eq hindex
+ contradiction
+ case h_2 j p q v l r ht1 ht2 ht3 _ _ =>
+ have h₂ : index.val = indexl.val + 1 := rfl
+ have h₃ : index.val = j.succ := Fin.val_eq_of_eq hindex
+ have h₄ : j = indexl.val := Nat.succ.inj $ h₃.subst (motive := λx↦ x = indexl.val + 1) h₂
+ have : p = (branch v l r ht1 ht2 ht3).leftLen (Nat.succ_pos _) := rfl
+ have h₅ : j < p := by simp only [this, indexl.isLt, h₄]
+ simp only [h₅, ↓reduceDite, Nat.add_eq]
+ unfold get at prereq
+ split at prereq
+ rename_i pp ii ll _ hel hei heq _
+ split
+ rename_i ppp lll _ _ _ _ _ _ _
+ have : pp = ppp := by omega
+ subst pp
+ simp only [gt_iff_lt, Nat.succ_eq_add_one, Nat.add_eq, heq_eq_eq, Nat.zero_lt_succ] at *
+ have : j = ii.val := by omega
+ subst j
+ simp
+ rw[←hei] at prereq
+ rw[left_unfold] at heq
+ rw[heq]
+ assumption
+
+private theorem if_contains_get_eq {α : Type u} {o : Nat} (tree : CompleteTree α (o+1)) (element : α) (h₁ : tree.contains element) : ∃(index : Fin (o+1)), tree.get' index = element := by
+ revert h₁
+ unfold contains
+ split ; rename_i hx _; exact absurd hx (Nat.succ_ne_zero o)
+ rename_i n m v l r _ _ _ he heq
+ intro h₁
+ cases h₁
+ case h_2.inl h₂ =>
+ unfold get'
+ exists 0
+ split
+ case h_2 hx => have hx := Fin.val_eq_of_eq hx; simp at hx;
+ case h_1 vv _ _ _ _ _ _ _ =>
+ have h₃ := heqSameRoot he (Nat.succ_pos _) heq
+ simp only[root_unfold] at h₃
+ simp only[h₃, h₂]
+ rename_i h
+ cases h
+ case h_2.inr.inl h₂ => exact
+ match hn : n, hl: l with
+ | 0, .leaf => by contradiction
+ | (nn+1), l => by
+ have nn_lt_o : nn < o := by have : o = nn + 1 + m := Nat.succ.inj he; omega
+ have blah := if_contains_get_eq l element h₂
+ have blupp := if_contains_get_eq_auxl tree element $ Nat.zero_lt_of_lt nn_lt_o
+ simp at blupp
+ simp[get_eq_get'] at blah ⊢
+ apply blah.elim
+ match o, tree with
+ | (yy+_), .branch _ ll _ _ _ _ =>
+ simp_all[left_unfold, leftLen_unfold]
+ have : yy = nn+1 := heqSameLeftLen (by omega) (Nat.succ_pos _) heq
+ subst yy
+ have : _ = m := heqSameRightLen (by omega) (Nat.succ_pos _) heq
+ subst m
+ simp_all
+ exact blupp
+ case h_2.inr.inr h₂ => sorry
+ termination_by o
+
+
+theorem contains_iff_index_exists {α : Type u} {o : Nat} (tree : CompleteTree α (o+1)) (element : α) : tree.contains element ↔ ∃ (index : Fin (o+1)), tree.get' index = element := by
+ constructor
+ case mpr =>
+ simp only [forall_exists_index]
+ exact if_get_eq_contains tree element
+ case mp =>
+ exact if_contains_get_eq tree element
/--Shows that the index and value returned by heapRemoveLastWithIndex are consistent.-/
-private theorem CompleteTree.heapRemoveLastWithIndexReturnsItemAtIndex {α : Type u} {o : Nat} (heap : CompleteTree α (o+1)) : heap.get heap.heapRemoveLastWithIndex.snd.snd = heap.heapRemoveLastWithIndex.snd.fst := by
+protected theorem heapRemoveLastWithIndexReturnsItemAtIndex {α : Type u} {o : Nat} (heap : CompleteTree α (o+1)) : heap.get' heap.heapRemoveLastWithIndex.snd.snd = heap.heapRemoveLastWithIndex.snd.fst := by
unfold CompleteTree.heapRemoveLastWithIndex CompleteTree.Internal.heapRemoveLastAux
split
rename_i n m v l r m_le_n max_height_difference subtree_full
simp only [Nat.add_eq, Fin.zero_eta, Fin.isValue, decide_eq_true_eq, Fin.castLE_succ]
split
case isTrue n_m_zero =>
- unfold get
+ unfold get'
split
case h_1 nn mm vv ll rr mm_le_nn _ _ _ _ he₁ he₂ =>
have h₁ : n = 0 := And.left $ Nat.add_eq_zero.mp n_m_zero.symm
@@ -24,7 +160,7 @@ private theorem CompleteTree.heapRemoveLastWithIndexReturnsItemAtIndex {α : Typ
case h_2 =>
omega -- to annoying to deal with Fin.ofNat... There's a hypothesis that says 0 = ⟨1,_⟩.
case isFalse n_m_not_zero =>
- unfold get
+ unfold get'
split
case h_1 nn mm vv ll rr mm_le_nn max_height_difference_2 subtree_full2 _ he₁ he₂ he₃ =>
--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -81,5 +217,5 @@ private theorem CompleteTree.heapRemoveLastWithIndexReturnsItemAtIndex {α : Typ
simp only [this, ↓reduceDite, Nat.pred_succ, Fin.isValue]
subst j -- overkill, but unlike rw it works
simp only [Nat.pred_succ, Fin.isValue, Nat.add_sub_cancel, Fin.eta]
- apply heapRemoveLastWithIndexReturnsItemAtIndex
+ apply AdditionalProofs.heapRemoveLastWithIndexReturnsItemAtIndex
done
diff --git a/BinaryHeap/CompleteTree/HeapOperations.lean b/BinaryHeap/CompleteTree/HeapOperations.lean
index 337797c..1c9a27e 100644
--- a/BinaryHeap/CompleteTree/HeapOperations.lean
+++ b/BinaryHeap/CompleteTree/HeapOperations.lean
@@ -1,7 +1,7 @@
import BinaryHeap.CompleteTree.Basic
import BinaryHeap.CompleteTree.NatLemmas
-namespace BinaryHeap
+namespace BinaryHeap.CompleteTree
----------------------------------------------------------------------------------------------
-- heapPush
@@ -18,9 +18,9 @@ private theorem power_of_two_mul_two_lt {n m : Nat} (h₁ : m.isPowerOfTwo) (h
Nat.lt_of_le_of_ne ((Nat.not_lt_eq _ _).mp h₄) h₅
/--Adds a new element to a given CompleteTree.-/
-def CompleteTree.heapPush (le : α → α → Bool) (elem : α) (heap : CompleteTree α o) : CompleteTree α (o+1) :=
+def heapPush (le : α → α → Bool) (elem : α) (heap : CompleteTree α o) : CompleteTree α (o+1) :=
match o, heap with
- | 0, .leaf => CompleteTree.branch elem (CompleteTree.leaf) (CompleteTree.leaf) (by simp) (by simp) (by simp[Nat.one_isPowerOfTwo])
+ | 0, .leaf => .branch elem (.leaf) (.leaf) (by simp) (by simp) (by simp[Nat.one_isPowerOfTwo])
| (n+m+1), .branch a left right p max_height_difference subtree_complete =>
let (elem, a) := if le elem a then (a, elem) else (elem, a)
-- okay, based on n and m we know if we want to add left or right.
@@ -95,7 +95,7 @@ private theorem power_of_two_mul_two_le {n m : Nat} (h₁ : (n+1).isPowerOfTwo)
h₅.resolve_left h₆
/-- Helper for heapRemoveLastAux -/
-private theorem CompleteTree.removeRightRightNotEmpty {n m : Nat} (m_gt_0_or_rightIsFull : m > 0 ∨ ((m+1).nextPowerOfTwo = m+1 : Bool)) (h₁ : 0 ≠ n + m) (h₂ : ¬(m < n ∧ ((m+1).nextPowerOfTwo = m+1 : Bool))) : m > 0 :=
+private theorem removeRightRightNotEmpty {n m : Nat} (m_gt_0_or_rightIsFull : m > 0 ∨ ((m+1).nextPowerOfTwo = m+1 : Bool)) (h₁ : 0 ≠ n + m) (h₂ : ¬(m < n ∧ ((m+1).nextPowerOfTwo = m+1 : Bool))) : m > 0 :=
match m_gt_0_or_rightIsFull with
| Or.inl h => h
| Or.inr h => by
@@ -108,7 +108,7 @@ private theorem CompleteTree.removeRightRightNotEmpty {n m : Nat} (m_gt_0_or_rig
. exact Nat.succ_pos _
/-- Helper for heapRemoveLastAux -/
-private theorem CompleteTree.removeRightLeftIsFull {n m : Nat} (r : ¬(m < n ∧ ((m+1).nextPowerOfTwo = m+1 : Bool))) (m_le_n : m ≤ n) (subtree_complete : (n + 1).isPowerOfTwo ∨ (m + 1).isPowerOfTwo) : (n+1).isPowerOfTwo := by
+private theorem removeRightLeftIsFull {n m : Nat} (r : ¬(m < n ∧ ((m+1).nextPowerOfTwo = m+1 : Bool))) (m_le_n : m ≤ n) (subtree_complete : (n + 1).isPowerOfTwo ∨ (m + 1).isPowerOfTwo) : (n+1).isPowerOfTwo := by
rewrite[Decidable.not_and_iff_or_not] at r
cases r
case inl h₁ => rewrite[Nat.not_lt_eq] at h₁
@@ -121,7 +121,7 @@ private theorem CompleteTree.removeRightLeftIsFull {n m : Nat} (r : ¬(m < n ∧
assumption
/-- Helper for heapRemoveLastAux -/
-private theorem CompleteTree.stillInRange {n m : Nat} (r : ¬(m < n ∧ ((m+1).nextPowerOfTwo = m+1 : Bool))) (m_le_n : m ≤ n) (m_gt_0 : m > 0) (leftIsFull : (n+1).isPowerOfTwo) (max_height_difference: n < 2 * (m + 1)) : n < 2*m := by
+private theorem stillInRange {n m : Nat} (r : ¬(m < n ∧ ((m+1).nextPowerOfTwo = m+1 : Bool))) (m_le_n : m ≤ n) (m_gt_0 : m > 0) (leftIsFull : (n+1).isPowerOfTwo) (max_height_difference: n < 2 * (m + 1)) : n < 2*m := by
rewrite[Decidable.not_and_iff_or_not] at r
cases r with
| inl h₁ => have m_eq_n : m = n := Nat.le_antisymm m_le_n (Nat.not_lt.mp h₁)
@@ -136,7 +136,7 @@ private theorem CompleteTree.stillInRange {n m : Nat} (r : ¬(m < n ∧ ((m+1).n
**BEWARE** that "last" here means the underlying complete tree. It is *not* the elemenent
at the largest index, nor is it the largest element in the heap.
-/
-protected def CompleteTree.Internal.heapRemoveLastAux
+protected def Internal.heapRemoveLastAux
{α : Type u}
{β : Nat → Type u}
{o : Nat}
@@ -179,7 +179,7 @@ protected def CompleteTree.Internal.heapRemoveLastAux
Removes the last element in the complete Tree. This is **NOT** the element with the
largest index, nor is it the largest element in the heap.
-/
-protected def CompleteTree.Internal.heapRemoveLast {α : Type u} {o : Nat} (heap : CompleteTree α (o+1)) : (CompleteTree α o × α) :=
+protected def Internal.heapRemoveLast {α : Type u} {o : Nat} (heap : CompleteTree α (o+1)) : (CompleteTree α o × α) :=
Internal.heapRemoveLastAux heap id (λ(a : α) _ ↦ a) (λa _ _ ↦ a)
/--
@@ -188,7 +188,7 @@ protected def CompleteTree.Internal.heapRemoveLast {α : Type u} {o : Nat} (heap
Also returns the index of the removed element.
-/
-protected def CompleteTree.heapRemoveLastWithIndex {α : Type u} {o : Nat} (heap : CompleteTree α (o+1)) : (CompleteTree α o × α × Fin (o+1)) :=
+protected def heapRemoveLastWithIndex {α : Type u} {o : Nat} (heap : CompleteTree α (o+1)) : (CompleteTree α o × α × Fin (o+1)) :=
Internal.heapRemoveLastAux heap (β := λn ↦ α × Fin n)
(λ(a : α) ↦ (a, Fin.mk 0 (Nat.succ_pos 0)))
(λ(a, prev_idx) h₁ ↦ (a, prev_idx.succ.castLE $ Nat.succ_le_of_lt h₁) )
@@ -198,9 +198,9 @@ protected def CompleteTree.heapRemoveLastWithIndex {α : Type u} {o : Nat} (heap
-- heapUpdateRoot
/--
- Helper for CompleteTree.heapUpdateAt. Makes proofing heap predicate work in Lean 4.9
+ Helper for heapUpdateAt. Makes proofing heap predicate work in Lean 4.9
-/
-def CompleteTree.heapUpdateRoot {α : Type u} {n : Nat} (le : α → α → Bool) (value : α) (heap : CompleteTree α n) (_ : n > 0) : CompleteTree α n × α :=
+def heapUpdateRoot {α : Type u} {n : Nat} (le : α → α → Bool) (value : α) (heap : CompleteTree α n) (_ : n > 0) : CompleteTree α n × α :=
match n, heap with
| (o+p+1), .branch v l r h₃ h₄ h₅ =>
if h₆ : o = 0 then
@@ -234,11 +234,11 @@ match n, heap with
-- heapRemoveAt
/--
- Helper for CompleteTree.heapRemoveAt.
+ Helper for heapRemoveAt.
Removes the element at index, and instead inserts the given value.
Returns the element at index, and the resulting tree.
-/
-def CompleteTree.heapUpdateAt {α : Type u} {n : Nat} (le : α → α → Bool) (index : Fin n) (value : α) (heap : CompleteTree α n) (h₁ : n > 0) : CompleteTree α n × α :=
+def heapUpdateAt {α : Type u} {n : Nat} (le : α → α → Bool) (index : Fin n) (value : α) (heap : CompleteTree α n) (h₁ : n > 0) : CompleteTree α n × α :=
if h₂ : index == ⟨0,h₁⟩ then
heapUpdateRoot le value heap h₁
else
@@ -268,7 +268,7 @@ def CompleteTree.heapUpdateAt {α : Type u} {n : Nat} (le : α → α → Bool)
----------------------------------------------------------------------------------------------
-- heapPop
-def CompleteTree.heapPop {α : Type u} {n : Nat} (le : α → α → Bool) (heap : CompleteTree α (n+1)) : CompleteTree α n × α :=
+def heapPop {α : Type u} {n : Nat} (le : α → α → Bool) (heap : CompleteTree α (n+1)) : CompleteTree α n × α :=
let l := Internal.heapRemoveLast heap
if p : n > 0 then
heapUpdateRoot le l.snd l.fst p
@@ -278,8 +278,8 @@ def CompleteTree.heapPop {α : Type u} {n : Nat} (le : α → α → Bool) (heap
----------------------------------------------------------------------------------------------
-- heapRemoveAt
-/--Removes the element at a given index. Use `CompleteTree.indexOf` to find the respective index.-/
-def CompleteTree.heapRemoveAt {α : Type u} {n : Nat} (le : α → α → Bool) (index : Fin (n+1)) (heap : CompleteTree α (n+1)) : CompleteTree α n × α :=
+/--Removes the element at a given index. Use `indexOf` to find the respective index.-/
+def heapRemoveAt {α : Type u} {n : Nat} (le : α → α → Bool) (index : Fin (n+1)) (heap : CompleteTree α (n+1)) : CompleteTree α n × α :=
--Since we cannot even temporarily break the completeness property, we go with the
--version from Wikipedia: We first remove the last element, and then update values in the tree
--indices are depth first, but "last" means last element of the complete tree.
diff --git a/BinaryHeap/CompleteTree/HeapProofs.lean b/BinaryHeap/CompleteTree/HeapProofs.lean
index d56e5b5..a41f963 100644
--- a/BinaryHeap/CompleteTree/HeapProofs.lean
+++ b/BinaryHeap/CompleteTree/HeapProofs.lean
@@ -3,7 +3,7 @@ import BinaryHeap.CompleteTree.Lemmas
namespace BinaryHeap
-theorem CompleteTree.emptyIsHeap {α : Type u} (le : α → α → Bool) : HeapPredicate CompleteTree.empty le := by trivial
+theorem CompleteTree.emptyIsHeap {α : Type u} (le : α → α → Bool) : HeapPredicate CompleteTree.empty le := True.intro
----------------------------------------------------------------------------------------------
-- heapPush
diff --git a/BinaryHeap/CompleteTree/Lemmas.lean b/BinaryHeap/CompleteTree/Lemmas.lean
index 2e4bda1..dc26dd5 100644
--- a/BinaryHeap/CompleteTree/Lemmas.lean
+++ b/BinaryHeap/CompleteTree/Lemmas.lean
@@ -1,4 +1,5 @@
import BinaryHeap.CompleteTree.Basic
+import BinaryHeap.CompleteTree.AdditionalOperations
import BinaryHeap.HeapPredicate
namespace BinaryHeap
@@ -21,17 +22,31 @@ theorem CompleteTree.root_unfold {α : Type u} {o p : Nat} (v : α) (l : Complet
/-- Helper to rw away left, because Lean 4.9 makes it unnecessarily hard to deal with match in tactics mode... -/
theorem CompleteTree.left_unfold {α : Type u} {o p : Nat} (v : α) (l : CompleteTree α o) (r : CompleteTree α p) (h₁ : p ≤ o) (h₂ : o < 2 * (p + 1)) (h₃ : (o + 1).isPowerOfTwo ∨ (p + 1).isPowerOfTwo) (h₄ : o + p + 1 > 0): (CompleteTree.branch v l r h₁ h₂ h₃).left h₄ = l := rfl
+theorem CompleteTree.leftLen_unfold {α : Type u} {o p : Nat} (v : α) (l : CompleteTree α o) (r : CompleteTree α p) (h₁ : p ≤ o) (h₂ : o < 2 * (p + 1)) (h₃ : (o + 1).isPowerOfTwo ∨ (p + 1).isPowerOfTwo) (h₄ : o + p + 1 > 0): (CompleteTree.branch v l r h₁ h₂ h₃).leftLen h₄ = o := rfl
+
/-- Helper to rw away right, because Lean 4.9 makes it unnecessarily hard to deal with match in tactics mode... -/
theorem CompleteTree.right_unfold {α : Type u} {o p : Nat} (v : α) (l : CompleteTree α o) (r : CompleteTree α p) (h₁ : p ≤ o) (h₂ : o < 2 * (p + 1)) (h₃ : (o + 1).isPowerOfTwo ∨ (p + 1).isPowerOfTwo) (h₄ : o + p + 1 > 0): (CompleteTree.branch v l r h₁ h₂ h₃).right h₄ = r := rfl
theorem CompleteTree.heqSameLeftLen {α : Type u} {n m : Nat} {a : CompleteTree α n} {b : CompleteTree α m} (h₁ : n = m) (h₂ : n > 0) (h₃ : HEq a b) : a.leftLen h₂ = b.leftLen (h₁.subst h₂) := by
subst n
have h₃ : a = b := eq_of_heq h₃
- subst a
- rfl
+ congr
theorem CompleteTree.heqSameRightLen {α : Type u} {n m : Nat} {a : CompleteTree α n} {b : CompleteTree α m} (h₁ : n = m) (h₂ : n > 0) (h₃ : HEq a b) : a.rightLen h₂ = b.rightLen (h₁.subst h₂) := by
subst n
have h₃ : a = b := eq_of_heq h₃
- subst a
- rfl
+ congr
+
+theorem CompleteTree.heqSameRoot {α : Type u} {n m : Nat} {a : CompleteTree α n} {b : CompleteTree α m} (h₁ : n = m) (h₂ : n > 0) (h₃ : HEq a b) : a.root h₂ = b.root (h₁.subst h₂) := by
+ subst n
+ have h₃ : a = b := eq_of_heq h₃
+ congr
+
+theorem CompleteTree.get_eq_get' {α : Type u} {n : Nat} (tree : CompleteTree α (n+1)) (index : Fin (n+1)) : tree.get' index = tree.get index (Nat.succ_pos n) := rfl
+
+theorem CompleteTree.leftLenLtN {α : Type u} {n : Nat} (tree : CompleteTree α n) (h₁ : n>0) : tree.leftLen h₁ < n := by
+ unfold leftLen
+ split
+ rw[length]
+ rename_i o p _ _ _ _ _ _ _
+ exact Nat.lt_of_le_of_lt (Nat.le_add_right o p) (Nat.lt_succ_self (o+p))