l3lab/ntp-mathlib huggingface dataset:
open scoped List in
theorem list_cycles_perm_list_cycles {α : Type*} [Finite α] {l₁ l₂ : List (Perm α)}
    (h₀ : l₁.prod = l₂.prod) (h₁l₁ : ∀ σ : Perm α, σ ∈ l₁ → σ.IsCycle)
    (h₁l₂ : ∀ σ : Perm α, σ ∈ l₂ → σ.IsCycle) (h₂l₁ : l₁.Pairwise Disjoint)
    (h₂l₂ : l₂.Pairwise Disjoint) : l₁ ~ l₂ := by
  classical
    refine'
      (List.perm_ext_iff_of_nodup (nodup_of_pairwise_disjoint_cycles h₁l₁ h₂l₁)
            (nodup_of_pairwise_disjoint_cycles h₁l₂ h₂l₂)).mpr
        fun σ => _
    by_cases hσ : σ.IsCycle
    · 

Proof state:
case pos
ι : Type u_1
α✝ : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α✝
α : Type u_4
inst✝ : Finite α
l₁ l₂ : List (Perm α)
h₀ : List.prod l₁ = List.prod l₂
h₁l₁ : ∀ σ ∈ l₁, IsCycle σ
h₁l₂ : ∀ σ ∈ l₂, IsCycle σ
h₂l₁ : List.Pairwise Disjoint l₁
h₂l₂ : List.Pairwise Disjoint l₂
σ : Perm α
hσ : IsCycle σ
⊢ σ ∈ l₁ ↔ σ ∈ l₂

Next tactic:
obtain _ := not_forall.mp (mt ext hσ.ne_one)
open scoped List in
theorem list_cycles_perm_list_cycles {α : Type*} [Finite α] {l₁ l₂ : List (Perm α)}
    (h₀ : l₁.prod = l₂.prod) (h₁l₁ : ∀ σ : Perm α, σ ∈ l₁ → σ.IsCycle)
    (h₁l₂ : ∀ σ : Perm α, σ ∈ l₂ → σ.IsCycle) (h₂l₁ : l₁.Pairwise Disjoint)
    (h₂l₂ : l₂.Pairwise Disjoint) : l₁ ~ l₂ := by
  classical
    refine'
      (List.perm_ext_iff_of_nodup (nodup_of_pairwise_disjoint_cycles h₁l₁ h₂l₁)
            (nodup_of_pairwise_disjoint_cycles h₁l₂ h₂l₂)).mpr
        fun σ => _
    by_cases hσ : σ.IsCycle
    · obtain _ := not_forall.mp (mt ext hσ.ne_one)
      

Proof state:
case pos
ι : Type u_1
α✝ : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α✝
α : Type u_4
inst✝ : Finite α
l₁ l₂ : List (Perm α)
h₀ : List.prod l₁ = List.prod l₂
h₁l₁ : ∀ σ ∈ l₁, IsCycle σ
h₁l₂ : ∀ σ ∈ l₂, IsCycle σ
h₂l₁ : List.Pairwise Disjoint l₁
h₂l₂ : List.Pairwise Disjoint l₂
σ : Perm α
hσ : IsCycle σ
x✝ : ∃ x, ¬σ x = 1 x
⊢ σ ∈ l₁ ↔ σ ∈ l₂

Next tactic:
rw [mem_list_cycles_iff h₁l₁ h₂l₁, mem_list_cycles_iff h₁l₂ h₂l₂, h₀]
open scoped List in
theorem list_cycles_perm_list_cycles {α : Type*} [Finite α] {l₁ l₂ : List (Perm α)}
    (h₀ : l₁.prod = l₂.prod) (h₁l₁ : ∀ σ : Perm α, σ ∈ l₁ → σ.IsCycle)
    (h₁l₂ : ∀ σ : Perm α, σ ∈ l₂ → σ.IsCycle) (h₂l₁ : l₁.Pairwise Disjoint)
    (h₂l₂ : l₂.Pairwise Disjoint) : l₁ ~ l₂ := by
  classical
    refine'
      (List.perm_ext_iff_of_nodup (nodup_of_pairwise_disjoint_cycles h₁l₁ h₂l₁)
            (nodup_of_pairwise_disjoint_cycles h₁l₂ h₂l₂)).mpr
        fun σ => _
    by_cases hσ : σ.IsCycle
    · obtain _ := not_forall.mp (mt ext hσ.ne_one)
      rw [mem_list_cycles_iff h₁l₁ h₂l₁, mem_list_cycles_iff h₁l₂ h₂l₂, h₀]
    · 

