l3lab/ntp-mathlib huggingface dataset:
/-- A finite product of pseudometric spaces is a pseudometric space, with the sup distance. -/
instance pseudoMetricSpacePi : PseudoMetricSpace (∀ b, π b) := by
  /- we construct the instance from the pseudoemetric space instance to avoid checking again that
    the uniformity is the same as the product uniformity, but we register nevertheless a nice
    formula for the distance -/
  let i := PseudoEMetricSpace.toPseudoMetricSpaceOfDist
    (fun f g : ∀ b, π b => ((sup univ fun b => nndist (f b) (g b) : ℝ≥0) : ℝ))
    (fun f g => ((Finset.sup_lt_iff bot_lt_top).2 fun b _ => edist_lt_top _ _).ne)
    (fun f g => by
      simp only [edist_pi_def, edist_nndist, ← ENNReal.coe_finset_sup, ENNReal.coe_toReal])
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
i : PseudoMetricSpace ((b : β) → π b) :=
  PseudoEMetricSpace.toPseudoMetricSpaceOfDist (fun f g => ↑(sup Finset.univ fun b => nndist (f b) (g b)))
    (_ : ∀ (f g : (b : β) → π b), (sup Finset.univ fun b => edist (f b) (g b)) ≠ ⊤)
    (_ :
      ∀ (f g : (b : β) → π b),
        ↑(sup Finset.univ fun b => nndist (f b) (g b)) = ENNReal.toReal (sup Finset.univ fun x => edist (f x) (g x)))
⊢ PseudoMetricSpace ((b : β) → π b)

Next tactic:
refine i.replaceBornology fun s => ?_
/-- A finite product of pseudometric spaces is a pseudometric space, with the sup distance. -/
instance pseudoMetricSpacePi : PseudoMetricSpace (∀ b, π b) := by
  /- we construct the instance from the pseudoemetric space instance to avoid checking again that
    the uniformity is the same as the product uniformity, but we register nevertheless a nice
    formula for the distance -/
  let i := PseudoEMetricSpace.toPseudoMetricSpaceOfDist
    (fun f g : ∀ b, π b => ((sup univ fun b => nndist (f b) (g b) : ℝ≥0) : ℝ))
    (fun f g => ((Finset.sup_lt_iff bot_lt_top).2 fun b _ => edist_lt_top _ _).ne)
    (fun f g => by
      simp only [edist_pi_def, edist_nndist, ← ENNReal.coe_finset_sup, ENNReal.coe_toReal])
  refine i.replaceBornology fun s => ?_
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
i : PseudoMetricSpace ((b : β) → π b) :=
  PseudoEMetricSpace.toPseudoMetricSpaceOfDist (fun f g => ↑(sup Finset.univ fun b => nndist (f b) (g b)))
    (_ : ∀ (f g : (b : β) → π b), (sup Finset.univ fun b => edist (f b) (g b)) ≠ ⊤)
    (_ :
      ∀ (f g : (b : β) → π b),
        ↑(sup Finset.univ fun b => nndist (f b) (g b)) = ENNReal.toReal (sup Finset.univ fun x => edist (f x) (g x)))
s : Set ((b : β) → π b)
⊢ IsBounded s ↔ IsBounded s

Next tactic:
simp only [← isBounded_def, isBounded_iff_eventually, ← forall_isBounded_image_eval_iff,
    ball_image_iff, ← Filter.eventually_all, Function.eval_apply, @dist_nndist (π _)]
