l3lab/ntp-mathlib huggingface dataset:
/-- The quotient ring of `I ⧸ I ^ 2` is `R ⧸ I`. -/
def quotCotangent : (R ⧸ I ^ 2) ⧸ I.cotangentIdeal ≃+* R ⧸ I := by
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝¹⁰ : CommRing R
inst✝⁹ : CommSemiring S
inst✝⁸ : Algebra S R
inst✝⁷ : CommSemiring S'
inst✝⁶ : Algebra S' R
inst✝⁵ : Algebra S S'
inst✝⁴ : IsScalarTower S S' R
I : Ideal R
A : Type u_1
B : Type u_2
inst✝³ : CommRing A
inst✝² : CommRing B
inst✝¹ : Algebra R A
inst✝ : Algebra R B
⊢ (R ⧸ I ^ 2) ⧸ cotangentIdeal I ≃+* R ⧸ I

Next tactic:
refine (Ideal.quotEquivOfEq (Ideal.map_eq_submodule_map _ _).symm).trans ?_
/-- The quotient ring of `I ⧸ I ^ 2` is `R ⧸ I`. -/
def quotCotangent : (R ⧸ I ^ 2) ⧸ I.cotangentIdeal ≃+* R ⧸ I := by
  refine (Ideal.quotEquivOfEq (Ideal.map_eq_submodule_map _ _).symm).trans ?_
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝¹⁰ : CommRing R
inst✝⁹ : CommSemiring S
inst✝⁸ : Algebra S R
inst✝⁷ : CommSemiring S'
inst✝⁶ : Algebra S' R
inst✝⁵ : Algebra S S'
inst✝⁴ : IsScalarTower S S' R
I : Ideal R
A : Type u_1
B : Type u_2
inst✝³ : CommRing A
inst✝² : CommRing B
inst✝¹ : Algebra R A
inst✝ : Algebra R B
⊢ (R ⧸ I ^ 2) ⧸ map (Quotient.mk (I ^ 2)) I ≃+* R ⧸ I

Next tactic:
refine (DoubleQuot.quotQuotEquivQuotSup _ _).trans ?_
/-- The quotient ring of `I ⧸ I ^ 2` is `R ⧸ I`. -/
def quotCotangent : (R ⧸ I ^ 2) ⧸ I.cotangentIdeal ≃+* R ⧸ I := by
  refine (Ideal.quotEquivOfEq (Ideal.map_eq_submodule_map _ _).symm).trans ?_
  refine (DoubleQuot.quotQuotEquivQuotSup _ _).trans ?_
  

Proof state:
R : Type u
S : Type v
S' : Type w
inst✝¹⁰ : CommRing R
inst✝⁹ : CommSemiring S
inst✝⁸ : Algebra S R
inst✝⁷ : CommSemiring S'
inst✝⁶ : Algebra S' R
inst✝⁵ : Algebra S S'
inst✝⁴ : IsScalarTower S S' R
I : Ideal R
A : Type u_1
B : Type u_2
inst✝³ : CommRing A
inst✝² : CommRing B
inst✝¹ : Algebra R A
inst✝ : Algebra R B
⊢ R ⧸ I ^ 2 ⊔ I ≃+* R ⧸ I

Next tactic:
exact Ideal.quotEquivOfEq (sup_eq_right.mpr <| Ideal.pow_le_self two_ne_zero)
@[to_additive]
theorem Bornology.IsBounded.mul (hs : IsBounded s) (ht : IsBounded t) : IsBounded (s * t) := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsBounded s
ht : IsBounded t
⊢ IsBounded (s * t)

Next tactic:
obtain ⟨Rs, hRs⟩ : ∃ R, ∀ x ∈ s, ‖x‖ ≤ R := hs.exists_norm_le'
@[to_additive]
theorem Bornology.IsBounded.mul (hs : IsBounded s) (ht : IsBounded t) : IsBounded (s * t) := by
  obtain ⟨Rs, hRs⟩ : ∃ R, ∀ x ∈ s, ‖x‖ ≤ R := hs.exists_norm_le'
  

