diff options
| author | Andreas Grois <andi@grois.info> | 2024-08-19 22:45:41 +0200 | 
|---|---|---|
| committer | Andreas Grois <andi@grois.info> | 2024-08-19 22:45:41 +0200 | 
| commit | 7d5df252a6e885f8b1ffab49196e0a4cc4b0131a (patch) | |
| tree | 85dc147fcd886ae169b7b82f65824f1fce7a7b05 | |
| parent | c52a36a1ae9bb5e661a4c689a05d8ebcefcc704c (diff) | |
heapUpdateAtOnlyUpdatesAt
| -rw-r--r-- | BinaryHeap/CompleteTree/AdditionalProofs/HeapUpdateAt.lean | 135 | ||||
| -rw-r--r-- | BinaryHeap/CompleteTree/HeapProofs/HeapUpdateAt.lean | 1 | ||||
| -rw-r--r-- | BinaryHeap/CompleteTree/NatLemmas.lean | 28 | ||||
| -rw-r--r-- | TODO | 8 | 
4 files changed, 167 insertions, 5 deletions
diff --git a/BinaryHeap/CompleteTree/AdditionalProofs/HeapUpdateAt.lean b/BinaryHeap/CompleteTree/AdditionalProofs/HeapUpdateAt.lean index 10364d3..7dbe23d 100644 --- a/BinaryHeap/CompleteTree/AdditionalProofs/HeapUpdateAt.lean +++ b/BinaryHeap/CompleteTree/AdditionalProofs/HeapUpdateAt.lean @@ -25,7 +25,7 @@ theorem heapUpdateAtReturnsElementAt {α : Type u} {n : Nat} (le : α → α →      case isTrue h => simp only [←hj, beq_iff_eq, Fin.mk.injEq, Nat.add_one_ne_zero] at h --contradiction      case isFalse =>        split -      subst hj +      subst hj -- and put it back, now that split succeeded.        simp only [Nat.add_eq, Nat.succ_eq_add_one, Nat.pred_succ]        split <;> simp only        case isTrue h₂ => @@ -41,3 +41,136 @@ theorem heapUpdateAtReturnsElementAt {α : Type u} {n : Nat} (le : α → α →            simp only [Nat.not_le] at h₂            simp only [leftLen_unfold, gt_iff_lt, h₂]          apply heapUpdateAtReturnsElementAt + +theorem heapUpdatAtRootEqUpdateRoot {α : Type u} {le : α → α → Bool} : CompleteTree.heapUpdateAt le ⟨0, h₁⟩ = CompleteTree.heapUpdateRoot le := by +  funext +  unfold heapUpdateAt +  rfl + +theorem heapUpdateAtContainsValue {α : Type u} {n : Nat} (le : α → α → Bool) (heap : CompleteTree α n) (h₁ : n > 0) (value : α) (index : Fin n) : (heap.heapUpdateAt le index value h₁).fst.contains value := by +  unfold heapUpdateAt +  split +  case isTrue h₂ => +    apply heapUpdateRootContainsUpdatedElement +  case isFalse h₂ => +    split +    rename_i o p v l r _ _ _ index h₁ h₂ +    cases le v value <;> dsimp +    case false => +      split +      <;> rewrite[contains_as_root_left_right _ _ (Nat.succ_pos _)] +      <;> left +      <;> rfl +    case true => +      split +      <;> rewrite[contains_as_root_left_right _ _ (Nat.succ_pos _)] +      <;> right +      case' isTrue => +        have : o < o+p+1 := Nat.lt_of_le_of_lt (Nat.le_add_right o p) (Nat.lt_succ_self (o+p)) --term +        left +        rewrite[left_unfold] +      case' isFalse => +        have : p < o+p+1 := Nat.lt_of_le_of_lt (Nat.le_add_left p o) (Nat.lt_succ_self (o+p)) --term +        right +        rewrite[right_unfold] +      all_goals +        apply heapUpdateAtContainsValue +termination_by n + +theorem heapUpdateAtOnlyUpdatesAt {α : Type u} {n : Nat} (le : α → α → Bool) (val : α) (heap : CompleteTree α n) (updateIndex : Fin n) (otherIndex : Fin n) (h₁ : n > 0) (h₂ : updateIndex ≠ otherIndex) : (heap.heapUpdateAt le updateIndex val h₁).fst.contains $ heap.get otherIndex h₁ := +  if h₃ : updateIndex = ⟨0, h₁⟩ then +    have h₄ : otherIndex ≠ ⟨0, h₁⟩ := h₃.subst h₂.symm +    heapUpdateRootOnlyUpdatesRoot le heap h₁ otherIndex h₄ val +    |> heapUpdatAtRootEqUpdateRoot.substr (p := λx↦(x val heap h₁).fst.contains (heap.get otherIndex h₁)) +    |> h₃.substr (p := λx↦((heap.heapUpdateAt le x val h₁).fst.contains $ heap.get otherIndex h₁)) +  else if h₄ : otherIndex = ⟨0, h₁⟩ then by +    subst h₄ +    rw[←get_zero_eq_root] +    unfold heapUpdateAt +    --cannot use h₃ here already - it makes split fail. So, splitting twice it is... +    split +    case isTrue h => exact absurd ((beq_iff_eq _ _).mp h) h₃ +    split +    rename_i d1 d2 d3 d4 d5 o p v l r _ _ _ updateIndex _ _ +    clear d1 d2 d3 d4 d5 +    cases le v val <;> dsimp +    case isFalse.true => +      -- v ≤ val -> current root smaller or equal, keep current root, move val down. +      split +      <;> simp only [gt_iff_lt, Nat.zero_lt_succ, contains_as_root_left_right] +      <;> left +      <;> rewrite[root_unfold] +      <;> rw[root_unfold] +    case isFalse.false => +      -- v > val -> repace current root by val, move current root down. +      split +      <;> simp only [gt_iff_lt, Nat.zero_lt_succ, contains_as_root_left_right] +      <;> right +      case' isTrue => +        left +        rewrite[left_unfold] +      case' isFalse => +        right +        rewrite[right_unfold] +      all_goals +        rewrite[root_unfold] +        apply heapUpdateAtContainsValue +  else by +    unfold heapUpdateAt +    split +    case isTrue hx => exact absurd ((beq_iff_eq _ _).mp hx) h₃ +    case isFalse => +      split +      rename_i d1 d2 d3 d4 d5 o p v l r olep mhd stc index _ _ +      clear d1 d2 d3 d4 d5 +      cases le v val +      <;> dsimp +      -- here we don'treally care if v or val gets handed down. We recurse in any case. +      -- we do care about the question if we go left or right though. +      <;> split +      all_goals +        have h₄₂ : otherIndex > 0 := Fin.pos_iff_ne_zero.mpr h₄ +        rw[contains_as_root_left_right _ _ (Nat.succ_pos _)] +        right +      case false.isTrue h₅ | true.isTrue h₅ => +        if h₆ : otherIndex ≤ o then +          have : otherIndex ≤ (branch v l r olep mhd stc).leftLen (Nat.succ_pos _) := by simp only [leftLen_unfold, h₆] +          rw[get_left _ _ (Nat.succ_pos _) h₄₂ this] +          left +          --rw[left_unfold] +          have : o < o + p + 1 := Nat.lt_of_le_of_lt (Nat.le_add_right o p) (Nat.lt_succ_self (o+p)) +          apply heapUpdateAtOnlyUpdatesAt +          simp only [ne_eq, Fin.mk.injEq] +          exact (Nat.pred_ne_of_ne (Fin.pos_iff_ne_zero.mpr h₃) (Fin.pos_iff_ne_zero.mpr h₄)).mp $ Fin.val_ne_iff.mpr h₂ +        else +          have : otherIndex > (branch v l r olep mhd stc).leftLen (Nat.succ_pos _) := by rw[leftLen_unfold]; exact Nat.gt_of_not_le h₆ +          rw[get_right _ _ (Nat.succ_pos _) this] +          right +          --rw[right_unfold] +          --rw[right_unfold] +          simp only[leftLen_unfold] +          rw[contains_iff_index_exists] +          generalize (⟨↑otherIndex - o - 1, _⟩ : Fin _) = solution -- Allows to skip the annoying proof that Lean already has... +          exists solution --also solves h.h₁ goal? Okay, I don't know why, but I won't complain. +      case false.isFalse h₅ | true.isFalse h₅ => +        if h₆ : otherIndex ≤ o then +          have : otherIndex ≤ (branch v l r olep mhd stc).leftLen (Nat.succ_pos _) := by simp only [leftLen_unfold, h₆] +          rw[get_left _ _ (Nat.succ_pos _) h₄₂ this] +          left +          --rw[left_unfold] +          --rw[left_unfold] +          rw[contains_iff_index_exists] +          generalize (⟨↑otherIndex - 1, _⟩ : Fin _) = solution +          exists solution +        else +          have h₆ : otherIndex > (branch v l r olep mhd stc).leftLen (Nat.succ_pos _) := by rw[leftLen_unfold]; exact Nat.gt_of_not_le h₆ +          rw[get_right _ _ (Nat.succ_pos _) h₆] +          right +          --rw[right_unfold] +          have : p < o + p + 1 := Nat.lt_of_le_of_lt (Nat.le_add_left p o) (Nat.lt_succ_self (o+p)) +          apply heapUpdateAtOnlyUpdatesAt +          simp only [ne_eq, Fin.mk.injEq] +          --rw[leftLen_unfold] +          have h₅ : index.val ≥ o + 1 := Nat.gt_of_not_le h₅ +          exact (Nat.sub_ne_of_ne h₅ h₆).mp $ Fin.val_ne_iff.mpr h₂ +termination_by n diff --git a/BinaryHeap/CompleteTree/HeapProofs/HeapUpdateAt.lean b/BinaryHeap/CompleteTree/HeapProofs/HeapUpdateAt.lean index b50d8c5..295fcbd 100644 --- a/BinaryHeap/CompleteTree/HeapProofs/HeapUpdateAt.lean +++ b/BinaryHeap/CompleteTree/HeapProofs/HeapUpdateAt.lean @@ -1,5 +1,6 @@  import BinaryHeap.CompleteTree.HeapOperations  import BinaryHeap.CompleteTree.Lemmas +import BinaryHeap.CompleteTree.NatLemmas  import BinaryHeap.CompleteTree.HeapProofs.HeapUpdateRoot  namespace BinaryHeap.CompleteTree diff --git a/BinaryHeap/CompleteTree/NatLemmas.lean b/BinaryHeap/CompleteTree/NatLemmas.lean index 5733b21..d05fe50 100644 --- a/BinaryHeap/CompleteTree/NatLemmas.lean +++ b/BinaryHeap/CompleteTree/NatLemmas.lean @@ -190,3 +190,31 @@ theorem lt_of_add {a b c : Nat} : a + b < c → a < c ∧ b < c := by      exact lt_of_add_left h₁    case right =>      exact lt_of_add_right h₁ + +theorem pred_ne_of_ne {a b : Nat} (h₁ : a > 0) (h₂ : b > 0) : a ≠ b ↔ a - 1 ≠ b - 1 := +  Iff.intro +    (λh₃ h₄ ↦ +      congrArg Nat.succ h₄ +      |> (Nat.succ_pred (Nat.ne_of_gt h₁)).subst (motive := λx ↦ x = b.pred.succ) +      |> (Nat.succ_pred (Nat.ne_of_gt h₂)).subst +      |> flip absurd h₃ +    ) +    (λh₃ h₄ ↦ +      h₄ +      |> (Nat.succ_pred (Nat.ne_of_gt h₁)).substr +      |> (Nat.succ_pred (Nat.ne_of_gt h₂)).substr +      |> Nat.succ.inj +      |> flip absurd h₃ +    ) + +theorem sub_ne_of_ne {a b c : Nat} (h₁ : a ≥ c) (h₂ : b ≥ c) : a ≠ b ↔ a - c ≠ b - c := by +  induction c +  case zero => rfl +  case succ cc hc => +    rw[←Nat.sub_sub] +    rw[←Nat.sub_sub] +    have h₃ := (Nat.lt_of_succ_le h₁) +    have h₄ := (Nat.lt_of_succ_le h₂) +    have h₅ := hc (Nat.le_of_lt h₃) (Nat.le_of_lt h₄) +    rw[h₅] +    apply pred_ne_of_ne (Nat.sub_pos_of_lt h₃) (Nat.sub_pos_of_lt h₄) @@ -15,14 +15,14 @@ This is a rough outline of upcoming tasks:  [x] Prove that heapPop leaves all values in the tree, except the root.      - Current proof is not rigorous. Needs more work in the future.  [x] Prove that heapPop returns the root -[ ] Prove that CompleteTree.heapUpdateAt returns the element at the given index -[ ] Prove that CompleteTree.heapUpdateAt indeed updates the value at the given index. +[x] Prove that CompleteTree.heapUpdateAt returns the element at the given index +[x] Prove that CompleteTree.heapUpdateAt indeed updates the value at the given index.      - Use the same approach as heapUpdateRoot  [ ] Prove that CompleteTree.heapRemoveAt returns the element at the given index  [ ] Prove that CompleteTree.heapRemoveAt leaves all values in the tree except at the input index. -Stuff below is not scheduled to happen any time soon. +Stuff below is not scheduled to happen any time soon. Feel free to contribute though.  [ ] Make proofs that currently aren't rigorous rigorous. -    - For instance by using element counts instead of just contains. +    - For instance by using element counts instead of contains.  [ ] Write the performance part of this file.
\ No newline at end of file  | 
