l3lab/ntp-mathlib huggingface dataset:
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 ⟨‹_›, ‹_›, ‹_›⟩
  dsimp only [Quotient.mk''_eq_mk] -- Porting note: Added `dsimp`
  

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⟧ = ⟦(x, y)⟧) (offDiag s)) = 2

Next tactic:
rw [this, card_insert_of_not_mem, card_singleton]
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 ⟨‹_›, ‹_›, ‹_›⟩
  dsimp only [Quotient.mk''_eq_mk] -- Porting note: Added `dsimp`
  rw [this, card_insert_of_not_mem, card_singleton]
  

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)}
⊢ (x, y) ∉ {(y, x)}

Next tactic:
simp only [not_and, Prod.mk.inj_iff, mem_singleton]
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 ⟨‹_›, ‹_›, ‹_›⟩
  dsimp only [Quotient.mk''_eq_mk] -- Porting note: Added `dsimp`
  rw [this, card_insert_of_not_mem, card_singleton]
  simp only [not_and, Prod.mk.inj_iff, mem_singleton]
  

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)}
⊢ x = y → ¬y = x

Next tactic:
exact fun _ => hxy'
/-- The `offDiag` of `s : Finset α` is sent on a finset of `Sym2 α` of card `s.offDiag.card / 2`.
This is because every element `⟦(x, y)⟧` of `Sym2 α` not on the diagonal comes from exactly two
pairs: `(x, y)` and `(y, x)`. -/
theorem card_image_offDiag (s : Finset α) :
    (s.offDiag.image (Quotient.mk _)).card = s.card.choose 2 := by
  

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

Next tactic:
rw [Nat.choose_two_right, mul_tsub, mul_one, ← offDiag_card,
    Nat.div_eq_of_eq_mul_right zero_lt_two (two_mul_card_image_offDiag s).symm]