Proof state:
case intro
E : Type u_1
inst✝ : SeminormedGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsBounded s
ht : IsBounded t
Rs : ℝ
hRs : ∀ x ∈ s, ‖x‖ ≤ Rs
⊢ IsBounded (s * t)

Next tactic:
obtain ⟨Rt, hRt⟩ : ∃ R, ∀ x ∈ t, ‖x‖ ≤ R := ht.exists_norm_le'
@[to_additive]
theorem Bornology.IsBounded.mul (hs : IsBounded s) (ht : IsBounded t) : IsBounded (s * t) := by
  obtain ⟨Rs, hRs⟩ : ∃ R, ∀ x ∈ s, ‖x‖ ≤ R := hs.exists_norm_le'
  obtain ⟨Rt, hRt⟩ : ∃ R, ∀ x ∈ t, ‖x‖ ≤ R := ht.exists_norm_le'
  

Proof state:
case intro.intro
E : Type u_1
inst✝ : SeminormedGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsBounded s
ht : IsBounded t
Rs : ℝ
hRs : ∀ x ∈ s, ‖x‖ ≤ Rs
Rt : ℝ
hRt : ∀ x ∈ t, ‖x‖ ≤ Rt
⊢ IsBounded (s * t)

Next tactic:
refine' isBounded_iff_forall_norm_le'.2 ⟨Rs + Rt, _⟩
@[to_additive]
theorem Bornology.IsBounded.mul (hs : IsBounded s) (ht : IsBounded t) : IsBounded (s * t) := by
  obtain ⟨Rs, hRs⟩ : ∃ R, ∀ x ∈ s, ‖x‖ ≤ R := hs.exists_norm_le'
  obtain ⟨Rt, hRt⟩ : ∃ R, ∀ x ∈ t, ‖x‖ ≤ R := ht.exists_norm_le'
  refine' isBounded_iff_forall_norm_le'.2 ⟨Rs + Rt, _⟩
  

Proof state:
case intro.intro
E : Type u_1
inst✝ : SeminormedGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsBounded s
ht : IsBounded t
Rs : ℝ
hRs : ∀ x ∈ s, ‖x‖ ≤ Rs
Rt : ℝ
hRt : ∀ x ∈ t, ‖x‖ ≤ Rt
⊢ ∀ x ∈ s * t, ‖x‖ ≤ Rs + Rt

Next tactic:
rintro z ⟨x, y, hx, hy, rfl⟩
@[to_additive]
theorem Bornology.IsBounded.mul (hs : IsBounded s) (ht : IsBounded t) : IsBounded (s * t) := by
  obtain ⟨Rs, hRs⟩ : ∃ R, ∀ x ∈ s, ‖x‖ ≤ R := hs.exists_norm_le'
  obtain ⟨Rt, hRt⟩ : ∃ R, ∀ x ∈ t, ‖x‖ ≤ R := ht.exists_norm_le'
  refine' isBounded_iff_forall_norm_le'.2 ⟨Rs + Rt, _⟩
  rintro z ⟨x, y, hx, hy, rfl⟩
  

Proof state:
case intro.intro.intro.intro.intro.intro
E : Type u_1
inst✝ : SeminormedGroup E
ε δ : ℝ
s t : Set E
x✝ y✝ : E
hs : IsBounded s
ht : IsBounded t
Rs : ℝ
hRs : ∀ x ∈ s, ‖x‖ ≤ Rs
Rt : ℝ
hRt : ∀ x ∈ t, ‖x‖ ≤ Rt
x y : E
hx : x ∈ s
hy : y ∈ t
⊢ ‖(fun x x_1 => x * x_1) x y‖ ≤ Rs + Rt

Next tactic:
exact norm_mul_le_of_le (hRs x hx) (hRt y hy)
@[to_additive]
theorem Bornology.IsBounded.inv : IsBounded s → IsBounded s⁻¹ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ IsBounded s → IsBounded s⁻¹

