l3lab/ntp-mathlib huggingface dataset:
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  

Proof state:
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq' : q ∣ mirror p
⊢ ¬0 < natDegree q

Next tactic:
intro hq''
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  

Proof state:
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq' : q ∣ mirror p
hq'' : 0 < natDegree q
⊢ False

Next tactic:
rw [natDegree_pos_iff_degree_pos] at hq''
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  rw [natDegree_pos_iff_degree_pos] at hq''
  

Proof state:
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq' : q ∣ mirror p
hq'' : 0 < degree q
⊢ False

Next tactic:
rw [← degree_map_eq_of_injective (algebraMap ℤ ℂ).injective_int] at hq''
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  rw [natDegree_pos_iff_degree_pos] at hq''
  rw [← degree_map_eq_of_injective (algebraMap ℤ ℂ).injective_int] at hq''
  

Proof state:
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq' : q ∣ mirror p
hq'' : 0 < degree (map (algebraMap ℤ ℂ) q)
⊢ False

Next tactic:
cases' Complex.exists_root hq'' with z hz
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  rw [natDegree_pos_iff_degree_pos] at hq''
  rw [← degree_map_eq_of_injective (algebraMap ℤ ℂ).injective_int] at hq''
  cases' Complex.exists_root hq'' with z hz
  

Proof state:
case intro
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq' : q ∣ mirror p
hq'' : 0 < degree (map (algebraMap ℤ ℂ) q)
z : ℂ
hz : IsRoot (map (algebraMap ℤ ℂ) q) z
⊢ False

Next tactic:
rw [IsRoot, eval_map, ← aeval_def] at hz
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  rw [natDegree_pos_iff_degree_pos] at hq''
  rw [← degree_map_eq_of_injective (algebraMap ℤ ℂ).injective_int] at hq''
  cases' Complex.exists_root hq'' with z hz
  rw [IsRoot, eval_map, ← aeval_def] at hz
  

Proof state:
case intro
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq' : q ∣ mirror p
hq'' : 0 < degree (map (algebraMap ℤ ℂ) q)
z : ℂ
hz : (aeval z) q = 0
⊢ False

Next tactic:
refine' h z ⟨_, _⟩
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  rw [natDegree_pos_iff_degree_pos] at hq''
  rw [← degree_map_eq_of_injective (algebraMap ℤ ℂ).injective_int] at hq''
  cases' Complex.exists_root hq'' with z hz
  rw [IsRoot, eval_map, ← aeval_def] at hz
  refine' h z ⟨_, _⟩
  · 

Proof state:
case intro.refine'_1
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq' : q ∣ mirror p
hq'' : 0 < degree (map (algebraMap ℤ ℂ) q)
z : ℂ
hz : (aeval z) q = 0
⊢ (aeval z) p = 0

Next tactic:
cases' hq with g' hg'
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  rw [natDegree_pos_iff_degree_pos] at hq''
  rw [← degree_map_eq_of_injective (algebraMap ℤ ℂ).injective_int] at hq''
  cases' Complex.exists_root hq'' with z hz
  rw [IsRoot, eval_map, ← aeval_def] at hz
  refine' h z ⟨_, _⟩
  · cases' hq with g' hg'
    

Proof state:
case intro.refine'_1.intro
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq' : q ∣ mirror p
hq'' : 0 < degree (map (algebraMap ℤ ℂ) q)
z : ℂ
hz : (aeval z) q = 0
g' : ℤ[X]
hg' : p = q * g'
⊢ (aeval z) p = 0

