From 24d4c1c62df7104cfeaddc98e6035f9fc5a29650 Mon Sep 17 00:00:00 2001 From: Haitian Date: Wed, 15 May 2024 13:04:07 +0200 Subject: [PATCH 01/32] add Order.lean --- Mathlib/Data/Multiset/Order.lean | 605 +++++++++++++++++++++++++++++++ 1 file changed, 605 insertions(+) create mode 100644 Mathlib/Data/Multiset/Order.lean diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean new file mode 100644 index 0000000000000..2500f369ad385 --- /dev/null +++ b/Mathlib/Data/Multiset/Order.lean @@ -0,0 +1,605 @@ +/- +Copyright (c) 2024 Haitian Wang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Author: Haitian Wang, Malvin Gattinger. +-/ +import Mathlib.Tactic.Linarith +import Mathlib.Data.Multiset.Basic +import Mathlib.Logic.Relation + +/-! +# Dershowitz-Manna ordering + +In this file we define the _Dershowitz-Manna ordering_ on multisets. +We prove that, given a well-founded partial order on the underlying set, +the Dershowitz-Manna ordering defined over multisets is also well-founded. + +## Main results + +- `MultisetLT` : the standard definition +- `dm_wf` : the main theorem about the `Dershowitz-Manna ordering`. +- `Lt_LT_equiv` : two definitions of the Dershowitz-Manna ordering are equivalent. + +## References + +* [Wikipedia, Dershowitz–Manna ordering*](https://en.wikipedia.org/wiki/Dershowitz%E2%80%93Manna_ordering) + +* [CoLoR](https://github.com/fblanqui/color), a Coq library on rewriting theory and termination. + Our code here is inspired by their version of called `mOrd_wf` in the file + [MultisetList.v](https://github.com/fblanqui/color/blob/1.8.5/Util/Multiset/MultisetList.v). + +-/ + +variable {α : Type*} + +inductive MultisetLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := + | MLT : ∀ (X Y Z: Multiset α), + Y ≠ ∅ → + M = Z + X → + N = Z + Y → + (∀ x ∈ X, ∃ y ∈ Y, x < y) → MultisetLT M N + +inductive MultisetRedLt [DecidableEq α][LT α] (M N : Multiset α) : Prop := + | RedLt : ∀ (X Y:Multiset α) (a : α) , + (M = X + Y) → + (N = X + {a}) → + (∀ y, y ∈ Y → y < a) → MultisetRedLt M N + +/-- MultisetLt is the transitive closure of MultisetRedLt -/ +def MultisetLt [DecidableEq α][LT α] : Multiset α → Multiset α → Prop := TC MultisetRedLt +def AccM_1 [DecidableEq α][Preorder α] : Multiset α → Prop := Acc MultisetRedLt + +-- Some useful lemmas about Multisets and the defined relations +lemma not_MultisetRedLt_0 [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedLt M 0 := by + intro h + cases h with + | RedLt X Y a M nonsense _ => + have contra : a ∈ (0 : Multiset α):= by + rw [nonsense] + simp_all only [Multiset.mem_add, Multiset.mem_singleton, or_true] + contradiction + +lemma meq_union_meq_reverse [DecidableEq α] [Preorder α] {M N P : Multiset α} + (_ : M = N) : M + P = N + P := by + simp_all only + +lemma mul_cons_trivial [DecidableEq α] [LT α] {a : α} {M : Multiset α} : + M + {a} = a ::ₘ M := by + intros + ext + simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] + +lemma mul_erase_trivial [DecidableEq α] [LT α] {a : α} {M : Multiset α} : + M - {a} = Multiset.erase M a := by + intros + ext + simp [Multiset.erase_singleton] + simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] + aesop -- Ask Malvin: Should I really replace all the aesops? + +lemma mul_mem_not_erase [DecidableEq α] [LT α] {a a0: α} {M X : Multiset α} + (H : M = Multiset.erase (a0 ::ₘ X) a) (hyp : ¬ a = a0) : a0 ∈ M := by + rw [H] + have : a0 ∈ Multiset.erase (a0 ::ₘ X) a ↔ a0 ∈ (a0 ::ₘ X) := by + apply Multiset.mem_erase_of_ne + aesop + rw [this] + aesop + +lemma mem_erase_cons [DecidableEq α] [LT α] {a0: α} {M : Multiset α} (_ : a0 ∈ M) : + M = M - {a0} + {a0} := by + simp_all [mul_cons_trivial, mul_erase_trivial, Multiset.cons_erase] + +lemma neq_erase [DecidableEq α] [LT α] {a a0: α} (M : Multiset α)(_ : a0 ≠ a) : + Multiset.count a0 (Multiset.erase M a) = Multiset.count a0 M := by + have : Multiset.count a0 (a ::ₘ (Multiset.erase M a)) = Multiset.count a0 (a ::ₘ M) := by simp_all + simp_all + +lemma cons_erase [DecidableEq α] [LT α] {a a0: α} {M X : Multiset α} + (H : a ::ₘ M = X + {a0}) : M = X + {a0} - {a} := by + if hyp : a = a0 then + simp [mul_cons_trivial, mul_erase_trivial] at * + aesop + else + have a0_a: a0 ≠ a := by rw [eq_comm] at hyp; exact hyp + ext b + simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] + have H : Multiset.count b (a ::ₘ M) = Multiset.count b (X + {a0}) := by aesop + if ba : b = a then + rw [ba] + rw [ba] at H + have : a ∈ X + {a0} := by + by_contra h + have absurd3 : Multiset.count a (a ::ₘ M) > 0 := by simp + aesop + have : Multiset.count a (a ::ₘ M) = Multiset.count a M + 1 := by simp + have : Multiset.count a (a0 ::ₘ X) = Multiset.count a (Multiset.erase (a0 ::ₘ X) a) + 1 := by simp ; aesop + aesop + else if ba0 : b = a0 then + rw [ba0] + rw [ba0] at H + have : Multiset.count a0 (Multiset.erase (a ::ₘ M) a) = Multiset.count a0 (Multiset.erase (a ::ₘ M) a) := by + simp + have : Multiset.count a0 (a ::ₘ M) = Multiset.count a0 X + 1 := by subst_eqs; rw [mul_cons_trivial] at H; simp_all + have : Multiset.count a0 M = Multiset.count a0 (a ::ₘ M) := by + have : a0 ≠ a := by simp_all + rw [Multiset.count_cons_of_ne this M] + simp_all + -- have : Multiset.count a0 (a ::ₘ M) = Multiset.count a0 M := by simp_all + else + have : Multiset.count b M = Multiset.count b (a ::ₘ M) := by + have : b ≠ a := by simp_all + -- have : ∀s, Multiset.count a s = Multiset.count a (b ::ₘ s) := by + rw [Multiset.count_cons_of_ne this M] + rw [this ] + have : Multiset.count b (X + {a0}) = Multiset.count b (Multiset.erase (a0 ::ₘ X) a) := by + simp + simp_all + simp_all + +lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} + (H : MultisetRedLt N (a ::ₘ M)) : + ∃ (M' : Multiset α), + N = (a ::ₘ M') ∧ (MultisetRedLt M' M) + ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by + rcases H with ⟨X, Y, a0, H1, H0, H2⟩ + -- cases h : (decide (a = a0)) + if hyp : a = a0 then + exists Y; right; apply And.intro + . rw [H1] + rw [add_left_inj] + rw [mul_cons_trivial] at H0 + simp_all + . simp_all + else + exists (Y + (M - {a0})) + left + constructor --; apply And.intro + . rw [H1] + have : X = (M - {a0} + {a}) := by + simp [mul_cons_trivial] at * + ext b + rw [Multiset.count_cons] + simp [Multiset.ext, Multiset.count_cons] at H0 + if h : b = a then + rw [h] + have := H0 b + aesop + else + have := H0 b + simp [mul_erase_trivial] + aesop + subst this + rw [add_comm,mul_cons_trivial] + aesop + . constructor + · change Y + (M - {a0}) = (M - {a0}) + Y + rw [add_comm] + · change M = M - {a0} + {a0} + have this0: M = X + {a0} - {a} := by apply cons_erase ; exact H0 + have a0M: a0 ∈ M := by + apply mul_mem_not_erase + . change M = Multiset.erase (a0 ::ₘ X) a + rw [mul_erase_trivial] at this0 + rw [mul_cons_trivial] at this0 + exact this0 + . exact hyp + apply mem_erase_cons + . exact a0M + exact H2 + +lemma mord_wf_1 {_ : Multiset α} [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) + (H1 : ∀ b (M : Multiset α), LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) + (H2 : AccM_1 M0) + (H3 : ∀ M, MultisetRedLt M M0 → AccM_1 (a ::ₘ M)) : + AccM_1 (a ::ₘ M0) := by + constructor + intros N N_lt + change AccM_1 N + rcases (red_insert N_lt) with ⟨x, H, H0⟩ + case h.intro.inr h => + rcases h with ⟨H, H0⟩ + rw [H] + clear H --It is weird that removing this line cause aesop to not be able to prove it. Even though it reports after `exhaustive` search? + induction x using Multiset.induction with + | empty => + simpa + | cons h => + rename_i _ _ a0 M + have trivial: M0 + a0 ::ₘ M = a0 ::ₘ (M0 + M) := by simp + rw [trivial] + simp_all + case h.intro.inl.intro => + simp_all + +lemma mord_wf_2 [DecidableEq α] [Preorder α] (a : α) + (H : ∀ (b : α), ∀ (M : Multiset α), LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) : + ∀ M, AccM_1 M → AccM_1 (a ::ₘ M) := by + unfold AccM_1 + intros M H0 + induction H0 with + | intro x wfH wfH2 => + apply mord_wf_1 + . simpa + . intros b x a + unfold AccM_1 + apply H + assumption + . constructor + simpa + . simpa + +lemma mord_wf_3 {_ : Multiset α} [DecidableEq α] [Preorder α] : + ∀ (a:α), Acc LT.lt a → ∀ (M : Multiset α), AccM_1 M → AccM_1 (a ::ₘ M) := by + intro w w_a + induction w_a with + | intro x _ ih => + intro M accM1 + apply @mord_wf_2 α _ _ _ _ _ accM1 + simp_all + +-- If all elements of a multiset M is accessible given the underlying relation `LT.lt`, then the multiset M is accessible given the `MultisetRedLt` relation. +-- It uses `not_MultisetRedLt_0` and `mord_wf_3` +lemma mred_acc [DecidableEq α] [Preorder α] : + ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → AccM_1 M := by + intros M wf_el + induction M using Multiset.induction_on with -- In Coq: mset_ind : forall P : Multiset -> Prop, P empty -> (forall (M : Multiset) (a : A), P M -> P (M + {{a}})) -> forall M : Multiset, P M + | empty => + constructor + intro y y_lt + absurd y_lt + apply not_MultisetRedLt_0 + | cons ih => + apply mord_wf_3 + . assumption + . apply wf_el + simp_all + . apply ih + intros + apply wf_el + simp_all + +-- If `LT.lt` is well-founded, then `MultisetRedLt` is well-founded. +-- lemma `mred_acc` needed. +lemma RedLt_wf [DecidableEq α] [Preorder α] + (wf_lt : WellFoundedLT α) : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop) := by + constructor + intros a + apply mred_acc + intros x _ + apply wf_lt.induction x + intros y h + apply Acc.intro y + assumption + +-- If `MultisetRedLt` is well-founded, then its transitive closure, namely `MultisetLt` is also well-founded. +lemma Lt_wf [DecidableEq α] [LT α] + (h : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop)) : + WellFounded (MultisetLt : Multiset α → Multiset α → Prop) := by + unfold MultisetLt + apply TC.wf + assumption + +lemma mul_geq_zero [DecidableEq α] [LT α] : ∀ (M : Multiset α), M ≥ 0 := by + intro M + simp_all only [Multiset.quot_mk_to_coe'', ge_iff_le, zero_le] + +lemma mem_leq_diff [DecidableEq α] [Preorder α] : ∀ (M N: Multiset α), N ≤ M → M = M - N + N := by + intros M N h + rw [← Multiset.union_def] + rw [Multiset.eq_union_left] + exact h + +lemma le_sub_add {α} [pre : Preorder α] [dec : DecidableEq α]: + ∀ (M N P : Multiset α) , N ≤ M → M - N + P = M + P - N := by + intro M N P h + have : M - N + P + N = M + P - N + N := by + have : M - N + P + N = M - N + N + P := by + have : M - N + P + N = M - N + (P + N) := by + apply add_assoc (M - N) + rw [this] + have : M - N + N + P = M - N + (N + P) := by apply add_assoc (M - N) + rw [this] + have : P + N = N + P := by apply add_comm P N + simp_all only [ge_iff_le] + rw [this] + have : M + P - N + N = M + P := by + have : M + P - N + N = (M + P) ∪ N := by apply Eq.refl + have : (M + P) ∪ N = M + P:= by + apply Multiset.eq_union_left + have : M ≤ M + P := by simp_all only [ge_iff_le, le_add_iff_nonneg_right, zero_le] + apply le_trans h this + simp_all only [ge_iff_le] + rw [this] + have : M - N + N = M := by + have : M = M - N + N := by + apply mem_leq_diff + exact h + rw [← this] + simp_all only [ge_iff_le] + simp_all only [ge_iff_le, add_left_inj] + +lemma le_eq_sub : ∀ (M N P Q : ℕ) , M ≤ P → M + N = P + Q → N = Q + (P - M):= by + intros M N P Q h0 h1 + have := tsub_add_cancel_of_le h0 + linarith + +lemma double_split {α} [Preorder α] [dec : DecidableEq α]: + ∀ (M N P Q: Multiset α) , M + N = P + Q → N = N ∩ Q + (P - M) := by + intros M N P Q h + ext x + rw [Multiset.count_add] + rw [Multiset.count_inter] + rw [Multiset.count_sub] + have H0 : Multiset.count x M + Multiset.count x N = Multiset.count x P + Multiset.count x Q := by + rw [Multiset.ext] at h + simp_all only [Multiset.mem_add, Multiset.count_add] + if l_u : Multiset.count x M ≤ Multiset.count x P then + have : Multiset.count x N ≥ Multiset.count x Q := by linarith + simp_all only [ge_iff_le, min_eq_right] + apply le_eq_sub (Multiset.count x M) (Multiset.count x N) (Multiset.count x P) (Multiset.count x Q) + · simp_all + · exact H0 + else + simp_all only [not_le, gt_iff_lt] + have : Multiset.count x N ≤ Multiset.count x Q := by linarith + have:= le_of_lt l_u + simp_all + +lemma in_notin_diff {α} [DecidableEq α]: + ∀ (x : α) (X Y: Multiset α) , x ∈ X → x ∉ Y → x ∈ X - Y := by + intros x X Y x_in_X x_notin_Y + have : Multiset.count x X ≥ 1 := by + rw [← Multiset.one_le_count_iff_mem] at x_in_X + exact x_in_X + have : Multiset.count x Y = 0 := by apply Multiset.count_eq_zero_of_not_mem; exact x_notin_Y + rw [← Multiset.one_le_count_iff_mem] + rw [Multiset.count_sub] + aesop + +-- `MultisetLT` is transitive. Two lemmas needed: double_split, in_notin_diff +lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: + ∀ (M N P : Multiset α) , MultisetLT N M → MultisetLT P N → MultisetLT P M := by + intros M N P LTNM LTPN + rcases LTNM with ⟨Y1, X1, Z1, X1_ne, N1_def, M1_def, Ord1⟩ + rcases LTPN with ⟨Y2, X2, Z2, _, P2_def, N2_def, Ord2⟩ + apply MultisetLT.MLT (Y2 + (Y1 - X2)) (X1 + (X2 - Y1)) (Z1 ∩ Z2) + . aesop + . rw [P2_def] + have : Z1 ∩ Z2 + (Y2 + (Y1 - X2)) = Z1 ∩ Z2 + (Y1 - X2) + Y2 := by + have : (Y2 + (Y1 - X2)) = (Y1 - X2) + Y2 := by rw [add_comm] + rw [this] + rw [add_assoc] + rw [this] + apply meq_union_meq_reverse + have : Z1 ∩ Z2 + (Y1 - X2) = Z2 ∩ Z1 + (Y1 - X2) := by + rw [Multiset.inter_comm] + rw [this] + rw [← double_split] + rw [add_comm] + rw [← N2_def] + rw [N1_def] + apply add_comm + . rw [M1_def] + have : Z1 ∩ Z2 + (X1 + (X2 - Y1)) = Z1 ∩ Z2 + (X2 - Y1) + X1 := by + have : (X1 + (X2 - Y1)) = (X2 - Y1) + X1 := by rw [add_comm] + rw [this] + rw [add_assoc] + rw [this] + apply meq_union_meq_reverse + apply double_split + rw [add_comm] + rw [← N1_def] + rw [N2_def] + apply add_comm + . intros y y_in_union + if y_in : y ∈ Y2 then + rcases (Ord2 y y_in) with ⟨x, x_in_X2, y_lt_x⟩ + if x_in : x ∈ Y1 then + rcases (Ord1 x x_in) with ⟨x', x'_in_X1, x_lt_x'⟩ + use x' + constructor + . rw [Multiset.mem_add] + constructor + exact x'_in_X1 + . exact lt_trans y_lt_x x_lt_x' + else + use x + constructor + . rw [add_comm] + rw [Multiset.mem_add] + constructor + apply in_notin_diff + exact x_in_X2 + exact x_in + . exact y_lt_x + else + have y_in : y ∈ (Y1 - X2) := by aesop + let h := (Ord1 y) + have y_in_Y1 : y ∈ Y1 := by + have : Y1 - X2 ≤ Y1 := by aesop + apply Multiset.mem_of_le + exact this + exact y_in + let _ := h y_in_Y1 + aesop + +lemma nat_not_0_not_1 : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by + intros n h0 h1 + cases n + case zero => contradiction + case succ m => + cases m + case zero => contradiction + case succ n=> + apply Nat.succ_le_succ + aesop + + lemma direct_subset_red [dec : DecidableEq α] [Preorder α] + [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (LTMN : MultisetLT M N) : + MultisetLt M N := by + -- intros M N LTXY + cases LTMN + case MLT X Y Z Y_not_empty MZX NZY h => + unfold MultisetLt + revert Z X M N + induction Y using Multiset.strongInductionOn + case ih Y IH => + intro M N X Z M_def N_def X_lt_Y + cases em (Multiset.card Y = 0) + · simp_all + cases em (Multiset.card Y = 1) + case inl hyp' hyp=> + rw [Multiset.card_eq_one] at hyp + rcases hyp with ⟨y,Y'_def⟩ + apply TC.base + rw [Y'_def] at N_def + apply @MultisetRedLt.RedLt α _ _ M N Z X y M_def N_def + simp [Y'_def] at X_lt_Y + exact X_lt_Y + case inr hyp' hyp => + have : ∃ a, a ∈ Y := by + rw [← Y.card_pos_iff_exists_mem] + cases foo : Multiset.card Y + tauto + simp + rcases this with ⟨y,claim⟩ + let newY := Y.erase y + have newY_nonEmpty : newY ≠ ∅ := by + have card_Y_ge_2 : Multiset.card Y ≥ 2 := by + apply nat_not_0_not_1 + exact hyp' + exact hyp + have : Multiset.card (Multiset.erase Y y) ≥ 1 := by + rw [Multiset.card_erase_eq_ite] + simp_all + have card_Y_g_1 : 1 < Multiset.card Y := by aesop + exact Nat.pred_le_pred card_Y_g_1 + have : 0 < Multiset.card (Multiset.erase Y y) := by aesop + rw [Multiset.card_pos] at this + aesop + have newY_sub_Y : newY < Y := by simp (config := {zetaDelta := true}); exact claim + let f : α → Multiset α := fun y' => X.filter (fun x => x < y') -- DecidableRel + let N' := Z + newY + f y + apply TC.trans + case intro.b => exact N' + -- step from N' to M + · apply IH newY newY_sub_Y newY_nonEmpty + change M = (Z + f y) + (X - f y) -- new try + · have : f y ≤ X := Multiset.filter_le (fun x => x < y) X + ext a + have count_lt := Multiset.count_le_of_le a this + rw [M_def] + simp_all + let x := Multiset.count a X + let z := Multiset.count a Z + let fx := Multiset.count a (Multiset.filter (fun x => x < y) X) + change z + x = z + fx + (x - fx) + change fx ≤ x at count_lt + have : x = fx + (x - fx) := by aesop + linarith + · have : Z + newY + f y = Z + f y + newY := by + have : newY + f y = f y + newY := by apply add_comm + have : Z + newY + f y = Z + (newY + f y) := by apply add_assoc + rw [this] + have : Z + f y + newY = Z + (f y + newY) := by apply add_assoc + rw [this] + simp (config := {zetaDelta := true}) + assumption + unfold_let N' + rw [add_assoc] + rw [add_assoc] + rw [add_comm newY (f y)] + · intro x x_in + let X_lt_Y := X_lt_Y x + have x_in_X : x ∈ X := by + have Xfy_le_X : X - f y ≤ X:= by simp (config := {zetaDelta := true}) + apply Multiset.mem_of_le Xfy_le_X + exact x_in + let X_lt_Y := X_lt_Y x_in_X + rcases X_lt_Y with ⟨t, t_in_Y, x_lt_t⟩ + use t + constructor + . if t_in_newY : t ∈ newY then + exact t_in_newY + else + exfalso + have : t = y := by + have : Y = newY + {y} := by + unfold_let newY + simp [mul_cons_trivial, Multiset.cons_erase claim] + rw [this] at t_in_Y + rw [Multiset.mem_add] at t_in_Y + have : t ∈ ( {y} : Multiset α) := by exact Or.resolve_left t_in_Y t_in_newY + rw [← Multiset.mem_singleton] + assumption + have x_in_fy : x ∈ f y := by unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ + have x_notin_Xfy : x ∉ X - f y := by + by_contra + let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') + sorry + -- have : X - f y = neg_f y := by + -- have fy_negfy_X : f y + neg_f y = X := by + -- rw [Multiset.filter_add_not] + -- have fy_le_X : f y ≤ X := Multiset.filter_le _ X + -- have : X - f y + f y = neg_f y + f y := by + -- have : X = X - f y + f y := by + -- apply mem_leq_diff + -- exact fy_le_X + -- rw [← this] + -- rw [← fy_negfy_X] + -- apply add_comm + -- rw [← fy_negfy_X]; simp + -- have x_in_neg_fy : x ∈ neg_f y := by rw [this] at x_in; exact x_in + -- subst_eqs + -- unfold_let neg_f at * + -- simp_all + exact x_notin_Xfy x_in + . exact x_lt_t + -- single step N to N' + · have : MultisetRedLt N' N := by + apply MultisetRedLt.RedLt (Z + newY) (f y) y + . rfl + . have newY_y_Y: newY + {y} = Y := by unfold_let newY; simp [mul_cons_trivial]; apply Multiset.cons_erase claim + have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc + rw [this] + rw [newY_y_Y] + exact N_def + . unfold_let f; intro z z_in; simp at z_in; exact z_in.2 + apply TC.base + exact this + +-- It uses `LT_trans`. +-- Is this gonna be hard to prove? Why does the coq proof use some other ways to prove: +-- mord_acc_mOrd_acc (Acc_homo), mOrd_acc. +lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: + (MultisetLt : Multiset α → Multiset α → Prop) = + (MultisetLT : Multiset α → Multiset α → Prop) := by + funext X Y + apply propext + constructor + · -- Lt → LT: + intros hLt + induction hLt with + | base a b hLt => + rcases hLt with ⟨Z, X, y, a_def, b_def, X_lt_y⟩ + use X + simp + simp + assumption + | trans Z W A _ _ aih bih => -- it suffices to show MultisetLT is transitive + exact LT_trans _ _ _ bih aih + · -- LT → Lt: + apply direct_subset_red + +-- If two relations are equivalent and one of them is well-founded, then the other one is also +-- well-founded. +lemma equiv_r_wf [DecidableEq α] [LT α] {r1 r2 : Multiset α → Multiset α → Prop} (h1 : WellFounded r1) + (h2: r1 = r2): WellFounded r2 := by + aesop_subst h2 + simp_all only + +-- The desired theorem. If `LT.lt` is well-founded, then `MultisetLT` is well-founded. +theorem dm_wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] + (wf_lt : WellFoundedLT α) :WellFounded (MultisetLT : Multiset α → Multiset α → Prop) := + equiv_r_wf (Lt_wf (RedLt_wf wf_lt)) Lt_LT_equiv From 1cc278431950936ea4ddd49b27b0d7db8da335f2 Mon Sep 17 00:00:00 2001 From: Malvin Gattinger Date: Wed, 12 Jun 2024 21:18:46 +0200 Subject: [PATCH 02/32] fixes for newer lean; add line to Mathlib.lean --- Mathlib.lean | 1 + Mathlib/Data/Multiset/Order.lean | 28 ++++++++++------------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/Mathlib.lean b/Mathlib.lean index 4e58a18529e1d..f791478c71b86 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2387,6 +2387,7 @@ import Mathlib.Data.Multiset.Interval import Mathlib.Data.Multiset.Lattice import Mathlib.Data.Multiset.NatAntidiagonal import Mathlib.Data.Multiset.Nodup +import Mathlib.Data.Multiset.Order import Mathlib.Data.Multiset.OrderedMonoid import Mathlib.Data.Multiset.Pi import Mathlib.Data.Multiset.Powerset diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index 2500f369ad385..b64aeabe93acb 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -205,10 +205,7 @@ lemma mord_wf_1 {_ : Multiset α} [DecidableEq α] [Preorder α] (a : α) (M0 : | empty => simpa | cons h => - rename_i _ _ a0 M - have trivial: M0 + a0 ::ₘ M = a0 ::ₘ (M0 + M) := by simp - rw [trivial] - simp_all + simp_all only [Multiset.mem_cons, or_true, implies_true, true_implies, forall_eq_or_imp, Multiset.add_cons] case h.intro.inl.intro => simp_all @@ -249,7 +246,7 @@ lemma mred_acc [DecidableEq α] [Preorder α] : intro y y_lt absurd y_lt apply not_MultisetRedLt_0 - | cons ih => + | cons _ _ ih => apply mord_wf_3 . assumption . apply wf_el @@ -435,7 +432,7 @@ lemma nat_not_0_not_1 : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by apply Nat.succ_le_succ aesop - lemma direct_subset_red [dec : DecidableEq α] [Preorder α] +lemma direct_subset_red [dec : DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (LTMN : MultisetLT M N) : MultisetLt M N := by -- intros M N LTXY @@ -466,10 +463,7 @@ lemma nat_not_0_not_1 : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by rcases this with ⟨y,claim⟩ let newY := Y.erase y have newY_nonEmpty : newY ≠ ∅ := by - have card_Y_ge_2 : Multiset.card Y ≥ 2 := by - apply nat_not_0_not_1 - exact hyp' - exact hyp + have card_Y_ge_2 : Multiset.card Y ≥ 2 := nat_not_0_not_1 _ hyp' hyp have : Multiset.card (Multiset.erase Y y) ≥ 1 := by rw [Multiset.card_erase_eq_ite] simp_all @@ -486,11 +480,11 @@ lemma nat_not_0_not_1 : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by -- step from N' to M · apply IH newY newY_sub_Y newY_nonEmpty change M = (Z + f y) + (X - f y) -- new try - · have : f y ≤ X := Multiset.filter_le (fun x => x < y) X - ext a - have count_lt := Multiset.count_le_of_le a this + · ext a + have count_lt := Multiset.count_le_of_le a (Multiset.filter_le (fun x => x < y) X) rw [M_def] - simp_all + simp_all only [Multiset.empty_eq_zero, ne_eq, Multiset.card_eq_zero, not_false_eq_true, + Multiset.count_add, Multiset.count_sub] let x := Multiset.count a X let z := Multiset.count a Z let fx := Multiset.count a (Multiset.filter (fun x => x < y) X) @@ -507,9 +501,7 @@ lemma nat_not_0_not_1 : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by simp (config := {zetaDelta := true}) assumption unfold_let N' - rw [add_assoc] - rw [add_assoc] - rw [add_comm newY (f y)] + rw [add_assoc, add_assoc, add_comm newY (f y)] · intro x x_in let X_lt_Y := X_lt_Y x have x_in_X : x ∈ X := by @@ -596,7 +588,7 @@ lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: -- well-founded. lemma equiv_r_wf [DecidableEq α] [LT α] {r1 r2 : Multiset α → Multiset α → Prop} (h1 : WellFounded r1) (h2: r1 = r2): WellFounded r2 := by - aesop_subst h2 + subst h2 simp_all only -- The desired theorem. If `LT.lt` is well-founded, then `MultisetLT` is well-founded. From ed844297d3aa7d33a3ba8848df0aa2f91800fb6b Mon Sep 17 00:00:00 2001 From: Malvin Gattinger Date: Wed, 12 Jun 2024 21:51:42 +0200 Subject: [PATCH 03/32] try to appease linter and avoid some aesops --- Mathlib/Data/Multiset/Order.lean | 229 +++++++++++++++---------------- 1 file changed, 112 insertions(+), 117 deletions(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index b64aeabe93acb..adbf6cb712a85 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2024 Haitian Wang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Author: Haitian Wang, Malvin Gattinger. +Authors: Haitian Wang, Malvin Gattinger -/ import Mathlib.Tactic.Linarith import Mathlib.Data.Multiset.Basic @@ -70,123 +70,117 @@ lemma mul_cons_trivial [DecidableEq α] [LT α] {a : α} {M : Multiset α} : simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] lemma mul_erase_trivial [DecidableEq α] [LT α] {a : α} {M : Multiset α} : - M - {a} = Multiset.erase M a := by + M - {a} = M.erase a := by intros ext simp [Multiset.erase_singleton] simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] - aesop -- Ask Malvin: Should I really replace all the aesops? + split <;> simp_all lemma mul_mem_not_erase [DecidableEq α] [LT α] {a a0: α} {M X : Multiset α} - (H : M = Multiset.erase (a0 ::ₘ X) a) (hyp : ¬ a = a0) : a0 ∈ M := by + (H : M = (a0 ::ₘ X).erase a) (hyp : ¬ a = a0) : a0 ∈ M := by rw [H] - have : a0 ∈ Multiset.erase (a0 ::ₘ X) a ↔ a0 ∈ (a0 ::ₘ X) := by + have : a0 ∈ (a0 ::ₘ X).erase a ↔ a0 ∈ (a0 ::ₘ X) := by apply Multiset.mem_erase_of_ne aesop rw [this] - aesop + simp_all lemma mem_erase_cons [DecidableEq α] [LT α] {a0: α} {M : Multiset α} (_ : a0 ∈ M) : M = M - {a0} + {a0} := by simp_all [mul_cons_trivial, mul_erase_trivial, Multiset.cons_erase] lemma neq_erase [DecidableEq α] [LT α] {a a0: α} (M : Multiset α)(_ : a0 ≠ a) : - Multiset.count a0 (Multiset.erase M a) = Multiset.count a0 M := by - have : Multiset.count a0 (a ::ₘ (Multiset.erase M a)) = Multiset.count a0 (a ::ₘ M) := by simp_all + (M.erase a).count a0 = M.count a0 := by + have : (a ::ₘ (M.erase a)).count a0 = (a ::ₘ M).count a0 := by simp_all simp_all lemma cons_erase [DecidableEq α] [LT α] {a a0: α} {M X : Multiset α} (H : a ::ₘ M = X + {a0}) : M = X + {a0} - {a} := by if hyp : a = a0 then - simp [mul_cons_trivial, mul_erase_trivial] at * - aesop + simp_all [hyp, mul_cons_trivial, mul_erase_trivial] else have a0_a: a0 ≠ a := by rw [eq_comm] at hyp; exact hyp ext b simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] have H : Multiset.count b (a ::ₘ M) = Multiset.count b (X + {a0}) := by aesop if ba : b = a then - rw [ba] - rw [ba] at H + rw [ba] at * have : a ∈ X + {a0} := by by_contra h have absurd3 : Multiset.count a (a ::ₘ M) > 0 := by simp - aesop - have : Multiset.count a (a ::ₘ M) = Multiset.count a M + 1 := by simp - have : Multiset.count a (a0 ::ₘ X) = Multiset.count a (Multiset.erase (a0 ::ₘ X) a) + 1 := by simp ; aesop - aesop + simp_all + have : (a ::ₘ M).count a = M.count a + 1 := by simp + have : (a0 ::ₘ X).count a = ((a0 ::ₘ X).erase a).count a + 1 := by simp_all + simp_all else if ba0 : b = a0 then rw [ba0] rw [ba0] at H - have : Multiset.count a0 (Multiset.erase (a ::ₘ M) a) = Multiset.count a0 (Multiset.erase (a ::ₘ M) a) := by + have : ((a ::ₘ M).erase a).count a0 = (Multiset.erase (a ::ₘ M) a).count a0 := by simp - have : Multiset.count a0 (a ::ₘ M) = Multiset.count a0 X + 1 := by subst_eqs; rw [mul_cons_trivial] at H; simp_all - have : Multiset.count a0 M = Multiset.count a0 (a ::ₘ M) := by + have : (a ::ₘ M).count a0 = X.count a0 + 1 := by + subst_eqs; rw [mul_cons_trivial] at H; simp_all + have : M.count a0 = Multiset.count a0 (a ::ₘ M) := by have : a0 ≠ a := by simp_all rw [Multiset.count_cons_of_ne this M] simp_all - -- have : Multiset.count a0 (a ::ₘ M) = Multiset.count a0 M := by simp_all - else - have : Multiset.count b M = Multiset.count b (a ::ₘ M) := by + else + have : M.count b = (a ::ₘ M).count b := by have : b ≠ a := by simp_all - -- have : ∀s, Multiset.count a s = Multiset.count a (b ::ₘ s) := by rw [Multiset.count_cons_of_ne this M] - rw [this ] - have : Multiset.count b (X + {a0}) = Multiset.count b (Multiset.erase (a0 ::ₘ X) a) := by - simp + rw [this] + have : (X + {a0}).count b = ((a0 ::ₘ X).erase a).count b := by simp_all simp_all -lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} - (H : MultisetRedLt N (a ::ₘ M)) : - ∃ (M' : Multiset α), - N = (a ::ₘ M') ∧ (MultisetRedLt M' M) - ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by - rcases H with ⟨X, Y, a0, H1, H0, H2⟩ - -- cases h : (decide (a = a0)) - if hyp : a = a0 then - exists Y; right; apply And.intro - . rw [H1] - rw [add_left_inj] - rw [mul_cons_trivial] at H0 - simp_all - . simp_all +lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : MultisetRedLt N (a ::ₘ M)) : + ∃ (M' : Multiset α), + N = (a ::ₘ M') ∧ (MultisetRedLt M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by + rcases H with ⟨X, Y, a0, H1, H0, H2⟩ + -- cases h : (decide (a = a0)) + if hyp : a = a0 then + exists Y; right; apply And.intro + · rw [H1] + rw [add_left_inj] + rw [mul_cons_trivial] at H0 + simp_all + · simp_all + else + exists (Y + (M - {a0})) + left + constructor --; apply And.intro + · rw [H1] + have : X = (M - {a0} + {a}) := by + simp [mul_cons_trivial] at * + ext b + rw [Multiset.count_cons] + simp [Multiset.ext, Multiset.count_cons] at H0 + if h : b = a then + rw [h] + have := H0 b + aesop else - exists (Y + (M - {a0})) - left - constructor --; apply And.intro - . rw [H1] - have : X = (M - {a0} + {a}) := by - simp [mul_cons_trivial] at * - ext b - rw [Multiset.count_cons] - simp [Multiset.ext, Multiset.count_cons] at H0 - if h : b = a then - rw [h] - have := H0 b - aesop - else - have := H0 b - simp [mul_erase_trivial] - aesop - subst this - rw [add_comm,mul_cons_trivial] - aesop - . constructor - · change Y + (M - {a0}) = (M - {a0}) + Y - rw [add_comm] - · change M = M - {a0} + {a0} - have this0: M = X + {a0} - {a} := by apply cons_erase ; exact H0 - have a0M: a0 ∈ M := by - apply mul_mem_not_erase - . change M = Multiset.erase (a0 ::ₘ X) a - rw [mul_erase_trivial] at this0 - rw [mul_cons_trivial] at this0 - exact this0 - . exact hyp - apply mem_erase_cons - . exact a0M - exact H2 + have := H0 b + simp [mul_erase_trivial] + aesop + subst this + rw [add_comm,mul_cons_trivial] + aesop + · constructor + · change Y + (M - {a0}) = (M - {a0}) + Y + rw [add_comm] + · change M = M - {a0} + {a0} + have this0: M = X + {a0} - {a} := by apply cons_erase; exact H0 + have a0M: a0 ∈ M := by + apply mul_mem_not_erase + · change M = Multiset.erase (a0 ::ₘ X) a + rw [mul_erase_trivial] at this0 + rw [mul_cons_trivial] at this0 + exact this0 + · exact hyp + apply mem_erase_cons + · exact a0M + exact H2 lemma mord_wf_1 {_ : Multiset α} [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) (H1 : ∀ b (M : Multiset α), LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) @@ -200,12 +194,13 @@ lemma mord_wf_1 {_ : Multiset α} [DecidableEq α] [Preorder α] (a : α) (M0 : case h.intro.inr h => rcases h with ⟨H, H0⟩ rw [H] - clear H --It is weird that removing this line cause aesop to not be able to prove it. Even though it reports after `exhaustive` search? + clear H -- Needed to make simp_all below safe. induction x using Multiset.induction with | empty => simpa | cons h => - simp_all only [Multiset.mem_cons, or_true, implies_true, true_implies, forall_eq_or_imp, Multiset.add_cons] + simp_all only [Multiset.mem_cons, or_true, implies_true, true_implies, forall_eq_or_imp, + Multiset.add_cons] case h.intro.inl.intro => simp_all @@ -217,14 +212,14 @@ lemma mord_wf_2 [DecidableEq α] [Preorder α] (a : α) induction H0 with | intro x wfH wfH2 => apply mord_wf_1 - . simpa - . intros b x a + · simpa + · intros b x a unfold AccM_1 apply H assumption - . constructor + · constructor simpa - . simpa + · simpa lemma mord_wf_3 {_ : Multiset α} [DecidableEq α] [Preorder α] : ∀ (a:α), Acc LT.lt a → ∀ (M : Multiset α), AccM_1 M → AccM_1 (a ::ₘ M) := by @@ -235,12 +230,12 @@ lemma mord_wf_3 {_ : Multiset α} [DecidableEq α] [Preorder α] : apply @mord_wf_2 α _ _ _ _ _ accM1 simp_all --- If all elements of a multiset M is accessible given the underlying relation `LT.lt`, then the multiset M is accessible given the `MultisetRedLt` relation. --- It uses `not_MultisetRedLt_0` and `mord_wf_3` +/-- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is +accessible given the `MultisetRedLt` relation. -/ lemma mred_acc [DecidableEq α] [Preorder α] : ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → AccM_1 M := by intros M wf_el - induction M using Multiset.induction_on with -- In Coq: mset_ind : forall P : Multiset -> Prop, P empty -> (forall (M : Multiset) (a : A), P M -> P (M + {{a}})) -> forall M : Multiset, P M + induction M using Multiset.induction_on with | empty => constructor intro y y_lt @@ -248,16 +243,15 @@ lemma mred_acc [DecidableEq α] [Preorder α] : apply not_MultisetRedLt_0 | cons _ _ ih => apply mord_wf_3 - . assumption - . apply wf_el + · assumption + · apply wf_el simp_all - . apply ih + · apply ih intros apply wf_el simp_all --- If `LT.lt` is well-founded, then `MultisetRedLt` is well-founded. --- lemma `mred_acc` needed. +/-- If `LT.lt` is well-founded, then `MultisetRedLt` is well-founded. -/ lemma RedLt_wf [DecidableEq α] [Preorder α] (wf_lt : WellFoundedLT α) : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop) := by constructor @@ -269,7 +263,8 @@ lemma RedLt_wf [DecidableEq α] [Preorder α] apply Acc.intro y assumption --- If `MultisetRedLt` is well-founded, then its transitive closure, namely `MultisetLt` is also well-founded. +/-- If `MultisetRedLt` is well-founded, then its transitive closure `MultisetLt` is also +well-founded. -/ lemma Lt_wf [DecidableEq α] [LT α] (h : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop)) : WellFounded (MultisetLt : Multiset α → Multiset α → Prop) := by @@ -328,13 +323,13 @@ lemma double_split {α} [Preorder α] [dec : DecidableEq α]: rw [Multiset.count_add] rw [Multiset.count_inter] rw [Multiset.count_sub] - have H0 : Multiset.count x M + Multiset.count x N = Multiset.count x P + Multiset.count x Q := by + have H0 : M.count x + N.count x = P.count x + Q.count x := by rw [Multiset.ext] at h simp_all only [Multiset.mem_add, Multiset.count_add] - if l_u : Multiset.count x M ≤ Multiset.count x P then - have : Multiset.count x N ≥ Multiset.count x Q := by linarith + if l_u : M.count x ≤ P.count x then + have : N.count x ≥ Q.count x := by linarith simp_all only [ge_iff_le, min_eq_right] - apply le_eq_sub (Multiset.count x M) (Multiset.count x N) (Multiset.count x P) (Multiset.count x Q) + apply le_eq_sub (M.count x) (N.count x) (P.count x) (Q.count x) · simp_all · exact H0 else @@ -361,8 +356,8 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: rcases LTNM with ⟨Y1, X1, Z1, X1_ne, N1_def, M1_def, Ord1⟩ rcases LTPN with ⟨Y2, X2, Z2, _, P2_def, N2_def, Ord2⟩ apply MultisetLT.MLT (Y2 + (Y1 - X2)) (X1 + (X2 - Y1)) (Z1 ∩ Z2) - . aesop - . rw [P2_def] + · aesop + · rw [P2_def] have : Z1 ∩ Z2 + (Y2 + (Y1 - X2)) = Z1 ∩ Z2 + (Y1 - X2) + Y2 := by have : (Y2 + (Y1 - X2)) = (Y1 - X2) + Y2 := by rw [add_comm] rw [this] @@ -377,7 +372,7 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: rw [← N2_def] rw [N1_def] apply add_comm - . rw [M1_def] + · rw [M1_def] have : Z1 ∩ Z2 + (X1 + (X2 - Y1)) = Z1 ∩ Z2 + (X2 - Y1) + X1 := by have : (X1 + (X2 - Y1)) = (X2 - Y1) + X1 := by rw [add_comm] rw [this] @@ -389,27 +384,27 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: rw [← N1_def] rw [N2_def] apply add_comm - . intros y y_in_union + · intros y y_in_union if y_in : y ∈ Y2 then rcases (Ord2 y y_in) with ⟨x, x_in_X2, y_lt_x⟩ if x_in : x ∈ Y1 then rcases (Ord1 x x_in) with ⟨x', x'_in_X1, x_lt_x'⟩ use x' constructor - . rw [Multiset.mem_add] + · rw [Multiset.mem_add] constructor exact x'_in_X1 - . exact lt_trans y_lt_x x_lt_x' + · exact lt_trans y_lt_x x_lt_x' else use x constructor - . rw [add_comm] + · rw [add_comm] rw [Multiset.mem_add] constructor apply in_notin_diff exact x_in_X2 exact x_in - . exact y_lt_x + · exact y_lt_x else have y_in : y ∈ (Y1 - X2) := by aesop let h := (Ord1 y) @@ -479,7 +474,7 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] case intro.b => exact N' -- step from N' to M · apply IH newY newY_sub_Y newY_nonEmpty - change M = (Z + f y) + (X - f y) -- new try + change M = (Z + f y) + (X - f y) · ext a have count_lt := Multiset.count_le_of_le a (Multiset.filter_le (fun x => x < y) X) rw [M_def] @@ -512,7 +507,7 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] rcases X_lt_Y with ⟨t, t_in_Y, x_lt_t⟩ use t constructor - . if t_in_newY : t ∈ newY then + · if t_in_newY : t ∈ newY then exact t_in_newY else exfalso @@ -525,7 +520,8 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] have : t ∈ ( {y} : Multiset α) := by exact Or.resolve_left t_in_Y t_in_newY rw [← Multiset.mem_singleton] assumption - have x_in_fy : x ∈ f y := by unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ + have x_in_fy : x ∈ f y := by + unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ have x_notin_Xfy : x ∉ X - f y := by by_contra let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') @@ -547,23 +543,22 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] -- unfold_let neg_f at * -- simp_all exact x_notin_Xfy x_in - . exact x_lt_t + · exact x_lt_t -- single step N to N' · have : MultisetRedLt N' N := by apply MultisetRedLt.RedLt (Z + newY) (f y) y - . rfl - . have newY_y_Y: newY + {y} = Y := by unfold_let newY; simp [mul_cons_trivial]; apply Multiset.cons_erase claim + · rfl + · have newY_y_Y: newY + {y} = Y := by + unfold_let newY; simp [mul_cons_trivial]; apply Multiset.cons_erase claim have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc rw [this] rw [newY_y_Y] exact N_def - . unfold_let f; intro z z_in; simp at z_in; exact z_in.2 + · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 apply TC.base exact this -- It uses `LT_trans`. --- Is this gonna be hard to prove? Why does the coq proof use some other ways to prove: --- mord_acc_mOrd_acc (Acc_homo), mOrd_acc. lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: (MultisetLt : Multiset α → Multiset α → Prop) = (MultisetLT : Multiset α → Multiset α → Prop) := by @@ -576,9 +571,9 @@ lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: | base a b hLt => rcases hLt with ⟨Z, X, y, a_def, b_def, X_lt_y⟩ use X - simp - simp - assumption + · simp + · simp only [Multiset.mem_singleton, exists_eq_left] + assumption | trans Z W A _ _ aih bih => -- it suffices to show MultisetLT is transitive exact LT_trans _ _ _ bih aih · -- LT → Lt: @@ -586,10 +581,10 @@ lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: -- If two relations are equivalent and one of them is well-founded, then the other one is also -- well-founded. -lemma equiv_r_wf [DecidableEq α] [LT α] {r1 r2 : Multiset α → Multiset α → Prop} (h1 : WellFounded r1) - (h2: r1 = r2): WellFounded r2 := by +lemma equiv_r_wf [DecidableEq α] [LT α] {r1 r2 : Multiset α → Multiset α → Prop} + (h1 : WellFounded r1) (h2: r1 = r2) : WellFounded r2 := by subst h2 - simp_all only + exact h1 -- The desired theorem. If `LT.lt` is well-founded, then `MultisetLT` is well-founded. theorem dm_wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] From b027927806b9b5f8ad1b1887e5b68f011b666689 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:22:14 +0200 Subject: [PATCH 04/32] fix sorry --- Mathlib/Data/Multiset/Order.lean | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index adbf6cb712a85..11ee0f9b86ece 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -22,7 +22,8 @@ the Dershowitz-Manna ordering defined over multisets is also well-founded. ## References -* [Wikipedia, Dershowitz–Manna ordering*](https://en.wikipedia.org/wiki/Dershowitz%E2%80%93Manna_ordering) +* [Wikipedia, Dershowitz–Manna ordering*] +(https://en.wikipedia.org/wiki/Dershowitz%E2%80%93Manna_ordering) * [CoLoR](https://github.com/fblanqui/color), a Coq library on rewriting theory and termination. Our code here is inspired by their version of called `mOrd_wf` in the file @@ -525,23 +526,22 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] have x_notin_Xfy : x ∉ X - f y := by by_contra let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') - sorry - -- have : X - f y = neg_f y := by - -- have fy_negfy_X : f y + neg_f y = X := by - -- rw [Multiset.filter_add_not] - -- have fy_le_X : f y ≤ X := Multiset.filter_le _ X - -- have : X - f y + f y = neg_f y + f y := by - -- have : X = X - f y + f y := by - -- apply mem_leq_diff - -- exact fy_le_X - -- rw [← this] - -- rw [← fy_negfy_X] - -- apply add_comm - -- rw [← fy_negfy_X]; simp - -- have x_in_neg_fy : x ∈ neg_f y := by rw [this] at x_in; exact x_in - -- subst_eqs - -- unfold_let neg_f at * - -- simp_all + have : X - f y = neg_f y := by + have fy_negfy_X : f y + neg_f y = X := by + rw [Multiset.filter_add_not] + have fy_le_X : f y ≤ X := Multiset.filter_le _ X + have : X - f y + f y = neg_f y + f y := by + have : X = X - f y + f y := by + apply mem_leq_diff + exact fy_le_X + rw [← this] + rw [← fy_negfy_X] + apply add_comm + rw [← fy_negfy_X]; simp + have x_in_neg_fy : x ∈ neg_f y := by rw [this] at x_in; exact x_in + subst_eqs + unfold_let neg_f at * + simp_all only [Multiset.mem_filter] exact x_notin_Xfy x_in · exact x_lt_t -- single step N to N' From e6c49b92dd39374342bd75f32622ba57d2bc8145 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:35:41 +0200 Subject: [PATCH 05/32] trivial lemmas removed --- Mathlib/Data/Multiset/Order.lean | 149 ++++++++++++------------------- 1 file changed, 58 insertions(+), 91 deletions(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index 11ee0f9b86ece..d4cebb736133f 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -33,6 +33,7 @@ the Dershowitz-Manna ordering defined over multisets is also well-founded. variable {α : Type*} +/-- The standard Dershowitz–Manna ordering: -/ inductive MultisetLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := | MLT : ∀ (X Y Z: Multiset α), Y ≠ ∅ → @@ -40,17 +41,20 @@ inductive MultisetLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop : N = Z + Y → (∀ x ∈ X, ∃ y ∈ Y, x < y) → MultisetLT M N +/-- Another equivalent (proved later) version of the ordering defined using transitive closure: -/ inductive MultisetRedLt [DecidableEq α][LT α] (M N : Multiset α) : Prop := | RedLt : ∀ (X Y:Multiset α) (a : α) , (M = X + Y) → (N = X + {a}) → (∀ y, y ∈ Y → y < a) → MultisetRedLt M N -/-- MultisetLt is the transitive closure of MultisetRedLt -/ +/-- MultisetLt is the transitive closure of MultisetRedLt. -/ def MultisetLt [DecidableEq α][LT α] : Multiset α → Multiset α → Prop := TC MultisetRedLt + +/-- AccM_1 defines the accessibility relation given MultisetRedLt. -/ def AccM_1 [DecidableEq α][Preorder α] : Multiset α → Prop := Acc MultisetRedLt --- Some useful lemmas about Multisets and the defined relations +/- Some useful lemmas about Multisets and the defined relations: -/ lemma not_MultisetRedLt_0 [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedLt M 0 := by intro h cases h with @@ -64,21 +68,13 @@ lemma meq_union_meq_reverse [DecidableEq α] [Preorder α] {M N P : Multiset α} (_ : M = N) : M + P = N + P := by simp_all only -lemma mul_cons_trivial [DecidableEq α] [LT α] {a : α} {M : Multiset α} : - M + {a} = a ::ₘ M := by - intros - ext - simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] - -lemma mul_erase_trivial [DecidableEq α] [LT α] {a : α} {M : Multiset α} : +lemma mul_singleton_erase [DecidableEq α] {a : α} {M : Multiset α} : M - {a} = M.erase a := by - intros ext - simp [Multiset.erase_singleton] - simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] + simp [Multiset.erase_singleton, Multiset.count_singleton] split <;> simp_all -lemma mul_mem_not_erase [DecidableEq α] [LT α] {a a0: α} {M X : Multiset α} +lemma mul_mem_not_erase [DecidableEq α] {a a0: α} {M X : Multiset α} (H : M = (a0 ::ₘ X).erase a) (hyp : ¬ a = a0) : a0 ∈ M := by rw [H] have : a0 ∈ (a0 ::ₘ X).erase a ↔ a0 ∈ (a0 ::ₘ X) := by @@ -87,40 +83,39 @@ lemma mul_mem_not_erase [DecidableEq α] [LT α] {a a0: α} {M X : Multiset α} rw [this] simp_all -lemma mem_erase_cons [DecidableEq α] [LT α] {a0: α} {M : Multiset α} (_ : a0 ∈ M) : +lemma mem_erase_cons [DecidableEq α] {a0: α} {M : Multiset α} (_ : a0 ∈ M) : M = M - {a0} + {a0} := by - simp_all [mul_cons_trivial, mul_erase_trivial, Multiset.cons_erase] + rw [add_comm] + simp_all [Multiset.singleton_add, mul_singleton_erase] -lemma neq_erase [DecidableEq α] [LT α] {a a0: α} (M : Multiset α)(_ : a0 ≠ a) : +lemma neq_erase [DecidableEq α] {a a0: α} (M : Multiset α)(_ : a0 ≠ a) : (M.erase a).count a0 = M.count a0 := by have : (a ::ₘ (M.erase a)).count a0 = (a ::ₘ M).count a0 := by simp_all simp_all -lemma cons_erase [DecidableEq α] [LT α] {a a0: α} {M X : Multiset α} +lemma cons_erase [DecidableEq α] {a a0: α} {M X : Multiset α} (H : a ::ₘ M = X + {a0}) : M = X + {a0} - {a} := by if hyp : a = a0 then - simp_all [hyp, mul_cons_trivial, mul_erase_trivial] + rw [hyp] + rw [add_comm] at H + simp_all [Multiset.singleton_add] else have a0_a: a0 ≠ a := by rw [eq_comm] at hyp; exact hyp ext b simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] - have H : Multiset.count b (a ::ₘ M) = Multiset.count b (X + {a0}) := by aesop + have H : Multiset.count b (a ::ₘ M) = Multiset.count b (X + {a0}) := by simp_all only + [Multiset.count_add] if ba : b = a then rw [ba] at * - have : a ∈ X + {a0} := by - by_contra h - have absurd3 : Multiset.count a (a ::ₘ M) > 0 := by simp - simp_all have : (a ::ₘ M).count a = M.count a + 1 := by simp - have : (a0 ::ₘ X).count a = ((a0 ::ₘ X).erase a).count a + 1 := by simp_all simp_all else if ba0 : b = a0 then rw [ba0] rw [ba0] at H - have : ((a ::ₘ M).erase a).count a0 = (Multiset.erase (a ::ₘ M) a).count a0 := by - simp have : (a ::ₘ M).count a0 = X.count a0 + 1 := by - subst_eqs; rw [mul_cons_trivial] at H; simp_all + subst_eqs + rw [add_comm, Multiset.singleton_add] at H + simp_all have : M.count a0 = Multiset.count a0 (a ::ₘ M) := by have : a0 ≠ a := by simp_all rw [Multiset.count_cons_of_ne this M] @@ -130,20 +125,17 @@ lemma cons_erase [DecidableEq α] [LT α] {a a0: α} {M X : Multiset α} have : b ≠ a := by simp_all rw [Multiset.count_cons_of_ne this M] rw [this] - have : (X + {a0}).count b = ((a0 ::ₘ X).erase a).count b := by - simp_all simp_all lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : MultisetRedLt N (a ::ₘ M)) : - ∃ (M' : Multiset α), + ∃ M', N = (a ::ₘ M') ∧ (MultisetRedLt M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by rcases H with ⟨X, Y, a0, H1, H0, H2⟩ - -- cases h : (decide (a = a0)) if hyp : a = a0 then exists Y; right; apply And.intro · rw [H1] rw [add_left_inj] - rw [mul_cons_trivial] at H0 + rw [add_comm, Multiset.singleton_add] at H0 simp_all · simp_all else @@ -152,7 +144,7 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : Mult constructor --; apply And.intro · rw [H1] have : X = (M - {a0} + {a}) := by - simp [mul_cons_trivial] at * + rw [add_comm, Multiset.singleton_add] at * ext b rw [Multiset.count_cons] simp [Multiset.ext, Multiset.count_cons] at H0 @@ -162,11 +154,12 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : Mult aesop else have := H0 b - simp [mul_erase_trivial] + simp [mul_singleton_erase] aesop subst this - rw [add_comm,mul_cons_trivial] - aesop + rw [add_comm] + nth_rewrite 2 [add_comm] + rw [Multiset.singleton_add, Multiset.add_cons] · constructor · change Y + (M - {a0}) = (M - {a0}) + Y rw [add_comm] @@ -175,8 +168,8 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : Mult have a0M: a0 ∈ M := by apply mul_mem_not_erase · change M = Multiset.erase (a0 ::ₘ X) a - rw [mul_erase_trivial] at this0 - rw [mul_cons_trivial] at this0 + rw [mul_singleton_erase] at this0 + rw [add_comm] at this0 exact this0 · exact hyp apply mem_erase_cons @@ -184,7 +177,7 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : Mult exact H2 lemma mord_wf_1 {_ : Multiset α} [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) - (H1 : ∀ b (M : Multiset α), LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) + (H1 : ∀ b M , LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) (H2 : AccM_1 M0) (H3 : ∀ M, MultisetRedLt M M0 → AccM_1 (a ::ₘ M)) : AccM_1 (a ::ₘ M0) := by @@ -206,7 +199,7 @@ lemma mord_wf_1 {_ : Multiset α} [DecidableEq α] [Preorder α] (a : α) (M0 : simp_all lemma mord_wf_2 [DecidableEq α] [Preorder α] (a : α) - (H : ∀ (b : α), ∀ (M : Multiset α), LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) : + (H : ∀ (b : α), ∀ M, LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) : ∀ M, AccM_1 M → AccM_1 (a ::ₘ M) := by unfold AccM_1 intros M H0 @@ -223,7 +216,7 @@ lemma mord_wf_2 [DecidableEq α] [Preorder α] (a : α) · simpa lemma mord_wf_3 {_ : Multiset α} [DecidableEq α] [Preorder α] : - ∀ (a:α), Acc LT.lt a → ∀ (M : Multiset α), AccM_1 M → AccM_1 (a ::ₘ M) := by + ∀ (a:α), Acc LT.lt a → ∀ M, AccM_1 M → AccM_1 (a ::ₘ M) := by intro w w_a induction w_a with | intro x _ ih => @@ -231,7 +224,7 @@ lemma mord_wf_3 {_ : Multiset α} [DecidableEq α] [Preorder α] : apply @mord_wf_2 α _ _ _ _ _ accM1 simp_all -/-- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is +/- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is accessible given the `MultisetRedLt` relation. -/ lemma mred_acc [DecidableEq α] [Preorder α] : ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → AccM_1 M := by @@ -252,7 +245,7 @@ lemma mred_acc [DecidableEq α] [Preorder α] : apply wf_el simp_all -/-- If `LT.lt` is well-founded, then `MultisetRedLt` is well-founded. -/ +/- If `LT.lt` is well-founded, then `MultisetRedLt` is well-founded. -/ lemma RedLt_wf [DecidableEq α] [Preorder α] (wf_lt : WellFoundedLT α) : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop) := by constructor @@ -264,7 +257,7 @@ lemma RedLt_wf [DecidableEq α] [Preorder α] apply Acc.intro y assumption -/-- If `MultisetRedLt` is well-founded, then its transitive closure `MultisetLt` is also +/- If `MultisetRedLt` is well-founded, then its transitive closure `MultisetLt` is also well-founded. -/ lemma Lt_wf [DecidableEq α] [LT α] (h : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop)) : @@ -273,17 +266,17 @@ lemma Lt_wf [DecidableEq α] [LT α] apply TC.wf assumption -lemma mul_geq_zero [DecidableEq α] [LT α] : ∀ (M : Multiset α), M ≥ 0 := by +lemma mul_geq_zero : ∀ (M : Multiset α), M ≥ 0 := by intro M simp_all only [Multiset.quot_mk_to_coe'', ge_iff_le, zero_le] -lemma mem_leq_diff [DecidableEq α] [Preorder α] : ∀ (M N: Multiset α), N ≤ M → M = M - N + N := by +lemma mem_leq_diff [DecidableEq α] : ∀ (M N: Multiset α), N ≤ M → M = M - N + N := by intros M N h rw [← Multiset.union_def] rw [Multiset.eq_union_left] exact h -lemma le_sub_add {α} [pre : Preorder α] [dec : DecidableEq α]: +lemma le_sub_add {α} [dec : DecidableEq α]: ∀ (M N P : Multiset α) , N ≤ M → M - N + P = M + P - N := by intro M N P h have : M - N + P + N = M + P - N + N := by @@ -317,7 +310,7 @@ lemma le_eq_sub : ∀ (M N P Q : ℕ) , M ≤ P → M + N = P + Q → N = Q + (P have := tsub_add_cancel_of_le h0 linarith -lemma double_split {α} [Preorder α] [dec : DecidableEq α]: +lemma double_split {α} [dec : DecidableEq α]: ∀ (M N P Q: Multiset α) , M + N = P + Q → N = N ∩ Q + (P - M) := by intros M N P Q h ext x @@ -345,10 +338,9 @@ lemma in_notin_diff {α} [DecidableEq α]: have : Multiset.count x X ≥ 1 := by rw [← Multiset.one_le_count_iff_mem] at x_in_X exact x_in_X - have : Multiset.count x Y = 0 := by apply Multiset.count_eq_zero_of_not_mem; exact x_notin_Y rw [← Multiset.one_le_count_iff_mem] rw [Multiset.count_sub] - aesop + simp_all only [not_false_eq_true, Multiset.count_eq_zero_of_not_mem, tsub_zero] -- `MultisetLT` is transitive. Two lemmas needed: double_split, in_notin_diff lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: @@ -357,7 +349,7 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: rcases LTNM with ⟨Y1, X1, Z1, X1_ne, N1_def, M1_def, Ord1⟩ rcases LTPN with ⟨Y2, X2, Z2, _, P2_def, N2_def, Ord2⟩ apply MultisetLT.MLT (Y2 + (Y1 - X2)) (X1 + (X2 - Y1)) (Z1 ∩ Z2) - · aesop + · simp_all only [Multiset.empty_eq_zero, ne_eq, add_eq_zero_iff, false_and, not_false_eq_true] · rw [P2_def] have : Z1 ∩ Z2 + (Y2 + (Y1 - X2)) = Z1 ∩ Z2 + (Y1 - X2) + Y2 := by have : (Y2 + (Y1 - X2)) = (Y1 - X2) + Y2 := by rw [add_comm] @@ -407,10 +399,11 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: exact x_in · exact y_lt_x else - have y_in : y ∈ (Y1 - X2) := by aesop + have y_in : y ∈ (Y1 - X2) := by simp_all only [Multiset.mem_add, false_or] let h := (Ord1 y) have y_in_Y1 : y ∈ Y1 := by - have : Y1 - X2 ≤ Y1 := by aesop + have : Y1 - X2 ≤ Y1 := by simp_all only [tsub_le_iff_right, le_add_iff_nonneg_right, + zero_le] apply Multiset.mem_of_le exact this exact y_in @@ -426,7 +419,7 @@ lemma nat_not_0_not_1 : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by case zero => contradiction case succ n=> apply Nat.succ_le_succ - aesop + simp_all only [le_add_iff_nonneg_left, zero_le] lemma direct_subset_red [dec : DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (LTMN : MultisetLT M N) : @@ -460,14 +453,9 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] let newY := Y.erase y have newY_nonEmpty : newY ≠ ∅ := by have card_Y_ge_2 : Multiset.card Y ≥ 2 := nat_not_0_not_1 _ hyp' hyp - have : Multiset.card (Multiset.erase Y y) ≥ 1 := by - rw [Multiset.card_erase_eq_ite] - simp_all - have card_Y_g_1 : 1 < Multiset.card Y := by aesop - exact Nat.pred_le_pred card_Y_g_1 have : 0 < Multiset.card (Multiset.erase Y y) := by aesop rw [Multiset.card_pos] at this - aesop + simp_all only [Multiset.empty_eq_zero, ne_eq, not_false_eq_true] have newY_sub_Y : newY < Y := by simp (config := {zetaDelta := true}); exact claim let f : α → Multiset α := fun y' => X.filter (fun x => x < y') -- DecidableRel let N' := Z + newY + f y @@ -486,17 +474,9 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] let fx := Multiset.count a (Multiset.filter (fun x => x < y) X) change z + x = z + fx + (x - fx) change fx ≤ x at count_lt - have : x = fx + (x - fx) := by aesop + have : x = fx + (x - fx) := by simp_all only [add_tsub_cancel_of_le] linarith - · have : Z + newY + f y = Z + f y + newY := by - have : newY + f y = f y + newY := by apply add_comm - have : Z + newY + f y = Z + (newY + f y) := by apply add_assoc - rw [this] - have : Z + f y + newY = Z + (f y + newY) := by apply add_assoc - rw [this] - simp (config := {zetaDelta := true}) - assumption - unfold_let N' + · unfold_let N' rw [add_assoc, add_assoc, add_comm newY (f y)] · intro x x_in let X_lt_Y := X_lt_Y x @@ -515,7 +495,8 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] have : t = y := by have : Y = newY + {y} := by unfold_let newY - simp [mul_cons_trivial, Multiset.cons_erase claim] + rw [add_comm, Multiset.singleton_add] + simp [Multiset.cons_erase claim] rw [this] at t_in_Y rw [Multiset.mem_add] at t_in_Y have : t ∈ ( {y} : Multiset α) := by exact Or.resolve_left t_in_Y t_in_newY @@ -529,14 +510,6 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] have : X - f y = neg_f y := by have fy_negfy_X : f y + neg_f y = X := by rw [Multiset.filter_add_not] - have fy_le_X : f y ≤ X := Multiset.filter_le _ X - have : X - f y + f y = neg_f y + f y := by - have : X = X - f y + f y := by - apply mem_leq_diff - exact fy_le_X - rw [← this] - rw [← fy_negfy_X] - apply add_comm rw [← fy_negfy_X]; simp have x_in_neg_fy : x ∈ neg_f y := by rw [this] at x_in; exact x_in subst_eqs @@ -549,7 +522,7 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] apply MultisetRedLt.RedLt (Z + newY) (f y) y · rfl · have newY_y_Y: newY + {y} = Y := by - unfold_let newY; simp [mul_cons_trivial]; apply Multiset.cons_erase claim + unfold_let newY; rw [add_comm, Multiset.singleton_add]; apply Multiset.cons_erase claim have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc rw [this] rw [newY_y_Y] @@ -558,7 +531,7 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] apply TC.base exact this --- It uses `LT_trans`. +/- MultisetLt and MultisetLT are equivalent. -/ lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: (MultisetLt : Multiset α → Multiset α → Prop) = (MultisetLT : Multiset α → Multiset α → Prop) := by @@ -579,14 +552,8 @@ lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: · -- LT → Lt: apply direct_subset_red --- If two relations are equivalent and one of them is well-founded, then the other one is also --- well-founded. -lemma equiv_r_wf [DecidableEq α] [LT α] {r1 r2 : Multiset α → Multiset α → Prop} - (h1 : WellFounded r1) (h2: r1 = r2) : WellFounded r2 := by - subst h2 - exact h1 - --- The desired theorem. If `LT.lt` is well-founded, then `MultisetLT` is well-founded. +/- The desired theorem: If `LT.lt` is well-founded, then `MultisetLT` is well-founded. -/ theorem dm_wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] - (wf_lt : WellFoundedLT α) :WellFounded (MultisetLT : Multiset α → Multiset α → Prop) := - equiv_r_wf (Lt_wf (RedLt_wf wf_lt)) Lt_LT_equiv + (wf_lt : WellFoundedLT α) :WellFounded (MultisetLT : Multiset α → Multiset α → Prop) := by + rw [← Lt_LT_equiv] + exact Lt_wf (RedLt_wf wf_lt) From d18ecfedc973d1e2c512d91de031d3f281acfc18 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:43:03 +0200 Subject: [PATCH 06/32] remove unnecessary --- Mathlib/Data/Multiset/Order.lean | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index d4cebb736133f..8e94f7792213a 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -64,10 +64,6 @@ lemma not_MultisetRedLt_0 [DecidableEq α] [LT α] (M: Multiset α) : ¬ Multise simp_all only [Multiset.mem_add, Multiset.mem_singleton, or_true] contradiction -lemma meq_union_meq_reverse [DecidableEq α] [Preorder α] {M N P : Multiset α} - (_ : M = N) : M + P = N + P := by - simp_all only - lemma mul_singleton_erase [DecidableEq α] {a : α} {M : Multiset α} : M - {a} = M.erase a := by ext @@ -88,11 +84,6 @@ lemma mem_erase_cons [DecidableEq α] {a0: α} {M : Multiset α} (_ : a0 ∈ M) rw [add_comm] simp_all [Multiset.singleton_add, mul_singleton_erase] -lemma neq_erase [DecidableEq α] {a a0: α} (M : Multiset α)(_ : a0 ≠ a) : - (M.erase a).count a0 = M.count a0 := by - have : (a ::ₘ (M.erase a)).count a0 = (a ::ₘ M).count a0 := by simp_all - simp_all - lemma cons_erase [DecidableEq α] {a a0: α} {M X : Multiset α} (H : a ::ₘ M = X + {a0}) : M = X + {a0} - {a} := by if hyp : a = a0 then @@ -176,7 +167,7 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : Mult · exact a0M exact H2 -lemma mord_wf_1 {_ : Multiset α} [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) +lemma mord_wf_1 [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) (H1 : ∀ b M , LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) (H2 : AccM_1 M0) (H3 : ∀ M, MultisetRedLt M M0 → AccM_1 (a ::ₘ M)) : @@ -207,15 +198,11 @@ lemma mord_wf_2 [DecidableEq α] [Preorder α] (a : α) | intro x wfH wfH2 => apply mord_wf_1 · simpa - · intros b x a - unfold AccM_1 - apply H - assumption · constructor simpa · simpa -lemma mord_wf_3 {_ : Multiset α} [DecidableEq α] [Preorder α] : +lemma mord_wf_3[DecidableEq α] [Preorder α] : ∀ (a:α), Acc LT.lt a → ∀ M, AccM_1 M → AccM_1 (a ::ₘ M) := by intro w w_a induction w_a with @@ -237,7 +224,6 @@ lemma mred_acc [DecidableEq α] [Preorder α] : apply not_MultisetRedLt_0 | cons _ _ ih => apply mord_wf_3 - · assumption · apply wf_el simp_all · apply ih @@ -356,7 +342,6 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: rw [this] rw [add_assoc] rw [this] - apply meq_union_meq_reverse have : Z1 ∩ Z2 + (Y1 - X2) = Z2 ∩ Z1 + (Y1 - X2) := by rw [Multiset.inter_comm] rw [this] @@ -370,8 +355,7 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: have : (X1 + (X2 - Y1)) = (X2 - Y1) + X1 := by rw [add_comm] rw [this] rw [add_assoc] - rw [this] - apply meq_union_meq_reverse + rw [this, add_left_inj] apply double_split rw [add_comm] rw [← N1_def] @@ -522,7 +506,8 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] apply MultisetRedLt.RedLt (Z + newY) (f y) y · rfl · have newY_y_Y: newY + {y} = Y := by - unfold_let newY; rw [add_comm, Multiset.singleton_add]; apply Multiset.cons_erase claim + unfold_let newY; rw [add_comm, Multiset.singleton_add] + apply Multiset.cons_erase claim have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc rw [this] rw [newY_y_Y] From 38b7b48d281dbedbcf900f1e5663559d7707f883 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:06:23 +0200 Subject: [PATCH 07/32] replace TC with TransGen --- Mathlib/Data/Multiset/Order.lean | 37 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index 8e94f7792213a..2efae4512ce7b 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -41,19 +41,32 @@ inductive MultisetLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop : N = Z + Y → (∀ x ∈ X, ∃ y ∈ Y, x < y) → MultisetLT M N -/-- Another equivalent (proved later) version of the ordering defined using transitive closure: -/ +/-- MultisetRedLt is a special case of MultisetLT. The transitive closure of it is used to define +an equivalent (proved later) version of the ordering. -/ inductive MultisetRedLt [DecidableEq α][LT α] (M N : Multiset α) : Prop := | RedLt : ∀ (X Y:Multiset α) (a : α) , (M = X + Y) → (N = X + {a}) → (∀ y, y ∈ Y → y < a) → MultisetRedLt M N -/-- MultisetLt is the transitive closure of MultisetRedLt. -/ -def MultisetLt [DecidableEq α][LT α] : Multiset α → Multiset α → Prop := TC MultisetRedLt +open Relation + +/-- MultisetLt is the transitive closure of MultisetRedLt and is equivalent to MultisetLT + (proved later). -/ +def MultisetLt [DecidableEq α][LT α] : Multiset α → Multiset α → Prop := TransGen MultisetRedLt /-- AccM_1 defines the accessibility relation given MultisetRedLt. -/ def AccM_1 [DecidableEq α][Preorder α] : Multiset α → Prop := Acc MultisetRedLt +/- MultisetRedLt is a special case of MultisetLT. -/ +theorem redLt_LT [DecidableEq α] [Preorder α] (M N : Multiset α) : + MultisetRedLt M N → MultisetLT M N := by + intro hyp + rcases hyp with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ + apply MultisetLT.MLT Y {a} X _ M_def N_def + · simp; assumption + · simp + /- Some useful lemmas about Multisets and the defined relations: -/ lemma not_MultisetRedLt_0 [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedLt M 0 := by intro h @@ -249,7 +262,7 @@ lemma Lt_wf [DecidableEq α] [LT α] (h : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop)) : WellFounded (MultisetLt : Multiset α → Multiset α → Prop) := by unfold MultisetLt - apply TC.wf + apply WellFounded.transGen assumption lemma mul_geq_zero : ∀ (M : Multiset α), M ≥ 0 := by @@ -422,7 +435,7 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] case inl hyp' hyp=> rw [Multiset.card_eq_one] at hyp rcases hyp with ⟨y,Y'_def⟩ - apply TC.base + apply TransGen.single rw [Y'_def] at N_def apply @MultisetRedLt.RedLt α _ _ M N Z X y M_def N_def simp [Y'_def] at X_lt_Y @@ -443,8 +456,7 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] have newY_sub_Y : newY < Y := by simp (config := {zetaDelta := true}); exact claim let f : α → Multiset α := fun y' => X.filter (fun x => x < y') -- DecidableRel let N' := Z + newY + f y - apply TC.trans - case intro.b => exact N' + apply @transitive_transGen _ _ _ N' -- step from N' to M · apply IH newY newY_sub_Y newY_nonEmpty change M = (Z + f y) + (X - f y) @@ -513,7 +525,7 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] rw [newY_y_Y] exact N_def · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 - apply TC.base + apply TransGen.single exact this /- MultisetLt and MultisetLT are equivalent. -/ @@ -526,14 +538,17 @@ lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: · -- Lt → LT: intros hLt induction hLt with - | base a b hLt => + | single hLt => rcases hLt with ⟨Z, X, y, a_def, b_def, X_lt_y⟩ use X · simp · simp only [Multiset.mem_singleton, exists_eq_left] assumption - | trans Z W A _ _ aih bih => -- it suffices to show MultisetLT is transitive - exact LT_trans _ _ _ bih aih + | tail _ aih bih => -- it suffices to show MultisetLT is transitive + apply LT_trans _ _ _ _ bih + apply redLt_LT + assumption + · -- LT → Lt: apply direct_subset_red From 2f5a35d81db0146d5c98ce58e47ed488a3752448 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:22:25 +0200 Subject: [PATCH 08/32] correct indent --- Mathlib/Data/Multiset/Order.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index 2efae4512ce7b..0272e04821992 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -60,7 +60,7 @@ def AccM_1 [DecidableEq α][Preorder α] : Multiset α → Prop := Acc MultisetR /- MultisetRedLt is a special case of MultisetLT. -/ theorem redLt_LT [DecidableEq α] [Preorder α] (M N : Multiset α) : - MultisetRedLt M N → MultisetLT M N := by + MultisetRedLt M N → MultisetLT M N := by intro hyp rcases hyp with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ apply MultisetLT.MLT Y {a} X _ M_def N_def From d623962a32e48dd6d654d038b81a0cab6608e267 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Fri, 5 Jul 2024 01:37:08 +0200 Subject: [PATCH 09/32] remove few trivial lemmas --- Mathlib/Data/Multiset/Order.lean | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index 0272e04821992..5db9e57f43d07 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -265,10 +265,6 @@ lemma Lt_wf [DecidableEq α] [LT α] apply WellFounded.transGen assumption -lemma mul_geq_zero : ∀ (M : Multiset α), M ≥ 0 := by - intro M - simp_all only [Multiset.quot_mk_to_coe'', ge_iff_le, zero_le] - lemma mem_leq_diff [DecidableEq α] : ∀ (M N: Multiset α), N ≤ M → M = M - N + N := by intros M N h rw [← Multiset.union_def] @@ -407,17 +403,6 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: let _ := h y_in_Y1 aesop -lemma nat_not_0_not_1 : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by - intros n h0 h1 - cases n - case zero => contradiction - case succ m => - cases m - case zero => contradiction - case succ n=> - apply Nat.succ_le_succ - simp_all only [le_add_iff_nonneg_left, zero_le] - lemma direct_subset_red [dec : DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (LTMN : MultisetLT M N) : MultisetLt M N := by @@ -449,7 +434,16 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] rcases this with ⟨y,claim⟩ let newY := Y.erase y have newY_nonEmpty : newY ≠ ∅ := by - have card_Y_ge_2 : Multiset.card Y ≥ 2 := nat_not_0_not_1 _ hyp' hyp + have : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by + intros n h0 h1 + cases n + case zero => contradiction + case succ m => + cases m + case zero => contradiction + case succ n=> + apply Nat.succ_le_succ + simp_all only [le_add_iff_nonneg_left, zero_le] have : 0 < Multiset.card (Multiset.erase Y y) := by aesop rw [Multiset.card_pos] at this simp_all only [Multiset.empty_eq_zero, ne_eq, not_false_eq_true] @@ -548,7 +542,6 @@ lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: apply LT_trans _ _ _ _ bih apply redLt_LT assumption - · -- LT → Lt: apply direct_subset_red From ad5f762ce937c0693648bfc6af2f33fc033a256e Mon Sep 17 00:00:00 2001 From: haitian-yuki <127060846+haitian-yuki@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:54:13 +0200 Subject: [PATCH 10/32] Apply suggestions from code review partly done Co-authored-by: Rida Hamadani <106540880+Rida-Hamadani@users.noreply.github.com> --- Mathlib/Data/Multiset/Order.lean | 33 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index 5db9e57f43d07..8c2ed220c04c1 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -64,7 +64,7 @@ theorem redLt_LT [DecidableEq α] [Preorder α] (M N : Multiset α) : intro hyp rcases hyp with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ apply MultisetLT.MLT Y {a} X _ M_def N_def - · simp; assumption + · simpa · simp /- Some useful lemmas about Multisets and the defined relations: -/ @@ -85,12 +85,8 @@ lemma mul_singleton_erase [DecidableEq α] {a : α} {M : Multiset α} : lemma mul_mem_not_erase [DecidableEq α] {a a0: α} {M X : Multiset α} (H : M = (a0 ::ₘ X).erase a) (hyp : ¬ a = a0) : a0 ∈ M := by - rw [H] - have : a0 ∈ (a0 ::ₘ X).erase a ↔ a0 ∈ (a0 ::ₘ X) := by - apply Multiset.mem_erase_of_ne - aesop - rw [this] - simp_all + rw [H, Multiset.mem_erase_of_ne fun h ↦ hyp <| id <| Eq.symm h, Multiset.mem_cons] + tauto lemma mem_erase_cons [DecidableEq α] {a0: α} {M : Multiset α} (_ : a0 ∈ M) : M = M - {a0} + {a0} := by @@ -309,9 +305,7 @@ lemma double_split {α} [dec : DecidableEq α]: ∀ (M N P Q: Multiset α) , M + N = P + Q → N = N ∩ Q + (P - M) := by intros M N P Q h ext x - rw [Multiset.count_add] - rw [Multiset.count_inter] - rw [Multiset.count_sub] + rw [Multiset.count_add, Multiset.count_inter, Multiset.count_sub] have H0 : M.count x + N.count x = P.count x + Q.count x := by rw [Multiset.ext] at h simp_all only [Multiset.mem_add, Multiset.count_add] @@ -319,12 +313,12 @@ lemma double_split {α} [dec : DecidableEq α]: have : N.count x ≥ Q.count x := by linarith simp_all only [ge_iff_le, min_eq_right] apply le_eq_sub (M.count x) (N.count x) (P.count x) (Q.count x) - · simp_all + · exact l_u · exact H0 else simp_all only [not_le, gt_iff_lt] have : Multiset.count x N ≤ Multiset.count x Q := by linarith - have:= le_of_lt l_u + have := le_of_lt l_u simp_all lemma in_notin_diff {α} [DecidableEq α]: @@ -489,19 +483,17 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] simp [Multiset.cons_erase claim] rw [this] at t_in_Y rw [Multiset.mem_add] at t_in_Y - have : t ∈ ( {y} : Multiset α) := by exact Or.resolve_left t_in_Y t_in_newY - rw [← Multiset.mem_singleton] - assumption + have : t ∈ ( {y} : Multiset α) := Or.resolve_left t_in_Y t_in_newY + rwa [← Multiset.mem_singleton] have x_in_fy : x ∈ f y := by unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ have x_notin_Xfy : x ∉ X - f y := by by_contra let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') have : X - f y = neg_f y := by - have fy_negfy_X : f y + neg_f y = X := by - rw [Multiset.filter_add_not] - rw [← fy_negfy_X]; simp - have x_in_neg_fy : x ∈ neg_f y := by rw [this] at x_in; exact x_in + have fy_negfy_X : f y + neg_f y = X := Multiset.filter_add_not _ _ + rw [← fy_negfy_X, add_tsub_cancel_left] + have x_in_neg_fy : x ∈ neg_f y := this ▸ x_in subst_eqs unfold_let neg_f at * simp_all only [Multiset.mem_filter] @@ -536,8 +528,7 @@ lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: rcases hLt with ⟨Z, X, y, a_def, b_def, X_lt_y⟩ use X · simp - · simp only [Multiset.mem_singleton, exists_eq_left] - assumption + · simpa | tail _ aih bih => -- it suffices to show MultisetLT is transitive apply LT_trans _ _ _ _ bih apply redLt_LT From 6599ec3480a3dce50fbc44850f63c635530fdc95 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 10 Jul 2024 14:16:47 +0200 Subject: [PATCH 11/32] replace if..then.. with by_cases --- Mathlib/Data/Multiset/Order.lean | 182 +++++++++++++------------------ 1 file changed, 76 insertions(+), 106 deletions(-) diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean index 8c2ed220c04c1..f89b0d1d9d9e9 100644 --- a/Mathlib/Data/Multiset/Order.lean +++ b/Mathlib/Data/Multiset/Order.lean @@ -95,24 +95,20 @@ lemma mem_erase_cons [DecidableEq α] {a0: α} {M : Multiset α} (_ : a0 ∈ M) lemma cons_erase [DecidableEq α] {a a0: α} {M X : Multiset α} (H : a ::ₘ M = X + {a0}) : M = X + {a0} - {a} := by - if hyp : a = a0 then - rw [hyp] - rw [add_comm] at H + by_cases hyp : a = a0 + · rw [hyp, add_comm] at H simp_all [Multiset.singleton_add] - else - have a0_a: a0 ≠ a := by rw [eq_comm] at hyp; exact hyp + · have a0_a: a0 ≠ a := by rw [eq_comm] at hyp; exact hyp ext b simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] have H : Multiset.count b (a ::ₘ M) = Multiset.count b (X + {a0}) := by simp_all only [Multiset.count_add] - if ba : b = a then - rw [ba] at * + by_cases ba : b = a + · rw [ba] at * have : (a ::ₘ M).count a = M.count a + 1 := by simp simp_all - else if ba0 : b = a0 then - rw [ba0] - rw [ba0] at H - have : (a ::ₘ M).count a0 = X.count a0 + 1 := by + by_cases ba0 : b = a0 + · have : (a ::ₘ M).count a0 = X.count a0 + 1 := by subst_eqs rw [add_comm, Multiset.singleton_add] at H simp_all @@ -120,8 +116,7 @@ lemma cons_erase [DecidableEq α] {a a0: α} {M X : Multiset α} have : a0 ≠ a := by simp_all rw [Multiset.count_cons_of_ne this M] simp_all - else - have : M.count b = (a ::ₘ M).count b := by + · have : M.count b = (a ::ₘ M).count b := by have : b ≠ a := by simp_all rw [Multiset.count_cons_of_ne this M] rw [this] @@ -131,29 +126,24 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : Mult ∃ M', N = (a ::ₘ M') ∧ (MultisetRedLt M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by rcases H with ⟨X, Y, a0, H1, H0, H2⟩ - if hyp : a = a0 then - exists Y; right; apply And.intro - · rw [H1] - rw [add_left_inj] - rw [add_comm, Multiset.singleton_add] at H0 - simp_all - · simp_all - else - exists (Y + (M - {a0})) + by_cases hyp : a = a0 + · exists Y; right; apply And.intro + · rw [H1, add_left_inj] + rw [add_comm, Multiset.singleton_add] at H0 + simp_all + · simp_all + · exists (Y + (M - {a0})) left constructor --; apply And.intro · rw [H1] have : X = (M - {a0} + {a}) := by rw [add_comm, Multiset.singleton_add] at * ext b - rw [Multiset.count_cons] simp [Multiset.ext, Multiset.count_cons] at H0 - if h : b = a then - rw [h] - have := H0 b + by_cases h : b = a + · have := H0 b aesop - else - have := H0 b + · have := H0 b simp [mul_singleton_erase] aesop subst this @@ -168,8 +158,7 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : Mult have a0M: a0 ∈ M := by apply mul_mem_not_erase · change M = Multiset.erase (a0 ::ₘ X) a - rw [mul_singleton_erase] at this0 - rw [add_comm] at this0 + rw [mul_singleton_erase, add_comm] at this0 exact this0 · exact hyp apply mem_erase_cons @@ -263,8 +252,7 @@ lemma Lt_wf [DecidableEq α] [LT α] lemma mem_leq_diff [DecidableEq α] : ∀ (M N: Multiset α), N ≤ M → M = M - N + N := by intros M N h - rw [← Multiset.union_def] - rw [Multiset.eq_union_left] + rw [← Multiset.union_def, Multiset.eq_union_left] exact h lemma le_sub_add {α} [dec : DecidableEq α]: @@ -274,12 +262,9 @@ lemma le_sub_add {α} [dec : DecidableEq α]: have : M - N + P + N = M - N + N + P := by have : M - N + P + N = M - N + (P + N) := by apply add_assoc (M - N) - rw [this] have : M - N + N + P = M - N + (N + P) := by apply add_assoc (M - N) - rw [this] have : P + N = N + P := by apply add_comm P N simp_all only [ge_iff_le] - rw [this] have : M + P - N + N = M + P := by have : M + P - N + N = (M + P) ∪ N := by apply Eq.refl have : (M + P) ∪ N = M + P:= by @@ -287,7 +272,6 @@ lemma le_sub_add {α} [dec : DecidableEq α]: have : M ≤ M + P := by simp_all only [ge_iff_le, le_add_iff_nonneg_right, zero_le] apply le_trans h this simp_all only [ge_iff_le] - rw [this] have : M - N + N = M := by have : M = M - N + N := by apply mem_leq_diff @@ -309,14 +293,13 @@ lemma double_split {α} [dec : DecidableEq α]: have H0 : M.count x + N.count x = P.count x + Q.count x := by rw [Multiset.ext] at h simp_all only [Multiset.mem_add, Multiset.count_add] - if l_u : M.count x ≤ P.count x then - have : N.count x ≥ Q.count x := by linarith + by_cases l_u : M.count x ≤ P.count x + · have : N.count x ≥ Q.count x := by linarith simp_all only [ge_iff_le, min_eq_right] apply le_eq_sub (M.count x) (N.count x) (P.count x) (Q.count x) · exact l_u · exact H0 - else - simp_all only [not_le, gt_iff_lt] + · simp_all only [not_le, gt_iff_lt] have : Multiset.count x N ≤ Multiset.count x Q := by linarith have := le_of_lt l_u simp_all @@ -327,8 +310,7 @@ lemma in_notin_diff {α} [DecidableEq α]: have : Multiset.count x X ≥ 1 := by rw [← Multiset.one_le_count_iff_mem] at x_in_X exact x_in_X - rw [← Multiset.one_le_count_iff_mem] - rw [Multiset.count_sub] + rw [← Multiset.one_le_count_iff_mem, Multiset.count_sub] simp_all only [not_false_eq_true, Multiset.count_eq_zero_of_not_mem, tsub_zero] -- `MultisetLT` is transitive. Two lemmas needed: double_split, in_notin_diff @@ -342,60 +324,51 @@ lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: · rw [P2_def] have : Z1 ∩ Z2 + (Y2 + (Y1 - X2)) = Z1 ∩ Z2 + (Y1 - X2) + Y2 := by have : (Y2 + (Y1 - X2)) = (Y1 - X2) + Y2 := by rw [add_comm] - rw [this] - rw [add_assoc] + rw [this, add_assoc] rw [this] have : Z1 ∩ Z2 + (Y1 - X2) = Z2 ∩ Z1 + (Y1 - X2) := by rw [Multiset.inter_comm] - rw [this] - rw [← double_split] - rw [add_comm] - rw [← N2_def] - rw [N1_def] + rw [this,← double_split] + -- Unable to merge into one line. Why? + rw [add_comm, ← N2_def, N1_def] apply add_comm · rw [M1_def] have : Z1 ∩ Z2 + (X1 + (X2 - Y1)) = Z1 ∩ Z2 + (X2 - Y1) + X1 := by have : (X1 + (X2 - Y1)) = (X2 - Y1) + X1 := by rw [add_comm] - rw [this] - rw [add_assoc] + rw [this, add_assoc] rw [this, add_left_inj] apply double_split - rw [add_comm] - rw [← N1_def] - rw [N2_def] + rw [add_comm, ← N1_def, N2_def] apply add_comm · intros y y_in_union - if y_in : y ∈ Y2 then - rcases (Ord2 y y_in) with ⟨x, x_in_X2, y_lt_x⟩ - if x_in : x ∈ Y1 then - rcases (Ord1 x x_in) with ⟨x', x'_in_X1, x_lt_x'⟩ + by_cases y_in : y ∈ Y2 + · rcases (Ord2 y y_in) with ⟨x, x_in_X2, y_lt_x⟩ + by_cases x_in : x ∈ Y1 + · rcases (Ord1 x x_in) with ⟨x', x'_in_X1, x_lt_x'⟩ use x' constructor · rw [Multiset.mem_add] constructor exact x'_in_X1 · exact lt_trans y_lt_x x_lt_x' - else - use x + · use x + constructor + · rw [add_comm, Multiset.mem_add] constructor - · rw [add_comm] - rw [Multiset.mem_add] - constructor - apply in_notin_diff - exact x_in_X2 - exact x_in - · exact y_lt_x - else - have y_in : y ∈ (Y1 - X2) := by simp_all only [Multiset.mem_add, false_or] - let h := (Ord1 y) - have y_in_Y1 : y ∈ Y1 := by - have : Y1 - X2 ≤ Y1 := by simp_all only [tsub_le_iff_right, le_add_iff_nonneg_right, - zero_le] - apply Multiset.mem_of_le - exact this - exact y_in - let _ := h y_in_Y1 - aesop + apply in_notin_diff + exact x_in_X2 + exact x_in + · exact y_lt_x + · have y_in : y ∈ (Y1 - X2) := by simp_all only [Multiset.mem_add, false_or] + let h := (Ord1 y) + have y_in_Y1 : y ∈ Y1 := by + have : Y1 - X2 ≤ Y1 := by simp_all only [tsub_le_iff_right, le_add_iff_nonneg_right, + zero_le] + apply Multiset.mem_of_le + exact this + exact y_in + let _ := h y_in_Y1 + aesop lemma direct_subset_red [dec : DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (LTMN : MultisetLT M N) : @@ -472,32 +445,30 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] rcases X_lt_Y with ⟨t, t_in_Y, x_lt_t⟩ use t constructor - · if t_in_newY : t ∈ newY then - exact t_in_newY - else - exfalso - have : t = y := by - have : Y = newY + {y} := by - unfold_let newY - rw [add_comm, Multiset.singleton_add] - simp [Multiset.cons_erase claim] - rw [this] at t_in_Y - rw [Multiset.mem_add] at t_in_Y - have : t ∈ ( {y} : Multiset α) := Or.resolve_left t_in_Y t_in_newY - rwa [← Multiset.mem_singleton] - have x_in_fy : x ∈ f y := by - unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ - have x_notin_Xfy : x ∉ X - f y := by - by_contra - let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') - have : X - f y = neg_f y := by - have fy_negfy_X : f y + neg_f y = X := Multiset.filter_add_not _ _ - rw [← fy_negfy_X, add_tsub_cancel_left] - have x_in_neg_fy : x ∈ neg_f y := this ▸ x_in - subst_eqs - unfold_let neg_f at * - simp_all only [Multiset.mem_filter] - exact x_notin_Xfy x_in + · by_cases t_in_newY : t ∈ newY + · exact t_in_newY + · exfalso + have : t = y := by + have : Y = newY + {y} := by + unfold_let newY + rw [add_comm, Multiset.singleton_add] + simp [Multiset.cons_erase claim] + rw [this, Multiset.mem_add] at t_in_Y + have : t ∈ ( {y} : Multiset α) := Or.resolve_left t_in_Y t_in_newY + rwa [← Multiset.mem_singleton] + have x_in_fy : x ∈ f y := by + unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ + have x_notin_Xfy : x ∉ X - f y := by + by_contra + let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') + have : X - f y = neg_f y := by + have fy_negfy_X : f y + neg_f y = X := Multiset.filter_add_not _ _ + rw [← fy_negfy_X, add_tsub_cancel_left] + have x_in_neg_fy : x ∈ neg_f y := this ▸ x_in + subst_eqs + unfold_let neg_f at * + simp_all only [Multiset.mem_filter] + exact x_notin_Xfy x_in · exact x_lt_t -- single step N to N' · have : MultisetRedLt N' N := by @@ -507,8 +478,7 @@ lemma direct_subset_red [dec : DecidableEq α] [Preorder α] unfold_let newY; rw [add_comm, Multiset.singleton_add] apply Multiset.cons_erase claim have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc - rw [this] - rw [newY_y_Y] + rw [this, newY_y_Y] exact N_def · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 apply TransGen.single From 9a6436149d5d901d88ad4c73ce0d4badcdffc46c Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 7 Aug 2024 19:15:09 +0200 Subject: [PATCH 12/32] better naming --- Mathlib/Data/Multiset/DershowitzManna.lean | 476 +++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 Mathlib/Data/Multiset/DershowitzManna.lean diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean new file mode 100644 index 0000000000000..425df0fb336b8 --- /dev/null +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -0,0 +1,476 @@ +/- +Copyright (c) 2024 Haitian Wang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Haitian Wang, Malvin Gattinger +-/ +import Mathlib.Tactic.Linarith +import Mathlib.Data.Multiset.Basic +import Mathlib.Logic.Relation + +/-! +# Dershowitz-Manna ordering + +In this file we define the _Dershowitz-Manna ordering_ on multisets. +We prove that, given a well-founded partial order on the underlying set, +the Dershowitz-Manna ordering defined over multisets is also well-founded. + +## Main results + +- `MultisetDMLT` : the standard definition fo the `Dershowitz-Manna ordering`. +- `dm_wf` : the main theorem about the `Dershowitz-Manna ordering` being well-founded. +- `TransLT_eq_DMLT` : two definitions of the `Dershowitz-Manna ordering` are equivalent. + +## References + +* [Wikipedia, Dershowitz–Manna ordering*] +(https://en.wikipedia.org/wiki/Dershowitz%E2%80%93Manna_ordering) + +* [CoLoR](https://github.com/fblanqui/color), a Coq library on rewriting theory and termination. + Our code here is inspired by their formalization and the theorem is called `mOrd_wf` in the file + [MultisetList.v](https://github.com/fblanqui/color/blob/1.8.5/Util/Multiset/MultisetOrder.v). + +-/ + +variable {α : Type*} + +/-- The standard Dershowitz–Manna ordering: -/ +inductive MultisetDMLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := + | DMLT : ∀ (X Y Z : Multiset α), + Y ≠ ∅ → + M = Z + X → + N = Z + Y → + (∀ x ∈ X, ∃ y ∈ Y, x < y) → MultisetDMLT M N + +/-- MultisetRedLT is a special case of MultisetDMLT. The transitive closure of it is used to define + an equivalent (proved later) version of the ordering. -/ +inductive MultisetRedLT [DecidableEq α] [LT α] (M N : Multiset α) : Prop := + | RedLT : ∀ (X Y : Multiset α) (a : α) , + (M = X + Y) → + (N = X + {a}) → + (∀ y, y ∈ Y → y < a) → MultisetRedLT M N + +open Relation + +/-- MultisetTransLT is the transitive closure of MultisetRedLT and is equivalent to MultisetDMLT + (proved later). -/ +def MultisetTransLT [DecidableEq α] [LT α] : Multiset α → Multiset α → Prop := + TransGen MultisetRedLT + +/-- A shorthand notation: AccM defines the accessibility relation given MultisetRedLT. -/ +def AccM [DecidableEq α] [Preorder α] : Multiset α → Prop := Acc MultisetRedLT + +/- MultisetRedLT is a special case of MultisetDMLT. -/ +theorem dmLT_of_redLT [DecidableEq α] [Preorder α] (M N : Multiset α) (h : MultisetRedLT M N): + MultisetDMLT M N := by + rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ + apply MultisetDMLT.DMLT Y {a} X _ M_def N_def + · simpa + · simp + +/- Some useful lemmas about Multisets and the defined relations, some of which should be added to + 'mathlib4/Mathlib/Data/Multiset/Basic.lean': -/ + +lemma not_redLT_zero [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedLT M 0 := by + intro h + cases h with + | RedLT X Y a M nonsense _ => + have contra : a ∈ (0 : Multiset α):= by + rw [nonsense] + simp_all only [Multiset.mem_add, Multiset.mem_singleton, or_true] + contradiction + +-- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' +lemma mul_singleton_erase [DecidableEq α] {a : α} {M : Multiset α} : + M - {a} = M.erase a := by + ext + simp [Multiset.erase_singleton, Multiset.count_singleton] + split <;> simp_all + +-- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' +lemma in_of_ne_of_cons_erase [DecidableEq α] {a a0: α} {M X : Multiset α} + (H : M = (a0 ::ₘ X).erase a) (hyp : ¬ a = a0) : a0 ∈ M := by + rw [H, Multiset.mem_erase_of_ne fun h ↦ hyp <| id <| Eq.symm h, Multiset.mem_cons] + tauto + +-- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' +lemma singleton_add_sub_of_cons_add [DecidableEq α] {a a0: α} {M X : Multiset α} + (H : a ::ₘ M = X + {a0}) : M = X + {a0} - {a} := by + by_cases hyp : a = a0 + · rw [hyp, add_comm] at H + simp_all [Multiset.singleton_add] + · have a0_a: a0 ≠ a := by rw [eq_comm] at hyp; exact hyp + ext b + simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] + have H : Multiset.count b (a ::ₘ M) = Multiset.count b (X + {a0}) := by simp_all only + [Multiset.count_add] + by_cases ba : b = a + · rw [ba] at * + have : (a ::ₘ M).count a = M.count a + 1 := by simp + simp_all + by_cases ba0 : b = a0 + · have : (a ::ₘ M).count a0 = X.count a0 + 1 := by + subst_eqs + rw [add_comm, Multiset.singleton_add] at H + simp_all + have : M.count a0 = Multiset.count a0 (a ::ₘ M) := by + have : a0 ≠ a := by simp_all + rw [Multiset.count_cons_of_ne this M] + simp_all + · have : M.count b = (a ::ₘ M).count b := by + have : b ≠ a := by simp_all + rw [Multiset.count_cons_of_ne this M] + rw [this] + simp_all + +lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : MultisetRedLT N (a ::ₘ M)) : + ∃ M', + N = (a ::ₘ M') ∧ (MultisetRedLT M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by + rcases h with ⟨X, Y, a0, h1, h0, h2⟩ + by_cases hyp : a = a0 + · exists Y; right; apply And.intro + · rw [h1, add_left_inj] + rw [add_comm, Multiset.singleton_add] at h0 + simp_all + · simp_all + · exists (Y + (M - {a0})) + left + constructor --; apply And.intro + · rw [h1] + have : X = (M - {a0} + {a}) := by + rw [add_comm, Multiset.singleton_add] at * + ext b + simp [Multiset.ext, Multiset.count_cons] at h0 + by_cases h : b = a + · have := h0 b + aesop + · have := h0 b + simp [mul_singleton_erase] + aesop + subst this + rw [add_comm] + nth_rewrite 2 [add_comm] + rw [Multiset.singleton_add, Multiset.add_cons] + · constructor + · change Y + (M - {a0}) = (M - {a0}) + Y + rw [add_comm] + · change M = M - {a0} + {a0} + have this0: M = X + {a0} - {a} := by apply singleton_add_sub_of_cons_add; exact h0 + have a0M: a0 ∈ M := by + apply in_of_ne_of_cons_erase + · change M = Multiset.erase (a0 ::ₘ X) a + rw [mul_singleton_erase, add_comm] at this0 + exact this0 + · exact hyp + rw [add_comm] + simp_all [Multiset.singleton_add] + exact h2 + +lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) + (_ : ∀ b M , LT.lt b a → AccM M → AccM (b ::ₘ M)) + (_ : AccM M0) + (_ : ∀ M, MultisetRedLT M M0 → AccM (a ::ₘ M)) : + AccM (a ::ₘ M0) := by + constructor + intros N N_lt + change AccM N + rcases (red_insert N_lt) with ⟨x, H, h0⟩ + case h.intro.inr h => + rcases h with ⟨H, h0⟩ + rw [H] + clear H -- Needed to make simp_all below safe. + induction x using Multiset.induction with + | empty => + simpa + | cons h => + simp_all only [Multiset.mem_cons, or_true, implies_true, true_implies, forall_eq_or_imp, + Multiset.add_cons] + case h.intro.inl.intro => + simp_all + +lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) + (H : ∀ (b : α), ∀ M, LT.lt b a → AccM M → AccM (b ::ₘ M)) : + ∀ M, AccM M → AccM (a ::ₘ M) := by + unfold AccM + intros M h0 + induction h0 with + | intro x wfH wfh2 => + apply acc_cons + · simpa + · constructor + simpa + · simpa + +lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : + ∀ (a:α), Acc LT.lt a → ∀ M, AccM M → AccM (a ::ₘ M) := by + intro w w_a + induction w_a with + | intro x _ ih => + intro M accM1 + apply @acc_cons_of_acc α _ _ _ _ _ accM1 + simp_all + +/- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is +accessible given the `MultisetRedLT` relation. -/ +lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : + ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → AccM M := by + intros M wf_el + induction M using Multiset.induction_on with + | empty => + constructor + intro y y_lt + absurd y_lt + apply not_redLT_zero + | cons _ _ ih => + apply acc_cons_of_acc_of_lt + · apply wf_el + simp_all + · apply ih + intros + apply wf_el + simp_all + +/- If `LT.lt` is well-founded, then `MultisetRedLT` is well-founded. -/ +lemma redLT_wf [DecidableEq α] [Preorder α] + (wf_lt : WellFoundedLT α) : WellFounded (MultisetRedLT : Multiset α → Multiset α → Prop) := by + constructor + intros a + apply acc_of_acc_lt + intros x _ + apply wf_lt.induction x + intros y h + apply Acc.intro y + assumption + +/- If `MultisetRedLT` is well-founded, then its transitive closure `MultisetTransLT` is also +well-founded. -/ +lemma transLT_wf [DecidableEq α] [LT α] + (h : WellFounded (MultisetRedLT : Multiset α → Multiset α → Prop)) : + WellFounded (MultisetTransLT : Multiset α → Multiset α → Prop) := by + unfold MultisetTransLT + apply WellFounded.transGen + assumption + +-- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' +lemma inter_add_sub_of_eq {α} [dec : DecidableEq α] {M N P Q: Multiset α} (h : M + N = P + Q) : + N = N ∩ Q + (P - M) := by + ext x + rw [Multiset.count_add, Multiset.count_inter, Multiset.count_sub] + have h0 : M.count x + N.count x = P.count x + Q.count x := by + rw [Multiset.ext] at h + simp_all only [Multiset.mem_add, Multiset.count_add] + by_cases l_u : M.count x ≤ P.count x + · have : N.count x ≥ Q.count x := by linarith + simp_all only [ge_iff_le, min_eq_right] + have := tsub_add_cancel_of_le l_u + linarith + · simp_all only [not_le, gt_iff_lt] + have : Multiset.count x N ≤ Multiset.count x Q := by linarith + have := le_of_lt l_u + simp_all + +-- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' +lemma mem_sub_of_not_mem_of_mem {α} [DecidableEq α] (x : α) (X Y: Multiset α) (x_in_X : x ∈ X) + (x_notin_Y : x ∉ Y) : x ∈ X - Y := by + have : Multiset.count x X ≥ 1 := by + rw [← Multiset.one_le_count_iff_mem] at x_in_X + exact x_in_X + rw [← Multiset.one_le_count_iff_mem, Multiset.count_sub] + simp_all only [not_false_eq_true, Multiset.count_eq_zero_of_not_mem, tsub_zero] + +-- `MultisetDMLT` is transitive. +lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: + ∀ (M N P : Multiset α) , MultisetDMLT N M → MultisetDMLT P N → MultisetDMLT P M := by + intros M N P LTNM LTPN + rcases LTNM with ⟨Y1, X1, Z1, X1_ne, N1_def, M1_def, Ord1⟩ + rcases LTPN with ⟨Y2, X2, Z2, _, P2_def, N2_def, Ord2⟩ + apply MultisetDMLT.DMLT (Y2 + (Y1 - X2)) (X1 + (X2 - Y1)) (Z1 ∩ Z2) + · simp_all only [Multiset.empty_eq_zero, ne_eq, add_eq_zero_iff, false_and, not_false_eq_true] + · rw [P2_def] + have : Z1 ∩ Z2 + (Y2 + (Y1 - X2)) = Z1 ∩ Z2 + (Y1 - X2) + Y2 := by + have : (Y2 + (Y1 - X2)) = (Y1 - X2) + Y2 := by rw [add_comm] + rw [this, add_assoc] + rw [this] + have : Z1 ∩ Z2 + (Y1 - X2) = Z2 ∩ Z1 + (Y1 - X2) := by + rw [Multiset.inter_comm] + rw [this,← inter_add_sub_of_eq] + rw [add_comm, ← N2_def, N1_def] + apply add_comm + · rw [M1_def] + have : Z1 ∩ Z2 + (X1 + (X2 - Y1)) = Z1 ∩ Z2 + (X2 - Y1) + X1 := by + have : (X1 + (X2 - Y1)) = (X2 - Y1) + X1 := by rw [add_comm] + rw [this, add_assoc] + rw [this, add_left_inj] + apply inter_add_sub_of_eq + rw [add_comm, ← N1_def, N2_def] + apply add_comm + · intros y y_in_union + by_cases y_in : y ∈ Y2 + · rcases (Ord2 y y_in) with ⟨x, x_in_X2, y_lt_x⟩ + by_cases x_in : x ∈ Y1 + · rcases (Ord1 x x_in) with ⟨x', x'_in_X1, x_lt_x'⟩ + use x' + constructor + · rw [Multiset.mem_add] + constructor + exact x'_in_X1 + · exact lt_trans y_lt_x x_lt_x' + · use x + constructor + · rw [add_comm, Multiset.mem_add] + constructor + apply mem_sub_of_not_mem_of_mem + exact x_in_X2 + exact x_in + · exact y_lt_x + · have y_in : y ∈ (Y1 - X2) := by simp_all only [Multiset.mem_add, false_or] + let h := (Ord1 y) + have y_in_Y1 : y ∈ Y1 := by + have : Y1 - X2 ≤ Y1 := by simp_all only [tsub_le_iff_right, le_add_iff_nonneg_right, + zero_le] + apply Multiset.mem_of_le + exact this + exact y_in + let _ := h y_in_Y1 + aesop + +lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] + [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (DMLTMN : MultisetDMLT M N) : + MultisetTransLT M N := by + -- intros M N LTXY + cases DMLTMN + case DMLT X Y Z Y_not_empty MZX NZY h => + unfold MultisetTransLT + revert Z X M N + induction Y using Multiset.strongInductionOn + case ih Y IH => + intro M N X Z M_def N_def X_lt_Y + cases em (Multiset.card Y = 0) + · simp_all + cases em (Multiset.card Y = 1) + case inl hyp' hyp=> + rw [Multiset.card_eq_one] at hyp + rcases hyp with ⟨y,Y'_def⟩ + apply TransGen.single + rw [Y'_def] at N_def + apply @MultisetRedLT.RedLT α _ _ M N Z X y M_def N_def + simp [Y'_def] at X_lt_Y + exact X_lt_Y + case inr hyp' hyp => + have : ∃ a, a ∈ Y := by + rw [← Y.card_pos_iff_exists_mem] + cases foo : Multiset.card Y + tauto + simp + rcases this with ⟨y,claim⟩ + let newY := Y.erase y + have newY_nonEmpty : newY ≠ ∅ := by + have : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by + intros n h0 h1 + cases n + case zero => contradiction + case succ m => + cases m + case zero => contradiction + case succ n=> + apply Nat.succ_le_succ + simp_all only [le_add_iff_nonneg_left, zero_le] + have : 0 < Multiset.card (Multiset.erase Y y) := by aesop + rw [Multiset.card_pos] at this + simp_all only [Multiset.empty_eq_zero, ne_eq, not_false_eq_true] + have newY_sub_Y : newY < Y := by simp (config := {zetaDelta := true}); exact claim + let f : α → Multiset α := fun y' => X.filter (fun x => x < y') -- DecidableRel + let N' := Z + newY + f y + apply @transitive_transGen _ _ _ N' + -- step from N' to M + · apply IH newY newY_sub_Y newY_nonEmpty + change M = (Z + f y) + (X - f y) + · ext a + have count_lt := Multiset.count_le_of_le a (Multiset.filter_le (fun x => x < y) X) + rw [M_def] + simp_all only [Multiset.empty_eq_zero, ne_eq, Multiset.card_eq_zero, not_false_eq_true, + Multiset.count_add, Multiset.count_sub] + let x := Multiset.count a X + let z := Multiset.count a Z + let fx := Multiset.count a (Multiset.filter (fun x => x < y) X) + change z + x = z + fx + (x - fx) + change fx ≤ x at count_lt + have : x = fx + (x - fx) := by simp_all only [add_tsub_cancel_of_le] + linarith + · unfold_let N' + rw [add_assoc, add_assoc, add_comm newY (f y)] + · intro x x_in + let X_lt_Y := X_lt_Y x + have x_in_X : x ∈ X := by + have Xfy_le_X : X - f y ≤ X:= by simp (config := {zetaDelta := true}) + apply Multiset.mem_of_le Xfy_le_X + exact x_in + let X_lt_Y := X_lt_Y x_in_X + rcases X_lt_Y with ⟨t, t_in_Y, x_lt_t⟩ + use t + constructor + · by_cases t_in_newY : t ∈ newY + · exact t_in_newY + · exfalso + have : t = y := by + have : Y = newY + {y} := by + unfold_let newY + rw [add_comm, Multiset.singleton_add] + simp [Multiset.cons_erase claim] + rw [this, Multiset.mem_add] at t_in_Y + have : t ∈ ( {y} : Multiset α) := Or.resolve_left t_in_Y t_in_newY + rwa [← Multiset.mem_singleton] + have x_in_fy : x ∈ f y := by + unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ + have x_notin_Xfy : x ∉ X - f y := by + by_contra + let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') + have : X - f y = neg_f y := by + have fy_negfy_X : f y + neg_f y = X := Multiset.filter_add_not _ _ + rw [← fy_negfy_X, add_tsub_cancel_left] + have x_in_neg_fy : x ∈ neg_f y := this ▸ x_in + subst_eqs + unfold_let neg_f at * + simp_all only [Multiset.mem_filter] + exact x_notin_Xfy x_in + · exact x_lt_t + -- single step N to N' + · have : MultisetRedLT N' N := by + apply MultisetRedLT.RedLT (Z + newY) (f y) y + · rfl + · have newY_y_Y: newY + {y} = Y := by + unfold_let newY; rw [add_comm, Multiset.singleton_add] + apply Multiset.cons_erase claim + have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc + rw [this, newY_y_Y] + exact N_def + · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 + apply TransGen.single + exact this + +/- MultisetTransLT and MultisetDMLT are equivalent. -/ +lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: + (MultisetTransLT : Multiset α → Multiset α → Prop) = + (MultisetDMLT : Multiset α → Multiset α → Prop) := by + funext X Y + apply propext + constructor + · -- TransLT → DMLT: + intros TransLT + induction TransLT with + | single TransLT => + rcases TransLT with ⟨Z, X, y, a_def, b_def, X_lt_y⟩ + use X + · simp + · simpa + | tail _ aih bih => -- it suffices to show MultisetDMLT is transitive + apply dmlt_trans _ _ _ _ bih + apply dmLT_of_redLT + assumption + · -- DMLT → TransLT: + apply transLT_of_dmLT + +/- The desired theorem: If `LT.lt` is well-founded, then `MultisetDMLT` is well-founded. -/ +theorem dmLT_wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] + (wf_lt : WellFoundedLT α) :WellFounded (MultisetDMLT : Multiset α → Multiset α → Prop) := by + rw [← transLT_eq_dmLT] + exact transLT_wf (redLT_wf wf_lt) From db3c9e539f519cf8300f60f2af77c5c0a661136b Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 7 Aug 2024 19:17:54 +0200 Subject: [PATCH 13/32] better naming --- Mathlib.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/Mathlib.lean b/Mathlib.lean index f791478c71b86..81fd1c29b4565 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2379,6 +2379,7 @@ import Mathlib.Data.Multiset.Antidiagonal import Mathlib.Data.Multiset.Basic import Mathlib.Data.Multiset.Bind import Mathlib.Data.Multiset.Dedup +import Mathlib.Data.Multiset.DershowitzManna import Mathlib.Data.Multiset.FinsetOps import Mathlib.Data.Multiset.Fintype import Mathlib.Data.Multiset.Fold From 49c2cd858c7a9e16206d213709c6dbcf841ddeed Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:28:37 +0200 Subject: [PATCH 14/32] remove Order.lean --- Mathlib.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib.lean b/Mathlib.lean index 81fd1c29b4565..0847e9c2999c8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2388,7 +2388,6 @@ import Mathlib.Data.Multiset.Interval import Mathlib.Data.Multiset.Lattice import Mathlib.Data.Multiset.NatAntidiagonal import Mathlib.Data.Multiset.Nodup -import Mathlib.Data.Multiset.Order import Mathlib.Data.Multiset.OrderedMonoid import Mathlib.Data.Multiset.Pi import Mathlib.Data.Multiset.Powerset From 22316b8fd4c3894bf49b35ca1cb97cb52fe1925a Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:42:09 +0200 Subject: [PATCH 15/32] remove order --- Mathlib/Data/Multiset/Order.lean | 513 ------------------------------- 1 file changed, 513 deletions(-) delete mode 100644 Mathlib/Data/Multiset/Order.lean diff --git a/Mathlib/Data/Multiset/Order.lean b/Mathlib/Data/Multiset/Order.lean deleted file mode 100644 index f89b0d1d9d9e9..0000000000000 --- a/Mathlib/Data/Multiset/Order.lean +++ /dev/null @@ -1,513 +0,0 @@ -/- -Copyright (c) 2024 Haitian Wang. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Haitian Wang, Malvin Gattinger --/ -import Mathlib.Tactic.Linarith -import Mathlib.Data.Multiset.Basic -import Mathlib.Logic.Relation - -/-! -# Dershowitz-Manna ordering - -In this file we define the _Dershowitz-Manna ordering_ on multisets. -We prove that, given a well-founded partial order on the underlying set, -the Dershowitz-Manna ordering defined over multisets is also well-founded. - -## Main results - -- `MultisetLT` : the standard definition -- `dm_wf` : the main theorem about the `Dershowitz-Manna ordering`. -- `Lt_LT_equiv` : two definitions of the Dershowitz-Manna ordering are equivalent. - -## References - -* [Wikipedia, Dershowitz–Manna ordering*] -(https://en.wikipedia.org/wiki/Dershowitz%E2%80%93Manna_ordering) - -* [CoLoR](https://github.com/fblanqui/color), a Coq library on rewriting theory and termination. - Our code here is inspired by their version of called `mOrd_wf` in the file - [MultisetList.v](https://github.com/fblanqui/color/blob/1.8.5/Util/Multiset/MultisetList.v). - --/ - -variable {α : Type*} - -/-- The standard Dershowitz–Manna ordering: -/ -inductive MultisetLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := - | MLT : ∀ (X Y Z: Multiset α), - Y ≠ ∅ → - M = Z + X → - N = Z + Y → - (∀ x ∈ X, ∃ y ∈ Y, x < y) → MultisetLT M N - -/-- MultisetRedLt is a special case of MultisetLT. The transitive closure of it is used to define -an equivalent (proved later) version of the ordering. -/ -inductive MultisetRedLt [DecidableEq α][LT α] (M N : Multiset α) : Prop := - | RedLt : ∀ (X Y:Multiset α) (a : α) , - (M = X + Y) → - (N = X + {a}) → - (∀ y, y ∈ Y → y < a) → MultisetRedLt M N - -open Relation - -/-- MultisetLt is the transitive closure of MultisetRedLt and is equivalent to MultisetLT - (proved later). -/ -def MultisetLt [DecidableEq α][LT α] : Multiset α → Multiset α → Prop := TransGen MultisetRedLt - -/-- AccM_1 defines the accessibility relation given MultisetRedLt. -/ -def AccM_1 [DecidableEq α][Preorder α] : Multiset α → Prop := Acc MultisetRedLt - -/- MultisetRedLt is a special case of MultisetLT. -/ -theorem redLt_LT [DecidableEq α] [Preorder α] (M N : Multiset α) : - MultisetRedLt M N → MultisetLT M N := by - intro hyp - rcases hyp with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ - apply MultisetLT.MLT Y {a} X _ M_def N_def - · simpa - · simp - -/- Some useful lemmas about Multisets and the defined relations: -/ -lemma not_MultisetRedLt_0 [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedLt M 0 := by - intro h - cases h with - | RedLt X Y a M nonsense _ => - have contra : a ∈ (0 : Multiset α):= by - rw [nonsense] - simp_all only [Multiset.mem_add, Multiset.mem_singleton, or_true] - contradiction - -lemma mul_singleton_erase [DecidableEq α] {a : α} {M : Multiset α} : - M - {a} = M.erase a := by - ext - simp [Multiset.erase_singleton, Multiset.count_singleton] - split <;> simp_all - -lemma mul_mem_not_erase [DecidableEq α] {a a0: α} {M X : Multiset α} - (H : M = (a0 ::ₘ X).erase a) (hyp : ¬ a = a0) : a0 ∈ M := by - rw [H, Multiset.mem_erase_of_ne fun h ↦ hyp <| id <| Eq.symm h, Multiset.mem_cons] - tauto - -lemma mem_erase_cons [DecidableEq α] {a0: α} {M : Multiset α} (_ : a0 ∈ M) : - M = M - {a0} + {a0} := by - rw [add_comm] - simp_all [Multiset.singleton_add, mul_singleton_erase] - -lemma cons_erase [DecidableEq α] {a a0: α} {M X : Multiset α} - (H : a ::ₘ M = X + {a0}) : M = X + {a0} - {a} := by - by_cases hyp : a = a0 - · rw [hyp, add_comm] at H - simp_all [Multiset.singleton_add] - · have a0_a: a0 ≠ a := by rw [eq_comm] at hyp; exact hyp - ext b - simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] - have H : Multiset.count b (a ::ₘ M) = Multiset.count b (X + {a0}) := by simp_all only - [Multiset.count_add] - by_cases ba : b = a - · rw [ba] at * - have : (a ::ₘ M).count a = M.count a + 1 := by simp - simp_all - by_cases ba0 : b = a0 - · have : (a ::ₘ M).count a0 = X.count a0 + 1 := by - subst_eqs - rw [add_comm, Multiset.singleton_add] at H - simp_all - have : M.count a0 = Multiset.count a0 (a ::ₘ M) := by - have : a0 ≠ a := by simp_all - rw [Multiset.count_cons_of_ne this M] - simp_all - · have : M.count b = (a ::ₘ M).count b := by - have : b ≠ a := by simp_all - rw [Multiset.count_cons_of_ne this M] - rw [this] - simp_all - -lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (H : MultisetRedLt N (a ::ₘ M)) : - ∃ M', - N = (a ::ₘ M') ∧ (MultisetRedLt M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by - rcases H with ⟨X, Y, a0, H1, H0, H2⟩ - by_cases hyp : a = a0 - · exists Y; right; apply And.intro - · rw [H1, add_left_inj] - rw [add_comm, Multiset.singleton_add] at H0 - simp_all - · simp_all - · exists (Y + (M - {a0})) - left - constructor --; apply And.intro - · rw [H1] - have : X = (M - {a0} + {a}) := by - rw [add_comm, Multiset.singleton_add] at * - ext b - simp [Multiset.ext, Multiset.count_cons] at H0 - by_cases h : b = a - · have := H0 b - aesop - · have := H0 b - simp [mul_singleton_erase] - aesop - subst this - rw [add_comm] - nth_rewrite 2 [add_comm] - rw [Multiset.singleton_add, Multiset.add_cons] - · constructor - · change Y + (M - {a0}) = (M - {a0}) + Y - rw [add_comm] - · change M = M - {a0} + {a0} - have this0: M = X + {a0} - {a} := by apply cons_erase; exact H0 - have a0M: a0 ∈ M := by - apply mul_mem_not_erase - · change M = Multiset.erase (a0 ::ₘ X) a - rw [mul_singleton_erase, add_comm] at this0 - exact this0 - · exact hyp - apply mem_erase_cons - · exact a0M - exact H2 - -lemma mord_wf_1 [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) - (H1 : ∀ b M , LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) - (H2 : AccM_1 M0) - (H3 : ∀ M, MultisetRedLt M M0 → AccM_1 (a ::ₘ M)) : - AccM_1 (a ::ₘ M0) := by - constructor - intros N N_lt - change AccM_1 N - rcases (red_insert N_lt) with ⟨x, H, H0⟩ - case h.intro.inr h => - rcases h with ⟨H, H0⟩ - rw [H] - clear H -- Needed to make simp_all below safe. - induction x using Multiset.induction with - | empty => - simpa - | cons h => - simp_all only [Multiset.mem_cons, or_true, implies_true, true_implies, forall_eq_or_imp, - Multiset.add_cons] - case h.intro.inl.intro => - simp_all - -lemma mord_wf_2 [DecidableEq α] [Preorder α] (a : α) - (H : ∀ (b : α), ∀ M, LT.lt b a → AccM_1 M → AccM_1 (b ::ₘ M)) : - ∀ M, AccM_1 M → AccM_1 (a ::ₘ M) := by - unfold AccM_1 - intros M H0 - induction H0 with - | intro x wfH wfH2 => - apply mord_wf_1 - · simpa - · constructor - simpa - · simpa - -lemma mord_wf_3[DecidableEq α] [Preorder α] : - ∀ (a:α), Acc LT.lt a → ∀ M, AccM_1 M → AccM_1 (a ::ₘ M) := by - intro w w_a - induction w_a with - | intro x _ ih => - intro M accM1 - apply @mord_wf_2 α _ _ _ _ _ accM1 - simp_all - -/- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is -accessible given the `MultisetRedLt` relation. -/ -lemma mred_acc [DecidableEq α] [Preorder α] : - ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → AccM_1 M := by - intros M wf_el - induction M using Multiset.induction_on with - | empty => - constructor - intro y y_lt - absurd y_lt - apply not_MultisetRedLt_0 - | cons _ _ ih => - apply mord_wf_3 - · apply wf_el - simp_all - · apply ih - intros - apply wf_el - simp_all - -/- If `LT.lt` is well-founded, then `MultisetRedLt` is well-founded. -/ -lemma RedLt_wf [DecidableEq α] [Preorder α] - (wf_lt : WellFoundedLT α) : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop) := by - constructor - intros a - apply mred_acc - intros x _ - apply wf_lt.induction x - intros y h - apply Acc.intro y - assumption - -/- If `MultisetRedLt` is well-founded, then its transitive closure `MultisetLt` is also -well-founded. -/ -lemma Lt_wf [DecidableEq α] [LT α] - (h : WellFounded (MultisetRedLt : Multiset α → Multiset α → Prop)) : - WellFounded (MultisetLt : Multiset α → Multiset α → Prop) := by - unfold MultisetLt - apply WellFounded.transGen - assumption - -lemma mem_leq_diff [DecidableEq α] : ∀ (M N: Multiset α), N ≤ M → M = M - N + N := by - intros M N h - rw [← Multiset.union_def, Multiset.eq_union_left] - exact h - -lemma le_sub_add {α} [dec : DecidableEq α]: - ∀ (M N P : Multiset α) , N ≤ M → M - N + P = M + P - N := by - intro M N P h - have : M - N + P + N = M + P - N + N := by - have : M - N + P + N = M - N + N + P := by - have : M - N + P + N = M - N + (P + N) := by - apply add_assoc (M - N) - have : M - N + N + P = M - N + (N + P) := by apply add_assoc (M - N) - have : P + N = N + P := by apply add_comm P N - simp_all only [ge_iff_le] - have : M + P - N + N = M + P := by - have : M + P - N + N = (M + P) ∪ N := by apply Eq.refl - have : (M + P) ∪ N = M + P:= by - apply Multiset.eq_union_left - have : M ≤ M + P := by simp_all only [ge_iff_le, le_add_iff_nonneg_right, zero_le] - apply le_trans h this - simp_all only [ge_iff_le] - have : M - N + N = M := by - have : M = M - N + N := by - apply mem_leq_diff - exact h - rw [← this] - simp_all only [ge_iff_le] - simp_all only [ge_iff_le, add_left_inj] - -lemma le_eq_sub : ∀ (M N P Q : ℕ) , M ≤ P → M + N = P + Q → N = Q + (P - M):= by - intros M N P Q h0 h1 - have := tsub_add_cancel_of_le h0 - linarith - -lemma double_split {α} [dec : DecidableEq α]: - ∀ (M N P Q: Multiset α) , M + N = P + Q → N = N ∩ Q + (P - M) := by - intros M N P Q h - ext x - rw [Multiset.count_add, Multiset.count_inter, Multiset.count_sub] - have H0 : M.count x + N.count x = P.count x + Q.count x := by - rw [Multiset.ext] at h - simp_all only [Multiset.mem_add, Multiset.count_add] - by_cases l_u : M.count x ≤ P.count x - · have : N.count x ≥ Q.count x := by linarith - simp_all only [ge_iff_le, min_eq_right] - apply le_eq_sub (M.count x) (N.count x) (P.count x) (Q.count x) - · exact l_u - · exact H0 - · simp_all only [not_le, gt_iff_lt] - have : Multiset.count x N ≤ Multiset.count x Q := by linarith - have := le_of_lt l_u - simp_all - -lemma in_notin_diff {α} [DecidableEq α]: - ∀ (x : α) (X Y: Multiset α) , x ∈ X → x ∉ Y → x ∈ X - Y := by - intros x X Y x_in_X x_notin_Y - have : Multiset.count x X ≥ 1 := by - rw [← Multiset.one_le_count_iff_mem] at x_in_X - exact x_in_X - rw [← Multiset.one_le_count_iff_mem, Multiset.count_sub] - simp_all only [not_false_eq_true, Multiset.count_eq_zero_of_not_mem, tsub_zero] - --- `MultisetLT` is transitive. Two lemmas needed: double_split, in_notin_diff -lemma LT_trans {α} [pre : Preorder α] [dec : DecidableEq α]: - ∀ (M N P : Multiset α) , MultisetLT N M → MultisetLT P N → MultisetLT P M := by - intros M N P LTNM LTPN - rcases LTNM with ⟨Y1, X1, Z1, X1_ne, N1_def, M1_def, Ord1⟩ - rcases LTPN with ⟨Y2, X2, Z2, _, P2_def, N2_def, Ord2⟩ - apply MultisetLT.MLT (Y2 + (Y1 - X2)) (X1 + (X2 - Y1)) (Z1 ∩ Z2) - · simp_all only [Multiset.empty_eq_zero, ne_eq, add_eq_zero_iff, false_and, not_false_eq_true] - · rw [P2_def] - have : Z1 ∩ Z2 + (Y2 + (Y1 - X2)) = Z1 ∩ Z2 + (Y1 - X2) + Y2 := by - have : (Y2 + (Y1 - X2)) = (Y1 - X2) + Y2 := by rw [add_comm] - rw [this, add_assoc] - rw [this] - have : Z1 ∩ Z2 + (Y1 - X2) = Z2 ∩ Z1 + (Y1 - X2) := by - rw [Multiset.inter_comm] - rw [this,← double_split] - -- Unable to merge into one line. Why? - rw [add_comm, ← N2_def, N1_def] - apply add_comm - · rw [M1_def] - have : Z1 ∩ Z2 + (X1 + (X2 - Y1)) = Z1 ∩ Z2 + (X2 - Y1) + X1 := by - have : (X1 + (X2 - Y1)) = (X2 - Y1) + X1 := by rw [add_comm] - rw [this, add_assoc] - rw [this, add_left_inj] - apply double_split - rw [add_comm, ← N1_def, N2_def] - apply add_comm - · intros y y_in_union - by_cases y_in : y ∈ Y2 - · rcases (Ord2 y y_in) with ⟨x, x_in_X2, y_lt_x⟩ - by_cases x_in : x ∈ Y1 - · rcases (Ord1 x x_in) with ⟨x', x'_in_X1, x_lt_x'⟩ - use x' - constructor - · rw [Multiset.mem_add] - constructor - exact x'_in_X1 - · exact lt_trans y_lt_x x_lt_x' - · use x - constructor - · rw [add_comm, Multiset.mem_add] - constructor - apply in_notin_diff - exact x_in_X2 - exact x_in - · exact y_lt_x - · have y_in : y ∈ (Y1 - X2) := by simp_all only [Multiset.mem_add, false_or] - let h := (Ord1 y) - have y_in_Y1 : y ∈ Y1 := by - have : Y1 - X2 ≤ Y1 := by simp_all only [tsub_le_iff_right, le_add_iff_nonneg_right, - zero_le] - apply Multiset.mem_of_le - exact this - exact y_in - let _ := h y_in_Y1 - aesop - -lemma direct_subset_red [dec : DecidableEq α] [Preorder α] - [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (LTMN : MultisetLT M N) : - MultisetLt M N := by - -- intros M N LTXY - cases LTMN - case MLT X Y Z Y_not_empty MZX NZY h => - unfold MultisetLt - revert Z X M N - induction Y using Multiset.strongInductionOn - case ih Y IH => - intro M N X Z M_def N_def X_lt_Y - cases em (Multiset.card Y = 0) - · simp_all - cases em (Multiset.card Y = 1) - case inl hyp' hyp=> - rw [Multiset.card_eq_one] at hyp - rcases hyp with ⟨y,Y'_def⟩ - apply TransGen.single - rw [Y'_def] at N_def - apply @MultisetRedLt.RedLt α _ _ M N Z X y M_def N_def - simp [Y'_def] at X_lt_Y - exact X_lt_Y - case inr hyp' hyp => - have : ∃ a, a ∈ Y := by - rw [← Y.card_pos_iff_exists_mem] - cases foo : Multiset.card Y - tauto - simp - rcases this with ⟨y,claim⟩ - let newY := Y.erase y - have newY_nonEmpty : newY ≠ ∅ := by - have : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by - intros n h0 h1 - cases n - case zero => contradiction - case succ m => - cases m - case zero => contradiction - case succ n=> - apply Nat.succ_le_succ - simp_all only [le_add_iff_nonneg_left, zero_le] - have : 0 < Multiset.card (Multiset.erase Y y) := by aesop - rw [Multiset.card_pos] at this - simp_all only [Multiset.empty_eq_zero, ne_eq, not_false_eq_true] - have newY_sub_Y : newY < Y := by simp (config := {zetaDelta := true}); exact claim - let f : α → Multiset α := fun y' => X.filter (fun x => x < y') -- DecidableRel - let N' := Z + newY + f y - apply @transitive_transGen _ _ _ N' - -- step from N' to M - · apply IH newY newY_sub_Y newY_nonEmpty - change M = (Z + f y) + (X - f y) - · ext a - have count_lt := Multiset.count_le_of_le a (Multiset.filter_le (fun x => x < y) X) - rw [M_def] - simp_all only [Multiset.empty_eq_zero, ne_eq, Multiset.card_eq_zero, not_false_eq_true, - Multiset.count_add, Multiset.count_sub] - let x := Multiset.count a X - let z := Multiset.count a Z - let fx := Multiset.count a (Multiset.filter (fun x => x < y) X) - change z + x = z + fx + (x - fx) - change fx ≤ x at count_lt - have : x = fx + (x - fx) := by simp_all only [add_tsub_cancel_of_le] - linarith - · unfold_let N' - rw [add_assoc, add_assoc, add_comm newY (f y)] - · intro x x_in - let X_lt_Y := X_lt_Y x - have x_in_X : x ∈ X := by - have Xfy_le_X : X - f y ≤ X:= by simp (config := {zetaDelta := true}) - apply Multiset.mem_of_le Xfy_le_X - exact x_in - let X_lt_Y := X_lt_Y x_in_X - rcases X_lt_Y with ⟨t, t_in_Y, x_lt_t⟩ - use t - constructor - · by_cases t_in_newY : t ∈ newY - · exact t_in_newY - · exfalso - have : t = y := by - have : Y = newY + {y} := by - unfold_let newY - rw [add_comm, Multiset.singleton_add] - simp [Multiset.cons_erase claim] - rw [this, Multiset.mem_add] at t_in_Y - have : t ∈ ( {y} : Multiset α) := Or.resolve_left t_in_Y t_in_newY - rwa [← Multiset.mem_singleton] - have x_in_fy : x ∈ f y := by - unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ - have x_notin_Xfy : x ∉ X - f y := by - by_contra - let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') - have : X - f y = neg_f y := by - have fy_negfy_X : f y + neg_f y = X := Multiset.filter_add_not _ _ - rw [← fy_negfy_X, add_tsub_cancel_left] - have x_in_neg_fy : x ∈ neg_f y := this ▸ x_in - subst_eqs - unfold_let neg_f at * - simp_all only [Multiset.mem_filter] - exact x_notin_Xfy x_in - · exact x_lt_t - -- single step N to N' - · have : MultisetRedLt N' N := by - apply MultisetRedLt.RedLt (Z + newY) (f y) y - · rfl - · have newY_y_Y: newY + {y} = Y := by - unfold_let newY; rw [add_comm, Multiset.singleton_add] - apply Multiset.cons_erase claim - have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc - rw [this, newY_y_Y] - exact N_def - · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 - apply TransGen.single - exact this - -/- MultisetLt and MultisetLT are equivalent. -/ -lemma Lt_LT_equiv [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: - (MultisetLt : Multiset α → Multiset α → Prop) = - (MultisetLT : Multiset α → Multiset α → Prop) := by - funext X Y - apply propext - constructor - · -- Lt → LT: - intros hLt - induction hLt with - | single hLt => - rcases hLt with ⟨Z, X, y, a_def, b_def, X_lt_y⟩ - use X - · simp - · simpa - | tail _ aih bih => -- it suffices to show MultisetLT is transitive - apply LT_trans _ _ _ _ bih - apply redLt_LT - assumption - · -- LT → Lt: - apply direct_subset_red - -/- The desired theorem: If `LT.lt` is well-founded, then `MultisetLT` is well-founded. -/ -theorem dm_wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] - (wf_lt : WellFoundedLT α) :WellFounded (MultisetLT : Multiset α → Multiset α → Prop) := by - rw [← Lt_LT_equiv] - exact Lt_wf (RedLt_wf wf_lt) From 1ee69724401074593010c1ab7d42c4c714f46ca3 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:27:28 +0200 Subject: [PATCH 16/32] fix sorries --- Mathlib/Data/Multiset/DershowitzManna.lean | 104 ++++----------------- 1 file changed, 20 insertions(+), 84 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 425df0fb336b8..3478f1c5d6a97 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -79,49 +79,6 @@ lemma not_redLT_zero [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedL simp_all only [Multiset.mem_add, Multiset.mem_singleton, or_true] contradiction --- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' -lemma mul_singleton_erase [DecidableEq α] {a : α} {M : Multiset α} : - M - {a} = M.erase a := by - ext - simp [Multiset.erase_singleton, Multiset.count_singleton] - split <;> simp_all - --- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' -lemma in_of_ne_of_cons_erase [DecidableEq α] {a a0: α} {M X : Multiset α} - (H : M = (a0 ::ₘ X).erase a) (hyp : ¬ a = a0) : a0 ∈ M := by - rw [H, Multiset.mem_erase_of_ne fun h ↦ hyp <| id <| Eq.symm h, Multiset.mem_cons] - tauto - --- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' -lemma singleton_add_sub_of_cons_add [DecidableEq α] {a a0: α} {M X : Multiset α} - (H : a ::ₘ M = X + {a0}) : M = X + {a0} - {a} := by - by_cases hyp : a = a0 - · rw [hyp, add_comm] at H - simp_all [Multiset.singleton_add] - · have a0_a: a0 ≠ a := by rw [eq_comm] at hyp; exact hyp - ext b - simp [Multiset.count_cons, Multiset.count_singleton, Multiset.count_add] - have H : Multiset.count b (a ::ₘ M) = Multiset.count b (X + {a0}) := by simp_all only - [Multiset.count_add] - by_cases ba : b = a - · rw [ba] at * - have : (a ::ₘ M).count a = M.count a + 1 := by simp - simp_all - by_cases ba0 : b = a0 - · have : (a ::ₘ M).count a0 = X.count a0 + 1 := by - subst_eqs - rw [add_comm, Multiset.singleton_add] at H - simp_all - have : M.count a0 = Multiset.count a0 (a ::ₘ M) := by - have : a0 ≠ a := by simp_all - rw [Multiset.count_cons_of_ne this M] - simp_all - · have : M.count b = (a ::ₘ M).count b := by - have : b ≠ a := by simp_all - rw [Multiset.count_cons_of_ne this M] - rw [this] - simp_all - lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : MultisetRedLT N (a ::ₘ M)) : ∃ M', N = (a ::ₘ M') ∧ (MultisetRedLT M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by @@ -144,7 +101,7 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : Mult · have := h0 b aesop · have := h0 b - simp [mul_singleton_erase] + simp [Multiset.sub_singleton] aesop subst this rw [add_comm] @@ -154,13 +111,14 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : Mult · change Y + (M - {a0}) = (M - {a0}) + Y rw [add_comm] · change M = M - {a0} + {a0} - have this0: M = X + {a0} - {a} := by apply singleton_add_sub_of_cons_add; exact h0 + have this0: M = X + {a0} - {a} := by + rw [← h0, Multiset.sub_singleton, Multiset.erase_cons_head] have a0M: a0 ∈ M := by - apply in_of_ne_of_cons_erase - · change M = Multiset.erase (a0 ::ₘ X) a - rw [mul_singleton_erase, add_comm] at this0 - exact this0 - · exact hyp + rw [this0, Multiset.sub_singleton, Multiset.mem_erase_of_ne] + rw [Multiset.mem_add, Multiset.mem_singleton] + · apply Or.inr + rfl + · exact fun h ↦ hyp (Eq.symm h) -- Yes! construct a function of 'λ (a0 = a). False' here rw [add_comm] simp_all [Multiset.singleton_add] exact h2 @@ -250,33 +208,6 @@ lemma transLT_wf [DecidableEq α] [LT α] apply WellFounded.transGen assumption --- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' -lemma inter_add_sub_of_eq {α} [dec : DecidableEq α] {M N P Q: Multiset α} (h : M + N = P + Q) : - N = N ∩ Q + (P - M) := by - ext x - rw [Multiset.count_add, Multiset.count_inter, Multiset.count_sub] - have h0 : M.count x + N.count x = P.count x + Q.count x := by - rw [Multiset.ext] at h - simp_all only [Multiset.mem_add, Multiset.count_add] - by_cases l_u : M.count x ≤ P.count x - · have : N.count x ≥ Q.count x := by linarith - simp_all only [ge_iff_le, min_eq_right] - have := tsub_add_cancel_of_le l_u - linarith - · simp_all only [not_le, gt_iff_lt] - have : Multiset.count x N ≤ Multiset.count x Q := by linarith - have := le_of_lt l_u - simp_all - --- Should be added to 'mathlib4/Mathlib/Data/Multiset/Basic.lean' -lemma mem_sub_of_not_mem_of_mem {α} [DecidableEq α] (x : α) (X Y: Multiset α) (x_in_X : x ∈ X) - (x_notin_Y : x ∉ Y) : x ∈ X - Y := by - have : Multiset.count x X ≥ 1 := by - rw [← Multiset.one_le_count_iff_mem] at x_in_X - exact x_in_X - rw [← Multiset.one_le_count_iff_mem, Multiset.count_sub] - simp_all only [not_false_eq_true, Multiset.count_eq_zero_of_not_mem, tsub_zero] - -- `MultisetDMLT` is transitive. lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: ∀ (M N P : Multiset α) , MultisetDMLT N M → MultisetDMLT P N → MultisetDMLT P M := by @@ -284,7 +215,12 @@ lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: rcases LTNM with ⟨Y1, X1, Z1, X1_ne, N1_def, M1_def, Ord1⟩ rcases LTPN with ⟨Y2, X2, Z2, _, P2_def, N2_def, Ord2⟩ apply MultisetDMLT.DMLT (Y2 + (Y1 - X2)) (X1 + (X2 - Y1)) (Z1 ∩ Z2) - · simp_all only [Multiset.empty_eq_zero, ne_eq, add_eq_zero_iff, false_and, not_false_eq_true] + · simp only [Multiset.empty_eq_zero] at * + rw [← Multiset.card_pos] + rw [← Multiset.card_pos] at X1_ne + simp only [map_add, add_pos_iff] + left + exact X1_ne · rw [P2_def] have : Z1 ∩ Z2 + (Y2 + (Y1 - X2)) = Z1 ∩ Z2 + (Y1 - X2) + Y2 := by have : (Y2 + (Y1 - X2)) = (Y1 - X2) + Y2 := by rw [add_comm] @@ -292,15 +228,14 @@ lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: rw [this] have : Z1 ∩ Z2 + (Y1 - X2) = Z2 ∩ Z1 + (Y1 - X2) := by rw [Multiset.inter_comm] - rw [this,← inter_add_sub_of_eq] + rw [this, Multiset.inter_add_sub_of_add_eq_add] rw [add_comm, ← N2_def, N1_def] apply add_comm · rw [M1_def] have : Z1 ∩ Z2 + (X1 + (X2 - Y1)) = Z1 ∩ Z2 + (X2 - Y1) + X1 := by have : (X1 + (X2 - Y1)) = (X2 - Y1) + X1 := by rw [add_comm] rw [this, add_assoc] - rw [this, add_left_inj] - apply inter_add_sub_of_eq + rw [this, add_left_inj, Multiset.inter_add_sub_of_add_eq_add] rw [add_comm, ← N1_def, N2_def] apply add_comm · intros y y_in_union @@ -318,15 +253,16 @@ lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: constructor · rw [add_comm, Multiset.mem_add] constructor - apply mem_sub_of_not_mem_of_mem - exact x_in_X2 + rwa [Multiset.mem_sub, Multiset.count_eq_zero_of_not_mem, Multiset.count_pos] exact x_in · exact y_lt_x · have y_in : y ∈ (Y1 - X2) := by simp_all only [Multiset.mem_add, false_or] let h := (Ord1 y) have y_in_Y1 : y ∈ Y1 := by - have : Y1 - X2 ≤ Y1 := by simp_all only [tsub_le_iff_right, le_add_iff_nonneg_right, + have : Y1 - X2 ≤ Y1 := by + simp_all [tsub_le_iff_right, le_add_iff_nonneg_right, zero_le] + simp only [Multiset.zero_le] apply Multiset.mem_of_le exact this exact y_in From 61d70ce689e6b2bb379f601b714b5033d68b5d06 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:29:14 +0200 Subject: [PATCH 17/32] remove comments --- Mathlib/Data/Multiset/DershowitzManna.lean | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 3478f1c5d6a97..4872ea296e307 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -67,9 +67,7 @@ theorem dmLT_of_redLT [DecidableEq α] [Preorder α] (M N : Multiset α) (h : Mu · simpa · simp -/- Some useful lemmas about Multisets and the defined relations, some of which should be added to - 'mathlib4/Mathlib/Data/Multiset/Basic.lean': -/ - +/- Some useful lemmas. -/ lemma not_redLT_zero [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedLT M 0 := by intro h cases h with @@ -91,7 +89,7 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : Mult · simp_all · exists (Y + (M - {a0})) left - constructor --; apply And.intro + constructor · rw [h1] have : X = (M - {a0} + {a}) := by rw [add_comm, Multiset.singleton_add] at * @@ -118,7 +116,7 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : Mult rw [Multiset.mem_add, Multiset.mem_singleton] · apply Or.inr rfl - · exact fun h ↦ hyp (Eq.symm h) -- Yes! construct a function of 'λ (a0 = a). False' here + · exact fun h ↦ hyp (Eq.symm h) rw [add_comm] simp_all [Multiset.singleton_add] exact h2 @@ -135,7 +133,7 @@ lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) case h.intro.inr h => rcases h with ⟨H, h0⟩ rw [H] - clear H -- Needed to make simp_all below safe. + clear H induction x using Multiset.induction with | empty => simpa @@ -272,7 +270,6 @@ lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (DMLTMN : MultisetDMLT M N) : MultisetTransLT M N := by - -- intros M N LTXY cases DMLTMN case DMLT X Y Z Y_not_empty MZX NZY h => unfold MultisetTransLT From 01745c582d42a07f57f025e746602fb061b332c1 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Fri, 1 Nov 2024 17:04:03 +0100 Subject: [PATCH 18/32] replace inductive with def --- Mathlib/Data/Multiset/DershowitzManna.lean | 324 ++++++++++----------- 1 file changed, 154 insertions(+), 170 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 4872ea296e307..58c01427a90f6 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -34,20 +34,20 @@ the Dershowitz-Manna ordering defined over multisets is also well-founded. variable {α : Type*} /-- The standard Dershowitz–Manna ordering: -/ -inductive MultisetDMLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := - | DMLT : ∀ (X Y Z : Multiset α), - Y ≠ ∅ → - M = Z + X → - N = Z + Y → - (∀ x ∈ X, ∃ y ∈ Y, x < y) → MultisetDMLT M N +def MultisetDMLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := + ∃ (X Y Z : Multiset α), + Y ≠ ∅ + ∧ M = Z + X + ∧ N = Z + Y + ∧ (∀ x ∈ X, ∃ y ∈ Y, x < y) /-- MultisetRedLT is a special case of MultisetDMLT. The transitive closure of it is used to define an equivalent (proved later) version of the ordering. -/ -inductive MultisetRedLT [DecidableEq α] [LT α] (M N : Multiset α) : Prop := - | RedLT : ∀ (X Y : Multiset α) (a : α) , - (M = X + Y) → - (N = X + {a}) → - (∀ y, y ∈ Y → y < a) → MultisetRedLT M N +def MultisetRedLT [DecidableEq α] [LT α] (M N : Multiset α) : Prop := + ∃ (X Y : Multiset α) (a : α) , + (M = X + Y) + ∧ (N = X + {a}) + ∧ (∀ y, y ∈ Y → y < a) open Relation @@ -56,26 +56,20 @@ open Relation def MultisetTransLT [DecidableEq α] [LT α] : Multiset α → Multiset α → Prop := TransGen MultisetRedLT -/-- A shorthand notation: AccM defines the accessibility relation given MultisetRedLT. -/ -def AccM [DecidableEq α] [Preorder α] : Multiset α → Prop := Acc MultisetRedLT - /- MultisetRedLT is a special case of MultisetDMLT. -/ theorem dmLT_of_redLT [DecidableEq α] [Preorder α] (M N : Multiset α) (h : MultisetRedLT M N): MultisetDMLT M N := by rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ - apply MultisetDMLT.DMLT Y {a} X _ M_def N_def + use Y, {a}, X, by simp, M_def, N_def · simpa - · simp /- Some useful lemmas. -/ lemma not_redLT_zero [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedLT M 0 := by - intro h - cases h with - | RedLT X Y a M nonsense _ => - have contra : a ∈ (0 : Multiset α):= by - rw [nonsense] - simp_all only [Multiset.mem_add, Multiset.mem_singleton, or_true] - contradiction + rintro ⟨X, Y, a, _, nonsense, _⟩ + have contra : a ∈ (0 : Multiset α):= by + rw [nonsense] + simp_all only [Multiset.mem_add, Multiset.mem_singleton, or_true] + contradiction lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : MultisetRedLT N (a ::ₘ M)) : ∃ M', @@ -94,18 +88,19 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : Mult have : X = (M - {a0} + {a}) := by rw [add_comm, Multiset.singleton_add] at * ext b - simp [Multiset.ext, Multiset.count_cons] at h0 + simp only [Multiset.ext, Multiset.count_cons] at h0 by_cases h : b = a · have := h0 b - aesop + simp_all? · have := h0 b simp [Multiset.sub_singleton] - aesop + aesop? subst this rw [add_comm] nth_rewrite 2 [add_comm] rw [Multiset.singleton_add, Multiset.add_cons] - · constructor + · unfold MultisetRedLT + refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ · change Y + (M - {a0}) = (M - {a0}) + Y rw [add_comm] · change M = M - {a0} + {a0} @@ -119,16 +114,15 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : Mult · exact fun h ↦ hyp (Eq.symm h) rw [add_comm] simp_all [Multiset.singleton_add] - exact h2 lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) - (_ : ∀ b M , LT.lt b a → AccM M → AccM (b ::ₘ M)) - (_ : AccM M0) - (_ : ∀ M, MultisetRedLT M M0 → AccM (a ::ₘ M)) : - AccM (a ::ₘ M0) := by + (_ : ∀ b M , LT.lt b a → Acc MultisetRedLT M → Acc MultisetRedLT (b ::ₘ M)) + (_ : Acc MultisetRedLT M0) + (_ : ∀ M, MultisetRedLT M M0 → Acc MultisetRedLT (a ::ₘ M)) : + Acc MultisetRedLT (a ::ₘ M0) := by constructor intros N N_lt - change AccM N + change Acc MultisetRedLT N rcases (red_insert N_lt) with ⟨x, H, h0⟩ case h.intro.inr h => rcases h with ⟨H, h0⟩ @@ -144,20 +138,18 @@ lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) simp_all lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) - (H : ∀ (b : α), ∀ M, LT.lt b a → AccM M → AccM (b ::ₘ M)) : - ∀ M, AccM M → AccM (a ::ₘ M) := by - unfold AccM + (H : ∀ (b : α), ∀ M, LT.lt b a → Acc MultisetRedLT M → Acc MultisetRedLT (b ::ₘ M)) : + ∀ M, Acc MultisetRedLT M → Acc MultisetRedLT (a ::ₘ M) := by intros M h0 induction h0 with | intro x wfH wfh2 => apply acc_cons · simpa - · constructor - simpa - · simpa + · constructor ; simpa only + · simpa only lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : - ∀ (a:α), Acc LT.lt a → ∀ M, AccM M → AccM (a ::ₘ M) := by + ∀ (a:α), Acc LT.lt a → ∀ M, Acc MultisetRedLT M → Acc MultisetRedLT (a ::ₘ M) := by intro w w_a induction w_a with | intro x _ ih => @@ -168,7 +160,7 @@ lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : /- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is accessible given the `MultisetRedLT` relation. -/ lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : - ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → AccM M := by + ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc MultisetRedLT M := by intros M wf_el induction M using Multiset.induction_on with | empty => @@ -197,22 +189,13 @@ lemma redLT_wf [DecidableEq α] [Preorder α] apply Acc.intro y assumption -/- If `MultisetRedLT` is well-founded, then its transitive closure `MultisetTransLT` is also -well-founded. -/ -lemma transLT_wf [DecidableEq α] [LT α] - (h : WellFounded (MultisetRedLT : Multiset α → Multiset α → Prop)) : - WellFounded (MultisetTransLT : Multiset α → Multiset α → Prop) := by - unfold MultisetTransLT - apply WellFounded.transGen - assumption - -- `MultisetDMLT` is transitive. lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: ∀ (M N P : Multiset α) , MultisetDMLT N M → MultisetDMLT P N → MultisetDMLT P M := by intros M N P LTNM LTPN rcases LTNM with ⟨Y1, X1, Z1, X1_ne, N1_def, M1_def, Ord1⟩ rcases LTPN with ⟨Y2, X2, Z2, _, P2_def, N2_def, Ord2⟩ - apply MultisetDMLT.DMLT (Y2 + (Y1 - X2)) (X1 + (X2 - Y1)) (Z1 ∩ Z2) + refine ⟨Y2 + (Y1 - X2), X1 + (X2 - Y1), Z1 ∩ Z2, ⟨?_, ?_, ?_, ?_⟩⟩ · simp only [Multiset.empty_eq_zero] at * rw [← Multiset.card_pos] rw [← Multiset.card_pos] at X1_ne @@ -255,7 +238,6 @@ lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: exact x_in · exact y_lt_x · have y_in : y ∈ (Y1 - X2) := by simp_all only [Multiset.mem_add, false_or] - let h := (Ord1 y) have y_in_Y1 : y ∈ Y1 := by have : Y1 - X2 ≤ Y1 := by simp_all [tsub_le_iff_right, le_add_iff_nonneg_right, @@ -264,121 +246,123 @@ lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: apply Multiset.mem_of_le exact this exact y_in - let _ := h y_in_Y1 - aesop + let ⟨w, ⟨left_1, right⟩⟩ := (Ord1 y) y_in_Y1 + subst P2_def M1_def N2_def + simp_all only [Multiset.empty_eq_zero, ne_eq, Multiset.mem_add, or_true] + use w + tauto lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (DMLTMN : MultisetDMLT M N) : MultisetTransLT M N := by - cases DMLTMN - case DMLT X Y Z Y_not_empty MZX NZY h => - unfold MultisetTransLT - revert Z X M N - induction Y using Multiset.strongInductionOn - case ih Y IH => - intro M N X Z M_def N_def X_lt_Y - cases em (Multiset.card Y = 0) - · simp_all - cases em (Multiset.card Y = 1) - case inl hyp' hyp=> - rw [Multiset.card_eq_one] at hyp - rcases hyp with ⟨y,Y'_def⟩ - apply TransGen.single - rw [Y'_def] at N_def - apply @MultisetRedLT.RedLT α _ _ M N Z X y M_def N_def - simp [Y'_def] at X_lt_Y - exact X_lt_Y - case inr hyp' hyp => - have : ∃ a, a ∈ Y := by - rw [← Y.card_pos_iff_exists_mem] - cases foo : Multiset.card Y - tauto - simp - rcases this with ⟨y,claim⟩ - let newY := Y.erase y - have newY_nonEmpty : newY ≠ ∅ := by - have : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by - intros n h0 h1 - cases n + rcases DMLTMN with ⟨X, Y, Z, Y_not_empty, MZX, NZY, h⟩ + unfold MultisetTransLT + revert Z X M N + induction Y using Multiset.strongInductionOn + case ih Y IH => + intro M N X Z M_def N_def X_lt_Y + cases em (Multiset.card Y = 0) + · simp_all + cases em (Multiset.card Y = 1) + case inl hyp' hyp=> + rw [Multiset.card_eq_one] at hyp + rcases hyp with ⟨y,Y'_def⟩ + apply TransGen.single + rw [Y'_def] at N_def + refine ⟨Z, X, y, M_def, N_def, ?_⟩ + simp only [Y'_def, Multiset.mem_singleton, exists_eq_left] at X_lt_Y + exact X_lt_Y + case inr hyp' hyp => + have : ∃ a, a ∈ Y := by + rw [← Y.card_pos_iff_exists_mem] + cases foo : Multiset.card Y + tauto + simp + rcases this with ⟨y,claim⟩ + let newY := Y.erase y + have newY_nonEmpty : newY ≠ ∅ := by + have : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by + intros n h0 h1 + cases n + case zero => contradiction + case succ m => + cases m case zero => contradiction - case succ m => - cases m - case zero => contradiction - case succ n=> - apply Nat.succ_le_succ - simp_all only [le_add_iff_nonneg_left, zero_le] - have : 0 < Multiset.card (Multiset.erase Y y) := by aesop - rw [Multiset.card_pos] at this - simp_all only [Multiset.empty_eq_zero, ne_eq, not_false_eq_true] - have newY_sub_Y : newY < Y := by simp (config := {zetaDelta := true}); exact claim - let f : α → Multiset α := fun y' => X.filter (fun x => x < y') -- DecidableRel - let N' := Z + newY + f y - apply @transitive_transGen _ _ _ N' - -- step from N' to M - · apply IH newY newY_sub_Y newY_nonEmpty - change M = (Z + f y) + (X - f y) - · ext a - have count_lt := Multiset.count_le_of_le a (Multiset.filter_le (fun x => x < y) X) - rw [M_def] - simp_all only [Multiset.empty_eq_zero, ne_eq, Multiset.card_eq_zero, not_false_eq_true, - Multiset.count_add, Multiset.count_sub] - let x := Multiset.count a X - let z := Multiset.count a Z - let fx := Multiset.count a (Multiset.filter (fun x => x < y) X) - change z + x = z + fx + (x - fx) - change fx ≤ x at count_lt - have : x = fx + (x - fx) := by simp_all only [add_tsub_cancel_of_le] - linarith - · unfold_let N' - rw [add_assoc, add_assoc, add_comm newY (f y)] - · intro x x_in - let X_lt_Y := X_lt_Y x - have x_in_X : x ∈ X := by - have Xfy_le_X : X - f y ≤ X:= by simp (config := {zetaDelta := true}) - apply Multiset.mem_of_le Xfy_le_X - exact x_in - let X_lt_Y := X_lt_Y x_in_X - rcases X_lt_Y with ⟨t, t_in_Y, x_lt_t⟩ - use t - constructor - · by_cases t_in_newY : t ∈ newY - · exact t_in_newY - · exfalso - have : t = y := by - have : Y = newY + {y} := by - unfold_let newY - rw [add_comm, Multiset.singleton_add] - simp [Multiset.cons_erase claim] - rw [this, Multiset.mem_add] at t_in_Y - have : t ∈ ( {y} : Multiset α) := Or.resolve_left t_in_Y t_in_newY - rwa [← Multiset.mem_singleton] - have x_in_fy : x ∈ f y := by - unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ - have x_notin_Xfy : x ∉ X - f y := by - by_contra - let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') - have : X - f y = neg_f y := by - have fy_negfy_X : f y + neg_f y = X := Multiset.filter_add_not _ _ - rw [← fy_negfy_X, add_tsub_cancel_left] - have x_in_neg_fy : x ∈ neg_f y := this ▸ x_in - subst_eqs - unfold_let neg_f at * - simp_all only [Multiset.mem_filter] - exact x_notin_Xfy x_in - · exact x_lt_t - -- single step N to N' - · have : MultisetRedLT N' N := by - apply MultisetRedLT.RedLT (Z + newY) (f y) y - · rfl - · have newY_y_Y: newY + {y} = Y := by - unfold_let newY; rw [add_comm, Multiset.singleton_add] - apply Multiset.cons_erase claim - have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc - rw [this, newY_y_Y] - exact N_def - · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 - apply TransGen.single - exact this + case succ n=> + apply Nat.succ_le_succ + simp_all only [le_add_iff_nonneg_left, zero_le] + have : 0 < Multiset.card (Multiset.erase Y y) := by aesop + rw [Multiset.card_pos] at this + simp_all only [Multiset.empty_eq_zero, ne_eq, not_false_eq_true] + have newY_sub_Y : newY < Y := by simp (config := {zetaDelta := true}); exact claim + let f : α → Multiset α := fun y' => X.filter (fun x => x < y') -- DecidableRel + let N' := Z + newY + f y + apply @transitive_transGen _ _ _ N' + -- step from N' to M + · apply IH newY newY_sub_Y newY_nonEmpty + change M = (Z + f y) + (X - f y) + · ext a + have count_lt := Multiset.count_le_of_le a (Multiset.filter_le (fun x => x < y) X) + rw [M_def] + simp_all only [Multiset.empty_eq_zero, ne_eq, Multiset.card_eq_zero, not_false_eq_true, + Multiset.count_add, Multiset.count_sub] + let x := Multiset.count a X + let z := Multiset.count a Z + let fx := Multiset.count a (Multiset.filter (fun x => x < y) X) + change z + x = z + fx + (x - fx) + change fx ≤ x at count_lt + have : x = fx + (x - fx) := by simp_all only [add_tsub_cancel_of_le] + linarith + · unfold_let N' + rw [add_assoc, add_assoc, add_comm newY (f y)] + · intro x x_in + let X_lt_Y := X_lt_Y x + have x_in_X : x ∈ X := by + have Xfy_le_X : X - f y ≤ X:= by simp (config := {zetaDelta := true}) + apply Multiset.mem_of_le Xfy_le_X + exact x_in + let X_lt_Y := X_lt_Y x_in_X + rcases X_lt_Y with ⟨t, t_in_Y, x_lt_t⟩ + use t + constructor + · by_cases t_in_newY : t ∈ newY + · exact t_in_newY + · exfalso + have : t = y := by + have : Y = newY + {y} := by + unfold_let newY + rw [add_comm, Multiset.singleton_add] + simp [Multiset.cons_erase claim] + rw [this, Multiset.mem_add] at t_in_Y + have : t ∈ ( {y} : Multiset α) := Or.resolve_left t_in_Y t_in_newY + rwa [← Multiset.mem_singleton] + have x_in_fy : x ∈ f y := by + unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ + have x_notin_Xfy : x ∉ X - f y := by + by_contra + let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') + have : X - f y = neg_f y := by + have fy_negfy_X : f y + neg_f y = X := Multiset.filter_add_not _ _ + rw [← fy_negfy_X, add_tsub_cancel_left] + have x_in_neg_fy : x ∈ neg_f y := this ▸ x_in + subst_eqs + unfold_let neg_f at * + simp_all only [Multiset.mem_filter] + exact x_notin_Xfy x_in + · exact x_lt_t + -- single step N to N' + · have : MultisetRedLT N' N := by + refine ⟨Z + newY, f y, y, ?_, ?_, ?_ ⟩ + · rfl + · have newY_y_Y: newY + {y} = Y := by + unfold_let newY; rw [add_comm, Multiset.singleton_add] + apply Multiset.cons_erase claim + have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc + rw [this, newY_y_Y] + exact N_def + · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 + apply TransGen.single + exact this /- MultisetTransLT and MultisetDMLT are equivalent. -/ lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: @@ -389,13 +373,12 @@ lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) constructor · -- TransLT → DMLT: intros TransLT - induction TransLT with - | single TransLT => - rcases TransLT with ⟨Z, X, y, a_def, b_def, X_lt_y⟩ - use X - · simp - · simpa - | tail _ aih bih => -- it suffices to show MultisetDMLT is transitive + induction TransLT + case single Z TransLT => + rcases TransLT with ⟨W, U, y, X_def, Z_def, U_lt_y⟩ + use U, {y}, W + simp_all + case tail _ aih bih => -- it suffices to show MultisetDMLT is transitive apply dmlt_trans _ _ _ _ bih apply dmLT_of_redLT assumption @@ -406,4 +389,5 @@ lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) theorem dmLT_wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) :WellFounded (MultisetDMLT : Multiset α → Multiset α → Prop) := by rw [← transLT_eq_dmLT] - exact transLT_wf (redLT_wf wf_lt) + apply WellFounded.transGen + exact (redLT_wf wf_lt) From d9e6f69644eb36e028516c922346863957c52ebe Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:20:30 +0100 Subject: [PATCH 19/32] add name space and wellfounded instance --- Mathlib/Data/Multiset/DershowitzManna.lean | 380 +++++++++++---------- 1 file changed, 196 insertions(+), 184 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 58c01427a90f6..599d5c212fb03 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -16,9 +16,9 @@ the Dershowitz-Manna ordering defined over multisets is also well-founded. ## Main results -- `MultisetDMLT` : the standard definition fo the `Dershowitz-Manna ordering`. -- `dm_wf` : the main theorem about the `Dershowitz-Manna ordering` being well-founded. -- `TransLT_eq_DMLT` : two definitions of the `Dershowitz-Manna ordering` are equivalent. +- `Multiset.DMLT` : the standard definition fo the `Dershowitz-Manna ordering`. +- `Multiset.DMLT.wf` : the main theorem about the `Dershowitz-Manna ordering` being well-founded. +- `Multiset.TransLT_eq_DMLT` : two definitions of the `Dershowitz-Manna ordering` are equivalent. ## References @@ -31,19 +31,21 @@ the Dershowitz-Manna ordering defined over multisets is also well-founded. -/ +namespace Multiset + variable {α : Type*} /-- The standard Dershowitz–Manna ordering: -/ -def MultisetDMLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := +def DMLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := ∃ (X Y Z : Multiset α), - Y ≠ ∅ - ∧ M = Z + X - ∧ N = Z + Y - ∧ (∀ x ∈ X, ∃ y ∈ Y, x < y) + Z ≠ ∅ + ∧ M = X + Y + ∧ N = X + Z + ∧ (∀ y ∈ Y, ∃ z ∈ Z, y < z) -/-- MultisetRedLT is a special case of MultisetDMLT. The transitive closure of it is used to define +/-- A special case of DMLT. The transitive closure of it is used to define an equivalent (proved later) version of the ordering. -/ -def MultisetRedLT [DecidableEq α] [LT α] (M N : Multiset α) : Prop := +def DMLT_singleton [DecidableEq α] [LT α] (M N : Multiset α) : Prop := ∃ (X Y : Multiset α) (a : α) , (M = X + Y) ∧ (N = X + {a}) @@ -51,34 +53,26 @@ def MultisetRedLT [DecidableEq α] [LT α] (M N : Multiset α) : Prop := open Relation -/-- MultisetTransLT is the transitive closure of MultisetRedLT and is equivalent to MultisetDMLT +/-- The transitive closure of DMLT_singleton and is equivalent to DMLT (proved later). -/ -def MultisetTransLT [DecidableEq α] [LT α] : Multiset α → Multiset α → Prop := - TransGen MultisetRedLT +def TransLT [DecidableEq α] [LT α] : Multiset α → Multiset α → Prop := + TransGen DMLT_singleton -/- MultisetRedLT is a special case of MultisetDMLT. -/ -theorem dmLT_of_redLT [DecidableEq α] [Preorder α] (M N : Multiset α) (h : MultisetRedLT M N): - MultisetDMLT M N := by +/- A special case of DMLT. -/ +theorem dmlt_of_DMLT_singleton [DecidableEq α] [Preorder α] (M N : Multiset α) + (h : DMLT_singleton M N) : DMLT M N := by rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ - use Y, {a}, X, by simp, M_def, N_def + use X, Y, {a}, by simp, M_def, N_def · simpa -/- Some useful lemmas. -/ -lemma not_redLT_zero [DecidableEq α] [LT α] (M: Multiset α) : ¬ MultisetRedLT M 0 := by - rintro ⟨X, Y, a, _, nonsense, _⟩ - have contra : a ∈ (0 : Multiset α):= by - rw [nonsense] - simp_all only [Multiset.mem_add, Multiset.mem_singleton, or_true] - contradiction - -lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : MultisetRedLT N (a ::ₘ M)) : - ∃ M', - N = (a ::ₘ M') ∧ (MultisetRedLT M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by +lemma DMLT_singleton_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} + (h : DMLT_singleton N (a ::ₘ M)) : + ∃ M', N = (a ::ₘ M') ∧ (DMLT_singleton M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by rcases h with ⟨X, Y, a0, h1, h0, h2⟩ by_cases hyp : a = a0 · exists Y; right; apply And.intro · rw [h1, add_left_inj] - rw [add_comm, Multiset.singleton_add] at h0 + rw [add_comm, singleton_add] at h0 simp_all · simp_all · exists (Y + (M - {a0})) @@ -86,44 +80,49 @@ lemma red_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} (h : Mult constructor · rw [h1] have : X = (M - {a0} + {a}) := by - rw [add_comm, Multiset.singleton_add] at * + rw [add_comm, singleton_add] at * ext b - simp only [Multiset.ext, Multiset.count_cons] at h0 + simp only [ext, count_cons] at h0 by_cases h : b = a · have := h0 b - simp_all? + simp_all only [ite_true, ite_false, add_zero, sub_singleton, count_cons_self, ne_eq, + not_false_eq_true, count_erase_of_ne] · have := h0 b - simp [Multiset.sub_singleton] - aesop? + simp [sub_singleton] + simp_all only [↓reduceIte, add_zero, ne_eq, not_false_eq_true, count_cons_of_ne] + split at this + next h_1 => + simp_all only [count_erase_self, add_tsub_cancel_right] + next h_1 => simp_all only [add_zero, ne_eq, not_false_eq_true, count_erase_of_ne] subst this rw [add_comm] nth_rewrite 2 [add_comm] - rw [Multiset.singleton_add, Multiset.add_cons] - · unfold MultisetRedLT + rw [singleton_add, add_cons] + · unfold DMLT_singleton refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ · change Y + (M - {a0}) = (M - {a0}) + Y rw [add_comm] · change M = M - {a0} + {a0} have this0: M = X + {a0} - {a} := by - rw [← h0, Multiset.sub_singleton, Multiset.erase_cons_head] + rw [← h0, sub_singleton, erase_cons_head] have a0M: a0 ∈ M := by - rw [this0, Multiset.sub_singleton, Multiset.mem_erase_of_ne] - rw [Multiset.mem_add, Multiset.mem_singleton] + rw [this0, sub_singleton, mem_erase_of_ne] + rw [mem_add, mem_singleton] · apply Or.inr rfl · exact fun h ↦ hyp (Eq.symm h) rw [add_comm] - simp_all [Multiset.singleton_add] + simp_all [singleton_add] lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) - (_ : ∀ b M , LT.lt b a → Acc MultisetRedLT M → Acc MultisetRedLT (b ::ₘ M)) - (_ : Acc MultisetRedLT M0) - (_ : ∀ M, MultisetRedLT M M0 → Acc MultisetRedLT (a ::ₘ M)) : - Acc MultisetRedLT (a ::ₘ M0) := by + (_ : ∀ b M , LT.lt b a → Acc DMLT_singleton M → Acc DMLT_singleton (b ::ₘ M)) + (_ : Acc DMLT_singleton M0) + (_ : ∀ M, DMLT_singleton M M0 → Acc DMLT_singleton (a ::ₘ M)) : + Acc DMLT_singleton (a ::ₘ M0) := by constructor intros N N_lt - change Acc MultisetRedLT N - rcases (red_insert N_lt) with ⟨x, H, h0⟩ + change Acc DMLT_singleton N + rcases (DMLT_singleton_insert N_lt) with ⟨x, H, h0⟩ case h.intro.inr h => rcases h with ⟨H, h0⟩ rw [H] @@ -132,14 +131,14 @@ lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) | empty => simpa | cons h => - simp_all only [Multiset.mem_cons, or_true, implies_true, true_implies, forall_eq_or_imp, - Multiset.add_cons] + simp_all only [mem_cons, or_true, implies_true, true_implies, forall_eq_or_imp, + add_cons] case h.intro.inl.intro => simp_all lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) - (H : ∀ (b : α), ∀ M, LT.lt b a → Acc MultisetRedLT M → Acc MultisetRedLT (b ::ₘ M)) : - ∀ M, Acc MultisetRedLT M → Acc MultisetRedLT (a ::ₘ M) := by + (H : ∀ (b : α), ∀ M, LT.lt b a → Acc DMLT_singleton M → Acc DMLT_singleton (b ::ₘ M)) : + ∀ M, Acc DMLT_singleton M → Acc DMLT_singleton (a ::ₘ M) := by intros M h0 induction h0 with | intro x wfH wfh2 => @@ -149,7 +148,7 @@ lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) · simpa only lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : - ∀ (a:α), Acc LT.lt a → ∀ M, Acc MultisetRedLT M → Acc MultisetRedLT (a ::ₘ M) := by + ∀ (a:α), Acc LT.lt a → ∀ M, Acc DMLT_singleton M → Acc DMLT_singleton (a ::ₘ M) := by intro w w_a induction w_a with | intro x _ ih => @@ -158,16 +157,19 @@ lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : simp_all /- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is -accessible given the `MultisetRedLT` relation. -/ +accessible given the `DMLT_singleton` relation. -/ lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : - ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc MultisetRedLT M := by + ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc DMLT_singleton M := by intros M wf_el induction M using Multiset.induction_on with | empty => constructor intro y y_lt absurd y_lt - apply not_redLT_zero + rintro ⟨X, Y, a, _, nonsense, _⟩ + have contra : a ∈ (0 : Multiset α):= by + simp_all only [mem_add, mem_singleton, or_true] + contradiction | cons _ _ ih => apply acc_cons_of_acc_of_lt · apply wf_el @@ -177,9 +179,9 @@ lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : apply wf_el simp_all -/- If `LT.lt` is well-founded, then `MultisetRedLT` is well-founded. -/ -lemma redLT_wf [DecidableEq α] [Preorder α] - (wf_lt : WellFoundedLT α) : WellFounded (MultisetRedLT : Multiset α → Multiset α → Prop) := by +/- If `LT.lt` is well-founded, then `DMLT_singleton` is well-founded. -/ +lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] + (wf_lt : WellFoundedLT α) : WellFounded (DMLT_singleton : Multiset α → Multiset α → Prop) := by constructor intros a apply acc_of_acc_lt @@ -189,98 +191,97 @@ lemma redLT_wf [DecidableEq α] [Preorder α] apply Acc.intro y assumption --- `MultisetDMLT` is transitive. +-- `DMLT` is transitive. lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: - ∀ (M N P : Multiset α) , MultisetDMLT N M → MultisetDMLT P N → MultisetDMLT P M := by + ∀ (M N P : Multiset α) , DMLT N M → DMLT P N → DMLT P M := by intros M N P LTNM LTPN - rcases LTNM with ⟨Y1, X1, Z1, X1_ne, N1_def, M1_def, Ord1⟩ - rcases LTPN with ⟨Y2, X2, Z2, _, P2_def, N2_def, Ord2⟩ - refine ⟨Y2 + (Y1 - X2), X1 + (X2 - Y1), Z1 ∩ Z2, ⟨?_, ?_, ?_, ?_⟩⟩ - · simp only [Multiset.empty_eq_zero] at * - rw [← Multiset.card_pos] - rw [← Multiset.card_pos] at X1_ne - simp only [map_add, add_pos_iff] + rcases LTNM with ⟨X1, Y1, Z1, Z1_ne, N1_def, M1_def, Ord1⟩ + rcases LTPN with ⟨X2, Y2, Z2, _, P2_def, N2_def, Ord2⟩ + refine ⟨X1 ∩ X2, Y2 + (Y1 - Z2), Z1 + (Z2 - Y1), ⟨?_, ?_, ?_, ?_⟩⟩ + · simp only [empty_eq_zero] at * + rw [← card_pos] + rw [← card_pos] at Z1_ne + simp only [_root_.map_add, add_pos_iff] left - exact X1_ne + exact Z1_ne · rw [P2_def] - have : Z1 ∩ Z2 + (Y2 + (Y1 - X2)) = Z1 ∩ Z2 + (Y1 - X2) + Y2 := by - have : (Y2 + (Y1 - X2)) = (Y1 - X2) + Y2 := by rw [add_comm] + have : X1 ∩ X2 + (Y2 + (Y1 - Z2)) = X1 ∩ X2 + (Y1 - Z2) + Y2 := by + have : (Y2 + (Y1 - Z2)) = (Y1 - Z2) + Y2 := by rw [add_comm] rw [this, add_assoc] rw [this] - have : Z1 ∩ Z2 + (Y1 - X2) = Z2 ∩ Z1 + (Y1 - X2) := by - rw [Multiset.inter_comm] - rw [this, Multiset.inter_add_sub_of_add_eq_add] + have : X1 ∩ X2 + (Y1 - Z2) = X2 ∩ X1 + (Y1 - Z2) := by + rw [inter_comm] + rw [this, inter_add_sub_of_add_eq_add] rw [add_comm, ← N2_def, N1_def] apply add_comm · rw [M1_def] - have : Z1 ∩ Z2 + (X1 + (X2 - Y1)) = Z1 ∩ Z2 + (X2 - Y1) + X1 := by - have : (X1 + (X2 - Y1)) = (X2 - Y1) + X1 := by rw [add_comm] + have : X1 ∩ X2 + (Z1 + (Z2 - Y1)) = X1 ∩ X2 + (Z2 - Y1) + Z1 := by + have : (Z1 + (Z2 - Y1)) = (Z2 - Y1) + Z1 := by rw [add_comm] rw [this, add_assoc] - rw [this, add_left_inj, Multiset.inter_add_sub_of_add_eq_add] + rw [this, add_left_inj, inter_add_sub_of_add_eq_add] rw [add_comm, ← N1_def, N2_def] apply add_comm · intros y y_in_union by_cases y_in : y ∈ Y2 - · rcases (Ord2 y y_in) with ⟨x, x_in_X2, y_lt_x⟩ - by_cases x_in : x ∈ Y1 - · rcases (Ord1 x x_in) with ⟨x', x'_in_X1, x_lt_x'⟩ - use x' + · rcases (Ord2 y y_in) with ⟨z, z_in_Z2, y_lt_z⟩ + by_cases z_in : z ∈ Y1 + · rcases (Ord1 z z_in) with ⟨z', z'_in_Z1, z_lt_z'⟩ + use z' constructor - · rw [Multiset.mem_add] + · rw [mem_add] constructor - exact x'_in_X1 - · exact lt_trans y_lt_x x_lt_x' - · use x + exact z'_in_Z1 + · exact lt_trans y_lt_z z_lt_z' + · use z constructor - · rw [add_comm, Multiset.mem_add] + · rw [add_comm, mem_add] constructor - rwa [Multiset.mem_sub, Multiset.count_eq_zero_of_not_mem, Multiset.count_pos] - exact x_in - · exact y_lt_x - · have y_in : y ∈ (Y1 - X2) := by simp_all only [Multiset.mem_add, false_or] + rwa [mem_sub, count_eq_zero_of_not_mem, count_pos] + exact z_in + · exact y_lt_z + · have y_in : y ∈ (Y1 - Z2) := by simp_all only [mem_add, false_or] have y_in_Y1 : y ∈ Y1 := by - have : Y1 - X2 ≤ Y1 := by + have : Y1 - Z2 ≤ Y1 := by simp_all [tsub_le_iff_right, le_add_iff_nonneg_right, zero_le] - simp only [Multiset.zero_le] - apply Multiset.mem_of_le + apply mem_of_le exact this exact y_in let ⟨w, ⟨left_1, right⟩⟩ := (Ord1 y) y_in_Y1 subst P2_def M1_def N2_def - simp_all only [Multiset.empty_eq_zero, ne_eq, Multiset.mem_add, or_true] + simp_all only [empty_eq_zero, ne_eq, mem_add, or_true] use w tauto lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] - [DecidableRel (fun (x : α) (y: α) => x < y)] (M N : Multiset α) (DMLTMN : MultisetDMLT M N) : - MultisetTransLT M N := by - rcases DMLTMN with ⟨X, Y, Z, Y_not_empty, MZX, NZY, h⟩ - unfold MultisetTransLT - revert Z X M N - induction Y using Multiset.strongInductionOn - case ih Y IH => - intro M N X Z M_def N_def X_lt_Y - cases em (Multiset.card Y = 0) + [DecidableRel (fun (x : α) (y : α) => x < y)] (M N : Multiset α) (DMLTMN : DMLT M N) : + TransLT M N := by + rcases DMLTMN with ⟨X, Y, Z, Z_not_empty, MXY, NXZ, h⟩ + unfold TransLT + revert X Y M N + induction Z using strongInductionOn + case ih Z IH => + intro M N X Y M_def N_def Y_lt_Z + cases em (card Z = 0) · simp_all - cases em (Multiset.card Y = 1) + cases em (card Z = 1) case inl hyp' hyp=> - rw [Multiset.card_eq_one] at hyp - rcases hyp with ⟨y,Y'_def⟩ + rw [card_eq_one] at hyp + rcases hyp with ⟨z,Z_def⟩ apply TransGen.single - rw [Y'_def] at N_def - refine ⟨Z, X, y, M_def, N_def, ?_⟩ - simp only [Y'_def, Multiset.mem_singleton, exists_eq_left] at X_lt_Y - exact X_lt_Y + rw [Z_def] at N_def + refine ⟨X, Y, z, M_def, N_def, ?_⟩ + simp only [Z_def, mem_singleton, exists_eq_left] at Y_lt_Z + exact Y_lt_Z case inr hyp' hyp => - have : ∃ a, a ∈ Y := by - rw [← Y.card_pos_iff_exists_mem] - cases foo : Multiset.card Y + have : ∃ a, a ∈ Z := by + rw [← Z.card_pos_iff_exists_mem] + cases Z_empty : card Z tauto simp - rcases this with ⟨y,claim⟩ - let newY := Y.erase y - have newY_nonEmpty : newY ≠ ∅ := by + rcases this with ⟨z,z_in_Z⟩ + let newZ := Z.erase z + have newZ_nonEmpty : newZ ≠ ∅ := by have : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by intros n h0 h1 cases n @@ -288,106 +289,117 @@ lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] case succ m => cases m case zero => contradiction - case succ n=> + case succ n => apply Nat.succ_le_succ - simp_all only [le_add_iff_nonneg_left, zero_le] - have : 0 < Multiset.card (Multiset.erase Y y) := by aesop - rw [Multiset.card_pos] at this - simp_all only [Multiset.empty_eq_zero, ne_eq, not_false_eq_true] - have newY_sub_Y : newY < Y := by simp (config := {zetaDelta := true}); exact claim - let f : α → Multiset α := fun y' => X.filter (fun x => x < y') -- DecidableRel - let N' := Z + newY + f y + simp_all + have : 0 < card (erase Z z) := by + subst M_def N_def + simp_all only + [empty_eq_zero, ne_eq, card_eq_zero, not_false_eq_true, ge_iff_le, card_erase_of_mem, + Nat.pred_eq_sub_one, tsub_pos_iff_lt] + apply this + · simp_all only [card_eq_zero, not_false_eq_true] + · simp_all only [not_false_eq_true] + rw [card_pos] at this + simp_all only [empty_eq_zero, ne_eq, not_false_eq_true] + have newZ_sub_Z : newZ < Z := by simp (config := {zetaDelta := true}); exact z_in_Z + let f : α → Multiset α := fun z => Y.filter (fun y => y < z) -- DecidableRel + let N' := X + newZ + f z apply @transitive_transGen _ _ _ N' -- step from N' to M - · apply IH newY newY_sub_Y newY_nonEmpty - change M = (Z + f y) + (X - f y) + · apply IH newZ newZ_sub_Z newZ_nonEmpty + change M = (X + f z) + (Y - f z) · ext a - have count_lt := Multiset.count_le_of_le a (Multiset.filter_le (fun x => x < y) X) + have count_lt := count_le_of_le a (filter_le (fun y => y < z) Y) rw [M_def] - simp_all only [Multiset.empty_eq_zero, ne_eq, Multiset.card_eq_zero, not_false_eq_true, - Multiset.count_add, Multiset.count_sub] - let x := Multiset.count a X - let z := Multiset.count a Z - let fx := Multiset.count a (Multiset.filter (fun x => x < y) X) - change z + x = z + fx + (x - fx) - change fx ≤ x at count_lt - have : x = fx + (x - fx) := by simp_all only [add_tsub_cancel_of_le] + simp_all only [empty_eq_zero, ne_eq, card_eq_zero, not_false_eq_true, + count_add, count_sub] + let y := count a Y + let x := count a X + let fz := count a (filter (fun x => x < z) Y) + change x + y = x + fz + (y - fz) + change fz ≤ y at count_lt + have : y = fz + (y - fz) := by simp_all only [add_tsub_cancel_of_le] linarith · unfold_let N' - rw [add_assoc, add_assoc, add_comm newY (f y)] - · intro x x_in - let X_lt_Y := X_lt_Y x - have x_in_X : x ∈ X := by - have Xfy_le_X : X - f y ≤ X:= by simp (config := {zetaDelta := true}) - apply Multiset.mem_of_le Xfy_le_X - exact x_in - let X_lt_Y := X_lt_Y x_in_X - rcases X_lt_Y with ⟨t, t_in_Y, x_lt_t⟩ + rw [add_assoc, add_assoc, add_comm newZ (f z)] + · intro y y_in + let Y_lt_Z := Y_lt_Z y + have y_in_Y : y ∈ Y := by + have Yfy_le_Y : Y - f z ≤ Y:= by simp (config := {zetaDelta := true}) + apply mem_of_le Yfy_le_Y + exact y_in + let Y_lt_Z := Y_lt_Z y_in_Y + rcases Y_lt_Z with ⟨t, t_in_Z, y_lt_t⟩ use t constructor - · by_cases t_in_newY : t ∈ newY - · exact t_in_newY + · by_cases t_in_newZ : t ∈ newZ + · exact t_in_newZ · exfalso - have : t = y := by - have : Y = newY + {y} := by - unfold_let newY - rw [add_comm, Multiset.singleton_add] - simp [Multiset.cons_erase claim] - rw [this, Multiset.mem_add] at t_in_Y - have : t ∈ ( {y} : Multiset α) := Or.resolve_left t_in_Y t_in_newY - rwa [← Multiset.mem_singleton] - have x_in_fy : x ∈ f y := by - unfold_let f; simp; rw [← this]; exact ⟨x_in_X, x_lt_t⟩ - have x_notin_Xfy : x ∉ X - f y := by + have : t = z := by + have : Z = newZ + {z} := by + unfold_let newZ + rw [add_comm, singleton_add] + simp [cons_erase z_in_Z] + rw [this, mem_add] at t_in_Z + have : t ∈ ( {z} : Multiset α) := Or.resolve_left t_in_Z t_in_newZ + rwa [← mem_singleton] + have y_in_fz : y ∈ f z := by + unfold_let f; simp; rw [← this]; exact ⟨y_in_Y, y_lt_t⟩ + have y_notin_Yfz : y ∉ Y - f z := by by_contra - let neg_f : α → Multiset α := fun y' => X.filter (fun x => ¬ x < y') - have : X - f y = neg_f y := by - have fy_negfy_X : f y + neg_f y = X := Multiset.filter_add_not _ _ - rw [← fy_negfy_X, add_tsub_cancel_left] - have x_in_neg_fy : x ∈ neg_f y := this ▸ x_in + let neg_f : α → Multiset α := fun y' => Y.filter (fun x => ¬ x < y') + have : Y - f z = neg_f z := by + have fz_negfz_Y : f z + neg_f z = Y := filter_add_not _ _ + rw [← fz_negfz_Y, add_tsub_cancel_left] + have y_in_neg_fz : y ∈ neg_f z := this ▸ y_in subst_eqs unfold_let neg_f at * - simp_all only [Multiset.mem_filter] - exact x_notin_Xfy x_in - · exact x_lt_t + simp_all only [mem_filter] + exact y_notin_Yfz y_in + · exact y_lt_t -- single step N to N' - · have : MultisetRedLT N' N := by - refine ⟨Z + newY, f y, y, ?_, ?_, ?_ ⟩ + · have : DMLT_singleton N' N := by + refine ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ · rfl - · have newY_y_Y: newY + {y} = Y := by - unfold_let newY; rw [add_comm, Multiset.singleton_add] - apply Multiset.cons_erase claim - have : Z + newY + {y} = Z + (newY + {y}) := by apply add_assoc - rw [this, newY_y_Y] + · have newZ_z_Z: newZ + {z} = Z := by + unfold_let newZ; rw [add_comm, singleton_add] + apply cons_erase z_in_Z + have : X + newZ + {z} = X + (newZ + {z}) := by apply add_assoc + rw [this, newZ_z_Z] exact N_def · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 apply TransGen.single exact this -/- MultisetTransLT and MultisetDMLT are equivalent. -/ +/- TransLT and DMLT are equivalent. -/ lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: - (MultisetTransLT : Multiset α → Multiset α → Prop) = - (MultisetDMLT : Multiset α → Multiset α → Prop) := by + (TransLT : Multiset α → Multiset α → Prop) = + (DMLT : Multiset α → Multiset α → Prop) := by funext X Y apply propext constructor - · -- TransLT → DMLT: - intros TransLT + · intros TransLT induction TransLT case single Z TransLT => rcases TransLT with ⟨W, U, y, X_def, Z_def, U_lt_y⟩ - use U, {y}, W + use W, U, {y} simp_all - case tail _ aih bih => -- it suffices to show MultisetDMLT is transitive + case tail _ aih bih => apply dmlt_trans _ _ _ _ bih - apply dmLT_of_redLT + apply dmlt_of_DMLT_singleton assumption - · -- DMLT → TransLT: - apply transLT_of_dmLT + · apply transLT_of_dmLT -/- The desired theorem: If `LT.lt` is well-founded, then `MultisetDMLT` is well-founded. -/ -theorem dmLT_wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] - (wf_lt : WellFoundedLT α) :WellFounded (MultisetDMLT : Multiset α → Multiset α → Prop) := by +/- The desired theorem: If `LT.lt` is well-founded, then `DMLT` is well-founded. -/ +theorem DMLT.wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] + (wf_lt : WellFoundedLT α) : WellFounded (DMLT : Multiset α → Multiset α → Prop) := by rw [← transLT_eq_dmLT] apply WellFounded.transGen - exact (redLT_wf wf_lt) + exact (DMLT_singleton_wf wf_lt) + +instance instWellFoundedDMLT [DecidableEq α] [Preorder α] + [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) : + WellFounded (@DMLT α _ _) := DMLT.wf wf_lt + +end Multiset From 749ce5931efc0d62bf6659fb9c04b915122cf2f7 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:23:25 +0100 Subject: [PATCH 20/32] remove space before a semicolon --- Mathlib/Data/Multiset/DershowitzManna.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 599d5c212fb03..46b00af90494c 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -144,7 +144,7 @@ lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) | intro x wfH wfh2 => apply acc_cons · simpa - · constructor ; simpa only + · constructor; simpa only · simpa only lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : From 4e791f056c8c6647faa35a49677d89e2474f8678 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:46:57 +0100 Subject: [PATCH 21/32] remove unnecessary `DecidableEq` inst --- Mathlib/Data/Multiset/DershowitzManna.lean | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 46b00af90494c..88d8ec1c1105a 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -36,7 +36,7 @@ namespace Multiset variable {α : Type*} /-- The standard Dershowitz–Manna ordering: -/ -def DMLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := +def DMLT [Preorder α] (M N : Multiset α) : Prop := ∃ (X Y Z : Multiset α), Z ≠ ∅ ∧ M = X + Y @@ -45,7 +45,7 @@ def DMLT [DecidableEq α] [Preorder α] (M N : Multiset α) : Prop := /-- A special case of DMLT. The transitive closure of it is used to define an equivalent (proved later) version of the ordering. -/ -def DMLT_singleton [DecidableEq α] [LT α] (M N : Multiset α) : Prop := +def DMLT_singleton [LT α] (M N : Multiset α) : Prop := ∃ (X Y : Multiset α) (a : α) , (M = X + Y) ∧ (N = X + {a}) @@ -55,11 +55,11 @@ open Relation /-- The transitive closure of DMLT_singleton and is equivalent to DMLT (proved later). -/ -def TransLT [DecidableEq α] [LT α] : Multiset α → Multiset α → Prop := +def TransLT [LT α] : Multiset α → Multiset α → Prop := TransGen DMLT_singleton /- A special case of DMLT. -/ -theorem dmlt_of_DMLT_singleton [DecidableEq α] [Preorder α] (M N : Multiset α) +theorem dmlt_of_DMLT_singleton [Preorder α] (M N : Multiset α) (h : DMLT_singleton M N) : DMLT M N := by rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ use X, Y, {a}, by simp, M_def, N_def @@ -192,7 +192,7 @@ lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] assumption -- `DMLT` is transitive. -lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α]: +lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : ∀ (M N P : Multiset α) , DMLT N M → DMLT P N → DMLT P M := by intros M N P LTNM LTPN rcases LTNM with ⟨X1, Y1, Z1, Z1_ne, N1_def, M1_def, Ord1⟩ @@ -400,6 +400,6 @@ theorem DMLT.wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : instance instWellFoundedDMLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) : - WellFounded (@DMLT α _ _) := DMLT.wf wf_lt + WellFounded (@DMLT α _) := DMLT.wf wf_lt end Multiset From dba4cf367cc3412a4e3854ba27473448fc34320a Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:34:06 +0100 Subject: [PATCH 22/32] instance changed to WellFounded Relation --- Mathlib/Data/Multiset/DershowitzManna.lean | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 88d8ec1c1105a..a7de8461f9829 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -58,7 +58,7 @@ open Relation def TransLT [LT α] : Multiset α → Multiset α → Prop := TransGen DMLT_singleton -/- A special case of DMLT. -/ +/-- A special case of DMLT. -/ theorem dmlt_of_DMLT_singleton [Preorder α] (M N : Multiset α) (h : DMLT_singleton M N) : DMLT M N := by rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ @@ -156,7 +156,7 @@ lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : apply @acc_cons_of_acc α _ _ _ _ _ accM1 simp_all -/- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is +/-- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is accessible given the `DMLT_singleton` relation. -/ lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc DMLT_singleton M := by @@ -179,7 +179,7 @@ lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : apply wf_el simp_all -/- If `LT.lt` is well-founded, then `DMLT_singleton` is well-founded. -/ +/-- If `LT.lt` is well-founded, then `DMLT_singleton` is well-founded. -/ lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] (wf_lt : WellFoundedLT α) : WellFounded (DMLT_singleton : Multiset α → Multiset α → Prop) := by constructor @@ -191,7 +191,7 @@ lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] apply Acc.intro y assumption --- `DMLT` is transitive. +/-- `DMLT` is transitive. -/ lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : ∀ (M N P : Multiset α) , DMLT N M → DMLT P N → DMLT P M := by intros M N P LTNM LTPN @@ -372,7 +372,7 @@ lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] apply TransGen.single exact this -/- TransLT and DMLT are equivalent. -/ +/-- TransLT and DMLT are equivalent. -/ lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: (TransLT : Multiset α → Multiset α → Prop) = (DMLT : Multiset α → Multiset α → Prop) := by @@ -391,15 +391,15 @@ lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) assumption · apply transLT_of_dmLT -/- The desired theorem: If `LT.lt` is well-founded, then `DMLT` is well-founded. -/ +/-- The desired theorem: If `LT.lt` is well-founded, then `DMLT` is well-founded. -/ theorem DMLT.wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) : WellFounded (DMLT : Multiset α → Multiset α → Prop) := by rw [← transLT_eq_dmLT] apply WellFounded.transGen exact (DMLT_singleton_wf wf_lt) -instance instWellFoundedDMLT [DecidableEq α] [Preorder α] - [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) : - WellFounded (@DMLT α _) := DMLT.wf wf_lt +instance instWellFoundedDMLT [DecidableEq α] [Preorder α] [wf_lt : WellFoundedLT α] + [DecidableRel (fun (x : α) (y : α) => x < y)] : + WellFoundedRelation (Multiset α) := ⟨DMLT, DMLT.wf wf_lt⟩ end Multiset From 08cacc6b6e732c2bb80a44e040996dc12ef9d99b Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:42:49 +0100 Subject: [PATCH 23/32] private def and lemma --- Mathlib/Data/Multiset/DershowitzManna.lean | 159 +++++++++++---------- 1 file changed, 80 insertions(+), 79 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index a7de8461f9829..37400c3c7eab3 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -10,9 +10,12 @@ import Mathlib.Logic.Relation /-! # Dershowitz-Manna ordering -In this file we define the _Dershowitz-Manna ordering_ on multisets. -We prove that, given a well-founded partial order on the underlying set, -the Dershowitz-Manna ordering defined over multisets is also well-founded. +In this file we define the _Dershowitz-Manna ordering_ on multisets. Specifically, for two multisets +M and N over an underlying set S, M is smaller than N in the Dershowitz-Manna ordering if M can be +obtained from N by replacing one or more elements in N by some finite number of elements from S, +each of which is smaller (in the underling ordering over S) than one of the replaced elements from +N. We prove that, given a well-founded partial order on the underlying set, the Dershowitz-Manna +ordering defined over multisets is also well-founded. ## Main results @@ -35,7 +38,7 @@ namespace Multiset variable {α : Type*} -/-- The standard Dershowitz–Manna ordering: -/ +/-- The standard Dershowitz–Manna ordering. -/ def DMLT [Preorder α] (M N : Multiset α) : Prop := ∃ (X Y Z : Multiset α), Z ≠ ∅ @@ -44,30 +47,28 @@ def DMLT [Preorder α] (M N : Multiset α) : Prop := ∧ (∀ y ∈ Y, ∃ z ∈ Z, y < z) /-- A special case of DMLT. The transitive closure of it is used to define - an equivalent (proved later) version of the ordering. -/ -def DMLT_singleton [LT α] (M N : Multiset α) : Prop := - ∃ (X Y : Multiset α) (a : α) , - (M = X + Y) - ∧ (N = X + {a}) - ∧ (∀ y, y ∈ Y → y < a) +an equivalent (proved later) version of the ordering. -/ +private def DMLTSingleton [LT α] (M N : Multiset α) : Prop := + ∃ X Y a, + M = X + Y + ∧ N = X + {a} + ∧ ∀ y ∈ Y, y < a open Relation -/-- The transitive closure of DMLT_singleton and is equivalent to DMLT - (proved later). -/ -def TransLT [LT α] : Multiset α → Multiset α → Prop := - TransGen DMLT_singleton +/-- The transitive closure of DMLTSingleton and is equivalent to DMLT (proved later). -/ +private def TransLT [LT α] : Multiset α → Multiset α → Prop := TransGen DMLTSingleton /-- A special case of DMLT. -/ -theorem dmlt_of_DMLT_singleton [Preorder α] (M N : Multiset α) - (h : DMLT_singleton M N) : DMLT M N := by +private lemma dmlt_of_DMLT_singleton [Preorder α] (M N : Multiset α) + (h : DMLTSingleton M N) : DMLT M N := by rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ use X, Y, {a}, by simp, M_def, N_def · simpa -lemma DMLT_singleton_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} - (h : DMLT_singleton N (a ::ₘ M)) : - ∃ M', N = (a ::ₘ M') ∧ (DMLT_singleton M' M) ∨ (N = M + M') ∧ (∀ x : α, x ∈ M' → x < a) := by +private lemma DMLT_singleton_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} + (h : DMLTSingleton N (a ::ₘ M)) : + ∃ M', N = a ::ₘ M' ∧ DMLTSingleton M' M ∨ N = M + M' ∧ ∀ x ∈ M', x < a := by rcases h with ⟨X, Y, a0, h1, h0, h2⟩ by_cases hyp : a = a0 · exists Y; right; apply And.intro @@ -75,53 +76,53 @@ lemma DMLT_singleton_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α rw [add_comm, singleton_add] at h0 simp_all · simp_all - · exists (Y + (M - {a0})) - left - constructor - · rw [h1] - have : X = (M - {a0} + {a}) := by - rw [add_comm, singleton_add] at * - ext b - simp only [ext, count_cons] at h0 - by_cases h : b = a - · have := h0 b - simp_all only [ite_true, ite_false, add_zero, sub_singleton, count_cons_self, ne_eq, - not_false_eq_true, count_erase_of_ne] - · have := h0 b - simp [sub_singleton] - simp_all only [↓reduceIte, add_zero, ne_eq, not_false_eq_true, count_cons_of_ne] - split at this - next h_1 => - simp_all only [count_erase_self, add_tsub_cancel_right] - next h_1 => simp_all only [add_zero, ne_eq, not_false_eq_true, count_erase_of_ne] - subst this + exists (Y + (M - {a0})) + left + constructor + · rw [h1] + have : X = (M - {a0} + {a}) := by + rw [add_comm, singleton_add] at * + ext b + simp only [ext, count_cons] at h0 + by_cases h : b = a + · have := h0 b + simp_all only [ite_true, ite_false, add_zero, sub_singleton, count_cons_self, ne_eq, + not_false_eq_true, count_erase_of_ne] + have := h0 b + simp [sub_singleton] + simp_all only [↓reduceIte, add_zero, ne_eq, not_false_eq_true, count_cons_of_ne] + split at this + next h_1 => + simp_all only [count_erase_self, add_tsub_cancel_right] + next h_1 => simp_all only [add_zero, ne_eq, not_false_eq_true, count_erase_of_ne] + subst this + rw [add_comm] + nth_rewrite 2 [add_comm] + rw [singleton_add, add_cons] + · unfold DMLTSingleton + refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ + · change Y + (M - {a0}) = (M - {a0}) + Y + rw [add_comm] + · change M = M - {a0} + {a0} + have this0 : M = X + {a0} - {a} := by + rw [← h0, sub_singleton, erase_cons_head] + have a0M : a0 ∈ M := by + rw [this0, sub_singleton, mem_erase_of_ne] + rw [mem_add, mem_singleton] + · apply Or.inr + rfl + · exact fun h ↦ hyp (Eq.symm h) rw [add_comm] - nth_rewrite 2 [add_comm] - rw [singleton_add, add_cons] - · unfold DMLT_singleton - refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ - · change Y + (M - {a0}) = (M - {a0}) + Y - rw [add_comm] - · change M = M - {a0} + {a0} - have this0: M = X + {a0} - {a} := by - rw [← h0, sub_singleton, erase_cons_head] - have a0M: a0 ∈ M := by - rw [this0, sub_singleton, mem_erase_of_ne] - rw [mem_add, mem_singleton] - · apply Or.inr - rfl - · exact fun h ↦ hyp (Eq.symm h) - rw [add_comm] - simp_all [singleton_add] + simp_all [singleton_add] -lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) - (_ : ∀ b M , LT.lt b a → Acc DMLT_singleton M → Acc DMLT_singleton (b ::ₘ M)) - (_ : Acc DMLT_singleton M0) - (_ : ∀ M, DMLT_singleton M M0 → Acc DMLT_singleton (a ::ₘ M)) : - Acc DMLT_singleton (a ::ₘ M0) := by +private lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) + (_ : ∀ b M , LT.lt b a → Acc DMLTSingleton M → Acc DMLTSingleton (b ::ₘ M)) + (_ : Acc DMLTSingleton M0) + (_ : ∀ M, DMLTSingleton M M0 → Acc DMLTSingleton (a ::ₘ M)) : + Acc DMLTSingleton (a ::ₘ M0) := by constructor intros N N_lt - change Acc DMLT_singleton N + change Acc DMLTSingleton N rcases (DMLT_singleton_insert N_lt) with ⟨x, H, h0⟩ case h.intro.inr h => rcases h with ⟨H, h0⟩ @@ -136,9 +137,9 @@ lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) case h.intro.inl.intro => simp_all -lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) - (H : ∀ (b : α), ∀ M, LT.lt b a → Acc DMLT_singleton M → Acc DMLT_singleton (b ::ₘ M)) : - ∀ M, Acc DMLT_singleton M → Acc DMLT_singleton (a ::ₘ M) := by +private lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) + (H : ∀ (b : α), ∀ M, LT.lt b a → Acc DMLTSingleton M → Acc DMLTSingleton (b ::ₘ M)) : + ∀ M, Acc DMLTSingleton M → Acc DMLTSingleton (a ::ₘ M) := by intros M h0 induction h0 with | intro x wfH wfh2 => @@ -147,8 +148,8 @@ lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) · constructor; simpa only · simpa only -lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : - ∀ (a:α), Acc LT.lt a → ∀ M, Acc DMLT_singleton M → Acc DMLT_singleton (a ::ₘ M) := by +private lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : + ∀ (a:α), Acc LT.lt a → ∀ M, Acc DMLTSingleton M → Acc DMLTSingleton (a ::ₘ M) := by intro w w_a induction w_a with | intro x _ ih => @@ -157,9 +158,9 @@ lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : simp_all /-- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is -accessible given the `DMLT_singleton` relation. -/ -lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : - ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc DMLT_singleton M := by +accessible given the `DMLTSingleton` relation. -/ +private lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : + ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc DMLTSingleton M := by intros M wf_el induction M using Multiset.induction_on with | empty => @@ -179,9 +180,9 @@ lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : apply wf_el simp_all -/-- If `LT.lt` is well-founded, then `DMLT_singleton` is well-founded. -/ -lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] - (wf_lt : WellFoundedLT α) : WellFounded (DMLT_singleton : Multiset α → Multiset α → Prop) := by +/-- If `LT.lt` is well-founded, then `DMLTSingleton` is well-founded. -/ +private lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] + (wf_lt : WellFoundedLT α) : WellFounded (DMLTSingleton : Multiset α → Multiset α → Prop) := by constructor intros a apply acc_of_acc_lt @@ -192,7 +193,7 @@ lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] assumption /-- `DMLT` is transitive. -/ -lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : +private lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : ∀ (M N P : Multiset α) , DMLT N M → DMLT P N → DMLT P M := by intros M N P LTNM LTPN rcases LTNM with ⟨X1, Y1, Z1, Z1_ne, N1_def, M1_def, Ord1⟩ @@ -253,7 +254,7 @@ lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : use w tauto -lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] +private lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] (M N : Multiset α) (DMLTMN : DMLT M N) : TransLT M N := by rcases DMLTMN with ⟨X, Y, Z, Z_not_empty, MXY, NXZ, h⟩ @@ -359,7 +360,7 @@ lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] exact y_notin_Yfz y_in · exact y_lt_t -- single step N to N' - · have : DMLT_singleton N' N := by + · have : DMLTSingleton N' N := by refine ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ · rfl · have newZ_z_Z: newZ + {z} = Z := by @@ -373,9 +374,9 @@ lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] exact this /-- TransLT and DMLT are equivalent. -/ -lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)]: - (TransLT : Multiset α → Multiset α → Prop) = - (DMLT : Multiset α → Multiset α → Prop) := by +private lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] + [DecidableRel (fun (x : α) (y: α) => x < y)] : + (TransLT : Multiset α → Multiset α → Prop) = (DMLT : Multiset α → Multiset α → Prop) := by funext X Y apply propext constructor From 3f1494718fa96a9f3dd04624f9aa363e2f9dbd8c Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:12:47 +0100 Subject: [PATCH 24/32] rename DMLT to IsDershowitzMannaLT --- Mathlib/Data/Multiset/DershowitzManna.lean | 55 ++++++++++++---------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 37400c3c7eab3..b85aa56546b1f 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -11,16 +11,17 @@ import Mathlib.Logic.Relation # Dershowitz-Manna ordering In this file we define the _Dershowitz-Manna ordering_ on multisets. Specifically, for two multisets -M and N over an underlying set S, M is smaller than N in the Dershowitz-Manna ordering if M can be -obtained from N by replacing one or more elements in N by some finite number of elements from S, -each of which is smaller (in the underling ordering over S) than one of the replaced elements from -N. We prove that, given a well-founded partial order on the underlying set, the Dershowitz-Manna -ordering defined over multisets is also well-founded. +`M` and `N` in a partial order `(S, <)`, `M` is smaller than `N` in the Dershowitz-Manna ordering if +`M` can be obtained from `N` by replacing one or more elements in `N` by some finite number of +elements from `S`, each of which is smaller (in the underling ordering over `S`) than one of the +replaced elements from `N`. We prove that, given a well-founded partial order on the underlying set, +the Dershowitz-Manna ordering defined over multisets is also well-founded. ## Main results -- `Multiset.DMLT` : the standard definition fo the `Dershowitz-Manna ordering`. -- `Multiset.DMLT.wf` : the main theorem about the `Dershowitz-Manna ordering` being well-founded. +- `Multiset.IsDershowitzMannaLT` : the standard definition fo the `Dershowitz-Manna ordering`. +- `Multiset.IsDershowitzMannaLT.wf` : the main theorem about the `Dershowitz-Manna ordering` +being well-founded. - `Multiset.TransLT_eq_DMLT` : two definitions of the `Dershowitz-Manna ordering` are equivalent. ## References @@ -39,14 +40,14 @@ namespace Multiset variable {α : Type*} /-- The standard Dershowitz–Manna ordering. -/ -def DMLT [Preorder α] (M N : Multiset α) : Prop := +def IsDershowitzMannaLT [Preorder α] (M N : Multiset α) : Prop := ∃ (X Y Z : Multiset α), Z ≠ ∅ ∧ M = X + Y ∧ N = X + Z ∧ (∀ y ∈ Y, ∃ z ∈ Z, y < z) -/-- A special case of DMLT. The transitive closure of it is used to define +/-- A special case of `IsDershowitzMannaLT`. The transitive closure of it is used to define an equivalent (proved later) version of the ordering. -/ private def DMLTSingleton [LT α] (M N : Multiset α) : Prop := ∃ X Y a, @@ -56,12 +57,13 @@ private def DMLTSingleton [LT α] (M N : Multiset α) : Prop := open Relation -/-- The transitive closure of DMLTSingleton and is equivalent to DMLT (proved later). -/ +/-- The transitive closure of `DMLTSingleton` and is equivalent to `IsDershowitzMannaLT` +(proved later). -/ private def TransLT [LT α] : Multiset α → Multiset α → Prop := TransGen DMLTSingleton -/-- A special case of DMLT. -/ +/-- A special case of `IsDershowitzMannaLT`. -/ private lemma dmlt_of_DMLT_singleton [Preorder α] (M N : Multiset α) - (h : DMLTSingleton M N) : DMLT M N := by + (h : DMLTSingleton M N) : IsDershowitzMannaLT M N := by rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ use X, Y, {a}, by simp, M_def, N_def · simpa @@ -157,7 +159,7 @@ private lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : apply @acc_cons_of_acc α _ _ _ _ _ accM1 simp_all -/-- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset M is +/-- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset `M` is accessible given the `DMLTSingleton` relation. -/ private lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc DMLTSingleton M := by @@ -192,9 +194,10 @@ private lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] apply Acc.intro y assumption -/-- `DMLT` is transitive. -/ +/-- `IsDershowitzMannaLT` is transitive. -/ private lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : - ∀ (M N P : Multiset α) , DMLT N M → DMLT P N → DMLT P M := by + ∀ (M N P : Multiset α) , + IsDershowitzMannaLT N M → IsDershowitzMannaLT P N → IsDershowitzMannaLT P M := by intros M N P LTNM LTPN rcases LTNM with ⟨X1, Y1, Z1, Z1_ne, N1_def, M1_def, Ord1⟩ rcases LTPN with ⟨X2, Y2, Z2, _, P2_def, N2_def, Ord2⟩ @@ -255,8 +258,8 @@ private lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : tauto private lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] - [DecidableRel (fun (x : α) (y : α) => x < y)] (M N : Multiset α) (DMLTMN : DMLT M N) : - TransLT M N := by + [DecidableRel (fun (x : α) (y : α) => x < y)] (M N : Multiset α) + (DMLTMN : IsDershowitzMannaLT M N) : TransLT M N := by rcases DMLTMN with ⟨X, Y, Z, Z_not_empty, MXY, NXZ, h⟩ unfold TransLT revert X Y M N @@ -307,7 +310,7 @@ private lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] let f : α → Multiset α := fun z => Y.filter (fun y => y < z) -- DecidableRel let N' := X + newZ + f z apply @transitive_transGen _ _ _ N' - -- step from N' to M + -- step from `N'` to `M` · apply IH newZ newZ_sub_Z newZ_nonEmpty change M = (X + f z) + (Y - f z) · ext a @@ -359,7 +362,7 @@ private lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] simp_all only [mem_filter] exact y_notin_Yfz y_in · exact y_lt_t - -- single step N to N' + -- single step `N` to `N'` · have : DMLTSingleton N' N := by refine ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ · rfl @@ -373,10 +376,11 @@ private lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] apply TransGen.single exact this -/-- TransLT and DMLT are equivalent. -/ +/-- `TransLT` and `IsDershowitzMannaLT` are equivalent. -/ private lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y: α) => x < y)] : - (TransLT : Multiset α → Multiset α → Prop) = (DMLT : Multiset α → Multiset α → Prop) := by + (TransLT : Multiset α → Multiset α → Prop) = + (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by funext X Y apply propext constructor @@ -392,15 +396,16 @@ private lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] assumption · apply transLT_of_dmLT -/-- The desired theorem: If `LT.lt` is well-founded, then `DMLT` is well-founded. -/ -theorem DMLT.wf [DecidableEq α] [Preorder α] [DecidableRel (fun (x : α) (y : α) => x < y)] - (wf_lt : WellFoundedLT α) : WellFounded (DMLT : Multiset α → Multiset α → Prop) := by +/-- The desired theorem: If `LT.lt` is well-founded, then `IsDershowitzMannaLT` is well-founded. -/ +theorem IsDershowitzMannaLT.wf [DecidableEq α] [Preorder α] + [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) : + WellFounded (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by rw [← transLT_eq_dmLT] apply WellFounded.transGen exact (DMLT_singleton_wf wf_lt) instance instWellFoundedDMLT [DecidableEq α] [Preorder α] [wf_lt : WellFoundedLT α] [DecidableRel (fun (x : α) (y : α) => x < y)] : - WellFoundedRelation (Multiset α) := ⟨DMLT, DMLT.wf wf_lt⟩ + WellFoundedRelation (Multiset α) := ⟨IsDershowitzMannaLT, IsDershowitzMannaLT.wf wf_lt⟩ end Multiset From 97366147f80a0e6ccfe32934658265d65d202473 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:51:27 +0100 Subject: [PATCH 25/32] =?UTF-8?q?add=20[Preorder=20=CE=B1]=20to=20variable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/Data/Multiset/DershowitzManna.lean | 75 +++++++++++----------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index b85aa56546b1f..1834fbbd786e0 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -20,8 +20,8 @@ the Dershowitz-Manna ordering defined over multisets is also well-founded. ## Main results - `Multiset.IsDershowitzMannaLT` : the standard definition fo the `Dershowitz-Manna ordering`. -- `Multiset.IsDershowitzMannaLT.wf` : the main theorem about the `Dershowitz-Manna ordering` -being well-founded. +- `Multiset.wellFounded_isDershowitzMannaLT` : the main theorem about the +`Dershowitz-Manna ordering` being well-founded. - `Multiset.TransLT_eq_DMLT` : two definitions of the `Dershowitz-Manna ordering` are equivalent. ## References @@ -37,10 +37,10 @@ being well-founded. namespace Multiset -variable {α : Type*} +variable {α : Type*} [Preorder α] /-- The standard Dershowitz–Manna ordering. -/ -def IsDershowitzMannaLT [Preorder α] (M N : Multiset α) : Prop := +def IsDershowitzMannaLT (M N : Multiset α) : Prop := ∃ (X Y Z : Multiset α), Z ≠ ∅ ∧ M = X + Y @@ -49,7 +49,7 @@ def IsDershowitzMannaLT [Preorder α] (M N : Multiset α) : Prop := /-- A special case of `IsDershowitzMannaLT`. The transitive closure of it is used to define an equivalent (proved later) version of the ordering. -/ -private def DMLTSingleton [LT α] (M N : Multiset α) : Prop := +private def OneStepLT [LT α] (M N : Multiset α) : Prop := ∃ X Y a, M = X + Y ∧ N = X + {a} @@ -57,20 +57,20 @@ private def DMLTSingleton [LT α] (M N : Multiset α) : Prop := open Relation -/-- The transitive closure of `DMLTSingleton` and is equivalent to `IsDershowitzMannaLT` +/-- The transitive closure of `OneStepLT` and is equivalent to `IsDershowitzMannaLT` (proved later). -/ -private def TransLT [LT α] : Multiset α → Multiset α → Prop := TransGen DMLTSingleton +private def TransLT [LT α] : Multiset α → Multiset α → Prop := TransGen OneStepLT /-- A special case of `IsDershowitzMannaLT`. -/ -private lemma dmlt_of_DMLT_singleton [Preorder α] (M N : Multiset α) - (h : DMLTSingleton M N) : IsDershowitzMannaLT M N := by +private lemma dmlt_of_DMLT_singleton (M N : Multiset α) + (h : OneStepLT M N) : IsDershowitzMannaLT M N := by rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ use X, Y, {a}, by simp, M_def, N_def · simpa -private lemma DMLT_singleton_insert [DecidableEq α] [LT α] {a : α} {M N : Multiset α} - (h : DMLTSingleton N (a ::ₘ M)) : - ∃ M', N = a ::ₘ M' ∧ DMLTSingleton M' M ∨ N = M + M' ∧ ∀ x ∈ M', x < a := by +private lemma DMLT_singleton_insert [DecidableEq α] {a : α} {M N : Multiset α} + (h : OneStepLT N (a ::ₘ M)) : + ∃ M', N = a ::ₘ M' ∧ OneStepLT M' M ∨ N = M + M' ∧ ∀ x ∈ M', x < a := by rcases h with ⟨X, Y, a0, h1, h0, h2⟩ by_cases hyp : a = a0 · exists Y; right; apply And.intro @@ -101,7 +101,7 @@ private lemma DMLT_singleton_insert [DecidableEq α] [LT α] {a : α} {M N : Mul rw [add_comm] nth_rewrite 2 [add_comm] rw [singleton_add, add_cons] - · unfold DMLTSingleton + · unfold OneStepLT refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ · change Y + (M - {a0}) = (M - {a0}) + Y rw [add_comm] @@ -117,14 +117,14 @@ private lemma DMLT_singleton_insert [DecidableEq α] [LT α] {a : α} {M N : Mul rw [add_comm] simp_all [singleton_add] -private lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α) - (_ : ∀ b M , LT.lt b a → Acc DMLTSingleton M → Acc DMLTSingleton (b ::ₘ M)) - (_ : Acc DMLTSingleton M0) - (_ : ∀ M, DMLTSingleton M M0 → Acc DMLTSingleton (a ::ₘ M)) : - Acc DMLTSingleton (a ::ₘ M0) := by +private lemma acc_cons [DecidableEq α] (a : α) (M0 : Multiset α) + (_ : ∀ b M , LT.lt b a → Acc OneStepLT M → Acc OneStepLT (b ::ₘ M)) + (_ : Acc OneStepLT M0) + (_ : ∀ M, OneStepLT M M0 → Acc OneStepLT (a ::ₘ M)) : + Acc OneStepLT (a ::ₘ M0) := by constructor intros N N_lt - change Acc DMLTSingleton N + change Acc OneStepLT N rcases (DMLT_singleton_insert N_lt) with ⟨x, H, h0⟩ case h.intro.inr h => rcases h with ⟨H, h0⟩ @@ -139,9 +139,9 @@ private lemma acc_cons [DecidableEq α] [Preorder α] (a : α) (M0 : Multiset α case h.intro.inl.intro => simp_all -private lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) - (H : ∀ (b : α), ∀ M, LT.lt b a → Acc DMLTSingleton M → Acc DMLTSingleton (b ::ₘ M)) : - ∀ M, Acc DMLTSingleton M → Acc DMLTSingleton (a ::ₘ M) := by +private lemma acc_cons_of_acc [DecidableEq α] (a : α) + (H : ∀ (b : α), ∀ M, LT.lt b a → Acc OneStepLT M → Acc OneStepLT (b ::ₘ M)) : + ∀ M, Acc OneStepLT M → Acc OneStepLT (a ::ₘ M) := by intros M h0 induction h0 with | intro x wfH wfh2 => @@ -150,8 +150,8 @@ private lemma acc_cons_of_acc [DecidableEq α] [Preorder α] (a : α) · constructor; simpa only · simpa only -private lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : - ∀ (a:α), Acc LT.lt a → ∀ M, Acc DMLTSingleton M → Acc DMLTSingleton (a ::ₘ M) := by +private lemma acc_cons_of_acc_of_lt [DecidableEq α] : + ∀ (a:α), Acc LT.lt a → ∀ M, Acc OneStepLT M → Acc OneStepLT (a ::ₘ M) := by intro w w_a induction w_a with | intro x _ ih => @@ -160,9 +160,9 @@ private lemma acc_cons_of_acc_of_lt [DecidableEq α] [Preorder α] : simp_all /-- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset `M` is -accessible given the `DMLTSingleton` relation. -/ -private lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : - ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc DMLTSingleton M := by +accessible given the `OneStepLT` relation. -/ +private lemma acc_of_acc_lt [DecidableEq α] : + ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc OneStepLT M := by intros M wf_el induction M using Multiset.induction_on with | empty => @@ -182,9 +182,9 @@ private lemma acc_of_acc_lt [DecidableEq α] [Preorder α] : apply wf_el simp_all -/-- If `LT.lt` is well-founded, then `DMLTSingleton` is well-founded. -/ -private lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] - (wf_lt : WellFoundedLT α) : WellFounded (DMLTSingleton : Multiset α → Multiset α → Prop) := by +/-- If `LT.lt` is well-founded, then `OneStepLT` is well-founded. -/ +private lemma DMLT_singleton_wf [DecidableEq α] + (wf_lt : WellFoundedLT α) : WellFounded (OneStepLT : Multiset α → Multiset α → Prop) := by constructor intros a apply acc_of_acc_lt @@ -195,7 +195,7 @@ private lemma DMLT_singleton_wf [DecidableEq α] [Preorder α] assumption /-- `IsDershowitzMannaLT` is transitive. -/ -private lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : +private lemma dmlt_trans {α} [dec : DecidableEq α] [Preorder α] : ∀ (M N P : Multiset α) , IsDershowitzMannaLT N M → IsDershowitzMannaLT P N → IsDershowitzMannaLT P M := by intros M N P LTNM LTPN @@ -257,7 +257,7 @@ private lemma dmlt_trans {α} [pre : Preorder α] [dec : DecidableEq α] : use w tauto -private lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] +private lemma transLT_of_dmLT [dec : DecidableEq α] [DecidableRel (fun (x : α) (y : α) => x < y)] (M N : Multiset α) (DMLTMN : IsDershowitzMannaLT M N) : TransLT M N := by rcases DMLTMN with ⟨X, Y, Z, Z_not_empty, MXY, NXZ, h⟩ @@ -363,7 +363,7 @@ private lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] exact y_notin_Yfz y_in · exact y_lt_t -- single step `N` to `N'` - · have : DMLTSingleton N' N := by + · have : OneStepLT N' N := by refine ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ · rfl · have newZ_z_Z: newZ + {z} = Z := by @@ -377,8 +377,7 @@ private lemma transLT_of_dmLT [dec : DecidableEq α] [Preorder α] exact this /-- `TransLT` and `IsDershowitzMannaLT` are equivalent. -/ -private lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] - [DecidableRel (fun (x : α) (y: α) => x < y)] : +private lemma transLT_eq_dmLT [DecidableEq α] [@DecidableRel α (· < ·)] : (TransLT : Multiset α → Multiset α → Prop) = (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by funext X Y @@ -397,15 +396,15 @@ private lemma transLT_eq_dmLT [DecidableEq α] [Preorder α] · apply transLT_of_dmLT /-- The desired theorem: If `LT.lt` is well-founded, then `IsDershowitzMannaLT` is well-founded. -/ -theorem IsDershowitzMannaLT.wf [DecidableEq α] [Preorder α] +theorem wellFounded_isDershowitzMannaLT [DecidableEq α] [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) : WellFounded (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by rw [← transLT_eq_dmLT] apply WellFounded.transGen exact (DMLT_singleton_wf wf_lt) -instance instWellFoundedDMLT [DecidableEq α] [Preorder α] [wf_lt : WellFoundedLT α] +instance instWellFoundedDMLT [DecidableEq α] [wf_lt : WellFoundedLT α] [DecidableRel (fun (x : α) (y : α) => x < y)] : - WellFoundedRelation (Multiset α) := ⟨IsDershowitzMannaLT, IsDershowitzMannaLT.wf wf_lt⟩ + WellFoundedRelation (Multiset α) := ⟨IsDershowitzMannaLT, wellFounded_isDershowitzMannaLT wf_lt⟩ end Multiset From e6963ab8e7183d5a237d18e4f50209f962b28c16 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:19:54 +0100 Subject: [PATCH 26/32] remove private for `isDershowitzMannaLT.trans` --- Mathlib/Data/Multiset/DershowitzManna.lean | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 1834fbbd786e0..aac35e1b9c9ef 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -22,7 +22,8 @@ the Dershowitz-Manna ordering defined over multisets is also well-founded. - `Multiset.IsDershowitzMannaLT` : the standard definition fo the `Dershowitz-Manna ordering`. - `Multiset.wellFounded_isDershowitzMannaLT` : the main theorem about the `Dershowitz-Manna ordering` being well-founded. -- `Multiset.TransLT_eq_DMLT` : two definitions of the `Dershowitz-Manna ordering` are equivalent. +- `Multiset.TransLT_eq_isDershowitzMannaLT` : two definitions of the `Dershowitz-Manna ordering` +are equivalent. ## References @@ -62,13 +63,13 @@ open Relation private def TransLT [LT α] : Multiset α → Multiset α → Prop := TransGen OneStepLT /-- A special case of `IsDershowitzMannaLT`. -/ -private lemma dmlt_of_DMLT_singleton (M N : Multiset α) +private lemma isDershowitzMannaLT_of_oneStepLT {M N : Multiset α} (h : OneStepLT M N) : IsDershowitzMannaLT M N := by rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ use X, Y, {a}, by simp, M_def, N_def · simpa -private lemma DMLT_singleton_insert [DecidableEq α] {a : α} {M N : Multiset α} +private lemma isDershowitzMannaLT_singleton_insert [DecidableEq α] {a : α} {M N : Multiset α} (h : OneStepLT N (a ::ₘ M)) : ∃ M', N = a ::ₘ M' ∧ OneStepLT M' M ∨ N = M + M' ∧ ∀ x ∈ M', x < a := by rcases h with ⟨X, Y, a0, h1, h0, h2⟩ @@ -125,7 +126,7 @@ private lemma acc_cons [DecidableEq α] (a : α) (M0 : Multiset α) constructor intros N N_lt change Acc OneStepLT N - rcases (DMLT_singleton_insert N_lt) with ⟨x, H, h0⟩ + rcases (isDershowitzMannaLT_singleton_insert N_lt) with ⟨x, H, h0⟩ case h.intro.inr h => rcases h with ⟨H, h0⟩ rw [H] @@ -183,7 +184,7 @@ private lemma acc_of_acc_lt [DecidableEq α] : simp_all /-- If `LT.lt` is well-founded, then `OneStepLT` is well-founded. -/ -private lemma DMLT_singleton_wf [DecidableEq α] +private lemma isDershowitzMannaLT_singleton_wf [DecidableEq α] (wf_lt : WellFoundedLT α) : WellFounded (OneStepLT : Multiset α → Multiset α → Prop) := by constructor intros a @@ -195,7 +196,7 @@ private lemma DMLT_singleton_wf [DecidableEq α] assumption /-- `IsDershowitzMannaLT` is transitive. -/ -private lemma dmlt_trans {α} [dec : DecidableEq α] [Preorder α] : +lemma isDershowitzMannaLT.trans {α} [dec : DecidableEq α] [Preorder α] : ∀ (M N P : Multiset α) , IsDershowitzMannaLT N M → IsDershowitzMannaLT P N → IsDershowitzMannaLT P M := by intros M N P LTNM LTPN @@ -257,7 +258,7 @@ private lemma dmlt_trans {α} [dec : DecidableEq α] [Preorder α] : use w tauto -private lemma transLT_of_dmLT [dec : DecidableEq α] +private lemma transLT_of_isDershowitzMannaLT [dec : DecidableEq α] [DecidableRel (fun (x : α) (y : α) => x < y)] (M N : Multiset α) (DMLTMN : IsDershowitzMannaLT M N) : TransLT M N := by rcases DMLTMN with ⟨X, Y, Z, Z_not_empty, MXY, NXZ, h⟩ @@ -377,7 +378,7 @@ private lemma transLT_of_dmLT [dec : DecidableEq α] exact this /-- `TransLT` and `IsDershowitzMannaLT` are equivalent. -/ -private lemma transLT_eq_dmLT [DecidableEq α] [@DecidableRel α (· < ·)] : +private lemma transLT_eq_isDershowitzMannaLT [DecidableEq α] [@DecidableRel α (· < ·)] : (TransLT : Multiset α → Multiset α → Prop) = (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by funext X Y @@ -390,20 +391,20 @@ private lemma transLT_eq_dmLT [DecidableEq α] [@DecidableRel α (· < ·)] : use W, U, {y} simp_all case tail _ aih bih => - apply dmlt_trans _ _ _ _ bih - apply dmlt_of_DMLT_singleton + apply isDershowitzMannaLT.trans _ _ _ _ bih + apply isDershowitzMannaLT_of_oneStepLT assumption - · apply transLT_of_dmLT + · apply transLT_of_isDershowitzMannaLT /-- The desired theorem: If `LT.lt` is well-founded, then `IsDershowitzMannaLT` is well-founded. -/ theorem wellFounded_isDershowitzMannaLT [DecidableEq α] [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) : WellFounded (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by - rw [← transLT_eq_dmLT] + rw [← transLT_eq_isDershowitzMannaLT] apply WellFounded.transGen - exact (DMLT_singleton_wf wf_lt) + exact (isDershowitzMannaLT_singleton_wf wf_lt) -instance instWellFoundedDMLT [DecidableEq α] [wf_lt : WellFoundedLT α] +instance instWellFoundedisDershowitzMannaLT [DecidableEq α] [wf_lt : WellFoundedLT α] [DecidableRel (fun (x : α) (y : α) => x < y)] : WellFoundedRelation (Multiset α) := ⟨IsDershowitzMannaLT, wellFounded_isDershowitzMannaLT wf_lt⟩ From 2893a3a59e0c3cd9b6a03bbe64d27de2e6a915b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 9 Nov 2024 23:29:55 +0000 Subject: [PATCH 27/32] first golf pass --- Mathlib/Data/Multiset/DershowitzManna.lean | 294 +++++++-------------- 1 file changed, 101 insertions(+), 193 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index aac35e1b9c9ef..38e389224de7b 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -3,9 +3,8 @@ Copyright (c) 2024 Haitian Wang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Haitian Wang, Malvin Gattinger -/ -import Mathlib.Tactic.Linarith -import Mathlib.Data.Multiset.Basic -import Mathlib.Logic.Relation +import Mathlib.Algebra.Order.Sub.Basic +import Mathlib.Data.Multiset.OrderedMonoid /-! # Dershowitz-Manna ordering @@ -36,54 +35,68 @@ are equivalent. -/ +open Relation + namespace Multiset -variable {α : Type*} [Preorder α] +variable {α : Type*} [Preorder α] {M N P : Multiset α} {a : α} /-- The standard Dershowitz–Manna ordering. -/ def IsDershowitzMannaLT (M N : Multiset α) : Prop := - ∃ (X Y Z : Multiset α), + ∃ X Y Z, Z ≠ ∅ ∧ M = X + Y ∧ N = X + Z - ∧ (∀ y ∈ Y, ∃ z ∈ Z, y < z) + ∧ ∀ y ∈ Y, ∃ z ∈ Z, y < z + +/-- `IsDershowitzMannaLT` is transitive. -/ +lemma IsDershowitzMannaLT.trans : + IsDershowitzMannaLT M N → IsDershowitzMannaLT N P → IsDershowitzMannaLT M P := by + classical + rintro ⟨X₁, Y₁, Z₁, hZ₁, rfl, rfl, hYZ₁⟩ ⟨X₂, Y₂, Z₂, hZ₂, hXZXY, rfl, hYZ₂⟩ + rw [add_comm X₁,add_comm X₂] at hXZXY + refine ⟨X₁ ∩ X₂, Y₁ + (Y₂ - Z₁), Z₂ + (Z₁ - Y₂), ?_, ?_, ?_, ?_⟩ + · simpa [-not_and, not_and_or] using .inl hZ₂ + · rwa [← add_assoc, add_right_comm, inter_add_sub_of_add_eq_add] + · rw [← add_assoc, add_right_comm, add_left_inj, inter_comm, inter_add_sub_of_add_eq_add] + rwa [eq_comm] + simp only [mem_add, or_imp, forall_and] + refine ⟨fun y hy ↦ ?_, fun y hy ↦ ?_⟩ + · obtain ⟨z, hz, hyz⟩ := hYZ₁ y hy + by_cases z_in : z ∈ Y₂ + · obtain ⟨w, hw, hzw⟩ := hYZ₂ z z_in + exact ⟨w, .inl hw, hyz.trans hzw⟩ + · exact ⟨z, .inr <| by rwa [mem_sub, count_eq_zero_of_not_mem z_in, count_pos], hyz⟩ + · obtain ⟨z, hz, hyz⟩ := hYZ₂ y <| mem_of_le (Multiset.sub_le_self ..) hy + exact ⟨z, .inl hz, hyz⟩ /-- A special case of `IsDershowitzMannaLT`. The transitive closure of it is used to define an equivalent (proved later) version of the ordering. -/ -private def OneStepLT [LT α] (M N : Multiset α) : Prop := +private def OneStep (M N : Multiset α) : Prop := ∃ X Y a, M = X + Y ∧ N = X + {a} ∧ ∀ y ∈ Y, y < a -open Relation - -/-- The transitive closure of `OneStepLT` and is equivalent to `IsDershowitzMannaLT` -(proved later). -/ -private def TransLT [LT α] : Multiset α → Multiset α → Prop := TransGen OneStepLT - -/-- A special case of `IsDershowitzMannaLT`. -/ -private lemma isDershowitzMannaLT_of_oneStepLT {M N : Multiset α} - (h : OneStepLT M N) : IsDershowitzMannaLT M N := by - rcases h with ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ +private lemma isDershowitzMannaLT_of_oneStep : OneStep M N → IsDershowitzMannaLT M N := by + rintro ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ use X, Y, {a}, by simp, M_def, N_def · simpa -private lemma isDershowitzMannaLT_singleton_insert [DecidableEq α] {a : α} {M N : Multiset α} - (h : OneStepLT N (a ::ₘ M)) : - ∃ M', N = a ::ₘ M' ∧ OneStepLT M' M ∨ N = M + M' ∧ ∀ x ∈ M', x < a := by - rcases h with ⟨X, Y, a0, h1, h0, h2⟩ +private lemma isDershowitzMannaLT_singleton_insert (h : OneStep N (a ::ₘ M)) : + ∃ M', N = a ::ₘ M' ∧ OneStep M' M ∨ N = M + M' ∧ ∀ x ∈ M', x < a := by + classical + rcases h with ⟨X, Y, a0, rfl, h0, h2⟩ by_cases hyp : a = a0 · exists Y; right; apply And.intro - · rw [h1, add_left_inj] + · rw [add_left_inj] rw [add_comm, singleton_add] at h0 simp_all · simp_all exists (Y + (M - {a0})) left constructor - · rw [h1] - have : X = (M - {a0} + {a}) := by + · have : X = (M - {a0} + {a}) := by rw [add_comm, singleton_add] at * ext b simp only [ext, count_cons] at h0 @@ -96,13 +109,13 @@ private lemma isDershowitzMannaLT_singleton_insert [DecidableEq α] {a : α} {M simp_all only [↓reduceIte, add_zero, ne_eq, not_false_eq_true, count_cons_of_ne] split at this next h_1 => - simp_all only [count_erase_self, add_tsub_cancel_right] + simp_all next h_1 => simp_all only [add_zero, ne_eq, not_false_eq_true, count_erase_of_ne] subst this rw [add_comm] nth_rewrite 2 [add_comm] rw [singleton_add, add_cons] - · unfold OneStepLT + · unfold OneStep refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ · change Y + (M - {a0}) = (M - {a0}) + Y rw [add_comm] @@ -118,14 +131,14 @@ private lemma isDershowitzMannaLT_singleton_insert [DecidableEq α] {a : α} {M rw [add_comm] simp_all [singleton_add] -private lemma acc_cons [DecidableEq α] (a : α) (M0 : Multiset α) - (_ : ∀ b M , LT.lt b a → Acc OneStepLT M → Acc OneStepLT (b ::ₘ M)) - (_ : Acc OneStepLT M0) - (_ : ∀ M, OneStepLT M M0 → Acc OneStepLT (a ::ₘ M)) : - Acc OneStepLT (a ::ₘ M0) := by +private lemma acc_cons (a : α) (M0 : Multiset α) + (_ : ∀ b M , LT.lt b a → Acc OneStep M → Acc OneStep (b ::ₘ M)) + (_ : Acc OneStep M0) + (_ : ∀ M, OneStep M M0 → Acc OneStep (a ::ₘ M)) : + Acc OneStep (a ::ₘ M0) := by constructor intros N N_lt - change Acc OneStepLT N + change Acc OneStep N rcases (isDershowitzMannaLT_singleton_insert N_lt) with ⟨x, H, h0⟩ case h.intro.inr h => rcases h with ⟨H, h0⟩ @@ -140,9 +153,9 @@ private lemma acc_cons [DecidableEq α] (a : α) (M0 : Multiset α) case h.intro.inl.intro => simp_all -private lemma acc_cons_of_acc [DecidableEq α] (a : α) - (H : ∀ (b : α), ∀ M, LT.lt b a → Acc OneStepLT M → Acc OneStepLT (b ::ₘ M)) : - ∀ M, Acc OneStepLT M → Acc OneStepLT (a ::ₘ M) := by +private lemma acc_cons_of_acc (a : α) + (H : ∀ b, ∀ M, b < a → Acc OneStep M → Acc OneStep (b ::ₘ M)) : + ∀ M, Acc OneStep M → Acc OneStep (a ::ₘ M) := by intros M h0 induction h0 with | intro x wfH wfh2 => @@ -151,20 +164,14 @@ private lemma acc_cons_of_acc [DecidableEq α] (a : α) · constructor; simpa only · simpa only -private lemma acc_cons_of_acc_of_lt [DecidableEq α] : - ∀ (a:α), Acc LT.lt a → ∀ M, Acc OneStepLT M → Acc OneStepLT (a ::ₘ M) := by - intro w w_a - induction w_a with - | intro x _ ih => - intro M accM1 - apply @acc_cons_of_acc α _ _ _ _ _ accM1 - simp_all +private lemma acc_cons_of_acc_of_lt (ha : Acc LT.lt a) : + ∀ M, Acc OneStep M → Acc OneStep (a ::ₘ M) := by + induction ha with + | intro x _ ih => exact acc_cons_of_acc _ (by simp_all) -/-- If all elements of a multiset `M` are accessible with `LT.lt`, then the multiset `M` is -accessible given the `OneStepLT` relation. -/ -private lemma acc_of_acc_lt [DecidableEq α] : - ∀ (M : Multiset α), (∀x, x ∈ M → Acc LT.lt x) → Acc OneStepLT M := by - intros M wf_el +/-- If all elements of a multiset `M` are accessible with `<`, then the multiset `M` is +accessible given the `OneStep` relation. -/ +private lemma acc_of_acc_lt (wf_el : ∀ x ∈ M, Acc LT.lt x) : Acc OneStep M := by induction M using Multiset.induction_on with | empty => constructor @@ -183,9 +190,9 @@ private lemma acc_of_acc_lt [DecidableEq α] : apply wf_el simp_all -/-- If `LT.lt` is well-founded, then `OneStepLT` is well-founded. -/ -private lemma isDershowitzMannaLT_singleton_wf [DecidableEq α] - (wf_lt : WellFoundedLT α) : WellFounded (OneStepLT : Multiset α → Multiset α → Prop) := by +/-- Over a well-founded order, `OneStep` is well-founded. -/ +private lemma isDershowitzMannaLT_singleton_wf (wf_lt : WellFoundedLT α) : + WellFounded (OneStep : Multiset α → Multiset α → Prop) := by constructor intros a apply acc_of_acc_lt @@ -195,88 +202,23 @@ private lemma isDershowitzMannaLT_singleton_wf [DecidableEq α] apply Acc.intro y assumption -/-- `IsDershowitzMannaLT` is transitive. -/ -lemma isDershowitzMannaLT.trans {α} [dec : DecidableEq α] [Preorder α] : - ∀ (M N P : Multiset α) , - IsDershowitzMannaLT N M → IsDershowitzMannaLT P N → IsDershowitzMannaLT P M := by - intros M N P LTNM LTPN - rcases LTNM with ⟨X1, Y1, Z1, Z1_ne, N1_def, M1_def, Ord1⟩ - rcases LTPN with ⟨X2, Y2, Z2, _, P2_def, N2_def, Ord2⟩ - refine ⟨X1 ∩ X2, Y2 + (Y1 - Z2), Z1 + (Z2 - Y1), ⟨?_, ?_, ?_, ?_⟩⟩ - · simp only [empty_eq_zero] at * - rw [← card_pos] - rw [← card_pos] at Z1_ne - simp only [_root_.map_add, add_pos_iff] - left - exact Z1_ne - · rw [P2_def] - have : X1 ∩ X2 + (Y2 + (Y1 - Z2)) = X1 ∩ X2 + (Y1 - Z2) + Y2 := by - have : (Y2 + (Y1 - Z2)) = (Y1 - Z2) + Y2 := by rw [add_comm] - rw [this, add_assoc] - rw [this] - have : X1 ∩ X2 + (Y1 - Z2) = X2 ∩ X1 + (Y1 - Z2) := by - rw [inter_comm] - rw [this, inter_add_sub_of_add_eq_add] - rw [add_comm, ← N2_def, N1_def] - apply add_comm - · rw [M1_def] - have : X1 ∩ X2 + (Z1 + (Z2 - Y1)) = X1 ∩ X2 + (Z2 - Y1) + Z1 := by - have : (Z1 + (Z2 - Y1)) = (Z2 - Y1) + Z1 := by rw [add_comm] - rw [this, add_assoc] - rw [this, add_left_inj, inter_add_sub_of_add_eq_add] - rw [add_comm, ← N1_def, N2_def] - apply add_comm - · intros y y_in_union - by_cases y_in : y ∈ Y2 - · rcases (Ord2 y y_in) with ⟨z, z_in_Z2, y_lt_z⟩ - by_cases z_in : z ∈ Y1 - · rcases (Ord1 z z_in) with ⟨z', z'_in_Z1, z_lt_z'⟩ - use z' - constructor - · rw [mem_add] - constructor - exact z'_in_Z1 - · exact lt_trans y_lt_z z_lt_z' - · use z - constructor - · rw [add_comm, mem_add] - constructor - rwa [mem_sub, count_eq_zero_of_not_mem, count_pos] - exact z_in - · exact y_lt_z - · have y_in : y ∈ (Y1 - Z2) := by simp_all only [mem_add, false_or] - have y_in_Y1 : y ∈ Y1 := by - have : Y1 - Z2 ≤ Y1 := by - simp_all [tsub_le_iff_right, le_add_iff_nonneg_right, - zero_le] - apply mem_of_le - exact this - exact y_in - let ⟨w, ⟨left_1, right⟩⟩ := (Ord1 y) y_in_Y1 - subst P2_def M1_def N2_def - simp_all only [empty_eq_zero, ne_eq, mem_add, or_true] - use w - tauto - -private lemma transLT_of_isDershowitzMannaLT [dec : DecidableEq α] - [DecidableRel (fun (x : α) (y : α) => x < y)] (M N : Multiset α) - (DMLTMN : IsDershowitzMannaLT M N) : TransLT M N := by - rcases DMLTMN with ⟨X, Y, Z, Z_not_empty, MXY, NXZ, h⟩ - unfold TransLT +private lemma transGen_oneStep_of_isDershowitzMannaLT : + IsDershowitzMannaLT M N → TransGen OneStep M N := by + classical + rintro ⟨X, Y, Z, Z_not_empty, MXY, NXZ, h⟩ revert X Y M N induction Z using strongInductionOn case ih Z IH => - intro M N X Y M_def N_def Y_lt_Z + rintro M N X Y rfl rfl Y_lt_Z cases em (card Z = 0) · simp_all cases em (card Z = 1) case inl hyp' hyp=> rw [card_eq_one] at hyp - rcases hyp with ⟨z,Z_def⟩ + obtain ⟨z, rfl⟩ := hyp apply TransGen.single - rw [Z_def] at N_def - refine ⟨X, Y, z, M_def, N_def, ?_⟩ - simp only [Z_def, mem_singleton, exists_eq_left] at Y_lt_Z + refine ⟨X, Y, z, rfl, rfl, ?_⟩ + simp only [mem_singleton, exists_eq_left] at Y_lt_Z exact Y_lt_Z case inr hyp' hyp => have : ∃ a, a ∈ Z := by @@ -286,37 +228,18 @@ private lemma transLT_of_isDershowitzMannaLT [dec : DecidableEq α] simp rcases this with ⟨z,z_in_Z⟩ let newZ := Z.erase z - have newZ_nonEmpty : newZ ≠ ∅ := by - have : ∀ (n : ℕ), n ≠ 0 → n ≠ 1 → n ≥ 2 := by - intros n h0 h1 - cases n - case zero => contradiction - case succ m => - cases m - case zero => contradiction - case succ n => - apply Nat.succ_le_succ - simp_all - have : 0 < card (erase Z z) := by - subst M_def N_def - simp_all only - [empty_eq_zero, ne_eq, card_eq_zero, not_false_eq_true, ge_iff_le, card_erase_of_mem, - Nat.pred_eq_sub_one, tsub_pos_iff_lt] - apply this - · simp_all only [card_eq_zero, not_false_eq_true] - · simp_all only [not_false_eq_true] - rw [card_pos] at this - simp_all only [empty_eq_zero, ne_eq, not_false_eq_true] + have newZ_nonEmpty : newZ ≠ 0 := by + simp [newZ, ← sub_singleton, tsub_eq_zero_iff_le] + aesop have newZ_sub_Z : newZ < Z := by simp (config := {zetaDelta := true}); exact z_in_Z let f : α → Multiset α := fun z => Y.filter (fun y => y < z) -- DecidableRel let N' := X + newZ + f z apply @transitive_transGen _ _ _ N' -- step from `N'` to `M` · apply IH newZ newZ_sub_Z newZ_nonEmpty - change M = (X + f z) + (Y - f z) - · ext a + · change _ = (X + f z) + (Y - f z) + ext a have count_lt := count_le_of_le a (filter_le (fun y => y < z) Y) - rw [M_def] simp_all only [empty_eq_zero, ne_eq, card_eq_zero, not_false_eq_true, count_add, count_sub] let y := count a Y @@ -324,9 +247,9 @@ private lemma transLT_of_isDershowitzMannaLT [dec : DecidableEq α] let fz := count a (filter (fun x => x < z) Y) change x + y = x + fz + (y - fz) change fz ≤ y at count_lt - have : y = fz + (y - fz) := by simp_all only [add_tsub_cancel_of_le] - linarith - · unfold_let N' + have : y = fz + (y - fz) := by simp_all + omega + · unfold N' rw [add_assoc, add_assoc, add_comm newZ (f z)] · intro y y_in let Y_lt_Z := Y_lt_Z y @@ -343,14 +266,14 @@ private lemma transLT_of_isDershowitzMannaLT [dec : DecidableEq α] · exfalso have : t = z := by have : Z = newZ + {z} := by - unfold_let newZ + unfold newZ rw [add_comm, singleton_add] simp [cons_erase z_in_Z] rw [this, mem_add] at t_in_Z have : t ∈ ( {z} : Multiset α) := Or.resolve_left t_in_Z t_in_newZ rwa [← mem_singleton] have y_in_fz : y ∈ f z := by - unfold_let f; simp; rw [← this]; exact ⟨y_in_Y, y_lt_t⟩ + unfold f; simp; rw [← this]; exact ⟨y_in_Y, y_lt_t⟩ have y_notin_Yfz : y ∉ Y - f z := by by_contra let neg_f : α → Multiset α := fun y' => Y.filter (fun x => ¬ x < y') @@ -359,53 +282,38 @@ private lemma transLT_of_isDershowitzMannaLT [dec : DecidableEq α] rw [← fz_negfz_Y, add_tsub_cancel_left] have y_in_neg_fz : y ∈ neg_f z := this ▸ y_in subst_eqs - unfold_let neg_f at * + unfold neg_f at * simp_all only [mem_filter] exact y_notin_Yfz y_in · exact y_lt_t -- single step `N` to `N'` - · have : OneStepLT N' N := by - refine ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ - · rfl - · have newZ_z_Z: newZ + {z} = Z := by - unfold_let newZ; rw [add_comm, singleton_add] - apply cons_erase z_in_Z - have : X + newZ + {z} = X + (newZ + {z}) := by apply add_assoc - rw [this, newZ_z_Z] - exact N_def - · unfold_let f; intro z z_in; simp at z_in; exact z_in.2 - apply TransGen.single - exact this + · refine .single ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ + · rfl + · have newZ_z_Z: newZ + {z} = Z := by + unfold newZ; rw [add_comm, singleton_add] + apply cons_erase z_in_Z + have : X + newZ + {z} = X + (newZ + {z}) := by apply add_assoc + rw [this, newZ_z_Z] + · unfold f; intro z z_in; simp at z_in; exact z_in.2 -/-- `TransLT` and `IsDershowitzMannaLT` are equivalent. -/ -private lemma transLT_eq_isDershowitzMannaLT [DecidableEq α] [@DecidableRel α (· < ·)] : - (TransLT : Multiset α → Multiset α → Prop) = - (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by - funext X Y - apply propext - constructor - · intros TransLT - induction TransLT - case single Z TransLT => - rcases TransLT with ⟨W, U, y, X_def, Z_def, U_lt_y⟩ - use W, U, {y} - simp_all - case tail _ aih bih => - apply isDershowitzMannaLT.trans _ _ _ _ bih - apply isDershowitzMannaLT_of_oneStepLT - assumption - · apply transLT_of_isDershowitzMannaLT +private lemma isDershowitzMannaLT_of_transGen_oneStep (hMN : TransGen OneStep M N) : + IsDershowitzMannaLT M N := + hMN.trans_induction_on (by rintro _ _ ⟨X, Y, a, rfl, rfl, hYa⟩; exact ⟨X, Y, {a}, by simpa⟩) + fun _ _ ↦ .trans + +/-- `TransGen OneStep` and `IsDershowitzMannaLT` are equivalent. -/ +private lemma transGen_oneStep_eq_isDershowitzMannaLT : + (TransGen OneStep : Multiset α → Multiset α → Prop) = IsDershowitzMannaLT := by + ext M N + exact ⟨isDershowitzMannaLT_of_transGen_oneStep, transGen_oneStep_of_isDershowitzMannaLT⟩ -/-- The desired theorem: If `LT.lt` is well-founded, then `IsDershowitzMannaLT` is well-founded. -/ -theorem wellFounded_isDershowitzMannaLT [DecidableEq α] - [DecidableRel (fun (x : α) (y : α) => x < y)] (wf_lt : WellFoundedLT α) : +/-- Over a well-founded order, the Dershowitz-Manna order on multisets is well-founded. -/ +theorem wellFounded_isDershowitzMannaLT [WellFoundedLT α] : WellFounded (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by - rw [← transLT_eq_isDershowitzMannaLT] - apply WellFounded.transGen - exact (isDershowitzMannaLT_singleton_wf wf_lt) + rw [← transGen_oneStep_eq_isDershowitzMannaLT] + exact (isDershowitzMannaLT_singleton_wf ‹_›).transGen -instance instWellFoundedisDershowitzMannaLT [DecidableEq α] [wf_lt : WellFoundedLT α] - [DecidableRel (fun (x : α) (y : α) => x < y)] : - WellFoundedRelation (Multiset α) := ⟨IsDershowitzMannaLT, wellFounded_isDershowitzMannaLT wf_lt⟩ +instance instWellFoundedisDershowitzMannaLT [WellFoundedLT α] : WellFoundedRelation (Multiset α) := + ⟨IsDershowitzMannaLT, wellFounded_isDershowitzMannaLT⟩ end Multiset From af8eea9dfe0a69a0a865132f2ac725b208cdcf2b Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:25:20 +0100 Subject: [PATCH 28/32] second glof pass --- Mathlib/Data/Multiset/DershowitzManna.lean | 47 +++++----------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 38e389224de7b..fc0121b20d174 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -102,15 +102,9 @@ private lemma isDershowitzMannaLT_singleton_insert (h : OneStep N (a ::ₘ M)) : simp only [ext, count_cons] at h0 by_cases h : b = a · have := h0 b - simp_all only [ite_true, ite_false, add_zero, sub_singleton, count_cons_self, ne_eq, - not_false_eq_true, count_erase_of_ne] - have := h0 b - simp [sub_singleton] - simp_all only [↓reduceIte, add_zero, ne_eq, not_false_eq_true, count_cons_of_ne] - split at this - next h_1 => simp_all - next h_1 => simp_all only [add_zero, ne_eq, not_false_eq_true, count_erase_of_ne] + have := h0 b + aesop subst this rw [add_comm] nth_rewrite 2 [add_comm] @@ -129,7 +123,7 @@ private lemma isDershowitzMannaLT_singleton_insert (h : OneStep N (a ::ₘ M)) : rfl · exact fun h ↦ hyp (Eq.symm h) rw [add_comm] - simp_all [singleton_add] + simp_all private lemma acc_cons (a : α) (M0 : Multiset α) (_ : ∀ b M , LT.lt b a → Acc OneStep M → Acc OneStep (b ::ₘ M)) @@ -138,7 +132,6 @@ private lemma acc_cons (a : α) (M0 : Multiset α) Acc OneStep (a ::ₘ M0) := by constructor intros N N_lt - change Acc OneStep N rcases (isDershowitzMannaLT_singleton_insert N_lt) with ⟨x, H, h0⟩ case h.intro.inr h => rcases h with ⟨H, h0⟩ @@ -148,8 +141,7 @@ private lemma acc_cons (a : α) (M0 : Multiset α) | empty => simpa | cons h => - simp_all only [mem_cons, or_true, implies_true, true_implies, forall_eq_or_imp, - add_cons] + simp_all case h.intro.inl.intro => simp_all @@ -161,8 +153,8 @@ private lemma acc_cons_of_acc (a : α) | intro x wfH wfh2 => apply acc_cons · simpa - · constructor; simpa only - · simpa only + · constructor; simpa + · simpa private lemma acc_cons_of_acc_of_lt (ha : Acc LT.lt a) : ∀ M, Acc OneStep M → Acc OneStep (a ::ₘ M) := by @@ -179,7 +171,7 @@ private lemma acc_of_acc_lt (wf_el : ∀ x ∈ M, Acc LT.lt x) : Acc OneStep M : absurd y_lt rintro ⟨X, Y, a, _, nonsense, _⟩ have contra : a ∈ (0 : Multiset α):= by - simp_all only [mem_add, mem_singleton, or_true] + simp_all contradiction | cons _ _ ih => apply acc_cons_of_acc_of_lt @@ -213,7 +205,7 @@ private lemma transGen_oneStep_of_isDershowitzMannaLT : cases em (card Z = 0) · simp_all cases em (card Z = 1) - case inl hyp' hyp=> + case inl hyp' hyp => rw [card_eq_one] at hyp obtain ⟨z, rfl⟩ := hyp apply TransGen.single @@ -232,7 +224,7 @@ private lemma transGen_oneStep_of_isDershowitzMannaLT : simp [newZ, ← sub_singleton, tsub_eq_zero_iff_le] aesop have newZ_sub_Z : newZ < Z := by simp (config := {zetaDelta := true}); exact z_in_Z - let f : α → Multiset α := fun z => Y.filter (fun y => y < z) -- DecidableRel + let f : α → Multiset α := fun z => Y.filter (fun y => y < z) let N' := X + newZ + f z apply @transitive_transGen _ _ _ N' -- step from `N'` to `M` @@ -246,17 +238,12 @@ private lemma transGen_oneStep_of_isDershowitzMannaLT : let x := count a X let fz := count a (filter (fun x => x < z) Y) change x + y = x + fz + (y - fz) - change fz ≤ y at count_lt - have : y = fz + (y - fz) := by simp_all omega · unfold N' rw [add_assoc, add_assoc, add_comm newZ (f z)] · intro y y_in let Y_lt_Z := Y_lt_Z y - have y_in_Y : y ∈ Y := by - have Yfy_le_Y : Y - f z ≤ Y:= by simp (config := {zetaDelta := true}) - apply mem_of_le Yfy_le_Y - exact y_in + have y_in_Y : y ∈ Y := by aesop let Y_lt_Z := Y_lt_Z y_in_Y rcases Y_lt_Z with ⟨t, t_in_Z, y_lt_t⟩ use t @@ -272,19 +259,7 @@ private lemma transGen_oneStep_of_isDershowitzMannaLT : rw [this, mem_add] at t_in_Z have : t ∈ ( {z} : Multiset α) := Or.resolve_left t_in_Z t_in_newZ rwa [← mem_singleton] - have y_in_fz : y ∈ f z := by - unfold f; simp; rw [← this]; exact ⟨y_in_Y, y_lt_t⟩ - have y_notin_Yfz : y ∉ Y - f z := by - by_contra - let neg_f : α → Multiset α := fun y' => Y.filter (fun x => ¬ x < y') - have : Y - f z = neg_f z := by - have fz_negfz_Y : f z + neg_f z = Y := filter_add_not _ _ - rw [← fz_negfz_Y, add_tsub_cancel_left] - have y_in_neg_fz : y ∈ neg_f z := this ▸ y_in - subst_eqs - unfold neg_f at * - simp_all only [mem_filter] - exact y_notin_Yfz y_in + aesop · exact y_lt_t -- single step `N` to `N'` · refine .single ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ From 9ccc1a6d31dc3e230b3f81a472d6ec794f83baa7 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:38:01 +0100 Subject: [PATCH 29/32] remove unecessary `unfold ..` and `simpa` --- Mathlib/Data/Multiset/DershowitzManna.lean | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index fc0121b20d174..cd23257452eef 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -109,8 +109,7 @@ private lemma isDershowitzMannaLT_singleton_insert (h : OneStep N (a ::ₘ M)) : rw [add_comm] nth_rewrite 2 [add_comm] rw [singleton_add, add_cons] - · unfold OneStep - refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ + · refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ · change Y + (M - {a0}) = (M - {a0}) + Y rw [add_comm] · change M = M - {a0} + {a0} @@ -152,9 +151,9 @@ private lemma acc_cons_of_acc (a : α) induction h0 with | intro x wfH wfh2 => apply acc_cons - · simpa - · constructor; simpa - · simpa + · assumption + · constructor; assumption + · assumption private lemma acc_cons_of_acc_of_lt (ha : Acc LT.lt a) : ∀ M, Acc OneStep M → Acc OneStep (a ::ₘ M) := by @@ -253,7 +252,6 @@ private lemma transGen_oneStep_of_isDershowitzMannaLT : · exfalso have : t = z := by have : Z = newZ + {z} := by - unfold newZ rw [add_comm, singleton_add] simp [cons_erase z_in_Z] rw [this, mem_add] at t_in_Z @@ -265,7 +263,7 @@ private lemma transGen_oneStep_of_isDershowitzMannaLT : · refine .single ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ · rfl · have newZ_z_Z: newZ + {z} = Z := by - unfold newZ; rw [add_comm, singleton_add] + rw [add_comm, singleton_add] apply cons_erase z_in_Z have : X + newZ + {z} = X + (newZ + {z}) := by apply add_assoc rw [this, newZ_z_Z] From 66764c1782b239cd0436207528975b53bfc9dd74 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Mon, 18 Nov 2024 22:55:59 +0100 Subject: [PATCH 30/32] replace with placeholder --- Mathlib/Data/Multiset/DershowitzManna.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index cd23257452eef..a8a8572380949 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -53,7 +53,7 @@ def IsDershowitzMannaLT (M N : Multiset α) : Prop := lemma IsDershowitzMannaLT.trans : IsDershowitzMannaLT M N → IsDershowitzMannaLT N P → IsDershowitzMannaLT M P := by classical - rintro ⟨X₁, Y₁, Z₁, hZ₁, rfl, rfl, hYZ₁⟩ ⟨X₂, Y₂, Z₂, hZ₂, hXZXY, rfl, hYZ₂⟩ + rintro ⟨X₁, Y₁, Z₁, _, rfl, rfl, hYZ₁⟩ ⟨X₂, Y₂, Z₂, hZ₂, hXZXY, rfl, hYZ₂⟩ rw [add_comm X₁,add_comm X₂] at hXZXY refine ⟨X₁ ∩ X₂, Y₁ + (Y₂ - Z₁), Z₂ + (Z₁ - Y₂), ?_, ?_, ?_, ?_⟩ · simpa [-not_and, not_and_or] using .inl hZ₂ From 4a2bf939b983eedca3ba204d2644124856090187 Mon Sep 17 00:00:00 2001 From: yukiniu <127060846+yukiniu@users.noreply.github.com> Date: Tue, 19 Nov 2024 13:54:53 +0100 Subject: [PATCH 31/32] - instead of _ --- Mathlib/Data/Multiset/DershowitzManna.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index a8a8572380949..7702d5d00933b 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -53,7 +53,7 @@ def IsDershowitzMannaLT (M N : Multiset α) : Prop := lemma IsDershowitzMannaLT.trans : IsDershowitzMannaLT M N → IsDershowitzMannaLT N P → IsDershowitzMannaLT M P := by classical - rintro ⟨X₁, Y₁, Z₁, _, rfl, rfl, hYZ₁⟩ ⟨X₂, Y₂, Z₂, hZ₂, hXZXY, rfl, hYZ₂⟩ + rintro ⟨X₁, Y₁, Z₁, -, rfl, rfl, hYZ₁⟩ ⟨X₂, Y₂, Z₂, hZ₂, hXZXY, rfl, hYZ₂⟩ rw [add_comm X₁,add_comm X₂] at hXZXY refine ⟨X₁ ∩ X₂, Y₁ + (Y₂ - Z₁), Z₂ + (Z₁ - Y₂), ?_, ?_, ?_, ?_⟩ · simpa [-not_and, not_and_or] using .inl hZ₂ From dbd9cbbc82e2cfe54857a16ef9ebb9437fed0b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 24 Nov 2024 13:37:43 +0000 Subject: [PATCH 32/32] second golf pass --- Mathlib/Data/Multiset/DershowitzManna.lean | 183 ++++++--------------- 1 file changed, 52 insertions(+), 131 deletions(-) diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean index 7702d5d00933b..965365ff2fa99 100644 --- a/Mathlib/Data/Multiset/DershowitzManna.lean +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -86,112 +86,52 @@ private lemma isDershowitzMannaLT_of_oneStep : OneStep M N → IsDershowitzManna private lemma isDershowitzMannaLT_singleton_insert (h : OneStep N (a ::ₘ M)) : ∃ M', N = a ::ₘ M' ∧ OneStep M' M ∨ N = M + M' ∧ ∀ x ∈ M', x < a := by classical - rcases h with ⟨X, Y, a0, rfl, h0, h2⟩ - by_cases hyp : a = a0 - · exists Y; right; apply And.intro - · rw [add_left_inj] - rw [add_comm, singleton_add] at h0 - simp_all - · simp_all - exists (Y + (M - {a0})) - left - constructor - · have : X = (M - {a0} + {a}) := by - rw [add_comm, singleton_add] at * - ext b - simp only [ext, count_cons] at h0 - by_cases h : b = a - · have := h0 b - simp_all - have := h0 b - aesop - subst this - rw [add_comm] - nth_rewrite 2 [add_comm] - rw [singleton_add, add_cons] - · refine ⟨M - {a0}, Y, a0, ?_, ?_, h2⟩ - · change Y + (M - {a0}) = (M - {a0}) + Y - rw [add_comm] - · change M = M - {a0} + {a0} - have this0 : M = X + {a0} - {a} := by - rw [← h0, sub_singleton, erase_cons_head] - have a0M : a0 ∈ M := by - rw [this0, sub_singleton, mem_erase_of_ne] - rw [mem_add, mem_singleton] - · apply Or.inr - rfl - · exact fun h ↦ hyp (Eq.symm h) - rw [add_comm] - simp_all - -private lemma acc_cons (a : α) (M0 : Multiset α) - (_ : ∀ b M , LT.lt b a → Acc OneStep M → Acc OneStep (b ::ₘ M)) - (_ : Acc OneStep M0) - (_ : ∀ M, OneStep M M0 → Acc OneStep (a ::ₘ M)) : - Acc OneStep (a ::ₘ M0) := by - constructor - intros N N_lt - rcases (isDershowitzMannaLT_singleton_insert N_lt) with ⟨x, H, h0⟩ - case h.intro.inr h => - rcases h with ⟨H, h0⟩ - rw [H] - clear H - induction x using Multiset.induction with - | empty => - simpa - | cons h => - simp_all - case h.intro.inl.intro => - simp_all - -private lemma acc_cons_of_acc (a : α) - (H : ∀ b, ∀ M, b < a → Acc OneStep M → Acc OneStep (b ::ₘ M)) : - ∀ M, Acc OneStep M → Acc OneStep (a ::ₘ M) := by - intros M h0 - induction h0 with - | intro x wfH wfh2 => - apply acc_cons - · assumption - · constructor; assumption - · assumption - -private lemma acc_cons_of_acc_of_lt (ha : Acc LT.lt a) : - ∀ M, Acc OneStep M → Acc OneStep (a ::ₘ M) := by - induction ha with - | intro x _ ih => exact acc_cons_of_acc _ (by simp_all) + obtain ⟨X, Y, b, rfl, h0, h2⟩ := h + obtain rfl | hab := eq_or_ne a b + · refine ⟨Y, .inr ⟨?_, h2⟩⟩ + simpa [add_comm _ {a}, singleton_add, eq_comm] using h0 + refine ⟨Y + (M - {b}), .inl ⟨?_, M - {b}, Y, b, add_comm .., ?_, h2⟩⟩ + · rw [← singleton_add, add_comm] at h0 + rw [tsub_eq_tsub_of_add_eq_add h0, add_comm Y, ← singleton_add, ← add_assoc, + add_tsub_cancel_of_le] + have : a ∈ X + {b} := by simp [← h0] + simpa [hab] using this + · rw [tsub_add_cancel_of_le] + have : b ∈ a ::ₘ M := by simp [h0] + simpa [hab.symm] using this + +private lemma acc_oneStep_cons_of_acc_lt (ha : Acc LT.lt a) : + ∀ {M}, Acc OneStep M → Acc OneStep (a ::ₘ M) := by + induction' ha with a _ ha + rintro M hM + induction' hM with M hM ihM + refine .intro _ fun N hNM ↦ ?_ + obtain ⟨N, ⟨rfl, hNM'⟩ | ⟨rfl, hN⟩⟩ := isDershowitzMannaLT_singleton_insert hNM + · exact ihM _ hNM' + clear hNM + induction N using Multiset.induction with + | empty => + simpa using .intro _ hM + | @cons b N ihN => + simp only [mem_cons, forall_eq_or_imp, add_cons] at hN ⊢ + obtain ⟨hba, hN⟩ := hN + exact ha _ hba <| ihN hN /-- If all elements of a multiset `M` are accessible with `<`, then the multiset `M` is accessible given the `OneStep` relation. -/ -private lemma acc_of_acc_lt (wf_el : ∀ x ∈ M, Acc LT.lt x) : Acc OneStep M := by +private lemma acc_oneStep_of_acc_lt (hM : ∀ x ∈ M, Acc LT.lt x) : Acc OneStep M := by induction M using Multiset.induction_on with | empty => constructor - intro y y_lt - absurd y_lt - rintro ⟨X, Y, a, _, nonsense, _⟩ - have contra : a ∈ (0 : Multiset α):= by - simp_all - contradiction - | cons _ _ ih => - apply acc_cons_of_acc_of_lt - · apply wf_el - simp_all - · apply ih - intros - apply wf_el - simp_all + simp [OneStep, eq_comm (b := _ + _)] + | cons a M ih => + exact acc_oneStep_cons_of_acc_lt (hM _ <| mem_cons_self ..) <| ih fun x hx ↦ + hM _ <| mem_cons_of_mem hx /-- Over a well-founded order, `OneStep` is well-founded. -/ -private lemma isDershowitzMannaLT_singleton_wf (wf_lt : WellFoundedLT α) : - WellFounded (OneStep : Multiset α → Multiset α → Prop) := by - constructor - intros a - apply acc_of_acc_lt - intros x _ - apply wf_lt.induction x - intros y h - apply Acc.intro y - assumption +private lemma isDershowitzMannaLT_singleton_wf [WellFoundedLT α] : + WellFounded (OneStep : Multiset α → Multiset α → Prop) := + ⟨fun _M ↦ acc_oneStep_of_acc_lt fun a _ ↦ WellFoundedLT.apply a⟩ private lemma transGen_oneStep_of_isDershowitzMannaLT : IsDershowitzMannaLT M N → TransGen OneStep M N := by @@ -212,18 +152,15 @@ private lemma transGen_oneStep_of_isDershowitzMannaLT : simp only [mem_singleton, exists_eq_left] at Y_lt_Z exact Y_lt_Z case inr hyp' hyp => - have : ∃ a, a ∈ Z := by + obtain ⟨z, z_in_Z⟩ : ∃ a, a ∈ Z := by rw [← Z.card_pos_iff_exists_mem] - cases Z_empty : card Z - tauto - simp - rcases this with ⟨z,z_in_Z⟩ + omega let newZ := Z.erase z have newZ_nonEmpty : newZ ≠ 0 := by simp [newZ, ← sub_singleton, tsub_eq_zero_iff_le] aesop have newZ_sub_Z : newZ < Z := by simp (config := {zetaDelta := true}); exact z_in_Z - let f : α → Multiset α := fun z => Y.filter (fun y => y < z) + let f (z : α) : Multiset α := Y.filter (· < z) let N' := X + newZ + f z apply @transitive_transGen _ _ _ N' -- step from `N'` to `M` @@ -241,33 +178,17 @@ private lemma transGen_oneStep_of_isDershowitzMannaLT : · unfold N' rw [add_assoc, add_assoc, add_comm newZ (f z)] · intro y y_in - let Y_lt_Z := Y_lt_Z y - have y_in_Y : y ∈ Y := by aesop - let Y_lt_Z := Y_lt_Z y_in_Y - rcases Y_lt_Z with ⟨t, t_in_Z, y_lt_t⟩ - use t - constructor - · by_cases t_in_newZ : t ∈ newZ - · exact t_in_newZ - · exfalso - have : t = z := by - have : Z = newZ + {z} := by - rw [add_comm, singleton_add] - simp [cons_erase z_in_Z] - rw [this, mem_add] at t_in_Z - have : t ∈ ( {z} : Multiset α) := Or.resolve_left t_in_Z t_in_newZ - rwa [← mem_singleton] - aesop - · exact y_lt_t + obtain ⟨t, t_in_Z, y_lt_t⟩ := Y_lt_Z y (by aesop) + refine ⟨t, (mem_erase_of_ne ?_).2 t_in_Z, y_lt_t⟩ + rintro rfl + simp [f, y_lt_t] at y_in -- single step `N` to `N'` - · refine .single ⟨X + newZ, f z, z, ?_, ?_, ?_ ⟩ - · rfl - · have newZ_z_Z: newZ + {z} = Z := by - rw [add_comm, singleton_add] - apply cons_erase z_in_Z - have : X + newZ + {z} = X + (newZ + {z}) := by apply add_assoc - rw [this, newZ_z_Z] - · unfold f; intro z z_in; simp at z_in; exact z_in.2 + · refine .single ⟨X + newZ, f z, z, rfl, ?_, by simp [f]⟩ + have newZ_z_Z : newZ + {z} = Z := by + rw [add_comm, singleton_add] + apply cons_erase z_in_Z + have : X + newZ + {z} = X + (newZ + {z}) := by apply add_assoc + rw [this, newZ_z_Z] private lemma isDershowitzMannaLT_of_transGen_oneStep (hMN : TransGen OneStep M N) : IsDershowitzMannaLT M N := @@ -284,7 +205,7 @@ private lemma transGen_oneStep_eq_isDershowitzMannaLT : theorem wellFounded_isDershowitzMannaLT [WellFoundedLT α] : WellFounded (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by rw [← transGen_oneStep_eq_isDershowitzMannaLT] - exact (isDershowitzMannaLT_singleton_wf ‹_›).transGen + exact isDershowitzMannaLT_singleton_wf.transGen instance instWellFoundedisDershowitzMannaLT [WellFoundedLT α] : WellFoundedRelation (Multiset α) := ⟨IsDershowitzMannaLT, wellFounded_isDershowitzMannaLT⟩