Next tactic:
simp_rw [isBounded_iff_forall_norm_le', ← image_inv, ball_image_iff, norm_inv']
@[to_additive]
theorem Bornology.IsBounded.inv : IsBounded s → IsBounded s⁻¹ := by
  simp_rw [isBounded_iff_forall_norm_le', ← image_inv, ball_image_iff, norm_inv']
  

Proof state:
E : Type u_1
inst✝ : SeminormedGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ (∃ C, ∀ x ∈ s, ‖x‖ ≤ C) → ∃ C, ∀ x ∈ s, ‖x‖ ≤ C

Next tactic:
exact id
@[to_additive (attr := simp)]
theorem infEdist_inv_inv (x : E) (s : Set E) : infEdist x⁻¹ s⁻¹ = infEdist x s := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s✝ t : Set E
x✝ y x : E
s : Set E
⊢ infEdist x⁻¹ s⁻¹ = infEdist x s

Next tactic:
rw [← image_inv, infEdist_image isometry_inv]
@[to_additive]
theorem infEdist_inv (x : E) (s : Set E) : infEdist x⁻¹ s = infEdist x s⁻¹ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s✝ t : Set E
x✝ y x : E
s : Set E
⊢ infEdist x⁻¹ s = infEdist x s⁻¹

Next tactic:
rw [← infEdist_inv_inv, inv_inv]
@[to_additive]
theorem ediam_mul_le (x y : Set E) : EMetric.diam (x * y) ≤ EMetric.diam x + EMetric.diam y :=
  (LipschitzOnWith.ediam_image2_le (· * ·) _ _
        (fun _ _ => (isometry_mul_right _).lipschitz.lipschitzOnWith _) fun _ _ =>
        (isometry_mul_left _).lipschitz.lipschitzOnWith _).trans_eq <|
    by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x✝ y✝ : E
x y : Set E
⊢ ↑1 * EMetric.diam x + ↑1 * EMetric.diam y = EMetric.diam x + EMetric.diam y

Next tactic:
simp only [ENNReal.coe_one, one_mul]
@[to_additive (attr := simp)]
theorem inv_thickening : (thickening δ s)⁻¹ = thickening δ s⁻¹ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ (thickening δ s)⁻¹ = thickening δ s⁻¹

Next tactic:
simp_rw [thickening, ← infEdist_inv]
@[to_additive (attr := simp)]
theorem inv_thickening : (thickening δ s)⁻¹ = thickening δ s⁻¹ := by
  simp_rw [thickening, ← infEdist_inv]
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x | EMetric.infEdist x s < ENNReal.ofReal δ}⁻¹ = {x | EMetric.infEdist x⁻¹ s < ENNReal.ofReal δ}

Next tactic:
rfl
@[to_additive (attr := simp)]
theorem inv_cthickening : (cthickening δ s)⁻¹ = cthickening δ s⁻¹ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ (cthickening δ s)⁻¹ = cthickening δ s⁻¹

Next tactic:
simp_rw [cthickening, ← infEdist_inv]
@[to_additive (attr := simp)]
theorem inv_cthickening : (cthickening δ s)⁻¹ = cthickening δ s⁻¹ := by
  simp_rw [cthickening, ← infEdist_inv]
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x | EMetric.infEdist x s ≤ ENNReal.ofReal δ}⁻¹ = {x | EMetric.infEdist x⁻¹ s ≤ ENNReal.ofReal δ}

Next tactic:
rfl
@[to_additive]
theorem singleton_mul_ball : {x} * ball y δ = ball (x * y) δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x} * ball y δ = ball (x * y) δ

Next tactic:
simp only [preimage_mul_ball, image_mul_left, singleton_mul, div_inv_eq_mul, mul_comm y x]
@[to_additive]
theorem singleton_div_ball : {x} / ball y δ = ball (x / y) δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x} / ball y δ = ball (x / y) δ

Next tactic:
simp_rw [div_eq_mul_inv, inv_ball, singleton_mul_ball]
@[to_additive]
theorem ball_mul_singleton : ball x δ * {y} = ball (x * y) δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ ball x δ * {y} = ball (x * y) δ

