l3lab/ntp-mathlib huggingface dataset:
/-- A functorial version of `SimplicialObject.Augmented.rightOp`. -/
@[simps]
def simplicialToCosimplicialAugmented :
    (SimplicialObject.Augmented C)ᵒᵖ ⥤ CosimplicialObject.Augmented Cᵒᵖ where
  obj X := X.unop.rightOp
  map f :=
    { left := f.unop.right.op
      right := NatTrans.rightOp f.unop.left
      w := by
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
⊢ (CosimplicialObject.const Cᵒᵖ).map f.unop.right.op ≫ ((fun X => SimplicialObject.Augmented.rightOp X.unop) Y✝).hom =
    ((fun X => SimplicialObject.Augmented.rightOp X.unop) X✝).hom ≫
      (𝟭 (CosimplicialObject Cᵒᵖ)).map (NatTrans.rightOp f.unop.left)

Next tactic:
ext x
/-- A functorial version of `SimplicialObject.Augmented.rightOp`. -/
@[simps]
def simplicialToCosimplicialAugmented :
    (SimplicialObject.Augmented C)ᵒᵖ ⥤ CosimplicialObject.Augmented Cᵒᵖ where
  obj X := X.unop.rightOp
  map f :=
    { left := f.unop.right.op
      right := NatTrans.rightOp f.unop.left
      w := by
        ext x
        

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
x : SimplexCategory
⊢ ((CosimplicialObject.const Cᵒᵖ).map f.unop.right.op ≫
          ((fun X => SimplicialObject.Augmented.rightOp X.unop) Y✝).hom).app
      x =
    (((fun X => SimplicialObject.Augmented.rightOp X.unop) X✝).hom ≫
          (𝟭 (CosimplicialObject Cᵒᵖ)).map (NatTrans.rightOp f.unop.left)).app
      x

Next tactic:
dsimp
/-- A functorial version of `SimplicialObject.Augmented.rightOp`. -/
@[simps]
def simplicialToCosimplicialAugmented :
    (SimplicialObject.Augmented C)ᵒᵖ ⥤ CosimplicialObject.Augmented Cᵒᵖ where
  obj X := X.unop.rightOp
  map f :=
    { left := f.unop.right.op
      right := NatTrans.rightOp f.unop.left
      w := by
        ext x
        dsimp
        

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
x : SimplexCategory
⊢ f.unop.right.op ≫ (Y✝.unop.hom.app (op x)).op = (X✝.unop.hom.app (op x)).op ≫ (f.unop.left.app (op x)).op

Next tactic:
simp_rw [← op_comp]
/-- A functorial version of `SimplicialObject.Augmented.rightOp`. -/
@[simps]
def simplicialToCosimplicialAugmented :
    (SimplicialObject.Augmented C)ᵒᵖ ⥤ CosimplicialObject.Augmented Cᵒᵖ where
  obj X := X.unop.rightOp
  map f :=
    { left := f.unop.right.op
      right := NatTrans.rightOp f.unop.left
      w := by
        ext x
        dsimp
        simp_rw [← op_comp]
        

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
x : SimplexCategory
⊢ (Y✝.unop.hom.app (op x) ≫ f.unop.right).op = (f.unop.left.app (op x) ≫ X✝.unop.hom.app (op x)).op

Next tactic:
congr 1
/-- A functorial version of `SimplicialObject.Augmented.rightOp`. -/
@[simps]
def simplicialToCosimplicialAugmented :
    (SimplicialObject.Augmented C)ᵒᵖ ⥤ CosimplicialObject.Augmented Cᵒᵖ where
  obj X := X.unop.rightOp
  map f :=
    { left := f.unop.right.op
      right := NatTrans.rightOp f.unop.left
      w := by
        ext x
        dsimp
        simp_rw [← op_comp]
        congr 1
        

Proof state:
case h.e_f
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
x : SimplexCategory
⊢ Y✝.unop.hom.app (op x) ≫ f.unop.right = f.unop.left.app (op x) ≫ X✝.unop.hom.app (op x)

Next tactic:
exact (congr_app f.unop.w (op x)).symm
/-- A functorial version of `Cosimplicial_object.Augmented.leftOp`. -/
@[simps]
def cosimplicialToSimplicialAugmented :
    CosimplicialObject.Augmented Cᵒᵖ ⥤ (SimplicialObject.Augmented C)ᵒᵖ where
  obj X := Opposite.op X.leftOp
  map f :=
    Quiver.Hom.op <|
      { left := NatTrans.leftOp f.right
        right := f.left.unop
        w := by
          

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : CosimplicialObject.Augmented Cᵒᵖ
f : X✝ ⟶ Y✝
⊢ (𝟭 (SimplicialObject C)).map (NatTrans.leftOp f.right) ≫ (CosimplicialObject.Augmented.leftOp X✝).hom =
    (CosimplicialObject.Augmented.leftOp Y✝).hom ≫ (SimplicialObject.const C).map f.left.unop

Next tactic:
ext x
/-- A functorial version of `Cosimplicial_object.Augmented.leftOp`. -/
@[simps]
def cosimplicialToSimplicialAugmented :
    CosimplicialObject.Augmented Cᵒᵖ ⥤ (SimplicialObject.Augmented C)ᵒᵖ where
  obj X := Opposite.op X.leftOp
  map f :=
    Quiver.Hom.op <|
      { left := NatTrans.leftOp f.right
        right := f.left.unop
        w := by
          ext x
          

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : CosimplicialObject.Augmented Cᵒᵖ
f : X✝ ⟶ Y✝
x : SimplexCategoryᵒᵖ
⊢ ((𝟭 (SimplicialObject C)).map (NatTrans.leftOp f.right) ≫ (CosimplicialObject.Augmented.leftOp X✝).hom).app x =
    ((CosimplicialObject.Augmented.leftOp Y✝).hom ≫ (SimplicialObject.const C).map f.left.unop).app x

Next tactic:
dsimp
/-- A functorial version of `Cosimplicial_object.Augmented.leftOp`. -/
@[simps]
def cosimplicialToSimplicialAugmented :
    CosimplicialObject.Augmented Cᵒᵖ ⥤ (SimplicialObject.Augmented C)ᵒᵖ where
  obj X := Opposite.op X.leftOp
  map f :=
    Quiver.Hom.op <|
      { left := NatTrans.leftOp f.right
        right := f.left.unop
        w := by
          ext x
          dsimp
          

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : CosimplicialObject.Augmented Cᵒᵖ
f : X✝ ⟶ Y✝
x : SimplexCategoryᵒᵖ
⊢ (f.right.app x.unop).unop ≫ (X✝.hom.app x.unop).unop = (Y✝.hom.app x.unop).unop ≫ f.left.unop

Next tactic:
simp_rw [← unop_comp]
/-- A functorial version of `Cosimplicial_object.Augmented.leftOp`. -/
@[simps]
def cosimplicialToSimplicialAugmented :
    CosimplicialObject.Augmented Cᵒᵖ ⥤ (SimplicialObject.Augmented C)ᵒᵖ where
  obj X := Opposite.op X.leftOp
  map f :=
    Quiver.Hom.op <|
      { left := NatTrans.leftOp f.right
        right := f.left.unop
        w := by
          ext x
          dsimp
          simp_rw [← unop_comp]
          

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : CosimplicialObject.Augmented Cᵒᵖ
f : X✝ ⟶ Y✝
x : SimplexCategoryᵒᵖ
⊢ (X✝.hom.app x.unop ≫ f.right.app x.unop).unop = (f.left ≫ Y✝.hom.app x.unop).unop

Next tactic:
congr 1
/-- A functorial version of `Cosimplicial_object.Augmented.leftOp`. -/
@[simps]
def cosimplicialToSimplicialAugmented :
    CosimplicialObject.Augmented Cᵒᵖ ⥤ (SimplicialObject.Augmented C)ᵒᵖ where
  obj X := Opposite.op X.leftOp
  map f :=
    Quiver.Hom.op <|
      { left := NatTrans.leftOp f.right
        right := f.left.unop
        w := by
          ext x
          dsimp
          simp_rw [← unop_comp]
          congr 1
          

Proof state:
case h.e_f
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : CosimplicialObject.Augmented Cᵒᵖ
f : X✝ ⟶ Y✝
x : SimplexCategoryᵒᵖ
⊢ X✝.hom.app x.unop ≫ f.right.app x.unop = f.left ≫ Y✝.hom.app x.unop

Next tactic:
exact (congr_app f.w (unop x)).symm
/-- The contravariant categorical equivalence between augmented simplicial
objects and augmented cosimplicial objects in the opposite category. -/
@[simps! functor inverse]
def simplicialCosimplicialAugmentedEquiv :
    (SimplicialObject.Augmented C)ᵒᵖ ≌ CosimplicialObject.Augmented Cᵒᵖ :=
  Equivalence.mk (simplicialToCosimplicialAugmented _) (cosimplicialToSimplicialAugmented _)
    (NatIso.ofComponents (fun X => X.unop.rightOpLeftOpIso.op) fun f => by
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
⊢ (𝟭 (SimplicialObject.Augmented C)ᵒᵖ).map f ≫
      ((fun X => Iso.op (SimplicialObject.Augmented.rightOpLeftOpIso X.unop)) Y✝).hom =
    ((fun X => Iso.op (SimplicialObject.Augmented.rightOpLeftOpIso X.unop)) X✝).hom ≫
      (simplicialToCosimplicialAugmented C ⋙ cosimplicialToSimplicialAugmented C).map f

Next tactic:
dsimp
/-- The contravariant categorical equivalence between augmented simplicial
objects and augmented cosimplicial objects in the opposite category. -/
@[simps! functor inverse]
def simplicialCosimplicialAugmentedEquiv :
    (SimplicialObject.Augmented C)ᵒᵖ ≌ CosimplicialObject.Augmented Cᵒᵖ :=
  Equivalence.mk (simplicialToCosimplicialAugmented _) (cosimplicialToSimplicialAugmented _)
    (NatIso.ofComponents (fun X => X.unop.rightOpLeftOpIso.op) fun f => by
      dsimp
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
⊢ f ≫ (SimplicialObject.Augmented.rightOpLeftOpIso Y✝.unop).hom.op =
    (SimplicialObject.Augmented.rightOpLeftOpIso X✝.unop).hom.op ≫
      (CommaMorphism.mk (NatTrans.leftOp (NatTrans.rightOp f.unop.left)) f.unop.right).op

Next tactic:
rw [← f.op_unop]
/-- The contravariant categorical equivalence between augmented simplicial
objects and augmented cosimplicial objects in the opposite category. -/
@[simps! functor inverse]
def simplicialCosimplicialAugmentedEquiv :
    (SimplicialObject.Augmented C)ᵒᵖ ≌ CosimplicialObject.Augmented Cᵒᵖ :=
  Equivalence.mk (simplicialToCosimplicialAugmented _) (cosimplicialToSimplicialAugmented _)
    (NatIso.ofComponents (fun X => X.unop.rightOpLeftOpIso.op) fun f => by
      dsimp
      rw [← f.op_unop]
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
⊢ f.unop.op ≫ (SimplicialObject.Augmented.rightOpLeftOpIso Y✝.unop).hom.op =
    (SimplicialObject.Augmented.rightOpLeftOpIso X✝.unop).hom.op ≫
      (CommaMorphism.mk (NatTrans.leftOp (NatTrans.rightOp f.unop.op.unop.left)) f.unop.op.unop.right).op

Next tactic:
simp_rw [← op_comp]
/-- The contravariant categorical equivalence between augmented simplicial
objects and augmented cosimplicial objects in the opposite category. -/
@[simps! functor inverse]
def simplicialCosimplicialAugmentedEquiv :
    (SimplicialObject.Augmented C)ᵒᵖ ≌ CosimplicialObject.Augmented Cᵒᵖ :=
  Equivalence.mk (simplicialToCosimplicialAugmented _) (cosimplicialToSimplicialAugmented _)
    (NatIso.ofComponents (fun X => X.unop.rightOpLeftOpIso.op) fun f => by
      dsimp
      rw [← f.op_unop]
      simp_rw [← op_comp]
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
⊢ ((SimplicialObject.Augmented.rightOpLeftOpIso Y✝.unop).hom ≫ f.unop).op =
    (CommaMorphism.mk (NatTrans.leftOp (NatTrans.rightOp f.unop.op.unop.left)) f.unop.op.unop.right ≫
        (SimplicialObject.Augmented.rightOpLeftOpIso X✝.unop).hom).op

Next tactic:
congr 1
/-- The contravariant categorical equivalence between augmented simplicial
objects and augmented cosimplicial objects in the opposite category. -/
@[simps! functor inverse]
def simplicialCosimplicialAugmentedEquiv :
    (SimplicialObject.Augmented C)ᵒᵖ ≌ CosimplicialObject.Augmented Cᵒᵖ :=
  Equivalence.mk (simplicialToCosimplicialAugmented _) (cosimplicialToSimplicialAugmented _)
    (NatIso.ofComponents (fun X => X.unop.rightOpLeftOpIso.op) fun f => by
      dsimp
      rw [← f.op_unop]
      simp_rw [← op_comp]
      congr 1
      

Proof state:
case e_f
C : Type u
inst✝ : Category.{v, u} C
X✝ Y✝ : (SimplicialObject.Augmented C)ᵒᵖ
f : X✝ ⟶ Y✝
⊢ (SimplicialObject.Augmented.rightOpLeftOpIso Y✝.unop).hom ≫ f.unop =
    CommaMorphism.mk (NatTrans.leftOp (NatTrans.rightOp f.unop.op.unop.left)) f.unop.op.unop.right ≫
      (SimplicialObject.Augmented.rightOpLeftOpIso X✝.unop).hom

Next tactic:
aesop_cat
/-- The congruence relation generated by a normal subgroup. -/
@[to_additive "The additive congruence relation generated by a normal additive subgroup."]
protected def con : Con G where
  toSetoid := leftRel N
  mul' := @fun a b c d hab hcd => by
    

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
a b c d : G
hab : Setoid.r a b
hcd : Setoid.r c d
⊢ Setoid.r (a * c) (b * d)

Next tactic:
rw [leftRel_eq] at hab hcd ⊢
/-- The congruence relation generated by a normal subgroup. -/
@[to_additive "The additive congruence relation generated by a normal additive subgroup."]
protected def con : Con G where
  toSetoid := leftRel N
  mul' := @fun a b c d hab hcd => by
    rw [leftRel_eq] at hab hcd ⊢
    

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
a b c d : G
hab : a⁻¹ * b ∈ N
hcd : c⁻¹ * d ∈ N
⊢ (fun x y => x⁻¹ * y ∈ N) (a * c) (b * d)

Next tactic:
dsimp only
/-- The congruence relation generated by a normal subgroup. -/
@[to_additive "The additive congruence relation generated by a normal additive subgroup."]
protected def con : Con G where
  toSetoid := leftRel N
  mul' := @fun a b c d hab hcd => by
    rw [leftRel_eq] at hab hcd ⊢
    dsimp only
    

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
a b c d : G
hab : a⁻¹ * b ∈ N
hcd : c⁻¹ * d ∈ N
⊢ (a * c)⁻¹ * (b * d) ∈ N

Next tactic:
calc
      (a * c)⁻¹ * (b * d) = c⁻¹ * (a⁻¹ * b) * c⁻¹⁻¹ * (c⁻¹ * d) :=
        by simp only [mul_inv_rev, mul_assoc, inv_mul_cancel_left]
      _ ∈ N := N.mul_mem (nN.conj_mem _ hab _) hcd
/-- The congruence relation generated by a normal subgroup. -/
@[to_additive "The additive congruence relation generated by a normal additive subgroup."]
protected def con : Con G where
  toSetoid := leftRel N
  mul' := @fun a b c d hab hcd => by
    rw [leftRel_eq] at hab hcd ⊢
    dsimp only
    calc
      (a * c)⁻¹ * (b * d) = c⁻¹ * (a⁻¹ * b) * c⁻¹⁻¹ * (c⁻¹ * d) :=
        by 

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
a b c d : G
hab : a⁻¹ * b ∈ N
hcd : c⁻¹ * d ∈ N
⊢ (a * c)⁻¹ * (b * d) = c⁻¹ * (a⁻¹ * b) * c⁻¹⁻¹ * (c⁻¹ * d)

Next tactic:
simp only [mul_inv_rev, mul_assoc, inv_mul_cancel_left]
@[to_additive]
theorem mk'_eq_mk' {x y : G} : mk' N x = mk' N y ↔ ∃ z ∈ N, x * z = y :=
  QuotientGroup.eq'.trans <| by
    

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
x y : G
⊢ x⁻¹ * y ∈ N ↔ ∃ z ∈ N, x * z = y

Next tactic:
simp only [← _root_.eq_inv_mul_iff_mul_eq, exists_prop, exists_eq_right]
@[to_additive (attr := simp)]
theorem eq_one_iff {N : Subgroup G} [nN : N.Normal] (x : G) : (x : G ⧸ N) = 1 ↔ x ∈ N := by
  

Proof state:
G : Type u
inst✝² : Group G
N✝ : Subgroup G
nN✝ : Subgroup.Normal N✝
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
N : Subgroup G
nN : Subgroup.Normal N
x : G
⊢ ↑x = 1 ↔ x ∈ N

Next tactic:
refine' QuotientGroup.eq.trans _
@[to_additive (attr := simp)]
theorem eq_one_iff {N : Subgroup G} [nN : N.Normal] (x : G) : (x : G ⧸ N) = 1 ↔ x ∈ N := by
  refine' QuotientGroup.eq.trans _
  

Proof state:
G : Type u
inst✝² : Group G
N✝ : Subgroup G
nN✝ : Subgroup.Normal N✝
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
N : Subgroup G
nN : Subgroup.Normal N
x : G
⊢ x⁻¹ * 1 ∈ N ↔ x ∈ N

Next tactic:
rw [mul_one, Subgroup.inv_mem_iff]
@[to_additive]
theorem ker_le_range_iff {I : Type w} [Group I] (f : G →* H) [f.range.Normal] (g : H →* I) :
    g.ker ≤ f.range ↔ (mk' f.range).comp g.ker.subtype = 1 :=
  ⟨fun h => MonoidHom.ext fun ⟨_, hx⟩ => (eq_one_iff _).mpr <| h hx,
    fun h x hx => (eq_one_iff _).mp <| by 

Proof state:
G : Type u
inst✝⁴ : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝³ : Group H
M : Type x
inst✝² : Monoid M
I : Type w
inst✝¹ : Group I
f : G →* H
inst✝ : Subgroup.Normal (MonoidHom.range f)
g : H →* I
h : MonoidHom.comp (mk' (MonoidHom.range f)) (Subgroup.subtype (MonoidHom.ker g)) = 1
x : H
hx : x ∈ MonoidHom.ker g
⊢ ↑x = 1

Next tactic:
exact FunLike.congr_fun h ⟨x, hx⟩
@[to_additive]
theorem eq_iff_div_mem {N : Subgroup G} [nN : N.Normal] {x y : G} :
    (x : G ⧸ N) = y ↔ x / y ∈ N := by
  

Proof state:
G : Type u
inst✝² : Group G
N✝ : Subgroup G
nN✝ : Subgroup.Normal N✝
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
N : Subgroup G
nN : Subgroup.Normal N
x y : G
⊢ ↑x = ↑y ↔ x / y ∈ N

Next tactic:
refine' eq_comm.trans (QuotientGroup.eq.trans _)
@[to_additive]
theorem eq_iff_div_mem {N : Subgroup G} [nN : N.Normal] {x y : G} :
    (x : G ⧸ N) = y ↔ x / y ∈ N := by
  refine' eq_comm.trans (QuotientGroup.eq.trans _)
  

Proof state:
G : Type u
inst✝² : Group G
N✝ : Subgroup G
nN✝ : Subgroup.Normal N✝
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
N : Subgroup G
nN : Subgroup.Normal N
x y : G
⊢ y⁻¹ * x ∈ N ↔ x / y ∈ N

Next tactic:
rw [nN.mem_comm_iff, div_eq_mul_inv]
/-- A group homomorphism `φ : G →* M` with `N ⊆ ker(φ)` descends (i.e. `lift`s) to a
group homomorphism `G/N →* M`. -/
@[to_additive "An `AddGroup` homomorphism `φ : G →+ M` with `N ⊆ ker(φ)` descends (i.e. `lift`s)
 to a group homomorphism `G/N →* M`."]
def lift (φ : G →* M) (HN : N ≤ φ.ker) : Q →* M :=
  (QuotientGroup.con N).lift φ fun x y h => by
    

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
φ : G →* M
HN : N ≤ MonoidHom.ker φ
x y : G
h : (QuotientGroup.con N) x y
⊢ (Con.ker φ) x y

Next tactic:
simp only [QuotientGroup.con, leftRel_apply, Con.rel_mk] at h
/-- A group homomorphism `φ : G →* M` with `N ⊆ ker(φ)` descends (i.e. `lift`s) to a
group homomorphism `G/N →* M`. -/
@[to_additive "An `AddGroup` homomorphism `φ : G →+ M` with `N ⊆ ker(φ)` descends (i.e. `lift`s)
 to a group homomorphism `G/N →* M`."]
def lift (φ : G →* M) (HN : N ≤ φ.ker) : Q →* M :=
  (QuotientGroup.con N).lift φ fun x y h => by
    simp only [QuotientGroup.con, leftRel_apply, Con.rel_mk] at h
    

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
φ : G →* M
HN : N ≤ MonoidHom.ker φ
x y : G
h : x⁻¹ * y ∈ N
⊢ (Con.ker φ) x y

Next tactic:
rw [Con.ker_rel]
/-- A group homomorphism `φ : G →* M` with `N ⊆ ker(φ)` descends (i.e. `lift`s) to a
group homomorphism `G/N →* M`. -/
@[to_additive "An `AddGroup` homomorphism `φ : G →+ M` with `N ⊆ ker(φ)` descends (i.e. `lift`s)
 to a group homomorphism `G/N →* M`."]
def lift (φ : G →* M) (HN : N ≤ φ.ker) : Q →* M :=
  (QuotientGroup.con N).lift φ fun x y h => by
    simp only [QuotientGroup.con, leftRel_apply, Con.rel_mk] at h
    rw [Con.ker_rel]
    

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
φ : G →* M
HN : N ≤ MonoidHom.ker φ
x y : G
h : x⁻¹ * y ∈ N
⊢ φ x = φ y

Next tactic:
calc
      φ x = φ (y * (x⁻¹ * y)⁻¹) := by rw [mul_inv_rev, inv_inv, mul_inv_cancel_left]
      _ = φ y := by rw [φ.map_mul, HN (N.inv_mem h), mul_one]
/-- A group homomorphism `φ : G →* M` with `N ⊆ ker(φ)` descends (i.e. `lift`s) to a
group homomorphism `G/N →* M`. -/
@[to_additive "An `AddGroup` homomorphism `φ : G →+ M` with `N ⊆ ker(φ)` descends (i.e. `lift`s)
 to a group homomorphism `G/N →* M`."]
def lift (φ : G →* M) (HN : N ≤ φ.ker) : Q →* M :=
  (QuotientGroup.con N).lift φ fun x y h => by
    simp only [QuotientGroup.con, leftRel_apply, Con.rel_mk] at h
    rw [Con.ker_rel]
    calc
      φ x = φ (y * (x⁻¹ * y)⁻¹) := by 

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
φ : G →* M
HN : N ≤ MonoidHom.ker φ
x y : G
h : x⁻¹ * y ∈ N
⊢ φ x = φ (y * (x⁻¹ * y)⁻¹)

Next tactic:
rw [mul_inv_rev, inv_inv, mul_inv_cancel_left]
/-- A group homomorphism `φ : G →* M` with `N ⊆ ker(φ)` descends (i.e. `lift`s) to a
group homomorphism `G/N →* M`. -/
@[to_additive "An `AddGroup` homomorphism `φ : G →+ M` with `N ⊆ ker(φ)` descends (i.e. `lift`s)
 to a group homomorphism `G/N →* M`."]
def lift (φ : G →* M) (HN : N ≤ φ.ker) : Q →* M :=
  (QuotientGroup.con N).lift φ fun x y h => by
    simp only [QuotientGroup.con, leftRel_apply, Con.rel_mk] at h
    rw [Con.ker_rel]
    calc
      φ x = φ (y * (x⁻¹ * y)⁻¹) := by rw [mul_inv_rev, inv_inv, mul_inv_cancel_left]
      _ = φ y := by 

Proof state:
G : Type u
inst✝² : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝¹ : Group H
M : Type x
inst✝ : Monoid M
φ : G →* M
HN : N ≤ MonoidHom.ker φ
x y : G
h : x⁻¹ * y ∈ N
⊢ φ (y * (x⁻¹ * y)⁻¹) = φ y

Next tactic:
rw [φ.map_mul, HN (N.inv_mem h), mul_one]
/-- A group homomorphism `f : G →* H` induces a map `G/N →* H/M` if `N ⊆ f⁻¹(M)`. -/
@[to_additive
      "An `AddGroup` homomorphism `f : G →+ H` induces a map `G/N →+ H/M` if `N ⊆ f⁻¹(M)`."]
def map (M : Subgroup H) [M.Normal] (f : G →* H) (h : N ≤ M.comap f) : G ⧸ N →* H ⧸ M := by
  

Proof state:
G : Type u
inst✝³ : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝² : Group H
M✝ : Type x
inst✝¹ : Monoid M✝
M : Subgroup H
inst✝ : Subgroup.Normal M
f : G →* H
h : N ≤ Subgroup.comap f M
⊢ G ⧸ N →* H ⧸ M

Next tactic:
refine' QuotientGroup.lift N ((mk' M).comp f) _
/-- A group homomorphism `f : G →* H` induces a map `G/N →* H/M` if `N ⊆ f⁻¹(M)`. -/
@[to_additive
      "An `AddGroup` homomorphism `f : G →+ H` induces a map `G/N →+ H/M` if `N ⊆ f⁻¹(M)`."]
def map (M : Subgroup H) [M.Normal] (f : G →* H) (h : N ≤ M.comap f) : G ⧸ N →* H ⧸ M := by
  refine' QuotientGroup.lift N ((mk' M).comp f) _
  

Proof state:
G : Type u
inst✝³ : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝² : Group H
M✝ : Type x
inst✝¹ : Monoid M✝
M : Subgroup H
inst✝ : Subgroup.Normal M
f : G →* H
h : N ≤ Subgroup.comap f M
⊢ N ≤ MonoidHom.ker (MonoidHom.comp (mk' M) f)

Next tactic:
intro x hx
/-- A group homomorphism `f : G →* H` induces a map `G/N →* H/M` if `N ⊆ f⁻¹(M)`. -/
@[to_additive
      "An `AddGroup` homomorphism `f : G →+ H` induces a map `G/N →+ H/M` if `N ⊆ f⁻¹(M)`."]
def map (M : Subgroup H) [M.Normal] (f : G →* H) (h : N ≤ M.comap f) : G ⧸ N →* H ⧸ M := by
  refine' QuotientGroup.lift N ((mk' M).comp f) _
  intro x hx
  

Proof state:
G : Type u
inst✝³ : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝² : Group H
M✝ : Type x
inst✝¹ : Monoid M✝
M : Subgroup H
inst✝ : Subgroup.Normal M
f : G →* H
h : N ≤ Subgroup.comap f M
x : G
hx : x ∈ N
⊢ x ∈ MonoidHom.ker (MonoidHom.comp (mk' M) f)

Next tactic:
refine' QuotientGroup.eq.2 _
/-- A group homomorphism `f : G →* H` induces a map `G/N →* H/M` if `N ⊆ f⁻¹(M)`. -/
@[to_additive
      "An `AddGroup` homomorphism `f : G →+ H` induces a map `G/N →+ H/M` if `N ⊆ f⁻¹(M)`."]
def map (M : Subgroup H) [M.Normal] (f : G →* H) (h : N ≤ M.comap f) : G ⧸ N →* H ⧸ M := by
  refine' QuotientGroup.lift N ((mk' M).comp f) _
  intro x hx
  refine' QuotientGroup.eq.2 _
  

Proof state:
G : Type u
inst✝³ : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝² : Group H
M✝ : Type x
inst✝¹ : Monoid M✝
M : Subgroup H
inst✝ : Subgroup.Normal M
f : G →* H
h : N ≤ Subgroup.comap f M
x : G
hx : x ∈ N
⊢ (f x)⁻¹ * 1 ∈ M

Next tactic:
rw [mul_one, Subgroup.inv_mem_iff]
/-- A group homomorphism `f : G →* H` induces a map `G/N →* H/M` if `N ⊆ f⁻¹(M)`. -/
@[to_additive
      "An `AddGroup` homomorphism `f : G →+ H` induces a map `G/N →+ H/M` if `N ⊆ f⁻¹(M)`."]
def map (M : Subgroup H) [M.Normal] (f : G →* H) (h : N ≤ M.comap f) : G ⧸ N →* H ⧸ M := by
  refine' QuotientGroup.lift N ((mk' M).comp f) _
  intro x hx
  refine' QuotientGroup.eq.2 _
  rw [mul_one, Subgroup.inv_mem_iff]
  

Proof state:
G : Type u
inst✝³ : Group G
N : Subgroup G
nN : Subgroup.Normal N
H : Type v
inst✝² : Group H
M✝ : Type x
inst✝¹ : Monoid M✝
M : Subgroup H
inst✝ : Subgroup.Normal M
f : G →* H
h : N ≤ Subgroup.comap f M
x : G
hx : x ∈ N
⊢ f x ∈ M

Next tactic:
exact h hx