/-- A finite product of pseudometric spaces is a pseudometric space, with the sup distance. -/
instance pseudoMetricSpacePi : PseudoMetricSpace (∀ b, π b) := by
  /- we construct the instance from the pseudoemetric space instance to avoid checking again that
    the uniformity is the same as the product uniformity, but we register nevertheless a nice
    formula for the distance -/
  let i := PseudoEMetricSpace.toPseudoMetricSpaceOfDist
    (fun f g : ∀ b, π b => ((sup univ fun b => nndist (f b) (g b) : ℝ≥0) : ℝ))
    (fun f g => ((Finset.sup_lt_iff bot_lt_top).2 fun b _ => edist_lt_top _ _).ne)
    (fun f g => by
      simp only [edist_pi_def, edist_nndist, ← ENNReal.coe_finset_sup, ENNReal.coe_toReal])
  refine i.replaceBornology fun s => ?_
  simp only [← isBounded_def, isBounded_iff_eventually, ← forall_isBounded_image_eval_iff,
    ball_image_iff, ← Filter.eventually_all, Function.eval_apply, @dist_nndist (π _)]
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
i : PseudoMetricSpace ((b : β) → π b) :=
  PseudoEMetricSpace.toPseudoMetricSpaceOfDist (fun f g => ↑(sup Finset.univ fun b => nndist (f b) (g b)))
    (_ : ∀ (f g : (b : β) → π b), (sup Finset.univ fun b => edist (f b) (g b)) ≠ ⊤)
    (_ :
      ∀ (f g : (b : β) → π b),
        ↑(sup Finset.univ fun b => nndist (f b) (g b)) = ENNReal.toReal (sup Finset.univ fun x => edist (f x) (g x)))
s : Set ((b : β) → π b)
⊢ (∀ᶠ (x : ℝ) in atTop, ∀ (i : β), ∀ x_1 ∈ s, ∀ x_2 ∈ s, ↑(nndist (Function.eval i x_1) (Function.eval i x_2)) ≤ x) ↔
    ∀ᶠ (C : ℝ) in atTop, ∀ ⦃x : (b : β) → π b⦄, x ∈ s → ∀ ⦃y : (b : β) → π b⦄, y ∈ s → dist x y ≤ C

Next tactic:
refine' eventually_congr ((eventually_ge_atTop 0).mono fun C hC => _)
/-- A finite product of pseudometric spaces is a pseudometric space, with the sup distance. -/
instance pseudoMetricSpacePi : PseudoMetricSpace (∀ b, π b) := by
  /- we construct the instance from the pseudoemetric space instance to avoid checking again that
    the uniformity is the same as the product uniformity, but we register nevertheless a nice
    formula for the distance -/
  let i := PseudoEMetricSpace.toPseudoMetricSpaceOfDist
    (fun f g : ∀ b, π b => ((sup univ fun b => nndist (f b) (g b) : ℝ≥0) : ℝ))
    (fun f g => ((Finset.sup_lt_iff bot_lt_top).2 fun b _ => edist_lt_top _ _).ne)
    (fun f g => by
      simp only [edist_pi_def, edist_nndist, ← ENNReal.coe_finset_sup, ENNReal.coe_toReal])
  refine i.replaceBornology fun s => ?_
  simp only [← isBounded_def, isBounded_iff_eventually, ← forall_isBounded_image_eval_iff,
    ball_image_iff, ← Filter.eventually_all, Function.eval_apply, @dist_nndist (π _)]
  refine' eventually_congr ((eventually_ge_atTop 0).mono fun C hC => _)
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
i : PseudoMetricSpace ((b : β) → π b) :=
  PseudoEMetricSpace.toPseudoMetricSpaceOfDist (fun f g => ↑(sup Finset.univ fun b => nndist (f b) (g b)))
    (_ : ∀ (f g : (b : β) → π b), (sup Finset.univ fun b => edist (f b) (g b)) ≠ ⊤)
    (_ :
      ∀ (f g : (b : β) → π b),
        ↑(sup Finset.univ fun b => nndist (f b) (g b)) = ENNReal.toReal (sup Finset.univ fun x => edist (f x) (g x)))
s : Set ((b : β) → π b)
C : ℝ
hC : 0 ≤ C
⊢ (∀ (i : β), ∀ x ∈ s, ∀ x_1 ∈ s, ↑(nndist (Function.eval i x) (Function.eval i x_1)) ≤ C) ↔
    ∀ ⦃x : (b : β) → π b⦄, x ∈ s → ∀ ⦃y : (b : β) → π b⦄, y ∈ s → dist x y ≤ C

