l3lab/ntp-mathlib huggingface dataset:
theorem IsNormal.conj' {S : Subgroupoid C} (Sn : IsNormal S) :
    ∀ {c d} (p : d ⟶ c) {γ : c ⟶ c}, γ ∈ S.arrows c c → p ≫ γ ≫ Groupoid.inv p ∈ S.arrows d d :=
  fun p γ hs => by 

Proof state:
C : Type u
inst✝ : Groupoid C
S✝ S : Subgroupoid C
Sn : IsNormal S
c✝ d✝ : C
p : d✝ ⟶ c✝
γ : c✝ ⟶ c✝
hs : γ ∈ arrows S c✝ c✝
⊢ p ≫ γ ≫ Groupoid.inv p ∈ arrows S d✝ d✝

Next tactic:
convert Sn.conj (Groupoid.inv p) hs
theorem IsNormal.conj' {S : Subgroupoid C} (Sn : IsNormal S) :
    ∀ {c d} (p : d ⟶ c) {γ : c ⟶ c}, γ ∈ S.arrows c c → p ≫ γ ≫ Groupoid.inv p ∈ S.arrows d d :=
  fun p γ hs => by convert Sn.conj (Groupoid.inv p) hs; 

Proof state:
case h.e'_4.h.e'_6
C : Type u
inst✝ : Groupoid C
S✝ S : Subgroupoid C
Sn : IsNormal S
c✝ d✝ : C
p : d✝ ⟶ c✝
γ : c✝ ⟶ c✝
hs : γ ∈ arrows S c✝ c✝
⊢ p = Groupoid.inv (Groupoid.inv p)

Next tactic:
simp
theorem IsNormal.conjugation_bij (Sn : IsNormal S) {c d} (p : c ⟶ d) :
    Set.BijOn (fun γ : c ⟶ c => Groupoid.inv p ≫ γ ≫ p) (S.arrows c c) (S.arrows d d) := by
  

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
Sn : IsNormal S
c d : C
p : c ⟶ d
⊢ BijOn (fun γ => Groupoid.inv p ≫ γ ≫ p) (arrows S c c) (arrows S d d)

Next tactic:
refine' ⟨fun γ γS => Sn.conj p γS, fun γ₁ _ γ₂ _ h => _, fun δ δS =>
    ⟨p ≫ δ ≫ Groupoid.inv p, Sn.conj' p δS, _⟩⟩
theorem IsNormal.conjugation_bij (Sn : IsNormal S) {c d} (p : c ⟶ d) :
    Set.BijOn (fun γ : c ⟶ c => Groupoid.inv p ≫ γ ≫ p) (S.arrows c c) (S.arrows d d) := by
  refine' ⟨fun γ γS => Sn.conj p γS, fun γ₁ _ γ₂ _ h => _, fun δ δS =>
    ⟨p ≫ δ ≫ Groupoid.inv p, Sn.conj' p δS, _⟩⟩
  · 

Proof state:
case refine'_1
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
Sn : IsNormal S
c d : C
p : c ⟶ d
γ₁ : c ⟶ c
x✝¹ : γ₁ ∈ arrows S c c
γ₂ : c ⟶ c
x✝ : γ₂ ∈ arrows S c c
h : (fun γ => Groupoid.inv p ≫ γ ≫ p) γ₁ = (fun γ => Groupoid.inv p ≫ γ ≫ p) γ₂
⊢ γ₁ = γ₂

Next tactic:
simpa only [inv_eq_inv, Category.assoc, IsIso.hom_inv_id, Category.comp_id,
      IsIso.hom_inv_id_assoc] using p ≫= h =≫ inv p
theorem IsNormal.conjugation_bij (Sn : IsNormal S) {c d} (p : c ⟶ d) :
    Set.BijOn (fun γ : c ⟶ c => Groupoid.inv p ≫ γ ≫ p) (S.arrows c c) (S.arrows d d) := by
  refine' ⟨fun γ γS => Sn.conj p γS, fun γ₁ _ γ₂ _ h => _, fun δ δS =>
    ⟨p ≫ δ ≫ Groupoid.inv p, Sn.conj' p δS, _⟩⟩
  · simpa only [inv_eq_inv, Category.assoc, IsIso.hom_inv_id, Category.comp_id,
      IsIso.hom_inv_id_assoc] using p ≫= h =≫ inv p
  · 

