-- Mathlib/Topology/MetricSpace/GromovHausdorff.lean
theorem eq_toGHSpace_iff {X : Type u} [MetricSpace X] [CompactSpace X] [Nonempty X]
    {p : NonemptyCompacts ℓ_infty_ℝ} :
    ⟦p⟧ = toGHSpace X ↔ ∃ Ψ : X → ℓ_infty_ℝ, Isometry Ψ ∧ range Ψ = p

Proof state:
case right
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
h : IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)
e : ↥(NonemptyCompacts.kuratowskiEmbedding X) ≃ᵢ ↥p
f : X ≃ᵢ ↥p
⊢ (range fun x => ↑(f x)) = ↑p

Tactic:
rw [range_comp', f.range_eq_univ, Set.image_univ, Subtype.range_coe]

Result:
no goals

Proof state:
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
⊢ ⟦p⟧ = toGHSpace X ↔ ∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p

Tactic:
simp only [toGHSpace, Quotient.eq]

Result:
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
⊢ IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X) ↔ ∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p

Proof state:
case refine_2.intro.intro
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
⊢ IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)

Tactic:
have f :=
  ((kuratowskiEmbedding.isometry X).isometryEquivOnRange.symm.trans
      isomΨ.isometryEquivOnRange).symm

Result:
case refine_2.intro.intro
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
f : ↑(range Ψ) ≃ᵢ ↑(range (kuratowskiEmbedding X))
⊢ IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)

Proof state:
case refine_1
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
h : IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)
⊢ ∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p

Tactic:
rcases Setoid.symm h with ⟨e⟩

Result:
case refine_1.intro
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
h : IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)
e : ↥(NonemptyCompacts.kuratowskiEmbedding X) ≃ᵢ ↥p
⊢ ∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p

Proof state:
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
f : ↑(range Ψ) ≃ᵢ ↑(range (kuratowskiEmbedding X))
⊢ (↑(range Ψ) ≃ᵢ ↥(NonemptyCompacts.kuratowskiEmbedding X)) = (↥p ≃ᵢ ↑(range (kuratowskiEmbedding X)))

Tactic:
dsimp only [NonemptyCompacts.kuratowskiEmbedding]

Result:
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
f : ↑(range Ψ) ≃ᵢ ↑(range (kuratowskiEmbedding X))
⊢ (↑(range Ψ) ≃ᵢ ↥{ carrier := range (kuratowskiEmbedding X), isCompact' := ⋯, nonempty' := ⋯ }) =
    (↥p ≃ᵢ ↑(range (kuratowskiEmbedding X)))

Proof state:
case refine_2.intro.intro
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
f : ↑(range Ψ) ≃ᵢ ↑(range (kuratowskiEmbedding X))
⊢ IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)

Tactic:
have E : (range Ψ ≃ᵢ NonemptyCompacts.kuratowskiEmbedding X)
    = (p ≃ᵢ range (kuratowskiEmbedding X)) := by
  dsimp only [NonemptyCompacts.kuratowskiEmbedding]; rw [rangeΨ]; rfl

Result:
case refine_2.intro.intro
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
f : ↑(range Ψ) ≃ᵢ ↑(range (kuratowskiEmbedding X))
E : (↑(range Ψ) ≃ᵢ ↥(NonemptyCompacts.kuratowskiEmbedding X)) = (↥p ≃ᵢ ↑(range (kuratowskiEmbedding X)))
⊢ IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)

Proof state:
case refine_2
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
⊢ (∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p) → IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)

Tactic:
rintro ⟨Ψ, ⟨isomΨ, rangeΨ⟩⟩

Result:
case refine_2.intro.intro
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
⊢ IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)

Proof state:
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
⊢ IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X) ↔ ∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p

Tactic:
refine ⟨fun h => ?_, ?_⟩

Result:
case refine_1
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
h : IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)
⊢ ∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p

case refine_2
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
⊢ (∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p) → IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)

Proof state:
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
f : ↑(range Ψ) ≃ᵢ ↑(range (kuratowskiEmbedding X))
⊢ (↑↑p ≃ᵢ ↥{ carrier := range (kuratowskiEmbedding X), isCompact' := ⋯, nonempty' := ⋯ }) =
    (↥p ≃ᵢ ↑(range (kuratowskiEmbedding X)))

Tactic:
rfl

Result:
no goals

Proof state:
case refine_1.intro
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
h : IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)
e : ↥(NonemptyCompacts.kuratowskiEmbedding X) ≃ᵢ ↥p
⊢ ∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p

Tactic:
have f := (kuratowskiEmbedding.isometry X).isometryEquivOnRange.trans e

Result:
case refine_1.intro
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
h : IsometryRel.setoid p (NonemptyCompacts.kuratowskiEmbedding X)
e : ↥(NonemptyCompacts.kuratowskiEmbedding X) ≃ᵢ ↥p
f : X ≃ᵢ ↥p
⊢ ∃ Ψ, Isometry Ψ ∧ range Ψ = ↑p

Proof state:
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
f : ↑(range Ψ) ≃ᵢ ↑(range (kuratowskiEmbedding X))
⊢ (↑(range Ψ) ≃ᵢ ↥{ carrier := range (kuratowskiEmbedding X), isCompact' := ⋯, nonempty' := ⋯ }) =
    (↥p ≃ᵢ ↑(range (kuratowskiEmbedding X)))

Tactic:
rw [rangeΨ]

Result:
X : Type u
inst✝² : MetricSpace X
inst✝¹ : CompactSpace X
inst✝ : Nonempty X
p : NonemptyCompacts ↥(lp (fun n => ℝ) ⊤)
Ψ : X → ↥(lp (fun n => ℝ) ⊤)
isomΨ : Isometry Ψ
rangeΨ : range Ψ = ↑p
f : ↑(range Ψ) ≃ᵢ ↑(range (kuratowskiEmbedding X))
⊢ (↑↑p ≃ᵢ ↥{ carrier := range (kuratowskiEmbedding X), isCompact' := ⋯, nonempty' := ⋯ }) =
    (↥p ≃ᵢ ↑(range (kuratowskiEmbedding X)))