l3lab/ntp-mathlib huggingface dataset:
/-- The canonical map `N →* N ⋊[φ] G` sending `n` to `⟨n, 1⟩` -/
def inl : N →* N ⋊[φ] G where
  toFun n := ⟨n, 1⟩
  map_one' := rfl
  map_mul' := by intros; 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ y✝ : N
⊢ OneHom.toFun
      { toFun := fun n => { left := n, right := 1 },
        map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
      (x✝ * y✝) =
    OneHom.toFun
        { toFun := fun n => { left := n, right := 1 },
          map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
        x✝ *
      OneHom.toFun
        { toFun := fun n => { left := n, right := 1 },
          map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
        y✝

Next tactic:
ext
/-- The canonical map `N →* N ⋊[φ] G` sending `n` to `⟨n, 1⟩` -/
def inl : N →* N ⋊[φ] G where
  toFun n := ⟨n, 1⟩
  map_one' := rfl
  map_mul' := by intros; ext <;>
    

Proof state:
case left
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ y✝ : N
⊢ (OneHom.toFun
        { toFun := fun n => { left := n, right := 1 },
          map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
        (x✝ * y✝)).left =
    (OneHom.toFun
          { toFun := fun n => { left := n, right := 1 },
            map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
          x✝ *
        OneHom.toFun
          { toFun := fun n => { left := n, right := 1 },
            map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
          y✝).left

Next tactic:
simp only [mul_left, map_one, MulAut.one_apply, mul_right, mul_one]
/-- The canonical map `N →* N ⋊[φ] G` sending `n` to `⟨n, 1⟩` -/
def inl : N →* N ⋊[φ] G where
  toFun n := ⟨n, 1⟩
  map_one' := rfl
  map_mul' := by intros; ext <;>
    

Proof state:
case right
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ y✝ : N
⊢ (OneHom.toFun
        { toFun := fun n => { left := n, right := 1 },
          map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
        (x✝ * y✝)).right =
    (OneHom.toFun
          { toFun := fun n => { left := n, right := 1 },
            map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
          x✝ *
        OneHom.toFun
          { toFun := fun n => { left := n, right := 1 },
            map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
          y✝).right

Next tactic:
simp only [mul_left, map_one, MulAut.one_apply, mul_right, mul_one]
/-- The canonical map `G →* N ⋊[φ] G` sending `g` to `⟨1, g⟩` -/
def inr : G →* N ⋊[φ] G where
  toFun g := ⟨1, g⟩
  map_one' := rfl
  map_mul' := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
⊢ ∀ (x y : G),
    OneHom.toFun
        { toFun := fun g => { left := 1, right := g },
          map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
        (x * y) =
      OneHom.toFun
          { toFun := fun g => { left := 1, right := g },
            map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
          x *
        OneHom.toFun
          { toFun := fun g => { left := 1, right := g },
            map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
          y

Next tactic:
intros
/-- The canonical map `G →* N ⋊[φ] G` sending `g` to `⟨1, g⟩` -/
def inr : G →* N ⋊[φ] G where
  toFun g := ⟨1, g⟩
  map_one' := rfl
  map_mul' := by intros; 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ y✝ : G
⊢ OneHom.toFun
      { toFun := fun g => { left := 1, right := g },
        map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
      (x✝ * y✝) =
    OneHom.toFun
        { toFun := fun g => { left := 1, right := g },
          map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
        x✝ *
      OneHom.toFun
        { toFun := fun g => { left := 1, right := g },
          map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
        y✝

Next tactic:
ext
/-- The canonical map `G →* N ⋊[φ] G` sending `g` to `⟨1, g⟩` -/
def inr : G →* N ⋊[φ] G where
  toFun g := ⟨1, g⟩
  map_one' := rfl
  map_mul' := by intros; ext <;> 

Proof state:
case left
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ y✝ : G
⊢ (OneHom.toFun
        { toFun := fun g => { left := 1, right := g },
          map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
        (x✝ * y✝)).left =
    (OneHom.toFun
          { toFun := fun g => { left := 1, right := g },
            map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
          x✝ *
        OneHom.toFun
          { toFun := fun g => { left := 1, right := g },
            map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
          y✝).left

Next tactic:
simp
/-- The canonical map `G →* N ⋊[φ] G` sending `g` to `⟨1, g⟩` -/
def inr : G →* N ⋊[φ] G where
  toFun g := ⟨1, g⟩
  map_one' := rfl
  map_mul' := by intros; ext <;> 

Proof state:
case right
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ y✝ : G
⊢ (OneHom.toFun
        { toFun := fun g => { left := 1, right := g },
          map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
        (x✝ * y✝)).right =
    (OneHom.toFun
          { toFun := fun g => { left := 1, right := g },
            map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
          x✝ *
        OneHom.toFun
          { toFun := fun g => { left := 1, right := g },
            map_one' := (_ : (fun g => { left := 1, right := g }) 1 = (fun g => { left := 1, right := g }) 1) }
          y✝).right

Next tactic:
simp
theorem inl_aut (g : G) (n : N) : (inl (φ g n) : N ⋊[φ] G) = inr g * inl n * inr g⁻¹ := by
  

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
g : G
n : N
⊢ inl ((φ g) n) = inr g * inl n * inr g⁻¹

Next tactic:
ext
theorem inl_aut (g : G) (n : N) : (inl (φ g n) : N ⋊[φ] G) = inr g * inl n * inr g⁻¹ := by
  ext <;> 

Proof state:
case left
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
g : G
n : N
⊢ (inl ((φ g) n)).left = (inr g * inl n * inr g⁻¹).left

Next tactic:
simp
theorem inl_aut (g : G) (n : N) : (inl (φ g n) : N ⋊[φ] G) = inr g * inl n * inr g⁻¹ := by
  ext <;> 

Proof state:
case right
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
g : G
n : N
⊢ (inl ((φ g) n)).right = (inr g * inl n * inr g⁻¹).right

Next tactic:
simp
theorem inl_aut_inv (g : G) (n : N) : (inl ((φ g)⁻¹ n) : N ⋊[φ] G) = inr g⁻¹ * inl n * inr g := by
  

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
g : G
n : N
⊢ inl ((φ g)⁻¹ n) = inr g⁻¹ * inl n * inr g

Next tactic:
rw [← MonoidHom.map_inv, inl_aut, inv_inv]
@[simp]
theorem mk_eq_inl_mul_inr (g : G) (n : N) : (⟨n, g⟩ : N ⋊[φ] G) = inl n * inr g := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
g : G
n : N
⊢ { left := n, right := g } = inl n * inr g

Next tactic:
ext
@[simp]
theorem mk_eq_inl_mul_inr (g : G) (n : N) : (⟨n, g⟩ : N ⋊[φ] G) = inl n * inr g := by ext <;> 

Proof state:
case left
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
g : G
n : N
⊢ { left := n, right := g }.left = (inl n * inr g).left

Next tactic:
simp
@[simp]
theorem mk_eq_inl_mul_inr (g : G) (n : N) : (⟨n, g⟩ : N ⋊[φ] G) = inl n * inr g := by ext <;> 

Proof state:
case right
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
g : G
n : N
⊢ { left := n, right := g }.right = (inl n * inr g).right

Next tactic:
simp
@[simp]
theorem inl_left_mul_inr_right (x : N ⋊[φ] G) : inl x.left * inr x.right = x := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x : N ⋊[φ] G
⊢ inl x.left * inr x.right = x

Next tactic:
ext
@[simp]
theorem inl_left_mul_inr_right (x : N ⋊[φ] G) : inl x.left * inr x.right = x := by ext <;> 

Proof state:
case left
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x : N ⋊[φ] G
⊢ (inl x.left * inr x.right).left = x.left

Next tactic:
simp
@[simp]
theorem inl_left_mul_inr_right (x : N ⋊[φ] G) : inl x.left * inr x.right = x := by ext <;> 

Proof state:
case right
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x : N ⋊[φ] G
⊢ (inl x.left * inr x.right).right = x.right

Next tactic:
simp
@[simp]
theorem rightHom_comp_inl : (rightHom : N ⋊[φ] G →* G).comp inl = 1 := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
⊢ MonoidHom.comp rightHom inl = 1

Next tactic:
ext
@[simp]
theorem rightHom_comp_inl : (rightHom : N ⋊[φ] G →* G).comp inl = 1 := by ext; 

Proof state:
case h
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ : N
⊢ (MonoidHom.comp rightHom inl) x✝ = 1 x✝

Next tactic:
simp [rightHom]
@[simp]
theorem rightHom_comp_inr : (rightHom : N ⋊[φ] G →* G).comp inr = MonoidHom.id _ := by
  

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
⊢ MonoidHom.comp rightHom inr = MonoidHom.id G

Next tactic:
ext
@[simp]
theorem rightHom_comp_inr : (rightHom : N ⋊[φ] G →* G).comp inr = MonoidHom.id _ := by
  ext; 

Proof state:
case h
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ : G
⊢ (MonoidHom.comp rightHom inr) x✝ = (MonoidHom.id G) x✝

Next tactic:
simp [rightHom]
@[simp]
theorem rightHom_inl (n : N) : rightHom (inl n : N ⋊[φ] G) = 1 := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
n : N
⊢ rightHom (inl n) = 1

Next tactic:
simp [rightHom]
@[simp]
theorem rightHom_inr (g : G) : rightHom (inr g : N ⋊[φ] G) = g := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
g : G
⊢ rightHom (inr g) = g

Next tactic:
simp [rightHom]
theorem range_inl_eq_ker_rightHom : (inl : N →* N ⋊[φ] G).range = rightHom.ker :=
  le_antisymm (fun _ ↦ by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x✝ : N ⋊[φ] G
⊢ x✝ ∈ MonoidHom.range inl → x✝ ∈ MonoidHom.ker rightHom

Next tactic:
simp (config := { contextual := true }) [MonoidHom.mem_ker, eq_comm]
theorem range_inl_eq_ker_rightHom : (inl : N →* N ⋊[φ] G).range = rightHom.ker :=
  le_antisymm (fun _ ↦ by simp (config := { contextual := true }) [MonoidHom.mem_ker, eq_comm])
    fun x hx ↦ ⟨x.left, by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x : N ⋊[φ] G
hx : x ∈ MonoidHom.ker rightHom
⊢ inl x.left = x

Next tactic:
ext
theorem range_inl_eq_ker_rightHom : (inl : N →* N ⋊[φ] G).range = rightHom.ker :=
  le_antisymm (fun _ ↦ by simp (config := { contextual := true }) [MonoidHom.mem_ker, eq_comm])
    fun x hx ↦ ⟨x.left, by ext <;> 

Proof state:
case left
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x : N ⋊[φ] G
hx : x ∈ MonoidHom.ker rightHom
⊢ (inl x.left).left = x.left

Next tactic:
simp_all [MonoidHom.mem_ker]
theorem range_inl_eq_ker_rightHom : (inl : N →* N ⋊[φ] G).range = rightHom.ker :=
  le_antisymm (fun _ ↦ by simp (config := { contextual := true }) [MonoidHom.mem_ker, eq_comm])
    fun x hx ↦ ⟨x.left, by ext <;> 

Proof state:
case right
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
x : N ⋊[φ] G
hx : x ∈ MonoidHom.ker rightHom
⊢ (inl x.left).right = x.right

Next tactic:
simp_all [MonoidHom.mem_ker]
/-- Define a group hom `N ⋊[φ] G →* H`, by defining maps `N →* H` and `G →* H`  -/
def lift (f₁ : N →* H) (f₂ : G →* H)
    (h : ∀ g, f₁.comp (φ g).toMonoidHom = (MulAut.conj (f₂ g)).toMonoidHom.comp f₁) : N ⋊[φ] G →* H
    where
  toFun a := f₁ a.1 * f₂ a.2
  map_one' := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁✝ : N →* H
f₂✝ : G →* H
h✝ :
  ∀ (g : G),
    MonoidHom.comp f₁✝ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂✝ g))) f₁✝
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
⊢ (fun a => f₁ a.left * f₂ a.right) 1 = 1

Next tactic:
simp
/-- Define a group hom `N ⋊[φ] G →* H`, by defining maps `N →* H` and `G →* H`  -/
def lift (f₁ : N →* H) (f₂ : G →* H)
    (h : ∀ g, f₁.comp (φ g).toMonoidHom = (MulAut.conj (f₂ g)).toMonoidHom.comp f₁) : N ⋊[φ] G →* H
    where
  toFun a := f₁ a.1 * f₂ a.2
  map_one' := by simp
  map_mul' a b := by
    

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁✝ : N →* H
f₂✝ : G →* H
h✝ :
  ∀ (g : G),
    MonoidHom.comp f₁✝ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂✝ g))) f₁✝
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
a b : N ⋊[φ] G
⊢ OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } (a * b) =
    OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } a *
      OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } b

Next tactic:
have := fun n g ↦ FunLike.ext_iff.1 (h n) g
/-- Define a group hom `N ⋊[φ] G →* H`, by defining maps `N →* H` and `G →* H`  -/
def lift (f₁ : N →* H) (f₂ : G →* H)
    (h : ∀ g, f₁.comp (φ g).toMonoidHom = (MulAut.conj (f₂ g)).toMonoidHom.comp f₁) : N ⋊[φ] G →* H
    where
  toFun a := f₁ a.1 * f₂ a.2
  map_one' := by simp
  map_mul' a b := by
    have := fun n g ↦ FunLike.ext_iff.1 (h n) g
    

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁✝ : N →* H
f₂✝ : G →* H
h✝ :
  ∀ (g : G),
    MonoidHom.comp f₁✝ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂✝ g))) f₁✝
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
a b : N ⋊[φ] G
this :
  ∀ (n : G) (g : N),
    (MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ n))) g =
      (MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ n))) f₁) g
⊢ OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } (a * b) =
    OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } a *
      OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } b

Next tactic:
simp only [MulAut.conj_apply, MonoidHom.comp_apply, MulEquiv.coe_toMonoidHom] at this
/-- Define a group hom `N ⋊[φ] G →* H`, by defining maps `N →* H` and `G →* H`  -/
def lift (f₁ : N →* H) (f₂ : G →* H)
    (h : ∀ g, f₁.comp (φ g).toMonoidHom = (MulAut.conj (f₂ g)).toMonoidHom.comp f₁) : N ⋊[φ] G →* H
    where
  toFun a := f₁ a.1 * f₂ a.2
  map_one' := by simp
  map_mul' a b := by
    have := fun n g ↦ FunLike.ext_iff.1 (h n) g
    simp only [MulAut.conj_apply, MonoidHom.comp_apply, MulEquiv.coe_toMonoidHom] at this
    

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁✝ : N →* H
f₂✝ : G →* H
h✝ :
  ∀ (g : G),
    MonoidHom.comp f₁✝ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂✝ g))) f₁✝
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
a b : N ⋊[φ] G
this : ∀ (n : G) (g : N), f₁ ((φ n) g) = f₂ n * f₁ g * (f₂ n)⁻¹
⊢ OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } (a * b) =
    OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } a *
      OneHom.toFun { toFun := fun a => f₁ a.left * f₂ a.right, map_one' := (_ : f₁ 1 * f₂ 1 = 1) } b

Next tactic:
simp only [mul_left, mul_right, map_mul, this, mul_assoc, inv_mul_cancel_left]
@[simp]
theorem lift_inl (n : N) : lift f₁ f₂ h (inl n) = f₁ n := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
n : N
⊢ (lift f₁ f₂ h) (inl n) = f₁ n

Next tactic:
simp [lift]
@[simp]
theorem lift_comp_inl : (lift f₁ f₂ h).comp inl = f₁ := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
⊢ MonoidHom.comp (lift f₁ f₂ h) inl = f₁

Next tactic:
ext
@[simp]
theorem lift_comp_inl : (lift f₁ f₂ h).comp inl = f₁ := by ext; 

Proof state:
case h
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
x✝ : N
⊢ (MonoidHom.comp (lift f₁ f₂ h) inl) x✝ = f₁ x✝

Next tactic:
simp
@[simp]
theorem lift_inr (g : G) : lift f₁ f₂ h (inr g) = f₂ g := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
g : G
⊢ (lift f₁ f₂ h) (inr g) = f₂ g

Next tactic:
simp [lift]
@[simp]
theorem lift_comp_inr : (lift f₁ f₂ h).comp inr = f₂ := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
⊢ MonoidHom.comp (lift f₁ f₂ h) inr = f₂

Next tactic:
ext
@[simp]
theorem lift_comp_inr : (lift f₁ f₂ h).comp inr = f₂ := by ext; 

Proof state:
case h
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
x✝ : G
⊢ (MonoidHom.comp (lift f₁ f₂ h) inr) x✝ = f₂ x✝

Next tactic:
simp
theorem lift_unique (F : N ⋊[φ] G →* H) :
    F = lift (F.comp inl) (F.comp inr) fun _ ↦ by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
F : N ⋊[φ] G →* H
x✝ : G
⊢ MonoidHom.comp (MonoidHom.comp F inl) (MulEquiv.toMonoidHom (φ x✝)) =
    MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj ((MonoidHom.comp F inr) x✝))) (MonoidHom.comp F inl)

