ReidemeisterSchreier.Discrete.OpenSubgroups.FreeBasis

8 Theorem | 6 Definition | 1 Abbreviation

This module develops the rewriting and basis constructions behind the subgroup calculations. It tracks words and relations through the chosen transversal to obtain the required presentation or basis statements.

import
Imported by

Declarations

noncomputable def FreeGroupBasis.actionGroupoidGeneratorTotalEquiv
    {ι G A : Type u} [Group G] [MulAction G A] (b : FreeGroupBasis ι G) :
    letI : IsFreeGroupoid (CategoryTheory.ActionCategory G A) :=
      FreeGroupBasis.actionGroupoidIsFree b
    Quiver.Total (IsFreeGroupoid.Generators (CategoryTheory.ActionCategory G A)) ≃ A × ι := by
  letI : IsFreeGroupoid (CategoryTheory.ActionCategory G A) :=
    FreeGroupBasis.actionGroupoidIsFree b
  refine
    { toFun := fun e => (e.left.back, e.hom.1)
      invFun := fun ai =>
        { left := show IsFreeGroupoid.Generators (CategoryTheory.ActionCategory G A) from
            ((ai.1 : A) : CategoryTheory.ActionCategory G A)
          right := show IsFreeGroupoid.Generators (CategoryTheory.ActionCategory G A) from
            ((b ai.2 • ai.1 : A) : CategoryTheory.ActionCategory G A)
          hom := ⟨ai.2, rfl⟩ }
      left_inv := ?_
      right_inv := ?_ }
  · intro e
    cases e with
    | mk left right hom =>
        cases left with
        | mk _ a =>
            cases right with
            | mk _ a' =>
                cases hom with
                | mk i hi =>
                    dsimp
                    cases hi
                    rfl
  · intro ai
    rfl

The total generator arrows in the action groupoid attached to a chosen free basis are indexed by a pair consisting of a vertex and a basis element.

noncomputable abbrev schreierComplementEdges
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T) : Type u := by
  letI := schreierTransversalRightCosetAction (X := X) hT
  letI : IsFreeGroupoid (CategoryTheory.ActionCategory (FreeGroup X) T) :=
    FreeGroupBasis.actionGroupoidIsFree (FreeGroup.inverseBasis X)
  exact
    ↥(((Quiver.wideSubquiverEquivSetTotal <|
      Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT))ᶜ :
        Set (Quiver.Total
          (IsFreeGroupoid.Generators (CategoryTheory.ActionCategory (FreeGroup X) T)))))

Complement edges of the symmetrized Schreier prefix tree. These are the canonical indexing objects for the Schreier free basis.

noncomputable def schreierComplementEdgesBasis
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T) :
    FreeGroupBasis (schreierComplementEdges (X := X) hT) L := by
  letI := schreierTransversalRightCosetAction (X := X) hT
  letI : IsFreeGroupoid (CategoryTheory.ActionCategory (FreeGroup X) T) :=
    FreeGroupBasis.actionGroupoidIsFree (FreeGroup.inverseBasis X)
  exact
    (IsFreeGroupoid.SpanningTree.endBasis (schreierPrefixTree (X := X) hT)).map
      (schreierRootEndMulEquiv (X := X) hT)

The Schreier basis indexed by complement edges of the prefix tree.

