Skip to content

feat(GroupTheory/PCore): define the p-core of a subgroup#39771

Open
kim-em wants to merge 22 commits into
masterfrom
kim-em/p-core
Open

feat(GroupTheory/PCore): define the p-core of a subgroup#39771
kim-em wants to merge 22 commits into
masterfrom
kim-em/p-core

Conversation

@kim-em

@kim-em kim-em commented May 24, 2026

Copy link
Copy Markdown
Contributor

This PR adds Subgroup.pCore p H, the largest normal p-subgroup of a subgroup H : Subgroup G (classically O_p(H)), defined as the supremum of all normal p-subgroups. Even without finiteness or primality hypotheses, this is itself a normal p-group (the family of normal p-subgroups is directed under , so every element of the supremum lies in some specific summand). For the classical O_p(G), take pCore p (⊤ : Subgroup G).

API covers the universal-property characterisations (le_pCore, normal_le_pCore, mem_pCore_iff, pCore_eq_bot_iff, pCore_eq_top_iff, pCore_zero, pCore_one), the Sylow alignment pCore p H = ⨅ P : Sylow p H, (P : Subgroup H), and behaviour under group homomorphisms via MonoidHom.subgroupMap and MonoidHom.subgroupComap (map_pCore_le_pCore, comap_pCore_eq_pCore and friends, MulEquiv.map_pCore).

Also adds Subgroup.normal_iSup_normal in Mathlib/Algebra/Group/Subgroup/Pointwise.lean (the supremum of a family of normal subgroups is normal) as the sibling of the existing normal_iInf_normal, and ker_subgroupComap in Mathlib/Algebra/Group/Subgroup/Ker.lean alongside the existing ker_subgroupMap. Both marked @[to_additive].

Used downstream in leanprover/lean-eval#311 to state the Baer-Suzuki theorem as a lean-eval problem.

🤖 Prepared with Claude Code

@github-actions github-actions Bot added the t-group-theory Group theory label May 24, 2026
@github-actions

github-actions Bot commented May 24, 2026

Copy link
Copy Markdown

PR summary b1fc61ea28

Import changes for modified files

No significant changes to the import graph

Import changes for all files
Files Import difference
Mathlib.GroupTheory.PCore (new file) 1176

Declarations diff

