l3lab/ntp-mathlib huggingface dataset:
/-- To avoid duplicating code, we define `toSubgroup A B u` and `toSubgroupEquiv u`
where `u : ℤˣ` is `1` or `-1`. `toSubgroup A B u` is `A` when `u = 1` and `B` when `u = -1`,
and `toSubgroupEquiv` is the group ismorphism from `toSubgroup A B u` to `toSubgroup A B (-u)`.
It is defined to be `φ` when `u = 1` and `φ⁻¹` when `u = -1`. -/
def toSubgroupEquiv (u : ℤˣ) : toSubgroup A B u ≃* toSubgroup A B (-u) :=
  if hu : u = 1 then hu ▸ φ else by
    convert φ.symm <;>
    cases Int.units_eq_one_or u <;> 

Proof state:
case h.e'_1.h.e'_2.h.h.e'_5.inr
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
u : ℤˣ
hu : ¬u = 1
x✝ : G
h✝ : u = -1
⊢ toSubgroup A B u = B

Next tactic:
simp_all
/-- To avoid duplicating code, we define `toSubgroup A B u` and `toSubgroupEquiv u`
where `u : ℤˣ` is `1` or `-1`. `toSubgroup A B u` is `A` when `u = 1` and `B` when `u = -1`,
and `toSubgroupEquiv` is the group ismorphism from `toSubgroup A B u` to `toSubgroup A B (-u)`.
It is defined to be `φ` when `u = 1` and `φ⁻¹` when `u = -1`. -/
def toSubgroupEquiv (u : ℤˣ) : toSubgroup A B u ≃* toSubgroup A B (-u) :=
  if hu : u = 1 then hu ▸ φ else by
    convert φ.symm <;>
    cases Int.units_eq_one_or u <;> 

Proof state:
case h.e'_2.h.e'_2.h.h.e'_5.inl
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
u : ℤˣ
hu : ¬u = 1
x✝ : G
h✝ : u = 1
⊢ toSubgroup A B (-u) = A

Next tactic:
simp_all
/-- To avoid duplicating code, we define `toSubgroup A B u` and `toSubgroupEquiv u`
where `u : ℤˣ` is `1` or `-1`. `toSubgroup A B u` is `A` when `u = 1` and `B` when `u = -1`,
and `toSubgroupEquiv` is the group ismorphism from `toSubgroup A B u` to `toSubgroup A B (-u)`.
It is defined to be `φ` when `u = 1` and `φ⁻¹` when `u = -1`. -/
def toSubgroupEquiv (u : ℤˣ) : toSubgroup A B u ≃* toSubgroup A B (-u) :=
  if hu : u = 1 then hu ▸ φ else by
    convert φ.symm <;>
    cases Int.units_eq_one_or u <;> 

Proof state:
case h.e'_2.h.e'_2.h.h.e'_5.inr
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
u : ℤˣ
hu : ¬u = 1
x✝ : G
h✝ : u = -1
⊢ toSubgroup A B (-u) = A

Next tactic:
simp_all
/-- To avoid duplicating code, we define `toSubgroup A B u` and `toSubgroupEquiv u`
where `u : ℤˣ` is `1` or `-1`. `toSubgroup A B u` is `A` when `u = 1` and `B` when `u = -1`,
and `toSubgroupEquiv` is the group ismorphism from `toSubgroup A B u` to `toSubgroup A B (-u)`.
It is defined to be `φ` when `u = 1` and `φ⁻¹` when `u = -1`. -/
def toSubgroupEquiv (u : ℤˣ) : toSubgroup A B u ≃* toSubgroup A B (-u) :=
  if hu : u = 1 then hu ▸ φ else by
    convert φ.symm <;>
    cases Int.units_eq_one_or u <;> 

Proof state:
case h.e'_3.e'_3.inl
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
u : ℤˣ
hu : ¬u = 1
e_1✝ : ↥(toSubgroup A B u) = ↥B
h✝ : u = 1
⊢ toSubgroup A B u = B

Next tactic:
simp_all
/-- To avoid duplicating code, we define `toSubgroup A B u` and `toSubgroupEquiv u`
where `u : ℤˣ` is `1` or `-1`. `toSubgroup A B u` is `A` when `u = 1` and `B` when `u = -1`,
and `toSubgroupEquiv` is the group ismorphism from `toSubgroup A B u` to `toSubgroup A B (-u)`.
It is defined to be `φ` when `u = 1` and `φ⁻¹` when `u = -1`. -/
def toSubgroupEquiv (u : ℤˣ) : toSubgroup A B u ≃* toSubgroup A B (-u) :=
  if hu : u = 1 then hu ▸ φ else by
    convert φ.symm <;>
    cases Int.units_eq_one_or u <;> 

Proof state:
case h.e'_3.e'_3.inr
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
u : ℤˣ
hu : ¬u = 1
e_1✝ : ↥(toSubgroup A B u) = ↥B
h✝ : u = -1
⊢ toSubgroup A B u = B

Next tactic:
simp_all
/-- To avoid duplicating code, we define `toSubgroup A B u` and `toSubgroupEquiv u`
where `u : ℤˣ` is `1` or `-1`. `toSubgroup A B u` is `A` when `u = 1` and `B` when `u = -1`,
and `toSubgroupEquiv` is the group ismorphism from `toSubgroup A B u` to `toSubgroup A B (-u)`.
It is defined to be `φ` when `u = 1` and `φ⁻¹` when `u = -1`. -/
def toSubgroupEquiv (u : ℤˣ) : toSubgroup A B u ≃* toSubgroup A B (-u) :=
  if hu : u = 1 then hu ▸ φ else by
    convert φ.symm <;>
    cases Int.units_eq_one_or u <;> 

Proof state:
case h.e'_4.e'_3.inl
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
u : ℤˣ
hu : ¬u = 1
e_2✝ : ↥(toSubgroup A B (-u)) = ↥A
h✝ : u = 1
⊢ toSubgroup A B (-u) = A

Next tactic:
simp_all
/-- To avoid duplicating code, we define `toSubgroup A B u` and `toSubgroupEquiv u`
where `u : ℤˣ` is `1` or `-1`. `toSubgroup A B u` is `A` when `u = 1` and `B` when `u = -1`,
and `toSubgroupEquiv` is the group ismorphism from `toSubgroup A B u` to `toSubgroup A B (-u)`.
It is defined to be `φ` when `u = 1` and `φ⁻¹` when `u = -1`. -/
def toSubgroupEquiv (u : ℤˣ) : toSubgroup A B u ≃* toSubgroup A B (-u) :=
  if hu : u = 1 then hu ▸ φ else by
    convert φ.symm <;>
    cases Int.units_eq_one_or u <;> 

Proof state:
case h.e'_4.e'_3.inr
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
u : ℤˣ
hu : ¬u = 1
e_2✝ : ↥(toSubgroup A B (-u)) = ↥A
h✝ : u = -1
⊢ toSubgroup A B (-u) = A

Next tactic:
simp_all
@[simp]
theorem toSubgroupEquiv_neg_apply (u : ℤˣ) (a : toSubgroup A B u) :
    (toSubgroupEquiv φ (-u) (toSubgroupEquiv φ u a) : G) = a := by
  

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
u : ℤˣ
a : ↥(toSubgroup A B u)
⊢ ↑((toSubgroupEquiv φ (-u)) ((toSubgroupEquiv φ u) a)) = ↑a

Next tactic:
rcases Int.units_eq_one_or u with rfl | rfl
@[simp]
theorem toSubgroupEquiv_neg_apply (u : ℤˣ) (a : toSubgroup A B u) :
    (toSubgroupEquiv φ (-u) (toSubgroupEquiv φ u a) : G) = a := by
  rcases Int.units_eq_one_or u with rfl | rfl
  · -- This used to be `simp` before leanprover/lean4#2644
    

Proof state:
case inl
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
a : ↥(toSubgroup A B 1)
⊢ ↑((toSubgroupEquiv φ (-1)) ((toSubgroupEquiv φ 1) a)) = ↑a

Next tactic:
simp
@[simp]
theorem toSubgroupEquiv_neg_apply (u : ℤˣ) (a : toSubgroup A B u) :
    (toSubgroupEquiv φ (-u) (toSubgroupEquiv φ u a) : G) = a := by
  rcases Int.units_eq_one_or u with rfl | rfl
  · -- This used to be `simp` before leanprover/lean4#2644
    simp; 

Proof state:
case inl
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
a : ↥(toSubgroup A B 1)
⊢ (MulEquiv.symm φ) (φ a) = a

Next tactic:
erw [MulEquiv.symm_apply_apply]
@[simp]
theorem toSubgroupEquiv_neg_apply (u : ℤˣ) (a : toSubgroup A B u) :
    (toSubgroupEquiv φ (-u) (toSubgroupEquiv φ u a) : G) = a := by
  rcases Int.units_eq_one_or u with rfl | rfl
  · -- This used to be `simp` before leanprover/lean4#2644
    simp; erw [MulEquiv.symm_apply_apply]
  · 

