import Huffman.HfmnTree_uniqueness variable {α : Type} [DecidableEq α] [Inhabited α] [Ord α] [HfmnType α] instance [Inhabited α] [DecidableEq α] : HfmnType α where default := default /- Check is a vertex is Leaf or not -/ @[simp, grind .] def Vertex.isLeaf (v : Vertex) : Bool := match v with | Vertex.Leaf _ => true | Vertex.Node _ => false /- This function returns the list of vertices of a Huffman tree that are leaves. -/ @[simp, grind .] def HfmnTree.leaves (t : HfmnTree α) (code : BoolList) : List Vertex := (t.vertices code).filter (fun v => v.isLeaf) -- #eval HfmnTree.leaves (HfmnTree.tree eg₁) [] /- * Theorem: All leaves of a Huffman tree are unique. Directly follows from `all_codes_distinct`. -/ theorem HfmnTree.all_leaves_distinct (t : HfmnTree α) (c : BoolList) : (t.leaves c).Pairwise (fun v₁ v₂ => v₁.code ≠ v₂.code) := by simp [leaves] exact (HfmnTree.all_codes_distinct t c).filter _ /- Check if 2 BoolEncList are prefix free of each other. -/ def checkPrefixfree (bl₁ bl₂: BoolList) : Bool := ¬List.isPrefixOf bl₁ bl₂ ∧ ¬ List.isPrefixOf bl₂ bl₁ -- #eval checkPrefixfree [true, false, false] [true, false] -- false @[simp, grind .] lemma List.eq_suff_eq_len ( c: BoolList) : (c ++ [true]).length = (c ++ [false]).length := by grind /- * Lemma - Two lists of equal length and prefix of the same list are equal. -/ lemma List.prefix_eqlen_eq_n (n : ℕ) : ∀ (l₁ l₂ bl : BoolList), l₁.length = n → l₂.length = n → l₁.isPrefixOf bl → l₂.isPrefixOf bl → l₁ = l₂ := by induction n with | zero => intro l₁ l₂ bl hlength₁ hlength₂ hpref₁ hpref₂ rw [length_eq_zero_iff] at hlength₁ hlength₂ grind | succ m ih => intro l₁ l₂ bl hlength₁ hlength₂ hpref₁ hpref₂ match bl with | [] => simp_all | b :: bs => match l₁, l₂ with | [], _ => simp at hlength₁ | _, [] => simp at hlength₂ | a₁ :: as₁, a₂ :: as₂ => grind /- * Lemma - Two lists of equal length and prefix of the same list are equal. Simplified version of the above lemma. -/ lemma List.prefix_eqlen_eq (l₁ l₂ bl : BoolList) : l₁.length = l₂.length → l₁.isPrefixOf bl → l₂.isPrefixOf bl → l₁ = l₂ := by have h := prefix_eqlen_eq_n l₁.length l₁ l₂ bl grind /- * Theorem: The Huffman tree is prefix-free. -/ theorem HfmnTree.hfmntree_is_prefix_free (t : HfmnTree α) (c : BoolList) : (t.vertices c).Pairwise (fun v₁ v₂ => v₁.isLeaf → v₂.isLeaf → checkPrefixfree v₁.code v₂.code) := by induction p:t with | Leaf _ _ => exact List.pwFilter_eq_self.mp rfl | Node l r => simp [vertices] let cL := c ++ [false] let cR := c ++ [true] let pl := HfmnTree.hfmntree_is_prefix_free l cL let pr := HfmnTree.hfmntree_is_prefix_free r cR apply List.pairwise_append.2 constructor case left => exact pl case right => constructor · exact pr · intro v₁ hv₁ v₂ hv₂ vl₁ vl₂ unfold checkPrefixfree simp only [List.isPrefixOf_iff_prefix, Bool.decide_and, decide_not, Bool.and_eq_true, Bool.not_eq_eq_eq_not, Bool.not_true, decide_eq_false_iff_not] have pr₁: (c++ [false]).isPrefixOf v₁.code := by exact initialCodeIsPrefix l cL v₁ hv₁ have pr₂: (c++ [true]).isPrefixOf v₂.code := by exact initialCodeIsPrefix r cR v₂ hv₂ have cleq : cL.length = cR.length := by exact Eq.symm (List.eq_suff_eq_len c) have cneq : ¬ cL = cR := by unfold cL cR simp only [List.append_cancel_left_eq, List.cons.injEq, Bool.false_eq_true, and_true, not_false_eq_true] constructor · intro h₁ have h' : (c ++ [false]).isPrefixOf v₂.code := by simp_all exact List.IsPrefix.trans pr₁ h₁ have ceq : cL = cR := by exact List.prefix_eqlen_eq cL cR v₂.code cleq h' pr₂ contradiction · intro h₂ have h' : (c ++ [true]).isPrefixOf v₁.code := by simp_all exact List.IsPrefix.trans pr₂ h₂ have ceq : cL = cR := by exact List.prefix_eqlen_eq cL cR v₁.code cleq pr₁ h' contradiction