theorem card_subtype_diag [Fintype α] : card { a : Sym2 α // a.IsDiag } = card α := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
⊢ Fintype.card { a // IsDiag a } = Fintype.card α

Next tactic:
convert card_image_diag (univ : Finset α)
theorem card_subtype_diag [Fintype α] : card { a : Sym2 α // a.IsDiag } = card α := by
  convert card_image_diag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_isDiag` was part of rw
  

Proof state:
case h.e'_2
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
⊢ Fintype.card { a // IsDiag a } = Finset.card (image (Quotient.mk (Rel.setoid α)) (Finset.diag univ))

Next tactic:
refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_isDiag univ))
theorem card_subtype_diag [Fintype α] : card { a : Sym2 α // a.IsDiag } = card α := by
  convert card_image_diag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_isDiag univ))
  

Proof state:
case h.e'_2
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
⊢ Fintype.card { a // IsDiag a } = Finset.card (filter IsDiag (image Quotient.mk'' (univ ×ˢ univ)))

Next tactic:
rw [Fintype.card_of_subtype]
theorem card_subtype_diag [Fintype α] : card { a : Sym2 α // a.IsDiag } = card α := by
  convert card_image_diag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_isDiag univ))
  rw [Fintype.card_of_subtype]
  

Proof state:
case h.e'_2.H
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
⊢ ∀ (x : Sym2 α), x ∈ filter IsDiag (image Quotient.mk'' (univ ×ˢ univ)) ↔ IsDiag x

Next tactic:
rintro x
theorem card_subtype_diag [Fintype α] : card { a : Sym2 α // a.IsDiag } = card α := by
  convert card_image_diag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_isDiag univ))
  rw [Fintype.card_of_subtype]
  rintro x
  

Proof state:
case h.e'_2.H
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
x : Sym2 α
⊢ x ∈ filter IsDiag (image Quotient.mk'' (univ ×ˢ univ)) ↔ IsDiag x

Next tactic:
rw [mem_filter, univ_product_univ, mem_image]
theorem card_subtype_diag [Fintype α] : card { a : Sym2 α // a.IsDiag } = card α := by
  convert card_image_diag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_isDiag univ))
  rw [Fintype.card_of_subtype]
  rintro x
  rw [mem_filter, univ_product_univ, mem_image]
  

Proof state:
case h.e'_2.H
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
x : Sym2 α
⊢ (∃ a ∈ univ, Quotient.mk'' a = x) ∧ IsDiag x ↔ IsDiag x

Next tactic:
obtain ⟨a, ha⟩ := Quotient.exists_rep x
theorem card_subtype_diag [Fintype α] : card { a : Sym2 α // a.IsDiag } = card α := by
  convert card_image_diag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_isDiag univ))
  rw [Fintype.card_of_subtype]
  rintro x
  rw [mem_filter, univ_product_univ, mem_image]
  obtain ⟨a, ha⟩ := Quotient.exists_rep x
  

Proof state:
case h.e'_2.H.intro
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
x : Sym2 α
a : α × α
ha : ⟦a⟧ = x
⊢ (∃ a ∈ univ, Quotient.mk'' a = x) ∧ IsDiag x ↔ IsDiag x

Next tactic:
exact and_iff_right ⟨a, mem_univ _, ha⟩
theorem card_subtype_not_diag [Fintype α] :
    card { a : Sym2 α // ¬a.IsDiag } = (card α).choose 2 := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
⊢ Fintype.card { a // ¬IsDiag a } = Nat.choose (Fintype.card α) 2

Next tactic:
convert card_image_offDiag (univ : Finset α)
theorem card_subtype_not_diag [Fintype α] :
    card { a : Sym2 α // ¬a.IsDiag } = (card α).choose 2 := by
  convert card_image_offDiag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_not_isDiag` was part of rw
  

Proof state:
case h.e'_2
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
⊢ Fintype.card { a // ¬IsDiag a } = Finset.card (image (Quotient.mk (Rel.setoid α)) (offDiag univ))

Next tactic:
refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_not_isDiag univ))
theorem card_subtype_not_diag [Fintype α] :
    card { a : Sym2 α // ¬a.IsDiag } = (card α).choose 2 := by
  convert card_image_offDiag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_not_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_not_isDiag univ))
  

Proof state:
case h.e'_2
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
⊢ Fintype.card { a // ¬IsDiag a } = Finset.card (filter (fun a => ¬IsDiag a) (image Quotient.mk'' (univ ×ˢ univ)))

Next tactic:
rw [Fintype.card_of_subtype]
theorem card_subtype_not_diag [Fintype α] :
    card { a : Sym2 α // ¬a.IsDiag } = (card α).choose 2 := by
  convert card_image_offDiag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_not_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_not_isDiag univ))
  rw [Fintype.card_of_subtype]
  

Proof state:
case h.e'_2.H
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
⊢ ∀ (x : Sym2 α), x ∈ filter (fun a => ¬IsDiag a) (image Quotient.mk'' (univ ×ˢ univ)) ↔ ¬IsDiag x

Next tactic:
rintro x
theorem card_subtype_not_diag [Fintype α] :
    card { a : Sym2 α // ¬a.IsDiag } = (card α).choose 2 := by
  convert card_image_offDiag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_not_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_not_isDiag univ))
  rw [Fintype.card_of_subtype]
  rintro x
  

Proof state:
case h.e'_2.H
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
x : Sym2 α
⊢ x ∈ filter (fun a => ¬IsDiag a) (image Quotient.mk'' (univ ×ˢ univ)) ↔ ¬IsDiag x

Next tactic:
rw [mem_filter, univ_product_univ, mem_image]
theorem card_subtype_not_diag [Fintype α] :
    card { a : Sym2 α // ¬a.IsDiag } = (card α).choose 2 := by
  convert card_image_offDiag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_not_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_not_isDiag univ))
  rw [Fintype.card_of_subtype]
  rintro x
  rw [mem_filter, univ_product_univ, mem_image]
  