Next tactic:
rw [mul_comm, singleton_mul_ball, mul_comm y]
@[to_additive]
theorem ball_div_singleton : ball x δ / {y} = ball (x / y) δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ ball x δ / {y} = ball (x / y) δ

Next tactic:
simp_rw [div_eq_mul_inv, inv_singleton, ball_mul_singleton]
@[to_additive]
theorem singleton_mul_ball_one : {x} * ball 1 δ = ball x δ := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x} * ball 1 δ = ball x δ

Next tactic:
simp
@[to_additive]
theorem singleton_div_ball_one : {x} / ball 1 δ = ball x δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x} / ball 1 δ = ball x δ

Next tactic:
rw [singleton_div_ball, div_one]
@[to_additive]
theorem ball_one_mul_singleton : ball 1 δ * {x} = ball x δ := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ ball 1 δ * {x} = ball x δ

Next tactic:
simp [ball_mul_singleton]
@[to_additive]
theorem ball_one_div_singleton : ball 1 δ / {x} = ball x⁻¹ δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ ball 1 δ / {x} = ball x⁻¹ δ

Next tactic:
rw [ball_div_singleton, one_div]
@[to_additive]
theorem smul_ball_one : x • ball (1 : E) δ = ball x δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ x • ball 1 δ = ball x δ

Next tactic:
rw [smul_ball, smul_eq_mul, mul_one]
@[to_additive (attr := simp 1100)]
theorem singleton_mul_closedBall : {x} * closedBall y δ = closedBall (x * y) δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x} * closedBall y δ = closedBall (x * y) δ

Next tactic:
simp_rw [singleton_mul, ← smul_eq_mul, image_smul, smul_closedBall]
@[to_additive (attr := simp 1100)]
theorem singleton_div_closedBall : {x} / closedBall y δ = closedBall (x / y) δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x} / closedBall y δ = closedBall (x / y) δ

Next tactic:
simp_rw [div_eq_mul_inv, inv_closedBall, singleton_mul_closedBall]
@[to_additive (attr := simp 1100)]
theorem closedBall_mul_singleton : closedBall x δ * {y} = closedBall (x * y) δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ closedBall x δ * {y} = closedBall (x * y) δ

Next tactic:
simp [mul_comm _ {y}, mul_comm y]
@[to_additive (attr := simp 1100)]
theorem closedBall_div_singleton : closedBall x δ / {y} = closedBall (x / y) δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ closedBall x δ / {y} = closedBall (x / y) δ

Next tactic:
simp [div_eq_mul_inv]
@[to_additive]
theorem singleton_mul_closedBall_one : {x} * closedBall 1 δ = closedBall x δ := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x} * closedBall 1 δ = closedBall x δ

Next tactic:
simp
@[to_additive]
theorem singleton_div_closedBall_one : {x} / closedBall 1 δ = closedBall x δ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ {x} / closedBall 1 δ = closedBall x δ

Next tactic:
rw [singleton_div_closedBall, div_one]
@[to_additive]
theorem closedBall_one_mul_singleton : closedBall 1 δ * {x} = closedBall x δ := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ closedBall 1 δ * {x} = closedBall x δ

Next tactic:
simp
@[to_additive]
theorem closedBall_one_div_singleton : closedBall 1 δ / {x} = closedBall x⁻¹ δ := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ closedBall 1 δ / {x} = closedBall x⁻¹ δ

Next tactic:
simp
@[to_additive (attr := simp 1100)]
theorem smul_closedBall_one : x • closedBall (1 : E) δ = closedBall x δ := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ x • closedBall 1 δ = closedBall x δ

Next tactic:
simp
@[to_additive]
theorem mul_ball_one : s * ball 1 δ = thickening δ s := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ s * ball 1 δ = thickening δ s

Next tactic:
rw [thickening_eq_biUnion_ball]
@[to_additive]
theorem mul_ball_one : s * ball 1 δ = thickening δ s := by
  rw [thickening_eq_biUnion_ball]
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ s * ball 1 δ = ⋃ x ∈ s, ball x δ

