Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 877f2e7

Browse files
committed
refactor(linear_algebra/ray): redefine same_ray to allow zero vectors (#12618)
In a strictly convex space, the new definition is equivalent to the fact that the triangle inequality becomes an equality. The old definition was only used for nonzero vectors in `mathlib`. Also make the definition of `ray_vector` semireducible so that `ray_vector.setoid` can be an instance.
1 parent e547058 commit 877f2e7

File tree

4 files changed

+395
-238
lines changed

4 files changed

+395
-238
lines changed

src/analysis/convex/basic.lean

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import algebra.order.invertible
77
import algebra.order.module
88
import linear_algebra.affine_space.midpoint
99
import linear_algebra.affine_space.affine_subspace
10+
import linear_algebra.ray
1011

1112
/-!
1213
# Convex sets and functions in vector spaces
@@ -58,6 +59,15 @@ def open_segment (x y : E) : set E :=
5859

5960
localized "notation `[` x ` -[` 𝕜 `] ` y `]` := segment 𝕜 x y" in convex
6061

62+
lemma segment_eq_image₂ (x y : E) :
63+
[x -[𝕜] y] = (λ p : 𝕜 × 𝕜, p.1 • x + p.2 • y) '' {p | 0 ≤ p.10 ≤ p.2 ∧ p.1 + p.2 = 1} :=
64+
by simp only [segment, image, prod.exists, mem_set_of_eq, exists_prop, and_assoc]
65+
66+
lemma open_segment_eq_image₂ (x y : E) :
67+
open_segment 𝕜 x y =
68+
(λ p : 𝕜 × 𝕜, p.1 • x + p.2 • y) '' {p | 0 < p.10 < p.2 ∧ p.1 + p.2 = 1} :=
69+
by simp only [open_segment, image, prod.exists, mem_set_of_eq, exists_prop, and_assoc]
70+
6171
lemma segment_symm (x y : E) : [x -[𝕜] y] = [y -[𝕜] x] :=
6272
set.ext $ λ z,
6373
⟨λ ⟨a, b, ha, hb, hab, H⟩, ⟨b, a, hb, ha, (add_comm _ _).trans hab, (add_comm _ _).trans H⟩,
@@ -101,7 +111,7 @@ end mul_action_with_zero
101111
section module
102112
variables (𝕜) [module 𝕜 E]
103113

104-
lemma segment_same (x : E) : [x -[𝕜] x] = {x} :=
114+
@[simp] lemma segment_same (x : E) : [x -[𝕜] x] = {x} :=
105115
set.ext $ λ z, ⟨λ ⟨a, b, ha, hb, hab, hz⟩,
106116
by simpa only [(add_smul _ _ _).symm, mem_singleton_iff, hab, one_smul, eq_comm] using hz,
107117
λ h, mem_singleton_iff.1 h ▸ left_mem_segment 𝕜 z z⟩
@@ -177,15 +187,6 @@ set.ext $ λ z,
177187
⟨b, ⟨hb, hab ▸ lt_add_of_pos_left _ ha⟩, hab ▸ hz ▸ by simp only [add_sub_cancel]⟩,
178188
λ ⟨θ, ⟨hθ₀, hθ₁⟩, hz⟩, ⟨1 - θ, θ, sub_pos.2 hθ₁, hθ₀, sub_add_cancel _ _, hz⟩⟩
179189

180-
lemma segment_eq_image₂ (x y : E) :
181-
[x -[𝕜] y] = (λ p : 𝕜 × 𝕜, p.1 • x + p.2 • y) '' {p | 0 ≤ p.10 ≤ p.2 ∧ p.1 + p.2 = 1} :=
182-
by simp only [segment, image, prod.exists, mem_set_of_eq, exists_prop, and_assoc]
183-
184-
lemma open_segment_eq_image₂ (x y : E) :
185-
open_segment 𝕜 x y =
186-
(λ p : 𝕜 × 𝕜, p.1 • x + p.2 • y) '' {p | 0 < p.10 < p.2 ∧ p.1 + p.2 = 1} :=
187-
by simp only [open_segment, image, prod.exists, mem_set_of_eq, exists_prop, and_assoc]
188-
189190
lemma segment_eq_image' (x y : E) :
190191
[x -[𝕜] y] = (λ (θ : 𝕜), x + θ • (y - x)) '' Icc (0 : 𝕜) 1 :=
191192
by { convert segment_eq_image 𝕜 x y, ext θ, simp only [smul_sub, sub_smul, one_smul], abel }
@@ -242,6 +243,15 @@ open_segment_translate_preimage 𝕜 a b c ▸ image_preimage_eq _ $ add_left_su
242243
end add_comm_group
243244
end ordered_ring
244245

246+
lemma same_ray_of_mem_segment [ordered_comm_ring 𝕜] [add_comm_group E] [module 𝕜 E]
247+
{x y z : E} (h : x ∈ [y -[𝕜] z]) : same_ray 𝕜 (x - y) (z - x) :=
248+
begin
249+
rw segment_eq_image' at h,
250+
rcases h with ⟨θ, ⟨hθ₀, hθ₁⟩, rfl⟩,
251+
simpa only [add_sub_cancel', ← sub_sub, sub_smul, one_smul]
252+
using (same_ray_nonneg_smul_left (z - y) hθ₀).nonneg_smul_right (sub_nonneg.2 hθ₁)
253+
end
254+
245255
section linear_ordered_ring
246256
variables [linear_ordered_ring 𝕜]
247257

@@ -278,6 +288,17 @@ variables [linear_ordered_field 𝕜]
278288
section add_comm_group
279289
variables [add_comm_group E] [add_comm_group F] [module 𝕜 E] [module 𝕜 F]
280290

291+
lemma mem_segment_iff_same_ray {x y z : E} :
292+
x ∈ [y -[𝕜] z] ↔ same_ray 𝕜 (x - y) (z - x) :=
293+
begin
294+
refine ⟨same_ray_of_mem_segment, λ h, _⟩,
295+
rcases h.exists_eq_smul_add with ⟨a, b, ha, hb, hab, hxy, hzx⟩,
296+
rw [add_comm, sub_add_sub_cancel] at hxy hzx,
297+
rw [← mem_segment_translate _ (-x), neg_add_self],
298+
refine ⟨b, a, hb, ha, add_comm a b ▸ hab, _⟩,
299+
rw [← sub_eq_neg_add, ← neg_sub, hxy, ← sub_eq_neg_add, hzx, smul_neg, smul_comm, neg_add_self]
300+
end
301+
281302
lemma mem_segment_iff_div {x y z : E} : x ∈ [y -[𝕜] z] ↔
282303
∃ a b : 𝕜, 0 ≤ a ∧ 0 ≤ b ∧ 0 < a + b ∧ (a / (a + b)) • y + (b / (a + b)) • z = x :=
283304
begin

src/analysis/normed_space/ray.lean

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/-
2+
Copyright (c) 2022 Yury Kudryashov. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Yury Kudryashov
5+
-/
6+
import linear_algebra.ray
7+
import analysis.normed_space.basic
8+
9+
/-!
10+
# Rays in a real normed vector space
11+
12+
In this file we prove some lemmas about the `same_ray` predicate in case of a real normed space. In
13+
this case, for two vectors `x y` in the same ray, the norm of their sum is equal to the sum of their
14+
norms and `∥y∥ • x = ∥x∥ • y`.
15+
-/
16+
17+
variables {E : Type*} [semi_normed_group E] [normed_space ℝ E]
18+
{F : Type*} [normed_group F] [normed_space ℝ F]
19+
20+
namespace same_ray
21+
22+
variables {x y : E}
23+
24+
/-- If `x` and `y` are on the same ray, then the triangle inequality becomes the equality: the norm
25+
of `x + y` is the sum of the norms of `x` and `y`. The converse is true for a strictly convex
26+
space. -/
27+
lemma norm_add (h : same_ray ℝ x y) : ∥x + y∥ = ∥x∥ + ∥y∥ :=
28+
begin
29+
rcases h.exists_eq_smul with ⟨u, a, b, ha, hb, -, rfl, rfl⟩,
30+
rw [← add_smul, norm_smul_of_nonneg (add_nonneg ha hb), norm_smul_of_nonneg ha,
31+
norm_smul_of_nonneg hb, add_mul]
32+
end
33+
34+
lemma norm_sub (h : same_ray ℝ x y) : ∥x - y∥ = |∥x∥ - ∥y∥| :=
35+
begin
36+
rcases h.exists_eq_smul with ⟨u, a, b, ha, hb, -, rfl, rfl⟩,
37+
wlog hab : b ≤ a := le_total b a using [a b, b a] tactic.skip,
38+
{ rw ← sub_nonneg at hab,
39+
rw [← sub_smul, norm_smul_of_nonneg hab, norm_smul_of_nonneg ha,
40+
norm_smul_of_nonneg hb, ← sub_mul, abs_of_nonneg (mul_nonneg hab (norm_nonneg _))] },
41+
{ intros ha hb hab,
42+
rw [norm_sub_rev, this hb ha hab.symm, abs_sub_comm] }
43+
end
44+
45+
lemma norm_smul_eq (h : same_ray ℝ x y) : ∥x∥ • y = ∥y∥ • x :=
46+
begin
47+
rcases h.exists_eq_smul with ⟨u, a, b, ha, hb, -, rfl, rfl⟩,
48+
simp only [norm_smul_of_nonneg, *, mul_smul, smul_comm (∥u∥)],
49+
apply smul_comm
50+
end
51+
52+
end same_ray
53+
54+
lemma same_ray_iff_norm_smul_eq {x y : F} :
55+
same_ray ℝ x y ↔ ∥x∥ • y = ∥y∥ • x :=
56+
⟨same_ray.norm_smul_eq, λ h, or_iff_not_imp_left.2 $ λ hx, or_iff_not_imp_left.2 $ λ hy,
57+
⟨∥y∥, ∥x∥, norm_pos_iff.2 hy, norm_pos_iff.2 hx, h.symm⟩⟩
58+
59+
/-- Two nonzero vectors `x y` in a real normed space are on the same ray if and only if the unit
60+
vectors `∥x∥⁻¹ • x` and `∥y∥⁻¹ • y` are equal. -/
61+
lemma same_ray_iff_inv_norm_smul_eq_of_ne {x y : F} (hx : x ≠ 0) (hy : y ≠ 0) :
62+
same_ray ℝ x y ↔ ∥x∥⁻¹ • x = ∥y∥⁻¹ • y :=
63+
begin
64+
have : ∥x∥⁻¹ * ∥y∥⁻¹ ≠ 0, by simp *,
65+
rw [same_ray_iff_norm_smul_eq, ← smul_right_inj this]; try { apply_instance },
66+
rw [smul_comm, mul_smul, mul_smul, smul_inv_smul₀, inv_smul_smul₀, eq_comm],
67+
exacts [norm_ne_zero_iff.2 hy, norm_ne_zero_iff.2 hx]
68+
end
69+
70+
alias same_ray_iff_inv_norm_smul_eq_of_ne ↔ same_ray.inv_norm_smul_eq _
71+
72+
/-- Two vectors `x y` in a real normed space are on the ray if and only if one of them is zero or
73+
the unit vectors `∥x∥⁻¹ • x` and `∥y∥⁻¹ • y` are equal. -/
74+
lemma same_ray_iff_inv_norm_smul_eq {x y : F} :
75+
same_ray ℝ x y ↔ x = 0 ∨ y = 0 ∨ ∥x∥⁻¹ • x = ∥y∥⁻¹ • y :=
76+
begin
77+
rcases eq_or_ne x 0 with rfl|hx, { simp [same_ray.zero_left] },
78+
rcases eq_or_ne y 0 with rfl|hy, { simp [same_ray.zero_right] },
79+
simp only [same_ray_iff_inv_norm_smul_eq_of_ne hx hy, *, false_or]
80+
end

src/linear_algebra/orientation.lean

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,40 +42,36 @@ variables (M : Type*) [add_comm_monoid M] [module R M]
4242
variables {N : Type*} [add_comm_monoid N] [module R N]
4343
variables (ι : Type*) [decidable_eq ι]
4444

45-
local attribute [instance] ray_vector.same_ray_setoid
46-
4745
/-- An orientation of a module, intended to be used when `ι` is a `fintype` with the same
4846
cardinality as a basis. -/
49-
abbreviation orientation [nontrivial R] := module.ray R (alternating_map R M R ι)
47+
abbreviation orientation := module.ray R (alternating_map R M R ι)
5048

5149
/-- A type class fixing an orientation of a module. -/
52-
class module.oriented [nontrivial R] :=
50+
class module.oriented :=
5351
(positive_orientation : orientation R M ι)
5452

5553
variables {R M}
5654

5755
/-- An equivalence between modules implies an equivalence between orientations. -/
58-
def orientation.map [nontrivial R] (e : M ≃ₗ[R] N) : orientation R M ι ≃ orientation R N ι :=
56+
def orientation.map (e : M ≃ₗ[R] N) : orientation R M ι ≃ orientation R N ι :=
5957
module.ray.map $ alternating_map.dom_lcongr R R ι R e
6058

61-
@[simp] lemma orientation.map_apply [nontrivial R] (e : M ≃ₗ[R] N) (v : alternating_map R M R ι)
59+
@[simp] lemma orientation.map_apply (e : M ≃ₗ[R] N) (v : alternating_map R M R ι)
6260
(hv : v ≠ 0) :
6361
orientation.map ι e (ray_of_ne_zero _ v hv) = ray_of_ne_zero _ (v.comp_linear_map e.symm)
6462
(mt (v.comp_linear_equiv_eq_zero_iff e.symm).mp hv) := rfl
6563

66-
@[simp] lemma orientation.map_refl [nontrivial R] :
64+
@[simp] lemma orientation.map_refl :
6765
(orientation.map ι $ linear_equiv.refl R M) = equiv.refl _ :=
6866
by rw [orientation.map, alternating_map.dom_lcongr_refl, module.ray.map_refl]
6967

70-
@[simp] lemma orientation.map_symm [nontrivial R] (e : M ≃ₗ[R] N) :
68+
@[simp] lemma orientation.map_symm (e : M ≃ₗ[R] N) :
7169
(orientation.map ι e).symm = orientation.map ι e.symm := rfl
7270

7371
end ordered_comm_semiring
7472

7573
section ordered_comm_ring
7674

77-
local attribute [instance] ray_vector.same_ray_setoid
78-
7975
variables {R : Type*} [ordered_comm_ring R]
8076
variables {M N : Type*} [add_comm_group M] [add_comm_group N] [module R M] [module R N]
8177

@@ -93,7 +89,7 @@ by simp_rw [basis.orientation, orientation.map_apply, basis.det_map']
9389

9490
/-- The value of `orientation.map` when the index type has the cardinality of a basis, in terms
9591
of `f.det`. -/
96-
lemma map_orientation_eq_det_inv_smul [nontrivial R] [is_domain R] (e : basis ι R M)
92+
lemma map_orientation_eq_det_inv_smul [is_domain R] (e : basis ι R M)
9793
(x : orientation R M ι) (f : M ≃ₗ[R] M) : orientation.map ι f x = (f.det)⁻¹ • x :=
9894
begin
9995
induction x using module.ray.ind with g hg,
@@ -132,19 +128,19 @@ variables [fintype ι]
132128
with respect to the other is positive. -/
133129
lemma orientation_eq_iff_det_pos (e₁ e₂ : basis ι R M) :
134130
e₁.orientation = e₂.orientation ↔ 0 < e₁.det e₂ :=
135-
by rw [basis.orientation, basis.orientation, ray_eq_iff,
136-
e₁.det.eq_smul_basis_det e₂, alternating_map.smul_apply, basis.det_self, smul_eq_mul,
137-
mul_one, same_ray_smul_left_iff e₂.det_ne_zero (_ : R)]
131+
calc e₁.orientation = e₂.orientation ↔ same_ray R e₁.det e₂.det : ray_eq_iff _ _
132+
... ↔ same_ray R (e₁.det e₂ • e₂.det) e₂.det : by rw [← e₁.det.eq_smul_basis_det e₂]
133+
... ↔ 0 < e₁.det e₂ : same_ray_smul_left_iff_of_ne e₂.det_ne_zero (e₁.is_unit_det e₂).ne_zero
138134

139135
/-- Given a basis, any orientation equals the orientation given by that basis or its negation. -/
140136
lemma orientation_eq_or_eq_neg (e : basis ι R M) (x : orientation R M ι) :
141137
x = e.orientation ∨ x = -e.orientation :=
142138
begin
143139
induction x using module.ray.ind with x hx,
144-
rw [basis.orientation, ray_eq_iff, ←ray_neg, ray_eq_iff, x.eq_smul_basis_det e,
145-
same_ray_neg_smul_left_iff e.det_ne_zero (_ : R), same_ray_smul_left_iff e.det_ne_zero (_ : R),
146-
lt_or_lt_iff_ne, ne_comm, alternating_map.map_basis_ne_zero_iff],
147-
exact hx
140+
rw ← x.map_basis_ne_zero_iff e at hx,
141+
rwa [basis.orientation, ray_eq_iff, neg_ray_of_ne_zero, ray_eq_iff, x.eq_smul_basis_det e,
142+
same_ray_neg_smul_left_iff_of_ne e.det_ne_zero hx,
143+
same_ray_smul_left_iff_of_ne e.det_ne_zero hx, lt_or_lt_iff_ne, ne_comm]
148144
end
149145

150146
/-- Given a basis, an orientation equals the negation of that given by that basis if and only

0 commit comments

Comments
 (0)