Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Commit

Permalink
feat({data/{finset,set},order/filter}/pointwise): Pointwise monoids a…
Browse files Browse the repository at this point in the history
…re division monoids (#13900)

`α` is a `division_monoid` implies that `set α`, `finset α`, `filter α` are too. The core result needed for this is that `s` is a unit in `set α`/`finset α`/`filter α` if and only if it is equal to `{u}`/`{u}`/`pure u` for some unit `u : α`.
  • Loading branch information
YaelDillies committed May 12, 2022
1 parent c2e87de commit c57cfc6
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 96 deletions.
93 changes: 77 additions & 16 deletions src/data/finset/pointwise.lean
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ localized "attribute [instance] finset.has_one finset.has_zero" in pointwise
@[simp, to_additive]
lemma image_one [decidable_eq β] {f : α → β} : image f 1 = {f 1} := image_singleton f 1

/-- The singleton operation as a `one_hom`. -/
@[to_additive "The singleton operation as a `zero_hom`."]
def singleton_one_hom : one_hom α (finset α) := ⟨singleton, singleton_one⟩

@[simp, to_additive] lemma coe_singleton_one_hom : (singleton_one_hom : α → finset α) = singleton :=
rfl
@[simp, to_additive] lemma singleton_one_hom_apply (a : α) : singleton_one_hom a = {a} := rfl

end has_one

/-! ### Finset negation/inversion -/
Expand Down Expand Up @@ -190,6 +198,14 @@ image₂_inter_subset_right
lemma subset_mul {s t : set α} : ↑u ⊆ s * t → ∃ s' t' : finset α, ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ s' * t' :=
subset_image₂

/-- The singleton operation as a `mul_hom`. -/
@[to_additive "The singleton operation as an `add_hom`."]
def singleton_mul_hom : α →ₙ* finset α := ⟨singleton, λ a b, (singleton_mul_singleton _ _).symm⟩

@[simp, to_additive] lemma coe_singleton_mul_hom : (singleton_mul_hom : α → finset α) = singleton :=
rfl
@[simp, to_additive] lemma singleton_mul_hom_apply (a : α) : singleton_mul_hom a = {a} := rfl

end has_mul

/-! ### Finset subtraction/division -/
Expand Down Expand Up @@ -306,6 +322,14 @@ coe_injective.mul_one_class _ (coe_singleton 1) coe_mul
localized "attribute [instance] finset.semigroup finset.add_semigroup finset.comm_semigroup
finset.add_comm_semigroup finset.mul_one_class finset.add_zero_class" in pointwise

/-- The singleton operation as a `monoid_hom`. -/
@[to_additive "The singleton operation as an `add_monoid_hom`."]
def singleton_monoid_hom : α →* finset α := { ..singleton_mul_hom, ..singleton_one_hom }

@[simp, to_additive] lemma coe_singleton_monoid_hom :
(singleton_monoid_hom : α → finset α) = singleton := rfl
@[simp, to_additive] lemma singleton_monoid_hom_apply (a : α) : singleton_monoid_hom a = {a} := rfl

end mul_one_class

section monoid
Expand All @@ -326,43 +350,80 @@ protected def monoid : monoid (finset α) := coe_injective.monoid _ coe_one coe_

localized "attribute [instance] finset.monoid finset.add_monoid" in pointwise

@[to_additive] protected lemma _root_.is_unit.finset : is_unit a → is_unit ({a} : finset α) :=
is_unit.map (singleton_monoid_hom : α →* finset α)

end monoid

/-- `finset α` is a `comm_monoid` under pointwise operations if `α` is. -/
@[to_additive "`finset α` is an `add_comm_monoid` under pointwise operations if `α` is. "]
protected def comm_monoid [comm_monoid α] : comm_monoid (finset α) :=
coe_injective.comm_monoid _ coe_one coe_mul coe_pow

-- TODO: Generalize the duplicated lemmas and instances below to `division_monoid`
open_locale pointwise

@[simp, to_additive] lemma coe_zpow [group α] (s : finset α) : ∀ n : ℤ, ↑(s ^ n) = (s ^ n : set α)
| (int.of_nat n) := coe_pow _ _
| (int.neg_succ_of_nat n) :=
by { refine (coe_inv _).trans _, convert congr_arg has_inv.inv (coe_pow _ _) }
section division_monoid
variables [division_monoid α] {s t : finset α}

@[simp] lemma coe_zpow' [group_with_zero α] (s : finset α) : ∀ n : ℤ, ↑(s ^ n) = (s ^ n : set α)
@[simp, to_additive] lemma coe_zpow (s : finset α) : ∀ n : ℤ, ↑(s ^ n) = (s ^ n : set α)
| (int.of_nat n) := coe_pow _ _
| (int.neg_succ_of_nat n) :=
by { refine (coe_inv _).trans _, convert congr_arg has_inv.inv (coe_pow _ _) }

/-- `finset α` is a `div_inv_monoid` under pointwise operations if `α` is. -/
@[to_additive "`finset α` is an `sub_neg_add_monoid` under pointwise operations if `α` is."]
protected def div_inv_monoid [group α] : div_inv_monoid (finset α) :=
coe_injective.div_inv_monoid _ coe_one coe_mul coe_inv coe_div coe_pow coe_zpow
@[to_additive] protected lemma mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 :=
by simp_rw [←coe_inj, coe_mul, coe_one, set.mul_eq_one_iff, coe_singleton]

/-- `finset α` is a `div_inv_monoid` under pointwise operations if `α` is. -/
protected def div_inv_monoid' [group_with_zero α] : div_inv_monoid (finset α) :=
coe_injective.div_inv_monoid _ coe_one coe_mul coe_inv coe_div coe_pow coe_zpow'
/-- `finset α` is a division monoid under pointwise operations if `α` is. -/
@[to_additive subtraction_monoid "`finset α` is a subtraction monoid under pointwise operations if
`α` is."]
protected def division_monoid : division_monoid (finset α) :=
coe_injective.division_monoid _ coe_one coe_mul coe_inv coe_div coe_pow coe_zpow

localized "attribute [instance] finset.comm_monoid finset.add_comm_monoid finset.div_inv_monoid
finset.sub_neg_add_monoid finset.div_inv_monoid'" in pointwise
@[simp, to_additive] lemma is_unit_iff : is_unit s ↔ ∃ a, s = {a} ∧ is_unit a :=
begin
split,
{ rintro ⟨u, rfl⟩,
obtain ⟨a, b, ha, hb, h⟩ := finset.mul_eq_one_iff.1 u.mul_inv,
refine ⟨a, ha, ⟨a, b, h, singleton_injective _⟩, rfl⟩,
rw [←singleton_mul_singleton, ←ha, ←hb],
exact u.inv_mul },
{ rintro ⟨a, rfl, ha⟩,
exact ha.finset }
end

@[simp, to_additive] lemma is_unit_coe : is_unit (s : set α) ↔ is_unit s :=
by simp_rw [is_unit_iff, set.is_unit_iff, coe_eq_singleton]

end division_monoid

/-- `finset α` is a commutative division monoid under pointwise operations if `α` is. -/
@[to_additive subtraction_comm_monoid "`finset α` is a commutative subtraction monoid under
pointwise operations if `α` is."]
protected def division_comm_monoid [division_comm_monoid α] : division_comm_monoid (finset α) :=
coe_injective.division_comm_monoid _ coe_one coe_mul coe_inv coe_div coe_pow coe_zpow

localized "attribute [instance] finset.comm_monoid finset.add_comm_monoid finset.division_monoid
finset.subtraction_monoid finset.division_comm_monoid finset.subtraction_comm_monoid" in pointwise

section group
variables [group α] {s t : finset α}

/-! Note that `finset` is not a `group` because `s / s ≠ 1` in general. -/

@[to_additive] lemma is_unit_singleton (a : α) : is_unit ({a} : finset α) :=
(group.is_unit a).finset

@[simp] lemma is_unit_iff_singleton : is_unit s ↔ ∃ a, s = {a} :=
by simp only [is_unit_iff, group.is_unit, and_true]

end group

end instances

section mul_zero_class
variables [decidable_eq α] [mul_zero_class α] {s t : finset α}

/-! Note that `set` is not a `mul_zero_class` because `0 * ∅ ≠ 0`. -/
/-! Note that `finset` is not a `mul_zero_class` because `0 * ∅ ≠ 0`. -/

lemma mul_zero_subset (s : finset α) : s * 00 := by simp [subset_iff, mem_mul]
lemma zero_mul_subset (s : finset α) : 0 * s ⊆ 0 := by simp [subset_iff, mem_mul]
Expand Down
151 changes: 101 additions & 50 deletions src/data/set/pointwise.lean
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ localized "attribute [instance] set.has_one set.has_zero" in pointwise
@[to_additive] lemma nonempty.subset_one_iff (h : s.nonempty) : s ⊆ 1 ↔ s = 1 :=
h.subset_singleton_iff

/-- The singleton operation as a `one_hom`. -/
@[to_additive "The singleton operation as a `zero_hom`."]
def singleton_one_hom : one_hom α (set α) := ⟨singleton, singleton_one⟩

@[simp, to_additive] lemma coe_singleton_one_hom : (singleton_one_hom : α → set α) = singleton :=
rfl

end one

/-! ### Set negation/inversion -/
Expand Down Expand Up @@ -244,13 +251,13 @@ image2_Inter₂_subset_right _ _ _
def fintype_mul [decidable_eq α] (s t : set α) [fintype s] [fintype t] : fintype (s * t : set α) :=
set.fintype_image2 _ _ _

/-- Under `[has_mul M]`, the `singleton` map from `M` to `set M` as a `mul_hom`, that is, a map
which preserves multiplication. -/
@[to_additive "Under `[has_add A]`, the `singleton` map from `A` to `set A` as an `add_hom`,
that is, a map which preserves addition.", simps]
def singleton_mul_hom : α →ₙ* (set α) :=
{ to_fun := singleton,
map_mul' := λ a b, singleton_mul_singleton.symm }
/-- The singleton operation as a `mul_hom`. -/
@[to_additive "The singleton operation as an `add_hom`."]
def singleton_mul_hom : α →ₙ* set α := ⟨singleton, λ a b, singleton_mul_singleton.symm⟩

@[simp, to_additive] lemma coe_singleton_mul_hom : (singleton_mul_hom : α → set α) = singleton :=
rfl
@[simp, to_additive] lemma singleton_mul_hom_apply (a : α) : singleton_mul_hom a = {a} := rfl

open mul_opposite

Expand Down Expand Up @@ -378,6 +385,14 @@ localized "attribute [instance] set.mul_one_class set.add_zero_class set.semigro
@[to_additive] lemma subset_mul_right {s : set α} (t : set α) (hs : (1 : α) ∈ s) : t ⊆ s * t :=
λ x hx, ⟨1, x, hs, hx, one_mul _⟩

/-- The singleton operation as a `monoid_hom`. -/
@[to_additive "The singleton operation as an `add_monoid_hom`."]
def singleton_monoid_hom : α →* set α := { ..singleton_mul_hom, ..singleton_one_hom }

@[simp, to_additive] lemma coe_singleton_monoid_hom :
(singleton_monoid_hom : α → set α) = singleton := rfl
@[simp, to_additive] lemma singleton_monoid_hom_apply (a : α) : singleton_monoid_hom a = {a} := rfl

end mul_one_class

section monoid
Expand Down Expand Up @@ -421,6 +436,9 @@ begin
simpa only [mem_mul, eq_univ_iff_forall, mem_univ, true_and]
end

@[to_additive] protected lemma _root_.is_unit.set : is_unit a → is_unit ({a} : set α) :=
is_unit.map (singleton_monoid_hom : α →* set α)

end monoid

/-- `set α` is a `comm_monoid` under pointwise operations if `α` is. -/
Expand All @@ -432,11 +450,87 @@ localized "attribute [instance] set.comm_monoid set.add_comm_monoid" in pointwis

open_locale pointwise

/-- Repeated pointwise addition (not the same as pointwise repeated addition!) of a `finset`. -/
protected def has_nsmul [has_zero α] [has_add α] : has_scalar ℕ (set α) := ⟨nsmul_rec⟩

/-- Repeated pointwise multiplication (not the same as pointwise repeated multiplication!) of a
`set`. -/
@[to_additive]
protected def has_npow [has_one α] [has_mul α] : has_pow (set α) ℕ := ⟨λ s n, npow_rec n s⟩

/-- Repeated pointwise addition/subtraction (not the same as pointwise repeated
addition/subtraction!) of a `set`. -/
protected def has_zsmul [has_zero α] [has_add α] [has_neg α] : has_scalar ℤ (set α) := ⟨zsmul_rec⟩

/-- Repeated pointwise multiplication/division (not the same as pointwise repeated
multiplication/division!) of a `set`. -/
@[to_additive] protected def has_zpow [has_one α] [has_mul α] [has_inv α] : has_pow (set α) ℤ :=
⟨λ s n, zpow_rec n s⟩

section division_monoid
variables [division_monoid α] {s t : set α}

@[to_additive] protected lemma mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 :=
begin
refine ⟨λ h, _, _⟩,
{ have hst : (s * t).nonempty := h.symm.subst one_nonempty,
obtain ⟨a, ha⟩ := hst.of_image2_left,
obtain ⟨b, hb⟩ := hst.of_image2_right,
have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) :=
λ a b ha hb, (h.subset $ mem_image2_of_mem ha hb),
refine ⟨a, b, _, _, H ha hb⟩; refine eq_singleton_iff_unique_mem.2 ⟨‹_›, λ x hx, _⟩,
{ exact (eq_inv_of_mul_eq_one_left $ H hx hb).trans (inv_eq_of_mul_eq_one_left $ H ha hb) },
{ exact (eq_inv_of_mul_eq_one_right $ H ha hx).trans (inv_eq_of_mul_eq_one_right $ H ha hb) } },
{ rintro ⟨b, c, rfl, rfl, h⟩,
rw [singleton_mul_singleton, h, singleton_one] }
end

/-- `set α` is a division monoid under pointwise operations if `α` is. -/
@[to_additive subtraction_monoid "`set α` is a subtraction monoid under pointwise operations if `α`
is."]
protected def division_monoid : division_monoid (set α) :=
{ mul_inv_rev := λ s t, by { simp_rw ←image_inv, exact image_image2_antidistrib mul_inv_rev },
inv_eq_of_mul := λ s t h, begin
obtain ⟨a, b, rfl, rfl, hab⟩ := set.mul_eq_one_iff.1 h,
rw [inv_singleton, inv_eq_of_mul_eq_one_right hab],
end,
div_eq_mul_inv := λ s t,
by { rw [←image_id (s / t), ←image_inv], exact image_image2_distrib_right div_eq_mul_inv },
..set.monoid, ..set.has_involutive_inv, ..set.has_div }

@[simp, to_additive] lemma is_unit_iff : is_unit s ↔ ∃ a, s = {a} ∧ is_unit a :=
begin
split,
{ rintro ⟨u, rfl⟩,
obtain ⟨a, b, ha, hb, h⟩ := set.mul_eq_one_iff.1 u.mul_inv,
refine ⟨a, ha, ⟨a, b, h, singleton_injective _⟩, rfl⟩,
rw [←singleton_mul_singleton, ←ha, ←hb],
exact u.inv_mul },
{ rintro ⟨a, rfl, ha⟩,
exact ha.set }
end

end division_monoid

/-- `set α` is a commutative division monoid under pointwise operations if `α` is. -/
@[to_additive subtraction_comm_monoid "`set α` is a commutative subtraction monoid under pointwise
operations if `α` is."]
protected def division_comm_monoid [division_comm_monoid α] : division_comm_monoid (set α) :=
{ ..set.division_monoid, ..set.comm_semigroup }

localized "attribute [instance] set.division_monoid set.subtraction_monoid set.division_comm_monoid
set.subtraction_comm_monoid" in pointwise

section group
variables [group α] {s t : set α} {a b : α}

/-! Note that `set` is not a `group` because `s / s ≠ 1` in general. -/

@[to_additive] lemma is_unit_singleton (a : α) : is_unit ({a} : set α) := (group.is_unit a).set

@[simp, to_additive] lemma is_unit_iff_singleton : is_unit s ↔ ∃ a, s = {a} :=
by simp only [is_unit_iff, group.is_unit, and_true]

@[simp, to_additive] lemma image_mul_left : ((*) a) '' t = ((*) a⁻¹) ⁻¹' t :=
by { rw image_eq_preimage_of_inverse; intro c; simp }

Expand Down Expand Up @@ -551,49 +645,6 @@ end

end big_operators

open_locale pointwise

/-- Repeated pointwise addition (not the same as pointwise repeated addition!) of a `finset`. -/
protected def has_nsmul [has_zero α] [has_add α] : has_scalar ℕ (set α) := ⟨nsmul_rec⟩

/-- Repeated pointwise multiplication (not the same as pointwise repeated multiplication!) of a
`set`. -/
@[to_additive]
protected def has_npow [has_one α] [has_mul α] : has_pow (set α) ℕ := ⟨λ s n, npow_rec n s⟩

/-- Repeated pointwise addition/subtraction (not the same as pointwise repeated
addition/subtraction!) of a `set`. -/
protected def has_zsmul [has_zero α] [has_add α] [has_neg α] : has_scalar ℤ (set α) := ⟨zsmul_rec⟩

/-- Repeated pointwise multiplication/division (not the same as pointwise repeated
multiplication/division!) of a `set`. -/
@[to_additive] protected def has_zpow [has_one α] [has_mul α] [has_inv α] : has_pow (set α) ℤ :=
⟨λ s n, zpow_rec n s⟩

-- TODO: Generalize the duplicated lemmas and instances below to `division_monoid`

@[to_additive] protected lemma mul_inv_rev [group α] (s t : set α) : (s * t)⁻¹ = t⁻¹ * s⁻¹ :=
by { simp_rw ←image_inv, exact image_image2_antidistrib mul_inv_rev }

protected lemma mul_inv_rev₀ [group_with_zero α] (s t : set α) : (s * t)⁻¹ = t⁻¹ * s⁻¹ :=
by { simp_rw ←image_inv, exact image_image2_antidistrib mul_inv_rev }

/-- `s / t = s * t⁻¹` for all `s t : set α` if `a / b = a * b⁻¹` for all `a b : α`. -/
@[to_additive "`s - t = s + -t` for all `s t : set α` if `a - b = a + -b` for all `a b : α`."]
protected def div_inv_monoid [group α] : div_inv_monoid (set α) :=
{ div_eq_mul_inv := λ s t,
by { rw [←image_id (s / t), ←image_inv], exact image_image2_distrib_right div_eq_mul_inv },
..set.monoid, ..set.has_inv, ..set.has_div }

/-- `s / t = s * t⁻¹` for all `s t : set α` if `a / b = a * b⁻¹` for all `a b : α`. -/
protected def div_inv_monoid' [group_with_zero α] : div_inv_monoid (set α) :=
{ div_eq_mul_inv := λ s t,
by { rw [←image_id (s / t), ←image_inv], exact image_image2_distrib_right div_eq_mul_inv },
..set.monoid, ..set.has_inv, ..set.has_div }

localized "attribute [instance] set.has_nsmul set.has_npow set.has_zsmul set.has_zpow
set.div_inv_monoid set.div_inv_monoid' set.sub_neg_add_monoid" in pointwise

/-! ### Translation/scaling of sets -/

section smul
Expand Down
Loading

0 comments on commit c57cfc6

Please sign in to comment.