l3lab/ntp-mathlib huggingface dataset:
open Classical in
/-- The map `Nobeling.ι` is a closed embedding. -/
theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) := by
  apply Continuous.closedEmbedding
  · dsimp (config := { unfoldPartialApp := true }) [ι]
    refine continuous_pi ?_
    intro C
    rw [← IsLocallyConstant.iff_continuous]
    refine ((IsLocallyConstant.tfae _).out 0 3).mpr ?_
    rintro ⟨⟩
    · refine IsClopen.isOpen (isClopen_compl_iff.mp ?_)
      convert C.2
      ext x
      simp only [Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        decide_eq_false_iff_not, not_not]
    · refine IsClopen.isOpen ?_
      convert C.2
      ext x
      simp only [Set.mem_preimage, Set.mem_singleton_iff, decide_eq_true_eq]
  · 

Proof state:
case hf
S : Profinite
⊢ Function.Injective (ι S)

Next tactic:
intro a b h
open Classical in
/-- The map `Nobeling.ι` is a closed embedding. -/
theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) := by
  apply Continuous.closedEmbedding
  · dsimp (config := { unfoldPartialApp := true }) [ι]
    refine continuous_pi ?_
    intro C
    rw [← IsLocallyConstant.iff_continuous]
    refine ((IsLocallyConstant.tfae _).out 0 3).mpr ?_
    rintro ⟨⟩
    · refine IsClopen.isOpen (isClopen_compl_iff.mp ?_)
      convert C.2
      ext x
      simp only [Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        decide_eq_false_iff_not, not_not]
    · refine IsClopen.isOpen ?_
      convert C.2
      ext x
      simp only [Set.mem_preimage, Set.mem_singleton_iff, decide_eq_true_eq]
  · intro a b h
    

Proof state:
case hf
S : Profinite
a b : ↑S.toCompHaus.toTop
h : ι S a = ι S b
⊢ a = b

Next tactic:
by_contra hn
open Classical in
/-- The map `Nobeling.ι` is a closed embedding. -/
theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) := by
  apply Continuous.closedEmbedding
  · dsimp (config := { unfoldPartialApp := true }) [ι]
    refine continuous_pi ?_
    intro C
    rw [← IsLocallyConstant.iff_continuous]
    refine ((IsLocallyConstant.tfae _).out 0 3).mpr ?_
    rintro ⟨⟩
    · refine IsClopen.isOpen (isClopen_compl_iff.mp ?_)
      convert C.2
      ext x
      simp only [Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        decide_eq_false_iff_not, not_not]
    · refine IsClopen.isOpen ?_
      convert C.2
      ext x
      simp only [Set.mem_preimage, Set.mem_singleton_iff, decide_eq_true_eq]
  · intro a b h
    by_contra hn
    

Proof state:
case hf
S : Profinite
a b : ↑S.toCompHaus.toTop
h : ι S a = ι S b
hn : ¬a = b
⊢ False

Next tactic:
obtain ⟨C, hC, hh⟩ := exists_isClopen_of_totally_separated hn
open Classical in
/-- The map `Nobeling.ι` is a closed embedding. -/
theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) := by
  apply Continuous.closedEmbedding
  · dsimp (config := { unfoldPartialApp := true }) [ι]
    refine continuous_pi ?_
    intro C
    rw [← IsLocallyConstant.iff_continuous]
    refine ((IsLocallyConstant.tfae _).out 0 3).mpr ?_
    rintro ⟨⟩
    · refine IsClopen.isOpen (isClopen_compl_iff.mp ?_)
      convert C.2
      ext x
      simp only [Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        decide_eq_false_iff_not, not_not]
    · refine IsClopen.isOpen ?_
      convert C.2
      ext x
      simp only [Set.mem_preimage, Set.mem_singleton_iff, decide_eq_true_eq]
  · intro a b h
    by_contra hn
    obtain ⟨C, hC, hh⟩ := exists_isClopen_of_totally_separated hn
    

Proof state:
case hf.intro.intro
S : Profinite
a b : ↑S.toCompHaus.toTop
h : ι S a = ι S b
hn : ¬a = b
C : Set ↑S.toCompHaus.toTop
hC : IsClopen C
hh : a ∈ C ∧ b ∈ Cᶜ
⊢ False

Next tactic:
apply hh.2 ∘ of_decide_eq_true
open Classical in
/-- The map `Nobeling.ι` is a closed embedding. -/
theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) := by
  apply Continuous.closedEmbedding
  · dsimp (config := { unfoldPartialApp := true }) [ι]
    refine continuous_pi ?_
    intro C
    rw [← IsLocallyConstant.iff_continuous]
    refine ((IsLocallyConstant.tfae _).out 0 3).mpr ?_
    rintro ⟨⟩
    · refine IsClopen.isOpen (isClopen_compl_iff.mp ?_)
      convert C.2
      ext x
      simp only [Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        decide_eq_false_iff_not, not_not]
    · refine IsClopen.isOpen ?_
      convert C.2
      ext x
      simp only [Set.mem_preimage, Set.mem_singleton_iff, decide_eq_true_eq]
  · intro a b h
    by_contra hn
    obtain ⟨C, hC, hh⟩ := exists_isClopen_of_totally_separated hn
    apply hh.2 ∘ of_decide_eq_true
    

Proof state:
case hf.intro.intro
S : Profinite
a b : ↑S.toCompHaus.toTop
h : ι S a = ι S b
hn : ¬a = b
C : Set ↑S.toCompHaus.toTop
hC : IsClopen C
hh : a ∈ C ∧ b ∈ Cᶜ
⊢ decide (b ∈ C) = true

Next tactic:
dsimp (config := { unfoldPartialApp := true }) [ι] at h
open Classical in
/-- The map `Nobeling.ι` is a closed embedding. -/
theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) := by
  apply Continuous.closedEmbedding
  · dsimp (config := { unfoldPartialApp := true }) [ι]
    refine continuous_pi ?_
    intro C
    rw [← IsLocallyConstant.iff_continuous]
    refine ((IsLocallyConstant.tfae _).out 0 3).mpr ?_
    rintro ⟨⟩
    · refine IsClopen.isOpen (isClopen_compl_iff.mp ?_)
      convert C.2
      ext x
      simp only [Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        decide_eq_false_iff_not, not_not]
    · refine IsClopen.isOpen ?_
      convert C.2
      ext x
      simp only [Set.mem_preimage, Set.mem_singleton_iff, decide_eq_true_eq]
  · intro a b h
    by_contra hn
    obtain ⟨C, hC, hh⟩ := exists_isClopen_of_totally_separated hn
    apply hh.2 ∘ of_decide_eq_true
    dsimp (config := { unfoldPartialApp := true }) [ι] at h
    

Proof state:
case hf.intro.intro
S : Profinite
a b : ↑S.toCompHaus.toTop
h : (fun C => decide (a ∈ ↑C)) = fun C => decide (b ∈ ↑C)
hn : ¬a = b
C : Set ↑S.toCompHaus.toTop
hC : IsClopen C
hh : a ∈ C ∧ b ∈ Cᶜ
⊢ decide (b ∈ C) = true

Next tactic:
rw [← congr_fun h ⟨C, hC⟩]
open Classical in
/-- The map `Nobeling.ι` is a closed embedding. -/
theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) := by
  apply Continuous.closedEmbedding
  · dsimp (config := { unfoldPartialApp := true }) [ι]
    refine continuous_pi ?_
    intro C
    rw [← IsLocallyConstant.iff_continuous]
    refine ((IsLocallyConstant.tfae _).out 0 3).mpr ?_
    rintro ⟨⟩
    · refine IsClopen.isOpen (isClopen_compl_iff.mp ?_)
      convert C.2
      ext x
      simp only [Set.mem_compl_iff, Set.mem_preimage, Set.mem_singleton_iff,
        decide_eq_false_iff_not, not_not]
    · refine IsClopen.isOpen ?_
      convert C.2
      ext x
      simp only [Set.mem_preimage, Set.mem_singleton_iff, decide_eq_true_eq]
  · intro a b h
    by_contra hn
    obtain ⟨C, hC, hh⟩ := exists_isClopen_of_totally_separated hn
    apply hh.2 ∘ of_decide_eq_true
    dsimp (config := { unfoldPartialApp := true }) [ι] at h
    rw [← congr_fun h ⟨C, hC⟩]
    

Proof state:
case hf.intro.intro
S : Profinite
a b : ↑S.toCompHaus.toTop
h : (fun C => decide (a ∈ ↑C)) = fun C => decide (b ∈ ↑C)
hn : ¬a = b
C : Set ↑S.toCompHaus.toTop
hC : IsClopen C
hh : a ∈ C ∧ b ∈ Cᶜ
⊢ decide (a ∈ ↑{ val := C, property := hC }) = true

Next tactic:
exact decide_eq_true hh.1
theorem mem_sym2_cons_iff {x : α} {xs : List α} {z : Sym2 α} :
    z ∈ (x :: xs).sym2 ↔ z = ⟦(x, x)⟧ ∨ (∃ y, y ∈ xs ∧ z = ⟦(x, y)⟧) ∨ z ∈ xs.sym2 := by
  

Proof state:
α : Type u_1
x : α
xs : List α
z : Sym2 α
⊢ z ∈ List.sym2 (x :: xs) ↔ z = ⟦(x, x)⟧ ∨ (∃ y ∈ xs, z = ⟦(x, y)⟧) ∨ z ∈ List.sym2 xs

Next tactic:
simp only [List.sym2, map_cons, cons_append, mem_cons, mem_append, mem_map]
theorem mem_sym2_cons_iff {x : α} {xs : List α} {z : Sym2 α} :
    z ∈ (x :: xs).sym2 ↔ z = ⟦(x, x)⟧ ∨ (∃ y, y ∈ xs ∧ z = ⟦(x, y)⟧) ∨ z ∈ xs.sym2 := by
  simp only [List.sym2, map_cons, cons_append, mem_cons, mem_append, mem_map]
  

Proof state:
α : Type u_1
x : α
xs : List α
z : Sym2 α
⊢ z = ⟦(x, x)⟧ ∨ (∃ a ∈ xs, ⟦(x, a)⟧ = z) ∨ z ∈ List.sym2 xs ↔
    z = ⟦(x, x)⟧ ∨ (∃ y ∈ xs, z = ⟦(x, y)⟧) ∨ z ∈ List.sym2 xs

Next tactic:
simp only [eq_comm]
@[simp]
theorem sym2_eq_nil_iff {xs : List α} : xs.sym2 = [] ↔ xs = [] := by
  

Proof state:
α : Type u_1
xs : List α
⊢ List.sym2 xs = [] ↔ xs = []

Next tactic:
cases xs
@[simp]
theorem sym2_eq_nil_iff {xs : List α} : xs.sym2 = [] ↔ xs = [] := by
  cases xs <;> 

Proof state:
case nil
α : Type u_1
⊢ List.sym2 [] = [] ↔ [] = []

Next tactic:
simp [List.sym2]
@[simp]
theorem sym2_eq_nil_iff {xs : List α} : xs.sym2 = [] ↔ xs = [] := by
  cases xs <;> 

Proof state:
case cons
α : Type u_1
head✝ : α
tail✝ : List α
⊢ List.sym2 (head✝ :: tail✝) = [] ↔ head✝ :: tail✝ = []

Next tactic:
simp [List.sym2]
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  

Proof state:
α : Type u_1
xs : List α
a b : α
h : ⟦(a, b)⟧ ∈ List.sym2 xs
⊢ a ∈ xs

Next tactic:
induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · rw [Sym2.eq_iff, ← and_or_left] at h
      exact .inl h.1
    · rw [Sym2.eq_iff] at h
      obtain (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) := h <;> simp [hc]
    · exact .inr <| ih h
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  

Proof state:
case nil
α : Type u_1
a b : α
h : ⟦(a, b)⟧ ∈ List.sym2 []
⊢ a ∈ []

Next tactic:
| nil => exact (not_mem_nil _ h).elim
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => 

Proof state:
case nil
α : Type u_1
a b : α
h : ⟦(a, b)⟧ ∈ List.sym2 []
⊢ a ∈ []

Next tactic:
exact (not_mem_nil _ h).elim
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  

Proof state:
case cons
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
h : ⟦(a, b)⟧ ∈ List.sym2 (x :: xs)
⊢ a ∈ x :: xs

Next tactic:
| cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · rw [Sym2.eq_iff, ← and_or_left] at h
      exact .inl h.1
    · rw [Sym2.eq_iff] at h
      obtain (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) := h <;> simp [hc]
    · exact .inr <| ih h
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    

Proof state:
case cons
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
h : ⟦(a, b)⟧ ∈ List.sym2 (x :: xs)
⊢ a ∈ x :: xs

Next tactic:
rw [mem_cons]
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    

Proof state:
case cons
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
h : ⟦(a, b)⟧ ∈ List.sym2 (x :: xs)
⊢ a = x ∨ a ∈ xs

Next tactic:
rw [mem_sym2_cons_iff] at h
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    

Proof state:
case cons
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
h : ⟦(a, b)⟧ = ⟦(x, x)⟧ ∨ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(x, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs
⊢ a = x ∨ a ∈ xs

Next tactic:
obtain (h | ⟨c, hc, h⟩ | h) := h
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · 

Proof state:
case cons.inl
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
h : ⟦(a, b)⟧ = ⟦(x, x)⟧
⊢ a = x ∨ a ∈ xs

Next tactic:
rw [Sym2.eq_iff, ← and_or_left] at h
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · rw [Sym2.eq_iff, ← and_or_left] at h
      

Proof state:
case cons.inl
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
h : a = x ∧ (b = x ∨ b = x)
⊢ a = x ∨ a ∈ xs

Next tactic:
exact .inl h.1
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · rw [Sym2.eq_iff, ← and_or_left] at h
      exact .inl h.1
    · 

Proof state:
case cons.inr.inl.intro.intro
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
c : α
hc : c ∈ xs
h : ⟦(a, b)⟧ = ⟦(x, c)⟧
⊢ a = x ∨ a ∈ xs

Next tactic:
rw [Sym2.eq_iff] at h
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · rw [Sym2.eq_iff, ← and_or_left] at h
      exact .inl h.1
    · rw [Sym2.eq_iff] at h
      

Proof state:
case cons.inr.inl.intro.intro
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
c : α
hc : c ∈ xs
h : a = x ∧ b = c ∨ a = c ∧ b = x
⊢ a = x ∨ a ∈ xs

Next tactic:
obtain (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) := h
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · rw [Sym2.eq_iff, ← and_or_left] at h
      exact .inl h.1
    · rw [Sym2.eq_iff] at h
      obtain (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) := h <;> 

Proof state:
case cons.inr.inl.intro.intro.inl.intro
α : Type u_1
a b : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
hc : b ∈ xs
⊢ a = a ∨ a ∈ xs

Next tactic:
simp [hc]
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · rw [Sym2.eq_iff, ← and_or_left] at h
      exact .inl h.1
    · rw [Sym2.eq_iff] at h
      obtain (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) := h <;> 

Proof state:
case cons.inr.inl.intro.intro.inr.intro
α : Type u_1
a b : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
hc : a ∈ xs
⊢ a = b ∨ a ∈ xs

Next tactic:
simp [hc]
theorem left_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : a ∈ xs := by
  induction xs with
  | nil => exact (not_mem_nil _ h).elim
  | cons x xs ih =>
    rw [mem_cons]
    rw [mem_sym2_cons_iff] at h
    obtain (h | ⟨c, hc, h⟩ | h) := h
    · rw [Sym2.eq_iff, ← and_or_left] at h
      exact .inl h.1
    · rw [Sym2.eq_iff] at h
      obtain (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) := h <;> simp [hc]
    · 

Proof state:
case cons.inr.inr
α : Type u_1
a b x : α
xs : List α
ih : ⟦(a, b)⟧ ∈ List.sym2 xs → a ∈ xs
h : ⟦(a, b)⟧ ∈ List.sym2 xs
⊢ a = x ∨ a ∈ xs

Next tactic:
exact .inr <| ih h
theorem right_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : b ∈ xs := by
  

Proof state:
α : Type u_1
xs : List α
a b : α
h : ⟦(a, b)⟧ ∈ List.sym2 xs
⊢ b ∈ xs

Next tactic:
rw [Sym2.eq_swap] at h
theorem right_mem_of_mk_mem_sym2 {xs : List α} {a b : α}
    (h : ⟦(a, b)⟧ ∈ xs.sym2) : b ∈ xs := by
  rw [Sym2.eq_swap] at h
  

Proof state:
α : Type u_1
xs : List α
a b : α
h : ⟦(b, a)⟧ ∈ List.sym2 xs
⊢ b ∈ xs

Next tactic:
exact left_mem_of_mk_mem_sym2 h
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  

Proof state:
α : Type u_1
xs : List α
a b : α
ha : a ∈ xs
hb : b ∈ xs
⊢ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · right; left; use b
    · right; left; rw [Sym2.eq_swap]; use a
    · right; right; exact ih ha hb
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  

Proof state:
case nil
α : Type u_1
a b : α
ha : a ∈ []
hb : b ∈ []
⊢ ⟦(a, b)⟧ ∈ List.sym2 []

Next tactic:
| nil => simp at ha
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => 

Proof state:
case nil
α : Type u_1
a b : α
ha : a ∈ []
hb : b ∈ []
⊢ ⟦(a, b)⟧ ∈ List.sym2 []

Next tactic:
simp at ha
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  

Proof state:
case cons
α : Type u_1
a b x : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
ha : a ∈ x :: xs
hb : b ∈ x :: xs
⊢ ⟦(a, b)⟧ ∈ List.sym2 (x :: xs)

Next tactic:
| cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · right; left; use b
    · right; left; rw [Sym2.eq_swap]; use a
    · right; right; exact ih ha hb
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    

Proof state:
case cons
α : Type u_1
a b x : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
ha : a ∈ x :: xs
hb : b ∈ x :: xs
⊢ ⟦(a, b)⟧ ∈ List.sym2 (x :: xs)

Next tactic:
rw [mem_sym2_cons_iff]
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    

Proof state:
case cons
α : Type u_1
a b x : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
ha : a ∈ x :: xs
hb : b ∈ x :: xs
⊢ ⟦(a, b)⟧ = ⟦(x, x)⟧ ∨ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(x, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
rw [mem_cons] at ha hb
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    

Proof state:
case cons
α : Type u_1
a b x : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
ha : a = x ∨ a ∈ xs
hb : b = x ∨ b ∈ xs
⊢ ⟦(a, b)⟧ = ⟦(x, x)⟧ ∨ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(x, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
obtain (rfl | ha) := ha
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> 

Proof state:
case cons.inl
α : Type u_1
a b : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
hb : b = a ∨ b ∈ xs
⊢ ⟦(a, b)⟧ = ⟦(a, a)⟧ ∨ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(a, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
obtain (rfl | hb) := hb
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> 

Proof state:
case cons.inr
α : Type u_1
a b x : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
hb : b = x ∨ b ∈ xs
ha : a ∈ xs
⊢ ⟦(a, b)⟧ = ⟦(x, x)⟧ ∨ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(x, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
obtain (rfl | hb) := hb
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · 

Proof state:
case cons.inl.inl
α : Type u_1
b : α
xs : List α
ih : b ∈ xs → b ∈ xs → ⟦(b, b)⟧ ∈ List.sym2 xs
⊢ ⟦(b, b)⟧ = ⟦(b, b)⟧ ∨ (∃ y ∈ xs, ⟦(b, b)⟧ = ⟦(b, y)⟧) ∨ ⟦(b, b)⟧ ∈ List.sym2 xs

Next tactic:
left
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; 

Proof state:
case cons.inl.inl.h
α : Type u_1
b : α
xs : List α
ih : b ∈ xs → b ∈ xs → ⟦(b, b)⟧ ∈ List.sym2 xs
⊢ ⟦(b, b)⟧ = ⟦(b, b)⟧

Next tactic:
rfl
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · 

Proof state:
case cons.inl.inr
α : Type u_1
a b : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
hb : b ∈ xs
⊢ ⟦(a, b)⟧ = ⟦(a, a)⟧ ∨ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(a, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
right
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · right; 

Proof state:
case cons.inl.inr.h
α : Type u_1
a b : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
hb : b ∈ xs
⊢ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(a, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
left
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · right; left; 

Proof state:
case cons.inl.inr.h.h
α : Type u_1
a b : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
hb : b ∈ xs
⊢ ∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(a, y)⟧

Next tactic:
use b
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · right; left; use b
    · 

Proof state:
case cons.inr.inl
α : Type u_1
a b : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
ha : a ∈ xs
⊢ ⟦(a, b)⟧ = ⟦(b, b)⟧ ∨ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(b, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
right
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · right; left; use b
    · right; 

Proof state:
case cons.inr.inl.h
α : Type u_1
a b : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
ha : a ∈ xs
⊢ (∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(b, y)⟧) ∨ ⟦(a, b)⟧ ∈ List.sym2 xs

Next tactic:
left
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · right; left; use b
    · right; left; 

Proof state:
case cons.inr.inl.h.h
α : Type u_1
a b : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
ha : a ∈ xs
⊢ ∃ y ∈ xs, ⟦(a, b)⟧ = ⟦(b, y)⟧

Next tactic:
rw [Sym2.eq_swap]
theorem mk_mem_sym2 {xs : List α} {a b : α} (ha : a ∈ xs) (hb : b ∈ xs) :
    ⟦(a, b)⟧ ∈ xs.sym2 := by
  induction xs with
  | nil => simp at ha
  | cons x xs ih =>
    rw [mem_sym2_cons_iff]
    rw [mem_cons] at ha hb
    obtain (rfl | ha) := ha <;> obtain (rfl | hb) := hb
    · left; rfl
    · right; left; use b
    · right; left; rw [Sym2.eq_swap]; 

Proof state:
case cons.inr.inl.h.h
α : Type u_1
a b : α
xs : List α
ih : a ∈ xs → b ∈ xs → ⟦(a, b)⟧ ∈ List.sym2 xs
ha : a ∈ xs
⊢ ∃ y ∈ xs, ⟦(b, a)⟧ = ⟦(b, y)⟧

Next tactic:
use a