Proof state:
case inr
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
a : ↥(toSubgroup A B (-1))
⊢ ↑((toSubgroupEquiv φ (- -1)) ((toSubgroupEquiv φ (-1)) a)) = ↑a

Next tactic:
simp only [toSubgroup_neg_one, toSubgroupEquiv_neg_one, SetLike.coe_eq_coe]
@[simp]
theorem toSubgroupEquiv_neg_apply (u : ℤˣ) (a : toSubgroup A B u) :
    (toSubgroupEquiv φ (-u) (toSubgroupEquiv φ u a) : G) = a := by
  rcases Int.units_eq_one_or u with rfl | rfl
  · -- This used to be `simp` before leanprover/lean4#2644
    simp; erw [MulEquiv.symm_apply_apply]
  · simp only [toSubgroup_neg_one, toSubgroupEquiv_neg_one, SetLike.coe_eq_coe]
    

Proof state:
case inr
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
a : ↥(toSubgroup A B (-1))
⊢ (toSubgroupEquiv φ (- -1)) ((MulEquiv.symm φ) a) = a

Next tactic:
exact φ.apply_symm_apply a
instance TransversalPair.nonempty : Nonempty (TransversalPair G A B) := by
  

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
⊢ Nonempty (TransversalPair G A B)

Next tactic:
choose t ht using fun u ↦ (toSubgroup A B u).exists_right_transversal 1
instance TransversalPair.nonempty : Nonempty (TransversalPair G A B) := by
  choose t ht using fun u ↦ (toSubgroup A B u).exists_right_transversal 1
  

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
t : ℤˣ → Set G
ht : ∀ (u : ℤˣ), t u ∈ rightTransversals ↑(toSubgroup A B u) ∧ 1 ∈ t u
⊢ Nonempty (TransversalPair G A B)