private noncomputable def nontrivialSchreierPairsEquivSchreierGeneratorSet
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T) :
    NontrivialSchreierPair (X := X) hT ≃ ↥(schreierGeneratorSet (X := X) hT) := by
  classical
  letI := schreierTransversalRightCosetAction (X := X) hT
  letI : IsFreeGroupoid (CategoryTheory.ActionCategory (FreeGroup X) T) :=
    FreeGroupBasis.actionGroupoidIsFree (FreeGroup.inverseBasis X)
  let C :
      Set (Quiver.Total
        (IsFreeGroupoid.Generators (CategoryTheory.ActionCategory (FreeGroup X) T))) :=
    ((Quiver.wideSubquiverEquivSetTotal <|
      Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT))ᶜ : Set _)
  let toSch : ↑C → ↥(schreierGeneratorSet (X := X) hT) := fun i =>
    ⟨schreierGenerator (X := X) hT (((i.1.left.back : T) : FreeGroup X)) i.1.hom.1,
      by
        refine ⟨
          ((i.1.left.back : T) : FreeGroup X), (i.1.left.back : T).property,
          i.1.hom.1, rfl, ?_⟩
        intro hgen
        exact i.2 (show i.1 ∈ Quiver.wideSubquiverEquivSetTotal
            (Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT)) from
          schreierGenerator_eq_one_implies_mem_prefixTree (X := X) hT i.1.hom hgen)⟩
  let b : FreeGroupBasis ↑C L :=
    (IsFreeGroupoid.SpanningTree.endBasis (schreierPrefixTree (X := X) hT)).map
      (schreierRootEndMulEquiv (X := X) hT)
  have hval : ∀ i : ↑C, (b i : L) = (((toSch i : ↥(schreierGeneratorSet (X := X) hT)) : L)⁻¹) := by
    intro i
    rw [FreeGroupBasis.map_apply, IsFreeGroupoid.SpanningTree.endBasis_apply]
    have htree : ∀ {a b : IsFreeGroupoid.Generators (CategoryTheory.ActionCategory (FreeGroup X) T)}
        (e : a ⟶ b),
        e ∈ Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT) a b →
          (schreierLabelFunctor (X := X) hT).map (IsFreeGroupoid.of e) = (1 : L) := by
      intro a b e he
      exact schreierLabelFunctor_map_of_eq_one_of_mem_tree (X := X) hT e he
    have hloop := IsFreeGroupoid.SpanningTree.map_loopOfHom_eq_map
      (T := schreierPrefixTree (X := X) hT)
      (F := schreierLabelFunctor (X := X) hT)
      (hTree := by
        intro a b e he
        exact htree e he)
      (q := IsFreeGroupoid.of i.1.hom)
    let loop := IsFreeGroupoid.SpanningTree.loopOfHom (schreierPrefixTree (X := X) hT)
      (IsFreeGroupoid.of i.1.hom)
    have hrootEq : (schreierRootEndMulEquiv (X := X) hT loop : L) =
        (schreierLabelFunctor (X := X) hT).map loop := by
      apply Subtype.ext
      change loop.1 = (1 : FreeGroup X) * loop.1 * (1 : FreeGroup X)⁻¹
      simp only [CategoryTheory.actionAsFunctor_obj, CategoryTheory.actionAsFunctor_map, one_mul, inv_one, mul_one]
    exact hrootEq.trans <| hloop.trans <| schreierLabelFunctor_map_of (X := X) hT i.1.hom
  have hto_inj : Function.Injective toSch := by
    intro i j hij
    apply b.injective
    have hz : ((toSch i : ↥(schreierGeneratorSet (X := X) hT)) : L) =
        ((toSch j : ↥(schreierGeneratorSet (X := X) hT)) : L) := congrArg Subtype.val hij
    have hz_inv : (((toSch i : ↥(schreierGeneratorSet (X := X) hT)) : L)⁻¹) =
        (((toSch j : ↥(schreierGeneratorSet (X := X) hT)) : L)⁻¹) := congrArg Inv.inv hz
    exact (hval i).trans (hz_inv.trans (hval j).symm)
  have hto_surj : Function.Surjective toSch := by
    intro z
    rcases z.2 with ⟨t, ht, x, hz, hne⟩
    let a : CategoryTheory.ActionCategory (FreeGroup X) T :=
      ((⟨t, ht⟩ : T) : CategoryTheory.ActionCategory (FreeGroup X) T)
    let b0 : CategoryTheory.ActionCategory (FreeGroup X) T :=
      (schreierRepresentative (X := X) hT (t * FreeGroup.of x) : T)
    let e :
        ((show IsFreeGroupoid.Generators (CategoryTheory.ActionCategory (FreeGroup X) T) from a) ⟶
          b0) :=
      ⟨x, by
        rw [FreeGroup.inverseBasis_apply]
        change (FreeGroup.of x)⁻¹ • (show T from CategoryTheory.ActionCategory.back a) =
          (show T from CategoryTheory.ActionCategory.back b0)
        simpa [a, b0] using
          (schreierTransversalRightCosetAction_smul (X := X) hT (FreeGroup.of x)⁻¹ (⟨t, ht⟩ : T))⟩
    have he_not : ⟨a, b0, e⟩ ∈ C := by
      change ¬ e ∈ Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT) a b0
      intro he
      have hgen1_inv :
          (schreierGenerator (X := X) hT
            ((show T from CategoryTheory.ActionCategory.back a) : FreeGroup X) e.1)⁻¹ = 1 := by
        have htreeLabel :=
          schreierLabelFunctor_map_of_eq_one_of_mem_tree (X := X) hT e he
        rw [schreierLabelFunctor_map_of (X := X) hT e] at htreeLabel
        exact htreeLabel
      have hgen1 :
          schreierGenerator (X := X) hT
            ((show T from CategoryTheory.ActionCategory.back a) : FreeGroup X) e.1 = 1 :=
        inv_eq_one.mp hgen1_inv
      exact hne (by simpa [a, e, hz] using hgen1)
    refine ⟨⟨⟨a, b0, e⟩, he_not⟩, ?_⟩
    apply Subtype.ext
    simpa [toSch, a, e] using hz.symm
  let eC : ↑C ≃ ↥(schreierGeneratorSet (X := X) hT) := Equiv.ofBijective toSch ⟨hto_inj, hto_surj⟩
  let ePair :
      ↑C ≃ NontrivialSchreierPair (X := X) hT := by
    let eTotal :
        Quiver.Total (IsFreeGroupoid.Generators (CategoryTheory.ActionCategory (FreeGroup X) T)) ≃
          T × X :=
      FreeGroupBasis.actionGroupoidGeneratorTotalEquiv (FreeGroup.inverseBasis X)
    refine
      { toFun := fun i =>
          ⟨eTotal i.1, by
            intro hgen
            have hgen' :
                schreierGenerator (X := X) hT
                  (((show T from CategoryTheory.ActionCategory.back i.1.left) : T) : FreeGroup X)
                  i.1.hom.1 = 1 := by
              simpa [eTotal] using hgen
            exact i.2 (show i.1 ∈ Quiver.wideSubquiverEquivSetTotal
                (Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT)) from
              schreierGenerator_eq_one_implies_mem_prefixTree (X := X) hT i.1.hom hgen')⟩
        invFun := fun p =>
          let e := eTotal.symm p.1
          ⟨e, by
            intro he
            have htreeLabel :=
              schreierLabelFunctor_map_of_eq_one_of_mem_tree (X := X) hT e.hom
                (show e.hom ∈ Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT)
                    e.left e.right from he)
            rw [schreierLabelFunctor_map_of (X := X) hT e.hom] at htreeLabel
            have hgen' :
                schreierGenerator (X := X) hT
                  (((show T from CategoryTheory.ActionCategory.back e.left) : T) : FreeGroup X)
                  e.hom.1 = 1 := inv_eq_one.mp htreeLabel
            exact p.2 (by simpa [eTotal] using hgen')⟩
        left_inv := by
          intro i
          apply Subtype.ext
          simp only [Equiv.symm_apply_apply, eTotal]
        right_inv := by
          intro p
          apply Subtype.ext
          simp only [ne_eq, Equiv.apply_symm_apply, eTotal]}
  exact ePair.symm.trans eC

