Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat: measurability of uniqueElim and piFinsetUnion #8249

Closed
wants to merge 9 commits into from
18 changes: 9 additions & 9 deletions Mathlib/Algebra/Group/Equiv/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -708,15 +708,15 @@ index. -/
@[to_additive (attr := simps!)
"A family indexed by a nonempty subsingleton type is
fpvandoorn marked this conversation as resolved.
Show resolved Hide resolved
equivalent to the element at the single index."]
def piSubsingleton {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Subsingleton ι]
(i : ι) : (∀ j, M j) ≃* M i :=
{ Equiv.piSubsingleton M i with map_mul' := fun _ _ => Pi.mul_apply _ _ _ }
#align mul_equiv.Pi_subsingleton MulEquiv.piSubsingleton
#align add_equiv.Pi_subsingleton AddEquiv.piSubsingleton
#align mul_equiv.Pi_subsingleton_apply MulEquiv.piSubsingleton_apply
#align add_equiv.Pi_subsingleton_apply AddEquiv.piSubsingleton_apply
#align mul_equiv.Pi_subsingleton_symm_apply MulEquiv.piSubsingleton_symm_apply
#align add_equiv.Pi_subsingleton_symm_apply AddEquiv.piSubsingleton_symm_apply
def piUnique {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Unique ι] :
(∀ j, M j) ≃* M default :=
eric-wieser marked this conversation as resolved.
Show resolved Hide resolved
{ Equiv.piUnique M with map_mul' := fun _ _ => Pi.mul_apply _ _ _ }
#align mul_equiv.Pi_subsingleton MulEquiv.piUnique
#align add_equiv.Pi_subsingleton AddEquiv.piUnique
#align mul_equiv.Pi_subsingleton_apply MulEquiv.piUnique_apply
#align add_equiv.Pi_subsingleton_apply AddEquiv.piUnique_apply
#align mul_equiv.Pi_subsingleton_symm_apply MulEquiv.piUnique_symm_apply
#align add_equiv.Pi_subsingleton_symm_apply AddEquiv.piUnique_symm_apply

/-!
# Groups
Expand Down
19 changes: 9 additions & 10 deletions Mathlib/GroupTheory/Sylow.lean
Original file line number Diff line number Diff line change
Expand Up @@ -710,23 +710,23 @@ theorem coe_ofCard [Fintype G] {p : ℕ} [Fact p.Prime] (H : Subgroup G) [Fintyp
rfl
#align sylow.coe_of_card Sylow.coe_ofCard

theorem subsingleton_of_normal {p : ℕ} [Fact p.Prime] [Finite (Sylow p G)] (P : Sylow p G)
(h : (P : Subgroup G).Normal) : Subsingleton (Sylow p G) := by
apply Subsingleton.intro
intro Q R
/-- If `G` has a normal Sylow `p`-subgroup, then it is the only Sylow `p`-subgroup. -/
noncomputable def unique_of_normal {p : ℕ} [Fact p.Prime] [Finite (Sylow p G)] (P : Sylow p G)
(h : (P : Subgroup G).Normal) : Unique (Sylow p G) := by
refine { uniq := fun Q ↦ ?_ }
obtain ⟨x, h1⟩ := exists_smul_eq G P Q
obtain ⟨x, h2⟩ := exists_smul_eq G P R
obtain ⟨x, h2⟩ := exists_smul_eq G P default
rw [Sylow.smul_eq_of_normal] at h1 h2
rw [← h1, ← h2]
#align sylow.subsingleton_of_normal Sylow.subsingleton_of_normal
#align sylow.subsingleton_of_normal Sylow.unique_of_normal

section Pointwise

open Pointwise

theorem characteristic_of_normal {p : ℕ} [Fact p.Prime] [Finite (Sylow p G)] (P : Sylow p G)
(h : (P : Subgroup G).Normal) : (P : Subgroup G).Characteristic := by
haveI := Sylow.subsingleton_of_normal P h
haveI := Sylow.unique_of_normal P h
rw [characteristic_iff_map_eq]
intro Φ
show (Φ • P).toSubgroup = P.toSubgroup
Expand Down Expand Up @@ -796,9 +796,8 @@ noncomputable def directProductOfNormal [Fintype G]
apply @MulEquiv.piCongrRight ps (fun p => ∀ P : Sylow p G, P) (fun p => P p) _ _
rintro ⟨p, hp⟩
haveI hp' := Fact.mk (Nat.prime_of_mem_factorization hp)
haveI := subsingleton_of_normal _ (hn (P p))
change (∀ P : Sylow p G, P) ≃* P p
exact MulEquiv.piSubsingleton _ _
letI := unique_of_normal _ (hn (P p))
apply MulEquiv.piUnique
show (∀ p : ps, P p) ≃* G
apply MulEquiv.ofBijective (Subgroup.noncommPiCoprod hcomm)
apply (bijective_iff_injective_and_card _).mpr
Expand Down
19 changes: 8 additions & 11 deletions Mathlib/Logic/Equiv/Defs.lean
Original file line number Diff line number Diff line change
Expand Up @@ -614,20 +614,17 @@ def arrowPUnitEquivPUnit (α : Sort*) : (α → PUnit.{v}) ≃ PUnit.{w} :=
⟨fun _ => .unit, fun _ _ => .unit, fun _ => rfl, fun _ => rfl⟩
#align equiv.arrow_punit_equiv_punit Equiv.arrowPUnitEquivPUnit

/-- If `α` is `Subsingleton` and `a : α`, then the type of dependent functions `Π (i : α), β i`
is equivalent to `β a`. -/
@[simps] def piSubsingleton (β : α → Sort*) [Subsingleton α] (a : α) : (∀ a', β a') ≃ β a where
toFun := eval a
invFun x b := cast (congr_arg β <| Subsingleton.elim a b) x
left_inv _ := funext fun b => by rw [Subsingleton.elim b a]; rfl
right_inv _ := rfl
#align equiv.Pi_subsingleton_apply Equiv.piSubsingleton_apply
#align equiv.Pi_subsingleton_symm_apply Equiv.piSubsingleton_symm_apply
#align equiv.Pi_subsingleton Equiv.piSubsingleton
/-- The equivalence `(∀ i, β i) ≃ β ⋆` when the domain of `β` only contains `⋆` -/
@[simps (config := .asFn)]
def piUnique [Unique α] (β : α → Sort*) : (∀ i, β i) ≃ β default where
toFun f := f default
invFun := uniqueElim
left_inv f := by ext i; cases Unique.eq_default i; rfl
right_inv x := rfl
eric-wieser marked this conversation as resolved.
Show resolved Hide resolved

/-- If `α` has a unique term, then the type of function `α → β` is equivalent to `β`. -/
@[simps! (config := { fullyApplied := false }) apply]
def funUnique (α β) [Unique.{u} α] : (α → β) ≃ β := piSubsingleton _ default
def funUnique (α β) [Unique.{u} α] : (α → β) ≃ β := piUnique _
#align equiv.fun_unique Equiv.funUnique
#align equiv.fun_unique_apply Equiv.funUnique_apply

Expand Down
6 changes: 5 additions & 1 deletion Mathlib/Logic/Unique.lean
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ end Function

section Pi

variable {ι : Type*} {α : ι → Type*}
variable {ι : Sort*} {α : ι → Sort*}
/-- Given one value over a unique, we get a dependent function. -/
def uniqueElim [Unique ι] (x : α (default : ι)) (i : ι) : α i := by
rw [Unique.eq_default i]
Expand All @@ -264,6 +264,10 @@ def uniqueElim [Unique ι] (x : α (default : ι)) (i : ι) : α i := by
theorem uniqueElim_default {_ : Unique ι} (x : α (default : ι)) : uniqueElim x (default : ι) = x :=
rfl

@[simp]
theorem uniqueElim_const {_ : Unique ι} (x : β) (i : ι) : uniqueElim (α := fun _ ↦ β) x i = x :=
rfl

end Pi

-- TODO: Mario turned this off as a simp lemma in Std, wanting to profile it.
Expand Down
49 changes: 37 additions & 12 deletions Mathlib/MeasureTheory/Constructions/Pi.lean
Original file line number Diff line number Diff line change
Expand Up @@ -764,8 +764,8 @@ theorem volume_measurePreserving_piCongrLeft (α : ι → Type*) (f : ι' ≃ ι
MeasurePreserving (MeasurableEquiv.piCongrLeft α f) volume volume :=
measurePreserving_piCongrLeft (fun _ ↦ volume) f

theorem measurePreserving_sumPiEquivProdPi_symm {π : ι ⊕ ι' → Type*} [∀ i, MeasurableSpace (π i)]
(μ : ∀ i, Measure (π i)) [∀ i, SigmaFinite (μ i)] :
theorem measurePreserving_sumPiEquivProdPi_symm {π : ι ⊕ ι' → Type*}
{m : ∀ i, MeasurableSpace (π i)} (μ : ∀ i, Measure (π i)) [∀ i, SigmaFinite (μ i)] :
MeasurePreserving (MeasurableEquiv.sumPiEquivProdPi π).symm
((Measure.pi fun i => μ (.inl i)).prod (Measure.pi fun i => μ (.inr i))) (Measure.pi μ) where
measurable := (MeasurableEquiv.sumPiEquivProdPi π).symm.measurable
Expand All @@ -780,7 +780,7 @@ theorem volume_measurePreserving_sumPiEquivProdPi_symm (π : ι ⊕ ι' → Type
MeasurePreserving (MeasurableEquiv.sumPiEquivProdPi π).symm volume volume :=
measurePreserving_sumPiEquivProdPi_symm (fun _ ↦ volume)

theorem measurePreserving_sumPiEquivProdPi {π : ι ⊕ ι' → Type*} [∀ i, MeasurableSpace (π i)]
theorem measurePreserving_sumPiEquivProdPi {π : ι ⊕ ι' → Type*} {_m : ∀ i, MeasurableSpace (π i)}
fpvandoorn marked this conversation as resolved.
Show resolved Hide resolved
(μ : ∀ i, Measure (π i)) [∀ i, SigmaFinite (μ i)] :
MeasurePreserving (MeasurableEquiv.sumPiEquivProdPi π)
(Measure.pi μ) ((Measure.pi fun i => μ (.inl i)).prod (Measure.pi fun i => μ (.inr i))) :=
Expand Down Expand Up @@ -810,16 +810,27 @@ theorem volume_preserving_piFinSuccAboveEquiv {n : ℕ} (α : Fin (n + 1) → Ty
measurePreserving_piFinSuccAboveEquiv (fun _ => volume) i
#align measure_theory.volume_preserving_pi_fin_succ_above_equiv MeasureTheory.volume_preserving_piFinSuccAboveEquiv

theorem measurePreserving_funUnique {β : Type u} {m : MeasurableSpace β} (μ : Measure β)
theorem measurePreserving_piUnique {π : ι → Type*} [Unique ι] {m : ∀ i, MeasurableSpace (π i)}
(μ : ∀ i, Measure (π i)) :
MeasurePreserving (MeasurableEquiv.piUnique π) (Measure.pi μ) (μ default) where
measurable := (MeasurableEquiv.piUnique π).measurable
map_eq := by
set e := MeasurableEquiv.piUnique π
have : (piPremeasure fun i => (μ i).toOuterMeasure) = Measure.map e.symm (μ default) := by
ext1 s
rw [piPremeasure, Fintype.prod_unique, e.symm.map_apply]
congr 1; exact e.toEquiv.image_eq_preimage s
simp_rw [Measure.pi, OuterMeasure.pi, this, boundedBy_eq_self, toOuterMeasure_toMeasure,
MeasurableEquiv.map_map_symm]

theorem volume_preserving_piUnique (π : ι → Type*) [Unique ι] [∀ i, MeasureSpace (π i)] :
MeasurePreserving (MeasurableEquiv.piUnique π) volume volume :=
measurePreserving_piUnique _

theorem measurePreserving_funUnique {β : Type u} {_m : MeasurableSpace β} (μ : Measure β)
(α : Type v) [Unique α] :
MeasurePreserving (MeasurableEquiv.funUnique α β) (Measure.pi fun _ : α => μ) μ := by
set e := MeasurableEquiv.funUnique α β
have : (piPremeasure fun _ : α => μ.toOuterMeasure) = Measure.map e.symm μ := by
ext1 s
rw [piPremeasure, Fintype.prod_unique, e.symm.map_apply]
congr 1; exact e.toEquiv.image_eq_preimage s
simp only [Measure.pi, OuterMeasure.pi, this, boundedBy_measure, toOuterMeasure_toMeasure]
exact (e.symm.measurable.measurePreserving _).symm e.symm
MeasurePreserving (MeasurableEquiv.funUnique α β) (Measure.pi fun _ : α => μ) μ :=
measurePreserving_piUnique _
#align measure_theory.measure_preserving_fun_unique MeasureTheory.measurePreserving_funUnique

theorem volume_preserving_funUnique (α : Type u) (β : Type v) [Unique α] [MeasureSpace β] :
Expand Down Expand Up @@ -877,6 +888,20 @@ theorem volume_preserving_pi_empty {ι : Type u} (α : ι → Type v) [IsEmpty
measurePreserving_pi_empty fun _ => volume
#align measure_theory.volume_preserving_pi_empty MeasureTheory.volume_preserving_pi_empty

theorem measurePreserving_piFinsetUnion [DecidableEq ι] {s t : Finset ι} (h : Disjoint s t)
(μ : ∀ i, Measure (α i)) [∀ i, SigmaFinite (μ i)] :
MeasurePreserving (MeasurableEquiv.piFinsetUnion α h)
((Measure.pi fun i : s ↦ μ i).prod (Measure.pi fun i : t ↦ μ i))
(Measure.pi fun i : ↥(s ∪ t) ↦ μ i) :=
let e := Equiv.Finset.union s t h
measurePreserving_piCongrLeft (fun i : ↥(s ∪ t) ↦ μ i) e |>.comp <|
measurePreserving_sumPiEquivProdPi_symm fun b ↦ μ (e b)

theorem volume_preserving_piFinsetUnion (α : ι → Type*) [DecidableEq ι] {s t : Finset ι}
(h : Disjoint s t) [∀ i, MeasureSpace (α i)] [∀ i, SigmaFinite (volume : Measure (α i))] :
MeasurePreserving (MeasurableEquiv.piFinsetUnion α h) volume volume :=
measurePreserving_piFinsetUnion h (fun _ ↦ volume)

end MeasurePreserving

end MeasureTheory
33 changes: 29 additions & 4 deletions Mathlib/MeasureTheory/MeasurableSpace/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl, Mario Carneiro
-/
import Mathlib.Algebra.IndicatorFunction
import Mathlib.Data.Finset.Update
import Mathlib.Data.Prod.TProd
import Mathlib.GroupTheory.Coset
import Mathlib.Logic.Equiv.Fin
Expand Down Expand Up @@ -921,6 +922,16 @@ theorem measurable_update' {a : δ} [DecidableEq δ] :
exact measurable_snd
· exact measurable_pi_iff.1 measurable_fst _

theorem measurable_uniqueElim [Unique δ] [∀ i, MeasurableSpace (π i)] :
Measurable (uniqueElim : π (default : δ) → ∀ i, π i) := by
simp_rw [measurable_pi_iff, Unique.forall_iff, uniqueElim_default]; exact measurable_id

theorem measurable_updateFinset [DecidableEq δ] {s : Finset δ} {x : ∀ i, π i} :
Measurable (updateFinset x s) := by
simp_rw [updateFinset, measurable_pi_iff]
intro i
by_cases h : i ∈ s <;> simp [h, measurable_pi_apply]

/-- The function `update f a : π a → Π a, π a` is always measurable.
This doesn't require `f` to be measurable.
This should not be confused with the statement that `update f a x` is measurable. -/
Expand Down Expand Up @@ -1630,12 +1641,18 @@ def piMeasurableEquivTProd [DecidableEq δ'] {l : List δ'} (hnd : l.Nodup) (h :
measurable_invFun := measurable_tProd_elim' h
#align measurable_equiv.pi_measurable_equiv_tprod MeasurableEquiv.piMeasurableEquivTProd

variable (π) in
/-- The measurable equivalence `(∀ i, π i) ≃ᵐ π ⋆` when the domain of `π` only contains `⋆` -/
@[simps! (config := .asFn)]
eric-wieser marked this conversation as resolved.
Show resolved Hide resolved
def piUnique [Unique δ'] : (∀ i, π i) ≃ᵐ π default where
toEquiv := Equiv.piUnique π
measurable_toFun := measurable_pi_apply _
measurable_invFun := measurable_uniqueElim

/-- If `α` has a unique term, then the type of function `α → β` is measurably equivalent to `β`. -/
@[simps! (config := { fullyApplied := false })]
def funUnique (α β : Type*) [Unique α] [MeasurableSpace β] : (α → β) ≃ᵐ β where
toEquiv := Equiv.funUnique α β
fpvandoorn marked this conversation as resolved.
Show resolved Hide resolved
measurable_toFun := measurable_pi_apply _
measurable_invFun := measurable_pi_iff.2 fun _ => measurable_id
def funUnique (α β : Type*) [Unique α] [MeasurableSpace β] : (α → β) ≃ᵐ β :=
MeasurableEquiv.piUnique _
#align measurable_equiv.fun_unique MeasurableEquiv.funUnique

/-- The space `Π i : Fin 2, α i` is measurably equivalent to `α 0 × α 1`. -/
Expand Down Expand Up @@ -1695,6 +1712,14 @@ theorem coe_sumPiEquivProdPi (α : δ ⊕ δ' → Type*) [∀ i, MeasurableSpace
theorem coe_sumPiEquivProdPi_symm (α : δ ⊕ δ' → Type*) [∀ i, MeasurableSpace (α i)] :
⇑(MeasurableEquiv.sumPiEquivProdPi α).symm = (Equiv.sumPiEquivProdPi α).symm := by rfl

/-- The measurable equivalence `(∀ i : s, π i) × (∀ i : t, π i) ≃ᵐ (∀ i : s ∪ t, π i)`
for disjoint finsets `s` and `t`. `Equiv.piFinsetUnion` as a measurable equivalence. -/
def piFinsetUnion [DecidableEq δ'] {s t : Finset δ'} (h : Disjoint s t) :
((∀ i : s, π i) × ∀ i : t, π i) ≃ᵐ ∀ i : (s ∪ t : Finset δ'), π i :=
let e := Finset.union s t h
fpvandoorn marked this conversation as resolved.
Show resolved Hide resolved
MeasurableEquiv.sumPiEquivProdPi (fun b ↦ π (e b)) |>.symm.trans <|
.piCongrLeft (fun i : ↥(s ∪ t) ↦ π i) e

/-- If `s` is a measurable set in a measurable space, that space is equivalent
to the sum of `s` and `sᶜ`.-/
def sumCompl {s : Set α} [DecidablePred (· ∈ s)] (hs : MeasurableSet s) :
Expand Down