[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
s : Set E
⊢ EMetric.diam (c • s) = ‖c‖₊ • EMetric.diam s
[PROOFSTEP]
refine' le_antisymm (ediam_smul_le c s) _
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
s : Set E
⊢ ‖c‖₊ • EMetric.diam s ≤ EMetric.diam (c • s)
[PROOFSTEP]
obtain rfl | hc := eq_or_ne c 0
[GOAL]
case inl
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
s : Set E
⊢ ‖0‖₊ • EMetric.diam s ≤ EMetric.diam (0 • s)
[PROOFSTEP]
obtain rfl | hs := s.eq_empty_or_nonempty
[GOAL]
case inl.inl
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
⊢ ‖0‖₊ • EMetric.diam ∅ ≤ EMetric.diam (0 • ∅)
[PROOFSTEP]
simp
[GOAL]
case inl.inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
s : Set E
hs : Set.Nonempty s
⊢ ‖0‖₊ • EMetric.diam s ≤ EMetric.diam (0 • s)
[PROOFSTEP]
simp [zero_smul_set hs, ← Set.singleton_zero]
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
s : Set E
hc : c ≠ 0
⊢ ‖c‖₊ • EMetric.diam s ≤ EMetric.diam (c • s)
[PROOFSTEP]
have := (lipschitzWith_smul c⁻¹).ediam_image_le (c • s)
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
s : Set E
hc : c ≠ 0
this : EMetric.diam ((fun x x_1 => x • x_1) c⁻¹ '' (c • s)) ≤ ↑‖c⁻¹‖₊ * EMetric.diam (c • s)
⊢ ‖c‖₊ • EMetric.diam s ≤ EMetric.diam (c • s)
[PROOFSTEP]
rwa [← smul_eq_mul, ← ENNReal.smul_def, Set.image_smul, inv_smul_smul₀ hc s, nnnorm_inv,
  ENNReal.le_inv_smul_iff (nnnorm_ne_zero_iff.mpr hc)] at this
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
x : Set E
⊢ diam (c • x) = ‖c‖ * diam x
[PROOFSTEP]
simp_rw [diam, ediam_smul₀, ENNReal.toReal_smul, NNReal.smul_def, coe_nnnorm, smul_eq_mul]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
⊢ EMetric.infEdist (c • x) (c • s) = ‖c‖₊ • EMetric.infEdist x s
[PROOFSTEP]
simp_rw [EMetric.infEdist]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
⊢ ⨅ (y : E) (_ : y ∈ c • s), edist (c • x) y = ‖c‖₊ • ⨅ (y : E) (_ : y ∈ s), edist x y
[PROOFSTEP]
have : Function.Surjective ((c • ·) : E → E) := Function.RightInverse.surjective (smul_inv_smul₀ hc)
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
this : Function.Surjective fun x => c • x
⊢ ⨅ (y : E) (_ : y ∈ c • s), edist (c • x) y = ‖c‖₊ • ⨅ (y : E) (_ : y ∈ s), edist x y
[PROOFSTEP]
trans ⨅ (y) (_ : y ∈ s), ‖c‖₊ • edist x y
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
this : Function.Surjective fun x => c • x
⊢ ⨅ (y : E) (_ : y ∈ c • s), edist (c • x) y = ⨅ (y : E) (_ : y ∈ s), ‖c‖₊ • edist x y
[PROOFSTEP]
refine' (this.iInf_congr _ fun y => _).symm
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
this : Function.Surjective fun x => c • x
y : E
⊢ ⨅ (_ : c • y ∈ c • s), edist (c • x) (c • y) = ⨅ (_ : y ∈ s), ‖c‖₊ • edist x y
[PROOFSTEP]
simp_rw [smul_mem_smul_set_iff₀ hc, edist_smul₀]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
this : Function.Surjective fun x => c • x
⊢ ⨅ (y : E) (_ : y ∈ s), ‖c‖₊ • edist x y = ‖c‖₊ • ⨅ (y : E) (_ : y ∈ s), edist x y
[PROOFSTEP]
have : (‖c‖₊ : ENNReal) ≠ 0 := by simp [hc]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
this : Function.Surjective fun x => c • x
⊢ ↑‖c‖₊ ≠ 0
[PROOFSTEP]
simp [hc]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
this✝ : Function.Surjective fun x => c • x
this : ↑‖c‖₊ ≠ 0
⊢ ⨅ (y : E) (_ : y ∈ s), ‖c‖₊ • edist x y = ‖c‖₊ • ⨅ (y : E) (_ : y ∈ s), edist x y
[PROOFSTEP]
simp_rw [ENNReal.smul_def, smul_eq_mul, ENNReal.mul_iInf_of_ne this ENNReal.coe_ne_top]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedDivisionRing 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : Module 𝕜 E
inst✝ : BoundedSMul 𝕜 E
c : 𝕜
hc : c ≠ 0
s : Set E
x : E
⊢ infDist (c • x) (c • s) = ‖c‖ * infDist x s
[PROOFSTEP]
simp_rw [Metric.infDist, infEdist_smul₀ hc s, ENNReal.toReal_smul, NNReal.smul_def, coe_nnnorm, smul_eq_mul]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
⊢ c • ball x r = ball (c • x) (‖c‖ * r)
[PROOFSTEP]
ext y
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
⊢ y ∈ c • ball x r ↔ y ∈ ball (c • x) (‖c‖ * r)
[PROOFSTEP]
rw [mem_smul_set_iff_inv_smul_mem₀ hc]
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
⊢ c⁻¹ • y ∈ ball x r ↔ y ∈ ball (c • x) (‖c‖ * r)
[PROOFSTEP]
conv_lhs => rw [← inv_smul_smul₀ hc x]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
| c⁻¹ • y ∈ ball x r
[PROOFSTEP]
rw [← inv_smul_smul₀ hc x]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
| c⁻¹ • y ∈ ball x r
[PROOFSTEP]
rw [← inv_smul_smul₀ hc x]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
| c⁻¹ • y ∈ ball x r
[PROOFSTEP]
rw [← inv_smul_smul₀ hc x]
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
⊢ c⁻¹ • y ∈ ball (c⁻¹ • c • x) r ↔ y ∈ ball (c • x) (‖c‖ * r)
[PROOFSTEP]
simp [← div_eq_inv_mul, div_lt_iff (norm_pos_iff.2 hc), mul_comm _ r, dist_smul₀]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
⊢ c • ball 0 1 = ball 0 ‖c‖
[PROOFSTEP]
rw [_root_.smul_ball hc, smul_zero, mul_one]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
⊢ c • sphere x r = sphere (c • x) (‖c‖ * r)
[PROOFSTEP]
ext y
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
⊢ y ∈ c • sphere x r ↔ y ∈ sphere (c • x) (‖c‖ * r)
[PROOFSTEP]
rw [mem_smul_set_iff_inv_smul_mem₀ hc]
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
⊢ c⁻¹ • y ∈ sphere x r ↔ y ∈ sphere (c • x) (‖c‖ * r)
[PROOFSTEP]
conv_lhs => rw [← inv_smul_smul₀ hc x]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
| c⁻¹ • y ∈ sphere x r
[PROOFSTEP]
rw [← inv_smul_smul₀ hc x]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
| c⁻¹ • y ∈ sphere x r
[PROOFSTEP]
rw [← inv_smul_smul₀ hc x]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
| c⁻¹ • y ∈ sphere x r
[PROOFSTEP]
rw [← inv_smul_smul₀ hc x]
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
y : E
⊢ c⁻¹ • y ∈ sphere (c⁻¹ • c • x) r ↔ y ∈ sphere (c • x) (‖c‖ * r)
[PROOFSTEP]
simp only [mem_sphere, dist_smul₀, norm_inv, ← div_eq_inv_mul, div_eq_iff (norm_pos_iff.2 hc).ne', mul_comm r]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
hc : c ≠ 0
x : E
r : ℝ
⊢ c • closedBall x r = closedBall (c • x) (‖c‖ * r)
[PROOFSTEP]
simp only [← ball_union_sphere, Set.smul_set_union, _root_.smul_ball hc, smul_sphere' hc]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
⊢ ∀ᶠ (r : 𝕜) in 𝓝 0, {x} + r • s ⊆ u
[PROOFSTEP]
obtain ⟨ε, εpos, hε⟩ : ∃ ε : ℝ, 0 < ε ∧ closedBall x ε ⊆ u := nhds_basis_closedBall.mem_iff.1 hu
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
⊢ ∀ᶠ (r : 𝕜) in 𝓝 0, {x} + r • s ⊆ u
[PROOFSTEP]
obtain ⟨R, Rpos, hR⟩ : ∃ R : ℝ, 0 < R ∧ s ⊆ closedBall 0 R := hs.subset_ball_lt 0 0
[GOAL]
case intro.intro.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
⊢ ∀ᶠ (r : 𝕜) in 𝓝 0, {x} + r • s ⊆ u
[PROOFSTEP]
have : Metric.closedBall (0 : 𝕜) (ε / R) ∈ 𝓝 (0 : 𝕜) := closedBall_mem_nhds _ (div_pos εpos Rpos)
[GOAL]
case intro.intro.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
⊢ ∀ᶠ (r : 𝕜) in 𝓝 0, {x} + r • s ⊆ u
[PROOFSTEP]
filter_upwards [this] with r hr
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
⊢ {x} + r • s ⊆ u
[PROOFSTEP]
simp only [image_add_left, singleton_add]
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
⊢ (fun x_1 => -x + x_1) ⁻¹' (r • s) ⊆ u
[PROOFSTEP]
intro y hy
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
y : E
hy : y ∈ (fun x_1 => -x + x_1) ⁻¹' (r • s)
⊢ y ∈ u
[PROOFSTEP]
obtain ⟨z, zs, hz⟩ : ∃ z : E, z ∈ s ∧ r • z = -x + y := by simpa [mem_smul_set] using hy
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
y : E
hy : y ∈ (fun x_1 => -x + x_1) ⁻¹' (r • s)
⊢ ∃ z, z ∈ s ∧ r • z = -x + y
[PROOFSTEP]
simpa [mem_smul_set] using hy
[GOAL]
case h.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
y : E
hy : y ∈ (fun x_1 => -x + x_1) ⁻¹' (r • s)
z : E
zs : z ∈ s
hz : r • z = -x + y
⊢ y ∈ u
[PROOFSTEP]
have I : ‖r • z‖ ≤ ε :=
  calc
    ‖r • z‖ = ‖r‖ * ‖z‖ := norm_smul _ _
    _ ≤ ε / R * R :=
      (mul_le_mul (mem_closedBall_zero_iff.1 hr) (mem_closedBall_zero_iff.1 (hR zs)) (norm_nonneg _)
        (div_pos εpos Rpos).le)
    _ = ε := by field_simp [Rpos.ne']
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
y : E
hy : y ∈ (fun x_1 => -x + x_1) ⁻¹' (r • s)
z : E
zs : z ∈ s
hz : r • z = -x + y
⊢ ε / R * R = ε
[PROOFSTEP]
field_simp [Rpos.ne']
[GOAL]
case h.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
y : E
hy : y ∈ (fun x_1 => -x + x_1) ⁻¹' (r • s)
z : E
zs : z ∈ s
hz : r • z = -x + y
I : ‖r • z‖ ≤ ε
⊢ y ∈ u
[PROOFSTEP]
have : y = x + r • z := by simp only [hz, add_neg_cancel_left]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
y : E
hy : y ∈ (fun x_1 => -x + x_1) ⁻¹' (r • s)
z : E
zs : z ∈ s
hz : r • z = -x + y
I : ‖r • z‖ ≤ ε
⊢ y = x + r • z
[PROOFSTEP]
simp only [hz, add_neg_cancel_left]
[GOAL]
case h.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this✝ : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
y : E
hy : y ∈ (fun x_1 => -x + x_1) ⁻¹' (r • s)
z : E
zs : z ∈ s
hz : r • z = -x + y
I : ‖r • z‖ ≤ ε
this : y = x + r • z
⊢ y ∈ u
[PROOFSTEP]
apply hε
[GOAL]
case h.intro.intro.a
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : SeminormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
s : Set E
hs : Metric.Bounded s
u : Set E
hu : u ∈ 𝓝 x
ε : ℝ
εpos : 0 < ε
hε : closedBall x ε ⊆ u
R : ℝ
Rpos : 0 < R
hR : s ⊆ closedBall 0 R
this✝ : closedBall 0 (ε / R) ∈ 𝓝 0
r : 𝕜
hr : r ∈ closedBall 0 (ε / R)
y : E
hy : y ∈ (fun x_1 => -x + x_1) ⁻¹' (r • s)
z : E
zs : z ∈ s
hz : r • z = -x + y
I : ‖r • z‖ ≤ ε
this : y = x + r • z
⊢ y ∈ closedBall x ε
[PROOFSTEP]
simpa only [this, dist_eq_norm, add_sub_cancel', mem_closedBall] using I
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε r : ℝ
hr : 0 < r
⊢ r • ball 0 1 = ball 0 r
[PROOFSTEP]
rw [smul_unitBall hr.ne', Real.norm_of_nonneg hr.le]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
x z : E
a b : ℝ
ha : 0 ≤ a
hb : 0 ≤ b
hab : a + b = 1
⊢ ∃ y, dist x y = b * dist x z ∧ dist y z = a * dist x z
[PROOFSTEP]
use a • x + b • z
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
x z : E
a b : ℝ
ha : 0 ≤ a
hb : 0 ≤ b
hab : a + b = 1
⊢ dist x (a • x + b • z) = b * dist x z ∧ dist (a • x + b • z) z = a * dist x z
[PROOFSTEP]
nth_rw 1 [← one_smul ℝ x]
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
x z : E
a b : ℝ
ha : 0 ≤ a
hb : 0 ≤ b
hab : a + b = 1
⊢ dist (1 • x) (a • x + b • z) = b * dist x z ∧ dist (a • x + b • z) z = a * dist x z
[PROOFSTEP]
nth_rw 4 [← one_smul ℝ z]
[GOAL]
case h
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
x z : E
a b : ℝ
ha : 0 ≤ a
hb : 0 ≤ b
hab : a + b = 1
⊢ dist (1 • x) (a • x + b • z) = b * dist x z ∧ dist (a • x + b • z) (1 • z) = a * dist x z
[PROOFSTEP]
simp [dist_eq_norm, ← hab, add_smul, ← smul_sub, norm_smul_of_nonneg, ha, hb]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : dist x z ≤ ε + δ
⊢ ∃ y, dist x y ≤ δ ∧ dist y z ≤ ε
[PROOFSTEP]
obtain rfl | hε' := hε.eq_or_lt
[GOAL]
case inl
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ 0
h : dist x z ≤ 0 + δ
⊢ ∃ y, dist x y ≤ δ ∧ dist y z ≤ 0
[PROOFSTEP]
exact ⟨z, by rwa [zero_add] at h , (dist_self _).le⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ 0
h : dist x z ≤ 0 + δ
⊢ dist x z ≤ δ
[PROOFSTEP]
rwa [zero_add] at h
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : dist x z ≤ ε + δ
hε' : 0 < ε
⊢ ∃ y, dist x y ≤ δ ∧ dist y z ≤ ε
[PROOFSTEP]
have hεδ := add_pos_of_pos_of_nonneg hε' hδ
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : dist x z ≤ ε + δ
hε' : 0 < ε
hεδ : 0 < ε + δ
⊢ ∃ y, dist x y ≤ δ ∧ dist y z ≤ ε
[PROOFSTEP]
refine'
  (exists_dist_eq x z (div_nonneg hε <| add_nonneg hε hδ) (div_nonneg hδ <| add_nonneg hε hδ) <| by
        rw [← add_div, div_self hεδ.ne']).imp
    fun y hy => _
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : dist x z ≤ ε + δ
hε' : 0 < ε
hεδ : 0 < ε + δ
⊢ ε / (ε + δ) + δ / (ε + δ) = 1
[PROOFSTEP]
rw [← add_div, div_self hεδ.ne']
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : dist x z ≤ ε + δ
hε' : 0 < ε
hεδ : 0 < ε + δ
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x y ≤ δ ∧ dist y z ≤ ε
[PROOFSTEP]
rw [hy.1, hy.2, div_mul_comm, div_mul_comm ε]
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : dist x z ≤ ε + δ
hε' : 0 < ε
hεδ : 0 < ε + δ
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x z / (ε + δ) * δ ≤ δ ∧ dist x z / (ε + δ) * ε ≤ ε
[PROOFSTEP]
rw [← div_le_one hεδ] at h
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : dist x z / (ε + δ) ≤ 1
hε' : 0 < ε
hεδ : 0 < ε + δ
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x z / (ε + δ) * δ ≤ δ ∧ dist x z / (ε + δ) * ε ≤ ε
[PROOFSTEP]
exact ⟨mul_le_of_le_one_left hδ h, mul_le_of_le_one_left hε h⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 < ε
h : dist x z < ε + δ
⊢ ∃ y, dist x y ≤ δ ∧ dist y z < ε
[PROOFSTEP]
refine'
  (exists_dist_eq x z (div_nonneg hε.le <| add_nonneg hε.le hδ) (div_nonneg hδ <| add_nonneg hε.le hδ) <| by
        rw [← add_div, div_self (add_pos_of_pos_of_nonneg hε hδ).ne']).imp
    fun y hy => _
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 < ε
h : dist x z < ε + δ
⊢ ε / (ε + δ) + δ / (ε + δ) = 1
[PROOFSTEP]
rw [← add_div, div_self (add_pos_of_pos_of_nonneg hε hδ).ne']
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 < ε
h : dist x z < ε + δ
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x y ≤ δ ∧ dist y z < ε
[PROOFSTEP]
rw [hy.1, hy.2, div_mul_comm, div_mul_comm ε]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 < ε
h : dist x z < ε + δ
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x z / (ε + δ) * δ ≤ δ ∧ dist x z / (ε + δ) * ε < ε
[PROOFSTEP]
rw [← div_lt_one (add_pos_of_pos_of_nonneg hε hδ)] at h
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 < ε
h : dist x z / (ε + δ) < 1
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x z / (ε + δ) * δ ≤ δ ∧ dist x z / (ε + δ) * ε < ε
[PROOFSTEP]
exact ⟨mul_le_of_le_one_left hδ h.le, mul_lt_of_lt_one_left hε h⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
h : dist x z < ε + δ
⊢ ∃ y, dist x y < δ ∧ dist y z ≤ ε
[PROOFSTEP]
obtain ⟨y, yz, xy⟩ := exists_dist_le_lt hε hδ (show dist z x < δ + ε by simpa only [dist_comm, add_comm] using h)
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
h : dist x z < ε + δ
⊢ dist z x < δ + ε
[PROOFSTEP]
simpa only [dist_comm, add_comm] using h
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
h : dist x z < ε + δ
y : E
yz : dist z y ≤ ε
xy : dist y x < δ
⊢ ∃ y, dist x y < δ ∧ dist y z ≤ ε
[PROOFSTEP]
exact ⟨y, by simp [dist_comm x y, dist_comm y z, *]⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
h : dist x z < ε + δ
y : E
yz : dist z y ≤ ε
xy : dist y x < δ
⊢ dist x y < δ ∧ dist y z ≤ ε
[PROOFSTEP]
simp [dist_comm x y, dist_comm y z, *]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : dist x z < ε + δ
⊢ ∃ y, dist x y < δ ∧ dist y z < ε
[PROOFSTEP]
refine'
  (exists_dist_eq x z (div_nonneg hε.le <| add_nonneg hε.le hδ.le) (div_nonneg hδ.le <| add_nonneg hε.le hδ.le) <| by
        rw [← add_div, div_self (add_pos hε hδ).ne']).imp
    fun y hy => _
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : dist x z < ε + δ
⊢ ε / (ε + δ) + δ / (ε + δ) = 1
[PROOFSTEP]
rw [← add_div, div_self (add_pos hε hδ).ne']
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : dist x z < ε + δ
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x y < δ ∧ dist y z < ε
[PROOFSTEP]
rw [hy.1, hy.2, div_mul_comm, div_mul_comm ε]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : dist x z < ε + δ
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x z / (ε + δ) * δ < δ ∧ dist x z / (ε + δ) * ε < ε
[PROOFSTEP]
rw [← div_lt_one (add_pos hε hδ)] at h
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y✝ z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : dist x z / (ε + δ) < 1
y : E
hy : dist x y = δ / (ε + δ) * dist x z ∧ dist y z = ε / (ε + δ) * dist x z
⊢ dist x z / (ε + δ) * δ < δ ∧ dist x z / (ε + δ) * ε < ε
[PROOFSTEP]
exact ⟨mul_lt_of_lt_one_left hδ h, mul_lt_of_lt_one_left hε h⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
⊢ Disjoint (ball x δ) (ball y ε) ↔ δ + ε ≤ dist x y
[PROOFSTEP]
refine' ⟨fun h => le_of_not_lt fun hxy => _, ball_disjoint_ball⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : Disjoint (ball x δ) (ball y ε)
hxy : dist x y < δ + ε
⊢ False
[PROOFSTEP]
rw [add_comm] at hxy
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : Disjoint (ball x δ) (ball y ε)
hxy : dist x y < ε + δ
⊢ False
[PROOFSTEP]
obtain ⟨z, hxz, hzy⟩ := exists_dist_lt_lt hδ hε hxy
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z✝ : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : Disjoint (ball x δ) (ball y ε)
hxy : dist x y < ε + δ
z : E
hxz : dist x z < δ
hzy : dist z y < ε
⊢ False
[PROOFSTEP]
rw [dist_comm] at hxz
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z✝ : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 < ε
h : Disjoint (ball x δ) (ball y ε)
hxy : dist x y < ε + δ
z : E
hxz : dist z x < δ
hzy : dist z y < ε
⊢ False
[PROOFSTEP]
exact h.le_bot ⟨hxz, hzy⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
⊢ Disjoint (ball x δ) (closedBall y ε) ↔ δ + ε ≤ dist x y
[PROOFSTEP]
refine' ⟨fun h => le_of_not_lt fun hxy => _, ball_disjoint_closedBall⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
h : Disjoint (ball x δ) (closedBall y ε)
hxy : dist x y < δ + ε
⊢ False
[PROOFSTEP]
rw [add_comm] at hxy
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
h : Disjoint (ball x δ) (closedBall y ε)
hxy : dist x y < ε + δ
⊢ False
[PROOFSTEP]
obtain ⟨z, hxz, hzy⟩ := exists_dist_lt_le hδ hε hxy
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z✝ : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
h : Disjoint (ball x δ) (closedBall y ε)
hxy : dist x y < ε + δ
z : E
hxz : dist x z < δ
hzy : dist z y ≤ ε
⊢ False
[PROOFSTEP]
rw [dist_comm] at hxz
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z✝ : E
δ ε : ℝ
hδ : 0 < δ
hε : 0 ≤ ε
h : Disjoint (ball x δ) (closedBall y ε)
hxy : dist x y < ε + δ
z : E
hxz : dist z x < δ
hzy : dist z y ≤ ε
⊢ False
[PROOFSTEP]
exact h.le_bot ⟨hxz, hzy⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 < ε
⊢ Disjoint (closedBall x δ) (ball y ε) ↔ δ + ε ≤ dist x y
[PROOFSTEP]
rw [disjoint_comm, disjoint_ball_closedBall_iff hε hδ, add_comm, dist_comm]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
⊢ Disjoint (closedBall x δ) (closedBall y ε) ↔ δ + ε < dist x y
[PROOFSTEP]
refine' ⟨fun h => lt_of_not_ge fun hxy => _, closedBall_disjoint_closedBall⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : Disjoint (closedBall x δ) (closedBall y ε)
hxy : δ + ε ≥ dist x y
⊢ False
[PROOFSTEP]
rw [add_comm] at hxy
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : Disjoint (closedBall x δ) (closedBall y ε)
hxy : ε + δ ≥ dist x y
⊢ False
[PROOFSTEP]
obtain ⟨z, hxz, hzy⟩ := exists_dist_le_le hδ hε hxy
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z✝ : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : Disjoint (closedBall x δ) (closedBall y ε)
hxy : ε + δ ≥ dist x y
z : E
hxz : dist x z ≤ δ
hzy : dist z y ≤ ε
⊢ False
[PROOFSTEP]
rw [dist_comm] at hxz
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z✝ : E
δ ε : ℝ
hδ : 0 ≤ δ
hε : 0 ≤ ε
h : Disjoint (closedBall x δ) (closedBall y ε)
hxy : ε + δ ≥ dist x y
z : E
hxz : dist z x ≤ δ
hzy : dist z y ≤ ε
⊢ False
[PROOFSTEP]
exact h.le_bot ⟨hxz, hzy⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
⊢ infEdist x (thickening δ s) = infEdist x s - ENNReal.ofReal δ
[PROOFSTEP]
obtain hs | hs := lt_or_le (infEdist x s) (ENNReal.ofReal δ)
[GOAL]
case inl
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : infEdist x s < ENNReal.ofReal δ
⊢ infEdist x (thickening δ s) = infEdist x s - ENNReal.ofReal δ
[PROOFSTEP]
rw [infEdist_zero_of_mem, tsub_eq_zero_of_le hs.le]
[GOAL]
case inl
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : infEdist x s < ENNReal.ofReal δ
⊢ x ∈ thickening δ s
[PROOFSTEP]
exact hs
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
⊢ infEdist x (thickening δ s) = infEdist x s - ENNReal.ofReal δ
[PROOFSTEP]
refine' (tsub_le_iff_right.2 infEdist_le_infEdist_thickening_add).antisymm' _
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
⊢ infEdist x (thickening δ s) ≤ infEdist x s - ENNReal.ofReal δ
[PROOFSTEP]
refine' le_sub_of_add_le_right ofReal_ne_top _
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
⊢ infEdist x (thickening δ s) + ENNReal.ofReal δ ≤ infEdist x s
[PROOFSTEP]
refine' le_infEdist.2 fun z hz => le_of_forall_lt' fun r h => _
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : ℝ≥0∞
h : edist x z < r
⊢ infEdist x (thickening δ s) + ENNReal.ofReal δ < r
[PROOFSTEP]
cases' r with r
[GOAL]
case inr.none
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
h : edist x z < none
⊢ infEdist x (thickening δ s) + ENNReal.ofReal δ < none
[PROOFSTEP]
exact add_lt_top.2 ⟨lt_top_iff_ne_top.2 <| infEdist_ne_top ⟨z, self_subset_thickening hδ _ hz⟩, ofReal_lt_top⟩
[GOAL]
case inr.some
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : edist x z < Option.some r
⊢ infEdist x (thickening δ s) + ENNReal.ofReal δ < Option.some r
[PROOFSTEP]
have hr : 0 < ↑r - δ := by
  refine' sub_pos_of_lt _
  have := hs.trans_lt ((infEdist_le_edist_of_mem hz).trans_lt h)
  rw [ofReal_eq_coe_nnreal hδ.le, some_eq_coe] at this
  exact_mod_cast this
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : edist x z < Option.some r
⊢ 0 < ↑r - δ
[PROOFSTEP]
refine' sub_pos_of_lt _
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : edist x z < Option.some r
⊢ δ < ↑r
[PROOFSTEP]
have := hs.trans_lt ((infEdist_le_edist_of_mem hz).trans_lt h)
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : edist x z < Option.some r
this : ENNReal.ofReal δ < Option.some r
⊢ δ < ↑r
[PROOFSTEP]
rw [ofReal_eq_coe_nnreal hδ.le, some_eq_coe] at this
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : edist x z < Option.some r
this : ↑{ val := δ, property := (_ : 0 ≤ δ) } < ↑r
⊢ δ < ↑r
[PROOFSTEP]
exact_mod_cast this
[GOAL]
case inr.some
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : edist x z < Option.some r
hr : 0 < ↑r - δ
⊢ infEdist x (thickening δ s) + ENNReal.ofReal δ < Option.some r
[PROOFSTEP]
rw [some_eq_coe, edist_lt_coe, ← dist_lt_coe, ← add_sub_cancel'_right δ ↑r] at h
[GOAL]
case inr.some
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : dist x z < δ + (↑r - δ)
hr : 0 < ↑r - δ
⊢ infEdist x (thickening δ s) + ENNReal.ofReal δ < Option.some r
[PROOFSTEP]
obtain ⟨y, hxy, hyz⟩ := exists_dist_lt_lt hr hδ h
[GOAL]
case inr.some.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y✝ z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : dist x z < δ + (↑r - δ)
hr : 0 < ↑r - δ
y : E
hxy : dist x y < ↑r - δ
hyz : dist y z < δ
⊢ infEdist x (thickening δ s) + ENNReal.ofReal δ < Option.some r
[PROOFSTEP]
refine'
  (ENNReal.add_lt_add_right ofReal_ne_top <|
        infEdist_lt_iff.2 ⟨_, mem_thickening_iff.2 ⟨_, hz, hyz⟩, edist_lt_ofReal.2 hxy⟩).trans_le
    _
[GOAL]
case inr.some.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y✝ z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : dist x z < δ + (↑r - δ)
hr : 0 < ↑r - δ
y : E
hxy : dist x y < ↑r - δ
hyz : dist y z < δ
⊢ ENNReal.ofReal (↑r - δ) + ENNReal.ofReal δ ≤ Option.some r
[PROOFSTEP]
rw [← ofReal_add hr.le hδ.le, sub_add_cancel, ofReal_coe_nnreal]
[GOAL]
case inr.some.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y✝ z✝ : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
x : E
hs : ENNReal.ofReal δ ≤ infEdist x s
z : E
hz : z ∈ s
r : NNReal
h : dist x z < δ + (↑r - δ)
hr : 0 < ↑r - δ
y : E
hxy : dist x y < ↑r - δ
hyz : dist y z < δ
⊢ ↑r ≤ Option.some r
[PROOFSTEP]
exact le_rfl
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 < δ
s : Set E
x : E
⊢ x ∈ thickening (ε + δ) s → x ∈ thickening ε (thickening δ s)
[PROOFSTEP]
simp_rw [mem_thickening_iff]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 < δ
s : Set E
x : E
⊢ (∃ z, z ∈ s ∧ dist x z < ε + δ) → ∃ z, (∃ z_1, z_1 ∈ s ∧ dist z z_1 < δ) ∧ dist x z < ε
[PROOFSTEP]
rintro ⟨z, hz, hxz⟩
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 < δ
s : Set E
x z : E
hz : z ∈ s
hxz : dist x z < ε + δ
⊢ ∃ z, (∃ z_1, z_1 ∈ s ∧ dist z z_1 < δ) ∧ dist x z < ε
[PROOFSTEP]
rw [add_comm] at hxz
[GOAL]
case intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z✝ : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 < δ
s : Set E
x z : E
hz : z ∈ s
hxz : dist x z < δ + ε
⊢ ∃ z, (∃ z_1, z_1 ∈ s ∧ dist z z_1 < δ) ∧ dist x z < ε
[PROOFSTEP]
obtain ⟨y, hxy, hyz⟩ := exists_dist_lt_lt hε hδ hxz
[GOAL]
case intro.intro.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y✝ z✝ : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 < δ
s : Set E
x z : E
hz : z ∈ s
hxz : dist x z < δ + ε
y : E
hxy : dist x y < ε
hyz : dist y z < δ
⊢ ∃ z, (∃ z_1, z_1 ∈ s ∧ dist z z_1 < δ) ∧ dist x z < ε
[PROOFSTEP]
exact ⟨y, ⟨_, hz, hyz⟩, hxy⟩
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 ≤ ε
hδ : 0 < δ
s : Set E
x : E
⊢ x ∈ cthickening (ε + δ) s → x ∈ cthickening ε (thickening δ s)
[PROOFSTEP]
simp_rw [mem_cthickening_iff, ENNReal.ofReal_add hε hδ.le, infEdist_thickening hδ]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 ≤ ε
hδ : 0 < δ
s : Set E
x : E
⊢ infEdist x s ≤ ENNReal.ofReal ε + ENNReal.ofReal δ → infEdist x s - ENNReal.ofReal δ ≤ ENNReal.ofReal ε
[PROOFSTEP]
exact tsub_le_iff_right.2
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hδ : 0 < δ
s : Set E
⊢ closure (thickening δ s) = cthickening δ s
[PROOFSTEP]
rw [← cthickening_zero, cthickening_thickening le_rfl hδ, zero_add]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ✝ ε δ : ℝ
s : Set E
x : E
⊢ infEdist x (cthickening δ s) = infEdist x s - ENNReal.ofReal δ
[PROOFSTEP]
obtain hδ | hδ := le_or_lt δ 0
[GOAL]
case inl
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ✝ ε δ : ℝ
s : Set E
x : E
hδ : δ ≤ 0
⊢ infEdist x (cthickening δ s) = infEdist x s - ENNReal.ofReal δ
[PROOFSTEP]
rw [cthickening_of_nonpos hδ, infEdist_closure, ofReal_of_nonpos hδ, tsub_zero]
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ✝ ε δ : ℝ
s : Set E
x : E
hδ : 0 < δ
⊢ infEdist x (cthickening δ s) = infEdist x s - ENNReal.ofReal δ
[PROOFSTEP]
rw [← closure_thickening hδ, infEdist_closure, infEdist_thickening hδ]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 ≤ δ
s : Set E
⊢ thickening ε (cthickening δ s) = thickening (ε + δ) s
[PROOFSTEP]
obtain rfl | hδ := hδ.eq_or_lt
[GOAL]
case inl
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
ε : ℝ
hε : 0 < ε
s : Set E
hδ : 0 ≤ 0
⊢ thickening ε (cthickening 0 s) = thickening (ε + 0) s
[PROOFSTEP]
rw [cthickening_zero, thickening_closure, add_zero]
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hε : 0 < ε
hδ✝ : 0 ≤ δ
s : Set E
hδ : 0 < δ
⊢ thickening ε (cthickening δ s) = thickening (ε + δ) s
[PROOFSTEP]
rw [← closure_thickening hδ, thickening_closure, thickening_thickening hε hδ]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 ≤ ε
hδ : 0 ≤ δ
s : Set E
x : E
⊢ x ∈ cthickening (ε + δ) s → x ∈ cthickening ε (cthickening δ s)
[PROOFSTEP]
simp_rw [mem_cthickening_iff, ENNReal.ofReal_add hε hδ, infEdist_cthickening]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 ≤ ε
hδ : 0 ≤ δ
s : Set E
x : E
⊢ infEdist x s ≤ ENNReal.ofReal ε + ENNReal.ofReal δ → infEdist x s - ENNReal.ofReal δ ≤ ENNReal.ofReal ε
[PROOFSTEP]
exact tsub_le_iff_right.2
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 < δ
x : E
⊢ thickening ε (Metric.ball x δ) = Metric.ball x (ε + δ)
[PROOFSTEP]
rw [← thickening_singleton, thickening_thickening hε hδ, thickening_singleton]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 ≤ δ
x : E
⊢ thickening ε (Metric.closedBall x δ) = Metric.ball x (ε + δ)
[PROOFSTEP]
rw [← cthickening_singleton _ hδ, thickening_cthickening hε hδ, thickening_singleton]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 ≤ ε
hδ : 0 < δ
x : E
⊢ cthickening ε (Metric.ball x δ) = Metric.closedBall x (ε + δ)
[PROOFSTEP]
rw [← thickening_singleton, cthickening_thickening hε hδ, cthickening_singleton _ (add_nonneg hε hδ.le)]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x✝ y z : E
δ ε : ℝ
hε : 0 ≤ ε
hδ : 0 ≤ δ
x : E
⊢ cthickening ε (Metric.closedBall x δ) = Metric.closedBall x (ε + δ)
[PROOFSTEP]
rw [← cthickening_singleton _ hδ, cthickening_cthickening hε hδ, cthickening_singleton _ (add_nonneg hε hδ)]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 < δ
a b : E
⊢ Metric.ball a ε + Metric.ball b δ = Metric.ball (a + b) (ε + δ)
[PROOFSTEP]
rw [ball_add, thickening_ball hε hδ b, Metric.vadd_ball, vadd_eq_add]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 < δ
a b : E
⊢ Metric.ball a ε - Metric.ball b δ = Metric.ball (a - b) (ε + δ)
[PROOFSTEP]
simp_rw [sub_eq_add_neg, neg_ball, ball_add_ball hε hδ]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 ≤ δ
a b : E
⊢ Metric.ball a ε + Metric.closedBall b δ = Metric.ball (a + b) (ε + δ)
[PROOFSTEP]
rw [ball_add, thickening_closedBall hε hδ b, Metric.vadd_ball, vadd_eq_add]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hε : 0 < ε
hδ : 0 ≤ δ
a b : E
⊢ Metric.ball a ε - Metric.closedBall b δ = Metric.ball (a - b) (ε + δ)
[PROOFSTEP]
simp_rw [sub_eq_add_neg, neg_closedBall, ball_add_closedBall hε hδ]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hε : 0 ≤ ε
hδ : 0 < δ
a b : E
⊢ Metric.closedBall a ε + Metric.ball b δ = Metric.ball (a + b) (ε + δ)
[PROOFSTEP]
rw [add_comm, ball_add_closedBall hδ hε b, add_comm, add_comm δ]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : SeminormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
hε : 0 ≤ ε
hδ : 0 < δ
a b : E
⊢ Metric.closedBall a ε - Metric.ball b δ = Metric.ball (a - b) (ε + δ)
[PROOFSTEP]
simp_rw [sub_eq_add_neg, neg_ball, closedBall_add_ball hε hδ]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : SeminormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
inst✝ : ProperSpace E
hε : 0 ≤ ε
hδ : 0 ≤ δ
a b : E
⊢ Metric.closedBall a ε + Metric.closedBall b δ = Metric.closedBall (a + b) (ε + δ)
[PROOFSTEP]
rw [(isCompact_closedBall _ _).add_closedBall hδ b, cthickening_closedBall hδ hε a, Metric.vadd_closedBall, vadd_eq_add,
  add_comm, add_comm δ]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : SeminormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
x y z : E
δ ε : ℝ
inst✝ : ProperSpace E
hε : 0 ≤ ε
hδ : 0 ≤ δ
a b : E
⊢ Metric.closedBall a ε - Metric.closedBall b δ = Metric.closedBall (a - b) (ε + δ)
[PROOFSTEP]
rw [sub_eq_add_neg, neg_closedBall, closedBall_add_closedBall hε hδ, sub_eq_add_neg]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
x : E
r : ℝ
hr : 0 ≤ r
⊢ c • closedBall x r = closedBall (c • x) (‖c‖ * r)
[PROOFSTEP]
rcases eq_or_ne c 0 with (rfl | hc)
[GOAL]
case inl
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
x : E
r : ℝ
hr : 0 ≤ r
⊢ 0 • closedBall x r = closedBall (0 • x) (‖0‖ * r)
[PROOFSTEP]
simp [hr, zero_smul_set, Set.singleton_zero, ← nonempty_closedBall]
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
x : E
r : ℝ
hr : 0 ≤ r
hc : c ≠ 0
⊢ c • closedBall x r = closedBall (c • x) (‖c‖ * r)
[PROOFSTEP]
exact smul_closedBall' hc x r
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝² : NormedField 𝕜
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
c : 𝕜
⊢ c • closedBall 0 1 = closedBall 0 ‖c‖
[PROOFSTEP]
rw [smul_closedBall _ _ zero_le_one, smul_zero, mul_one]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : NormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
r : ℝ
hr : 0 ≤ r
⊢ r • closedBall 0 1 = closedBall 0 r
[PROOFSTEP]
rw [smul_closedUnitBall, Real.norm_of_nonneg hr]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
x : E
r : ℝ
⊢ Set.Nonempty (sphere x r) ↔ 0 ≤ r
[PROOFSTEP]
obtain ⟨y, hy⟩ := exists_ne x
[GOAL]
case intro
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
x : E
r : ℝ
y : E
hy : y ≠ x
⊢ Set.Nonempty (sphere x r) ↔ 0 ≤ r
[PROOFSTEP]
refine' ⟨fun h => nonempty_closedBall.1 (h.mono sphere_subset_closedBall), fun hr => ⟨r • ‖y - x‖⁻¹ • (y - x) + x, _⟩⟩
[GOAL]
case intro
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
x : E
r : ℝ
y : E
hy : y ≠ x
hr : 0 ≤ r
⊢ r • ‖y - x‖⁻¹ • (y - x) + x ∈ sphere x r
[PROOFSTEP]
have : ‖y - x‖ ≠ 0 := by simpa [sub_eq_zero]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
x : E
r : ℝ
y : E
hy : y ≠ x
hr : 0 ≤ r
⊢ ‖y - x‖ ≠ 0
[PROOFSTEP]
simpa [sub_eq_zero]
[GOAL]
case intro
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
x : E
r : ℝ
y : E
hy : y ≠ x
hr : 0 ≤ r
this : ‖y - x‖ ≠ 0
⊢ r • ‖y - x‖⁻¹ • (y - x) + x ∈ sphere x r
[PROOFSTEP]
simp [norm_smul, this, Real.norm_of_nonneg hr]
[GOAL]
case intro
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
x : E
r : ℝ
y : E
hy : y ≠ x
hr : 0 ≤ r
this : ‖y - x‖ ≠ 0
⊢ |r| * (‖y - x‖⁻¹ * ‖y - x‖) = r
[PROOFSTEP]
rw [inv_mul_cancel this, mul_one, abs_eq_self.mpr hr]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
c : 𝕜
x : E
r : ℝ
hr : 0 ≤ r
⊢ c • sphere x r = sphere (c • x) (‖c‖ * r)
[PROOFSTEP]
rcases eq_or_ne c 0 with (rfl | hc)
[GOAL]
case inl
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
x : E
r : ℝ
hr : 0 ≤ r
⊢ 0 • sphere x r = sphere (0 • x) (‖0‖ * r)
[PROOFSTEP]
simp [zero_smul_set, Set.singleton_zero, hr]
[GOAL]
case inr
𝕜 : Type u_1
E : Type u_2
inst✝⁴ : NormedField 𝕜
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
inst✝¹ : NormedSpace ℝ E
inst✝ : Nontrivial E
c : 𝕜
x : E
r : ℝ
hr : 0 ≤ r
hc : c ≠ 0
⊢ c • sphere x r = sphere (c • x) (‖c‖ * r)
[PROOFSTEP]
exact smul_sphere' hc x r
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : NormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
r : ℝ
hr : 0 < r
x : E
⊢ x +ᵥ r • ball 0 1 = ball x r
[PROOFSTEP]
rw [smul_unitBall_of_pos hr, vadd_ball_zero]
[GOAL]
𝕜 : Type u_1
E : Type u_2
inst✝³ : NormedField 𝕜
inst✝² : NormedAddCommGroup E
inst✝¹ : NormedSpace 𝕜 E
inst✝ : NormedSpace ℝ E
r : ℝ
hr : 0 ≤ r
x : E
⊢ x +ᵥ r • closedBall 0 1 = closedBall x r
[PROOFSTEP]
rw [smul_closedUnitBall, Real.norm_of_nonneg hr, vadd_closedBall_zero]


[GOAL]
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : CommMonoid α
inst✝ : CommMonoid β
s : Finset γ
f : γ → α
g : γ → β
this : DecidableEq γ
⊢ ∀ ⦃a : γ⦄ {s : Finset γ},
    ¬a ∈ s →
      (∏ x in s, f x, ∏ x in s, g x) = ∏ x in s, (f x, g x) →
        (∏ x in insert a s, f x, ∏ x in insert a s, g x) = ∏ x in insert a s, (f x, g x)
[PROOFSTEP]
simp (config := { contextual := true }) [Prod.ext_iff]
[GOAL]
I : Type u_1
inst✝² : DecidableEq I
Z : I → Type u_2
inst✝¹ : (i : I) → CommMonoid (Z i)
inst✝ : Fintype I
f : (i : I) → Z i
⊢ ∏ i : I, Pi.mulSingle i (f i) = f
[PROOFSTEP]
ext a
[GOAL]
case h
I : Type u_1
inst✝² : DecidableEq I
Z : I → Type u_2
inst✝¹ : (i : I) → CommMonoid (Z i)
inst✝ : Fintype I
f : (i : I) → Z i
a : I
⊢ Finset.prod univ (fun i => Pi.mulSingle i (f i)) a = f a
[PROOFSTEP]
simp
[GOAL]
I : Type u_1
inst✝³ : DecidableEq I
Z : I → Type u_2
inst✝² : (i : I) → CommMonoid (Z i)
inst✝¹ : Finite I
G : Type u_3
inst✝ : CommMonoid G
g h : ((i : I) → Z i) →* G
H : ∀ (i : I) (x : Z i), ↑g (Pi.mulSingle i x) = ↑h (Pi.mulSingle i x)
⊢ g = h
[PROOFSTEP]
cases nonempty_fintype I
[GOAL]
case intro
I : Type u_1
inst✝³ : DecidableEq I
Z : I → Type u_2
inst✝² : (i : I) → CommMonoid (Z i)
inst✝¹ : Finite I
G : Type u_3
inst✝ : CommMonoid G
g h : ((i : I) → Z i) →* G
H : ∀ (i : I) (x : Z i), ↑g (Pi.mulSingle i x) = ↑h (Pi.mulSingle i x)
val✝ : Fintype I
⊢ g = h
[PROOFSTEP]
ext k
[GOAL]
case intro.h
I : Type u_1
inst✝³ : DecidableEq I
Z : I → Type u_2
inst✝² : (i : I) → CommMonoid (Z i)
inst✝¹ : Finite I
G : Type u_3
inst✝ : CommMonoid G
g h : ((i : I) → Z i) →* G
H : ∀ (i : I) (x : Z i), ↑g (Pi.mulSingle i x) = ↑h (Pi.mulSingle i x)
val✝ : Fintype I
k : (i : I) → Z i
⊢ ↑g k = ↑h k
[PROOFSTEP]
rw [← Finset.univ_prod_mulSingle k, g.map_prod, h.map_prod]
[GOAL]
case intro.h
I : Type u_1
inst✝³ : DecidableEq I
Z : I → Type u_2
inst✝² : (i : I) → CommMonoid (Z i)
inst✝¹ : Finite I
G : Type u_3
inst✝ : CommMonoid G
g h : ((i : I) → Z i) →* G
H : ∀ (i : I) (x : Z i), ↑g (Pi.mulSingle i x) = ↑h (Pi.mulSingle i x)
val✝ : Fintype I
k : (i : I) → Z i
⊢ ∏ x : I, ↑g (Pi.mulSingle x (k x)) = ∏ x : I, ↑h (Pi.mulSingle x (k x))
[PROOFSTEP]
simp only [H]


[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
⊢ (∃ y, y ^ 2 = x) ↔ x ^ (p / 2) = 1
[PROOFSTEP]
by_cases hc : p = 2
[GOAL]
case pos
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
hc : p = 2
⊢ (∃ y, y ^ 2 = x) ↔ x ^ (p / 2) = 1
[PROOFSTEP]
subst hc
[GOAL]
case pos
inst✝ : Fact (Nat.Prime 2)
x : (ZMod 2)ˣ
⊢ (∃ y, y ^ 2 = x) ↔ x ^ (2 / 2) = 1
[PROOFSTEP]
simp only [eq_iff_true_of_subsingleton, exists_const]
[GOAL]
case neg
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
hc : ¬p = 2
⊢ (∃ y, y ^ 2 = x) ↔ x ^ (p / 2) = 1
[PROOFSTEP]
have h₀ := FiniteField.unit_isSquare_iff (by rwa [ringChar_zmod_n]) x
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
hc : ¬p = 2
⊢ ringChar (ZMod p) ≠ 2
[PROOFSTEP]
rwa [ringChar_zmod_n]
[GOAL]
case neg
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
hc : ¬p = 2
h₀ : IsSquare x ↔ x ^ (Fintype.card (ZMod p) / 2) = 1
⊢ (∃ y, y ^ 2 = x) ↔ x ^ (p / 2) = 1
[PROOFSTEP]
have hs : (∃ y : (ZMod p)ˣ, y ^ 2 = x) ↔ IsSquare x :=
  by
  rw [isSquare_iff_exists_sq x]
  simp_rw [eq_comm]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
hc : ¬p = 2
h₀ : IsSquare x ↔ x ^ (Fintype.card (ZMod p) / 2) = 1
⊢ (∃ y, y ^ 2 = x) ↔ IsSquare x
[PROOFSTEP]
rw [isSquare_iff_exists_sq x]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
hc : ¬p = 2
h₀ : IsSquare x ↔ x ^ (Fintype.card (ZMod p) / 2) = 1
⊢ (∃ y, y ^ 2 = x) ↔ ∃ c, x = c ^ 2
[PROOFSTEP]
simp_rw [eq_comm]
[GOAL]
case neg
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
hc : ¬p = 2
h₀ : IsSquare x ↔ x ^ (Fintype.card (ZMod p) / 2) = 1
hs : (∃ y, y ^ 2 = x) ↔ IsSquare x
⊢ (∃ y, y ^ 2 = x) ↔ x ^ (p / 2) = 1
[PROOFSTEP]
rw [hs]
[GOAL]
case neg
p : ℕ
inst✝ : Fact (Nat.Prime p)
x : (ZMod p)ˣ
hc : ¬p = 2
h₀ : IsSquare x ↔ x ^ (Fintype.card (ZMod p) / 2) = 1
hs : (∃ y, y ^ 2 = x) ↔ IsSquare x
⊢ IsSquare x ↔ x ^ (p / 2) = 1
[PROOFSTEP]
rwa [card p] at h₀
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
⊢ IsSquare a ↔ a ^ (p / 2) = 1
[PROOFSTEP]
apply (iff_congr _ (by simp [Units.ext_iff])).mp (euler_criterion_units p (Units.mk0 a ha))
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
⊢ Units.mk0 a ha ^ (p / 2) = 1 ↔ a ^ (p / 2) = 1
[PROOFSTEP]
simp [Units.ext_iff]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
⊢ (∃ y, y ^ 2 = Units.mk0 a ha) ↔ IsSquare a
[PROOFSTEP]
simp only [Units.ext_iff, sq, Units.val_mk0, Units.val_mul]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
⊢ (∃ y, ↑y * ↑y = a) ↔ IsSquare a
[PROOFSTEP]
constructor
[GOAL]
case mp
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
⊢ (∃ y, ↑y * ↑y = a) → IsSquare a
[PROOFSTEP]
rintro ⟨y, hy⟩
[GOAL]
case mp.intro
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
y : (ZMod p)ˣ
hy : ↑y * ↑y = a
⊢ IsSquare a
[PROOFSTEP]
exact ⟨y, hy.symm⟩
[GOAL]
case mpr
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
⊢ IsSquare a → ∃ y, ↑y * ↑y = a
[PROOFSTEP]
rintro ⟨y, rfl⟩
[GOAL]
case mpr.intro
p : ℕ
inst✝ : Fact (Nat.Prime p)
y : ZMod p
ha : y * y ≠ 0
⊢ ∃ y_1, ↑y_1 * ↑y_1 = y * y
[PROOFSTEP]
have hy : y ≠ 0 := by
  rintro rfl
  simp [zero_pow, mul_zero, ne_eq, not_true] at ha
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
y : ZMod p
ha : y * y ≠ 0
⊢ y ≠ 0
[PROOFSTEP]
rintro rfl
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
ha : 0 * 0 ≠ 0
⊢ False
[PROOFSTEP]
simp [zero_pow, mul_zero, ne_eq, not_true] at ha
[GOAL]
case mpr.intro
p : ℕ
inst✝ : Fact (Nat.Prime p)
y : ZMod p
ha : y * y ≠ 0
hy : y ≠ 0
⊢ ∃ y_1, ↑y_1 * ↑y_1 = y * y
[PROOFSTEP]
refine' ⟨Units.mk0 y hy, _⟩
[GOAL]
case mpr.intro
p : ℕ
inst✝ : Fact (Nat.Prime p)
y : ZMod p
ha : y * y ≠ 0
hy : y ≠ 0
⊢ ↑(Units.mk0 y hy) * ↑(Units.mk0 y hy) = y * y
[PROOFSTEP]
simp
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
⊢ a ^ (p / 2) = 1 ∨ a ^ (p / 2) = -1
[PROOFSTEP]
cases' Prime.eq_two_or_odd (@Fact.out p.Prime _) with hp2 hp_odd
[GOAL]
case inl
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
hp2 : p = 2
⊢ a ^ (p / 2) = 1 ∨ a ^ (p / 2) = -1
[PROOFSTEP]
subst p
[GOAL]
case inl
inst✝ : Fact (Nat.Prime 2)
a : ZMod 2
ha : a ≠ 0
⊢ a ^ (2 / 2) = 1 ∨ a ^ (2 / 2) = -1
[PROOFSTEP]
revert a ha
[GOAL]
case inl
inst✝ : Fact (Nat.Prime 2)
⊢ ∀ {a : ZMod 2}, a ≠ 0 → a ^ (2 / 2) = 1 ∨ a ^ (2 / 2) = -1
[PROOFSTEP]
intro a
[GOAL]
case inl
inst✝ : Fact (Nat.Prime 2)
a : ZMod 2
⊢ a ≠ 0 → a ^ (2 / 2) = 1 ∨ a ^ (2 / 2) = -1
[PROOFSTEP]
fin_cases a
[GOAL]
case inl.head
inst✝ : Fact (Nat.Prime 2)
⊢ { val := 0, isLt := (_ : 0 < 1 + 1) } ≠ 0 →
    { val := 0, isLt := (_ : 0 < 1 + 1) } ^ (2 / 2) = 1 ∨ { val := 0, isLt := (_ : 0 < 1 + 1) } ^ (2 / 2) = -1
case inl.tail.head
inst✝ : Fact (Nat.Prime 2)
⊢ { val := 1, isLt := (_ : (fun a => a < 1 + 1) 1) } ≠ 0 →
    { val := 1, isLt := (_ : (fun a => a < 1 + 1) 1) } ^ (2 / 2) = 1 ∨
      { val := 1, isLt := (_ : (fun a => a < 1 + 1) 1) } ^ (2 / 2) = -1
[PROOFSTEP]
tauto
[GOAL]
case inl.tail.head
inst✝ : Fact (Nat.Prime 2)
⊢ { val := 1, isLt := (_ : (fun a => a < 1 + 1) 1) } ≠ 0 →
    { val := 1, isLt := (_ : (fun a => a < 1 + 1) 1) } ^ (2 / 2) = 1 ∨
      { val := 1, isLt := (_ : (fun a => a < 1 + 1) 1) } ^ (2 / 2) = -1
[PROOFSTEP]
simp
[GOAL]
case inr
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
hp_odd : p % 2 = 1
⊢ a ^ (p / 2) = 1 ∨ a ^ (p / 2) = -1
[PROOFSTEP]
rw [← mul_self_eq_one_iff, ← pow_add, ← two_mul, two_mul_odd_div_two hp_odd]
[GOAL]
case inr
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ZMod p
ha : a ≠ 0
hp_odd : p % 2 = 1
⊢ a ^ (p - 1) = 1
[PROOFSTEP]
exact pow_card_sub_one_eq_one ha
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
⊢ ↑(legendreSym p a) = ↑a ^ (p / 2)
[PROOFSTEP]
cases' eq_or_ne (ringChar (ZMod p)) 2 with hc hc
[GOAL]
case inl
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) = 2
⊢ ↑(legendreSym p a) = ↑a ^ (p / 2)
[PROOFSTEP]
by_cases ha : (a : ZMod p) = 0
[GOAL]
case pos
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) = 2
ha : ↑a = 0
⊢ ↑(legendreSym p a) = ↑a ^ (p / 2)
[PROOFSTEP]
rw [legendreSym, ha, quadraticChar_zero, zero_pow (Nat.div_pos (@Fact.out p.Prime).two_le (succ_pos 1))]
[GOAL]
case pos
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) = 2
ha : ↑a = 0
⊢ ↑0 = 0
[PROOFSTEP]
norm_cast
[GOAL]
case neg
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) = 2
ha : ¬↑a = 0
⊢ ↑(legendreSym p a) = ↑a ^ (p / 2)
[PROOFSTEP]
have := (ringChar_zmod_n p).symm.trans hc
[GOAL]
case neg
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) = 2
ha : ¬↑a = 0
this : p = 2
⊢ ↑(legendreSym p a) = ↑a ^ (p / 2)
[PROOFSTEP]
subst p
[GOAL]
case neg
a : ℤ
inst✝ : Fact (Nat.Prime 2)
hc : ringChar (ZMod 2) = 2
ha : ¬↑a = 0
⊢ ↑(legendreSym 2 a) = ↑a ^ (2 / 2)
[PROOFSTEP]
rw [legendreSym, quadraticChar_eq_one_of_char_two hc ha]
[GOAL]
case neg
a : ℤ
inst✝ : Fact (Nat.Prime 2)
hc : ringChar (ZMod 2) = 2
ha : ¬↑a = 0
⊢ ↑1 = ↑a ^ (2 / 2)
[PROOFSTEP]
revert ha
[GOAL]
case neg
a : ℤ
inst✝ : Fact (Nat.Prime 2)
hc : ringChar (ZMod 2) = 2
⊢ ¬↑a = 0 → ↑1 = ↑a ^ (2 / 2)
[PROOFSTEP]
push_cast
[GOAL]
case neg
a : ℤ
inst✝ : Fact (Nat.Prime 2)
hc : ringChar (ZMod 2) = 2
⊢ ¬↑a = 0 → 1 = ↑a ^ (2 / 2)
[PROOFSTEP]
generalize (a : ZMod 2) = b
[GOAL]
case neg
a : ℤ
inst✝ : Fact (Nat.Prime 2)
hc : ringChar (ZMod 2) = 2
b : ZMod 2
⊢ ¬b = 0 → 1 = b ^ (2 / 2)
[PROOFSTEP]
fin_cases b
[GOAL]
case neg.head
a : ℤ
inst✝ : Fact (Nat.Prime 2)
hc : ringChar (ZMod 2) = 2
⊢ ¬{ val := 0, isLt := (_ : 0 < 1 + 1) } = 0 → 1 = { val := 0, isLt := (_ : 0 < 1 + 1) } ^ (2 / 2)
[PROOFSTEP]
tauto
[GOAL]
case neg.tail.head
a : ℤ
inst✝ : Fact (Nat.Prime 2)
hc : ringChar (ZMod 2) = 2
⊢ ¬{ val := 1, isLt := (_ : (fun a => a < 1 + 1) 1) } = 0 →
    1 = { val := 1, isLt := (_ : (fun a => a < 1 + 1) 1) } ^ (2 / 2)
[PROOFSTEP]
simp
[GOAL]
case inr
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) ≠ 2
⊢ ↑(legendreSym p a) = ↑a ^ (p / 2)
[PROOFSTEP]
convert quadraticChar_eq_pow_of_char_ne_two' hc (a : ZMod p)
[GOAL]
case h.e'_3.h.e'_6.h.e'_5
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) ≠ 2
⊢ p = Fintype.card (ZMod p)
[PROOFSTEP]
norm_cast
[GOAL]
case h.e'_3.h.e'_6.h.e'_5
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) ≠ 2
⊢ p = Fintype.card (ZMod p)
[PROOFSTEP]
congr
[GOAL]
case h.e'_3.h.e'_6.h.e'_5
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
hc : ringChar (ZMod p) ≠ 2
⊢ p = Fintype.card (ZMod p)
[PROOFSTEP]
exact (card p).symm
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ legendreSym p 0 = 0
[PROOFSTEP]
rw [legendreSym, Int.cast_zero, MulChar.map_zero]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ legendreSym p 1 = 1
[PROOFSTEP]
rw [legendreSym, Int.cast_one, MulChar.map_one]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a b : ℤ
⊢ legendreSym p (a * b) = legendreSym p a * legendreSym p b
[PROOFSTEP]
simp [legendreSym, Int.cast_mul, map_mul, quadraticCharFun_mul]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
⊢ legendreSym p (a ^ 2) = 1
[PROOFSTEP]
dsimp only [legendreSym]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
⊢ ↑(quadraticChar (ZMod p)) ↑(a ^ 2) = 1
[PROOFSTEP]
rw [Int.cast_pow]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
⊢ ↑(quadraticChar (ZMod p)) (↑a ^ 2) = 1
[PROOFSTEP]
exact quadraticChar_sq_one' ha
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
⊢ legendreSym p a = legendreSym p (a % ↑p)
[PROOFSTEP]
simp only [legendreSym, int_cast_mod]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℕ
ha0 : ↑a ≠ 0
⊢ legendreSym p ↑a = 1 ↔ IsSquare ↑a
[PROOFSTEP]
rw [eq_one_iff]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℕ
ha0 : ↑a ≠ 0
⊢ IsSquare ↑↑a ↔ IsSquare ↑a
case ha0 p : ℕ inst✝ : Fact (Nat.Prime p) a : ℕ ha0 : ↑a ≠ 0 ⊢ ↑↑a ≠ 0
[PROOFSTEP]
norm_cast
[GOAL]
case ha0
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℕ
ha0 : ↑a ≠ 0
⊢ ↑↑a ≠ 0
[PROOFSTEP]
exact_mod_cast ha0
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℕ
⊢ legendreSym p ↑a = -1 ↔ ¬IsSquare ↑a
[PROOFSTEP]
rw [eq_neg_one_iff]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℕ
⊢ ¬IsSquare ↑↑a ↔ ¬IsSquare ↑a
[PROOFSTEP]
norm_cast
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x y : ZMod p
hy : y ≠ 0
hxy : x ^ 2 - ↑a * y ^ 2 = 0
⊢ legendreSym p a = 1
[PROOFSTEP]
apply_fun (· * y⁻¹ ^ 2) at hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x y : ZMod p
hy : y ≠ 0
hxy : (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = 0 * y⁻¹ ^ 2
⊢ legendreSym p a = 1
[PROOFSTEP]
simp only [zero_mul] at hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x y : ZMod p
hy : y ≠ 0
hxy : (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = 0
⊢ legendreSym p a = 1
[PROOFSTEP]
rw [(by ring : (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = (x * y⁻¹) ^ 2 - a * (y * y⁻¹) ^ 2), mul_inv_cancel hy, one_pow, mul_one,
  sub_eq_zero, pow_two] at hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x y : ZMod p
hy : y ≠ 0
hxy : (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = 0
⊢ (x ^ 2 - ↑a * y ^ 2) * y⁻¹ ^ 2 = (x * y⁻¹) ^ 2 - ↑a * (y * y⁻¹) ^ 2
[PROOFSTEP]
ring
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x y : ZMod p
hy : y ≠ 0
hxy : x * y⁻¹ * (x * y⁻¹) = ↑a
⊢ legendreSym p a = 1
[PROOFSTEP]
exact (eq_one_iff p ha).mpr ⟨x * y⁻¹, hxy.symm⟩
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x y : ZMod p
hx : x ≠ 0
hxy : x ^ 2 - ↑a * y ^ 2 = 0
⊢ legendreSym p a = 1
[PROOFSTEP]
haveI hy : y ≠ 0 := by
  rintro rfl
  rw [zero_pow' 2 (by norm_num), mul_zero, sub_zero, pow_eq_zero_iff (by norm_num : 0 < 2)] at hxy
  exact hx hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x y : ZMod p
hx : x ≠ 0
hxy : x ^ 2 - ↑a * y ^ 2 = 0
⊢ y ≠ 0
[PROOFSTEP]
rintro rfl
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x : ZMod p
hx : x ≠ 0
hxy : x ^ 2 - ↑a * 0 ^ 2 = 0
⊢ False
[PROOFSTEP]
rw [zero_pow' 2 (by norm_num), mul_zero, sub_zero, pow_eq_zero_iff (by norm_num : 0 < 2)] at hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x : ZMod p
hx : x ≠ 0
hxy : x ^ 2 - ↑a * 0 ^ 2 = 0
⊢ 2 ≠ 0
[PROOFSTEP]
norm_num
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x : ZMod p
hx : x ≠ 0
hxy : x ^ 2 = 0
⊢ 0 < 2
[PROOFSTEP]
norm_num
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x : ZMod p
hx : x ≠ 0
hxy : x = 0
⊢ False
[PROOFSTEP]
exact hx hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
ha : ↑a ≠ 0
x y : ZMod p
hx : x ≠ 0
hxy : x ^ 2 - ↑a * y ^ 2 = 0
hy : y ≠ 0
⊢ legendreSym p a = 1
[PROOFSTEP]
exact eq_one_of_sq_sub_mul_sq_eq_zero ha hy hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
⊢ x = 0 ∧ y = 0
[PROOFSTEP]
have ha : (a : ZMod p) ≠ 0 := by
  intro hf
  rw [(eq_zero_iff p a).mpr hf] at h
  exact Int.zero_ne_neg_of_ne zero_ne_one h
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
⊢ ↑a ≠ 0
[PROOFSTEP]
intro hf
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
hf : ↑a = 0
⊢ False
[PROOFSTEP]
rw [(eq_zero_iff p a).mpr hf] at h
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : 0 = -1
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
hf : ↑a = 0
⊢ False
[PROOFSTEP]
exact Int.zero_ne_neg_of_ne zero_ne_one h
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
ha : ↑a ≠ 0
⊢ x = 0 ∧ y = 0
[PROOFSTEP]
by_contra hf
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
ha : ↑a ≠ 0
hf : ¬(x = 0 ∧ y = 0)
⊢ False
[PROOFSTEP]
cases' imp_iff_or_not.mp (not_and'.mp hf) with hx hy
[GOAL]
case inl
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
ha : ↑a ≠ 0
hf : ¬(x = 0 ∧ y = 0)
hx : ¬x = 0
⊢ False
[PROOFSTEP]
rw [eq_one_of_sq_sub_mul_sq_eq_zero' ha hx hxy, eq_neg_self_iff] at h
[GOAL]
case inl
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : 1 = 0
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
ha : ↑a ≠ 0
hf : ¬(x = 0 ∧ y = 0)
hx : ¬x = 0
⊢ False
[PROOFSTEP]
exact one_ne_zero h
[GOAL]
case inr
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
ha : ↑a ≠ 0
hf : ¬(x = 0 ∧ y = 0)
hy : ¬y = 0
⊢ False
[PROOFSTEP]
rw [eq_one_of_sq_sub_mul_sq_eq_zero ha hy hxy, eq_neg_self_iff] at h
[GOAL]
case inr
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : 1 = 0
x y : ZMod p
hxy : x ^ 2 - ↑a * y ^ 2 = 0
ha : ↑a ≠ 0
hf : ¬(x = 0 ∧ y = 0)
hy : ¬y = 0
⊢ False
[PROOFSTEP]
exact one_ne_zero h
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ℤ
hxy : ↑p ∣ x ^ 2 - a * y ^ 2
⊢ ↑p ∣ x ∧ ↑p ∣ y
[PROOFSTEP]
simp_rw [← ZMod.int_cast_zmod_eq_zero_iff_dvd] at hxy ⊢
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ℤ
hxy : ↑(x ^ 2 - a * y ^ 2) = 0
⊢ ↑x = 0 ∧ ↑y = 0
[PROOFSTEP]
push_cast at hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
a : ℤ
h : legendreSym p a = -1
x y : ℤ
hxy : ↑x ^ 2 - ↑a * ↑y ^ 2 = 0
⊢ ↑x = 0 ∧ ↑y = 0
[PROOFSTEP]
exact eq_zero_mod_of_eq_neg_one h hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ legendreSym p (-1) = ↑χ₄ ↑p
[PROOFSTEP]
simp only [legendreSym, card p, quadraticChar_neg_one ((ringChar_zmod_n p).substr hp), Int.cast_neg, Int.cast_one]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ IsSquare (-1) ↔ p % 4 ≠ 3
[PROOFSTEP]
rw [FiniteField.isSquare_neg_one_iff, card p]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
x y : ZMod p
hy : y ≠ 0
hxy : x ^ 2 = -y ^ 2
⊢ (x / y) ^ 2 = -1
[PROOFSTEP]
apply_fun fun z => z / y ^ 2 at hxy
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
x y : ZMod p
hy : y ≠ 0
hxy : x ^ 2 / y ^ 2 = -y ^ 2 / y ^ 2
⊢ (x / y) ^ 2 = -1
[PROOFSTEP]
rwa [neg_div, ← div_pow, ← div_pow, div_self hy, one_pow] at hxy


[GOAL]
n : ℕ
⊢ choose n 0 = 1
[PROOFSTEP]
cases n
[GOAL]
case zero
⊢ choose zero 0 = 1
[PROOFSTEP]
rfl
[GOAL]
case succ
n✝ : ℕ
⊢ choose (succ n✝) 0 = 1
[PROOFSTEP]
rfl
[GOAL]
n k : ℕ
hk : n + 1 < k + 1
⊢ choose (n + 1) (k + 1) = 0
[PROOFSTEP]
have hnk : n < k := lt_of_succ_lt_succ hk
[GOAL]
n k : ℕ
hk : n + 1 < k + 1
hnk : n < k
⊢ choose (n + 1) (k + 1) = 0
[PROOFSTEP]
have hnk1 : n < k + 1 := lt_of_succ_lt hk
[GOAL]
n k : ℕ
hk : n + 1 < k + 1
hnk : n < k
hnk1 : n < k + 1
⊢ choose (n + 1) (k + 1) = 0
[PROOFSTEP]
rw [choose_succ_succ, choose_eq_zero_of_lt hnk, choose_eq_zero_of_lt hnk1]
[GOAL]
n : ℕ
⊢ choose n n = 1
[PROOFSTEP]
induction n
[GOAL]
case zero
⊢ choose zero zero = 1
[PROOFSTEP]
simp [*, choose, choose_eq_zero_of_lt (lt_succ_self _)]
[GOAL]
case succ
n✝ : ℕ
n_ih✝ : choose n✝ n✝ = 1
⊢ choose (succ n✝) (succ n✝) = 1
[PROOFSTEP]
simp [*, choose, choose_eq_zero_of_lt (lt_succ_self _)]
[GOAL]
n : ℕ
⊢ choose n 1 = n
[PROOFSTEP]
induction n
[GOAL]
case zero
⊢ choose zero 1 = zero
[PROOFSTEP]
simp [*, choose, add_comm]
[GOAL]
case succ
n✝ : ℕ
n_ih✝ : choose n✝ 1 = n✝
⊢ choose (succ n✝) 1 = succ n✝
[PROOFSTEP]
simp [*, choose, add_comm]
[GOAL]
n : ℕ
⊢ (n + 1) * (n + 1 - 1) / 2 = n * (n - 1) / 2 + n
[PROOFSTEP]
rw [← add_mul_div_left, mul_comm 2 n, ← mul_add, add_tsub_cancel_right, mul_comm]
[GOAL]
n : ℕ
⊢ n * (n + 1) / 2 = n * (n - 1 + 2) / 2
[PROOFSTEP]
cases n
[GOAL]
case zero
⊢ zero * (zero + 1) / 2 = zero * (zero - 1 + 2) / 2
[PROOFSTEP]
rfl
[GOAL]
case succ
n✝ : ℕ
⊢ succ n✝ * (succ n✝ + 1) / 2 = succ n✝ * (succ n✝ - 1 + 2) / 2
[PROOFSTEP]
rfl
[GOAL]
case H
n : ℕ
⊢ 0 < 2
[PROOFSTEP]
apply zero_lt_succ
[GOAL]
n : ℕ
⊢ choose n 2 = n * (n - 1) / 2
[PROOFSTEP]
induction' n with n ih
[GOAL]
case zero
⊢ choose zero 2 = zero * (zero - 1) / 2
[PROOFSTEP]
simp
[GOAL]
case succ
n : ℕ
ih : choose n 2 = n * (n - 1) / 2
⊢ choose (succ n) 2 = succ n * (succ n - 1) / 2
[PROOFSTEP]
rw [triangle_succ n, choose, ih]
[GOAL]
case succ
n : ℕ
ih : choose n 2 = n * (n - 1) / 2
⊢ choose n 1 + n * (n - 1) / 2 = n * (n - 1) / 2 + n
[PROOFSTEP]
simp [add_comm]
[GOAL]
x✝ : ℕ
hk : x✝ ≤ 0
⊢ 0 < choose 0 x✝
[PROOFSTEP]
rw [Nat.eq_zero_of_le_zero hk]
[GOAL]
x✝ : ℕ
hk : x✝ ≤ 0
⊢ 0 < choose 0 0
[PROOFSTEP]
decide
[GOAL]
n : ℕ
x✝ : 0 ≤ n + 1
⊢ 0 < choose (n + 1) 0
[PROOFSTEP]
simp
[GOAL]
n k : ℕ
hk : k + 1 ≤ n + 1
⊢ 0 < choose (n + 1) (k + 1)
[PROOFSTEP]
rw [choose_succ_succ]
[GOAL]
n k : ℕ
hk : k + 1 ≤ n + 1
⊢ 0 < choose n k + choose n (succ k)
[PROOFSTEP]
exact add_pos_of_pos_of_nonneg (choose_pos (le_of_succ_le_succ hk)) (Nat.zero_le _)
[GOAL]
⊢ succ 0 * choose 0 0 = choose (succ 0) (succ 0) * succ 0
[PROOFSTEP]
decide
[GOAL]
k : ℕ
⊢ succ 0 * choose 0 (k + 1) = choose (succ 0) (succ (k + 1)) * succ (k + 1)
[PROOFSTEP]
simp [choose]
[GOAL]
n : ℕ
⊢ succ (n + 1) * choose (n + 1) 0 = choose (succ (n + 1)) (succ 0) * succ 0
[PROOFSTEP]
simp [choose, mul_succ, succ_eq_add_one, add_comm]
[GOAL]
n k : ℕ
⊢ succ (n + 1) * choose (n + 1) (k + 1) = choose (succ (n + 1)) (succ (k + 1)) * succ (k + 1)
[PROOFSTEP]
rw [choose_succ_succ (succ n) (succ k), add_mul, ← succ_mul_choose_eq n, mul_succ, ← succ_mul_choose_eq n,
  add_right_comm, ← mul_add, ← choose_succ_succ, ← succ_mul]
[GOAL]
x✝ : ℕ
hk : x✝ ≤ 0
⊢ choose 0 x✝ * x✝! * (0 - x✝)! = 0!
[PROOFSTEP]
simp [Nat.eq_zero_of_le_zero hk]
[GOAL]
n : ℕ
x✝ : 0 ≤ n + 1
⊢ choose (n + 1) 0 * 0! * (n + 1 - 0)! = (n + 1)!
[PROOFSTEP]
simp
[GOAL]
n k : ℕ
hk : succ k ≤ n + 1
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!
[PROOFSTEP]
cases' lt_or_eq_of_le hk with hk₁ hk₁
[GOAL]
case inl
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!
[PROOFSTEP]
have h : choose n k * k.succ ! * (n - k)! = (k + 1) * n ! :=
  by
  rw [← choose_mul_factorial_mul_factorial (le_of_succ_le_succ hk)]
  simp [factorial_succ, mul_comm, mul_left_comm, mul_assoc]
[GOAL]
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
⊢ choose n k * (succ k)! * (n - k)! = (k + 1) * n !
[PROOFSTEP]
rw [← choose_mul_factorial_mul_factorial (le_of_succ_le_succ hk)]
[GOAL]
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
⊢ choose n k * (succ k)! * (n - k)! = (k + 1) * (choose n k * k ! * (n - k)!)
[PROOFSTEP]
simp [factorial_succ, mul_comm, mul_left_comm, mul_assoc]
[GOAL]
case inl
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
h : choose n k * (succ k)! * (n - k)! = (k + 1) * n !
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!
[PROOFSTEP]
have h₁ : (n - k)! = (n - k) * (n - k.succ)! := by rw [← succ_sub_succ, succ_sub (le_of_lt_succ hk₁), factorial_succ]
[GOAL]
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
h : choose n k * (succ k)! * (n - k)! = (k + 1) * n !
⊢ (n - k)! = (n - k) * (n - succ k)!
[PROOFSTEP]
rw [← succ_sub_succ, succ_sub (le_of_lt_succ hk₁), factorial_succ]
[GOAL]
case inl
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
h : choose n k * (succ k)! * (n - k)! = (k + 1) * n !
h₁ : (n - k)! = (n - k) * (n - succ k)!
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!
[PROOFSTEP]
have h₂ : choose n (succ k) * k.succ ! * ((n - k) * (n - k.succ)!) = (n - k) * n ! :=
  by
  rw [← choose_mul_factorial_mul_factorial (le_of_lt_succ hk₁)]
  simp [factorial_succ, mul_comm, mul_left_comm, mul_assoc]
[GOAL]
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
h : choose n k * (succ k)! * (n - k)! = (k + 1) * n !
h₁ : (n - k)! = (n - k) * (n - succ k)!
⊢ choose n (succ k) * (succ k)! * ((n - k) * (n - succ k)!) = (n - k) * n !
[PROOFSTEP]
rw [← choose_mul_factorial_mul_factorial (le_of_lt_succ hk₁)]
[GOAL]
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
h : choose n k * (succ k)! * (n - k)! = (k + 1) * n !
h₁ : (n - k)! = (n - k) * (n - succ k)!
⊢ choose n (succ k) * (succ k)! * ((n - k) * (n - succ k)!) = (n - k) * (choose n (succ k) * (succ k)! * (n - succ k)!)
[PROOFSTEP]
simp [factorial_succ, mul_comm, mul_left_comm, mul_assoc]
[GOAL]
case inl
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
h : choose n k * (succ k)! * (n - k)! = (k + 1) * n !
h₁ : (n - k)! = (n - k) * (n - succ k)!
h₂ : choose n (succ k) * (succ k)! * ((n - k) * (n - succ k)!) = (n - k) * n !
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!
[PROOFSTEP]
have h₃ : k * n ! ≤ n * n ! := Nat.mul_le_mul_right _ (le_of_succ_le_succ hk)
[GOAL]
case inl
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
h : choose n k * (succ k)! * (n - k)! = (k + 1) * n !
h₁ : (n - k)! = (n - k) * (n - succ k)!
h₂ : choose n (succ k) * (succ k)! * ((n - k) * (n - succ k)!) = (n - k) * n !
h₃ : k * n ! ≤ n * n !
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!
[PROOFSTEP]
rw [choose_succ_succ, add_mul, add_mul, succ_sub_succ, h, h₁, h₂, add_mul, tsub_mul, factorial_succ, ←
  add_tsub_assoc_of_le h₃, add_assoc, ← add_mul, add_tsub_cancel_left, add_comm]
[GOAL]
case inr
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k = n + 1
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!
[PROOFSTEP]
rw [hk₁]
[GOAL]
case inr
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k = n + 1
⊢ choose (n + 1) (n + 1) * (n + 1)! * (n + 1 - (n + 1))! = (n + 1)!
[PROOFSTEP]
simp [hk₁, mul_comm, choose, tsub_self]
[GOAL]
n k s : ℕ
hkn : k ≤ n
hsk : s ≤ k
⊢ (n - k)! * (k - s)! * s ! ≠ 0
[PROOFSTEP]
apply_rules [factorial_ne_zero, mul_ne_zero]
[GOAL]
n k s : ℕ
hkn : k ≤ n
hsk : s ≤ k
h : (n - k)! * (k - s)! * s ! ≠ 0
⊢ choose n k * choose k s * ((n - k)! * (k - s)! * s !) = choose n k * (choose k s * s ! * (k - s)!) * (n - k)!
[PROOFSTEP]
rw [mul_assoc, mul_assoc, mul_assoc, mul_assoc _ s !, mul_assoc, mul_comm (n - k)!, mul_comm s !]
[GOAL]
n k s : ℕ
hkn : k ≤ n
hsk : s ≤ k
h : (n - k)! * (k - s)! * s ! ≠ 0
⊢ choose n k * (choose k s * s ! * (k - s)!) * (n - k)! = n !
[PROOFSTEP]
rw [choose_mul_factorial_mul_factorial hsk, choose_mul_factorial_mul_factorial hkn]
[GOAL]
n k s : ℕ
hkn : k ≤ n
hsk : s ≤ k
h : (n - k)! * (k - s)! * s ! ≠ 0
⊢ n ! = choose n s * s ! * (choose (n - s) (k - s) * (k - s)! * (n - s - (k - s))!)
[PROOFSTEP]
rw [choose_mul_factorial_mul_factorial (tsub_le_tsub_right hkn _), choose_mul_factorial_mul_factorial (hsk.trans hkn)]
[GOAL]
n k s : ℕ
hkn : k ≤ n
hsk : s ≤ k
h : (n - k)! * (k - s)! * s ! ≠ 0
⊢ choose n s * s ! * (choose (n - s) (k - s) * (k - s)! * (n - s - (k - s))!) =
    choose n s * choose (n - s) (k - s) * ((n - k)! * (k - s)! * s !)
[PROOFSTEP]
rw [tsub_tsub_tsub_cancel_right hsk, mul_assoc, mul_left_comm s !, mul_assoc, mul_comm (k - s)!, mul_comm s !,
  mul_right_comm, ← mul_assoc]
[GOAL]
n k : ℕ
hk : k ≤ n
⊢ choose n k = n ! / (k ! * (n - k)!)
[PROOFSTEP]
rw [← choose_mul_factorial_mul_factorial hk, mul_assoc]
[GOAL]
n k : ℕ
hk : k ≤ n
⊢ choose n k = choose n k * (k ! * (n - k)!) / (k ! * (n - k)!)
[PROOFSTEP]
exact (mul_div_left _ (mul_pos (factorial_pos _) (factorial_pos _))).symm
[GOAL]
i j : ℕ
⊢ choose (i + j) j = (i + j)! / (i ! * j !)
[PROOFSTEP]
rw [choose_eq_factorial_div_factorial (Nat.le_add_left j i), add_tsub_cancel_right, mul_comm]
[GOAL]
i j : ℕ
⊢ choose (i + j) j * i ! * j ! = (i + j)!
[PROOFSTEP]
rw [← choose_mul_factorial_mul_factorial (Nat.le_add_left _ _), add_tsub_cancel_right, mul_right_comm]
[GOAL]
n k : ℕ
hk : k ≤ n
⊢ k ! * (n - k)! ∣ n !
[PROOFSTEP]
rw [← choose_mul_factorial_mul_factorial hk, mul_assoc]
[GOAL]
n k : ℕ
hk : k ≤ n
⊢ k ! * (n - k)! ∣ choose n k * (k ! * (n - k)!)
[PROOFSTEP]
exact dvd_mul_left _ _
[GOAL]
i j : ℕ
⊢ i ! * j ! ∣ (i + j)!
[PROOFSTEP]
suffices : i ! * (i + j - i)! ∣ (i + j)!
[GOAL]
i j : ℕ
this : i ! * (i + j - i)! ∣ (i + j)!
⊢ i ! * j ! ∣ (i + j)!
[PROOFSTEP]
rwa [add_tsub_cancel_left i j] at this
[GOAL]
case this
i j : ℕ
⊢ i ! * (i + j - i)! ∣ (i + j)!
[PROOFSTEP]
exact factorial_mul_factorial_dvd_factorial (Nat.le_add_right _ _)
[GOAL]
n k : ℕ
hk : k ≤ n
⊢ choose n (n - k) = choose n k
[PROOFSTEP]
rw [choose_eq_factorial_div_factorial hk, choose_eq_factorial_div_factorial (Nat.sub_le _ _), tsub_tsub_cancel_of_le hk,
  mul_comm]
[GOAL]
n a b : ℕ
h : n = a + b
⊢ choose n a = choose n b
[PROOFSTEP]
suffices : choose n (n - b) = choose n b
[GOAL]
n a b : ℕ
h : n = a + b
this : choose n (n - b) = choose n b
⊢ choose n a = choose n b
[PROOFSTEP]
rw [h, add_tsub_cancel_right] at this
[GOAL]
n a b : ℕ
h : n = a + b
this : choose (a + b) a = choose (a + b) b
⊢ choose n a = choose n b
[PROOFSTEP]
rwa [h]
[GOAL]
case this
n a b : ℕ
h : n = a + b
⊢ choose n (n - b) = choose n b
[PROOFSTEP]
exact choose_symm (h ▸ le_add_left _ _)
[GOAL]
m : ℕ
⊢ choose (2 * m + 1) (m + 1) = choose (2 * m + 1) m
[PROOFSTEP]
apply choose_symm_of_eq_add
[GOAL]
case h
m : ℕ
⊢ 2 * m + 1 = m + 1 + m
[PROOFSTEP]
rw [add_comm m 1, add_assoc 1 m m, add_comm (2 * m) 1, two_mul m]
[GOAL]
n k : ℕ
⊢ choose n (k + 1) * (k + 1) = choose n k * (n - k)
[PROOFSTEP]
have e : (n + 1) * choose n k = choose n k * (k + 1) + choose n (k + 1) * (k + 1)
[GOAL]
case e
n k : ℕ
⊢ (n + 1) * choose n k = choose n k * (k + 1) + choose n (k + 1) * (k + 1)
n k : ℕ
e : (n + 1) * choose n k = choose n k * (k + 1) + choose n (k + 1) * (k + 1)
⊢ choose n (k + 1) * (k + 1) = choose n k * (n - k)
[PROOFSTEP]
rw [← right_distrib, ← choose_succ_succ, succ_mul_choose_eq]
[GOAL]
n k : ℕ
e : (n + 1) * choose n k = choose n k * (k + 1) + choose n (k + 1) * (k + 1)
⊢ choose n (k + 1) * (k + 1) = choose n k * (n - k)
[PROOFSTEP]
rw [← tsub_eq_of_eq_add_rev e, mul_comm, ← mul_tsub, add_tsub_add_eq_tsub_right]
[GOAL]
n : ℕ
⊢ choose (n + 1 + 1) (n + 1) = n + 1 + 1
[PROOFSTEP]
rw [choose_succ_succ, choose_succ_self_right n, choose_self]
[GOAL]
n k : ℕ
⊢ choose n k * (n + 1) = choose (n + 1) k * (n + 1 - k)
[PROOFSTEP]
cases k with
| zero => simp
| succ k =>
  obtain hk | hk := le_or_lt (k + 1) (n + 1)
  ·
    rw [choose_succ_succ, add_mul, succ_sub_succ, ← choose_succ_right_eq, ← succ_sub_succ, mul_tsub,
      add_tsub_cancel_of_le (Nat.mul_le_mul_left _ hk)]
  · rw [choose_eq_zero_of_lt hk, choose_eq_zero_of_lt (n.lt_succ_self.trans hk), zero_mul, zero_mul]
[GOAL]
n k : ℕ
⊢ choose n k * (n + 1) = choose (n + 1) k * (n + 1 - k)
[PROOFSTEP]
cases k with
| zero => simp
| succ k =>
  obtain hk | hk := le_or_lt (k + 1) (n + 1)
  ·
    rw [choose_succ_succ, add_mul, succ_sub_succ, ← choose_succ_right_eq, ← succ_sub_succ, mul_tsub,
      add_tsub_cancel_of_le (Nat.mul_le_mul_left _ hk)]
  · rw [choose_eq_zero_of_lt hk, choose_eq_zero_of_lt (n.lt_succ_self.trans hk), zero_mul, zero_mul]
[GOAL]
case zero
n : ℕ
⊢ choose n zero * (n + 1) = choose (n + 1) zero * (n + 1 - zero)
[PROOFSTEP]

| zero => simp
[GOAL]
case zero
n : ℕ
⊢ choose n zero * (n + 1) = choose (n + 1) zero * (n + 1 - zero)
[PROOFSTEP]
simp
[GOAL]
case succ
n k : ℕ
⊢ choose n (succ k) * (n + 1) = choose (n + 1) (succ k) * (n + 1 - succ k)
[PROOFSTEP]

| succ k =>
  obtain hk | hk := le_or_lt (k + 1) (n + 1)
  ·
    rw [choose_succ_succ, add_mul, succ_sub_succ, ← choose_succ_right_eq, ← succ_sub_succ, mul_tsub,
      add_tsub_cancel_of_le (Nat.mul_le_mul_left _ hk)]
  · rw [choose_eq_zero_of_lt hk, choose_eq_zero_of_lt (n.lt_succ_self.trans hk), zero_mul, zero_mul]
[GOAL]
case succ
n k : ℕ
⊢ choose n (succ k) * (n + 1) = choose (n + 1) (succ k) * (n + 1 - succ k)
[PROOFSTEP]
obtain hk | hk := le_or_lt (k + 1) (n + 1)
[GOAL]
case succ.inl
n k : ℕ
hk : k + 1 ≤ n + 1
⊢ choose n (succ k) * (n + 1) = choose (n + 1) (succ k) * (n + 1 - succ k)
[PROOFSTEP]
rw [choose_succ_succ, add_mul, succ_sub_succ, ← choose_succ_right_eq, ← succ_sub_succ, mul_tsub,
  add_tsub_cancel_of_le (Nat.mul_le_mul_left _ hk)]
[GOAL]
case succ.inr
n k : ℕ
hk : n + 1 < k + 1
⊢ choose n (succ k) * (n + 1) = choose (n + 1) (succ k) * (n + 1 - succ k)
[PROOFSTEP]
rw [choose_eq_zero_of_lt hk, choose_eq_zero_of_lt (n.lt_succ_self.trans hk), zero_mul, zero_mul]
[GOAL]
n k : ℕ
⊢ ascFactorial n k = k ! * choose (n + k) k
[PROOFSTEP]
rw [mul_comm]
[GOAL]
n k : ℕ
⊢ ascFactorial n k = choose (n + k) k * k !
[PROOFSTEP]
apply mul_right_cancel₀ (factorial_ne_zero (n + k - k))
[GOAL]
n k : ℕ
⊢ ascFactorial n k * (n + k - k)! = choose (n + k) k * k ! * (n + k - k)!
[PROOFSTEP]
rw [choose_mul_factorial_mul_factorial, add_tsub_cancel_right, ← factorial_mul_ascFactorial, mul_comm]
[GOAL]
n k : ℕ
⊢ k ≤ n + k
[PROOFSTEP]
exact Nat.le_add_left k n
[GOAL]
n k : ℕ
⊢ choose (n + k) k = ascFactorial n k / k !
[PROOFSTEP]
apply mul_left_cancel₀ (factorial_ne_zero k)
[GOAL]
n k : ℕ
⊢ k ! * choose (n + k) k = k ! * (ascFactorial n k / k !)
[PROOFSTEP]
rw [← ascFactorial_eq_factorial_mul_choose]
[GOAL]
n k : ℕ
⊢ ascFactorial n k = k ! * (ascFactorial n k / k !)
[PROOFSTEP]
exact (Nat.mul_div_cancel' <| factorial_dvd_ascFactorial _ _).symm
[GOAL]
n k : ℕ
⊢ descFactorial n k = k ! * choose n k
[PROOFSTEP]
obtain h | h := Nat.lt_or_ge n k
[GOAL]
case inl
n k : ℕ
h : n < k
⊢ descFactorial n k = k ! * choose n k
[PROOFSTEP]
rw [descFactorial_eq_zero_iff_lt.2 h, choose_eq_zero_of_lt h, mul_zero]
[GOAL]
case inr
n k : ℕ
h : n ≥ k
⊢ descFactorial n k = k ! * choose n k
[PROOFSTEP]
rw [mul_comm]
[GOAL]
case inr
n k : ℕ
h : n ≥ k
⊢ descFactorial n k = choose n k * k !
[PROOFSTEP]
apply mul_right_cancel₀ (factorial_ne_zero (n - k))
[GOAL]
case inr
n k : ℕ
h : n ≥ k
⊢ descFactorial n k * (n - k)! = choose n k * k ! * (n - k)!
[PROOFSTEP]
rw [choose_mul_factorial_mul_factorial h, ← factorial_mul_descFactorial h, mul_comm]
[GOAL]
n k : ℕ
⊢ choose n k = descFactorial n k / k !
[PROOFSTEP]
apply mul_left_cancel₀ (factorial_ne_zero k)
[GOAL]
n k : ℕ
⊢ k ! * choose n k = k ! * (descFactorial n k / k !)
[PROOFSTEP]
rw [← descFactorial_eq_factorial_mul_choose]
[GOAL]
n k : ℕ
⊢ descFactorial n k = k ! * (descFactorial n k / k !)
[PROOFSTEP]
exact (Nat.mul_div_cancel' <| factorial_dvd_descFactorial _ _).symm
[GOAL]
r n : ℕ
h : r < n / 2
⊢ choose n r ≤ choose n (r + 1)
[PROOFSTEP]
refine' le_of_mul_le_mul_right _ (lt_tsub_iff_left.mpr (lt_of_lt_of_le h (n.div_le_self 2)))
[GOAL]
r n : ℕ
h : r < n / 2
⊢ choose n r * (n - r) ≤ choose n (r + 1) * (n - r)
[PROOFSTEP]
rw [← choose_succ_right_eq]
[GOAL]
r n : ℕ
h : r < n / 2
⊢ choose n (r + 1) * (r + 1) ≤ choose n (r + 1) * (n - r)
[PROOFSTEP]
apply Nat.mul_le_mul_left
[GOAL]
case h
r n : ℕ
h : r < n / 2
⊢ r + 1 ≤ n - r
[PROOFSTEP]
rw [← Nat.lt_iff_add_one_le, lt_tsub_iff_left, ← mul_two]
[GOAL]
case h
r n : ℕ
h : r < n / 2
⊢ r * 2 < n
[PROOFSTEP]
exact lt_of_lt_of_le (mul_lt_mul_of_pos_right h zero_lt_two) (n.div_mul_le_self 2)
[GOAL]
r n : ℕ
⊢ choose n r ≤ choose n (n / 2)
[PROOFSTEP]
cases' le_or_gt r n with b b
[GOAL]
case inl
r n : ℕ
b : r ≤ n
⊢ choose n r ≤ choose n (n / 2)
[PROOFSTEP]
cases' le_or_lt r (n / 2) with a h
[GOAL]
case inl.inl
r n : ℕ
b : r ≤ n
a : r ≤ n / 2
⊢ choose n r ≤ choose n (n / 2)
[PROOFSTEP]
apply choose_le_middle_of_le_half_left a
[GOAL]
case inl.inr
r n : ℕ
b : r ≤ n
h : n / 2 < r
⊢ choose n r ≤ choose n (n / 2)
[PROOFSTEP]
rw [← choose_symm b]
[GOAL]
case inl.inr
r n : ℕ
b : r ≤ n
h : n / 2 < r
⊢ choose n (n - r) ≤ choose n (n / 2)
[PROOFSTEP]
apply choose_le_middle_of_le_half_left
[GOAL]
case inl.inr.hr
r n : ℕ
b : r ≤ n
h : n / 2 < r
⊢ n - r ≤ n / 2
[PROOFSTEP]
rw [div_lt_iff_lt_mul' zero_lt_two] at h
[GOAL]
case inl.inr.hr
r n : ℕ
b : r ≤ n
h : n < r * 2
⊢ n - r ≤ n / 2
[PROOFSTEP]
rw [le_div_iff_mul_le' zero_lt_two, tsub_mul, tsub_le_iff_tsub_le, mul_two, add_tsub_cancel_right]
[GOAL]
case inl.inr.hr
r n : ℕ
b : r ≤ n
h : n < r * 2
⊢ n ≤ r * 2
[PROOFSTEP]
exact le_of_lt h
[GOAL]
case inr
r n : ℕ
b : r > n
⊢ choose n r ≤ choose n (n / 2)
[PROOFSTEP]
rw [choose_eq_zero_of_lt b]
[GOAL]
case inr
r n : ℕ
b : r > n
⊢ 0 ≤ choose n (n / 2)
[PROOFSTEP]
apply zero_le
[GOAL]
a c : ℕ
⊢ choose a c ≤ choose (succ a) c
[PROOFSTEP]
cases c
[GOAL]
case zero
a : ℕ
⊢ choose a zero ≤ choose (succ a) zero
[PROOFSTEP]
simp [Nat.choose_succ_succ]
[GOAL]
case succ
a n✝ : ℕ
⊢ choose a (succ n✝) ≤ choose (succ a) (succ n✝)
[PROOFSTEP]
simp [Nat.choose_succ_succ]
[GOAL]
a b c : ℕ
⊢ choose a c ≤ choose (a + b) c
[PROOFSTEP]
induction' b with b_n b_ih
[GOAL]
case zero
a c : ℕ
⊢ choose a c ≤ choose (a + zero) c
[PROOFSTEP]
simp
[GOAL]
case succ
a c b_n : ℕ
b_ih : choose a c ≤ choose (a + b_n) c
⊢ choose a c ≤ choose (a + succ b_n) c
[PROOFSTEP]
exact le_trans b_ih (choose_le_succ (a + b_n) c)
[GOAL]
n : ℕ
⊢ multichoose n 0 = 1
[PROOFSTEP]
cases n
[GOAL]
case zero
⊢ multichoose zero 0 = 1
[PROOFSTEP]
simp [multichoose]
[GOAL]
case succ
n✝ : ℕ
⊢ multichoose (succ n✝) 0 = 1
[PROOFSTEP]
simp [multichoose]
[GOAL]
k : ℕ
⊢ multichoose 0 (k + 1) = 0
[PROOFSTEP]
simp [multichoose]
[GOAL]
n k : ℕ
⊢ multichoose (n + 1) (k + 1) = multichoose n (k + 1) + multichoose (n + 1) k
[PROOFSTEP]
simp [multichoose]
[GOAL]
k : ℕ
⊢ multichoose 1 k = 1
[PROOFSTEP]
induction' k with k IH
[GOAL]
case zero
⊢ multichoose 1 zero = 1
[PROOFSTEP]
simp
[GOAL]
case succ
k : ℕ
IH : multichoose 1 k = 1
⊢ multichoose 1 (succ k) = 1
[PROOFSTEP]
simp [multichoose_succ_succ 0 k, IH]
[GOAL]
k : ℕ
⊢ multichoose 2 k = k + 1
[PROOFSTEP]
induction' k with k IH
[GOAL]
case zero
⊢ multichoose 2 zero = zero + 1
[PROOFSTEP]
simp
[GOAL]
case succ
k : ℕ
IH : multichoose 2 k = k + 1
⊢ multichoose 2 (succ k) = succ k + 1
[PROOFSTEP]
rw [multichoose, IH]
[GOAL]
case succ
k : ℕ
IH : multichoose 2 k = k + 1
⊢ multichoose 1 (k + 1) + (k + 1) = succ k + 1
[PROOFSTEP]
simp [add_comm, succ_eq_add_one]
[GOAL]
n : ℕ
⊢ multichoose n 1 = n
[PROOFSTEP]
induction' n with n IH
[GOAL]
case zero
⊢ multichoose zero 1 = zero
[PROOFSTEP]
simp
[GOAL]
case succ
n : ℕ
IH : multichoose n 1 = n
⊢ multichoose (succ n) 1 = succ n
[PROOFSTEP]
simp [multichoose_succ_succ n 0, IH]
[GOAL]
x✝ : ℕ
⊢ multichoose x✝ 0 = choose (x✝ + 0 - 1) 0
[PROOFSTEP]
simp
[GOAL]
k : ℕ
⊢ multichoose 0 (k + 1) = choose (0 + (k + 1) - 1) (k + 1)
[PROOFSTEP]
simp
[GOAL]
n k : ℕ
⊢ multichoose (n + 1) (k + 1) = choose (n + 1 + (k + 1) - 1) (k + 1)
[PROOFSTEP]
have : n + (k + 1) < (n + 1) + (k + 1) := add_lt_add_right (Nat.lt_succ_self _) _
[GOAL]
n k : ℕ
this : n + (k + 1) < n + 1 + (k + 1)
⊢ multichoose (n + 1) (k + 1) = choose (n + 1 + (k + 1) - 1) (k + 1)
[PROOFSTEP]
have : (n + 1) + k < (n + 1) + (k + 1) := add_lt_add_left (Nat.lt_succ_self _) _
[GOAL]
n k : ℕ
this✝ : n + (k + 1) < n + 1 + (k + 1)
this : n + 1 + k < n + 1 + (k + 1)
⊢ multichoose (n + 1) (k + 1) = choose (n + 1 + (k + 1) - 1) (k + 1)
[PROOFSTEP]
erw [multichoose_succ_succ, add_comm, Nat.succ_add_sub_one, ← add_assoc, Nat.choose_succ_succ]
[GOAL]
n k : ℕ
this✝ : n + (k + 1) < n + 1 + (k + 1)
this : n + 1 + k < n + 1 + (k + 1)
⊢ multichoose (n + 1) k + multichoose n (k + 1) = choose (n + k) k + choose (n + k) (succ k)
[PROOFSTEP]
simp [multichoose_eq n (k + 1), multichoose_eq (n + 1) k]
[GOAL]
n k : ℕ
x✝ :
  ∀ (y : (_ : ℕ) ×' ℕ),
    (invImage (fun a => PSigma.casesOn a fun a snd => a + snd) instWellFoundedRelation).1 y
        { fst := succ n, snd := succ k } →
      multichoose y.1 y.2 = choose (y.1 + y.2 - 1) y.2
this✝ : n + (k + 1) < n + 1 + (k + 1)
this : n + 1 + k < n + 1 + (k + 1)
⊢ (invImage (fun a => PSigma.casesOn a fun a snd => a + snd) instWellFoundedRelation).1 { fst := n + 1, snd := k }
    { fst := succ n, snd := succ k }
[PROOFSTEP]
{assumption
}
[GOAL]
n k : ℕ
x✝ :
  ∀ (y : (_ : ℕ) ×' ℕ),
    (invImage (fun a => PSigma.casesOn a fun a snd => a + snd) instWellFoundedRelation).1 y
        { fst := succ n, snd := succ k } →
      multichoose y.1 y.2 = choose (y.1 + y.2 - 1) y.2
this✝ : n + (k + 1) < n + 1 + (k + 1)
this : n + 1 + k < n + 1 + (k + 1)
⊢ (invImage (fun a => PSigma.casesOn a fun a snd => a + snd) instWellFoundedRelation).1 { fst := n + 1, snd := k }
    { fst := succ n, snd := succ k }
[PROOFSTEP]
assumption
[GOAL]
n k : ℕ
x✝ :
  ∀ (y : (_ : ℕ) ×' ℕ),
    (invImage (fun a => PSigma.casesOn a fun a snd => a + snd) instWellFoundedRelation).1 y
        { fst := succ n, snd := succ k } →
      multichoose y.1 y.2 = choose (y.1 + y.2 - 1) y.2
this✝ : n + (k + 1) < n + 1 + (k + 1)
this : n + 1 + k < n + 1 + (k + 1)
⊢ (invImage (fun a => PSigma.casesOn a fun a snd => a + snd) instWellFoundedRelation).1 { fst := n, snd := k + 1 }
    { fst := succ n, snd := succ k }
[PROOFSTEP]
{assumption
}
[GOAL]
n k : ℕ
x✝ :
  ∀ (y : (_ : ℕ) ×' ℕ),
    (invImage (fun a => PSigma.casesOn a fun a snd => a + snd) instWellFoundedRelation).1 y
        { fst := succ n, snd := succ k } →
      multichoose y.1 y.2 = choose (y.1 + y.2 - 1) y.2
this✝ : n + (k + 1) < n + 1 + (k + 1)
this : n + 1 + k < n + 1 + (k + 1)
⊢ (invImage (fun a => PSigma.casesOn a fun a snd => a + snd) instWellFoundedRelation).1 { fst := n, snd := k + 1 }
    { fst := succ n, snd := succ k }
[PROOFSTEP]
assumption