Next tactic:
convert iUnion₂_mul (fun x (_ : x ∈ s) => {x}) (ball (1 : E) δ)
@[to_additive]
theorem mul_ball_one : s * ball 1 δ = thickening δ s := by
  rw [thickening_eq_biUnion_ball]
  convert iUnion₂_mul (fun x (_ : x ∈ s) => {x}) (ball (1 : E) δ)
  

Proof state:
case h.e'_2.h.e'_5
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ s = ⋃ i ∈ s, {i}
case h.e'_3.h.e'_3.h.f
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y x✝¹ : E
x✝ : x✝¹ ∈ s
⊢ ball x✝¹ δ = {x✝¹} * ball 1 δ

Next tactic:
exact s.biUnion_of_singleton.symm
@[to_additive]
theorem mul_ball_one : s * ball 1 δ = thickening δ s := by
  rw [thickening_eq_biUnion_ball]
  convert iUnion₂_mul (fun x (_ : x ∈ s) => {x}) (ball (1 : E) δ)
  exact s.biUnion_of_singleton.symm
  

Proof state:
case h.e'_3.h.e'_3.h.f
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y x✝¹ : E
x✝ : x✝¹ ∈ s
⊢ ball x✝¹ δ = {x✝¹} * ball 1 δ

Next tactic:
ext x
@[to_additive]
theorem mul_ball_one : s * ball 1 δ = thickening δ s := by
  rw [thickening_eq_biUnion_ball]
  convert iUnion₂_mul (fun x (_ : x ∈ s) => {x}) (ball (1 : E) δ)
  exact s.biUnion_of_singleton.symm
  ext x
  

Proof state:
case h.e'_3.h.e'_3.h.f.h
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x✝² y x✝¹ : E
x✝ : x✝¹ ∈ s
x : E
⊢ x ∈ ball x✝¹ δ ↔ x ∈ {x✝¹} * ball 1 δ

Next tactic:
simp_rw [singleton_mul_ball, mul_one]
@[to_additive]
theorem div_ball_one : s / ball 1 δ = thickening δ s := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ s / ball 1 δ = thickening δ s

Next tactic:
simp [div_eq_mul_inv, mul_ball_one]
@[to_additive]
theorem ball_mul_one : ball 1 δ * s = thickening δ s := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ ball 1 δ * s = thickening δ s

Next tactic:
rw [mul_comm, mul_ball_one]
@[to_additive]
theorem ball_div_one : ball 1 δ / s = thickening δ s⁻¹ := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ ball 1 δ / s = thickening δ s⁻¹

Next tactic:
simp [div_eq_mul_inv, ball_mul_one]
@[to_additive (attr := simp)]
theorem mul_ball : s * ball x δ = x • thickening δ s := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ s * ball x δ = x • thickening δ s

Next tactic:
rw [← smul_ball_one, mul_smul_comm, mul_ball_one]
@[to_additive (attr := simp)]
theorem div_ball : s / ball x δ = x⁻¹ • thickening δ s := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ s / ball x δ = x⁻¹ • thickening δ s

Next tactic:
simp [div_eq_mul_inv]
@[to_additive (attr := simp)]
theorem ball_mul : ball x δ * s = x • thickening δ s := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ ball x δ * s = x • thickening δ s

Next tactic:
rw [mul_comm, mul_ball]
@[to_additive (attr := simp)]
theorem ball_div : ball x δ / s = x • thickening δ s⁻¹ := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
⊢ ball x δ / s = x • thickening δ s⁻¹

Next tactic:
simp [div_eq_mul_inv]
@[to_additive]
theorem IsCompact.mul_closedBall_one (hs : IsCompact s) (hδ : 0 ≤ δ) :
    s * closedBall (1 : E) δ = cthickening δ s := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsCompact s
hδ : 0 ≤ δ
⊢ s * closedBall 1 δ = cthickening δ s

Next tactic:
rw [hs.cthickening_eq_biUnion_closedBall hδ]
@[to_additive]
theorem IsCompact.mul_closedBall_one (hs : IsCompact s) (hδ : 0 ≤ δ) :
    s * closedBall (1 : E) δ = cthickening δ s := by
  rw [hs.cthickening_eq_biUnion_closedBall hδ]
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsCompact s
hδ : 0 ≤ δ
⊢ s * closedBall 1 δ = ⋃ x ∈ s, closedBall x δ

Next tactic:
ext x
@[to_additive]
theorem IsCompact.mul_closedBall_one (hs : IsCompact s) (hδ : 0 ≤ δ) :
    s * closedBall (1 : E) δ = cthickening δ s := by
  rw [hs.cthickening_eq_biUnion_closedBall hδ]
  ext x
  

Proof state:
case h
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x✝ y : E
hs : IsCompact s
hδ : 0 ≤ δ
x : E
⊢ x ∈ s * closedBall 1 δ ↔ x ∈ ⋃ x ∈ s, closedBall x δ

Next tactic:
simp only [mem_mul, dist_eq_norm_div, exists_prop, mem_iUnion, mem_closedBall, exists_and_left,
    mem_closedBall_one_iff, ← eq_div_iff_mul_eq'', div_one, exists_eq_right]
@[to_additive]
theorem IsCompact.div_closedBall_one (hs : IsCompact s) (hδ : 0 ≤ δ) :
    s / closedBall 1 δ = cthickening δ s := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsCompact s
hδ : 0 ≤ δ
⊢ s / closedBall 1 δ = cthickening δ s

Next tactic:
simp [div_eq_mul_inv, hs.mul_closedBall_one hδ]
@[to_additive]
theorem IsCompact.closedBall_one_mul (hs : IsCompact s) (hδ : 0 ≤ δ) :
    closedBall 1 δ * s = cthickening δ s := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsCompact s
hδ : 0 ≤ δ
⊢ closedBall 1 δ * s = cthickening δ s

Next tactic:
rw [mul_comm, hs.mul_closedBall_one hδ]
@[to_additive]
theorem IsCompact.closedBall_one_div (hs : IsCompact s) (hδ : 0 ≤ δ) :
    closedBall 1 δ / s = cthickening δ s⁻¹ := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x y : E
hs : IsCompact s
hδ : 0 ≤ δ
⊢ closedBall 1 δ / s = cthickening δ s⁻¹

Next tactic:
simp [div_eq_mul_inv, mul_comm, hs.inv.mul_closedBall_one hδ]
@[to_additive]
theorem IsCompact.mul_closedBall (hs : IsCompact s) (hδ : 0 ≤ δ) (x : E) :
    s * closedBall x δ = x • cthickening δ s := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x✝ y : E
hs : IsCompact s
hδ : 0 ≤ δ
x : E
⊢ s * closedBall x δ = x • cthickening δ s

Next tactic:
rw [← smul_closedBall_one, mul_smul_comm, hs.mul_closedBall_one hδ]
@[to_additive]
theorem IsCompact.div_closedBall (hs : IsCompact s) (hδ : 0 ≤ δ) (x : E) :
    s / closedBall x δ = x⁻¹ • cthickening δ s := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x✝ y : E
hs : IsCompact s
hδ : 0 ≤ δ
x : E
⊢ s / closedBall x δ = x⁻¹ • cthickening δ s

Next tactic:
simp [div_eq_mul_inv, mul_comm, hs.mul_closedBall hδ]
@[to_additive]
theorem IsCompact.closedBall_mul (hs : IsCompact s) (hδ : 0 ≤ δ) (x : E) :
    closedBall x δ * s = x • cthickening δ s := by 

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x✝ y : E
hs : IsCompact s
hδ : 0 ≤ δ
x : E
⊢ closedBall x δ * s = x • cthickening δ s

Next tactic:
rw [mul_comm, hs.mul_closedBall hδ]
@[to_additive]
theorem IsCompact.closedBall_div (hs : IsCompact s) (hδ : 0 ≤ δ) (x : E) :
    closedBall x δ * s = x • cthickening δ s := by
  