+ _root_.MulEquiv.map_pCore
+ comap_pCore_eq_pCore
+ comap_pCore_le_pCore
+ directed_pCore
+ instance : Nonempty {N : Subgroup H // N.Normal ∧ IsPGroup p N}
+ isPGroup_iInf_sylow
+ isPGroup_pCore
+ isPGroup_pCore_subgroupOf
+ ker_subgroupComap
+ le_pCore
+ le_pCore_of_le
+ le_pCore_subgroupOf
+ le_pCore_subgroupOf_iff
+ map_pCore_eq_pCore
+ map_pCore_eq_pCore_of_ker_isPGroup
+ map_pCore_le_pCore
+ map_subtype_le_pCore_iff
+ mem_pCore_iff
+ mem_pCore_subgroupOf_iff
+ normal_iInf_sylow
+ pCore
+ pCore_bot
+ pCore_eq_bot_iff
+ pCore_eq_iInf_sylow
+ pCore_eq_iSup
+ pCore_eq_self
+ pCore_eq_self_iff
+ pCore_le
+ pCore_le_comap_pCore
+ pCore_le_sylow
+ pCore_one
+ pCore_subgroupOf
+ pCore_subgroupOf_characteristic
+ pCore_subgroupOf_eq_iInf_sylow
+ pCore_subgroupOf_eq_sylow_iff_normal
+ pCore_subgroupOf_le_sylow
+ pCore_subgroupOf_normal
+ pCore_zero
+ subgroupOf_comap_subgroupComap
+ subgroupOf_map_subgroupMap
+ sylow_eq_pCore_subgroupOf_of_normal
+ top_map_subtype

You can run this locally as follows
## from your `mathlib4` directory:
git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci

## summary with just the declaration names:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh <optional_commit>

## more verbose report:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh long <optional_commit>

The doc-module for scripts/pr_summary/declarations_diff.sh in the mathlib-ci repository contains some details about this script.


No changes to strong technical debt.
No changes to weak technical debt.

Current commit b1fc61ea28
Reference commit 6da0491965

This script lives in the mathlib-ci repository. To run it locally, from your mathlib4 directory:

git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci
../mathlib-ci/scripts/reporting/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

Comment thread Mathlib/GroupTheory/PCore.lean Outdated
kim-em added 8 commits May 25, 2026 09:56
This PR adds `Subgroup.pCore p G`, the largest normal `p`-subgroup of
`G`, classically denoted `O_p(G)`. Defined as the supremum of all
normal `p`-subgroups; proved to be itself a normal `p`-group, without
any finiteness hypothesis on `G`.

The proof that `pCore p G` is a `p`-group uses the fact that the
family of normal `p`-subgroups is directed under `≤` (the join of
two normal `p`-subgroups is again a normal `p`-subgroup, by the
existing `Subgroup.sup_normal` and `IsPGroup.to_sup_of_normal_left`),
so `mem_iSup_of_directed` gives: every element of the supremum lies
in one of the summands, and therefore has `p`-power order.

Used downstream in `leanprover/lean-eval` to state the Baer-Suzuki
theorem (leanprover/lean-eval#311).

Follow-up work (filed in module TODO):
* `pCore p G = ⨅ P : Sylow p G, (P : Subgroup G)` for finite `G` and
  prime `p`.
* Behaviour of `pCore` under group homomorphisms.
* Interaction with `IsSolvable`.
For a finite group `G` and a prime `p`, the `p`-core equals the
intersection of all Sylow `p`-subgroups:
  `pCore p G = ⨅ P : Sylow p G, (P : Subgroup G)`

New lemmas:
* `Subgroup.pCore_le_sylow` — `pCore p G` is contained in every Sylow
  `p`-subgroup (uses that `pCore` is a normal `p`-subgroup so equals
  its conjugate, plus Sylow conjugacy).
* `Subgroup.normal_iInf_sylow` — the intersection of all Sylow
  `p`-subgroups is normal (conjugation permutes Sylows).
* `Subgroup.isPGroup_iInf_sylow` — the intersection is a `p`-group
  (contained in any one Sylow).
* `Subgroup.pCore_eq_iInf_sylow` — the main result.

Changes the import from `PGroup` to `Sylow` to access Sylow theory.

Proof contributed via Codex pair-programming.
Cleanup pass:
* Extract `Nonempty` subtype instance to top-level (was duplicated as
  `haveI` in `isPGroup_pCore` and `mem_pCore_iff`).
* Replace `@`-instance threading in `directed_normal_isPGroup` with
  `haveI`-based instance synthesis.
* Collapse the `1` case in `pCore_normal` to `by simp`.
* Simplify the final `Subtype.ext` in `isPGroup_pCore` to `ext + simpa`.
* Unify the two branches in `normal_iInf_sylow` to a single direction
  (one-sided argument suffices via `mem_pointwise_smul_iff_inv_smul_mem`).
* Drop unnecessary `classical` calls and `MulAut.conj_apply` hint.
* Replace `(isPGroup_pCore (G := G) (p := p))` with a clean
  `have hpg : IsPGroup p (pCore p G) := isPGroup_pCore` step.
* Switch `normal_iInf_sylow` from `refine ⟨...⟩` to `where conj_mem`
  to match the style used by `pCore_normal`.
Codex review pass:
* Add `Subgroup.normal_iSup_normal` to `Pointwise.lean` (sibling of
  the existing `normal_iInf_normal` in `Basic.lean`; needed
  `iSup_induction` which lives in `Pointwise.lean`). Generalizes
  the supremum-of-normals-is-normal proof previously inlined in
  `pCore_normal`.
* Simplify `pCore_normal` to a one-liner using the new general lemma.
* Add `pCore_eq_bot_iff` (the `p`-core is trivial iff `G` has no
  non-trivial normal `p`-subgroup).
* Add `pCore_eq_top` (if `G` is itself a `p`-group, the `p`-core is
  the whole group).
* Rename module-doc "Notation" section to "Terminology" (the section
  describes the textbook name `O_p(G)`, but introduces no notation).

Kept `directed_normal_isPGroup` public (per user preference): it is
genuinely useful API for anyone working with `pCore`, not just a
private implementation lemma.

The `to_additive` translation of `normal_iSup_normal` is left for a
follow-up; the multiplicative proof routes through `MulAut.conj`,
which translates but its `map_mul` step needs a small workaround
in the additive setting.
Mirrors the API for `Subgroup.normalCore`:

* `normal_le_pCore` — for `N` normal in `G`, `N ≤ pCore p G ↔ IsPGroup p N`.
  Previously only the (←) direction was available (`le_pCore`).
* `pCore_eq_top_iff` — `pCore p G = ⊤ ↔ IsPGroup p (⊤ : Subgroup G)`.
  Previously only the (←) direction (`pCore_eq_top`); the (→) direction
  follows from `isPGroup_pCore.to_le`.
For a homomorphism `f : G →* H`:

* `map_pCore_le_pCore (hf : Surjective f)`: `(pCore p G).map f ≤ pCore p H`
  — the image of the `p`-core under a surjective hom is a normal
  `p`-subgroup of `H`, hence in its `p`-core.
* `pCore_le_comap_pCore (hf : Surjective f)`: the same fact restated
  via the map-comap adjunction.
* `comap_pCore_le_pCore (hker : IsPGroup p f.ker)`: when the kernel is
  a `p`-group, the preimage of `pCore p H` is a normal `p`-subgroup
  of `G`, hence in `pCore p G`.
* `comap_pCore_eq_pCore (hf : Surjective f) (hker : IsPGroup p f.ker)`:
  both conditions together give equality.
* `MulEquiv.map_pCore`: a group isomorphism preserves the `p`-core
  (immediate from the equality above with `e.symm`).

These cover the classical hom-behaviour story for `O_p(G)`. Removes
the "Behaviour of `pCore` under group homomorphisms" item from the
module TODO.
…pCore

Shorter, more idiomatic name tied to the pCore definition.
The original proof used `MulAut.conj g` and `map_mul`. The
`to_additive` translation of `MulAut.conj` is `AddAut.conj`, whose
codomain is `Additive (AddAut G)` (wrapping the inherently
multiplicative automorphism group), so the proof did not translate.

Replace with the same `simp only [mul_assoc, inv_mul_cancel_left]`
manipulation that the existing `sup_normal` (immediately above) uses
for the analogous step. Both `mul_assoc` and `inv_mul_cancel_left`
have `@[to_additive]`, so the proof now translates cleanly.

The lemma `AddSubgroup.normal_iSup_normal` is now also exported and
mirrors the existing `AddSubgroup.normal_iInf_normal` in `Basic.lean`.
kim-em added 5 commits May 25, 2026 10:04
…lignment

The Sylow alignment `pCore p G = ⨅ P : Sylow p G, (P : Subgroup G)` is
unconditional, not specific to finite groups or prime `p`:

* `pCore_le_sylow` (no longer needs `[Fact p.Prime] [Finite G]`): for any
  Sylow `P`, the join `P ⊔ pCore p G` is a `p`-subgroup (by
  `IsPGroup.to_sup_of_normal_right`), so maximality of `P` forces
  `P ⊔ pCore = P`, hence `pCore ≤ P`.
* `normal_iInf_sylow` (no hypotheses): conjugation permutes the Sylows,
  so the intersection is invariant.
* `isPGroup_iInf_sylow` (no hypotheses): the intersection lies in any
  one Sylow, hence is a `p`-group. `Sylow.nonempty` is unconditional.
* `pCore_eq_iInf_sylow` (no hypotheses): le_antisymm of the above.

The new proof of `pCore_le_sylow` is also shorter — it avoids the
Sylow-II conjugacy machinery (`MulAction.exists_smul_eq`) entirely.
Edge cases:
* `pCore_zero`: `pCore 0 G = ⊤`. Every group is a `0`-group via
  `g ^ 0 ^ 1 = g ^ 0 = 1`.
* `pCore_one`: `pCore 1 G = ⊥`. A `1`-group must be trivial, since
  `g ^ 1 ^ k = g ^ 1 = g`.

Both marked `@[simp]`.
…opyright

* Replace the `change` + `have` + `rw` block in the mul case of
  `Subgroup.normal_iSup_normal` with a single `simpa only` step
  using `mul_mem hy hz`: `simp only` handles beta-reduction plus
  the `[mul_assoc, inv_mul_cancel_left]` normalisation of the
  conjugation identity in one go.

* Update copyright holder in `PCore.lean` to Lean FRO, LLC.
* Cut "Main results" down to the four headline statements
  (normality + isPGroup, universal property, Sylow alignment, hom
  behaviour). The individual API lemmas are documented at their
  declarations.
* Remove "Terminology" section — the docstring of `pCore` already
  notes the `O_p(G)` notation.
The `Nonempty {N : Subgroup G // N.Normal ∧ IsPGroup p N}` instance is
an implementation detail used only in this file (by `isPGroup_pCore`
and `mem_pCore_iff`). External users shouldn't need it.
@kim-em
kim-em marked this pull request as ready for review May 25, 2026 10:23
Comment thread Mathlib/GroupTheory/PCore.lean Outdated
kim-em and others added 2 commits May 25, 2026 11:02
Replace the file-wide `@[expose] public section` with per-declaration
`public` (and `@[expose]` on `pCore` itself), so only the definition's
body is exposed and theorem proofs stay private.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore only

Per-declaration `public` is too noisy. Restore a `public section` for
visibility and keep `@[expose]` only on the `pCore` definition, where
the body needs to be unfoldable downstream.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tb65536

tb65536 commented May 26, 2026

Copy link
Copy Markdown
Contributor

Oh, great! This might be relevant for some stuff @Whysoserioushah has been thinking about.

Comment thread Mathlib/GroupTheory/PCore.lean Outdated
Following the convention used for `Sylow p H`, the `p`-core of a
subgroup `H : Subgroup G` is now a `Subgroup H` rather than a
`Subgroup G`. This matches finite group theory usage, where `O_p` is
applied to subgroups like `N_G(P)` or `C_G(x)` and the result is
compared inside `H`.

Intrinsic API (`pCore_normal`, `isPGroup_pCore`, `le_pCore`,
`mem_pCore_iff`, `pCore_eq_iInf_sylow`) becomes cleaner — no
`subgroupOf` ceremony for normality. The hom API uses
`MonoidHom.subgroupMap` and `MonoidHom.subgroupComap` for natural
restrictions; `map_pCore_le_pCore` drops its surjectivity hypothesis
because `subgroupMap` is intrinsically surjective.

Also adds `ker_subgroupComap` (alongside the existing `ker_subgroupMap`)
in `Mathlib/Algebra/Group/Subgroup/Ker.lean`, used in the proof of
`comap_pCore_le_pCore`.

For the classical `O_p(G)`, take `pCore p (⊤ : Subgroup G)`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kim-em kim-em changed the title feat(GroupTheory/PCore): define the p-core of a group feat(GroupTheory/PCore): define the p-core of a subgroup May 28, 2026
… lemmas

Follow-up to the subgroup redesign, addressing review feedback:

* `pCore_characteristic`: `pCore p H` is characteristic in `H`.
* `pCore_eq_top_iff` now states `↔ IsPGroup p H` (predicate on the type,
  per the `Group → Prop` convention) rather than `IsPGroup p (⊤ : Subgroup H)`.
* `map_pCore_eq_pCore`: the image-equals form, with the minimal
  `IsPGroup p (f.subgroupMap H).ker` hypothesis. `MulEquiv.map_pCore` now
  derives from it.
* `comap_pCore_le_pCore` / `comap_pCore_eq_pCore` use the minimal restricted
  hypotheses (`IsPGroup p (f.subgroupComap H').ker`, surjectivity of the
  restriction) instead of the stronger whole-map versions.
* `sylow_eq_pCore_of_normal`, `pCore_eq_sylow_iff_normal`: a Sylow
  `p`-subgroup of `H` coincides with the `p`-core exactly when it is normal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@SnirBroshi

Copy link
Copy Markdown
Collaborator

Hello! I just found this PR when I went to open my own PR defining p-cores 😅

I'll try to review this soon to see if I find stuff worth keeping from my take on this, and in the meantime I opened it as a draft PR if people are interested to play spot-the-difference until I get to it: #40036
(I'll close it after I suggest stuff here)

@tb65536 tb65536 added the awaiting-author A reviewer has asked the author a question or requested changes. label May 30, 2026
@kim-em

kim-em commented May 31, 2026

Copy link
Copy Markdown
Contributor Author

@tb65536, I see you marked this back as awaiting-author, but I only see a conversation between you and @SnirBroshi, which I think concludes with agreeing with the status quo?

I'm going to remove awaiting-author again, but please point me to anything I've missed.

@kim-em kim-em removed the awaiting-author A reviewer has asked the author a question or requested changes. label May 31, 2026
@SnirBroshi

SnirBroshi commented May 31, 2026

Copy link
Copy Markdown
Collaborator

The status quo is

def pCore (p : ℕ) (H : Subgroup G) : Subgroup H :=
  ⨆ N : {N : Subgroup H // N.Normal ∧ IsPGroup p N}, (N : Subgroup H)

but we've suggested

def pCore (p : ℕ) (H : Subgroup G) : Subgroup G :=
  ⨆ N ≤ H, ⨆ _ : (N.subgroupOf H).Normal, ⨆ _ : IsPGroup p N, N

Specifically the issue is that pCore p changes the ambient group, but should be Subgroup G → Subgroup G.

@SnirBroshi SnirBroshi added the awaiting-author A reviewer has asked the author a question or requested changes. label May 31, 2026
Comment thread Mathlib/GroupTheory/PCore.lean Outdated
Comment thread Mathlib/GroupTheory/PCore.lean Outdated
Comment thread Mathlib/GroupTheory/PCore.lean Outdated
Comment thread Mathlib/Algebra/Group/Subgroup/Pointwise.lean Outdated
# Conflicts:
#	Mathlib/Algebra/Group/Subgroup/Pointwise.lean
@kim-em
kim-em temporarily deployed to cache-upload-forks June 4, 2026 04:20 — with GitHub Actions Inactive
Drop the duplicate normal_iSup_normal (master gained Subgroup.iSup_normal in
#40011) and derive pCore_normal from it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kim-em
kim-em temporarily deployed to cache-upload-forks June 4, 2026 05:39 — with GitHub Actions Inactive
…ubgroupOf

Per reviewer discussion, pCore p H now returns a Subgroup G (lying inside H,
see pCore_le) so it composes with ambient-group constructions without .map
H.subtype clutter. Since O_p(H) is only normal in H, normality/characteristicity
are stated for (pCore p H).subgroupOf H. Drop @[expose] (pCore_subgroupOf is the
characterisation lemma); simplify isPGroup_pCore via Sylow.iSup_of_normal; convert
the Sylow-alignment and homomorphism-behaviour lemmas to the Subgroup G API.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kim-em kim-em removed the awaiting-author A reviewer has asked the author a question or requested changes. label Jun 4, 2026
@kim-em
kim-em temporarily deployed to cache-upload-forks June 4, 2026 06:43 — with GitHub Actions Inactive
Add pCore_eq_iSup, ambient mem_pCore_iff, @[simp] pCore_bot; make the in-H
universal property le_pCore_subgroupOf_iff primary (map_subtype_le_pCore_iff
its corollary); add map_pCore_eq_pCore_of_ker_isPGroup; split the docstring so
the ambient isPGroup result is distinguished from the relative normality/
characteristic results.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kim-em
kim-em temporarily deployed to cache-upload-forks June 4, 2026 06:59 — with GitHub Actions Inactive
…via subgroupMap

Add Subgroup.subgroupOf_map_subgroupMap and Subgroup.subgroupOf_comap_subgroupComap
(with to_additive), promoting two helpers from the p-core development to general
subgroup API (named after the existing subgroupOf_map_subtype), and use them in
GroupTheory/PCore.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kim-em
kim-em temporarily deployed to cache-upload-forks June 4, 2026 08:28 — with GitHub Actions Inactive
Comment on lines +67 to +68
def pCore (p : ℕ) (H : Subgroup G) : Subgroup G :=
⨆ N : {N : Subgroup H // N.Normal ∧ IsPGroup p N}, (N : Subgroup H).map H.subtype

@SnirBroshi SnirBroshi Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems really awkward to me, could you use

⨆ N ≤ H, ⨆ _ : (N.subgroupOf H).Normal, ⨆ _ : IsPGroup p N, N

instead?
If it makes the proofs worse for some reason, then could you instead add versions of pCore_eq_iSup and mem_pCore_iff with this def?

@rosborn

rosborn commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

I'm not sure if this should be a Zulip post, so let me know. I've been refamiliarizing myself with mathlib's group theory api and have noticed IsPGroup, (recently) primaryComponent, and now pCore are all prime agnostic (for composite n, they only care about n.primeFactors). pCore n H at composite n is already O_{primes n}(H), primaryComponent G n is the π-primary component, etc. Should we make this clearer in the docstrings? As far as I know, this deviates from the standard literature, but in my own experiments, parameterizing by n is easier to work with than translating to a set of primes.

@tb65536 tb65536 added the awaiting-author A reviewer has asked the author a question or requested changes. label Jun 8, 2026

@rosborn rosborn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

directed_pCore can be deleted with the suggested changes to mem_pCore_subgroupOf_iff / mem_pCore_iff / pCore_eq_bot_iff.

normal_iInf_sylow / isPGroup_iInf_sylow no longer have any pCore-specific neighbors. Might be worth moving to Sylow.lean?

map_le_iff_le_comap.mp (map_pCore_le_pCore f)

/-- A group isomorphism `e : G ≃* G'` carries the `p`-core of `H` to the `p`-core of its image. -/
theorem _root_.MulEquiv.map_pCore (e : G ≃* G') :

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a corollary of map_pCore_eq_pCore_of_ker_isPGroup

map_pCore_eq_pCore_of_ker_isPGroup (e : G →* G') (by
  rw [(e : G →* G').ker_eq_bot e.injective]
  exact IsPGroup.of_bot)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also requires import Mathlib.Algebra.Group.Subgroup.Ker

Comment on lines +135 to +138
rw [pCore, ← Subgroup.map_iSup]
haveI : ∀ N : {N : Subgroup H // N.Normal ∧ IsPGroup p N}, ((N : Subgroup H)).Normal :=
fun N => N.2.1
exact (Sylow.iSup_of_normal _ fun N => N.2.2).map H.subtype

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rw [pCore, ← Subgroup.map_iSup]
haveI : ∀ N : {N : Subgroup H // N.Normal ∧ IsPGroup p N}, ((N : Subgroup H)).Normal :=
fun N => N.2.1
exact (Sylow.iSup_of_normal _ fun N => N.2.2).map H.subtype
isPGroup_pCore_subgroupOf.of_equiv (subgroupOfEquivOfLe pCore_le)

/-- The subtype of normal `p`-subgroups of `H` is nonempty (it contains `⊥`). -/
private instance : Nonempty {N : Subgroup H // N.Normal ∧ IsPGroup p N} :=
⟨⟨⊥, inferInstance, IsPGroup.of_bot⟩⟩

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can also add an instance for normality

private instance (N : {N : Subgroup H // N.Normal ∧ IsPGroup p N}) : (N : Subgroup H).Normal :=
  N.2.1

Will get rid of the haveIs in isPGroup_pCore_subgroupOf and pCore_subgroupOf_normal.

Comment on lines +265 to +275
/-- A normal Sylow `p`-subgroup of `H` coincides with the `p`-core inside `H`. -/
theorem sylow_eq_pCore_subgroupOf_of_normal (P : Sylow p H) [(P : Subgroup H).Normal] :
(P : Subgroup H) = (pCore p H).subgroupOf H :=
le_antisymm (le_pCore_subgroupOf inferInstance P.2) (pCore_subgroupOf_le_sylow P)

/-- A Sylow `p`-subgroup of `H` equals the `p`-core (inside `H`) iff it is normal. -/
theorem pCore_subgroupOf_eq_sylow_iff_normal (P : Sylow p H) :
(pCore p H).subgroupOf H = (P : Subgroup H) ↔ (P : Subgroup H).Normal := by
refine ⟨fun h => h ▸ pCore_subgroupOf_normal, fun h => ?_⟩
haveI := h
exact (sylow_eq_pCore_subgroupOf_of_normal P).symm

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason these are flipped?

Comment on lines +169 to +172
x ∈ (pCore p H).subgroupOf H ↔ ∃ N : Subgroup H, N.Normal ∧ IsPGroup p N ∧ x ∈ N := by
rw [pCore_subgroupOf, mem_iSup_of_directed directed_pCore]
exact ⟨fun ⟨N, hxN⟩ => ⟨N, N.2.1, N.2.2, hxN⟩,
fun ⟨N, hN, hP, hxN⟩ => ⟨⟨N, hN, hP⟩, hxN⟩⟩

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
x ∈ (pCore p H).subgroupOf H ↔ ∃ N : Subgroup H, N.Normal ∧ IsPGroup p N ∧ x ∈ N := by
rw [pCore_subgroupOf, mem_iSup_of_directed directed_pCore]
exact ⟨fun ⟨N, hxN⟩ => ⟨N, N.2.1, N.2.2, hxN⟩,
fun ⟨N, hN, hP, hxN⟩ => ⟨⟨N, hN, hP⟩, hxN⟩⟩
x ∈ (pCore p H).subgroupOf H ↔ ∃ N : Subgroup H, N.Normal ∧ IsPGroup p N ∧ x ∈ N :=
⟨fun hx => ⟨(pCore p H).subgroupOf H, pCore_subgroupOf_normal, isPGroup_pCore_subgroupOf, hx⟩,
fun ⟨_, hN, hP, hxN⟩ => le_pCore_subgroupOf hN hP hxN⟩

Comment on lines +177 to +181
x ∈ pCore p H ↔ ∃ N : Subgroup H, N.Normal ∧ IsPGroup p N ∧ x ∈ N.map H.subtype := by
rw [pCore_eq_iSup, mem_iSup_of_directed fun a b =>
(directed_pCore a b).imp fun _ h => ⟨map_mono h.1, map_mono h.2⟩]
exact ⟨fun ⟨N, hxN⟩ => ⟨N, N.2.1, N.2.2, hxN⟩,
fun ⟨N, hN, hP, hxN⟩ => ⟨⟨N, hN, hP⟩, hxN⟩⟩

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
x ∈ pCore p H ↔ ∃ N : Subgroup H, N.Normal ∧ IsPGroup p N ∧ x ∈ N.map H.subtype := by
rw [pCore_eq_iSup, mem_iSup_of_directed fun a b =>
(directed_pCore a b).imp fun _ h => ⟨map_mono h.1, map_mono h.2⟩]
exact ⟨fun ⟨N, hxN⟩ => ⟨N, N.2.1, N.2.2, hxN⟩,
fun ⟨N, hN, hP, hxN⟩ => ⟨⟨N, hN, hP⟩, hxN⟩⟩
x ∈ pCore p H ↔ ∃ N : Subgroup H, N.Normal ∧ IsPGroup p N ∧ x ∈ N.map H.subtype :=
⟨fun hx => ⟨(pCore p H).subgroupOf H, pCore_subgroupOf_normal, isPGroup_pCore_subgroupOf,
by rwa [map_subgroupOf_eq_of_le pCore_le]⟩,
fun ⟨_, hN, hP, hxN⟩ => le_pCore hN hP hxN⟩

Comment on lines +186 to +196
have key : pCore p H = ⊥ ↔ (pCore p H).subgroupOf H = ⊥ :=
⟨fun h => by rw [h, bot_subgroupOf],
fun h => by rw [← map_subgroupOf_eq_of_le (pCore_le (H := H)), h, map_bot]⟩
rw [key, pCore_subgroupOf]
refine ⟨fun h N hN hP => le_bot_iff.mp (h ▸ le_iSup
(fun N : {N : Subgroup H // N.Normal ∧ IsPGroup p N} => (N : Subgroup H)) ⟨N, hN, hP⟩),
fun h => ?_⟩
rw [eq_bot_iff_forall]
intro x hx
obtain ⟨N, hxN⟩ := (mem_iSup_of_directed directed_pCore).mp hx
simpa [h N N.2.1 N.2.2] using hxN

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
have key : pCore p H = ⊥ ↔ (pCore p H).subgroupOf H = ⊥ :=
⟨fun h => by rw [h, bot_subgroupOf],
fun h => by rw [← map_subgroupOf_eq_of_le (pCore_le (H := H)), h, map_bot]⟩
rw [key, pCore_subgroupOf]
refine ⟨fun h N hN hP => le_bot_iff.mp (h ▸ le_iSup
(fun N : {N : Subgroup H // N.Normal ∧ IsPGroup p N} => (N : Subgroup H)) ⟨N, hN, hP⟩),
fun h => ?_⟩
rw [eq_bot_iff_forall]
intro x hx
obtain ⟨N, hxN⟩ := (mem_iSup_of_directed directed_pCore).mp hx
simpa [h N N.2.1 N.2.2] using hxN
refine ⟨fun h N hN hP => ?_, fun h => ?_⟩
· have hle := le_pCore hN hP
rwa [h, le_bot_iff, map_eq_bot_iff_of_injective _ H.subtype_injective] at hle
· rw [← map_subgroupOf_eq_of_le (pCore_le (H := H)),
h _ pCore_subgroupOf_normal isPGroup_pCore_subgroupOf, Subgroup.map_bot]

Comment on lines +228 to +232
theorem pCore_subgroupOf_le_sylow (P : Sylow p H) : (pCore p H).subgroupOf H ≤ P := by
have hpsup : IsPGroup p ((P : Subgroup H) ⊔ (pCore p H).subgroupOf H : Subgroup H) :=
P.2.to_sup_of_normal_right isPGroup_pCore_subgroupOf
have heq : (P : Subgroup H) ⊔ (pCore p H).subgroupOf H = P := P.3 hpsup le_sup_left
exact le_sup_right.trans heq.le

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since #40012 merged, this can be shortened.

Suggested change
theorem pCore_subgroupOf_le_sylow (P : Sylow p H) : (pCore p H).subgroupOf H ≤ P := by
have hpsup : IsPGroup p ((P : Subgroup H) ⊔ (pCore p H).subgroupOf H : Subgroup H) :=
P.2.to_sup_of_normal_right isPGroup_pCore_subgroupOf
have heq : (P : Subgroup H) ⊔ (pCore p H).subgroupOf H = P := P.3 hpsup le_sup_left
exact le_sup_right.trans heq.le
theorem pCore_subgroupOf_le_sylow (P : Sylow p H) : (pCore p H).subgroupOf H ≤ P :=
isPGroup_pCore_subgroupOf.le_sylow_of_normal P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-author A reviewer has asked the author a question or requested changes. t-group-theory Group theory

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants