l3lab/ntp-mathlib huggingface dataset:
theorem card_sym_fin_eq_multichoose : ∀ n k : ℕ, card (Sym (Fin n) k) = multichoose n k
  | n, 0 => by simp
  | 0, k + 1 => by rw [multichoose_zero_succ]; exact card_eq_zero
  | 1, k + 1 => by simp
  | n + 2, k + 1 => by
    rw [multichoose_succ_succ, ← card_sym_fin_eq_multichoose (n + 1) (k + 1),
      ← card_sym_fin_eq_multichoose (n + 2) k, add_comm (Fintype.card _), ← card_sum]
    

Proof state:
α : Type u_1
β : Type u_2
n✝ n k : ℕ
⊢ Fintype.card (Sym (Fin (n + 2)) (k + 1)) = Fintype.card (Sym (Fin (n + 2)) k ⊕ Sym (Fin (n + 1)) (k + 1))

Next tactic:
refine Fintype.card_congr (Equiv.symm ?_)
theorem card_sym_fin_eq_multichoose : ∀ n k : ℕ, card (Sym (Fin n) k) = multichoose n k
  | n, 0 => by simp
  | 0, k + 1 => by rw [multichoose_zero_succ]; exact card_eq_zero
  | 1, k + 1 => by simp
  | n + 2, k + 1 => by
    rw [multichoose_succ_succ, ← card_sym_fin_eq_multichoose (n + 1) (k + 1),
      ← card_sym_fin_eq_multichoose (n + 2) k, add_comm (Fintype.card _), ← card_sum]
    refine Fintype.card_congr (Equiv.symm ?_)
    

Proof state:
α : Type u_1
β : Type u_2
n✝ n k : ℕ
⊢ Sym (Fin (n + 2)) k ⊕ Sym (Fin (n + 1)) (k + 1) ≃ Sym (Fin (n + 2)) (k + 1)

Next tactic:
apply (Sym.e1.symm.sumCongr Sym.e2.symm).trans
theorem card_sym_fin_eq_multichoose : ∀ n k : ℕ, card (Sym (Fin n) k) = multichoose n k
  | n, 0 => by simp
  | 0, k + 1 => by rw [multichoose_zero_succ]; exact card_eq_zero
  | 1, k + 1 => by simp
  | n + 2, k + 1 => by
    rw [multichoose_succ_succ, ← card_sym_fin_eq_multichoose (n + 1) (k + 1),
      ← card_sym_fin_eq_multichoose (n + 2) k, add_comm (Fintype.card _), ← card_sum]
    refine Fintype.card_congr (Equiv.symm ?_)
    apply (Sym.e1.symm.sumCongr Sym.e2.symm).trans
    