Next tactic:
exact ⟨⟨t, fun i ↦ (ht i).1⟩⟩
@[ext]
theorem ext {w w' : NormalWord d}
    (h1 : w.head = w'.head) (h2 : w.toList = w'.toList): w = w' := by
  

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
w w' : NormalWord d
h1 : w.head = w'.head
h2 : w.toList = w'.toList
⊢ w = w'

Next tactic:
rcases w with ⟨⟨⟩, _⟩
@[ext]
theorem ext {w w' : NormalWord d}
    (h1 : w.head = w'.head) (h2 : w.toList = w'.toList): w = w' := by
  rcases w with ⟨⟨⟩, _⟩; 

Proof state:
case mk.mk
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
w' : NormalWord d
head✝ : G
toList✝ : List (ℤˣ × G)
chain✝ : List.Chain' (fun a b => a.2 ∈ toSubgroup A B a.1 → a.1 = b.1) toList✝
mem_set✝ :
  ∀ (u : ℤˣ) (g : G),
    (u, g) ∈ { head := head✝, toList := toList✝, chain := chain✝ }.toList → g ∈ TransversalPair.set d u
h1 :
  { toReducedWord := { head := head✝, toList := toList✝, chain := chain✝ }, mem_set := mem_set✝ }.toReducedWord.head =
    w'.head
h2 :
  { toReducedWord := { head := head✝, toList := toList✝, chain := chain✝ }, mem_set := mem_set✝ }.toReducedWord.toList =
    w'.toList
⊢ { toReducedWord := { head := head✝, toList := toList✝, chain := chain✝ }, mem_set := mem_set✝ } = w'

Next tactic:
cases w'
@[ext]
theorem ext {w w' : NormalWord d}
    (h1 : w.head = w'.head) (h2 : w.toList = w'.toList): w = w' := by
  rcases w with ⟨⟨⟩, _⟩; cases w'; 

Proof state:
case mk.mk.mk
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
head✝ : G
toList✝ : List (ℤˣ × G)
chain✝ : List.Chain' (fun a b => a.2 ∈ toSubgroup A B a.1 → a.1 = b.1) toList✝
mem_set✝¹ :
  ∀ (u : ℤˣ) (g : G),
    (u, g) ∈ { head := head✝, toList := toList✝, chain := chain✝ }.toList → g ∈ TransversalPair.set d u
toReducedWord✝ : ReducedWord G A B
mem_set✝ : ∀ (u : ℤˣ) (g : G), (u, g) ∈ toReducedWord✝.toList → g ∈ TransversalPair.set d u
h1 :
  { toReducedWord := { head := head✝, toList := toList✝, chain := chain✝ }, mem_set := mem_set✝¹ }.toReducedWord.head =
    { toReducedWord := toReducedWord✝, mem_set := mem_set✝ }.toReducedWord.head
h2 :
  { toReducedWord := { head := head✝, toList := toList✝, chain := chain✝ },
          mem_set := mem_set✝¹ }.toReducedWord.toList =
    { toReducedWord := toReducedWord✝, mem_set := mem_set✝ }.toReducedWord.toList
⊢ { toReducedWord := { head := head✝, toList := toList✝, chain := chain✝ }, mem_set := mem_set✝¹ } =
    { toReducedWord := toReducedWord✝, mem_set := mem_set✝ }

Next tactic:
simp_all
/-- The empty word -/
@[simps]
def empty : NormalWord d :=
  { head := 1
    toList := []
    mem_set := by 

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
⊢ ∀ (u : ℤˣ) (g : G),
    (u, g) ∈
        { head := 1, toList := [],
            chain := (_ : List.Chain' (fun a b => a.2 ∈ toSubgroup A B a.1 → a.1 = b.1) []) }.toList →
      g ∈ TransversalPair.set d u

Next tactic:
simp
/-- The `NormalWord` representing an element `g` of the group `G`, which is just the element `g`
itself. -/
@[simps]
def ofGroup (g : G) : NormalWord d :=
  { head := g
    toList := []
    mem_set := by 

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
⊢ ∀ (u : ℤˣ) (g_1 : G),
    (u, g_1) ∈
        { head := g, toList := [],
            chain := (_ : List.Chain' (fun a b => a.2 ∈ toSubgroup A B a.1 → a.1 = b.1) []) }.toList →
      g_1 ∈ TransversalPair.set d u

Next tactic:
simp
instance : MulAction G (NormalWord d) :=
  { smul := fun g w => { w with head := g * w.head }
    one_smul := by 

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
⊢ ∀ (b : NormalWord d), 1 • b = b

Next tactic:
simp [instHSMul]
instance : MulAction G (NormalWord d) :=
  { smul := fun g w => { w with head := g * w.head }
    one_smul := by simp [instHSMul]
    mul_smul := by 

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
⊢ ∀ (x y : G) (b : NormalWord d), (x * y) • b = x • y • b

Next tactic:
simp [instHSMul, mul_assoc]
instance : FaithfulSMul G (NormalWord d) := ⟨by 

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
⊢ ∀ {m₁ m₂ : G}, (∀ (a : NormalWord d), m₁ • a = m₂ • a) → m₁ = m₂

Next tactic:
simp [group_smul_def]
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      intro u' g' h'
      simp only [List.mem_cons, Prod.mk.injEq] at h'
      rcases h' with ⟨rfl, rfl⟩ | h'
      · exact h1
      · exact w.mem_set _ _ h'
    chain := by
      

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
u : ℤˣ
w : NormalWord d
h1 : w.head ∈ TransversalPair.set d u
h2 : ∀ u' ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u → u = u'
⊢ List.Chain' (fun a b => a.2 ∈ toSubgroup A B a.1 → a.1 = b.1) ((u, w.head) :: w.toList)

Next tactic:
refine List.chain'_cons'.2 ⟨?_, w.chain⟩
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      intro u' g' h'
      simp only [List.mem_cons, Prod.mk.injEq] at h'
      rcases h' with ⟨rfl, rfl⟩ | h'
      · exact h1
      · exact w.mem_set _ _ h'
    chain := by
      refine List.chain'_cons'.2 ⟨?_, w.chain⟩
      

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
u : ℤˣ
w : NormalWord d
h1 : w.head ∈ TransversalPair.set d u
h2 : ∀ u' ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u → u = u'
⊢ ∀ y ∈ List.head? w.toList, (u, w.head).2 ∈ toSubgroup A B (u, w.head).1 → (u, w.head).1 = y.1

Next tactic:
rintro ⟨u', g'⟩ hu' hw1
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      intro u' g' h'
      simp only [List.mem_cons, Prod.mk.injEq] at h'
      rcases h' with ⟨rfl, rfl⟩ | h'
      · exact h1
      · exact w.mem_set _ _ h'
    chain := by
      refine List.chain'_cons'.2 ⟨?_, w.chain⟩
      rintro ⟨u', g'⟩ hu' hw1
      

Proof state:
case mk
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
u : ℤˣ
w : NormalWord d
h1 : w.head ∈ TransversalPair.set d u
h2 : ∀ u' ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u → u = u'
u' : ℤˣ
g' : G
hu' : (u', g') ∈ List.head? w.toList
hw1 : (u, w.head).2 ∈ toSubgroup A B (u, w.head).1
⊢ (u, w.head).1 = (u', g').1

Next tactic:
exact h2 _ (by simp_all) hw1
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      intro u' g' h'
      simp only [List.mem_cons, Prod.mk.injEq] at h'
      rcases h' with ⟨rfl, rfl⟩ | h'
      · exact h1
      · exact w.mem_set _ _ h'
    chain := by
      refine List.chain'_cons'.2 ⟨?_, w.chain⟩
      rintro ⟨u', g'⟩ hu' hw1
      exact h2 _ (by 

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
u : ℤˣ
w : NormalWord d
h1 : w.head ∈ TransversalPair.set d u
h2 : ∀ u' ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u → u = u'
u' : ℤˣ
g' : G
hu' : (u', g') ∈ List.head? w.toList
hw1 : (u, w.head).2 ∈ toSubgroup A B (u, w.head).1
⊢ (u', g').1 ∈ Option.map Prod.fst (List.head? w.toList)

Next tactic:
simp_all
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
u : ℤˣ
w : NormalWord d
h1 : w.head ∈ TransversalPair.set d u
h2 : ∀ u' ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u → u = u'
⊢ ∀ (u_1 : ℤˣ) (g_1 : G),
    (u_1, g_1) ∈
        { head := g, toList := (u, w.head) :: w.toList,
            chain :=
              (_ : List.Chain' (fun a b => a.2 ∈ toSubgroup A B a.1 → a.1 = b.1) ((u, w.head) :: w.toList)) }.toList →
      g_1 ∈ TransversalPair.set d u_1

Next tactic:
intro u' g' h'
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      intro u' g' h'
      

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
u : ℤˣ
w : NormalWord d
h1 : w.head ∈ TransversalPair.set d u
h2 : ∀ u' ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u → u = u'
u' : ℤˣ
g' : G
h' :
  (u', g') ∈
    { head := g, toList := (u, w.head) :: w.toList,
        chain := (_ : List.Chain' (fun a b => a.2 ∈ toSubgroup A B a.1 → a.1 = b.1) ((u, w.head) :: w.toList)) }.toList
⊢ g' ∈ TransversalPair.set d u'

Next tactic:
simp only [List.mem_cons, Prod.mk.injEq] at h'
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      intro u' g' h'
      simp only [List.mem_cons, Prod.mk.injEq] at h'
      

Proof state:
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
u : ℤˣ
w : NormalWord d
h1 : w.head ∈ TransversalPair.set d u
h2 : ∀ u' ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u → u = u'
u' : ℤˣ
g' : G
h' : u' = u ∧ g' = w.head ∨ (u', g') ∈ w.toList
⊢ g' ∈ TransversalPair.set d u'

Next tactic:
rcases h' with ⟨rfl, rfl⟩ | h'
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      intro u' g' h'
      simp only [List.mem_cons, Prod.mk.injEq] at h'
      rcases h' with ⟨rfl, rfl⟩ | h'
      · 

Proof state:
case inl.intro
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
w : NormalWord d
u' : ℤˣ
h1 : w.head ∈ TransversalPair.set d u'
h2 : ∀ u'_1 ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u' → u' = u'_1
⊢ w.head ∈ TransversalPair.set d u'

Next tactic:
exact h1
/-- A constructor to append an element `g` of `G` and `u : ℤˣ` to a word `w` with sufficient
hypotheses that no normalization or cancellation need take place for the result to be in normal form
-/
@[simps]
def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u)
    (h2 : ∀ u' ∈ Option.map Prod.fst w.toList.head?, w.head ∈ toSubgroup A B u → u = u') :
    NormalWord d :=
  { head := g,
    toList := (u, w.head) :: w.toList,
    mem_set := by
      intro u' g' h'
      simp only [List.mem_cons, Prod.mk.injEq] at h'
      rcases h' with ⟨rfl, rfl⟩ | h'
      · exact h1
      · 

Proof state:
case inr
G : Type u_1
inst✝² : Group G
A B : Subgroup G
φ : ↥A ≃* ↥B
H : Type u_2
inst✝¹ : Group H
M : Type u_3
inst✝ : Monoid M
d : TransversalPair G A B
g : G
u : ℤˣ
w : NormalWord d
h1 : w.head ∈ TransversalPair.set d u
h2 : ∀ u' ∈ Option.map Prod.fst (List.head? w.toList), w.head ∈ toSubgroup A B u → u = u'
u' : ℤˣ
g' : G
h' : (u', g') ∈ w.toList
⊢ g' ∈ TransversalPair.set d u'

Next tactic:
exact w.mem_set _ _ h'