Next tactic:
lift C to ℝ≥0 using hC
/-- A finite product of pseudometric spaces is a pseudometric space, with the sup distance. -/
instance pseudoMetricSpacePi : PseudoMetricSpace (∀ b, π b) := by
  /- we construct the instance from the pseudoemetric space instance to avoid checking again that
    the uniformity is the same as the product uniformity, but we register nevertheless a nice
    formula for the distance -/
  let i := PseudoEMetricSpace.toPseudoMetricSpaceOfDist
    (fun f g : ∀ b, π b => ((sup univ fun b => nndist (f b) (g b) : ℝ≥0) : ℝ))
    (fun f g => ((Finset.sup_lt_iff bot_lt_top).2 fun b _ => edist_lt_top _ _).ne)
    (fun f g => by
      simp only [edist_pi_def, edist_nndist, ← ENNReal.coe_finset_sup, ENNReal.coe_toReal])
  refine i.replaceBornology fun s => ?_
  simp only [← isBounded_def, isBounded_iff_eventually, ← forall_isBounded_image_eval_iff,
    ball_image_iff, ← Filter.eventually_all, Function.eval_apply, @dist_nndist (π _)]
  refine' eventually_congr ((eventually_ge_atTop 0).mono fun C hC => _)
  lift C to ℝ≥0 using hC
  

Proof state:
case intro
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
i : PseudoMetricSpace ((b : β) → π b) :=
  PseudoEMetricSpace.toPseudoMetricSpaceOfDist (fun f g => ↑(sup Finset.univ fun b => nndist (f b) (g b)))
    (_ : ∀ (f g : (b : β) → π b), (sup Finset.univ fun b => edist (f b) (g b)) ≠ ⊤)
    (_ :
      ∀ (f g : (b : β) → π b),
        ↑(sup Finset.univ fun b => nndist (f b) (g b)) = ENNReal.toReal (sup Finset.univ fun x => edist (f x) (g x)))
s : Set ((b : β) → π b)
C : ℝ≥0
⊢ (∀ (i : β), ∀ x ∈ s, ∀ x_1 ∈ s, ↑(nndist (Function.eval i x) (Function.eval i x_1)) ≤ ↑C) ↔
    ∀ ⦃x : (b : β) → π b⦄, x ∈ s → ∀ ⦃y : (b : β) → π b⦄, y ∈ s → dist x y ≤ ↑C

Next tactic:
refine' ⟨fun H x hx y hy => NNReal.coe_le_coe.2 <| Finset.sup_le fun b _ => H b x hx y hy,
    fun H b x hx y hy => NNReal.coe_le_coe.2 _⟩
/-- A finite product of pseudometric spaces is a pseudometric space, with the sup distance. -/
instance pseudoMetricSpacePi : PseudoMetricSpace (∀ b, π b) := by
  /- we construct the instance from the pseudoemetric space instance to avoid checking again that
    the uniformity is the same as the product uniformity, but we register nevertheless a nice
    formula for the distance -/
  let i := PseudoEMetricSpace.toPseudoMetricSpaceOfDist
    (fun f g : ∀ b, π b => ((sup univ fun b => nndist (f b) (g b) : ℝ≥0) : ℝ))
    (fun f g => ((Finset.sup_lt_iff bot_lt_top).2 fun b _ => edist_lt_top _ _).ne)
    (fun f g => by
      simp only [edist_pi_def, edist_nndist, ← ENNReal.coe_finset_sup, ENNReal.coe_toReal])
  refine i.replaceBornology fun s => ?_
  simp only [← isBounded_def, isBounded_iff_eventually, ← forall_isBounded_image_eval_iff,
    ball_image_iff, ← Filter.eventually_all, Function.eval_apply, @dist_nndist (π _)]
  refine' eventually_congr ((eventually_ge_atTop 0).mono fun C hC => _)
  lift C to ℝ≥0 using hC
  refine' ⟨fun H x hx y hy => NNReal.coe_le_coe.2 <| Finset.sup_le fun b _ => H b x hx y hy,
    fun H b x hx y hy => NNReal.coe_le_coe.2 _⟩
  

