l3lab/ntp-mathlib huggingface dataset:
theorem comapEq_symm {β γ : Type w} {f g : β → γ} (h : f = g) :
    comapEq C h.symm = (comapEq C h).symm := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
β γ : Type w
f g : β → γ
h : f = g
⊢ comapEq C (_ : g = f) = (comapEq C h).symm

Next tactic:
aesop_cat
theorem comapEq_trans {β γ : Type w} {f g h : β → γ} (k : f = g) (l : g = h) :
    comapEq C (k.trans l) = comapEq C k ≪≫ comapEq C l := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
β γ : Type w
f g h : β → γ
k : f = g
l : g = h
⊢ comapEq C (_ : f = h) = comapEq C k ≪≫ comapEq C l

Next tactic:
aesop_cat
@[simp]
theorem eqToHom_apply {β : Type w} {X Y : ∀ _ : β, C} (h : X = Y) (b : β) :
    (eqToHom h : X ⟶ Y) b = eqToHom (by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
β : Type w
X Y : β → C
h : X = Y
b : β
⊢ X b = Y b

Next tactic:
rw [h]
@[simp]
theorem eqToHom_apply {β : Type w} {X Y : ∀ _ : β, C} (h : X = Y) (b : β) :
    (eqToHom h : X ⟶ Y) b = eqToHom (by rw [h]) := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
β : Type w
X Y : β → C
h : X = Y
b : β
⊢ eqToHom h b = eqToHom (_ : X b = Y b)

Next tactic:
subst h
@[simp]
theorem eqToHom_apply {β : Type w} {X Y : ∀ _ : β, C} (h : X = Y) (b : β) :
    (eqToHom h : X ⟶ Y) b = eqToHom (by rw [h]) := by
  subst h
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
β : Type w
X : β → C
b : β
⊢ eqToHom (_ : X = X) b = eqToHom (_ : X b = X b)

Next tactic:
rfl
/-- The equivalence between β-graded objects and γ-graded objects,
given an equivalence between β and γ.
-/
@[simps]
def comapEquiv {β γ : Type w} (e : β ≃ γ) : GradedObject β C ≌ GradedObject γ C where
  functor := comap C (e.symm : γ → β)
  inverse := comap C (e : β → γ)
  counitIso :=
    (Pi.comapComp (fun _ => C) _ _).trans (comapEq C (by ext; simp))
  unitIso :=
    (comapEq C (by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
β γ : Type w
e : β ≃ γ
⊢ (fun i => i) = ⇑e.symm ∘ ⇑e

Next tactic:
ext
/-- The equivalence between β-graded objects and γ-graded objects,
given an equivalence between β and γ.
-/
@[simps]
def comapEquiv {β γ : Type w} (e : β ≃ γ) : GradedObject β C ≌ GradedObject γ C where
  functor := comap C (e.symm : γ → β)
  inverse := comap C (e : β → γ)
  counitIso :=
    (Pi.comapComp (fun _ => C) _ _).trans (comapEq C (by ext; simp))
  unitIso :=
    (comapEq C (by ext; 

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
β γ : Type w
e : β ≃ γ
x✝ : β
⊢ x✝ = (⇑e.symm ∘ ⇑e) x✝

Next tactic:
simp
/-- The equivalence between β-graded objects and γ-graded objects,
given an equivalence between β and γ.
-/
@[simps]
def comapEquiv {β γ : Type w} (e : β ≃ γ) : GradedObject β C ≌ GradedObject γ C where
  functor := comap C (e.symm : γ → β)
  inverse := comap C (e : β → γ)
  counitIso :=
    (Pi.comapComp (fun _ => C) _ _).trans (comapEq C (by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
β γ : Type w
e : β ≃ γ
⊢ ⇑e ∘ ⇑e.symm = fun i => i

Next tactic:
ext
/-- The equivalence between β-graded objects and γ-graded objects,
given an equivalence between β and γ.
-/
@[simps]
def comapEquiv {β γ : Type w} (e : β ≃ γ) : GradedObject β C ≌ GradedObject γ C where
  functor := comap C (e.symm : γ → β)
  inverse := comap C (e : β → γ)
  counitIso :=
    (Pi.comapComp (fun _ => C) _ _).trans (comapEq C (by ext; 

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
β γ : Type w
e : β ≃ γ
x✝ : γ
⊢ (⇑e ∘ ⇑e.symm) x✝ = x✝

Next tactic:
simp
instance hasShift {β : Type*} [AddCommGroup β] (s : β) : HasShift (GradedObjectWithShift s C) ℤ :=
  hasShiftMk _ _
    { F := fun n => comap C fun b : β => b + n • s
      zero := comapEq C (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
β : Type u_1
inst✝ : AddCommGroup β
s : β
⊢ (fun b => b + 0 • s) = id

Next tactic:
aesop_cat
instance hasShift {β : Type*} [AddCommGroup β] (s : β) : HasShift (GradedObjectWithShift s C) ℤ :=
  hasShiftMk _ _
    { F := fun n => comap C fun b : β => b + n • s
      zero := comapEq C (by aesop_cat) ≪≫ Pi.comapId β fun _ => C
      add := fun m n => comapEq C (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
β : Type u_1
inst✝ : AddCommGroup β
s : β
m n : ℤ
⊢ (fun b => b + (m + n) • s) = (fun b => b + m • s) ∘ fun b => b + n • s

Next tactic:
ext
instance hasShift {β : Type*} [AddCommGroup β] (s : β) : HasShift (GradedObjectWithShift s C) ℤ :=
  hasShiftMk _ _
    { F := fun n => comap C fun b : β => b + n • s
      zero := comapEq C (by aesop_cat) ≪≫ Pi.comapId β fun _ => C
      add := fun m n => comapEq C (by ext; 

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
β : Type u_1
inst✝ : AddCommGroup β
s : β
m n : ℤ
x✝ : β
⊢ x✝ + (m + n) • s = ((fun b => b + m • s) ∘ fun b => b + n • s) x✝

Next tactic:
dsimp
instance hasShift {β : Type*} [AddCommGroup β] (s : β) : HasShift (GradedObjectWithShift s C) ℤ :=
  hasShiftMk _ _
    { F := fun n => comap C fun b : β => b + n • s
      zero := comapEq C (by aesop_cat) ≪≫ Pi.comapId β fun _ => C
      add := fun m n => comapEq C (by ext; dsimp; 

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
β : Type u_1
inst✝ : AddCommGroup β
s : β
m n : ℤ
x✝ : β
⊢ x✝ + (m + n) • s = x✝ + n • s + m • s

Next tactic:
rw [add_comm m n, add_zsmul, add_assoc]
instance hasZeroObject [HasZeroObject C] [HasZeroMorphisms C] (β : Type w) :
    HasZeroObject.{max w v} (GradedObject β C) := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
β : Type w
⊢ HasZeroObject (GradedObject β C)

Next tactic:
refine' ⟨⟨fun _ => 0, fun X => ⟨⟨⟨fun b => 0⟩, fun f => _⟩⟩, fun X =>
    ⟨⟨⟨fun b => 0⟩, fun f => _⟩⟩⟩⟩
instance hasZeroObject [HasZeroObject C] [HasZeroMorphisms C] (β : Type w) :
    HasZeroObject.{max w v} (GradedObject β C) := by
  refine' ⟨⟨fun _ => 0, fun X => ⟨⟨⟨fun b => 0⟩, fun f => _⟩⟩, fun X =>
    ⟨⟨⟨fun b => 0⟩, fun f => _⟩⟩⟩⟩ <;> 

Proof state:
case refine'_1
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
β : Type w
X : GradedObject β C
f : (fun x => 0) ⟶ X
⊢ f = default

Next tactic:
aesop_cat
instance hasZeroObject [HasZeroObject C] [HasZeroMorphisms C] (β : Type w) :
    HasZeroObject.{max w v} (GradedObject β C) := by
  refine' ⟨⟨fun _ => 0, fun X => ⟨⟨⟨fun b => 0⟩, fun f => _⟩⟩, fun X =>
    ⟨⟨⟨fun b => 0⟩, fun f => _⟩⟩⟩⟩ <;> 

Proof state:
case refine'_2
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
β : Type w
X : GradedObject β C
f : X ⟶ fun x => 0
⊢ f = default

Next tactic:
aesop_cat
/--
The `total` functor taking a graded object to the coproduct of its graded components is faithful.
To prove this, we need to know that the coprojections into the coproduct are monomorphisms,
which follows from the fact we have zero morphisms and decidable equality for the grading.
-/
instance : Faithful (total β C) where
  map_injective {X Y} f g w := by
    

Proof state:
β : Type
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasCoproducts C
inst✝ : HasZeroMorphisms C
X Y : GradedObject β C
f g : X ⟶ Y
w : (total β C).map f = (total β C).map g
⊢ f = g

Next tactic:
ext i
/--
The `total` functor taking a graded object to the coproduct of its graded components is faithful.
To prove this, we need to know that the coprojections into the coproduct are monomorphisms,
which follows from the fact we have zero morphisms and decidable equality for the grading.
-/
instance : Faithful (total β C) where
  map_injective {X Y} f g w := by
    ext i
    

Proof state:
case h
β : Type
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasCoproducts C
inst✝ : HasZeroMorphisms C
X Y : GradedObject β C
f g : X ⟶ Y
w : (total β C).map f = (total β C).map g
i : β
⊢ f i = g i

Next tactic:
replace w := Sigma.ι (fun i : β => X i) i ≫= w
/--
The `total` functor taking a graded object to the coproduct of its graded components is faithful.
To prove this, we need to know that the coprojections into the coproduct are monomorphisms,
which follows from the fact we have zero morphisms and decidable equality for the grading.
-/
instance : Faithful (total β C) where
  map_injective {X Y} f g w := by
    ext i
    replace w := Sigma.ι (fun i : β => X i) i ≫= w
    

Proof state:
case h
β : Type
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasCoproducts C
inst✝ : HasZeroMorphisms C
X Y : GradedObject β C
f g : X ⟶ Y
i : β
w : Sigma.ι (fun i => X i) i ≫ (total β C).map f = Sigma.ι (fun i => X i) i ≫ (total β C).map g
⊢ f i = g i

Next tactic:
erw [colimit.ι_map, colimit.ι_map] at w
/--
The `total` functor taking a graded object to the coproduct of its graded components is faithful.
To prove this, we need to know that the coprojections into the coproduct are monomorphisms,
which follows from the fact we have zero morphisms and decidable equality for the grading.
-/
instance : Faithful (total β C) where
  map_injective {X Y} f g w := by
    ext i
    replace w := Sigma.ι (fun i : β => X i) i ≫= w
    erw [colimit.ι_map, colimit.ι_map] at w
    

Proof state:
case h
β : Type
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasCoproducts C
inst✝ : HasZeroMorphisms C
X Y : GradedObject β C
f g : X ⟶ Y
i : β
w :
  (Discrete.natTrans fun X => (fun i => f i) X.as).app { as := i } ≫
      colimit.ι (Discrete.functor fun i => Y i) { as := i } =
    (Discrete.natTrans fun X => (fun i => g i) X.as).app { as := i } ≫
      colimit.ι (Discrete.functor fun i => Y i) { as := i }
⊢ f i = g i

Next tactic:
simp? at * says simp only [Discrete.functor_obj, Discrete.natTrans_app] at *
/--
The `total` functor taking a graded object to the coproduct of its graded components is faithful.
To prove this, we need to know that the coprojections into the coproduct are monomorphisms,
which follows from the fact we have zero morphisms and decidable equality for the grading.
-/
instance : Faithful (total β C) where
  map_injective {X Y} f g w := by
    ext i
    replace w := Sigma.ι (fun i : β => X i) i ≫= w
    erw [colimit.ι_map, colimit.ι_map] at w
    simp? at * says 

Proof state:
case h
β : Type
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasCoproducts C
inst✝ : HasZeroMorphisms C
X Y : GradedObject β C
f g : X ⟶ Y
i : β
w :
  (Discrete.natTrans fun X => (fun i => f i) X.as).app { as := i } ≫
      colimit.ι (Discrete.functor fun i => Y i) { as := i } =
    (Discrete.natTrans fun X => (fun i => g i) X.as).app { as := i } ≫
      colimit.ι (Discrete.functor fun i => Y i) { as := i }
⊢ f i = g i

Next tactic:
simp only [Discrete.functor_obj, Discrete.natTrans_app] at *
/--
The `total` functor taking a graded object to the coproduct of its graded components is faithful.
To prove this, we need to know that the coprojections into the coproduct are monomorphisms,
which follows from the fact we have zero morphisms and decidable equality for the grading.
-/
instance : Faithful (total β C) where
  map_injective {X Y} f g w := by
    ext i
    replace w := Sigma.ι (fun i : β => X i) i ≫= w
    erw [colimit.ι_map, colimit.ι_map] at w
    simp? at * says simp only [Discrete.functor_obj, Discrete.natTrans_app] at *
    

Proof state:
case h
β : Type
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasCoproducts C
inst✝ : HasZeroMorphisms C
X Y : GradedObject β C
f g : X ⟶ Y
i : β
w :
  f i ≫ colimit.ι (Discrete.functor fun i => Y i) { as := i } =
    g i ≫ colimit.ι (Discrete.functor fun i => Y i) { as := i }
⊢ f i = g i

Next tactic:
exact Mono.right_cancellation _ _ w
@[reassoc (attr := simp)]
lemma ι_descMapObj {A : C} {j : J}
    (φ : ∀ (i : I) (_ : p i = j), X i ⟶ A) (i : I) (hi : p i = j) :
    X.ιMapObj p i j hi ≫ X.descMapObj p φ = φ i hi := by
  

Proof state:
I : Type u_1
J : Type u_2
C : Type u_3
inst✝³ : Category.{u_4, u_3} C
X Y Z : GradedObject I C
φ✝ : X ⟶ Y
e : X ≅ Y
ψ : Y ⟶ Z
p : I → J
j✝ : J
inst✝² : HasMap X p
inst✝¹ : HasMap Y p
inst✝ : HasMap Z p
A : C
j : J
φ : (i : I) → p i = j → (X i ⟶ A)
i : I
hi : p i = j
⊢ ιMapObj X p i j hi ≫ descMapObj X p φ = φ i hi

Next tactic:
apply Cofan.IsColimit.fac
@[reassoc (attr := simp)]
lemma inj_iso_hom (i : I) (hi : p i = j) :
    c.inj ⟨i, hi⟩ ≫ (c.iso hc).hom = X.ιMapObj p i j hi := by
  

Proof state:
I : Type u_1
J : Type u_2
C : Type u_3
inst✝⁴ : Category.{u_4, u_3} C
X Y Z : GradedObject I C
φ : X ⟶ Y
e : X ≅ Y
ψ : Y ⟶ Z
p : I → J
j : J
inst✝³ : HasMap X p
inst✝² : HasMap Y p
inst✝¹ : HasMap Z p
c : CofanMapObjFun X p j
hc : IsColimit c
inst✝ : HasMap X p
i : I
hi : p i = j
⊢ Cofan.inj c { val := i, property := hi } ≫ (iso hc).hom = ιMapObj X p i j hi

Next tactic:
apply IsColimit.comp_coconePointUniqueUpToIso_hom
@[reassoc (attr := simp)]
lemma ιMapObj_iso_inv (i : I) (hi : p i = j) :
    X.ιMapObj p i j hi ≫ (c.iso hc).inv = c.inj ⟨i, hi⟩ := by
  

Proof state:
I : Type u_1
J : Type u_2
C : Type u_3
inst✝⁴ : Category.{u_4, u_3} C
X Y Z : GradedObject I C
φ : X ⟶ Y
e : X ≅ Y
ψ : Y ⟶ Z
p : I → J
j : J
inst✝³ : HasMap X p
inst✝² : HasMap Y p
inst✝¹ : HasMap Z p
c : CofanMapObjFun X p j
hc : IsColimit c
inst✝ : HasMap X p
i : I
hi : p i = j
⊢ ιMapObj X p i j hi ≫ (iso hc).inv = Cofan.inj c { val := i, property := hi }

Next tactic:
apply IsColimit.comp_coconePointUniqueUpToIso_inv
@[reassoc (attr := simp)]
lemma ι_mapMap (i : I) (j : J) (hij : p i = j) :
    X.ιMapObj p i j hij ≫ mapMap φ p j = φ i ≫ Y.ιMapObj p i j hij := by
  

Proof state:
I : Type u_1
J : Type u_2
C : Type u_3
inst✝³ : Category.{u_4, u_3} C
X Y Z : GradedObject I C
φ : X ⟶ Y
e : X ≅ Y
ψ : Y ⟶ Z
p : I → J
j✝ : J
inst✝² : HasMap X p
inst✝¹ : HasMap Y p
inst✝ : HasMap Z p
i : I
j : J
hij : p i = j
⊢ ιMapObj X p i j hij ≫ mapMap φ p j = φ i ≫ ιMapObj Y p i j hij

Next tactic:
simp only [mapMap, ι_descMapObj]
lemma congr_mapMap (φ₁ φ₂ : X ⟶ Y) (h : φ₁ = φ₂) : mapMap φ₁ p = mapMap φ₂ p := by
  

Proof state:
I : Type u_1
J : Type u_2
C : Type u_3
inst✝³ : Category.{u_4, u_3} C
X Y Z : GradedObject I C
φ : X ⟶ Y
e : X ≅ Y
ψ : Y ⟶ Z
p : I → J
j : J
inst✝² : HasMap X p
inst✝¹ : HasMap Y p
inst✝ : HasMap Z p
φ₁ φ₂ : X ⟶ Y
h : φ₁ = φ₂
⊢ mapMap φ₁ p = mapMap φ₂ p

Next tactic:
subst h
lemma congr_mapMap (φ₁ φ₂ : X ⟶ Y) (h : φ₁ = φ₂) : mapMap φ₁ p = mapMap φ₂ p := by
  subst h
  

Proof state:
I : Type u_1
J : Type u_2
C : Type u_3
inst✝³ : Category.{u_4, u_3} C
X Y Z : GradedObject I C
φ : X ⟶ Y
e : X ≅ Y
ψ : Y ⟶ Z
p : I → J
j : J
inst✝² : HasMap X p
inst✝¹ : HasMap Y p
inst✝ : HasMap Z p
φ₁ : X ⟶ Y
⊢ mapMap φ₁ p = mapMap φ₁ p

Next tactic:
rfl
@[simp]
lemma mapMap_id : mapMap (𝟙 X) p = 𝟙 _ := by 

Proof state:
I : Type u_1
J : Type u_2
C : Type u_3
inst✝³ : Category.{u_4, u_3} C
X Y Z : GradedObject I C
φ : X ⟶ Y
e : X ≅ Y
ψ : Y ⟶ Z
p : I → J
j : J
inst✝² : HasMap X p
inst✝¹ : HasMap Y p
inst✝ : HasMap Z p
⊢ mapMap (𝟙 X) p = 𝟙 (mapObj X p)

Next tactic:
aesop_cat
@[simp, reassoc]
lemma mapMap_comp : mapMap (φ ≫ ψ) p = mapMap φ p ≫ mapMap ψ p := by 

Proof state:
I : Type u_1
J : Type u_2
C : Type u_3
inst✝³ : Category.{u_4, u_3} C
X Y Z : GradedObject I C
φ : X ⟶ Y
e : X ≅ Y
ψ : Y ⟶ Z
p : I → J
j : J
inst✝² : HasMap X p
inst✝¹ : HasMap Y p
inst✝ : HasMap Z p
⊢ mapMap (φ ≫ ψ) p = mapMap φ p ≫ mapMap ψ p

Next tactic:
aesop_cat
theorem doset_eq_of_mem {H K : Subgroup G} {a b : G} (hb : b ∈ doset a H K) :
    doset b H K = doset a H K := by
  

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b : G
hb : b ∈ doset a ↑H ↑K
⊢ doset b ↑H ↑K = doset a ↑H ↑K

Next tactic:
obtain ⟨_, k, ⟨h, a, hh, rfl : _ = _, rfl⟩, hk, rfl⟩ := hb
theorem doset_eq_of_mem {H K : Subgroup G} {a b : G} (hb : b ∈ doset a H K) :
    doset b H K = doset a H K := by
  obtain ⟨_, k, ⟨h, a, hh, rfl : _ = _, rfl⟩, hk, rfl⟩ := hb
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
k h a : G
hh : h ∈ ↑H
hk : k ∈ ↑K
⊢ doset ((fun x x_1 => x * x_1) ((fun x x_1 => x * x_1) h a) k) ↑H ↑K = doset a ↑H ↑K

Next tactic:
rw [doset, doset, ← Set.singleton_mul_singleton, ← Set.singleton_mul_singleton, mul_assoc,
    mul_assoc, Subgroup.singleton_mul_subgroup hk, ← mul_assoc, ← mul_assoc,
    Subgroup.subgroup_mul_singleton hh]
theorem mem_doset_of_not_disjoint {H K : Subgroup G} {a b : G}
    (h : ¬Disjoint (doset a H K) (doset b H K)) : b ∈ doset a H K := by
  

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b : G
h : ¬Disjoint (doset a ↑H ↑K) (doset b ↑H ↑K)
⊢ b ∈ doset a ↑H ↑K

Next tactic:
rw [Set.not_disjoint_iff] at h
theorem mem_doset_of_not_disjoint {H K : Subgroup G} {a b : G}
    (h : ¬Disjoint (doset a H K) (doset b H K)) : b ∈ doset a H K := by
  rw [Set.not_disjoint_iff] at h
  

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b : G
h : ∃ x ∈ doset a ↑H ↑K, x ∈ doset b ↑H ↑K
⊢ b ∈ doset a ↑H ↑K

Next tactic:
simp only [mem_doset] at *
theorem mem_doset_of_not_disjoint {H K : Subgroup G} {a b : G}
    (h : ¬Disjoint (doset a H K) (doset b H K)) : b ∈ doset a H K := by
  rw [Set.not_disjoint_iff] at h
  simp only [mem_doset] at *
  

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b : G
h : ∃ x, (∃ x_1 ∈ ↑H, ∃ y ∈ ↑K, x = x_1 * a * y) ∧ ∃ x_1 ∈ ↑H, ∃ y ∈ ↑K, x = x_1 * b * y
⊢ ∃ x ∈ ↑H, ∃ y ∈ ↑K, b = x * a * y

Next tactic:
obtain ⟨x, ⟨l, hl, r, hr, hrx⟩, y, hy, ⟨r', hr', rfl⟩⟩ := h
theorem mem_doset_of_not_disjoint {H K : Subgroup G} {a b : G}
    (h : ¬Disjoint (doset a H K) (doset b H K)) : b ∈ doset a H K := by
  rw [Set.not_disjoint_iff] at h
  simp only [mem_doset] at *
  obtain ⟨x, ⟨l, hl, r, hr, hrx⟩, y, hy, ⟨r', hr', rfl⟩⟩ := h
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b l : G
hl : l ∈ ↑H
r : G
hr : r ∈ ↑K
y : G
hy : y ∈ ↑H
r' : G
hr' : r' ∈ ↑K
hrx : y * b * r' = l * a * r
⊢ ∃ x ∈ ↑H, ∃ y ∈ ↑K, b = x * a * y

Next tactic:
refine' ⟨y⁻¹ * l, H.mul_mem (H.inv_mem hy) hl, r * r'⁻¹, K.mul_mem hr (K.inv_mem hr'), _⟩
theorem mem_doset_of_not_disjoint {H K : Subgroup G} {a b : G}
    (h : ¬Disjoint (doset a H K) (doset b H K)) : b ∈ doset a H K := by
  rw [Set.not_disjoint_iff] at h
  simp only [mem_doset] at *
  obtain ⟨x, ⟨l, hl, r, hr, hrx⟩, y, hy, ⟨r', hr', rfl⟩⟩ := h
  refine' ⟨y⁻¹ * l, H.mul_mem (H.inv_mem hy) hl, r * r'⁻¹, K.mul_mem hr (K.inv_mem hr'), _⟩
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b l : G
hl : l ∈ ↑H
r : G
hr : r ∈ ↑K
y : G
hy : y ∈ ↑H
r' : G
hr' : r' ∈ ↑K
hrx : y * b * r' = l * a * r
⊢ b = y⁻¹ * l * a * (r * r'⁻¹)

Next tactic:
rwa [mul_assoc, mul_assoc, eq_inv_mul_iff_mul_eq, ← mul_assoc, ← mul_assoc, eq_mul_inv_iff_mul_eq]
theorem eq_of_not_disjoint {H K : Subgroup G} {a b : G}
    (h : ¬Disjoint (doset a H K) (doset b H K)) : doset a H K = doset b H K := by
  

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b : G
h : ¬Disjoint (doset a ↑H ↑K) (doset b ↑H ↑K)
⊢ doset a ↑H ↑K = doset b ↑H ↑K

Next tactic:
rw [disjoint_comm] at h
theorem eq_of_not_disjoint {H K : Subgroup G} {a b : G}
    (h : ¬Disjoint (doset a H K) (doset b H K)) : doset a H K = doset b H K := by
  rw [disjoint_comm] at h
  

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b : G
h : ¬Disjoint (doset b ↑H ↑K) (doset a ↑H ↑K)
⊢ doset a ↑H ↑K = doset b ↑H ↑K

Next tactic:
have ha : a ∈ doset b H K := mem_doset_of_not_disjoint h
theorem eq_of_not_disjoint {H K : Subgroup G} {a b : G}
    (h : ¬Disjoint (doset a H K) (doset b H K)) : doset a H K = doset b H K := by
  rw [disjoint_comm] at h
  have ha : a ∈ doset b H K := mem_doset_of_not_disjoint h
  

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H K : Subgroup G
a b : G
h : ¬Disjoint (doset b ↑H ↑K) (doset a ↑H ↑K)
ha : a ∈ doset b ↑H ↑K
⊢ doset a ↑H ↑K = doset b ↑H ↑K

Next tactic:
apply doset_eq_of_mem ha
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
⊢ Setoid.Rel (setoid ↑⊥ ↑H) = Setoid.Rel (QuotientGroup.leftRel H)

Next tactic:
ext a b
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  ext a b
  

Proof state:
case h.h.a
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
a b : G
⊢ Setoid.Rel (setoid ↑⊥ ↑H) a b ↔ Setoid.Rel (QuotientGroup.leftRel H) a b

Next tactic:
rw [rel_iff, Setoid.Rel, QuotientGroup.leftRel_apply]
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  ext a b
  rw [rel_iff, Setoid.Rel, QuotientGroup.leftRel_apply]
  

Proof state:
case h.h.a
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
a b : G
⊢ (∃ a_1 ∈ ⊥, ∃ b_1 ∈ H, b = a_1 * a * b_1) ↔ a⁻¹ * b ∈ H

Next tactic:
constructor
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  ext a b
  rw [rel_iff, Setoid.Rel, QuotientGroup.leftRel_apply]
  constructor
  · 

Proof state:
case h.h.a.mp
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
a b : G
⊢ (∃ a_1 ∈ ⊥, ∃ b_1 ∈ H, b = a_1 * a * b_1) → a⁻¹ * b ∈ H

Next tactic:
rintro ⟨a, rfl : a = 1, b, hb, rfl⟩
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  ext a b
  rw [rel_iff, Setoid.Rel, QuotientGroup.leftRel_apply]
  constructor
  · rintro ⟨a, rfl : a = 1, b, hb, rfl⟩
    

Proof state:
case h.h.a.mp.intro.intro.intro.intro
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
a b : G
hb : b ∈ H
⊢ a⁻¹ * (1 * a * b) ∈ H

Next tactic:
change a⁻¹ * (1 * a * b) ∈ H
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  ext a b
  rw [rel_iff, Setoid.Rel, QuotientGroup.leftRel_apply]
  constructor
  · rintro ⟨a, rfl : a = 1, b, hb, rfl⟩
    change a⁻¹ * (1 * a * b) ∈ H
    

Proof state:
case h.h.a.mp.intro.intro.intro.intro
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
a b : G
hb : b ∈ H
⊢ a⁻¹ * (1 * a * b) ∈ H

Next tactic:
rwa [one_mul, inv_mul_cancel_left]
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  ext a b
  rw [rel_iff, Setoid.Rel, QuotientGroup.leftRel_apply]
  constructor
  · rintro ⟨a, rfl : a = 1, b, hb, rfl⟩
    change a⁻¹ * (1 * a * b) ∈ H
    rwa [one_mul, inv_mul_cancel_left]
  · 

Proof state:
case h.h.a.mpr
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
a b : G
⊢ a⁻¹ * b ∈ H → ∃ a_2 ∈ ⊥, ∃ b_1 ∈ H, b = a_2 * a * b_1

Next tactic:
rintro (h : a⁻¹ * b ∈ H)
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  ext a b
  rw [rel_iff, Setoid.Rel, QuotientGroup.leftRel_apply]
  constructor
  · rintro ⟨a, rfl : a = 1, b, hb, rfl⟩
    change a⁻¹ * (1 * a * b) ∈ H
    rwa [one_mul, inv_mul_cancel_left]
  · rintro (h : a⁻¹ * b ∈ H)
    

Proof state:
case h.h.a.mpr
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
a b : G
h : a⁻¹ * b ∈ H
⊢ ∃ a_1 ∈ ⊥, ∃ b_1 ∈ H, b = a_1 * a * b_1

Next tactic:
exact ⟨1, rfl, a⁻¹ * b, h, by rw [one_mul, mul_inv_cancel_left]⟩
theorem bot_rel_eq_leftRel (H : Subgroup G) :
    (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by
  ext a b
  rw [rel_iff, Setoid.Rel, QuotientGroup.leftRel_apply]
  constructor
  · rintro ⟨a, rfl : a = 1, b, hb, rfl⟩
    change a⁻¹ * (1 * a * b) ∈ H
    rwa [one_mul, inv_mul_cancel_left]
  · rintro (h : a⁻¹ * b ∈ H)
    exact ⟨1, rfl, a⁻¹ * b, h, by 

Proof state:
G : Type u_1
inst✝¹ : Group G
α : Type u_2
inst✝ : Mul α
J : Subgroup G
g : G
H : Subgroup G
a b : G
h : a⁻¹ * b ∈ H
⊢ b = 1 * a * (a⁻¹ * b)

Next tactic:
rw [one_mul, mul_inv_cancel_left]