Skip to content

Commit 4fe0086

Browse files
committed
feat(UpperHalfPlane): add positivity extensions (#9545)
1 parent 9a8dc7a commit 4fe0086

File tree

2 files changed

+54
-28
lines changed

2 files changed

+54
-28
lines changed

Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,40 @@ theorem ne_zero (z : ℍ) : (z : ℂ) ≠ 0 :=
139139
mt (congr_arg Complex.im) z.im_ne_zero
140140
#align upper_half_plane.ne_zero UpperHalfPlane.ne_zero
141141

142+
end UpperHalfPlane
143+
144+
namespace Mathlib.Meta.Positivity
145+
146+
open Lean Meta Qq
147+
148+
/-- Extension for the `positivity` tactic: `UpperHalfPlane.im`. -/
149+
@[positivity UpperHalfPlane.im _]
150+
def evalUpperHalfPlaneIm : PositivityExt where eval {u α} _zα _pα e := do
151+
-- TODO: can't merge the `match`es without lean4#3060
152+
match u with
153+
| 0 => match α, e with
154+
| ~q(ℝ), ~q(UpperHalfPlane.im $a) =>
155+
assertInstancesCommute
156+
pure (.positive q(@UpperHalfPlane.im_pos $a))
157+
| _, _ => throwError "not UpperHalfPlane.im"
158+
| _ => throwError "not UpperHalfPlane.im"
159+
160+
/-- Extension for the `positivity` tactic: `UpperHalfPlane.coe`. -/
161+
@[positivity UpperHalfPlane.coe _]
162+
def evalUpperHalfPlaneCoe : PositivityExt where eval {u α} _zα _pα e := do
163+
-- TODO: can't merge the `match`es without lean4#3060
164+
match u with
165+
| 0 => match α, e with
166+
| ~q(ℂ), ~q(UpperHalfPlane.coe $a) =>
167+
assertInstancesCommute
168+
pure (.nonzero q(@UpperHalfPlane.ne_zero $a))
169+
| _, _ => throwError "not UpperHalfPlane.coe"
170+
| _ => throwError "not UpperHalfPlane.coe"
171+
172+
end Mathlib.Meta.Positivity
173+
174+
namespace UpperHalfPlane
175+
142176
theorem normSq_pos (z : ℍ) : 0 < Complex.normSq (z : ℂ) := by
143177
rw [Complex.normSq_pos]; exact z.ne_zero
144178
#align upper_half_plane.norm_sq_pos UpperHalfPlane.normSq_pos

Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,18 @@ theorem sinh_half_dist (z w : ℍ) :
4949

5050
theorem cosh_half_dist (z w : ℍ) :
5151
cosh (dist z w / 2) = dist (z : ℂ) (conj (w : ℂ)) / (2 * sqrt (z.im * w.im)) := by
52-
have H₁ : (2 ^ 2 : ℝ) = 4 := by norm_num1
53-
have H₂ : 0 < z.im * w.im := mul_pos z.im_pos w.im_pos
54-
have H₃ : 0 < 2 * sqrt (z.im * w.im) := mul_pos two_pos (sqrt_pos.2 H₂)
55-
rw [← sq_eq_sq (cosh_pos _).le (div_nonneg dist_nonneg H₃.le), cosh_sq', sinh_half_dist, div_pow,
56-
div_pow, one_add_div (pow_ne_zero 2 H₃.ne'), mul_pow, sq_sqrt H₂.le, H₁]
57-
congr 1
58-
simp only [Complex.dist_eq, Complex.sq_abs, Complex.normSq_sub, Complex.normSq_conj,
59-
Complex.conj_conj, Complex.mul_re, Complex.conj_re, Complex.conj_im, coe_im]
60-
ring
52+
rw [← sq_eq_sq, cosh_sq', sinh_half_dist, div_pow, div_pow, one_add_div, mul_pow, sq_sqrt]
53+
· congr 1
54+
simp only [Complex.dist_eq, Complex.sq_abs, Complex.normSq_sub, Complex.normSq_conj,
55+
Complex.conj_conj, Complex.mul_re, Complex.conj_re, Complex.conj_im, coe_im]
56+
ring
57+
all_goals positivity
6158
#align upper_half_plane.cosh_half_dist UpperHalfPlane.cosh_half_dist
6259

6360
theorem tanh_half_dist (z w : ℍ) :
6461
tanh (dist z w / 2) = dist (z : ℂ) w / dist (z : ℂ) (conj ↑w) := by
6562
rw [tanh_eq_sinh_div_cosh, sinh_half_dist, cosh_half_dist, div_div_div_comm, div_self, div_one]
66-
exact (mul_pos (zero_lt_two' ℝ) (sqrt_pos.2 <| mul_pos z.im_pos w.im_pos)).ne'
63+
positivity
6764
#align upper_half_plane.tanh_half_dist UpperHalfPlane.tanh_half_dist
6865

6966
theorem exp_half_dist (z w : ℍ) :
@@ -73,8 +70,7 @@ theorem exp_half_dist (z w : ℍ) :
7370

7471
theorem cosh_dist (z w : ℍ) : cosh (dist z w) = 1 + dist (z : ℂ) w ^ 2 / (2 * z.im * w.im) := by
7572
rw [dist_eq, cosh_two_mul, cosh_sq', add_assoc, ← two_mul, sinh_arsinh, div_pow, mul_pow,
76-
sq_sqrt (mul_pos z.im_pos w.im_pos).le, sq (2 : ℝ), mul_assoc, ← mul_div_assoc, mul_assoc,
77-
mul_div_mul_left _ _ (two_ne_zero' ℝ)]
73+
sq_sqrt, sq (2 : ℝ), mul_assoc, ← mul_div_assoc, mul_assoc, mul_div_mul_left] <;> positivity
7874
#align upper_half_plane.cosh_dist UpperHalfPlane.cosh_dist
7975

8076
theorem sinh_half_dist_add_dist (a b c : ℍ) : sinh ((dist a b + dist b c) / 2) =
@@ -106,23 +102,21 @@ theorem dist_eq_iff_eq_sq_sinh (hr : 0 ≤ r) :
106102
dist z w = r ↔ dist (z : ℂ) w ^ 2 / (4 * z.im * w.im) = sinh (r / 2) ^ 2 := by
107103
rw [dist_eq_iff_eq_sinh, ← sq_eq_sq, div_pow, mul_pow, sq_sqrt, mul_assoc]
108104
· norm_num
109-
· exact (mul_pos z.im_pos w.im_pos).le
110-
· exact div_nonneg dist_nonneg (mul_nonneg zero_le_two <| sqrt_nonneg _)
111-
· exact sinh_nonneg_iff.2 (div_nonneg hr zero_le_two)
105+
all_goals positivity
112106
#align upper_half_plane.dist_eq_iff_eq_sq_sinh UpperHalfPlane.dist_eq_iff_eq_sq_sinh
113107

114108
protected theorem dist_triangle (a b c : ℍ) : dist a c ≤ dist a b + dist b c := by
115109
rw [dist_le_iff_le_sinh, sinh_half_dist_add_dist, div_mul_eq_div_div _ _ (dist _ _), le_div_iff,
116110
div_mul_eq_mul_div]
117-
· exact div_le_div_of_le (mul_nonneg zero_le_two (sqrt_nonneg _))
118-
(EuclideanGeometry.mul_dist_le_mul_dist_add_mul_dist (a : ℂ) b c (conj (b : ℂ)))
111+
· gcongr
112+
exact EuclideanGeometry.mul_dist_le_mul_dist_add_mul_dist (a : ℂ) b c (conj (b : ℂ))
119113
· rw [dist_comm, dist_pos, Ne.def, Complex.conj_eq_iff_im]
120114
exact b.im_ne_zero
121115
#align upper_half_plane.dist_triangle UpperHalfPlane.dist_triangle
122116

123117
theorem dist_le_dist_coe_div_sqrt (z w : ℍ) : dist z w ≤ dist (z : ℂ) w / sqrt (z.im * w.im) := by
124118
rw [dist_le_iff_le_sinh, ← div_mul_eq_div_div_swap, self_le_sinh_iff]
125-
exact div_nonneg dist_nonneg (mul_nonneg zero_le_two (sqrt_nonneg _))
119+
positivity
126120
#align upper_half_plane.dist_le_dist_coe_div_sqrt UpperHalfPlane.dist_le_dist_coe_div_sqrt
127121

128122
/-- An auxiliary `MetricSpace` instance on the upper half-plane. This instance has bad projection
@@ -141,14 +135,13 @@ open Complex
141135

142136
theorem cosh_dist' (z w : ℍ) :
143137
Real.cosh (dist z w) = ((z.re - w.re) ^ 2 + z.im ^ 2 + w.im ^ 2) / (2 * z.im * w.im) := by
144-
have H : 0 < 2 * z.im * w.im := mul_pos (mul_pos two_pos z.im_pos) w.im_pos
145-
field_simp [cosh_dist, Complex.dist_eq, Complex.sq_abs, normSq_apply, H, H.ne']
138+
field_simp [cosh_dist, Complex.dist_eq, Complex.sq_abs, normSq_apply]
146139
ring
147140
#align upper_half_plane.cosh_dist' UpperHalfPlane.cosh_dist'
148141

149142
/-- Euclidean center of the circle with center `z` and radius `r` in the hyperbolic metric. -/
150143
def center (z : ℍ) (r : ℝ) : ℍ :=
151-
⟨⟨z.re, z.im * Real.cosh r⟩, mul_pos z.im_pos (cosh_pos _)
144+
⟨⟨z.re, z.im * Real.cosh r⟩, by positivity
152145
#align upper_half_plane.center UpperHalfPlane.center
153146

154147
@[simp]
@@ -168,7 +161,7 @@ theorem center_zero (z : ℍ) : center z 0 = z :=
168161

169162
theorem dist_coe_center_sq (z w : ℍ) (r : ℝ) : dist (z : ℂ) (w.center r) ^ 2 =
170163
2 * z.im * w.im * (Real.cosh (dist z w) - Real.cosh r) + (w.im * Real.sinh r) ^ 2 := by
171-
have H : 2 * z.im * w.im ≠ 0 := by apply_rules [mul_ne_zero, two_ne_zero, im_ne_zero]
164+
have H : 2 * z.im * w.im ≠ 0 := by positivity
172165
simp only [Complex.dist_eq, Complex.sq_abs, normSq_apply, coe_re, coe_im, center_re, center_im,
173166
cosh_dist', mul_div_cancel' _ H, sub_sq z.im, mul_pow, Real.cosh_sq, sub_re, sub_im, mul_sub, ←
174167
sq]
@@ -187,8 +180,8 @@ theorem cmp_dist_eq_cmp_dist_coe_center (z w : ℍ) (r : ℝ) :
187180
· trans Ordering.gt
188181
exacts [(hr₀.trans_le dist_nonneg).cmp_eq_gt,
189182
((mul_neg_of_pos_of_neg w.im_pos (sinh_neg_iff.2 hr₀)).trans_le dist_nonneg).cmp_eq_gt.symm]
190-
have hr₀' : 0 ≤ w.im * Real.sinh r := mul_nonneg w.im_pos.le (sinh_nonneg_iff.2 hr₀)
191-
have hzw₀ : 0 < 2 * z.im * w.im := mul_pos (mul_pos two_pos z.im_pos) w.im_pos
183+
have hr₀' : 0 ≤ w.im * Real.sinh r := by positivity
184+
have hzw₀ : 0 < 2 * z.im * w.im := by positivity
192185
simp only [← cosh_strictMonoOn.cmp_map_eq dist_nonneg hr₀, ←
193186
(pow_left_strictMonoOn two_ne_zero).cmp_map_eq dist_nonneg hr₀', dist_coe_center_sq]
194187
rw [← cmp_mul_pos_left hzw₀, ← cmp_sub_zero, ← mul_sub, ← cmp_add_right, zero_add]
@@ -235,14 +228,14 @@ theorem le_dist_iff_le_dist_coe_center :
235228
/-- For two points on the same vertical line, the distance is equal to the distance between the
236229
logarithms of their imaginary parts. -/
237230
nonrec theorem dist_of_re_eq (h : z.re = w.re) : dist z w = dist (log z.im) (log w.im) := by
238-
have h₀ : 0 < z.im / w.im := div_pos z.im_pos w.im_pos
231+
have h₀ : 0 < z.im / w.im := by positivity
239232
rw [dist_eq_iff_dist_coe_center_eq, Real.dist_eq, ← abs_sinh, ← log_div z.im_ne_zero w.im_ne_zero,
240233
sinh_log h₀, dist_of_re_eq, coe_im, coe_im, center_im, cosh_abs, cosh_log h₀, inv_div] <;>
241234
[skip; exact h]
242235
nth_rw 4 [← abs_of_pos w.im_pos]
243236
simp only [← _root_.abs_mul, coe_im, Real.dist_eq]
244237
congr 1
245-
field_simp [z.im_pos, w.im_pos, z.im_ne_zero, w.im_ne_zero]
238+
field_simp
246239
ring
247240
#align upper_half_plane.dist_of_re_eq UpperHalfPlane.dist_of_re_eq
248241

@@ -292,8 +285,7 @@ instance : MetricSpace ℍ :=
292285
metricSpaceAux.replaceTopology <| by
293286
refine' le_antisymm (continuous_id_iff_le.1 _) _
294287
· refine' (@continuous_iff_continuous_dist ℍ ℍ metricSpaceAux.toPseudoMetricSpace _ _).2 _
295-
have : ∀ x : ℍ × ℍ, 2 * Real.sqrt (x.1.im * x.2.im) ≠ 0 := fun x =>
296-
mul_ne_zero two_ne_zero (Real.sqrt_pos.2 <| mul_pos x.1.im_pos x.2.im_pos).ne'
288+
have : ∀ x : ℍ × ℍ, 2 * Real.sqrt (x.1.im * x.2.im) ≠ 0 := fun x => by positivity
297289
-- `continuity` fails to apply `Continuous.div`
298290
apply_rules [Continuous.div, Continuous.mul, continuous_const, Continuous.arsinh,
299291
Continuous.dist, continuous_coe.comp, continuous_fst, continuous_snd,

0 commit comments

Comments
 (0)