Proof state:
case intro
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
i : PseudoMetricSpace ((b : β) → π b) :=
  PseudoEMetricSpace.toPseudoMetricSpaceOfDist (fun f g => ↑(sup Finset.univ fun b => nndist (f b) (g b)))
    (_ : ∀ (f g : (b : β) → π b), (sup Finset.univ fun b => edist (f b) (g b)) ≠ ⊤)
    (_ :
      ∀ (f g : (b : β) → π b),
        ↑(sup Finset.univ fun b => nndist (f b) (g b)) = ENNReal.toReal (sup Finset.univ fun x => edist (f x) (g x)))
s : Set ((b : β) → π b)
C : ℝ≥0
H : ∀ ⦃x : (b : β) → π b⦄, x ∈ s → ∀ ⦃y : (b : β) → π b⦄, y ∈ s → dist x y ≤ ↑C
b : β
x : (x : β) → π x
hx : x ∈ s
y : (x : β) → π x
hy : y ∈ s
⊢ nndist (Function.eval b x) (Function.eval b y) ≤ C

Next tactic:
simpa only using Finset.sup_le_iff.1 (NNReal.coe_le_coe.1 <| H hx hy) b (Finset.mem_univ b)
theorem nndist_pi_le_iff {f g : ∀ b, π b} {r : ℝ≥0} :
    nndist f g ≤ r ↔ ∀ b, nndist (f b) (g b) ≤ r := by 

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
⊢ nndist f g ≤ r ↔ ∀ (b : β), nndist (f b) (g b) ≤ r

Next tactic:
simp [nndist_pi_def]
theorem nndist_pi_lt_iff {f g : ∀ b, π b} {r : ℝ≥0} (hr : 0 < r) :
    nndist f g < r ↔ ∀ b, nndist (f b) (g b) < r := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : 0 < r
⊢ nndist f g < r ↔ ∀ (b : β), nndist (f b) (g b) < r

