diff --git a/src/data/finset/basic.lean b/src/data/finset/basic.lean index 3e438875ed350..e161ee228c855 100644 --- a/src/data/finset/basic.lean +++ b/src/data/finset/basic.lean @@ -402,8 +402,11 @@ theorem not_mem_singleton {a b : α} : a ∉ ({b} : finset α) ↔ a ≠ b := no theorem mem_singleton_self (a : α) : a ∈ ({a} : finset α) := or.inl rfl +lemma singleton_injective : injective (singleton : α → finset α) := +λ a b h, mem_singleton.1 (h ▸ mem_singleton_self _) + theorem singleton_inj {a b : α} : ({a} : finset α) = {b} ↔ a = b := -⟨λ h, mem_singleton.1 (h ▸ mem_singleton_self _), congr_arg _⟩ +singleton_injective.eq_iff @[simp] theorem singleton_nonempty (a : α) : ({a} : finset α).nonempty := ⟨a, mem_singleton_self a⟩ @@ -644,6 +647,21 @@ theorem induction_on' {α : Type*} {p : finset α → Prop} [decidable_eq α] @finset.induction_on α (λ T, T ⊆ S → p T) _ S (λ _, h₁) (λ a s has hqs hs, let ⟨hS, sS⟩ := finset.insert_subset.1 hs in h₂ hS sS has (hqs sS)) (finset.subset.refl S) +/-- To prove a proposition about a nonempty `s : finset α`, it suffices to show it holds for all +singletons and that if it holds for `t : finset α`, then it also holds for the `finset` obtained by +inserting an element in `t`. -/ +@[elab_as_eliminator] +lemma nonempty.cons_induction {α : Type*} {s : finset α} (hs : s.nonempty) {p : finset α → Prop} + (h₀ : ∀ a, p {a}) (h₁ : ∀ ⦃a⦄ s (h : a ∉ s), p s → p (finset.cons a s h)) : + p s := +begin + induction s using finset.cons_induction with a t ha h, + { exact (not_nonempty_empty hs).elim, }, + obtain rfl | ht := t.eq_empty_or_nonempty, + { exact h₀ a }, + { exact h₁ t ha (h ht) } +end + /-- Inserting an element to a finite set is equivalent to the option type. -/ def subtype_insert_equiv_option {t : finset α} {x : α} (h : x ∉ t) : {i // i ∈ insert x t} ≃ option {i // i ∈ t} := @@ -2170,6 +2188,8 @@ card_eq_zero.trans val_eq_zero theorem card_pos {s : finset α} : 0 < card s ↔ s.nonempty := pos_iff_ne_zero.trans $ (not_congr card_eq_zero).trans nonempty_iff_ne_empty.symm +alias finset.card_pos ↔ _ finset.nonempty.card_pos + theorem card_ne_zero_of_mem {s : finset α} {a : α} (h : a ∈ s) : card s ≠ 0 := (not_congr card_eq_zero).2 (ne_empty_of_mem h) @@ -2794,6 +2814,13 @@ by rw [disjoint.comm, disjoint_left] theorem disjoint_iff_ne {s t : finset α} : disjoint s t ↔ ∀ a ∈ s, ∀ b ∈ t, a ≠ b := by simp only [disjoint_left, imp_not_comm, forall_eq'] +lemma not_disjoint_iff {s t : finset α} : + ¬disjoint s t ↔ ∃ a, a ∈ s ∧ a ∈ t := +not_forall.trans $ exists_congr $ λ a, begin + rw [finset.inf_eq_inter, finset.mem_inter], + exact not_not, +end + theorem disjoint_of_subset_left {s t u : finset α} (h : s ⊆ u) (d : disjoint u t) : disjoint s t := disjoint_left.2 (λ x m₁, (disjoint_left.1 d) (h m₁)) diff --git a/src/data/finset/lattice.lean b/src/data/finset/lattice.lean index ea4aa01d8a5cb..df0e137f991fe 100644 --- a/src/data/finset/lattice.lean +++ b/src/data/finset/lattice.lean @@ -25,7 +25,7 @@ variables [semilattice_sup_bot α] /-- Supremum of a finite set: `sup {a, b, c} f = f a ⊔ f b ⊔ f c` -/ def sup (s : finset β) (f : β → α) : α := s.fold (⊔) ⊥ f -variables {s s₁ s₂ : finset β} {f : β → α} +variables {s s₁ s₂ : finset β} {f g : β → α} lemma sup_def : s.sup f = (s.1.map f).sup := rfl @@ -38,7 +38,7 @@ fold_cons h @[simp] lemma sup_insert [decidable_eq β] {b : β} : (insert b s : finset β).sup f = f b ⊔ s.sup f := fold_insert_idem -lemma sup_image [decidable_eq β] (s : finset γ) (f : γ → β) (g : β → α): +lemma sup_image [decidable_eq β] (s : finset γ) (f : γ → β) (g : β → α) : (s.image f).sup g = s.sup (g ∘ f) := fold_image_idem @@ -53,6 +53,14 @@ lemma sup_union [decidable_eq β] : (s₁ ∪ s₂).sup f = s₁.sup f ⊔ s₂. finset.induction_on s₁ (by rw [empty_union, sup_empty, bot_sup_eq]) $ λ a s has ih, by rw [insert_union, sup_insert, sup_insert, ih, sup_assoc] +lemma sup_sup : s.sup (f ⊔ g) = s.sup f ⊔ s.sup g := +begin + refine finset.cons_induction_on s _ (λ b t _ h, _), + { rw [sup_empty, sup_empty, sup_empty, bot_sup_eq] }, + { rw [sup_cons, sup_cons, sup_cons, h], + exact sup_sup_sup_comm _ _ _ _ } +end + theorem sup_congr {f g : β → α} (hs : s₁ = s₂) (hfg : ∀a∈s₂, f a = g a) : s₁.sup f = s₂.sup g := by subst hs; exact finset.fold_congr hfg @@ -98,6 +106,26 @@ sup_le $ assume b hb, le_sup (h hb) (λ h, ⟨c, or.inl rfl, h⟩) (λ h, let ⟨b, hb, hlt⟩ := ih h in ⟨b, or.inr hb, hlt⟩)), (λ ⟨b, hb, hlt⟩, lt_of_lt_of_le hlt (le_sup hb))⟩ +@[simp] lemma sup_attach (s : finset β) (f : β → α) : s.attach.sup (λ x, f x) = s.sup f := +(s.attach.sup_map (function.embedding.subtype _) f).symm.trans $ congr_arg _ attach_map_val + +@[simp] lemma sup_erase_bot [decidable_eq α] (s : finset α) : (s.erase ⊥).sup id = s.sup id := +begin + refine (sup_mono (s.erase_subset _)).antisymm (finset.sup_le_iff.2 $ λ a ha, _), + obtain rfl | ha' := eq_or_ne a ⊥, + { exact bot_le }, + { exact le_sup (mem_erase.2 ⟨ha', ha⟩) } +end + +lemma sup_sdiff_right {α β : Type*} [generalized_boolean_algebra α] (s : finset β) (f : β → α) + (a : α) : + s.sup (λ b, f b \ a) = s.sup f \ a := +begin + refine finset.cons_induction_on s _ (λ b t _ h, _), + { rw [sup_empty, sup_empty, bot_sdiff] }, + { rw [sup_cons, sup_cons, h, sup_sdiff] } +end + lemma comp_sup_eq_sup_comp [semilattice_sup_bot γ] {s : finset β} {f : β → α} (g : α → γ) (g_sup : ∀ x y, g (x ⊔ y) = g x ⊔ g y) (bot : g ⊥ = ⊥) : g (s.sup f) = s.sup (g ∘ f) := @@ -137,7 +165,7 @@ begin end lemma sup_le_of_le_directed {α : Type*} [semilattice_sup_bot α] (s : set α) - (hs : s.nonempty) (hdir : directed_on (≤) s) (t : finset α): + (hs : s.nonempty) (hdir : directed_on (≤) s) (t : finset α) : (∀ x ∈ t, ∃ y ∈ s, x ≤ y) → ∃ x, x ∈ s ∧ t.sup id ≤ x := begin classical, @@ -188,7 +216,7 @@ variables [semilattice_inf_top α] /-- Infimum of a finite set: `inf {a, b, c} f = f a ⊓ f b ⊓ f c` -/ def inf (s : finset β) (f : β → α) : α := s.fold (⊓) ⊤ f -variables {s s₁ s₂ : finset β} {f : β → α} +variables {s s₁ s₂ : finset β} {f g : β → α} lemma inf_def : s.inf f = (s.1.map f).inf := rfl @@ -201,7 +229,7 @@ fold_empty @[simp] lemma inf_insert [decidable_eq β] {b : β} : (insert b s : finset β).inf f = f b ⊓ s.inf f := fold_insert_idem -lemma inf_image [decidable_eq β] (s : finset γ) (f : γ → β) (g : β → α): +lemma inf_image [decidable_eq β] (s : finset γ) (f : γ → β) (g : β → α) : (s.image f).inf g = s.inf (g ∘ f) := fold_image_idem @@ -215,6 +243,9 @@ inf_singleton lemma inf_union [decidable_eq β] : (s₁ ∪ s₂).inf f = s₁.inf f ⊓ s₂.inf f := @sup_union (order_dual α) _ _ _ _ _ _ +lemma inf_inf : s.inf (f ⊓ g) = s.inf f ⊓ s.inf g := +@sup_sup (order_dual α) _ _ _ _ _ + theorem inf_congr {f g : β → α} (hs : s₁ = s₂) (hfg : ∀a∈s₂, f a = g a) : s₁.inf f = s₂.inf g := by subst hs; exact finset.fold_congr hfg @@ -249,6 +280,38 @@ le_inf $ assume b hb, inf_le (h hb) @[simp] lemma inf_lt_iff [is_total α (≤)] {a : α} : s.inf f < a ↔ (∃ b ∈ s, f b < a) := @lt_sup_iff (order_dual α) _ _ _ _ _ _ +lemma inf_attach (s : finset β) (f : β → α) : s.attach.inf (λ x, f x) = s.inf f := +@sup_attach (order_dual α) _ _ _ _ + +@[simp] lemma inf_erase_top [decidable_eq α] (s : finset α) : (s.erase ⊤).inf id = s.inf id := +@sup_erase_bot (order_dual α) _ _ _ + +lemma sup_sdiff_left {α β : Type*} [boolean_algebra α] (s : finset β) (f : β → α) (a : α) : + s.sup (λ b, a \ f b) = a \ s.inf f := +begin + refine finset.cons_induction_on s _ (λ b t _ h, _), + { rw [sup_empty, inf_empty, sdiff_top] }, + { rw [sup_cons, inf_cons, h, sdiff_inf] } +end + +lemma inf_sdiff_left {α β : Type*} [boolean_algebra α] {s : finset β} (hs : s.nonempty) (f : β → α) + (a : α) : + s.inf (λ b, a \ f b) = a \ s.sup f := +begin + refine hs.cons_induction (λ b, _) (λ b t _ h, _), + { rw [sup_singleton, inf_singleton] }, + { rw [sup_cons, inf_cons, h, sdiff_sup] } +end + +lemma inf_sdiff_right {α β : Type*} [boolean_algebra α] {s : finset β} (hs : s.nonempty) (f : β → α) + (a : α) : + s.inf (λ b, f b \ a) = s.inf f \ a := +begin + refine hs.cons_induction (λ b, _) (λ b t _ h, _), + { rw [inf_singleton, inf_singleton] }, + { rw [inf_cons, inf_cons, h, inf_sdiff] } +end + lemma comp_inf_eq_inf_comp [semilattice_inf_top γ] {s : finset β} {f : β → α} (g : α → γ) (g_inf : ∀ x y, g (x ⊓ y) = g x ⊓ g y) (top : g ⊤ = ⊤) : g (s.inf f) = s.inf (g ∘ f) := @@ -892,6 +955,12 @@ lemma sup_eq_bUnion {α β} [decidable_eq β] (s : finset α) (t : α → finset s.sup t = s.bUnion t := by { ext, rw [mem_sup, mem_bUnion], } +@[simp] lemma sup_singleton' [decidable_eq α] (s : finset α) : s.sup singleton = s := +begin + refine (finset.sup_le $ λ a, _).antisymm (λ a ha, mem_sup.2 ⟨a, ha, mem_singleton_self a⟩), + exact singleton_subset_iff.2, +end + end finset section lattice diff --git a/src/order/lattice.lean b/src/order/lattice.lean index 46d5e2606067d..bd1f2c10c6dcd 100644 --- a/src/order/lattice.lean +++ b/src/order/lattice.lean @@ -234,6 +234,9 @@ by rw [← sup_assoc, ← sup_assoc, @sup_comm α _ a] lemma sup_right_comm (a b c : α) : a ⊔ b ⊔ c = a ⊔ c ⊔ b := by rw [sup_assoc, sup_assoc, @sup_comm _ _ b] +lemma sup_sup_sup_comm (a b c d : α) : a ⊔ b ⊔ (c ⊔ d) = a ⊔ c ⊔ (b ⊔ d) := +by rw [sup_assoc, sup_left_comm b, ←sup_assoc] + lemma forall_le_or_exists_lt_sup (a : α) : (∀b, b ≤ a) ∨ (∃b, a < b) := suffices (∃b, ¬b ≤ a) → (∃b, a < b), by rwa [or_iff_not_imp_left, not_forall], @@ -389,6 +392,9 @@ lemma inf_left_comm (a b c : α) : a ⊓ (b ⊓ c) = b ⊓ (a ⊓ c) := lemma inf_right_comm (a b c : α) : a ⊓ b ⊓ c = a ⊓ c ⊓ b := @sup_right_comm (order_dual α) _ a b c +lemma inf_inf_inf_comm (a b c d : α) : a ⊓ b ⊓ (c ⊓ d) = a ⊓ c ⊓ (b ⊓ d) := +@sup_sup_sup_comm (order_dual α) _ _ _ _ _ + lemma forall_le_or_exists_lt_inf (a : α) : (∀b, a ≤ b) ∨ (∃b, b < a) := @forall_le_or_exists_lt_sup (order_dual α) _ a