l3lab/ntp-mathlib huggingface dataset:
/-- Given a family of endomorphisms of `C` which are intertwined by a fully faithful `F : C ⥤ D`
with shift functors on `D`, we can promote that family to shift functors on `C`. -/
def hasShiftOfFullyFaithful :
    HasShift C A :=
  hasShiftMk C A
    { F := s
      zero := hasShiftOfFullyFaithful_zero F s i
      add := hasShiftOfFullyFaithful_add F s i
      assoc_hom_app := fun m₁ m₂ m₃ X => F.map_injective (by
        have h := shiftFunctorAdd'_assoc_hom_app m₁ m₂ m₃ _ _ (m₁+m₂+m₃) rfl rfl rfl (F.obj X)
        simp only [shiftFunctorAdd'_eq_shiftFunctorAdd] at h
        rw [← cancel_mono ((i m₃).hom.app ((s m₂).obj ((s m₁).obj X)))]
        simp only [Functor.comp_obj, Functor.map_comp, map_hasShiftOfFullyFaithful_add_hom_app,
          Category.assoc, Iso.inv_hom_id_app_assoc, NatTrans.naturality_assoc, Functor.comp_map,
          Iso.inv_hom_id_app, Category.comp_id]
        erw [(i m₃).hom.naturality]
        rw [Functor.comp_map, map_hasShiftOfFullyFaithful_add_hom_app,
          Functor.map_comp, Functor.map_comp, Iso.inv_hom_id_app_assoc,
          ← Functor.map_comp_assoc _ ((i (m₁ + m₂)).inv.app X), Iso.inv_hom_id_app,
          Functor.map_id, Category.id_comp, reassoc_of% h,
          dcongr_arg (fun a => (i a).hom.app X) (add_assoc m₁ m₂ m₃)]
        simp [shiftFunctorAdd', eqToHom_map])
      zero_add_hom_app := fun n X => F.map_injective (by
        have this := dcongr_arg (fun a => (i a).hom.app X) (zero_add n)
        rw [← cancel_mono ((i n).hom.app ((s 0).obj X)) ]
        simp [this, map_hasShiftOfFullyFaithful_add_hom_app,
          shiftFunctorAdd_zero_add_hom_app, eqToHom_map]
        congr 1
        erw [(i n).hom.naturality]
        dsimp
        

Proof state:
case e_a
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{?u.290838, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
n : A
X : C
this :
  (i (0 + n)).hom.app X =
    eqToHom (_ : (s (0 + n) ⋙ F).obj X = (s n ⋙ F).obj X) ≫
      (i n).hom.app X ≫ eqToHom (_ : (F ⋙ shiftFunctor D n).obj X = (F ⋙ shiftFunctor D (0 + n)).obj X)
⊢ (i n).hom.app X ≫
      (shiftFunctor D n).map ((shiftFunctorZero D A).inv.app (F.obj X)) ≫ (shiftFunctor D n).map ((i 0).inv.app X) =
    (i n).hom.app X ≫ (shiftFunctor D n).map (F.map ((hasShiftOfFullyFaithful_zero F s i).inv.app X))

Next tactic:
simp
/-- Given a family of endomorphisms of `C` which are intertwined by a fully faithful `F : C ⥤ D`
with shift functors on `D`, we can promote that family to shift functors on `C`. -/
def hasShiftOfFullyFaithful :
    HasShift C A :=
  hasShiftMk C A
    { F := s
      zero := hasShiftOfFullyFaithful_zero F s i
      add := hasShiftOfFullyFaithful_add F s i
      assoc_hom_app := fun m₁ m₂ m₃ X => F.map_injective (by
        have h := shiftFunctorAdd'_assoc_hom_app m₁ m₂ m₃ _ _ (m₁+m₂+m₃) rfl rfl rfl (F.obj X)
        simp only [shiftFunctorAdd'_eq_shiftFunctorAdd] at h
        rw [← cancel_mono ((i m₃).hom.app ((s m₂).obj ((s m₁).obj X)))]
        simp only [Functor.comp_obj, Functor.map_comp, map_hasShiftOfFullyFaithful_add_hom_app,
          Category.assoc, Iso.inv_hom_id_app_assoc, NatTrans.naturality_assoc, Functor.comp_map,
          Iso.inv_hom_id_app, Category.comp_id]
        erw [(i m₃).hom.naturality]
        rw [Functor.comp_map, map_hasShiftOfFullyFaithful_add_hom_app,
          Functor.map_comp, Functor.map_comp, Iso.inv_hom_id_app_assoc,
          ← Functor.map_comp_assoc _ ((i (m₁ + m₂)).inv.app X), Iso.inv_hom_id_app,
          Functor.map_id, Category.id_comp, reassoc_of% h,
          dcongr_arg (fun a => (i a).hom.app X) (add_assoc m₁ m₂ m₃)]
        simp [shiftFunctorAdd', eqToHom_map])
      zero_add_hom_app := fun n X => F.map_injective (by
        have this := dcongr_arg (fun a => (i a).hom.app X) (zero_add n)
        rw [← cancel_mono ((i n).hom.app ((s 0).obj X)) ]
        simp [this, map_hasShiftOfFullyFaithful_add_hom_app,
          shiftFunctorAdd_zero_add_hom_app, eqToHom_map]
        congr 1
        erw [(i n).hom.naturality]
        dsimp
        simp)
      add_zero_hom_app := fun n X => F.map_injective (by
        

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{?u.290838, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
n : A
X : C
⊢ F.map ((hasShiftOfFullyFaithful_add F s i n 0).hom.app X) =
    F.map
      (eqToHom (_ : (s (n + 0)).obj X = (𝟭 C).obj ((s n).obj X)) ≫
        (hasShiftOfFullyFaithful_zero F s i).inv.app ((s n).obj X))

Next tactic:
have := dcongr_arg (fun a => (i a).hom.app X) (add_zero n)
/-- Given a family of endomorphisms of `C` which are intertwined by a fully faithful `F : C ⥤ D`
with shift functors on `D`, we can promote that family to shift functors on `C`. -/
def hasShiftOfFullyFaithful :
    HasShift C A :=
  hasShiftMk C A
    { F := s
      zero := hasShiftOfFullyFaithful_zero F s i
      add := hasShiftOfFullyFaithful_add F s i
      assoc_hom_app := fun m₁ m₂ m₃ X => F.map_injective (by
        have h := shiftFunctorAdd'_assoc_hom_app m₁ m₂ m₃ _ _ (m₁+m₂+m₃) rfl rfl rfl (F.obj X)
        simp only [shiftFunctorAdd'_eq_shiftFunctorAdd] at h
        rw [← cancel_mono ((i m₃).hom.app ((s m₂).obj ((s m₁).obj X)))]
        simp only [Functor.comp_obj, Functor.map_comp, map_hasShiftOfFullyFaithful_add_hom_app,
          Category.assoc, Iso.inv_hom_id_app_assoc, NatTrans.naturality_assoc, Functor.comp_map,
          Iso.inv_hom_id_app, Category.comp_id]
        erw [(i m₃).hom.naturality]
        rw [Functor.comp_map, map_hasShiftOfFullyFaithful_add_hom_app,
          Functor.map_comp, Functor.map_comp, Iso.inv_hom_id_app_assoc,
          ← Functor.map_comp_assoc _ ((i (m₁ + m₂)).inv.app X), Iso.inv_hom_id_app,
          Functor.map_id, Category.id_comp, reassoc_of% h,
          dcongr_arg (fun a => (i a).hom.app X) (add_assoc m₁ m₂ m₃)]
        simp [shiftFunctorAdd', eqToHom_map])
      zero_add_hom_app := fun n X => F.map_injective (by
        have this := dcongr_arg (fun a => (i a).hom.app X) (zero_add n)
        rw [← cancel_mono ((i n).hom.app ((s 0).obj X)) ]
        simp [this, map_hasShiftOfFullyFaithful_add_hom_app,
          shiftFunctorAdd_zero_add_hom_app, eqToHom_map]
        congr 1
        erw [(i n).hom.naturality]
        dsimp
        simp)
      add_zero_hom_app := fun n X => F.map_injective (by
        have := dcongr_arg (fun a => (i a).hom.app X) (add_zero n)
        

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{?u.290838, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
n : A
X : C
this :
  (i (n + 0)).hom.app X =
    eqToHom (_ : (s (n + 0) ⋙ F).obj X = (s n ⋙ F).obj X) ≫
      (i n).hom.app X ≫ eqToHom (_ : (F ⋙ shiftFunctor D n).obj X = (F ⋙ shiftFunctor D (n + 0)).obj X)
⊢ F.map ((hasShiftOfFullyFaithful_add F s i n 0).hom.app X) =
    F.map
      (eqToHom (_ : (s (n + 0)).obj X = (𝟭 C).obj ((s n).obj X)) ≫
        (hasShiftOfFullyFaithful_zero F s i).inv.app ((s n).obj X))

Next tactic:
simp [this, ← NatTrans.naturality_assoc, eqToHom_map,
          shiftFunctorAdd_add_zero_hom_app]
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
⊢ Perm.Disjoint (formPerm l) (formPerm l') ↔ Disjoint l l'

Next tactic:
rw [disjoint_iff_eq_or_eq, List.Disjoint]
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
⊢ (∀ (x : α), (formPerm l) x = x ∨ (formPerm l') x = x) ↔ ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False

Next tactic:
constructor
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · 

Proof state:
case mp
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
⊢ (∀ (x : α), (formPerm l) x = x ∨ (formPerm l') x = x) → ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False

Next tactic:
rintro h x hx hx'
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    

Proof state:
case mp
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ (x : α), (formPerm l) x = x ∨ (formPerm l') x = x
x : α
hx : x ∈ l
hx' : x ∈ l'
⊢ False

Next tactic:
specialize h x
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    

Proof state:
case mp
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
x : α
hx : x ∈ l
hx' : x ∈ l'
h : (formPerm l) x = x ∨ (formPerm l') x = x
⊢ False

Next tactic:
rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    

Proof state:
case mp
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
x : α
hx : x ∈ l
hx' : x ∈ l'
h : length l ≤ 1 ∨ length l' ≤ 1
⊢ False

Next tactic:
rcases h with (hl | hl')
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> 

Proof state:
case mp.inl
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl✝ : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
x : α
hx : x ∈ l
hx' : x ∈ l'
hl : length l ≤ 1
⊢ False

Next tactic:
linarith
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> 

Proof state:
case mp.inr
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl'✝ : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
x : α
hx : x ∈ l
hx' : x ∈ l'
hl' : length l' ≤ 1
⊢ False

Next tactic:
linarith
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · 

Proof state:
case mpr
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
⊢ (∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False) → ∀ (x : α), (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
intro h x
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · intro h x
    

Proof state:
case mpr
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
⊢ (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
by_cases hx : x ∈ l
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · intro h x
    by_cases hx : x ∈ l
    

Proof state:
case pos
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∈ l
⊢ (formPerm l) x = x ∨ (formPerm l') x = x
case neg
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∉ l
⊢ (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
by_cases hx' : x ∈ l'
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · intro h x
    by_cases hx : x ∈ l
    by_cases hx' : x ∈ l'
    · 

Proof state:
case pos
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∈ l
hx' : x ∈ l'
⊢ (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
exact (h hx hx').elim
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · intro h x
    by_cases hx : x ∈ l
    by_cases hx' : x ∈ l'
    · exact (h hx hx').elim
    

Proof state:
case neg
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∈ l
hx' : x ∉ l'
⊢ (formPerm l) x = x ∨ (formPerm l') x = x
case neg
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∉ l
⊢ (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
all_goals have := formPerm_eq_self_of_not_mem _ _ ‹_›; tauto
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · intro h x
    by_cases hx : x ∈ l
    by_cases hx' : x ∈ l'
    · exact (h hx hx').elim
    all_goals 

Proof state:
case neg
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∈ l
hx' : x ∉ l'
⊢ (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
have := formPerm_eq_self_of_not_mem _ _ ‹_›
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · intro h x
    by_cases hx : x ∈ l
    by_cases hx' : x ∈ l'
    · exact (h hx hx').elim
    all_goals have := formPerm_eq_self_of_not_mem _ _ ‹_›; 

Proof state:
case neg
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∈ l
hx' : x ∉ l'
this : (formPerm l') x = x
⊢ (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
tauto
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · intro h x
    by_cases hx : x ∈ l
    by_cases hx' : x ∈ l'
    · exact (h hx hx').elim
    all_goals 

Proof state:
case neg
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∉ l
⊢ (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
have := formPerm_eq_self_of_not_mem _ _ ‹_›
theorem formPerm_disjoint_iff (hl : Nodup l) (hl' : Nodup l') (hn : 2 ≤ l.length)
    (hn' : 2 ≤ l'.length) : Perm.Disjoint (formPerm l) (formPerm l') ↔ l.Disjoint l' := by
  rw [disjoint_iff_eq_or_eq, List.Disjoint]
  constructor
  · rintro h x hx hx'
    specialize h x
    rw [formPerm_apply_mem_eq_self_iff _ hl _ hx, formPerm_apply_mem_eq_self_iff _ hl' _ hx'] at h
    rcases h with (hl | hl') <;> linarith
  · intro h x
    by_cases hx : x ∈ l
    by_cases hx' : x ∈ l'
    · exact (h hx hx').elim
    all_goals have := formPerm_eq_self_of_not_mem _ _ ‹_›; 

Proof state:
case neg
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hl' : Nodup l'
hn : 2 ≤ length l
hn' : 2 ≤ length l'
h : ∀ ⦃a : α⦄, a ∈ l → a ∈ l' → False
x : α
hx : x ∉ l
this : (formPerm l) x = x
⊢ (formPerm l) x = x ∨ (formPerm l') x = x

Next tactic:
tauto
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
l l' : List α
hl : Nodup l
hn : 2 ≤ length l
⊢ IsCycle (formPerm l)

Next tactic:
cases' l with x l
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  cases' l with x l
  · 

Proof state:
case nil
α : Type u_1
inst✝ : DecidableEq α
l' : List α
hl : Nodup []
hn : 2 ≤ length []
⊢ IsCycle (formPerm [])

Next tactic:
norm_num at hn
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  cases' l with x l
  · norm_num at hn
  

Proof state:
case cons
α : Type u_1
inst✝ : DecidableEq α
l' : List α
x : α
l : List α
hl : Nodup (x :: l)
hn : 2 ≤ length (x :: l)
⊢ IsCycle (formPerm (x :: l))

Next tactic:
induction' l with y l generalizing x
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  cases' l with x l
  · norm_num at hn
  induction' l with y l generalizing x
  · 

Proof state:
case cons.nil
α : Type u_1
inst✝ : DecidableEq α
l' : List α
x : α
hl : Nodup [x]
hn : 2 ≤ length [x]
⊢ IsCycle (formPerm [x])

Next tactic:
norm_num at hn
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  cases' l with x l
  · norm_num at hn
  induction' l with y l generalizing x
  · norm_num at hn
  · 

Proof state:
case cons.cons
α : Type u_1
inst✝ : DecidableEq α
l' : List α
y : α
l : List α
tail_ih✝ : ∀ (x : α), Nodup (x :: l) → 2 ≤ length (x :: l) → IsCycle (formPerm (x :: l))
x : α
hl : Nodup (x :: y :: l)
hn : 2 ≤ length (x :: y :: l)
⊢ IsCycle (formPerm (x :: y :: l))

Next tactic:
use x
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  cases' l with x l
  · norm_num at hn
  induction' l with y l generalizing x
  · norm_num at hn
  · use x
    

Proof state:
case h
α : Type u_1
inst✝ : DecidableEq α
l' : List α
y : α
l : List α
tail_ih✝ : ∀ (x : α), Nodup (x :: l) → 2 ≤ length (x :: l) → IsCycle (formPerm (x :: l))
x : α
hl : Nodup (x :: y :: l)
hn : 2 ≤ length (x :: y :: l)
⊢ (formPerm (x :: y :: l)) x ≠ x ∧
    ∀ ⦃y_1 : α⦄, (formPerm (x :: y :: l)) y_1 ≠ y_1 → SameCycle (formPerm (x :: y :: l)) x y_1

Next tactic:
constructor
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  cases' l with x l
  · norm_num at hn
  induction' l with y l generalizing x
  · norm_num at hn
  · use x
    constructor
    · 

Proof state:
case h.left
α : Type u_1
inst✝ : DecidableEq α
l' : List α
y : α
l : List α
tail_ih✝ : ∀ (x : α), Nodup (x :: l) → 2 ≤ length (x :: l) → IsCycle (formPerm (x :: l))
x : α
hl : Nodup (x :: y :: l)
hn : 2 ≤ length (x :: y :: l)
⊢ (formPerm (x :: y :: l)) x ≠ x

Next tactic:
rwa [formPerm_apply_mem_ne_self_iff _ hl _ (mem_cons_self _ _)]
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  cases' l with x l
  · norm_num at hn
  induction' l with y l generalizing x
  · norm_num at hn
  · use x
    constructor
    · rwa [formPerm_apply_mem_ne_self_iff _ hl _ (mem_cons_self _ _)]
    · 

Proof state:
case h.right
α : Type u_1
inst✝ : DecidableEq α
l' : List α
y : α
l : List α
tail_ih✝ : ∀ (x : α), Nodup (x :: l) → 2 ≤ length (x :: l) → IsCycle (formPerm (x :: l))
x : α
hl : Nodup (x :: y :: l)
hn : 2 ≤ length (x :: y :: l)
⊢ ∀ ⦃y_1 : α⦄, (formPerm (x :: y :: l)) y_1 ≠ y_1 → SameCycle (formPerm (x :: y :: l)) x y_1

Next tactic:
intro w hw
set_option linter.deprecated false in
theorem isCycle_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : IsCycle (formPerm l) := by
  cases' l with x l
  · norm_num at hn
  induction' l with y l generalizing x
  · norm_num at hn
  · use x
    constructor
    · rwa [formPerm_apply_mem_ne_self_iff _ hl _ (mem_cons_self _ _)]
    · intro w hw
      

Proof state:
case h.right
α : Type u_1
inst✝ : DecidableEq α
l' : List α
y : α
l : List α
tail_ih✝ : ∀ (x : α), Nodup (x :: l) → 2 ≤ length (x :: l) → IsCycle (formPerm (x :: l))
x : α
hl : Nodup (x :: y :: l)
hn : 2 ≤ length (x :: y :: l)
w : α
hw : (formPerm (x :: y :: l)) w ≠ w
⊢ SameCycle (formPerm (x :: y :: l)) x w

Next tactic:
have : w ∈ x::y::l := mem_of_formPerm_ne_self _ _ hw