Next tactic:
rw [← bot_eq_zero'] at hr
theorem nndist_pi_lt_iff {f g : ∀ b, π b} {r : ℝ≥0} (hr : 0 < r) :
    nndist f g < r ↔ ∀ b, nndist (f b) (g b) < r := by
  rw [← bot_eq_zero'] at hr
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : ⊥ < r
⊢ nndist f g < r ↔ ∀ (b : β), nndist (f b) (g b) < r

Next tactic:
simp [nndist_pi_def, Finset.sup_lt_iff hr]
theorem nndist_pi_eq_iff {f g : ∀ b, π b} {r : ℝ≥0} (hr : 0 < r) :
    nndist f g = r ↔ (∃ i, nndist (f i) (g i) = r) ∧ ∀ b, nndist (f b) (g b) ≤ r := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : 0 < r
⊢ nndist f g = r ↔ (∃ i, nndist (f i) (g i) = r) ∧ ∀ (b : β), nndist (f b) (g b) ≤ r

Next tactic:
rw [eq_iff_le_not_lt, nndist_pi_lt_iff hr, nndist_pi_le_iff, not_forall, and_comm]
theorem nndist_pi_eq_iff {f g : ∀ b, π b} {r : ℝ≥0} (hr : 0 < r) :
    nndist f g = r ↔ (∃ i, nndist (f i) (g i) = r) ∧ ∀ b, nndist (f b) (g b) ≤ r := by
  rw [eq_iff_le_not_lt, nndist_pi_lt_iff hr, nndist_pi_le_iff, not_forall, and_comm]
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : 0 < r
⊢ ((∃ x, ¬nndist (f x) (g x) < r) ∧ ∀ (b : β), nndist (f b) (g b) ≤ r) ↔
    (∃ i, nndist (f i) (g i) = r) ∧ ∀ (b : β), nndist (f b) (g b) ≤ r

Next tactic:
simp_rw [not_lt, and_congr_left_iff, le_antisymm_iff]
theorem nndist_pi_eq_iff {f g : ∀ b, π b} {r : ℝ≥0} (hr : 0 < r) :
    nndist f g = r ↔ (∃ i, nndist (f i) (g i) = r) ∧ ∀ b, nndist (f b) (g b) ≤ r := by
  rw [eq_iff_le_not_lt, nndist_pi_lt_iff hr, nndist_pi_le_iff, not_forall, and_comm]
  simp_rw [not_lt, and_congr_left_iff, le_antisymm_iff]
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : 0 < r
⊢ (∀ (b : β), nndist (f b) (g b) ≤ r) →
    ((∃ x, r ≤ nndist (f x) (g x)) ↔ ∃ i, nndist (f i) (g i) ≤ r ∧ r ≤ nndist (f i) (g i))

Next tactic:
intro h
theorem nndist_pi_eq_iff {f g : ∀ b, π b} {r : ℝ≥0} (hr : 0 < r) :
    nndist f g = r ↔ (∃ i, nndist (f i) (g i) = r) ∧ ∀ b, nndist (f b) (g b) ≤ r := by
  rw [eq_iff_le_not_lt, nndist_pi_lt_iff hr, nndist_pi_le_iff, not_forall, and_comm]
  simp_rw [not_lt, and_congr_left_iff, le_antisymm_iff]
  intro h
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : 0 < r
h : ∀ (b : β), nndist (f b) (g b) ≤ r
⊢ (∃ x, r ≤ nndist (f x) (g x)) ↔ ∃ i, nndist (f i) (g i) ≤ r ∧ r ≤ nndist (f i) (g i)

Next tactic:
refine' exists_congr fun b => _
theorem nndist_pi_eq_iff {f g : ∀ b, π b} {r : ℝ≥0} (hr : 0 < r) :
    nndist f g = r ↔ (∃ i, nndist (f i) (g i) = r) ∧ ∀ b, nndist (f b) (g b) ≤ r := by
  rw [eq_iff_le_not_lt, nndist_pi_lt_iff hr, nndist_pi_le_iff, not_forall, and_comm]
  simp_rw [not_lt, and_congr_left_iff, le_antisymm_iff]
  intro h
  refine' exists_congr fun b => _
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : 0 < r
h : ∀ (b : β), nndist (f b) (g b) ≤ r
b : β
⊢ r ≤ nndist (f b) (g b) ↔ nndist (f b) (g b) ≤ r ∧ r ≤ nndist (f b) (g b)

Next tactic:
apply (and_iff_right <| h _).symm
theorem dist_pi_lt_iff {f g : ∀ b, π b} {r : ℝ} (hr : 0 < r) :
    dist f g < r ↔ ∀ b, dist (f b) (g b) < r := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ
hr : 0 < r
⊢ dist f g < r ↔ ∀ (b : β), dist (f b) (g b) < r

Next tactic:
lift r to ℝ≥0 using hr.le
theorem dist_pi_lt_iff {f g : ∀ b, π b} {r : ℝ} (hr : 0 < r) :
    dist f g < r ↔ ∀ b, dist (f b) (g b) < r := by
  lift r to ℝ≥0 using hr.le
  

Proof state:
case intro
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : 0 < ↑r
⊢ dist f g < ↑r ↔ ∀ (b : β), dist (f b) (g b) < ↑r

Next tactic:
exact nndist_pi_lt_iff hr
theorem dist_pi_le_iff {f g : ∀ b, π b} {r : ℝ} (hr : 0 ≤ r) :
    dist f g ≤ r ↔ ∀ b, dist (f b) (g b) ≤ r := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ
hr : 0 ≤ r
⊢ dist f g ≤ r ↔ ∀ (b : β), dist (f b) (g b) ≤ r

Next tactic:
lift r to ℝ≥0 using hr
theorem dist_pi_le_iff {f g : ∀ b, π b} {r : ℝ} (hr : 0 ≤ r) :
    dist f g ≤ r ↔ ∀ b, dist (f b) (g b) ≤ r := by
  lift r to ℝ≥0 using hr
  

Proof state:
case intro
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
⊢ dist f g ≤ ↑r ↔ ∀ (b : β), dist (f b) (g b) ≤ ↑r

Next tactic:
exact nndist_pi_le_iff
theorem dist_pi_eq_iff {f g : ∀ b, π b} {r : ℝ} (hr : 0 < r) :
    dist f g = r ↔ (∃ i, dist (f i) (g i) = r) ∧ ∀ b, dist (f b) (g b) ≤ r := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ
hr : 0 < r
⊢ dist f g = r ↔ (∃ i, dist (f i) (g i) = r) ∧ ∀ (b : β), dist (f b) (g b) ≤ r

Next tactic:
lift r to ℝ≥0 using hr.le
theorem dist_pi_eq_iff {f g : ∀ b, π b} {r : ℝ} (hr : 0 < r) :
    dist f g = r ↔ (∃ i, dist (f i) (g i) = r) ∧ ∀ b, dist (f b) (g b) ≤ r := by
  lift r to ℝ≥0 using hr.le
  

Proof state:
case intro
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
r : ℝ≥0
hr : 0 < ↑r
⊢ dist f g = ↑r ↔ (∃ i, dist (f i) (g i) = ↑r) ∧ ∀ (b : β), dist (f b) (g b) ≤ ↑r

Next tactic:
simp_rw [← coe_nndist, NNReal.coe_eq, nndist_pi_eq_iff hr, NNReal.coe_le_coe]
theorem dist_pi_le_iff' [Nonempty β] {f g : ∀ b, π b} {r : ℝ} :
    dist f g ≤ r ↔ ∀ b, dist (f b) (g b) ≤ r := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝³ : PseudoMetricSpace α
π : β → Type u_3
inst✝² : Fintype β
inst✝¹ : (b : β) → PseudoMetricSpace (π b)
inst✝ : Nonempty β
f g : (b : β) → π b
r : ℝ
⊢ dist f g ≤ r ↔ ∀ (b : β), dist (f b) (g b) ≤ r

Next tactic:
by_cases hr : 0 ≤ r
theorem dist_pi_le_iff' [Nonempty β] {f g : ∀ b, π b} {r : ℝ} :
    dist f g ≤ r ↔ ∀ b, dist (f b) (g b) ≤ r := by
  by_cases hr : 0 ≤ r
  · 

Proof state:
case pos
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝³ : PseudoMetricSpace α
π : β → Type u_3
inst✝² : Fintype β
inst✝¹ : (b : β) → PseudoMetricSpace (π b)
inst✝ : Nonempty β
f g : (b : β) → π b
r : ℝ
hr : 0 ≤ r
⊢ dist f g ≤ r ↔ ∀ (b : β), dist (f b) (g b) ≤ r

Next tactic:
exact dist_pi_le_iff hr
theorem dist_pi_le_iff' [Nonempty β] {f g : ∀ b, π b} {r : ℝ} :
    dist f g ≤ r ↔ ∀ b, dist (f b) (g b) ≤ r := by
  by_cases hr : 0 ≤ r
  · exact dist_pi_le_iff hr
  · 

Proof state:
case neg
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝³ : PseudoMetricSpace α
π : β → Type u_3
inst✝² : Fintype β
inst✝¹ : (b : β) → PseudoMetricSpace (π b)
inst✝ : Nonempty β
f g : (b : β) → π b
r : ℝ
hr : ¬0 ≤ r
⊢ dist f g ≤ r ↔ ∀ (b : β), dist (f b) (g b) ≤ r

Next tactic:
exact iff_of_false (fun h => hr <| dist_nonneg.trans h) fun h =>
      hr <| dist_nonneg.trans <| h <| Classical.arbitrary _
@[simp]
theorem dist_pi_const [Nonempty β] (a b : α) : (dist (fun _ : β => a) fun _ => b) = dist a b := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝³ : PseudoMetricSpace α
π : β → Type u_3
inst✝² : Fintype β
inst✝¹ : (b : β) → PseudoMetricSpace (π b)
inst✝ : Nonempty β
a b : α
⊢ (dist (fun x => a) fun x => b) = dist a b

Next tactic:
simpa only [dist_edist] using congr_arg ENNReal.toReal (edist_pi_const a b)
theorem nndist_le_pi_nndist (f g : ∀ b, π b) (b : β) : nndist (f b) (g b) ≤ nndist f g := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
b : β
⊢ nndist (f b) (g b) ≤ nndist f g

Next tactic:
rw [← ENNReal.coe_le_coe, ← edist_nndist, ← edist_nndist]
theorem nndist_le_pi_nndist (f g : ∀ b, π b) (b : β) : nndist (f b) (g b) ≤ nndist f g := by
  rw [← ENNReal.coe_le_coe, ← edist_nndist, ← edist_nndist]
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
b : β
⊢ edist (f b) (g b) ≤ edist f g

Next tactic:
exact edist_le_pi_edist f g b
theorem dist_le_pi_dist (f g : ∀ b, π b) (b : β) : dist (f b) (g b) ≤ dist f g := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
f g : (b : β) → π b
b : β
⊢ dist (f b) (g b) ≤ dist f g

Next tactic:
simp only [dist_nndist, NNReal.coe_le_coe, nndist_le_pi_nndist f g b]
/-- An open ball in a product space is a product of open balls. See also `ball_pi'`
for a version assuming `Nonempty β` instead of `0 < r`. -/
theorem ball_pi (x : ∀ b, π b) {r : ℝ} (hr : 0 < r) :
    ball x r = Set.pi univ fun b => ball (x b) r := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
x : (b : β) → π b
r : ℝ
hr : 0 < r
⊢ ball x r = Set.pi Set.univ fun b => ball (x b) r

Next tactic:
ext p
/-- An open ball in a product space is a product of open balls. See also `ball_pi'`
for a version assuming `Nonempty β` instead of `0 < r`. -/
theorem ball_pi (x : ∀ b, π b) {r : ℝ} (hr : 0 < r) :
    ball x r = Set.pi univ fun b => ball (x b) r := by
  ext p
  

Proof state:
case h
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
x : (b : β) → π b
r : ℝ
hr : 0 < r
p : (b : β) → π b
⊢ p ∈ ball x r ↔ p ∈ Set.pi Set.univ fun b => ball (x b) r

Next tactic:
simp [dist_pi_lt_iff hr]
/-- An open ball in a product space is a product of open balls. See also `ball_pi`
for a version assuming `0 < r` instead of `Nonempty β`. -/
theorem ball_pi' [Nonempty β] (x : ∀ b, π b) (r : ℝ) :
    ball x r = Set.pi univ fun b => ball (x b) r :=
  (lt_or_le 0 r).elim (ball_pi x) fun hr => by 

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝³ : PseudoMetricSpace α
π : β → Type u_3
inst✝² : Fintype β
inst✝¹ : (b : β) → PseudoMetricSpace (π b)
inst✝ : Nonempty β
x : (b : β) → π b
r : ℝ
hr : r ≤ 0
⊢ ball x r = Set.pi Set.univ fun b => ball (x b) r

Next tactic:
simp [ball_eq_empty.2 hr]
/-- A closed ball in a product space is a product of closed balls. See also `closedBall_pi'`
for a version assuming `Nonempty β` instead of `0 ≤ r`. -/
theorem closedBall_pi (x : ∀ b, π b) {r : ℝ} (hr : 0 ≤ r) :
    closedBall x r = Set.pi univ fun b => closedBall (x b) r := by
  

Proof state:
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
x : (b : β) → π b
r : ℝ
hr : 0 ≤ r
⊢ closedBall x r = Set.pi Set.univ fun b => closedBall (x b) r

Next tactic:
ext p
/-- A closed ball in a product space is a product of closed balls. See also `closedBall_pi'`
for a version assuming `Nonempty β` instead of `0 ≤ r`. -/
theorem closedBall_pi (x : ∀ b, π b) {r : ℝ} (hr : 0 ≤ r) :
    closedBall x r = Set.pi univ fun b => closedBall (x b) r := by
  ext p
  

Proof state:
case h
α : Type u
β : Type v
X : Type u_1
ι : Type u_2
inst✝² : PseudoMetricSpace α
π : β → Type u_3
inst✝¹ : Fintype β
inst✝ : (b : β) → PseudoMetricSpace (π b)
x : (b : β) → π b
r : ℝ
hr : 0 ≤ r
p : (b : β) → π b
⊢ p ∈ closedBall x r ↔ p ∈ Set.pi Set.univ fun b => closedBall (x b) r

Next tactic:
simp [dist_pi_le_iff hr]