Proof state:
case neg
ι : Type u_1
α✝ : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α✝
α : Type u_4
inst✝ : Finite α
l₁ l₂ : List (Perm α)
h₀ : List.prod l₁ = List.prod l₂
h₁l₁ : ∀ σ ∈ l₁, IsCycle σ
h₁l₂ : ∀ σ ∈ l₂, IsCycle σ
h₂l₁ : List.Pairwise Disjoint l₁
h₂l₂ : List.Pairwise Disjoint l₂
σ : Perm α
hσ : ¬IsCycle σ
⊢ σ ∈ l₁ ↔ σ ∈ l₂

Next tactic:
exact iff_of_false (mt (h₁l₁ σ) hσ) (mt (h₁l₂ σ) hσ)
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
⊢ cycleFactorsFinset σ = List.toFinset l ↔ (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ

Next tactic:
obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  

Proof state:
case intro.mk.intro.intro
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
⊢ cycleFactorsFinset σ = List.toFinset l ↔ (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ

Next tactic:
have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
⊢ cycleFactorsFinset σ = List.toFinset l'

Next tactic:
rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  

Proof state:
case intro.mk.intro.intro
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
⊢ cycleFactorsFinset σ = List.toFinset l ↔ (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ

Next tactic:
rw [ht]
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  

Proof state:
case intro.mk.intro.intro
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
⊢ List.toFinset l' = List.toFinset l ↔ (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ

Next tactic:
constructor
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · 

Proof state:
case intro.mk.intro.intro.mp
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
⊢ List.toFinset l' = List.toFinset l → (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ

Next tactic:
intro h
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    

Proof state:
case intro.mk.intro.intro.mp
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
⊢ (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ

Next tactic:
have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    

Proof state:
case intro.mk.intro.intro.mp
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
hn' : List.Nodup l'
⊢ (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ

Next tactic:
have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    

Proof state:
case intro.mk.intro.intro.mp
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
hn' : List.Nodup l'
hperm : l ~ l'
⊢ (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ

Next tactic:
refine' ⟨_, _, _⟩
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    refine' ⟨_, _, _⟩
    · 

Proof state:
case intro.mk.intro.intro.mp.refine'_1
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
hn' : List.Nodup l'
hperm : l ~ l'
⊢ ∀ f ∈ l, IsCycle f

Next tactic:
exact fun _ h => hc' _ (hperm.subset h)
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    refine' ⟨_, _, _⟩
    · exact fun _ h => hc' _ (hperm.subset h)
    · 

Proof state:
case intro.mk.intro.intro.mp.refine'_2
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
hn' : List.Nodup l'
hperm : l ~ l'
⊢ List.Pairwise Disjoint l

Next tactic:
have := List.Perm.pairwise_iff (@Disjoint.symmetric _) hperm
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    refine' ⟨_, _, _⟩
    · exact fun _ h => hc' _ (hperm.subset h)
    · have := List.Perm.pairwise_iff (@Disjoint.symmetric _) hperm
      

Proof state:
case intro.mk.intro.intro.mp.refine'_2
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
hn' : List.Nodup l'
hperm : l ~ l'
this : List.Pairwise (fun x y => Disjoint x y) l ↔ List.Pairwise (fun x y => Disjoint x y) l'
⊢ List.Pairwise Disjoint l

Next tactic:
rwa [this]
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    refine' ⟨_, _, _⟩
    · exact fun _ h => hc' _ (hperm.subset h)
    · have := List.Perm.pairwise_iff (@Disjoint.symmetric _) hperm
      rwa [this]
    · 

Proof state:
case intro.mk.intro.intro.mp.refine'_3
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
hn' : List.Nodup l'
hperm : l ~ l'
⊢ List.prod l = σ

Next tactic:
rw [← hp', hperm.symm.prod_eq']
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    refine' ⟨_, _, _⟩
    · exact fun _ h => hc' _ (hperm.subset h)
    · have := List.Perm.pairwise_iff (@Disjoint.symmetric _) hperm
      rwa [this]
    · rw [← hp', hperm.symm.prod_eq']
      

Proof state:
case intro.mk.intro.intro.mp.refine'_3
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
hn' : List.Nodup l'
hperm : l ~ l'
⊢ List.Pairwise Commute l'

Next tactic:
refine' hd'.imp _
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    refine' ⟨_, _, _⟩
    · exact fun _ h => hc' _ (hperm.subset h)
    · have := List.Perm.pairwise_iff (@Disjoint.symmetric _) hperm
      rwa [this]
    · rw [← hp', hperm.symm.prod_eq']
      refine' hd'.imp _
      

Proof state:
case intro.mk.intro.intro.mp.refine'_3
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
h : List.toFinset l' = List.toFinset l
hn' : List.Nodup l'
hperm : l ~ l'
⊢ ∀ {a b : Perm α}, Disjoint a b → Commute a b

Next tactic:
exact Disjoint.commute
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    refine' ⟨_, _, _⟩
    · exact fun _ h => hc' _ (hperm.subset h)
    · have := List.Perm.pairwise_iff (@Disjoint.symmetric _) hperm
      rwa [this]
    · rw [← hp', hperm.symm.prod_eq']
      refine' hd'.imp _
      exact Disjoint.commute
  · 

Proof state:
case intro.mk.intro.intro.mpr
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
⊢ (∀ f ∈ l, IsCycle f) ∧ List.Pairwise Disjoint l ∧ List.prod l = σ → List.toFinset l' = List.toFinset l

Next tactic:
rintro ⟨hc, hd, hp⟩
open scoped List in
theorem cycleFactorsFinset_eq_list_toFinset {σ : Perm α} {l : List (Perm α)} (hn : l.Nodup) :
    σ.cycleFactorsFinset = l.toFinset ↔
      (∀ f : Perm α, f ∈ l → f.IsCycle) ∧ l.Pairwise Disjoint ∧ l.prod = σ := by
  obtain ⟨⟨l', hp', hc', hd'⟩, hl⟩ := Trunc.exists_rep σ.truncCycleFactors
  have ht : cycleFactorsFinset σ = l'.toFinset := by
    rw [cycleFactorsFinset, ← hl, Trunc.lift_mk]
  rw [ht]
  constructor
  · intro h
    have hn' : l'.Nodup := nodup_of_pairwise_disjoint_cycles hc' hd'
    have hperm : l ~ l' := List.perm_of_nodup_nodup_toFinset_eq hn hn' h.symm
    refine' ⟨_, _, _⟩
    · exact fun _ h => hc' _ (hperm.subset h)
    · have := List.Perm.pairwise_iff (@Disjoint.symmetric _) hperm
      rwa [this]
    · rw [← hp', hperm.symm.prod_eq']
      refine' hd'.imp _
      exact Disjoint.commute
  · rintro ⟨hc, hd, hp⟩
    

Proof state:
case intro.mk.intro.intro.mpr.intro.intro
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝¹ : DecidableEq α
inst✝ : Fintype α
f σ : Perm α
l : List (Perm α)
hn : List.Nodup l
l' : List (Perm α)
hp' : List.prod l' = σ
hc' : ∀ g ∈ l', IsCycle g
hd' : List.Pairwise Disjoint l'
hl :
  Trunc.mk { val := l', property := (_ : List.prod l' = σ ∧ (∀ g ∈ l', IsCycle g) ∧ List.Pairwise Disjoint l') } =
    truncCycleFactors σ
ht : cycleFactorsFinset σ = List.toFinset l'
hc : ∀ f ∈ l, IsCycle f
hd : List.Pairwise Disjoint l
hp : List.prod l = σ
⊢ List.toFinset l' = List.toFinset l

Next tactic:
refine' List.toFinset_eq_of_perm _ _ _