diff options
Diffstat (limited to 'BinaryHeap/CompleteTree/HeapProofs/HeapUpdateRoot.lean')
| -rw-r--r-- | BinaryHeap/CompleteTree/HeapProofs/HeapUpdateRoot.lean | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/BinaryHeap/CompleteTree/HeapProofs/HeapUpdateRoot.lean b/BinaryHeap/CompleteTree/HeapProofs/HeapUpdateRoot.lean new file mode 100644 index 0000000..c2cc072 --- /dev/null +++ b/BinaryHeap/CompleteTree/HeapProofs/HeapUpdateRoot.lean @@ -0,0 +1,239 @@ +import BinaryHeap.CompleteTree.HeapOperations +import BinaryHeap.CompleteTree.Lemmas + +namespace BinaryHeap.CompleteTree + +private theorem heapUpdateRootReturnsRoot {α : Type u} {n : Nat} (le : α → α → Bool) (value : α) (heap : CompleteTree α n) (h₁ : n > 0) : (heap.heapUpdateRoot le value h₁).snd = heap.root h₁ := by + unfold heapUpdateRoot + split + rename_i o p v l r h₃ h₄ h₅ h₁ + simp + cases o <;> simp + case zero => + exact root_unfold v l r h₃ h₄ h₅ h₁ + case succ => + cases p <;> simp + case zero => + cases le value (root l _) + <;> simp only [Bool.false_eq_true, ↓reduceIte, root_unfold] + case succ => + cases le value (root l _) <;> cases le value (root r _) + <;> cases le (root l _) (root r _) + <;> simp only [Bool.false_eq_true, and_self, and_true, and_false, ↓reduceIte, root_unfold] + +private theorem heapUpdateRootPossibleRootValuesAuxL {α : Type u} (heap : CompleteTree α n) (h₁ : n > 1) : 0 < heap.leftLen (Nat.lt_trans (Nat.lt_succ_self 0) h₁) := + match h₅: n, heap with + | (o+p+1), .branch v l r h₂ h₃ h₄ => by + simp[leftLen, length] + cases o + case zero => rewrite[(Nat.le_zero_eq p).mp h₂] at h₁; contradiction + case succ q => exact Nat.zero_lt_succ q + +private theorem heapUpdateRootPossibleRootValuesAuxR {α : Type u} (heap : CompleteTree α n) (h₁ : n > 2) : 0 < heap.rightLen (Nat.lt_trans (Nat.lt_succ_self 0) $ Nat.lt_trans (Nat.lt_succ_self 1) h₁) := + match h₅: n, heap with + | (o+p+1), .branch v l r h₂ h₃ h₄ => by + simp[rightLen, length] + cases p + case zero => simp_arith at h₁; simp at h₃; exact absurd h₁ (Nat.not_le_of_gt h₃) + case succ q => exact Nat.zero_lt_succ q + +private theorem heapUpdateRootPossibleRootValues1 {α : Type u} (le : α → α → Bool) (value : α) (heap : CompleteTree α n) (h₁ : n = 1) : (heap.heapUpdateRoot le value (h₁.substr (Nat.lt_succ_self 0))).fst.root (h₁.substr (Nat.lt_succ_self 0)) = value := by + unfold heapUpdateRoot + generalize (h₁.substr (Nat.lt_succ_self 0) : n > 0) = hx + split + rename_i o p v l r _ _ _ h₁ + have h₃ : o = 0 := (Nat.add_eq_zero.mp $ Nat.succ.inj h₁).left + simp[h₃, root_unfold] + +private theorem heapUpdateRootPossibleRootValues2 {α : Type u} (le : α → α → Bool) (value : α) (heap : CompleteTree α n) (h₁ : n = 2) : +have h₂ : 0 < n := Nat.lt_trans (Nat.lt_succ_self 0) $ h₁.substr (Nat.lt_succ_self 1) +have h₃ : 0 < leftLen heap h₂ := heapUpdateRootPossibleRootValuesAuxL heap (h₁.substr (Nat.lt_succ_self 1)) +(heap.heapUpdateRoot le value h₂).fst.root h₂ = value +∨ (heap.heapUpdateRoot le value h₂).fst.root h₂ = (heap.left h₂).root h₃ +:= by + simp + unfold heapUpdateRoot + generalize (Nat.lt_trans (Nat.lt_succ_self 0) (Eq.substr h₁ (Nat.lt_succ_self 1)) : 0 < n) = h₂ + split + rename_i o p v l r h₃ h₄ h₅ h₂ + cases o <;> simp + case zero => simp only[root, true_or] + case succ oo => + have h₆ : p = 0 := by simp at h₁; omega + simp only [h₆, ↓reduceDite] + cases le value (l.root _) + <;> simp[heapUpdateRootReturnsRoot, root_unfold, left_unfold] + +private theorem heapUpdateRootPossibleRootValues3 {α : Type u} (le : α → α → Bool) (value : α) (heap : CompleteTree α n) (h₁ : n > 2) : +have h₂ : 0 < n := Nat.lt_trans (Nat.lt_succ_self 0) $ Nat.lt_trans (Nat.lt_succ_self 1) h₁ +have h₃ : 0 < leftLen heap h₂ := heapUpdateRootPossibleRootValuesAuxL heap $ Nat.lt_trans (Nat.lt_succ_self 1) h₁ +have h₄ : 0 < rightLen heap h₂ := heapUpdateRootPossibleRootValuesAuxR heap h₁ +(heap.heapUpdateRoot le value h₂).fst.root h₂ = value +∨ (heap.heapUpdateRoot le value h₂).fst.root h₂ = (heap.left h₂).root h₃ +∨ (heap.heapUpdateRoot le value h₂).fst.root h₂ = (heap.right h₂).root h₄ +:= by + simp only + unfold heapUpdateRoot + generalize (Nat.lt_trans (Nat.lt_succ_self 0) (Nat.lt_trans (Nat.lt_succ_self 1) h₁) : 0 < n) = h₂ + split + rename_i o p v l r h₃ h₄ h₅ h₂ + cases o + case zero => simp only[root, true_or] + case succ oo => + have h₆ : p ≠ 0 := by simp at h₁; omega + simp only [Nat.add_one_ne_zero, ↓reduceDite, h₆] + cases le value (l.root _) <;> simp + rotate_right + cases le value (r.root _) <;> simp + case true.true => simp[root] + case false | true.false => + cases le (l.root _) (r.root _) + <;> simp only [Bool.false_eq_true, ↓reduceIte, heapUpdateRootReturnsRoot, root_unfold, left_unfold, right_unfold, true_or, or_true] + +protected theorem heapUpdateRootIsHeapLeRootAux {α : Type u} (le : α → α → Bool) (value : α) (heap : CompleteTree α n) (h₁ : HeapPredicate heap le) (h₂ : n > 0) (h₃ : le (root heap h₂) value) : HeapPredicate.leOrLeaf le (root heap h₂) (heapUpdateRoot le value heap h₂).fst := + if h₄ : n = 1 then by + have h₅ : le (heap.root h₂) ( (heapUpdateRoot le value heap h₂).fst.root h₂) := by simp only[h₃, h₄, heapUpdateRootPossibleRootValues1] + unfold HeapPredicate.leOrLeaf + split + · rfl + · exact h₅ + else if h₅ : n = 2 then by + have h₆ := heapUpdateRootPossibleRootValues2 le value heap h₅ + cases h₆ + case inl h₆ => + have h₇ : le (heap.root h₂) ( (heapUpdateRoot le value heap h₂).fst.root h₂) := by simp only [h₆, h₃] + unfold HeapPredicate.leOrLeaf + split + · rfl + · exact h₇ + case inr h₆ => + unfold HeapPredicate.leOrLeaf + unfold HeapPredicate at h₁ + split at h₁ + case h_1 => contradiction + case h_2 o p v l r h₇ h₈ h₉ => + have h₁₁ : p = 0 := by + simp at h₅ + cases o; simp only [Nat.le_zero_eq] at h₇; exact h₇; simp_arith[Nat.add_eq_zero] at h₅; exact h₅.right + have h₁₀ : o = 1 := by simp_arith[h₁₁] at h₅; assumption + simp only + rw[h₆] + have h₁₂ := h₁.right.right.left + unfold HeapPredicate.leOrLeaf at h₁₂ + cases o ; contradiction; + case succ => + exact h₁₂ + else by + have h₆ : n > 2 := by omega + have h₇ := heapUpdateRootPossibleRootValues3 le value heap h₆ + simp at h₇ + unfold HeapPredicate at h₁ + cases h₇ + case inl h₇ => + have h₈ : le (heap.root h₂) ( (heapUpdateRoot le value heap h₂).fst.root h₂) := by simp only [h₇, h₃] + unfold HeapPredicate.leOrLeaf + split + · rfl + · exact h₈ + case inr h₇ => + cases h₇ + case inl h₇ | inr h₇ => + unfold HeapPredicate.leOrLeaf + split at h₁ + contradiction + simp_all + case h_2 o p v l r _ _ _ => + cases o + omega + cases p + omega + have h₈ := h₁.right.right.left + have h₉ := h₁.right.right.right + assumption + +private theorem heapUpdateRootIsHeapLeRootAuxLe {α : Type u} (le : α → α → Bool) {a b c : α} (h₁ : transitive_le le) (h₂ : total_le le) (h₃ : le b c) : ¬le a c ∨ ¬ le a b → le b a +| .inr h₅ => not_le_imp_le h₂ _ _ h₅ +| .inl h₅ => h₁ b c a ⟨h₃,not_le_imp_le h₂ _ _ h₅⟩ + +theorem heapUpdateRootIsHeap {α : Type u} {n: Nat} (le : α → α → Bool) (value : α) (heap : CompleteTree α n) (h₁ : n > 0) (h₂ : HeapPredicate heap le) (h₃ : transitive_le le) (h₄ : total_le le) : HeapPredicate (heap.heapUpdateRoot le value h₁).fst le := by + unfold heapUpdateRoot + split + rename_i o p v l r h₇ h₈ h₉ heq + exact + if h₁₀ : o = 0 then by + simp only [Nat.add_eq, Nat.succ_eq_add_one, h₁₀, ↓reduceDite] + unfold HeapPredicate at h₂ ⊢ + simp only [h₂, true_and] + unfold HeapPredicate.leOrLeaf + have : p = 0 := by rw[h₁₀, Nat.le_zero_eq] at h₇; assumption + apply And.intro + case left => match o, l with + | Nat.zero, _ => trivial + case right => match p, r with + | Nat.zero, _ => trivial + else if h₁₁ : p = 0 then by + simp only [↓reduceDite, h₁₀, h₁₁] + cases h₉ : le value (root l (_ : 0 < o)) <;> simp + case true => + unfold HeapPredicate at * + simp only [h₂, true_and] + unfold HeapPredicate.leOrLeaf + apply And.intro + case right => match p, r with + | Nat.zero, _ => trivial + case left => match o, l with + | Nat.succ _, _ => assumption + case false => + rw[heapUpdateRootReturnsRoot] + have h₁₂ : le (l.root (Nat.zero_lt_of_ne_zero h₁₀)) value := by simp[h₉, h₄, not_le_imp_le] + have h₁₃ : o = 1 := Nat.le_antisymm (by simp_arith[h₁₁] at h₈; exact h₈) (Nat.succ_le_of_lt (Nat.zero_lt_of_ne_zero h₁₀)) + unfold HeapPredicate at * + simp only [h₂, true_and] --closes one sub-goal + apply And.intro <;> try apply And.intro + case right.right => match p, r with + | 0, .leaf => simp[HeapPredicate.leOrLeaf] + case right.left => + simp only [HeapPredicate.leOrLeaf] + cases o <;> simp only [Nat.succ_eq_add_one, heapUpdateRootPossibleRootValues1, h₁₃, h₁₂] + case left => + apply heapUpdateRootIsHeap + exact h₂.left + exact h₃ + exact h₄ + else if h₁₂ : le value (root l (Nat.zero_lt_of_ne_zero h₁₀)) ∧ le value (root r (Nat.zero_lt_of_ne_zero h₁₁)) then by + unfold HeapPredicate at * + simp only [↓reduceDite, and_self, ↓reduceIte, true_and, h₁₀, h₁₁, h₁₂, h₂] + unfold HeapPredicate.leOrLeaf + cases o + · contradiction + · cases p + · contradiction + · assumption + else by + simp only [↓reduceDite, ↓reduceIte, h₁₀, h₁₁, h₁₂] + have h₁₃ : ¬le value (root l _) ∨ ¬le value (root r _) := (Decidable.not_and_iff_or_not (le value (root l (Nat.zero_lt_of_ne_zero h₁₀)) = true) (le value (root r (Nat.zero_lt_of_ne_zero h₁₁)) = true)).mp h₁₂ + cases h₁₄ : le (root l (_ : 0 < o)) (root r (_ : 0 < p)) + <;> simp only [Bool.false_eq_true, ↓reduceIte] + <;> unfold HeapPredicate at * + <;> simp only [true_and, h₂] + <;> apply And.intro + <;> try apply And.intro + case false.left | true.left => + apply heapUpdateRootIsHeap + <;> simp only [h₂, h₃, h₄] + case false.right.left => + unfold HeapPredicate.leOrLeaf + have h₁₅ : le (r.root _) (l.root _) = true := not_le_imp_le h₄ (l.root _) (r.root _) $ (Bool.not_eq_true $ le (root l (_ : 0 < o)) (root r (_ : 0 < p))).substr h₁₄ + simp only[heapUpdateRootReturnsRoot] + cases o <;> simp only[h₁₅] + case true.right.right => + unfold HeapPredicate.leOrLeaf + simp only[heapUpdateRootReturnsRoot] + cases p <;> simp only[h₁₄] + case false.right.right => + have h₁₅ : le (r.root _) (l.root _) = true := not_le_imp_le h₄ (l.root _) (r.root _) $ (Bool.not_eq_true $ le (root l (_ : 0 < o)) (root r (_ : 0 < p))).substr h₁₄ + have h₁₆ : le (r.root _) value := heapUpdateRootIsHeapLeRootAuxLe le h₃ h₄ h₁₅ h₁₃ + simp only [heapUpdateRootReturnsRoot, CompleteTree.heapUpdateRootIsHeapLeRootAux, h₂, h₁₆] + case true.right.left => + have h₁₆ : le (l.root _) value := heapUpdateRootIsHeapLeRootAuxLe le h₃ h₄ h₁₄ h₁₃.symm + simp only [heapUpdateRootReturnsRoot, CompleteTree.heapUpdateRootIsHeapLeRootAux, h₂, h₁₆] |