Proof state:
E : Type u_1
inst✝ : SeminormedCommGroup E
ε δ : ℝ
s t : Set E
x✝ y : E
hs : IsCompact s
hδ : 0 ≤ δ
x : E
⊢ closedBall x δ * s = x • cthickening δ s

Next tactic:
simp [div_eq_mul_inv, hs.closedBall_mul hδ]
/-- Given a section of a functor F into `Type*`,
  construct a cone over F with `PUnit` as the cone point. -/
def coneOfSection {s} (hs : s ∈ F.sections) : Cone F where
  pt := PUnit
  π :=
  { app := fun j _ ↦ s j,
    naturality := fun i j f ↦ by 

Proof state:
J : Type v
inst✝ : Category.{?u.44, v} J
F : J ⥤ Type u
s : (j : J) → F.obj j
hs : s ∈ Functor.sections F
i j : J
f : i ⟶ j
⊢ ((Functor.const J).obj PUnit.{u + 1}).map f ≫ (fun j x => s j) j = (fun j x => s j) i ≫ F.map f

Next tactic:
ext
/-- Given a section of a functor F into `Type*`,
  construct a cone over F with `PUnit` as the cone point. -/
def coneOfSection {s} (hs : s ∈ F.sections) : Cone F where
  pt := PUnit
  π :=
  { app := fun j _ ↦ s j,
    naturality := fun i j f ↦ by ext; 

Proof state:
case h
J : Type v
inst✝ : Category.{?u.44, v} J
F : J ⥤ Type u
s : (j : J) → F.obj j
hs : s ∈ Functor.sections F
i j : J
f : i ⟶ j
a✝ : ((Functor.const J).obj PUnit.{u + 1}).obj i
⊢ (((Functor.const J).obj PUnit.{u + 1}).map f ≫ (fun j x => s j) j) a✝ = ((fun j x => s j) i ≫ F.map f) a✝

Next tactic:
exact (hs f).symm
theorem isLimit_iff (c : Cone F) :
    Nonempty (IsLimit c) ↔ ∀ s ∈ F.sections, ∃! x : c.pt, ∀ i, c.π.app i x = s i := by
  

Proof state:
J : Type v
inst✝ : Category.{u_1, v} J
F : J ⥤ Type u
c : Cone F
⊢ Nonempty (IsLimit c) ↔ ∀ s ∈ Functor.sections F, ∃! x, ∀ (i : J), c.π.app i x = s i

Next tactic:
refine ⟨fun ⟨t⟩ s hs ↦ ?_, fun h ↦ ⟨?_⟩⟩
theorem isLimit_iff (c : Cone F) :
    Nonempty (IsLimit c) ↔ ∀ s ∈ F.sections, ∃! x : c.pt, ∀ i, c.π.app i x = s i := by
  refine ⟨fun ⟨t⟩ s hs ↦ ?_, fun h ↦ ⟨?_⟩⟩
  · 

Proof state:
case refine_1
J : Type v
inst✝ : Category.{u_1, v} J
F : J ⥤ Type u
c : Cone F
x✝ : Nonempty (IsLimit c)
s : (j : J) → F.obj j
hs : s ∈ Functor.sections F
t : IsLimit c
⊢ ∃! x, ∀ (i : J), c.π.app i x = s i

Next tactic:
let cs := coneOfSection hs
theorem isLimit_iff (c : Cone F) :
    Nonempty (IsLimit c) ↔ ∀ s ∈ F.sections, ∃! x : c.pt, ∀ i, c.π.app i x = s i := by
  refine ⟨fun ⟨t⟩ s hs ↦ ?_, fun h ↦ ⟨?_⟩⟩
  · let cs := coneOfSection hs
    

Proof state:
case refine_1
J : Type v
inst✝ : Category.{u_1, v} J
F : J ⥤ Type u
c : Cone F
x✝ : Nonempty (IsLimit c)
s : (j : J) → F.obj j
hs : s ∈ Functor.sections F
t : IsLimit c
cs : Cone F := coneOfSection (_ : ∀ {j j' : J} (f : j ⟶ j'), F.map f (s j) = s j')
⊢ ∃! x, ∀ (i : J), c.π.app i x = s i

Next tactic:
exact ⟨t.lift cs ⟨⟩, fun j ↦ congr_fun (t.fac cs j) ⟨⟩,
      fun x hx ↦ congr_fun (t.uniq cs (fun _ ↦ x) fun j ↦ funext fun _ ↦ hx j) ⟨⟩⟩
theorem isLimit_iff (c : Cone F) :
    Nonempty (IsLimit c) ↔ ∀ s ∈ F.sections, ∃! x : c.pt, ∀ i, c.π.app i x = s i := by
  refine ⟨fun ⟨t⟩ s hs ↦ ?_, fun h ↦ ⟨?_⟩⟩
  · let cs := coneOfSection hs
    exact ⟨t.lift cs ⟨⟩, fun j ↦ congr_fun (t.fac cs j) ⟨⟩,
      fun x hx ↦ congr_fun (t.uniq cs (fun _ ↦ x) fun j ↦ funext fun _ ↦ hx j) ⟨⟩⟩
  · 

Proof state:
case refine_2
J : Type v
inst✝ : Category.{u_1, v} J
F : J ⥤ Type u
c : Cone F
h : ∀ s ∈ Functor.sections F, ∃! x, ∀ (i : J), c.π.app i x = s i
⊢ IsLimit c

Next tactic:
choose x hx using fun c y ↦ h _ (sectionOfCone c y).2
theorem isLimit_iff (c : Cone F) :
    Nonempty (IsLimit c) ↔ ∀ s ∈ F.sections, ∃! x : c.pt, ∀ i, c.π.app i x = s i := by
  refine ⟨fun ⟨t⟩ s hs ↦ ?_, fun h ↦ ⟨?_⟩⟩
  · let cs := coneOfSection hs
    exact ⟨t.lift cs ⟨⟩, fun j ↦ congr_fun (t.fac cs j) ⟨⟩,
      fun x hx ↦ congr_fun (t.uniq cs (fun _ ↦ x) fun j ↦ funext fun _ ↦ hx j) ⟨⟩⟩
  · choose x hx using fun c y ↦ h _ (sectionOfCone c y).2
    

Proof state:
case refine_2
J : Type v
inst✝ : Category.{u_1, v} J
F : J ⥤ Type u
c : Cone F
h : ∀ s ∈ Functor.sections F, ∃! x, ∀ (i : J), c.π.app i x = s i
x : (c_1 : Cone F) → c_1.pt → c.pt
hx :
  ∀ (c_1 : Cone F) (y : c_1.pt),
    (fun x => ∀ (i : J), c.π.app i x = ↑(sectionOfCone c_1 y) i) (x c_1 y) ∧
      ∀ (y_1 : c.pt), (fun x => ∀ (i : J), c.π.app i x = ↑(sectionOfCone c_1 y) i) y_1 → y_1 = x c_1 y
⊢ IsLimit c

Next tactic:
exact ⟨x, fun c j ↦ funext fun y ↦ (hx c y).1 j,
      fun c f hf ↦ funext fun y ↦ (hx c y).2 (f y) (fun j ↦ congr_fun (hf j) y)⟩
@[simp]
theorem isLimitEquivSections_symm_apply {c : Cone F} (t : IsLimit c)
    (x : F.sections) (j : J) :
    c.π.app j ((isLimitEquivSections t).symm x) = (x : ∀ j, F.obj j) j := by
  

Proof state:
J : Type v
inst✝ : Category.{u_1, v} J
F : J ⥤ Type u
c : Cone F
t : IsLimit c
x : ↑(Functor.sections F)
j : J
⊢ c.π.app j ((isLimitEquivSections t).symm x) = ↑x j

Next tactic:
conv_rhs => rw [← (isLimitEquivSections t).right_inv x]