Proof state:
case refine'_2
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
Sn : IsNormal S
c d : C
p : c ⟶ d
δ : d ⟶ d
δS : δ ∈ arrows S d d
⊢ (fun γ => Groupoid.inv p ≫ γ ≫ p) (p ≫ δ ≫ Groupoid.inv p) = δ

Next tactic:
simp only [inv_eq_inv, Category.assoc, IsIso.inv_hom_id, Category.comp_id,
      IsIso.inv_hom_id_assoc]
theorem sInf_isNormal (s : Set <| Subgroupoid C) (sn : ∀ S ∈ s, IsNormal S) : IsNormal (sInf s) :=
  { wide := by 

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
s : Set (Subgroupoid C)
sn : ∀ S ∈ s, IsNormal S
⊢ ∀ (c : C), 𝟙 c ∈ arrows (sInf s) c c

Next tactic:
simp_rw [sInf, mem_iInter₂]
theorem sInf_isNormal (s : Set <| Subgroupoid C) (sn : ∀ S ∈ s, IsNormal S) : IsNormal (sInf s) :=
  { wide := by simp_rw [sInf, mem_iInter₂]; 

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
s : Set (Subgroupoid C)
sn : ∀ S ∈ s, IsNormal S
⊢ ∀ (c : C), ∀ i ∈ s, 𝟙 c ∈ arrows i c c

Next tactic:
exact fun c S Ss => (sn S Ss).wide c
theorem sInf_isNormal (s : Set <| Subgroupoid C) (sn : ∀ S ∈ s, IsNormal S) : IsNormal (sInf s) :=
  { wide := by simp_rw [sInf, mem_iInter₂]; exact fun c S Ss => (sn S Ss).wide c
    conj := by 

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
s : Set (Subgroupoid C)
sn : ∀ S ∈ s, IsNormal S
⊢ ∀ {c d : C} (p : c ⟶ d) {γ : c ⟶ c}, γ ∈ arrows (sInf s) c c → Groupoid.inv p ≫ γ ≫ p ∈ arrows (sInf s) d d

Next tactic:
simp_rw [sInf, mem_iInter₂]
theorem sInf_isNormal (s : Set <| Subgroupoid C) (sn : ∀ S ∈ s, IsNormal S) : IsNormal (sInf s) :=
  { wide := by simp_rw [sInf, mem_iInter₂]; exact fun c S Ss => (sn S Ss).wide c
    conj := by simp_rw [sInf, mem_iInter₂]; 

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
s : Set (Subgroupoid C)
sn : ∀ S ∈ s, IsNormal S
⊢ ∀ {c d : C} (p : c ⟶ d) {γ : c ⟶ c}, (∀ i ∈ s, γ ∈ arrows i c c) → ∀ i ∈ s, Groupoid.inv p ≫ γ ≫ p ∈ arrows i d d

Next tactic:
exact fun p γ hγ S Ss => (sn S Ss).conj p (hγ S Ss)
theorem discrete_isNormal : (@discrete C _).IsNormal :=
  { wide := fun c => by 

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
c : C
⊢ 𝟙 c ∈ arrows discrete c c

Next tactic:
constructor
theorem discrete_isNormal : (@discrete C _).IsNormal :=
  { wide := fun c => by constructor
    conj := fun f γ hγ => by
      

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
c✝ d✝ : C
f : c✝ ⟶ d✝
γ : c✝ ⟶ c✝
hγ : γ ∈ arrows discrete c✝ c✝
⊢ Groupoid.inv f ≫ γ ≫ f ∈ arrows discrete d✝ d✝

Next tactic:
cases hγ
theorem discrete_isNormal : (@discrete C _).IsNormal :=
  { wide := fun c => by constructor
    conj := fun f γ hγ => by
      cases hγ
      

Proof state:
case id
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
c✝ d✝ : C
f : c✝ ⟶ d✝
⊢ Groupoid.inv f ≫ 𝟙 c✝ ≫ f ∈ arrows discrete d✝ d✝

Next tactic:
simp only [inv_eq_inv, Category.id_comp, IsIso.inv_hom_id]
theorem discrete_isNormal : (@discrete C _).IsNormal :=
  { wide := fun c => by constructor
    conj := fun f γ hγ => by
      cases hγ
      simp only [inv_eq_inv, Category.id_comp, IsIso.inv_hom_id]; 

Proof state:
case id
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
c✝ d✝ : C
f : c✝ ⟶ d✝
⊢ 𝟙 d✝ ∈ arrows discrete d✝ d✝

Next tactic:
constructor
theorem IsNormal.vertexSubgroup (Sn : IsNormal S) (c : C) (cS : c ∈ S.objs) :
    (S.vertexSubgroup cS).Normal where
  conj_mem x hx y := by 

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
Sn : IsNormal S
c : C
cS : c ∈ objs S
x : c ⟶ c
hx : x ∈ Subgroupoid.vertexSubgroup S cS
y : c ⟶ c
⊢ y * x * y⁻¹ ∈ Subgroupoid.vertexSubgroup S cS

Next tactic:
rw [mul_assoc]
theorem IsNormal.vertexSubgroup (Sn : IsNormal S) (c : C) (cS : c ∈ S.objs) :
    (S.vertexSubgroup cS).Normal where
  conj_mem x hx y := by rw [mul_assoc]; 

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
Sn : IsNormal S
c : C
cS : c ∈ objs S
x : c ⟶ c
hx : x ∈ Subgroupoid.vertexSubgroup S cS
y : c ⟶ c
⊢ y * (x * y⁻¹) ∈ Subgroupoid.vertexSubgroup S cS

Next tactic:
exact Sn.conj' y hx
theorem subset_generated (c d : C) : X c d ⊆ (generated X).arrows c d := by
  

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
c d : C
⊢ X c d ⊆ arrows (generated X) c d

Next tactic:
dsimp only [generated, sInf]
theorem subset_generated (c d : C) : X c d ⊆ (generated X).arrows c d := by
  dsimp only [generated, sInf]
  

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
c d : C
⊢ X c d ⊆ ⋂ S ∈ {S | ∀ (c d : C), X c d ⊆ arrows S c d}, arrows S c d

Next tactic:
simp only [subset_iInter₂_iff]
theorem subset_generated (c d : C) : X c d ⊆ (generated X).arrows c d := by
  dsimp only [generated, sInf]
  simp only [subset_iInter₂_iff]
  

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
c d : C
⊢ ∀ i ∈ {S | ∀ (c d : C), X c d ⊆ arrows S c d}, X c d ⊆ arrows i c d

Next tactic:
exact fun S hS f fS => hS _ _ fS
theorem generated_le_generatedNormal : generated X ≤ generatedNormal X := by
  

Proof state:
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
⊢ generated X ≤ generatedNormal X

Next tactic:
apply @sInf_le_sInf (Subgroupoid C) _
theorem generated_le_generatedNormal : generated X ≤ generatedNormal X := by
  apply @sInf_le_sInf (Subgroupoid C) _
  

Proof state:
case h
C : Type u
inst✝ : Groupoid C
S : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
⊢ {S | (∀ (c d : C), X c d ⊆ arrows S c d) ∧ IsNormal S} ⊆ {S | ∀ (c d : C), X c d ⊆ arrows S c d}

Next tactic:
exact fun S ⟨h, _⟩ => h
theorem IsNormal.generatedNormal_le {S : Subgroupoid C} (Sn : S.IsNormal) :
    generatedNormal X ≤ S ↔ ∀ c d, X c d ⊆ S.arrows c d := by
  

Proof state:
C : Type u
inst✝ : Groupoid C
S✝ : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
S : Subgroupoid C
Sn : IsNormal S
⊢ generatedNormal X ≤ S ↔ ∀ (c d : C), X c d ⊆ arrows S c d

Next tactic:
constructor
theorem IsNormal.generatedNormal_le {S : Subgroupoid C} (Sn : S.IsNormal) :
    generatedNormal X ≤ S ↔ ∀ c d, X c d ⊆ S.arrows c d := by
  constructor
  · 

Proof state:
case mp
C : Type u
inst✝ : Groupoid C
S✝ : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
S : Subgroupoid C
Sn : IsNormal S
⊢ generatedNormal X ≤ S → ∀ (c d : C), X c d ⊆ arrows S c d

Next tactic:
rintro h c d
theorem IsNormal.generatedNormal_le {S : Subgroupoid C} (Sn : S.IsNormal) :
    generatedNormal X ≤ S ↔ ∀ c d, X c d ⊆ S.arrows c d := by
  constructor
  · rintro h c d
    

Proof state:
case mp
C : Type u
inst✝ : Groupoid C
S✝ : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
S : Subgroupoid C
Sn : IsNormal S
h : generatedNormal X ≤ S
c d : C
⊢ X c d ⊆ arrows S c d

Next tactic:
have h' := generated_le_generatedNormal X
theorem IsNormal.generatedNormal_le {S : Subgroupoid C} (Sn : S.IsNormal) :
    generatedNormal X ≤ S ↔ ∀ c d, X c d ⊆ S.arrows c d := by
  constructor
  · rintro h c d
    have h' := generated_le_generatedNormal X
    

Proof state:
case mp
C : Type u
inst✝ : Groupoid C
S✝ : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
S : Subgroupoid C
Sn : IsNormal S
h : generatedNormal X ≤ S
c d : C
h' : generated X ≤ generatedNormal X
⊢ X c d ⊆ arrows S c d

Next tactic:
rw [le_iff] at h h'
theorem IsNormal.generatedNormal_le {S : Subgroupoid C} (Sn : S.IsNormal) :
    generatedNormal X ≤ S ↔ ∀ c d, X c d ⊆ S.arrows c d := by
  constructor
  · rintro h c d
    have h' := generated_le_generatedNormal X
    rw [le_iff] at h h'
    

Proof state:
case mp
C : Type u
inst✝ : Groupoid C
S✝ : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
S : Subgroupoid C
Sn : IsNormal S
h : ∀ {c d : C}, arrows (generatedNormal X) c d ⊆ arrows S c d
c d : C
h' : ∀ {c d : C}, arrows (generated X) c d ⊆ arrows (generatedNormal X) c d
⊢ X c d ⊆ arrows S c d

Next tactic:
exact ((subset_generated X c d).trans (@h' c d)).trans (@h c d)
theorem IsNormal.generatedNormal_le {S : Subgroupoid C} (Sn : S.IsNormal) :
    generatedNormal X ≤ S ↔ ∀ c d, X c d ⊆ S.arrows c d := by
  constructor
  · rintro h c d
    have h' := generated_le_generatedNormal X
    rw [le_iff] at h h'
    exact ((subset_generated X c d).trans (@h' c d)).trans (@h c d)
  · 

Proof state:
case mpr
C : Type u
inst✝ : Groupoid C
S✝ : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
S : Subgroupoid C
Sn : IsNormal S
⊢ (∀ (c d : C), X c d ⊆ arrows S c d) → generatedNormal X ≤ S

Next tactic:
rintro h
theorem IsNormal.generatedNormal_le {S : Subgroupoid C} (Sn : S.IsNormal) :
    generatedNormal X ≤ S ↔ ∀ c d, X c d ⊆ S.arrows c d := by
  constructor
  · rintro h c d
    have h' := generated_le_generatedNormal X
    rw [le_iff] at h h'
    exact ((subset_generated X c d).trans (@h' c d)).trans (@h c d)
  · rintro h
    

Proof state:
case mpr
C : Type u
inst✝ : Groupoid C
S✝ : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
S : Subgroupoid C
Sn : IsNormal S
h : ∀ (c d : C), X c d ⊆ arrows S c d
⊢ generatedNormal X ≤ S

Next tactic:
apply @sInf_le (Subgroupoid C) _
theorem IsNormal.generatedNormal_le {S : Subgroupoid C} (Sn : S.IsNormal) :
    generatedNormal X ≤ S ↔ ∀ c d, X c d ⊆ S.arrows c d := by
  constructor
  · rintro h c d
    have h' := generated_le_generatedNormal X
    rw [le_iff] at h h'
    exact ((subset_generated X c d).trans (@h' c d)).trans (@h c d)
  · rintro h
    apply @sInf_le (Subgroupoid C) _
    

Proof state:
case mpr.a
C : Type u
inst✝ : Groupoid C
S✝ : Subgroupoid C
X : (c d : C) → Set (c ⟶ d)
S : Subgroupoid C
Sn : IsNormal S
h : ∀ (c d : C), X c d ⊆ arrows S c d
⊢ S ∈ {S | (∀ (c d : C), X c d ⊆ arrows S c d) ∧ IsNormal S}

Next tactic:
exact ⟨h, Sn⟩
/-- A functor between groupoid defines a map of subgroupoids in the reverse direction
by taking preimages.
 -/
def comap (S : Subgroupoid D) : Subgroupoid C where
  arrows c d := {f : c ⟶ d | φ.map f ∈ S.arrows (φ.obj c) (φ.obj d)}
  inv hp := by 

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
c✝ d✝ : C
p✝ : c✝ ⟶ d✝
hp : p✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c✝ d✝
⊢ Groupoid.inv p✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) d✝ c✝

Next tactic:
rw [mem_setOf, inv_eq_inv, φ.map_inv, ← inv_eq_inv]
/-- A functor between groupoid defines a map of subgroupoids in the reverse direction
by taking preimages.
 -/
def comap (S : Subgroupoid D) : Subgroupoid C where
  arrows c d := {f : c ⟶ d | φ.map f ∈ S.arrows (φ.obj c) (φ.obj d)}
  inv hp := by rw [mem_setOf, inv_eq_inv, φ.map_inv, ← inv_eq_inv]; 

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
c✝ d✝ : C
p✝ : c✝ ⟶ d✝
hp : p✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c✝ d✝
⊢ Groupoid.inv (φ.map p✝) ∈ arrows S (φ.obj d✝) (φ.obj c✝)

Next tactic:
exact S.inv hp
/-- A functor between groupoid defines a map of subgroupoids in the reverse direction
by taking preimages.
 -/
def comap (S : Subgroupoid D) : Subgroupoid C where
  arrows c d := {f : c ⟶ d | φ.map f ∈ S.arrows (φ.obj c) (φ.obj d)}
  inv hp := by rw [mem_setOf, inv_eq_inv, φ.map_inv, ← inv_eq_inv]; exact S.inv hp
  mul := by
    

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
⊢ ∀ {c d e : C} {p : c ⟶ d},
    p ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c d →
      ∀ {q : d ⟶ e},
        q ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) d e →
          p ≫ q ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c e

Next tactic:
intros
/-- A functor between groupoid defines a map of subgroupoids in the reverse direction
by taking preimages.
 -/
def comap (S : Subgroupoid D) : Subgroupoid C where
  arrows c d := {f : c ⟶ d | φ.map f ∈ S.arrows (φ.obj c) (φ.obj d)}
  inv hp := by rw [mem_setOf, inv_eq_inv, φ.map_inv, ← inv_eq_inv]; exact S.inv hp
  mul := by
    intros
    

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
c✝ d✝ e✝ : C
p✝ : c✝ ⟶ d✝
a✝¹ : p✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c✝ d✝
q✝ : d✝ ⟶ e✝
a✝ : q✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) d✝ e✝
⊢ p✝ ≫ q✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c✝ e✝

Next tactic:
simp only [mem_setOf, Functor.map_comp]
/-- A functor between groupoid defines a map of subgroupoids in the reverse direction
by taking preimages.
 -/
def comap (S : Subgroupoid D) : Subgroupoid C where
  arrows c d := {f : c ⟶ d | φ.map f ∈ S.arrows (φ.obj c) (φ.obj d)}
  inv hp := by rw [mem_setOf, inv_eq_inv, φ.map_inv, ← inv_eq_inv]; exact S.inv hp
  mul := by
    intros
    simp only [mem_setOf, Functor.map_comp]
    

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
c✝ d✝ e✝ : C
p✝ : c✝ ⟶ d✝
a✝¹ : p✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c✝ d✝
q✝ : d✝ ⟶ e✝
a✝ : q✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) d✝ e✝
⊢ φ.map p✝ ≫ φ.map q✝ ∈ arrows S (φ.obj c✝) (φ.obj e✝)

Next tactic:
apply S.mul
/-- A functor between groupoid defines a map of subgroupoids in the reverse direction
by taking preimages.
 -/
def comap (S : Subgroupoid D) : Subgroupoid C where
  arrows c d := {f : c ⟶ d | φ.map f ∈ S.arrows (φ.obj c) (φ.obj d)}
  inv hp := by rw [mem_setOf, inv_eq_inv, φ.map_inv, ← inv_eq_inv]; exact S.inv hp
  mul := by
    intros
    simp only [mem_setOf, Functor.map_comp]
    apply S.mul <;> 

Proof state:
case a
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
c✝ d✝ e✝ : C
p✝ : c✝ ⟶ d✝
a✝¹ : p✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c✝ d✝
q✝ : d✝ ⟶ e✝
a✝ : q✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) d✝ e✝
⊢ φ.map p✝ ∈ arrows S (φ.obj c✝) (φ.obj d✝)

Next tactic:
assumption
/-- A functor between groupoid defines a map of subgroupoids in the reverse direction
by taking preimages.
 -/
def comap (S : Subgroupoid D) : Subgroupoid C where
  arrows c d := {f : c ⟶ d | φ.map f ∈ S.arrows (φ.obj c) (φ.obj d)}
  inv hp := by rw [mem_setOf, inv_eq_inv, φ.map_inv, ← inv_eq_inv]; exact S.inv hp
  mul := by
    intros
    simp only [mem_setOf, Functor.map_comp]
    apply S.mul <;> 

Proof state:
case a
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
c✝ d✝ e✝ : C
p✝ : c✝ ⟶ d✝
a✝¹ : p✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) c✝ d✝
q✝ : d✝ ⟶ e✝
a✝ : q✝ ∈ (fun c d => {f | φ.map f ∈ arrows S (φ.obj c) (φ.obj d)}) d✝ e✝
⊢ φ.map q✝ ∈ arrows S (φ.obj d✝) (φ.obj e✝)

Next tactic:
assumption
theorem isNormal_comap {S : Subgroupoid D} (Sn : IsNormal S) : IsNormal (comap φ S) where
  wide c := by 

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
Sn : IsNormal S
c : C
⊢ 𝟙 c ∈ arrows (comap φ S) c c

Next tactic:
rw [comap, mem_setOf, Functor.map_id]
theorem isNormal_comap {S : Subgroupoid D} (Sn : IsNormal S) : IsNormal (comap φ S) where
  wide c := by rw [comap, mem_setOf, Functor.map_id]; 

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
Sn : IsNormal S
c : C
⊢ 𝟙 (φ.obj c) ∈ arrows S (φ.obj c) (φ.obj c)

Next tactic:
apply Sn.wide
theorem isNormal_comap {S : Subgroupoid D} (Sn : IsNormal S) : IsNormal (comap φ S) where
  wide c := by rw [comap, mem_setOf, Functor.map_id]; apply Sn.wide
  conj f γ hγ := by
    

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
Sn : IsNormal S
c✝ d✝ : C
f : c✝ ⟶ d✝
γ : c✝ ⟶ c✝
hγ : γ ∈ arrows (comap φ S) c✝ c✝
⊢ Groupoid.inv f ≫ γ ≫ f ∈ arrows (comap φ S) d✝ d✝

Next tactic:
simp_rw [inv_eq_inv f, comap, mem_setOf, Functor.map_comp, Functor.map_inv, ← inv_eq_inv]
theorem isNormal_comap {S : Subgroupoid D} (Sn : IsNormal S) : IsNormal (comap φ S) where
  wide c := by rw [comap, mem_setOf, Functor.map_id]; apply Sn.wide
  conj f γ hγ := by
    simp_rw [inv_eq_inv f, comap, mem_setOf, Functor.map_comp, Functor.map_inv, ← inv_eq_inv]
    

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
S : Subgroupoid D
Sn : IsNormal S
c✝ d✝ : C
f : c✝ ⟶ d✝
γ : c✝ ⟶ c✝
hγ : γ ∈ arrows (comap φ S) c✝ c✝
⊢ Groupoid.inv (φ.map f) ≫ φ.map γ ≫ φ.map f ∈ arrows S (φ.obj d✝) (φ.obj d✝)

Next tactic:
exact Sn.conj _ hγ
theorem Map.arrows_iff (hφ : Function.Injective φ.obj) (S : Subgroupoid C) {c d : D} (f : c ⟶ d) :
    Map.Arrows φ hφ S c d f ↔
      ∃ (a b : C) (g : a ⟶ b) (ha : φ.obj a = c) (hb : φ.obj b = d) (_hg : g ∈ S.arrows a b),
        f = eqToHom ha.symm ≫ φ.map g ≫ eqToHom hb := by
  

Proof state:
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
hφ : Function.Injective φ.obj
S : Subgroupoid C
c d : D
f : c ⟶ d
⊢ Arrows φ hφ S c d f ↔
    ∃ a b g,
      ∃ (ha : φ.obj a = c) (hb : φ.obj b = d) (_ : g ∈ arrows S a b),
        f = eqToHom (_ : c = φ.obj a) ≫ φ.map g ≫ eqToHom hb

Next tactic:
constructor
theorem Map.arrows_iff (hφ : Function.Injective φ.obj) (S : Subgroupoid C) {c d : D} (f : c ⟶ d) :
    Map.Arrows φ hφ S c d f ↔
      ∃ (a b : C) (g : a ⟶ b) (ha : φ.obj a = c) (hb : φ.obj b = d) (_hg : g ∈ S.arrows a b),
        f = eqToHom ha.symm ≫ φ.map g ≫ eqToHom hb := by
  constructor
  · 

Proof state:
case mp
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
hφ : Function.Injective φ.obj
S : Subgroupoid C
c d : D
f : c ⟶ d
⊢ Arrows φ hφ S c d f →
    ∃ a b g,
      ∃ (ha : φ.obj a = c) (hb : φ.obj b = d) (_ : g ∈ arrows S a b),
        f = eqToHom (_ : c = φ.obj a) ≫ φ.map g ≫ eqToHom hb

Next tactic:
rintro ⟨g, hg⟩
theorem Map.arrows_iff (hφ : Function.Injective φ.obj) (S : Subgroupoid C) {c d : D} (f : c ⟶ d) :
    Map.Arrows φ hφ S c d f ↔
      ∃ (a b : C) (g : a ⟶ b) (ha : φ.obj a = c) (hb : φ.obj b = d) (_hg : g ∈ S.arrows a b),
        f = eqToHom ha.symm ≫ φ.map g ≫ eqToHom hb := by
  constructor
  · rintro ⟨g, hg⟩; 

Proof state:
case mp.im
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
hφ : Function.Injective φ.obj
S : Subgroupoid C
c d : D
c✝ d✝ : C
g : c✝ ⟶ d✝
hg : g ∈ arrows S c✝ d✝
⊢ ∃ a b g_1,
    ∃ (ha : φ.obj a = φ.obj c✝) (hb : φ.obj b = φ.obj d✝) (_ : g_1 ∈ arrows S a b),
      φ.map g = eqToHom (_ : φ.obj c✝ = φ.obj a) ≫ φ.map g_1 ≫ eqToHom hb

Next tactic:
exact ⟨_, _, g, rfl, rfl, hg, eq_conj_eqToHom _⟩
theorem Map.arrows_iff (hφ : Function.Injective φ.obj) (S : Subgroupoid C) {c d : D} (f : c ⟶ d) :
    Map.Arrows φ hφ S c d f ↔
      ∃ (a b : C) (g : a ⟶ b) (ha : φ.obj a = c) (hb : φ.obj b = d) (_hg : g ∈ S.arrows a b),
        f = eqToHom ha.symm ≫ φ.map g ≫ eqToHom hb := by
  constructor
  · rintro ⟨g, hg⟩; exact ⟨_, _, g, rfl, rfl, hg, eq_conj_eqToHom _⟩
  · 

Proof state:
case mpr
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
hφ : Function.Injective φ.obj
S : Subgroupoid C
c d : D
f : c ⟶ d
⊢ (∃ a b g,
      ∃ (ha : φ.obj a = c) (hb : φ.obj b = d) (_ : g ∈ arrows S a b),
        f = eqToHom (_ : c = φ.obj a) ≫ φ.map g ≫ eqToHom hb) →
    Arrows φ hφ S c d f

Next tactic:
rintro ⟨a, b, g, rfl, rfl, hg, rfl⟩
theorem Map.arrows_iff (hφ : Function.Injective φ.obj) (S : Subgroupoid C) {c d : D} (f : c ⟶ d) :
    Map.Arrows φ hφ S c d f ↔
      ∃ (a b : C) (g : a ⟶ b) (ha : φ.obj a = c) (hb : φ.obj b = d) (_hg : g ∈ S.arrows a b),
        f = eqToHom ha.symm ≫ φ.map g ≫ eqToHom hb := by
  constructor
  · rintro ⟨g, hg⟩; exact ⟨_, _, g, rfl, rfl, hg, eq_conj_eqToHom _⟩
  · rintro ⟨a, b, g, rfl, rfl, hg, rfl⟩; 

Proof state:
case mpr.intro.intro.intro.intro.intro.intro
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
hφ : Function.Injective φ.obj
S : Subgroupoid C
a b : C
g : a ⟶ b
hg : g ∈ arrows S a b
⊢ Arrows φ hφ S (φ.obj a) (φ.obj b) (eqToHom (_ : φ.obj a = φ.obj a) ≫ φ.map g ≫ eqToHom (_ : φ.obj b = φ.obj b))

Next tactic:
rw [← eq_conj_eqToHom]
theorem Map.arrows_iff (hφ : Function.Injective φ.obj) (S : Subgroupoid C) {c d : D} (f : c ⟶ d) :
    Map.Arrows φ hφ S c d f ↔
      ∃ (a b : C) (g : a ⟶ b) (ha : φ.obj a = c) (hb : φ.obj b = d) (_hg : g ∈ S.arrows a b),
        f = eqToHom ha.symm ≫ φ.map g ≫ eqToHom hb := by
  constructor
  · rintro ⟨g, hg⟩; exact ⟨_, _, g, rfl, rfl, hg, eq_conj_eqToHom _⟩
  · rintro ⟨a, b, g, rfl, rfl, hg, rfl⟩; rw [← eq_conj_eqToHom]; 

Proof state:
case mpr.intro.intro.intro.intro.intro.intro
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
hφ : Function.Injective φ.obj
S : Subgroupoid C
a b : C
g : a ⟶ b
hg : g ∈ arrows S a b
⊢ Arrows φ hφ S (φ.obj a) (φ.obj b) (φ.map g)

Next tactic:
constructor
theorem Map.arrows_iff (hφ : Function.Injective φ.obj) (S : Subgroupoid C) {c d : D} (f : c ⟶ d) :
    Map.Arrows φ hφ S c d f ↔
      ∃ (a b : C) (g : a ⟶ b) (ha : φ.obj a = c) (hb : φ.obj b = d) (_hg : g ∈ S.arrows a b),
        f = eqToHom ha.symm ≫ φ.map g ≫ eqToHom hb := by
  constructor
  · rintro ⟨g, hg⟩; exact ⟨_, _, g, rfl, rfl, hg, eq_conj_eqToHom _⟩
  · rintro ⟨a, b, g, rfl, rfl, hg, rfl⟩; rw [← eq_conj_eqToHom]; constructor; 

Proof state:
case mpr.intro.intro.intro.intro.intro.intro.hf
C : Type u
inst✝¹ : Groupoid C
S✝ : Subgroupoid C
D : Type u_1
inst✝ : Groupoid D
φ : C ⥤ D
hφ : Function.Injective φ.obj
S : Subgroupoid C
a b : C
g : a ⟶ b
hg : g ∈ arrows S a b
⊢ g ∈ arrows S a b

Next tactic:
exact hg