Auxiliary bridge from nontrivial Schreier pairs to the classical Schreier generator value set.

noncomputable def schreierComplementEdgesEquivNontrivialPairs
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T) :
    schreierComplementEdges (X := X) hT ≃ NontrivialSchreierPair (X := X) hT := by
  classical
  letI := schreierTransversalRightCosetAction (X := X) hT
  letI : IsFreeGroupoid (CategoryTheory.ActionCategory (FreeGroup X) T) :=
    FreeGroupBasis.actionGroupoidIsFree (FreeGroup.inverseBasis X)
  let C :
      Set (Quiver.Total
        (IsFreeGroupoid.Generators (CategoryTheory.ActionCategory (FreeGroup X) T))) :=
    ((Quiver.wideSubquiverEquivSetTotal <|
      Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT))ᶜ : Set _)
  change ↑C ≃ NontrivialSchreierPair (X := X) hT
  let eTotal :
      Quiver.Total (IsFreeGroupoid.Generators (CategoryTheory.ActionCategory (FreeGroup X) T)) ≃
        T × X :=
    FreeGroupBasis.actionGroupoidGeneratorTotalEquiv (FreeGroup.inverseBasis X)
  refine
    { toFun := fun i =>
        ⟨eTotal i.1, by
          intro hgen
          have hgen' :
              schreierGenerator (X := X) hT
                (((show T from CategoryTheory.ActionCategory.back i.1.left) : T) : FreeGroup X)
                i.1.hom.1 = 1 := by
            simpa [eTotal] using hgen
          exact i.2 (show i.1 ∈ Quiver.wideSubquiverEquivSetTotal
              (Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT)) from
            (schreierGenerator_eq_one_iff_mem_prefixTree (X := X) hT i.1.hom).1 hgen')⟩
      invFun := fun p =>
        let e := eTotal.symm p.1
        ⟨e, by
          intro he
          have hgen' :
              schreierGenerator (X := X) hT
                (((show T from CategoryTheory.ActionCategory.back e.left) : T) : FreeGroup X)
                e.hom.1 = 1 :=
            (schreierGenerator_eq_one_iff_mem_prefixTree (X := X) hT e.hom).2
              (show e.hom ∈ Quiver.wideSubquiverSymmetrify (schreierPrefixTree (X := X) hT)
                  e.left e.right from he)
          exact p.2 (by simpa [eTotal] using hgen')⟩
      left_inv := by
        intro i
        apply Subtype.ext
        simp only [Equiv.symm_apply_apply, eTotal]
      right_inv := by
        intro p
        apply Subtype.ext
        simp only [ne_eq, Equiv.apply_symm_apply, eTotal]}

Complement edges are equivalent to nontrivial Schreier pairs.

noncomputable def nontrivialSchreierPairBasis
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T) :
    FreeGroupBasis (NontrivialSchreierPair (X := X) hT) L :=
  (schreierComplementEdgesBasis (X := X) hT).reindex
    (schreierComplementEdgesEquivNontrivialPairs (X := X) hT)

