l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem limLax_μ (F G : J ⥤ C) :
    (@limLax J _ C _ _ _).μ F G =
      limit.lift (F ⊗ G)
        { pt := limit F ⊗ limit G
          π :=
            { app := fun j => limit.π F j ⊗ limit.π G j
              naturality := fun j j' f => by
                dsimp
                

Proof state:
J : Type v
inst✝³ : SmallCategory J
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasLimits C
inst✝ : MonoidalCategory C
F G : J ⥤ C
j j' : J
f : j ⟶ j'
⊢ 𝟙 (limit F ⊗ limit G) ≫ (limit.π F j' ⊗ limit.π G j') = (limit.π F j ⊗ limit.π G j) ≫ (F.map f ⊗ G.map f)

Next tactic:
simp only [Category.id_comp, ← tensor_comp, limit.w]
theorem derivedSeries_normal (n : ℕ) : (derivedSeries G n).Normal := by
  

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
n : ℕ
⊢ Normal (derivedSeries G n)

Next tactic:
induction' n with n ih
theorem derivedSeries_normal (n : ℕ) : (derivedSeries G n).Normal := by
  induction' n with n ih
  · 

Proof state:
case zero
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
⊢ Normal (derivedSeries G Nat.zero)

Next tactic:
exact (⊤ : Subgroup G).normal_of_characteristic
theorem derivedSeries_normal (n : ℕ) : (derivedSeries G n).Normal := by
  induction' n with n ih
  · exact (⊤ : Subgroup G).normal_of_characteristic
  · 

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
n : ℕ
ih : Normal (derivedSeries G n)
⊢ Normal (derivedSeries G (Nat.succ n))

Next tactic:
exact @Subgroup.commutator_normal G _ (derivedSeries G n) (derivedSeries G n) ih ih
theorem map_derivedSeries_le_derivedSeries (n : ℕ) :
    (derivedSeries G n).map f ≤ derivedSeries G' n := by
  

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
n : ℕ
⊢ map f (derivedSeries G n) ≤ derivedSeries G' n

Next tactic:
induction' n with n ih
theorem map_derivedSeries_le_derivedSeries (n : ℕ) :
    (derivedSeries G n).map f ≤ derivedSeries G' n := by
  induction' n with n ih
  · 

Proof state:
case zero
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
⊢ map f (derivedSeries G Nat.zero) ≤ derivedSeries G' Nat.zero

Next tactic:
exact le_top
theorem map_derivedSeries_le_derivedSeries (n : ℕ) :
    (derivedSeries G n).map f ≤ derivedSeries G' n := by
  induction' n with n ih
  · exact le_top
  · 

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
n : ℕ
ih : map f (derivedSeries G n) ≤ derivedSeries G' n
⊢ map f (derivedSeries G (Nat.succ n)) ≤ derivedSeries G' (Nat.succ n)

Next tactic:
simp only [derivedSeries_succ, map_commutator, commutator_mono, ih]
theorem derivedSeries_le_map_derivedSeries (hf : Function.Surjective f) (n : ℕ) :
    derivedSeries G' n ≤ (derivedSeries G n).map f := by
  

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
hf : Function.Surjective ⇑f
n : ℕ
⊢ derivedSeries G' n ≤ map f (derivedSeries G n)

Next tactic:
induction' n with n ih
theorem derivedSeries_le_map_derivedSeries (hf : Function.Surjective f) (n : ℕ) :
    derivedSeries G' n ≤ (derivedSeries G n).map f := by
  induction' n with n ih
  · 

Proof state:
case zero
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
hf : Function.Surjective ⇑f
⊢ derivedSeries G' Nat.zero ≤ map f (derivedSeries G Nat.zero)

Next tactic:
exact (map_top_of_surjective f hf).ge
theorem derivedSeries_le_map_derivedSeries (hf : Function.Surjective f) (n : ℕ) :
    derivedSeries G' n ≤ (derivedSeries G n).map f := by
  induction' n with n ih
  · exact (map_top_of_surjective f hf).ge
  · 

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
hf : Function.Surjective ⇑f
n : ℕ
ih : derivedSeries G' n ≤ map f (derivedSeries G n)
⊢ derivedSeries G' (Nat.succ n) ≤ map f (derivedSeries G (Nat.succ n))

Next tactic:
exact commutator_le_map_commutator ih ih
theorem isSolvable_of_comm {G : Type*} [hG : Group G] (h : ∀ a b : G, a * b = b * a) :
    IsSolvable G := by
  

Proof state:
G✝ : Type u_1
G' : Type u_2
inst✝¹ : Group G✝
inst✝ : Group G'
f : G✝ →* G'
G : Type u_3
hG : Group G
h : ∀ (a b : G), a * b = b * a
⊢ IsSolvable G

Next tactic:
letI hG' : CommGroup G := { hG with mul_comm := h }
theorem isSolvable_of_comm {G : Type*} [hG : Group G] (h : ∀ a b : G, a * b = b * a) :
    IsSolvable G := by
  letI hG' : CommGroup G := { hG with mul_comm := h }
  

Proof state:
G✝ : Type u_1
G' : Type u_2
inst✝¹ : Group G✝
inst✝ : Group G'
f : G✝ →* G'
G : Type u_3
hG : Group G
h : ∀ (a b : G), a * b = b * a
hG' : CommGroup G := CommGroup.mk h
⊢ IsSolvable G

Next tactic:
cases hG
theorem isSolvable_of_comm {G : Type*} [hG : Group G] (h : ∀ a b : G, a * b = b * a) :
    IsSolvable G := by
  letI hG' : CommGroup G := { hG with mul_comm := h }
  cases hG
  

Proof state:
case mk
G✝ : Type u_1
G' : Type u_2
inst✝¹ : Group G✝
inst✝ : Group G'
f : G✝ →* G'
G : Type u_3
toDivInvMonoid✝ : DivInvMonoid G
mul_left_inv✝ : ∀ (a : G), a⁻¹ * a = 1
h : ∀ (a b : G), a * b = b * a
hG' : CommGroup G := CommGroup.mk h
⊢ IsSolvable G

Next tactic:
exact CommGroup.isSolvable
instance (priority := 100) isSolvable_of_subsingleton [Subsingleton G] : IsSolvable G :=
  isSolvable_of_top_eq_bot G (by 

Proof state:
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : Subsingleton G
⊢ ⊤ = ⊥

Next tactic:
simp [eq_iff_true_of_subsingleton]
theorem solvable_of_ker_le_range {G' G'' : Type*} [Group G'] [Group G''] (f : G' →* G)
    (g : G →* G'') (hfg : g.ker ≤ f.range) [hG' : IsSolvable G'] [hG'' : IsSolvable G''] :
    IsSolvable G := by
  

Proof state:
G : Type u_1
G'✝ : Type u_2
inst✝³ : Group G
inst✝² : Group G'✝
f✝ : G →* G'✝
G' : Type u_3
G'' : Type u_4
inst✝¹ : Group G'
inst✝ : Group G''
f : G' →* G
g : G →* G''
hfg : MonoidHom.ker g ≤ MonoidHom.range f
hG' : IsSolvable G'
hG'' : IsSolvable G''
⊢ IsSolvable G

Next tactic:
obtain ⟨n, hn⟩ := id hG''
theorem solvable_of_ker_le_range {G' G'' : Type*} [Group G'] [Group G''] (f : G' →* G)
    (g : G →* G'') (hfg : g.ker ≤ f.range) [hG' : IsSolvable G'] [hG'' : IsSolvable G''] :
    IsSolvable G := by
  obtain ⟨n, hn⟩ := id hG''
  

Proof state:
case mk.intro
G : Type u_1
G'✝ : Type u_2
inst✝³ : Group G
inst✝² : Group G'✝
f✝ : G →* G'✝
G' : Type u_3
G'' : Type u_4
inst✝¹ : Group G'
inst✝ : Group G''
f : G' →* G
g : G →* G''
hfg : MonoidHom.ker g ≤ MonoidHom.range f
hG' : IsSolvable G'
hG'' : IsSolvable G''
n : ℕ
hn : derivedSeries G'' n = ⊥
⊢ IsSolvable G

Next tactic:
obtain ⟨m, hm⟩ := id hG'
theorem solvable_of_ker_le_range {G' G'' : Type*} [Group G'] [Group G''] (f : G' →* G)
    (g : G →* G'') (hfg : g.ker ≤ f.range) [hG' : IsSolvable G'] [hG'' : IsSolvable G''] :
    IsSolvable G := by
  obtain ⟨n, hn⟩ := id hG''
  obtain ⟨m, hm⟩ := id hG'
  

Proof state:
case mk.intro.mk.intro
G : Type u_1
G'✝ : Type u_2
inst✝³ : Group G
inst✝² : Group G'✝
f✝ : G →* G'✝
G' : Type u_3
G'' : Type u_4
inst✝¹ : Group G'
inst✝ : Group G''
f : G' →* G
g : G →* G''
hfg : MonoidHom.ker g ≤ MonoidHom.range f
hG' : IsSolvable G'
hG'' : IsSolvable G''
n : ℕ
hn : derivedSeries G'' n = ⊥
m : ℕ
hm : derivedSeries G' m = ⊥
⊢ IsSolvable G

Next tactic:
refine' ⟨⟨n + m, le_bot_iff.mp (map_bot f ▸ hm ▸ _)⟩⟩
theorem solvable_of_ker_le_range {G' G'' : Type*} [Group G'] [Group G''] (f : G' →* G)
    (g : G →* G'') (hfg : g.ker ≤ f.range) [hG' : IsSolvable G'] [hG'' : IsSolvable G''] :
    IsSolvable G := by
  obtain ⟨n, hn⟩ := id hG''
  obtain ⟨m, hm⟩ := id hG'
  refine' ⟨⟨n + m, le_bot_iff.mp (map_bot f ▸ hm ▸ _)⟩⟩
  

Proof state:
case mk.intro.mk.intro
G : Type u_1
G'✝ : Type u_2
inst✝³ : Group G
inst✝² : Group G'✝
f✝ : G →* G'✝
G' : Type u_3
G'' : Type u_4
inst✝¹ : Group G'
inst✝ : Group G''
f : G' →* G
g : G →* G''
hfg : MonoidHom.ker g ≤ MonoidHom.range f
hG' : IsSolvable G'
hG'' : IsSolvable G''
n : ℕ
hn : derivedSeries G'' n = ⊥
m : ℕ
hm : derivedSeries G' m = ⊥
⊢ derivedSeries G (n + m) ≤ map f (derivedSeries G' m)

Next tactic:
clear hm
theorem solvable_of_ker_le_range {G' G'' : Type*} [Group G'] [Group G''] (f : G' →* G)
    (g : G →* G'') (hfg : g.ker ≤ f.range) [hG' : IsSolvable G'] [hG'' : IsSolvable G''] :
    IsSolvable G := by
  obtain ⟨n, hn⟩ := id hG''
  obtain ⟨m, hm⟩ := id hG'
  refine' ⟨⟨n + m, le_bot_iff.mp (map_bot f ▸ hm ▸ _)⟩⟩
  clear hm
  

Proof state:
case mk.intro.mk.intro
G : Type u_1
G'✝ : Type u_2
inst✝³ : Group G
inst✝² : Group G'✝
f✝ : G →* G'✝
G' : Type u_3
G'' : Type u_4
inst✝¹ : Group G'
inst✝ : Group G''
f : G' →* G
g : G →* G''
hfg : MonoidHom.ker g ≤ MonoidHom.range f
hG' : IsSolvable G'
hG'' : IsSolvable G''
n : ℕ
hn : derivedSeries G'' n = ⊥
m : ℕ
⊢ derivedSeries G (n + m) ≤ map f (derivedSeries G' m)

Next tactic:
induction' m with m hm
theorem solvable_of_ker_le_range {G' G'' : Type*} [Group G'] [Group G''] (f : G' →* G)
    (g : G →* G'') (hfg : g.ker ≤ f.range) [hG' : IsSolvable G'] [hG'' : IsSolvable G''] :
    IsSolvable G := by
  obtain ⟨n, hn⟩ := id hG''
  obtain ⟨m, hm⟩ := id hG'
  refine' ⟨⟨n + m, le_bot_iff.mp (map_bot f ▸ hm ▸ _)⟩⟩
  clear hm
  induction' m with m hm
  · 

Proof state:
case mk.intro.mk.intro.zero
G : Type u_1
G'✝ : Type u_2
inst✝³ : Group G
inst✝² : Group G'✝
f✝ : G →* G'✝
G' : Type u_3
G'' : Type u_4
inst✝¹ : Group G'
inst✝ : Group G''
f : G' →* G
g : G →* G''
hfg : MonoidHom.ker g ≤ MonoidHom.range f
hG' : IsSolvable G'
hG'' : IsSolvable G''
n : ℕ
hn : derivedSeries G'' n = ⊥
⊢ derivedSeries G (n + Nat.zero) ≤ map f (derivedSeries G' Nat.zero)

Next tactic:
exact f.range_eq_map ▸ ((derivedSeries G n).map_eq_bot_iff.mp
      (le_bot_iff.mp ((map_derivedSeries_le_derivedSeries g n).trans hn.le))).trans hfg
theorem solvable_of_ker_le_range {G' G'' : Type*} [Group G'] [Group G''] (f : G' →* G)
    (g : G →* G'') (hfg : g.ker ≤ f.range) [hG' : IsSolvable G'] [hG'' : IsSolvable G''] :
    IsSolvable G := by
  obtain ⟨n, hn⟩ := id hG''
  obtain ⟨m, hm⟩ := id hG'
  refine' ⟨⟨n + m, le_bot_iff.mp (map_bot f ▸ hm ▸ _)⟩⟩
  clear hm
  induction' m with m hm
  · exact f.range_eq_map ▸ ((derivedSeries G n).map_eq_bot_iff.mp
      (le_bot_iff.mp ((map_derivedSeries_le_derivedSeries g n).trans hn.le))).trans hfg
  · 

Proof state:
case mk.intro.mk.intro.succ
G : Type u_1
G'✝ : Type u_2
inst✝³ : Group G
inst✝² : Group G'✝
f✝ : G →* G'✝
G' : Type u_3
G'' : Type u_4
inst✝¹ : Group G'
inst✝ : Group G''
f : G' →* G
g : G →* G''
hfg : MonoidHom.ker g ≤ MonoidHom.range f
hG' : IsSolvable G'
hG'' : IsSolvable G''
n : ℕ
hn : derivedSeries G'' n = ⊥
m : ℕ
hm : derivedSeries G (n + m) ≤ map f (derivedSeries G' m)
⊢ derivedSeries G (n + Nat.succ m) ≤ map f (derivedSeries G' (Nat.succ m))

Next tactic:
exact commutator_le_map_commutator hm hm
theorem IsSimpleGroup.derivedSeries_succ {n : ℕ} : derivedSeries G n.succ = commutator G := by
  

Proof state:
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
n : ℕ
⊢ derivedSeries G (Nat.succ n) = _root_.commutator G

Next tactic:
induction' n with n ih
theorem IsSimpleGroup.derivedSeries_succ {n : ℕ} : derivedSeries G n.succ = commutator G := by
  induction' n with n ih
  · 

Proof state:
case zero
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
⊢ derivedSeries G (Nat.succ Nat.zero) = _root_.commutator G

Next tactic:
exact derivedSeries_one G
theorem IsSimpleGroup.derivedSeries_succ {n : ℕ} : derivedSeries G n.succ = commutator G := by
  induction' n with n ih
  · exact derivedSeries_one G
  

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
n : ℕ
ih : derivedSeries G (Nat.succ n) = _root_.commutator G
⊢ derivedSeries G (Nat.succ (Nat.succ n)) = _root_.commutator G

Next tactic:
rw [_root_.derivedSeries_succ, ih, _root_.commutator]
theorem IsSimpleGroup.derivedSeries_succ {n : ℕ} : derivedSeries G n.succ = commutator G := by
  induction' n with n ih
  · exact derivedSeries_one G
  rw [_root_.derivedSeries_succ, ih, _root_.commutator]
  

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
n : ℕ
ih : derivedSeries G (Nat.succ n) = _root_.commutator G
⊢ ⁅⁅⊤, ⊤⁆, ⁅⊤, ⊤⁆⁆ = ⁅⊤, ⊤⁆

Next tactic:
cases' (commutator_normal (⊤ : Subgroup G) (⊤ : Subgroup G)).eq_bot_or_eq_top with h h
theorem IsSimpleGroup.derivedSeries_succ {n : ℕ} : derivedSeries G n.succ = commutator G := by
  induction' n with n ih
  · exact derivedSeries_one G
  rw [_root_.derivedSeries_succ, ih, _root_.commutator]
  cases' (commutator_normal (⊤ : Subgroup G) (⊤ : Subgroup G)).eq_bot_or_eq_top with h h
  · 

Proof state:
case succ.inl
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
n : ℕ
ih : derivedSeries G (Nat.succ n) = _root_.commutator G
h : ⁅⊤, ⊤⁆ = ⊥
⊢ ⁅⁅⊤, ⊤⁆, ⁅⊤, ⊤⁆⁆ = ⁅⊤, ⊤⁆

Next tactic:
rw [h, commutator_bot_left]
theorem IsSimpleGroup.derivedSeries_succ {n : ℕ} : derivedSeries G n.succ = commutator G := by
  induction' n with n ih
  · exact derivedSeries_one G
  rw [_root_.derivedSeries_succ, ih, _root_.commutator]
  cases' (commutator_normal (⊤ : Subgroup G) (⊤ : Subgroup G)).eq_bot_or_eq_top with h h
  · rw [h, commutator_bot_left]
  · 

Proof state:
case succ.inr
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
n : ℕ
ih : derivedSeries G (Nat.succ n) = _root_.commutator G
h : ⁅⊤, ⊤⁆ = ⊤
⊢ ⁅⁅⊤, ⊤⁆, ⁅⊤, ⊤⁆⁆ = ⁅⊤, ⊤⁆

Next tactic:
rwa [h]
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    

Proof state:
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
n : ℕ
hn : derivedSeries G n = ⊥
⊢ ∀ (a b : G), a * b = b * a

Next tactic:
cases n
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · 

Proof state:
case zero
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
hn : derivedSeries G Nat.zero = ⊥
⊢ ∀ (a b : G), a * b = b * a

Next tactic:
intro a b
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      

Proof state:
case zero
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
hn : derivedSeries G Nat.zero = ⊥
a b : G
⊢ a * b = b * a

Next tactic:
refine' (mem_bot.1 _).trans (mem_bot.1 _).symm
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      refine' (mem_bot.1 _).trans (mem_bot.1 _).symm <;>
        · 

Proof state:
case zero.refine'_1
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
hn : derivedSeries G Nat.zero = ⊥
a b : G
⊢ a * b ∈ ⊥

Next tactic:
rw [← hn]
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      refine' (mem_bot.1 _).trans (mem_bot.1 _).symm <;>
        · rw [← hn]
          

Proof state:
case zero.refine'_1
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
hn : derivedSeries G Nat.zero = ⊥
a b : G
⊢ a * b ∈ derivedSeries G Nat.zero

Next tactic:
exact mem_top _
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      refine' (mem_bot.1 _).trans (mem_bot.1 _).symm <;>
        · 

Proof state:
case zero.refine'_2
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
hn : derivedSeries G Nat.zero = ⊥
a b : G
⊢ b * a ∈ ⊥

Next tactic:
rw [← hn]
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      refine' (mem_bot.1 _).trans (mem_bot.1 _).symm <;>
        · rw [← hn]
          

Proof state:
case zero.refine'_2
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
hn : derivedSeries G Nat.zero = ⊥
a b : G
⊢ b * a ∈ derivedSeries G Nat.zero

Next tactic:
exact mem_top _
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      refine' (mem_bot.1 _).trans (mem_bot.1 _).symm <;>
        · rw [← hn]
          exact mem_top _
    · 

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
n✝ : ℕ
hn : derivedSeries G (Nat.succ n✝) = ⊥
⊢ ∀ (a b : G), a * b = b * a

Next tactic:
rw [IsSimpleGroup.derivedSeries_succ] at hn
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      refine' (mem_bot.1 _).trans (mem_bot.1 _).symm <;>
        · rw [← hn]
          exact mem_top _
    · rw [IsSimpleGroup.derivedSeries_succ] at hn
      

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
n✝ : ℕ
hn : _root_.commutator G = ⊥
⊢ ∀ (a b : G), a * b = b * a

Next tactic:
intro a b
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      refine' (mem_bot.1 _).trans (mem_bot.1 _).symm <;>
        · rw [← hn]
          exact mem_top _
    · rw [IsSimpleGroup.derivedSeries_succ] at hn
      intro a b
      

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
n✝ : ℕ
hn : _root_.commutator G = ⊥
a b : G
⊢ a * b = b * a

Next tactic:
rw [← mul_inv_eq_one, mul_inv_rev, ← mul_assoc, ← mem_bot, ← hn, commutator_eq_closure]
theorem IsSimpleGroup.comm_iff_isSolvable : (∀ a b : G, a * b = b * a) ↔ IsSolvable G :=
  ⟨isSolvable_of_comm, fun ⟨⟨n, hn⟩⟩ => by
    cases n
    · intro a b
      refine' (mem_bot.1 _).trans (mem_bot.1 _).symm <;>
        · rw [← hn]
          exact mem_top _
    · rw [IsSimpleGroup.derivedSeries_succ] at hn
      intro a b
      rw [← mul_inv_eq_one, mul_inv_rev, ← mul_assoc, ← mem_bot, ← hn, commutator_eq_closure]
      

Proof state:
case succ
G : Type u_1
G' : Type u_2
inst✝² : Group G
inst✝¹ : Group G'
f : G →* G'
inst✝ : IsSimpleGroup G
x✝ : IsSolvable G
n✝ : ℕ
hn : _root_.commutator G = ⊥
a b : G
⊢ a * b * a⁻¹ * b⁻¹ ∈ closure (commutatorSet G)

Next tactic:
exact subset_closure ⟨a, b, rfl⟩
theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by
  

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
⊢ ¬IsSolvable (Perm (Fin 5))

Next tactic:
let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by decide, by decide⟩
theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by
  let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by 

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
⊢ Function.LeftInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]

Next tactic:
decide
theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by
  let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by decide, by 

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
⊢ Function.RightInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]

Next tactic:
decide
theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by
  let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by decide, by decide⟩
  

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
x : Perm (Fin 5) :=
  { toFun := ![1, 2, 0, 3, 4], invFun := ![2, 0, 1, 3, 4],
    left_inv := (_ : Function.LeftInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]),
    right_inv := (_ : Function.RightInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]) }
⊢ ¬IsSolvable (Perm (Fin 5))

Next tactic:
let y : Equiv.Perm (Fin 5) := ⟨![3, 4, 2, 0, 1], ![3, 4, 2, 0, 1], by decide, by decide⟩
theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by
  let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by decide, by decide⟩
  let y : Equiv.Perm (Fin 5) := ⟨![3, 4, 2, 0, 1], ![3, 4, 2, 0, 1], by 

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
x : Perm (Fin 5) :=
  { toFun := ![1, 2, 0, 3, 4], invFun := ![2, 0, 1, 3, 4],
    left_inv := (_ : Function.LeftInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]),
    right_inv := (_ : Function.RightInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]) }
⊢ Function.LeftInverse ![3, 4, 2, 0, 1] ![3, 4, 2, 0, 1]

Next tactic:
decide
theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by
  let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by decide, by decide⟩
  let y : Equiv.Perm (Fin 5) := ⟨![3, 4, 2, 0, 1], ![3, 4, 2, 0, 1], by decide, by 

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
x : Perm (Fin 5) :=
  { toFun := ![1, 2, 0, 3, 4], invFun := ![2, 0, 1, 3, 4],
    left_inv := (_ : Function.LeftInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]),
    right_inv := (_ : Function.RightInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]) }
⊢ Function.RightInverse ![3, 4, 2, 0, 1] ![3, 4, 2, 0, 1]

Next tactic:
decide
theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by
  let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by decide, by decide⟩
  let y : Equiv.Perm (Fin 5) := ⟨![3, 4, 2, 0, 1], ![3, 4, 2, 0, 1], by decide, by decide⟩
  

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
x : Perm (Fin 5) :=
  { toFun := ![1, 2, 0, 3, 4], invFun := ![2, 0, 1, 3, 4],
    left_inv := (_ : Function.LeftInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]),
    right_inv := (_ : Function.RightInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]) }
y : Perm (Fin 5) :=
  { toFun := ![3, 4, 2, 0, 1], invFun := ![3, 4, 2, 0, 1],
    left_inv := (_ : Function.LeftInverse ![3, 4, 2, 0, 1] ![3, 4, 2, 0, 1]),
    right_inv := (_ : Function.RightInverse ![3, 4, 2, 0, 1] ![3, 4, 2, 0, 1]) }
⊢ ¬IsSolvable (Perm (Fin 5))

Next tactic:
let z : Equiv.Perm (Fin 5) := ⟨![0, 3, 2, 1, 4], ![0, 3, 2, 1, 4], by decide, by decide⟩
theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by
  let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by decide, by decide⟩
  let y : Equiv.Perm (Fin 5) := ⟨![3, 4, 2, 0, 1], ![3, 4, 2, 0, 1], by decide, by decide⟩
  let z : Equiv.Perm (Fin 5) := ⟨![0, 3, 2, 1, 4], ![0, 3, 2, 1, 4], by 

Proof state:
G : Type u_1
G' : Type u_2
inst✝¹ : Group G
inst✝ : Group G'
f : G →* G'
x : Perm (Fin 5) :=
  { toFun := ![1, 2, 0, 3, 4], invFun := ![2, 0, 1, 3, 4],
    left_inv := (_ : Function.LeftInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]),
    right_inv := (_ : Function.RightInverse ![2, 0, 1, 3, 4] ![1, 2, 0, 3, 4]) }
y : Perm (Fin 5) :=
  { toFun := ![3, 4, 2, 0, 1], invFun := ![3, 4, 2, 0, 1],
    left_inv := (_ : Function.LeftInverse ![3, 4, 2, 0, 1] ![3, 4, 2, 0, 1]),
    right_inv := (_ : Function.RightInverse ![3, 4, 2, 0, 1] ![3, 4, 2, 0, 1]) }
⊢ Function.LeftInverse ![0, 3, 2, 1, 4] ![0, 3, 2, 1, 4]

Next tactic:
decide