Next tactic:
ext
theorem lift_unique (F : N ⋊[φ] G →* H) :
    F = lift (F.comp inl) (F.comp inr) fun _ ↦ by ext; 

Proof state:
case h
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
F : N ⋊[φ] G →* H
x✝¹ : G
x✝ : N
⊢ (MonoidHom.comp (MonoidHom.comp F inl) (MulEquiv.toMonoidHom (φ x✝¹))) x✝ =
    (MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj ((MonoidHom.comp F inr) x✝¹))) (MonoidHom.comp F inl)) x✝

Next tactic:
simp [inl_aut]
theorem lift_unique (F : N ⋊[φ] G →* H) :
    F = lift (F.comp inl) (F.comp inr) fun _ ↦ by ext; simp [inl_aut] := by
  

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
F : N ⋊[φ] G →* H
⊢ F =
    lift (MonoidHom.comp F inl) (MonoidHom.comp F inr)
      (_ :
        ∀ (x : G),
          MonoidHom.comp (MonoidHom.comp F inl) (MulEquiv.toMonoidHom (φ x)) =
            MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj ((MonoidHom.comp F inr) x))) (MonoidHom.comp F inl))

Next tactic:
rw [FunLike.ext_iff]
theorem lift_unique (F : N ⋊[φ] G →* H) :
    F = lift (F.comp inl) (F.comp inr) fun _ ↦ by ext; simp [inl_aut] := by
  rw [FunLike.ext_iff]
  

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
F : N ⋊[φ] G →* H
⊢ ∀ (x : N ⋊[φ] G),
    F x =
      (lift (MonoidHom.comp F inl) (MonoidHom.comp F inr)
          (_ :
            ∀ (x : G),
              MonoidHom.comp (MonoidHom.comp F inl) (MulEquiv.toMonoidHom (φ x)) =
                MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj ((MonoidHom.comp F inr) x))) (MonoidHom.comp F inl)))
        x

Next tactic:
simp only [lift, MonoidHom.comp_apply, MonoidHom.coe_mk, OneHom.coe_mk, ← map_mul,
    inl_left_mul_inr_right, forall_const]
/-- Two maps out of the semidirect product are equal if they're equal after composition
  with both `inl` and `inr` -/
theorem hom_ext {f g : N ⋊[φ] G →* H} (hl : f.comp inl = g.comp inl)
    (hr : f.comp inr = g.comp inr) : f = g := by
  

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
f₁ : N →* H
f₂ : G →* H
h :
  ∀ (g : G),
    MonoidHom.comp f₁ (MulEquiv.toMonoidHom (φ g)) = MonoidHom.comp (MulEquiv.toMonoidHom (MulAut.conj (f₂ g))) f₁
f g : N ⋊[φ] G →* H
hl : MonoidHom.comp f inl = MonoidHom.comp g inl
hr : MonoidHom.comp f inr = MonoidHom.comp g inr
⊢ f = g

Next tactic:
rw [lift_unique f, lift_unique g]