Proof state:
α : Type u_1
β : Type u_2
n✝ n k : ℕ
⊢ { s // 0 ∈ s } ⊕ { s // 0 ∉ s } ≃ Sym (Fin (n + 2)) (k + 1)

Next tactic:
apply Equiv.sumCompl
/-- For any fintype `α` of cardinality `n`, `card (Sym α k) = multichoose (card α) k`. -/
theorem card_sym_eq_multichoose (α : Type*) (k : ℕ) [Fintype α] [Fintype (Sym α k)] :
    card (Sym α k) = multichoose (card α) k := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
n : ℕ
α : Type u_3
k : ℕ
inst✝¹ : Fintype α
inst✝ : Fintype (Sym α k)
⊢ Fintype.card (Sym α k) = multichoose (Fintype.card α) k

Next tactic:
rw [← card_sym_fin_eq_multichoose]
/-- For any fintype `α` of cardinality `n`, `card (Sym α k) = multichoose (card α) k`. -/
theorem card_sym_eq_multichoose (α : Type*) (k : ℕ) [Fintype α] [Fintype (Sym α k)] :
    card (Sym α k) = multichoose (card α) k := by
  rw [← card_sym_fin_eq_multichoose]
  

Proof state:
α✝ : Type u_1
β : Type u_2
n : ℕ
α : Type u_3
k : ℕ
inst✝¹ : Fintype α
inst✝ : Fintype (Sym α k)
⊢ Fintype.card (Sym α k) = Fintype.card (Sym (Fin (Fintype.card α)) k)

Next tactic:
exact card_congr (equivCongr (equivFin α))
/-- The *stars and bars* lemma: the cardinality of `Sym α k` is equal to
`Nat.choose (card α + k - 1) k`. -/
theorem card_sym_eq_choose {α : Type*} [Fintype α] (k : ℕ) [Fintype (Sym α k)] :
    card (Sym α k) = (card α + k - 1).choose k := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
n : ℕ
α : Type u_3
inst✝¹ : Fintype α
k : ℕ
inst✝ : Fintype (Sym α k)
⊢ Fintype.card (Sym α k) = Nat.choose (Fintype.card α + k - 1) k

Next tactic:
rw [card_sym_eq_multichoose, Nat.multichoose_eq]
/-- The `diag` of `s : Finset α` is sent on a finset of `Sym2 α` of card `s.card`. -/
theorem card_image_diag (s : Finset α) : (s.diag.image (Quotient.mk _)).card = s.card := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
⊢ Finset.card (image (Quotient.mk (Rel.setoid α)) (Finset.diag s)) = Finset.card s

Next tactic:
rw [card_image_of_injOn, diag_card]
/-- The `diag` of `s : Finset α` is sent on a finset of `Sym2 α` of card `s.card`. -/
theorem card_image_diag (s : Finset α) : (s.diag.image (Quotient.mk _)).card = s.card := by
  rw [card_image_of_injOn, diag_card]
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
⊢ Set.InjOn (Quotient.mk (Rel.setoid α)) ↑(Finset.diag s)

Next tactic:
rintro ⟨x₀, x₁⟩ hx _ _ h
/-- The `diag` of `s : Finset α` is sent on a finset of `Sym2 α` of card `s.card`. -/
theorem card_image_diag (s : Finset α) : (s.diag.image (Quotient.mk _)).card = s.card := by
  rw [card_image_of_injOn, diag_card]
  rintro ⟨x₀, x₁⟩ hx _ _ h
  

Proof state:
case mk
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x₀ x₁ : α
hx : (x₀, x₁) ∈ ↑(Finset.diag s)
x₂✝ : α × α
a✝ : x₂✝ ∈ ↑(Finset.diag s)
h : ⟦(x₀, x₁)⟧ = ⟦x₂✝⟧
⊢ (x₀, x₁) = x₂✝

Next tactic:
cases Quotient.eq'.1 h
/-- The `diag` of `s : Finset α` is sent on a finset of `Sym2 α` of card `s.card`. -/
theorem card_image_diag (s : Finset α) : (s.diag.image (Quotient.mk _)).card = s.card := by
  rw [card_image_of_injOn, diag_card]
  rintro ⟨x₀, x₁⟩ hx _ _ h
  cases Quotient.eq'.1 h
  · 

Proof state:
case mk.refl
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x₀ x₁ : α
hx a✝ : (x₀, x₁) ∈ ↑(Finset.diag s)
h : ⟦(x₀, x₁)⟧ = ⟦(x₀, x₁)⟧
⊢ (x₀, x₁) = (x₀, x₁)

Next tactic:
rfl
/-- The `diag` of `s : Finset α` is sent on a finset of `Sym2 α` of card `s.card`. -/
theorem card_image_diag (s : Finset α) : (s.diag.image (Quotient.mk _)).card = s.card := by
  rw [card_image_of_injOn, diag_card]
  rintro ⟨x₀, x₁⟩ hx _ _ h
  cases Quotient.eq'.1 h
  · rfl
  · 

Proof state:
case mk.swap
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x₀ x₁ : α
hx : (x₀, x₁) ∈ ↑(Finset.diag s)
a✝ : (x₁, x₀) ∈ ↑(Finset.diag s)
h : ⟦(x₀, x₁)⟧ = ⟦(x₁, x₀)⟧
⊢ (x₀, x₁) = (x₁, x₀)

Next tactic:
simp only [mem_coe, mem_diag] at hx
/-- The `diag` of `s : Finset α` is sent on a finset of `Sym2 α` of card `s.card`. -/
theorem card_image_diag (s : Finset α) : (s.diag.image (Quotient.mk _)).card = s.card := by
  rw [card_image_of_injOn, diag_card]
  rintro ⟨x₀, x₁⟩ hx _ _ h
  cases Quotient.eq'.1 h
  · rfl
  · simp only [mem_coe, mem_diag] at hx
    

Proof state:
case mk.swap
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x₀ x₁ : α
a✝ : (x₁, x₀) ∈ ↑(Finset.diag s)
h : ⟦(x₀, x₁)⟧ = ⟦(x₁, x₀)⟧
hx : x₀ ∈ s ∧ x₀ = x₁
⊢ (x₀, x₁) = (x₁, x₀)

Next tactic:
rw [hx.2]
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
⊢ 2 * Finset.card (image (Quotient.mk (Rel.setoid α)) (offDiag s)) = Finset.card (offDiag s)

Next tactic:
rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
⊢ ∀ (a : α × α),
    Quotient.mk'' a ∈ image (Quotient.mk (Rel.setoid α)) (offDiag s) →
      Finset.card (filter (fun x => ⟦x⟧ = Quotient.mk'' a) (offDiag s)) = 2

Next tactic:
rintro ⟨x, y⟩ hxy
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  

Proof state:
case mk
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
hxy : Quotient.mk'' (x, y) ∈ image (Quotient.mk (Rel.setoid α)) (offDiag s)
⊢ Finset.card (filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' (x, y)) (offDiag s)) = 2

Next tactic:
simp_rw [mem_image, mem_offDiag] at hxy
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  

Proof state:
case mk
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
hxy : ∃ a, (a.1 ∈ s ∧ a.2 ∈ s ∧ a.1 ≠ a.2) ∧ ⟦a⟧ = Quotient.mk'' (x, y)
⊢ Finset.card (filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' (x, y)) (offDiag s)) = 2

Next tactic:
obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  

Proof state:
case mk.intro.intro.intro.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
h : ⟦a⟧ = Quotient.mk'' (x, y)
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
⊢ Finset.card (filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' (x, y)) (offDiag s)) = 2

Next tactic:
replace h := Quotient.eq.1 h
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  

Proof state:
case mk.intro.intro.intro.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
⊢ Finset.card (filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' (x, y)) (offDiag s)) = 2

Next tactic:
obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
⊢ x ∈ s ∧ y ∈ s ∧ x ≠ y

Next tactic:
cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
⊢ x ∈ s ∧ y ∈ s ∧ x ≠ y

Next tactic:
cases h
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> 

Proof state:
case refl
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
ha₁ : (x, y).1 ∈ s
ha₂ : (x, y).2 ∈ s
ha : (x, y).1 ≠ (x, y).2
⊢ x ∈ s ∧ y ∈ s ∧ x ≠ y

Next tactic:
refine' ⟨‹_›, ‹_›, _⟩
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> 

Proof state:
case swap
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
ha₁ : (y, x).1 ∈ s
ha₂ : (y, x).2 ∈ s
ha : (y, x).1 ≠ (y, x).2
⊢ x ∈ s ∧ y ∈ s ∧ x ≠ y

Next tactic:
refine' ⟨‹_›, ‹_›, _⟩
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [

Proof state:
case refl
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
ha₁ : (x, y).1 ∈ s
ha₂ : (x, y).2 ∈ s
ha : (x, y).1 ≠ (x, y).2
⊢ x ≠ y

Next tactic:
exact ha
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; 

Proof state:
case swap
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
ha₁ : (y, x).1 ∈ s
ha₂ : (y, x).2 ∈ s
ha : (y, x).1 ≠ (y, x).2
⊢ x ≠ y

Next tactic:
exact ha.symm
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  

Proof state:
case mk.intro.intro.intro.intro.intro.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
hx : x ∈ s
hy : y ∈ s
hxy : x ≠ y
⊢ Finset.card (filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' (x, y)) (offDiag s)) = 2

Next tactic:
have hxy' : y ≠ x := hxy.symm
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  

Proof state:
case mk.intro.intro.intro.intro.intro.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
hx : x ∈ s
hy : y ∈ s
hxy : x ≠ y
hxy' : y ≠ x
⊢ Finset.card (filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' (x, y)) (offDiag s)) = 2

Next tactic:
have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    ext ⟨x₁, y₁⟩
    rw [mem_filter, mem_insert, mem_singleton, Sym2.eq_iff, Prod.mk.inj_iff, Prod.mk.inj_iff,
      and_iff_right_iff_imp]
    -- `hxy'` is used in `exact`
    rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) <;> rw [mem_offDiag] <;> exact ⟨‹_›, ‹_›, ‹_›⟩
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
hx : x ∈ s
hy : y ∈ s
hxy : x ≠ y
hxy' : y ≠ x
⊢ filter (fun z => ⟦z⟧ = ⟦(x, y)⟧) (offDiag s) = {(x, y), (y, x)}

Next tactic:
ext ⟨x₁, y₁⟩
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    ext ⟨x₁, y₁⟩
    

Proof state:
case a.mk
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
hx : x ∈ s
hy : y ∈ s
hxy : x ≠ y
hxy' : y ≠ x
x₁ y₁ : α
⊢ (x₁, y₁) ∈ filter (fun z => ⟦z⟧ = ⟦(x, y)⟧) (offDiag s) ↔ (x₁, y₁) ∈ {(x, y), (y, x)}

Next tactic:
rw [mem_filter, mem_insert, mem_singleton, Sym2.eq_iff, Prod.mk.inj_iff, Prod.mk.inj_iff,
      and_iff_right_iff_imp]
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    ext ⟨x₁, y₁⟩
    rw [mem_filter, mem_insert, mem_singleton, Sym2.eq_iff, Prod.mk.inj_iff, Prod.mk.inj_iff,
      and_iff_right_iff_imp]
    -- `hxy'` is used in `exact`
    

Proof state:
case a.mk
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
hx : x ∈ s
hy : y ∈ s
hxy : x ≠ y
hxy' : y ≠ x
x₁ y₁ : α
⊢ x₁ = x ∧ y₁ = y ∨ x₁ = y ∧ y₁ = x → (x₁, y₁) ∈ offDiag s

Next tactic:
rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩)
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    ext ⟨x₁, y₁⟩
    rw [mem_filter, mem_insert, mem_singleton, Sym2.eq_iff, Prod.mk.inj_iff, Prod.mk.inj_iff,
      and_iff_right_iff_imp]
    -- `hxy'` is used in `exact`
    rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) <;> 

Proof state:
case a.mk.inl.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
x₁ y₁ : α
hx : x₁ ∈ s
hy : y₁ ∈ s
h : a ≈ (x₁, y₁)
hxy : x₁ ≠ y₁
hxy' : y₁ ≠ x₁
⊢ (x₁, y₁) ∈ offDiag s

Next tactic:
rw [mem_offDiag]
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    ext ⟨x₁, y₁⟩
    rw [mem_filter, mem_insert, mem_singleton, Sym2.eq_iff, Prod.mk.inj_iff, Prod.mk.inj_iff,
      and_iff_right_iff_imp]
    -- `hxy'` is used in `exact`
    rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) <;> 

Proof state:
case a.mk.inr.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
x₁ y₁ : α
hy : x₁ ∈ s
hx : y₁ ∈ s
h : a ≈ (y₁, x₁)
hxy : y₁ ≠ x₁
hxy' : x₁ ≠ y₁
⊢ (x₁, y₁) ∈ offDiag s

Next tactic:
rw [mem_offDiag]
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    ext ⟨x₁, y₁⟩
    rw [mem_filter, mem_insert, mem_singleton, Sym2.eq_iff, Prod.mk.inj_iff, Prod.mk.inj_iff,
      and_iff_right_iff_imp]
    -- `hxy'` is used in `exact`
    rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) <;> rw [mem_offDiag] <;> 

Proof state:
case a.mk.inl.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
x₁ y₁ : α
hx : x₁ ∈ s
hy : y₁ ∈ s
h : a ≈ (x₁, y₁)
hxy : x₁ ≠ y₁
hxy' : y₁ ≠ x₁
⊢ (x₁, y₁).1 ∈ s ∧ (x₁, y₁).2 ∈ s ∧ (x₁, y₁).1 ≠ (x₁, y₁).2

Next tactic:
exact ⟨‹_›, ‹_›, ‹_›⟩
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    ext ⟨x₁, y₁⟩
    rw [mem_filter, mem_insert, mem_singleton, Sym2.eq_iff, Prod.mk.inj_iff, Prod.mk.inj_iff,
      and_iff_right_iff_imp]
    -- `hxy'` is used in `exact`
    rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) <;> rw [mem_offDiag] <;> 

Proof state:
case a.mk.inr.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
x₁ y₁ : α
hy : x₁ ∈ s
hx : y₁ ∈ s
h : a ≈ (y₁, x₁)
hxy : y₁ ≠ x₁
hxy' : x₁ ≠ y₁
⊢ (x₁, y₁).1 ∈ s ∧ (x₁, y₁).2 ∈ s ∧ (x₁, y₁).1 ≠ (x₁, y₁).2

Next tactic:
exact ⟨‹_›, ‹_›, ‹_›⟩
theorem two_mul_card_image_offDiag (s : Finset α) :
    2 * (s.offDiag.image (Quotient.mk _)).card = s.offDiag.card := by
  rw [card_eq_sum_card_image (Quotient.mk _ : α × α → _), sum_const_nat (Quotient.ind' _), mul_comm]
  rintro ⟨x, y⟩ hxy
  simp_rw [mem_image, mem_offDiag] at hxy
  obtain ⟨a, ⟨ha₁, ha₂, ha⟩, h⟩ := hxy
  replace h := Quotient.eq.1 h
  obtain ⟨hx, hy, hxy⟩ : x ∈ s ∧ y ∈ s ∧ x ≠ y := by
    cases h <;> refine' ⟨‹_›, ‹_›, _⟩ <;> [exact ha; exact ha.symm]
  have hxy' : y ≠ x := hxy.symm
  have : (s.offDiag.filter fun z => ⟦z⟧ = ⟦(x, y)⟧) = ({(x, y), (y, x)} : Finset _) := by
    ext ⟨x₁, y₁⟩
    rw [mem_filter, mem_insert, mem_singleton, Sym2.eq_iff, Prod.mk.inj_iff, Prod.mk.inj_iff,
      and_iff_right_iff_imp]
    -- `hxy'` is used in `exact`
    rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) <;> rw [mem_offDiag] <;> exact ⟨‹_›, ‹_›, ‹_›⟩
  

Proof state:
case mk.intro.intro.intro.intro.intro.intro
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Finset α
x y : α
a : α × α
ha₁ : a.1 ∈ s
ha₂ : a.2 ∈ s
ha : a.1 ≠ a.2
h : a ≈ (x, y)
hx : x ∈ s
hy : y ∈ s
hxy : x ≠ y
hxy' : y ≠ x
this : filter (fun z => ⟦z⟧ = ⟦(x, y)⟧) (offDiag s) = {(x, y), (y, x)}
⊢ Finset.card (filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' (x, y)) (offDiag s)) = 2

Next tactic:
dsimp only [Quotient.mk''_eq_mk]