The Schreier free basis indexed by nontrivial Schreier pairs. This is the preferred Schreier-basis formulation; the classical value-set basis is a reindexing of this one.

noncomputable def nontrivialSchreierPairBasisEquiv
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T) :
    FreeGroup (NontrivialSchreierPair (X := X) hT) ≃* L :=
  (nontrivialSchreierPairBasis (X := X) hT).repr.symm

The free group equivalence obtained directly from the preferred pair-indexed Schreier basis.

@[simp] theorem nontrivialSchreierPairBasisEquiv_of
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T)
    (p : NontrivialSchreierPair (X := X) hT) :
    nontrivialSchreierPairBasisEquiv (X := X) hT (FreeGroup.of p) =
      nontrivialSchreierPairBasis (X := X) hT p

The preferred pair-indexed basis equivalence sends each free generator to its Schreier basis element.

Show proof
private theorem nontrivialSchreierPairsEquivSchreierGeneratorSet_apply
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T)
    (p : NontrivialSchreierPair (X := X) hT) :
    ((nontrivialSchreierPairsEquivSchreierGeneratorSet (X := X) hT p :
        ↥(schreierGeneratorSet (X := X) hT)) : L) =
      schreierGenerator (X := X) hT ((p.1.1 : T) : FreeGroup X) p.1.2

The Reidemeister--Schreier equivalence is evaluated by the chosen nontrivial Schreier pair and its associated generator.

Show proof
theorem schreierGenerator_injective_of_nontrivial
    {X : Type u} [DecidableEq X] {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    (hT : IsRightSchreierTransversal (X := X) L T) :
    Function.Injective
      (nontrivialSchreierPairGenerator (X := X) hT)

The Schreier-generator map is injective on nontrivial Schreier pairs.

Show proof
theorem natCard_schreierTransversal_eq_index
    {X : Type u} [DecidableEq X]
    {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    [Finite (Quotient (QuotientGroup.rightRel L))]
    (hT : IsRightSchreierTransversal (X := X) L T) :
    Nat.card T = Nat.card (Quotient (QuotientGroup.rightRel L))

A right Schreier transversal has cardinality equal to the corresponding right-coset index.

Show proof
theorem natCard_schreierComplementEdges_eq_rankTransform_direct
    {X : Type u} [DecidableEq X] [Finite X]
    {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    [Finite T]
    (hT : IsRightSchreierTransversal (X := X) L T) :
    Nat.card (schreierComplementEdges (X := X) hT) =
      _root_.ReidemeisterSchreier.Schreier.rankTransform (Nat.card X) (Nat.card T)

The direct combinatorial count of complement edges in the Schreier prefix tree: all labelled edges minus tree edges.

Show proof
theorem natCard_nontrivialSchreierPairs_eq_rankTransform_direct
    {X : Type u} [DecidableEq X] [Finite X]
    {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    [Finite T]
    (hT : IsRightSchreierTransversal (X := X) L T) :
    Nat.card (NontrivialSchreierPair (X := X) hT) =
      _root_.ReidemeisterSchreier.Schreier.rankTransform (Nat.card X) (Nat.card T)

The preferred pair-indexed generator type has cardinality equal to the Schreier rank-transform count.

Show proof
theorem natCard_nontrivialSchreierPairs_eq_rankTransform
    {X : Type u} [DecidableEq X] [Finite X]
    {L : Subgroup (FreeGroup X)} {T : Set (FreeGroup X)}
    [Finite (FreeGroup X ⧸ L)]
    (hT : IsRightSchreierTransversal (X := X) L T) :
    Nat.card (NontrivialSchreierPair (X := X) hT) =
      _root_.ReidemeisterSchreier.Schreier.rankTransform (Nat.card X) (Nat.card (FreeGroup X ⧸ L))

The number of nontrivial Schreier pairs equals the Schreier rank-transform count, with the index written as the usual left-coset quotient.

Show proof
theorem exists_freeBasis_subgroupOfFreeGroup_of_rankTransform
    {X : Type u} {L : Subgroup (FreeGroup X)} [Finite X] [Finite (FreeGroup X ⧸ L)] :
    ∃ Y : Type u, Nonempty (FreeGroupBasis Y L) ∧
      Nat.card Y = _root_.ReidemeisterSchreier.Schreier.rankTransform (Nat.card X) (Nat.card (FreeGroup X ⧸ L))

A finite-index subgroup of a free group admits a free basis of Schreier-transformed cardinality.

Show proof