Proof state:
case h.e'_2.H
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
x : Sym2 α
⊢ (∃ a ∈ univ, Quotient.mk'' a = x) ∧ ¬IsDiag x ↔ ¬IsDiag x

Next tactic:
obtain ⟨a, ha⟩ := Quotient.exists_rep x
theorem card_subtype_not_diag [Fintype α] :
    card { a : Sym2 α // ¬a.IsDiag } = (card α).choose 2 := by
  convert card_image_offDiag (univ : Finset α)
  -- Porting note (kmill): Quotient.mk and Quotient.mk'' are syntactically different.
  -- `filter_image_quotient_mk''_not_isDiag` was part of rw
  refine Eq.trans ?_ congr(Finset.card $(filter_image_quotient_mk''_not_isDiag univ))
  rw [Fintype.card_of_subtype]
  rintro x
  rw [mem_filter, univ_product_univ, mem_image]
  obtain ⟨a, ha⟩ := Quotient.exists_rep x
  

Proof state:
case h.e'_2.H.intro
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : Fintype α
x : Sym2 α
a : α × α
ha : ⟦a⟧ = x
⊢ (∃ a ∈ univ, Quotient.mk'' a = x) ∧ ¬IsDiag x ↔ ¬IsDiag x

Next tactic:
exact and_iff_right ⟨a, mem_univ _, ha⟩
@[simp]
theorem Sphere.mk_center_radius (s : Sphere P) : (⟨s.center, s.radius⟩ : Sphere P) = s := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
s : Sphere P
⊢ { center := s.center, radius := s.radius } = s

Next tactic:
ext
@[simp]
theorem Sphere.mk_center_radius (s : Sphere P) : (⟨s.center, s.radius⟩ : Sphere P) = s := by
  ext <;> 

Proof state:
case center
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
s : Sphere P
⊢ { center := s.center, radius := s.radius }.center = s.center

Next tactic:
rfl
@[simp]
theorem Sphere.mk_center_radius (s : Sphere P) : (⟨s.center, s.radius⟩ : Sphere P) = s := by
  ext <;> 

Proof state:
case radius
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
s : Sphere P
⊢ { center := s.center, radius := s.radius }.radius = s.radius

Next tactic:
rfl
theorem Sphere.ne_iff {s₁ s₂ : Sphere P} :
    s₁ ≠ s₂ ↔ s₁.center ≠ s₂.center ∨ s₁.radius ≠ s₂.radius := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
s₁ s₂ : Sphere P
⊢ s₁ ≠ s₂ ↔ s₁.center ≠ s₂.center ∨ s₁.radius ≠ s₂.radius

Next tactic:
rw [← not_and_or, ← Sphere.ext_iff]
theorem Sphere.center_eq_iff_eq_of_mem {s₁ s₂ : Sphere P} {p : P} (hs₁ : p ∈ s₁) (hs₂ : p ∈ s₂) :
    s₁.center = s₂.center ↔ s₁ = s₂ := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
s₁ s₂ : Sphere P
p : P
hs₁ : p ∈ s₁
hs₂ : p ∈ s₂
⊢ s₁.center = s₂.center ↔ s₁ = s₂

Next tactic:
refine' ⟨fun h => Sphere.ext _ _ h _, fun h => h ▸ rfl⟩
theorem Sphere.center_eq_iff_eq_of_mem {s₁ s₂ : Sphere P} {p : P} (hs₁ : p ∈ s₁) (hs₂ : p ∈ s₂) :
    s₁.center = s₂.center ↔ s₁ = s₂ := by
  refine' ⟨fun h => Sphere.ext _ _ h _, fun h => h ▸ rfl⟩
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
s₁ s₂ : Sphere P
p : P
hs₁ : p ∈ s₁
hs₂ : p ∈ s₂
h : s₁.center = s₂.center
⊢ s₁.radius = s₂.radius

Next tactic:
rw [mem_sphere] at hs₁ hs₂
theorem Sphere.center_eq_iff_eq_of_mem {s₁ s₂ : Sphere P} {p : P} (hs₁ : p ∈ s₁) (hs₂ : p ∈ s₂) :
    s₁.center = s₂.center ↔ s₁ = s₂ := by
  refine' ⟨fun h => Sphere.ext _ _ h _, fun h => h ▸ rfl⟩
  rw [mem_sphere] at hs₁ hs₂
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
s₁ s₂ : Sphere P
p : P
hs₁ : dist p s₁.center = s₁.radius
hs₂ : dist p s₂.center = s₂.radius
h : s₁.center = s₂.center
⊢ s₁.radius = s₂.radius

Next tactic:
rw [← hs₁, ← hs₂, h]
theorem dist_center_eq_dist_center_of_mem_sphere {p₁ p₂ : P} {s : Sphere P} (hp₁ : p₁ ∈ s)
    (hp₂ : p₂ ∈ s) : dist p₁ s.center = dist p₂ s.center := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
p₁ p₂ : P
s : Sphere P
hp₁ : p₁ ∈ s
hp₂ : p₂ ∈ s
⊢ dist p₁ s.center = dist p₂ s.center

Next tactic:
rw [mem_sphere.1 hp₁, mem_sphere.1 hp₂]
theorem dist_center_eq_dist_center_of_mem_sphere' {p₁ p₂ : P} {s : Sphere P} (hp₁ : p₁ ∈ s)
    (hp₂ : p₂ ∈ s) : dist s.center p₁ = dist s.center p₂ := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
p₁ p₂ : P
s : Sphere P
hp₁ : p₁ ∈ s
hp₂ : p₂ ∈ s
⊢ dist s.center p₁ = dist s.center p₂

Next tactic:
rw [mem_sphere'.1 hp₁, mem_sphere'.1 hp₂]
/-- A set of points is cospherical if and only if they lie in some sphere. -/
theorem cospherical_iff_exists_sphere {ps : Set P} :
    Cospherical ps ↔ ∃ s : Sphere P, ps ⊆ (s : Set P) := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
ps : Set P
⊢ Cospherical ps ↔ ∃ s, ps ⊆ Metric.sphere s.center s.radius

Next tactic:
refine' ⟨fun h => _, fun h => _⟩
/-- A set of points is cospherical if and only if they lie in some sphere. -/
theorem cospherical_iff_exists_sphere {ps : Set P} :
    Cospherical ps ↔ ∃ s : Sphere P, ps ⊆ (s : Set P) := by
  refine' ⟨fun h => _, fun h => _⟩
  · 

Proof state:
case refine'_1
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
ps : Set P
h : Cospherical ps
⊢ ∃ s, ps ⊆ Metric.sphere s.center s.radius

Next tactic:
rcases h with ⟨c, r, h⟩
/-- A set of points is cospherical if and only if they lie in some sphere. -/
theorem cospherical_iff_exists_sphere {ps : Set P} :
    Cospherical ps ↔ ∃ s : Sphere P, ps ⊆ (s : Set P) := by
  refine' ⟨fun h => _, fun h => _⟩
  · rcases h with ⟨c, r, h⟩
    

Proof state:
case refine'_1.intro.intro
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
ps : Set P
c : P
r : ℝ
h : ∀ p ∈ ps, dist p c = r
⊢ ∃ s, ps ⊆ Metric.sphere s.center s.radius

Next tactic:
exact ⟨⟨c, r⟩, h⟩
/-- A set of points is cospherical if and only if they lie in some sphere. -/
theorem cospherical_iff_exists_sphere {ps : Set P} :
    Cospherical ps ↔ ∃ s : Sphere P, ps ⊆ (s : Set P) := by
  refine' ⟨fun h => _, fun h => _⟩
  · rcases h with ⟨c, r, h⟩
    exact ⟨⟨c, r⟩, h⟩
  · 

Proof state:
case refine'_2
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
ps : Set P
h : ∃ s, ps ⊆ Metric.sphere s.center s.radius
⊢ Cospherical ps

Next tactic:
rcases h with ⟨s, h⟩
/-- A set of points is cospherical if and only if they lie in some sphere. -/
theorem cospherical_iff_exists_sphere {ps : Set P} :
    Cospherical ps ↔ ∃ s : Sphere P, ps ⊆ (s : Set P) := by
  refine' ⟨fun h => _, fun h => _⟩
  · rcases h with ⟨c, r, h⟩
    exact ⟨⟨c, r⟩, h⟩
  · rcases h with ⟨s, h⟩
    

Proof state:
case refine'_2.intro
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
ps : Set P
s : Sphere P
h : ps ⊆ Metric.sphere s.center s.radius
⊢ Cospherical ps

Next tactic:
exact ⟨s.center, s.radius, h⟩
/-- A subset of a cospherical set is cospherical. -/
theorem Cospherical.subset {ps₁ ps₂ : Set P} (hs : ps₁ ⊆ ps₂) (hc : Cospherical ps₂) :
    Cospherical ps₁ := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
ps₁ ps₂ : Set P
hs : ps₁ ⊆ ps₂
hc : Cospherical ps₂
⊢ Cospherical ps₁

Next tactic:
rcases hc with ⟨c, r, hcr⟩
/-- A subset of a cospherical set is cospherical. -/
theorem Cospherical.subset {ps₁ ps₂ : Set P} (hs : ps₁ ⊆ ps₂) (hc : Cospherical ps₂) :
    Cospherical ps₁ := by
  rcases hc with ⟨c, r, hcr⟩
  

Proof state:
case intro.intro
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
ps₁ ps₂ : Set P
hs : ps₁ ⊆ ps₂
c : P
r : ℝ
hcr : ∀ p ∈ ps₂, dist p c = r
⊢ Cospherical ps₁

Next tactic:
exact ⟨c, r, fun p hp => hcr p (hs hp)⟩
/-- A single point is cospherical. -/
theorem cospherical_singleton (p : P) : Cospherical ({p} : Set P) := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
p : P
⊢ Cospherical {p}

Next tactic:
use p
/-- A single point is cospherical. -/
theorem cospherical_singleton (p : P) : Cospherical ({p} : Set P) := by
  use p
  

Proof state:
case h
V : Type u_1
P : Type u_2
inst✝ : MetricSpace P
p : P
⊢ ∃ radius, ∀ p_1 ∈ {p}, dist p_1 p = radius

Next tactic:
simp
/-- Two points are cospherical. -/
theorem cospherical_pair (p₁ p₂ : P) : Cospherical ({p₁, p₂} : Set P) :=
  ⟨midpoint ℝ p₁ p₂, ‖(2 : ℝ)‖⁻¹ * dist p₁ p₂, by
    

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ : P
⊢ ∀ p ∈ {p₁, p₂}, dist p (midpoint ℝ p₁ p₂) = ‖2‖⁻¹ * dist p₁ p₂

Next tactic:
rintro p (rfl | rfl | _)
/-- Two points are cospherical. -/
theorem cospherical_pair (p₁ p₂ : P) : Cospherical ({p₁, p₂} : Set P) :=
  ⟨midpoint ℝ p₁ p₂, ‖(2 : ℝ)‖⁻¹ * dist p₁ p₂, by
    rintro p (rfl | rfl | _)
    · 

Proof state:
case inl
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₂ p : P
⊢ dist p (midpoint ℝ p p₂) = ‖2‖⁻¹ * dist p p₂

Next tactic:
rw [dist_comm, dist_midpoint_left (𝕜 := ℝ)]
/-- Two points are cospherical. -/
theorem cospherical_pair (p₁ p₂ : P) : Cospherical ({p₁, p₂} : Set P) :=
  ⟨midpoint ℝ p₁ p₂, ‖(2 : ℝ)‖⁻¹ * dist p₁ p₂, by
    rintro p (rfl | rfl | _)
    · rw [dist_comm, dist_midpoint_left (𝕜 := ℝ)]
    · 

Proof state:
case inr.refl
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ : P
⊢ dist p₂ (midpoint ℝ p₁ p₂) = ‖2‖⁻¹ * dist p₁ p₂

Next tactic:
rw [dist_comm, dist_midpoint_right (𝕜 := ℝ)]
/-- Any three points in a cospherical set are affinely independent. -/
theorem Cospherical.affineIndependent {s : Set P} (hs : Cospherical s) {p : Fin 3 → P}
    (hps : Set.range p ⊆ s) (hpi : Function.Injective p) : AffineIndependent ℝ p := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
s : Set P
hs : Cospherical s
p : Fin 3 → P
hps : Set.range p ⊆ s
hpi : Function.Injective p
⊢ AffineIndependent ℝ p

Next tactic:
rw [affineIndependent_iff_not_collinear]
/-- Any three points in a cospherical set are affinely independent. -/
theorem Cospherical.affineIndependent {s : Set P} (hs : Cospherical s) {p : Fin 3 → P}
    (hps : Set.range p ⊆ s) (hpi : Function.Injective p) : AffineIndependent ℝ p := by
  rw [affineIndependent_iff_not_collinear]
  

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
s : Set P
hs : Cospherical s
p : Fin 3 → P
hps : Set.range p ⊆ s
hpi : Function.Injective p
⊢ ¬Collinear ℝ (Set.range p)

Next tactic:
intro hc
/-- Any three points in a cospherical set are affinely independent. -/
theorem Cospherical.affineIndependent {s : Set P} (hs : Cospherical s) {p : Fin 3 → P}
    (hps : Set.range p ⊆ s) (hpi : Function.Injective p) : AffineIndependent ℝ p := by
  rw [affineIndependent_iff_not_collinear]
  intro hc
  

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
s : Set P
hs : Cospherical s
p : Fin 3 → P
hps : Set.range p ⊆ s
hpi : Function.Injective p
hc : Collinear ℝ (Set.range p)
⊢ False

Next tactic:
rw [collinear_iff_of_mem (Set.mem_range_self (0 : Fin 3))] at hc
/-- Any three points in a cospherical set are affinely independent. -/
theorem Cospherical.affineIndependent {s : Set P} (hs : Cospherical s) {p : Fin 3 → P}
    (hps : Set.range p ⊆ s) (hpi : Function.Injective p) : AffineIndependent ℝ p := by
  rw [affineIndependent_iff_not_collinear]
  intro hc
  rw [collinear_iff_of_mem (Set.mem_range_self (0 : Fin 3))] at hc
  

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
s : Set P
hs : Cospherical s
p : Fin 3 → P
hps : Set.range p ⊆ s
hpi : Function.Injective p
hc : ∃ v, ∀ p_1 ∈ Set.range p, ∃ r, p_1 = r • v +ᵥ p 0
⊢ False

Next tactic:
rcases hc with ⟨v, hv⟩
/-- Any three points in a cospherical set are affinely independent. -/
theorem Cospherical.affineIndependent {s : Set P} (hs : Cospherical s) {p : Fin 3 → P}
    (hps : Set.range p ⊆ s) (hpi : Function.Injective p) : AffineIndependent ℝ p := by
  rw [affineIndependent_iff_not_collinear]
  intro hc
  rw [collinear_iff_of_mem (Set.mem_range_self (0 : Fin 3))] at hc
  rcases hc with ⟨v, hv⟩
  

Proof state:
case intro
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
s : Set P
hs : Cospherical s
p : Fin 3 → P
hps : Set.range p ⊆ s
hpi : Function.Injective p
v : V
hv : ∀ p_1 ∈ Set.range p, ∃ r, p_1 = r • v +ᵥ p 0
⊢ False

Next tactic:
rw [Set.forall_range_iff] at hv