Next tactic:
rw [hg', aeval_mul, hz, zero_mul]
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  rw [natDegree_pos_iff_degree_pos] at hq''
  rw [← degree_map_eq_of_injective (algebraMap ℤ ℂ).injective_int] at hq''
  cases' Complex.exists_root hq'' with z hz
  rw [IsRoot, eval_map, ← aeval_def] at hz
  refine' h z ⟨_, _⟩
  · cases' hq with g' hg'
    rw [hg', aeval_mul, hz, zero_mul]
  · 

Proof state:
case intro.refine'_2
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq' : q ∣ mirror p
hq'' : 0 < degree (map (algebraMap ℤ ℂ) q)
z : ℂ
hz : (aeval z) q = 0
⊢ (aeval z) (mirror p) = 0

Next tactic:
cases' hq' with g' hg'
/-- A unit trinomial is irreducible if it has no complex roots in common with its mirror -/
theorem irreducible_of_coprime' (hp : IsUnitTrinomial p)
    (h : ∀ z : ℂ, ¬(aeval z p = 0 ∧ aeval z (mirror p) = 0)) : Irreducible p := by
  refine' hp.irreducible_of_coprime fun q hq hq' => _
  suffices ¬0 < q.natDegree by
    rcases hq with ⟨p, rfl⟩
    replace hp := hp.leadingCoeff_isUnit
    rw [leadingCoeff_mul] at hp
    replace hp := isUnit_of_mul_isUnit_left hp
    rw [not_lt, le_zero_iff] at this
    rwa [eq_C_of_natDegree_eq_zero this, isUnit_C, ← this]
  intro hq''
  rw [natDegree_pos_iff_degree_pos] at hq''
  rw [← degree_map_eq_of_injective (algebraMap ℤ ℂ).injective_int] at hq''
  cases' Complex.exists_root hq'' with z hz
  rw [IsRoot, eval_map, ← aeval_def] at hz
  refine' h z ⟨_, _⟩
  · cases' hq with g' hg'
    rw [hg', aeval_mul, hz, zero_mul]
  · cases' hq' with g' hg'
    

Proof state:
case intro.refine'_2.intro
p q✝ : ℤ[X]
hp : IsUnitTrinomial p
h : ∀ (z : ℂ), ¬((aeval z) p = 0 ∧ (aeval z) (mirror p) = 0)
q : ℤ[X]
hq : q ∣ p
hq'' : 0 < degree (map (algebraMap ℤ ℂ) q)
z : ℂ
hz : (aeval z) q = 0
g' : ℤ[X]
hg' : mirror p = q * g'
⊢ (aeval z) (mirror p) = 0

Next tactic:
rw [hg', aeval_mul, hz, zero_mul]
/-- Makes a `OneHom` inverse from the bijective inverse of a `OneHom` -/
@[to_additive (attr := simps)
  "Make a `ZeroHom` inverse from the bijective inverse of a `ZeroHom`"]
def OneHom.inverse [One M] [One N]
    (f : OneHom M N) (g : N → M)
    (h₁ : Function.LeftInverse g f) :
  OneHom N M :=
  { toFun := g,
    map_one' := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝¹ : One M
inst✝ : One N
f : OneHom M N
g : N → M
h₁ : Function.LeftInverse g ⇑f
⊢ g 1 = 1

Next tactic:
rw [← f.map_one, h₁]
/-- Makes a multiplicative inverse from a bijection which preserves multiplication. -/
@[to_additive (attr := simps)
  "Makes an additive inverse from a bijection which preserves addition."]
def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M)
    (h₁ : Function.LeftInverse g f)
    (h₂ : Function.RightInverse g f) : N →ₙ* M where
  toFun := g
  map_mul' x y :=
    calc
      g (x * y) = g (f (g x) * f (g y)) := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝¹ : Mul M
inst✝ : Mul N
f : M →ₙ* N
g : N → M
h₁ : Function.LeftInverse g ⇑f
h₂ : Function.RightInverse g ⇑f
x y : N
⊢ g (x * y) = g (f (g x) * f (g y))

Next tactic:
rw [h₂ x, h₂ y]
/-- Makes a multiplicative inverse from a bijection which preserves multiplication. -/
@[to_additive (attr := simps)
  "Makes an additive inverse from a bijection which preserves addition."]
def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M)
    (h₁ : Function.LeftInverse g f)
    (h₂ : Function.RightInverse g f) : N →ₙ* M where
  toFun := g
  map_mul' x y :=
    calc
      g (x * y) = g (f (g x) * f (g y)) := by rw [h₂ x, h₂ y]
      _ = g (f (g x * g y)) := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝¹ : Mul M
inst✝ : Mul N
f : M →ₙ* N
g : N → M
h₁ : Function.LeftInverse g ⇑f
h₂ : Function.RightInverse g ⇑f
x y : N
⊢ g (f (g x) * f (g y)) = g (f (g x * g y))

Next tactic:
rw [f.map_mul]
@[to_additive]
instance (priority := 100) instMonoidHomClass
    [MulOneClass M] [MulOneClass N] [MulEquivClass F M N] :
    MonoidHomClass F M N :=
  { MulEquivClass.instMulHomClass F with
    coe := fun _ => _,
    map_one := fun e =>
      calc
        e 1 = e 1 * 1 := (mul_one _).symm
        _ = e 1 * e (MulEquivClass.toEquivLike.inv e (1 : N) : M) :=
          congr_arg _ (MulEquivClass.toEquivLike.right_inv e 1).symm
        _ = e (MulEquivClass.toEquivLike.inv e (1 : N)) := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝² : MulOneClass M
inst✝¹ : MulOneClass N
inst✝ : MulEquivClass F M N
src✝ : MulHomClass F M N := instMulHomClass F
e : F
⊢ e 1 * e (EquivLike.inv e 1) = e (EquivLike.inv e 1)

Next tactic:
rw [← map_mul, one_mul]
instance (priority := 100) toZeroHomClass
    [MulZeroClass α] [MulZeroClass β] [MulEquivClass F α β] :
    ZeroHomClass F α β where
  map_zero := fun e =>
    calc
      e 0 = e 0 * e (EquivLike.inv e 0) := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝² : MulZeroClass α
inst✝¹ : MulZeroClass β
inst✝ : MulEquivClass F α β
e : F
⊢ e 0 = e 0 * e (EquivLike.inv e 0)

Next tactic:
rw [← map_mul, zero_mul]
instance (priority := 100) toZeroHomClass
    [MulZeroClass α] [MulZeroClass β] [MulEquivClass F α β] :
    ZeroHomClass F α β where
  map_zero := fun e =>
    calc
      e 0 = e 0 * e (EquivLike.inv e 0) := by rw [← map_mul, zero_mul]
        _ = 0 := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝² : MulZeroClass α
inst✝¹ : MulZeroClass β
inst✝ : MulEquivClass F α β
e : F
⊢ e 0 * e (EquivLike.inv e 0) = 0

Next tactic:
simp
@[to_additive]
instance [Mul M] [Mul N] : MulEquivClass (M ≃* N) M N where
  coe f := f.toFun
  inv f := f.invFun
  left_inv f := f.left_inv
  right_inv f := f.right_inv
  coe_injective' f g h₁ h₂ := by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝¹ : Mul M
inst✝ : Mul N
f g : M ≃* N
h₁ : (fun f => f.toFun) f = (fun f => f.toFun) g
h₂ : (fun f => f.invFun) f = (fun f => f.invFun) g
⊢ f = g

Next tactic:
cases f
@[to_additive]
instance [Mul M] [Mul N] : MulEquivClass (M ≃* N) M N where
  coe f := f.toFun
  inv f := f.invFun
  left_inv f := f.left_inv
  right_inv f := f.right_inv
  coe_injective' f g h₁ h₂ := by
    cases f
    

Proof state:
case mk
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝¹ : Mul M
inst✝ : Mul N
g : M ≃* N
toEquiv✝ : M ≃ N
map_mul'✝ : ∀ (x y : M), Equiv.toFun toEquiv✝ (x * y) = Equiv.toFun toEquiv✝ x * Equiv.toFun toEquiv✝ y
h₁ : (fun f => f.toFun) { toEquiv := toEquiv✝, map_mul' := map_mul'✝ } = (fun f => f.toFun) g
h₂ : (fun f => f.invFun) { toEquiv := toEquiv✝, map_mul' := map_mul'✝ } = (fun f => f.invFun) g
⊢ { toEquiv := toEquiv✝, map_mul' := map_mul'✝ } = g

Next tactic:
cases g
@[to_additive]
instance [Mul M] [Mul N] : MulEquivClass (M ≃* N) M N where
  coe f := f.toFun
  inv f := f.invFun
  left_inv f := f.left_inv
  right_inv f := f.right_inv
  coe_injective' f g h₁ h₂ := by
    cases f
    cases g
    

Proof state:
case mk.mk
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝¹ : Mul M
inst✝ : Mul N
toEquiv✝¹ : M ≃ N
map_mul'✝¹ : ∀ (x y : M), Equiv.toFun toEquiv✝¹ (x * y) = Equiv.toFun toEquiv✝¹ x * Equiv.toFun toEquiv✝¹ y
toEquiv✝ : M ≃ N
map_mul'✝ : ∀ (x y : M), Equiv.toFun toEquiv✝ (x * y) = Equiv.toFun toEquiv✝ x * Equiv.toFun toEquiv✝ y
h₁ :
  (fun f => f.toFun) { toEquiv := toEquiv✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.toFun) { toEquiv := toEquiv✝, map_mul' := map_mul'✝ }
h₂ :
  (fun f => f.invFun) { toEquiv := toEquiv✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.invFun) { toEquiv := toEquiv✝, map_mul' := map_mul'✝ }
⊢ { toEquiv := toEquiv✝¹, map_mul' := map_mul'✝¹ } = { toEquiv := toEquiv✝, map_mul' := map_mul'✝ }

Next tactic:
congr
@[to_additive]
instance [Mul M] [Mul N] : MulEquivClass (M ≃* N) M N where
  coe f := f.toFun
  inv f := f.invFun
  left_inv f := f.left_inv
  right_inv f := f.right_inv
  coe_injective' f g h₁ h₂ := by
    cases f
    cases g
    congr
    

Proof state:
case mk.mk.e_toEquiv
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝¹ : Mul M
inst✝ : Mul N
toEquiv✝¹ : M ≃ N
map_mul'✝¹ : ∀ (x y : M), Equiv.toFun toEquiv✝¹ (x * y) = Equiv.toFun toEquiv✝¹ x * Equiv.toFun toEquiv✝¹ y
toEquiv✝ : M ≃ N
map_mul'✝ : ∀ (x y : M), Equiv.toFun toEquiv✝ (x * y) = Equiv.toFun toEquiv✝ x * Equiv.toFun toEquiv✝ y
h₁ :
  (fun f => f.toFun) { toEquiv := toEquiv✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.toFun) { toEquiv := toEquiv✝, map_mul' := map_mul'✝ }
h₂ :
  (fun f => f.invFun) { toEquiv := toEquiv✝¹, map_mul' := map_mul'✝¹ } =
    (fun f => f.invFun) { toEquiv := toEquiv✝, map_mul' := map_mul'✝ }
⊢ toEquiv✝¹ = toEquiv✝

Next tactic:
apply Equiv.coe_fn_injective h₁
/-- Transitivity of multiplication-preserving isomorphisms -/
@[to_additive (attr := trans) "Transitivity of addition-preserving isomorphisms"]
def trans (h1 : M ≃* N) (h2 : N ≃* P) : M ≃* P :=
  { h1.toEquiv.trans h2.toEquiv with
    map_mul' := fun x y => show h2 (h1 (x * y)) = h2 (h1 x) * h2 (h1 y) by
      

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M : Type u_6
N : Type u_7
P : Type u_8
Q : Type u_9
G : Type u_10
H : Type u_11
inst✝³ : Mul M
inst✝² : Mul N
inst✝¹ : Mul P
inst✝ : Mul Q
h1 : M ≃* N
h2 : N ≃* P
src✝ : M ≃ P := h1.trans h2.toEquiv
x y : M
⊢ h2 (h1 (x * y)) = h2 (h1 x) * h2 (h1 y)

Next tactic:
rw [h1.map_mul, h2.map_mul]
/-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) where
  toFun h n := g (h (f.symm n))
  invFun k m := g.symm (k (f m))
  left_inv h := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M✝ : Type u_6
N✝ : Type u_7
P✝ : Type u_8
Q✝ : Type u_9
G : Type u_10
H : Type u_11
inst✝⁵ : Mul M✝
inst✝⁴ : Mul N✝
inst✝³ : Mul P✝
inst✝² : Mul Q✝
M : Type u_12
N : Type u_13
P : Type u_14
Q : Type u_15
inst✝¹ : Mul P
inst✝ : Mul Q
f : M ≃ N
g : P ≃* Q
h : M → P
⊢ (fun k m => (symm g) (k (f m))) ((fun h n => g (h (f.symm n))) h) = h

Next tactic:
ext
/-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) where
  toFun h n := g (h (f.symm n))
  invFun k m := g.symm (k (f m))
  left_inv h := by ext; 

Proof state:
case h
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M✝ : Type u_6
N✝ : Type u_7
P✝ : Type u_8
Q✝ : Type u_9
G : Type u_10
H : Type u_11
inst✝⁵ : Mul M✝
inst✝⁴ : Mul N✝
inst✝³ : Mul P✝
inst✝² : Mul Q✝
M : Type u_12
N : Type u_13
P : Type u_14
Q : Type u_15
inst✝¹ : Mul P
inst✝ : Mul Q
f : M ≃ N
g : P ≃* Q
h : M → P
x✝ : M
⊢ (fun k m => (symm g) (k (f m))) ((fun h n => g (h (f.symm n))) h) x✝ = h x✝

Next tactic:
simp
/-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) where
  toFun h n := g (h (f.symm n))
  invFun k m := g.symm (k (f m))
  left_inv h := by ext; simp
  right_inv k := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M✝ : Type u_6
N✝ : Type u_7
P✝ : Type u_8
Q✝ : Type u_9
G : Type u_10
H : Type u_11
inst✝⁵ : Mul M✝
inst✝⁴ : Mul N✝
inst✝³ : Mul P✝
inst✝² : Mul Q✝
M : Type u_12
N : Type u_13
P : Type u_14
Q : Type u_15
inst✝¹ : Mul P
inst✝ : Mul Q
f : M ≃ N
g : P ≃* Q
k : N → Q
⊢ (fun h n => g (h (f.symm n))) ((fun k m => (symm g) (k (f m))) k) = k

Next tactic:
ext
/-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) where
  toFun h n := g (h (f.symm n))
  invFun k m := g.symm (k (f m))
  left_inv h := by ext; simp
  right_inv k := by ext; 

Proof state:
case h
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M✝ : Type u_6
N✝ : Type u_7
P✝ : Type u_8
Q✝ : Type u_9
G : Type u_10
H : Type u_11
inst✝⁵ : Mul M✝
inst✝⁴ : Mul N✝
inst✝³ : Mul P✝
inst✝² : Mul Q✝
M : Type u_12
N : Type u_13
P : Type u_14
Q : Type u_15
inst✝¹ : Mul P
inst✝ : Mul Q
f : M ≃ N
g : P ≃* Q
k : N → Q
x✝ : N
⊢ (fun h n => g (h (f.symm n))) ((fun k m => (symm g) (k (f m))) k) x✝ = k x✝

Next tactic:
simp
/-- A multiplicative analogue of `Equiv.arrowCongr`,
where the equivalence between the targets is multiplicative.
-/
@[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`,
  where the equivalence between the targets is additive."]
def arrowCongr {M N P Q : Type*} [Mul P] [Mul Q] (f : M ≃ N) (g : P ≃* Q) :
    (M → P) ≃* (N → Q) where
  toFun h n := g (h (f.symm n))
  invFun k m := g.symm (k (f m))
  left_inv h := by ext; simp
  right_inv k := by ext; simp
  map_mul' h k := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
A : Type u_4
B : Type u_5
M✝ : Type u_6
N✝ : Type u_7
P✝ : Type u_8
Q✝ : Type u_9
G : Type u_10
H : Type u_11
inst✝⁵ : Mul M✝
inst✝⁴ : Mul N✝
inst✝³ : Mul P✝
inst✝² : Mul Q✝
M : Type u_12
N : Type u_13
P : Type u_14
Q : Type u_15
inst✝¹ : Mul P
inst✝ : Mul Q
f : M ≃ N
g : P ≃* Q
h k : M → P
⊢ Equiv.toFun
      { toFun := fun h n => g (h (f.symm n)), invFun := fun k m => (symm g) (k (f m)),
        left_inv := (_ : ∀ (h : M → P), (fun k m => (symm g) (k (f m))) ((fun h n => g (h (f.symm n))) h) = h),
        right_inv := (_ : ∀ (k : N → Q), (fun h n => g (h (f.symm n))) ((fun k m => (symm g) (k (f m))) k) = k) }
      (h * k) =
    Equiv.toFun
        { toFun := fun h n => g (h (f.symm n)), invFun := fun k m => (symm g) (k (f m)),
          left_inv := (_ : ∀ (h : M → P), (fun k m => (symm g) (k (f m))) ((fun h n => g (h (f.symm n))) h) = h),
          right_inv := (_ : ∀ (k : N → Q), (fun h n => g (h (f.symm n))) ((fun k m => (symm g) (k (f m))) k) = k) }
        h *
      Equiv.toFun
        { toFun := fun h n => g (h (f.symm n)), invFun := fun k m => (symm g) (k (f m)),
          left_inv := (_ : ∀ (h : M → P), (fun k m => (symm g) (k (f m))) ((fun h n => g (h (f.symm n))) h) = h),
          right_inv := (_ : ∀ (k : N → Q), (fun h n => g (h (f.symm n))) ((fun k m => (symm g) (k (f m))) k) = k) }
        k

Next tactic:
ext