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

Commit 797177c

Browse files
jsm28urkud
andcommitted
feat(linear_algebra/affine_space): affine combinations of points (#2979)
Some basic definitions and lemmas related to affine combinations of points, in preparation for defining barycentric coordinates for use in geometry. This version for sums over a `fintype` is probably the most convenient for geometrical uses (where the type will be `fin 3` in the case of a triangle, or more generally `fin (n + 1)` for an n-simplex), but other use cases may find that `finset` or `finsupp` versions of these definitions are of use as well. The definition `weighted_vsub` is expected to be used with weights that sum to zero, and the definition `affine_combination` is expected to be used with weights that sum to 1, but such a hypothesis is only specified for lemmas that need it rather than for those definitions. I expect that most nontrivial geometric uses of barycentric coordinates will need to prove such a hypothesis at some point, but that it will still be more convenient not to need to pass it to all the definitions and trivial lemmas. Co-authored-by: Yury G. Kudryashov <urkud@urkud.name>
1 parent 77c5dfe commit 797177c

File tree

2 files changed

+199
-1
lines changed

2 files changed

+199
-1
lines changed

src/algebra/add_torsor.lean

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Authors: Joseph Myers, Yury Kudryashov.
55
-/
66
import algebra.group.prod
77
import algebra.group.type_tags
8+
import algebra.pi_instances
89
import data.equiv.basic
910

1011
/-!
@@ -268,6 +269,32 @@ instance : add_torsor (G × G') (P × P') :=
268269

269270
end prod
270271

272+
namespace pi
273+
274+
universes u v w
275+
variables {I : Type u} {fg : I → Type v} [∀ i, add_group (fg i)] {fp : I → Type w}
276+
277+
open add_action add_torsor
278+
279+
/-- A product of `add_torsor`s is an `add_torsor`. -/
280+
instance [T : ∀ i, add_torsor (fg i) (fp i)] : add_torsor (Π i, fg i) (Π i, fp i) :=
281+
{
282+
vadd := λ g p, λ i, g i +ᵥ p i,
283+
zero_vadd' := λ p, funext $ λ i, zero_vadd (fg i) (p i),
284+
vadd_assoc' := λ g₁ g₂ p, funext $ λ i, vadd_assoc (fg i) (g₁ i) (g₂ i) (p i),
285+
vsub := λ p₁ p₂, λ i, p₁ i -ᵥ p₂ i,
286+
nonempty := ⟨λ i, classical.choice (T i).nonempty⟩,
287+
vsub_vadd' := λ p₁ p₂, funext $ λ i, vsub_vadd (fg i) (p₁ i) (p₂ i),
288+
vadd_vsub' := λ g p, funext $ λ i, vadd_vsub (fg i) (g i) (p i),
289+
}
290+
291+
/-- Addition in a product of `add_torsor`s. -/
292+
@[simp] lemma vadd_apply [T : ∀ i, add_torsor (fg i) (fp i)] (x : Π i, fg i) (y : Π i, fp i)
293+
{i : I} : (x +ᵥ y) i = x i +ᵥ y i
294+
:= rfl
295+
296+
end pi
297+
271298
namespace equiv
272299

273300
variables (G : Type*) {P : Type*} [add_group G] [add_torsor G P]

src/linear_algebra/affine_space.lean

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import algebra.add_torsor
77
import linear_algebra.basis
88

99
noncomputable theory
10+
open_locale big_operators
1011

1112
/-!
1213
# Affine spaces
1314
1415
This file defines affine spaces (over modules) and subspaces, affine
15-
maps, and the affine span of a set of points.
16+
maps, affine combinations of points, and the affine span of a set of
17+
points.
1618
1719
## Implementation notes
1820
@@ -100,6 +102,158 @@ begin
100102
apply set.mem_of_mem_of_subset hp1p2 hp1p2s
101103
end
102104

105+
section combination
106+
107+
variables {k} {ι : Type*} [fintype ι]
108+
109+
/-- A weighted sum of the results of subtracting a base point from the
110+
given points. The main cases of interest are where the sum of the
111+
weights is 0, in which case the sum is independent of the choice of
112+
base point, and where the sum of the weights is 1, in which case the
113+
sum added to the base point is independent of the choice of base
114+
point. -/
115+
def weighted_vsub_of_point (w : ι → k) (p : ι → P) (b : P) : V := ∑ i, w i • (p i -ᵥ b)
116+
117+
/-- `weighted_vsub_of_point` as a linear map on the weights. -/
118+
def weighted_vsub_of_point_linear (p : ι → P) (b : P) : (ι → k) →ₗ[k] V :=
119+
∑ i, (linear_map.proj i : (ι → k) →ₗ[k] k).smul_right (p i -ᵥ b)
120+
121+
@[simp] lemma weighted_vsub_of_point_linear_apply (w : ι → k) (p : ι → P) (b : P) :
122+
weighted_vsub_of_point_linear V p b w = weighted_vsub_of_point V w p b :=
123+
by simp [weighted_vsub_of_point_linear, linear_map.sum_apply, weighted_vsub_of_point]
124+
125+
/-- The weighted sum when the weights are 0. -/
126+
@[simp] lemma weighted_vsub_of_point_zero (p : ι → P) (b : P) :
127+
weighted_vsub_of_point V (0 : ι → k) p b = 0 :=
128+
by rw [← weighted_vsub_of_point_linear_apply, linear_map.map_zero]
129+
130+
/-- The weighted sum, multiplied by a constant. -/
131+
lemma weighted_vsub_of_point_smul (r : k) (w : ι → k) (p : ι → P) (b : P) :
132+
r • weighted_vsub_of_point V w p b = weighted_vsub_of_point V (r • w) p b :=
133+
by simp only [← weighted_vsub_of_point_linear_apply, linear_map.map_smul]
134+
135+
/-- The weighted sum, negated. -/
136+
lemma weighted_vsub_of_point_neg (w : ι → k) (p : ι → P) (b : P) :
137+
-weighted_vsub_of_point V w p b = weighted_vsub_of_point V (-w) p b :=
138+
by simp only [← weighted_vsub_of_point_linear_apply, linear_map.map_neg]
139+
140+
/-- Adding two weighted sums. -/
141+
lemma weighted_vsub_of_point_add (w₁ w₂ : ι → k) (p : ι → P) (b : P) :
142+
weighted_vsub_of_point V w₁ p b + weighted_vsub_of_point V w₂ p b =
143+
weighted_vsub_of_point V (w₁ + w₂) p b :=
144+
by simp only [← weighted_vsub_of_point_linear_apply, linear_map.map_add]
145+
146+
/-- Subtracting two weighted sums. -/
147+
lemma weighted_vsub_of_point_sub (w₁ w₂ : ι → k) (p : ι → P) (b : P) :
148+
weighted_vsub_of_point V w₁ p b - weighted_vsub_of_point V w₂ p b =
149+
weighted_vsub_of_point V (w₁ - w₂) p b :=
150+
by simp only [← weighted_vsub_of_point_linear_apply, linear_map.map_sub]
151+
152+
/-- The weighted sum is independent of the base point when the sum of
153+
the weights is 0. -/
154+
lemma weighted_vsub_of_point_eq_of_sum_eq_zero (w : ι → k) (p : ι → P) (h : ∑ i, w i = 0)
155+
(b₁ b₂ : P) : weighted_vsub_of_point V w p b₁ = weighted_vsub_of_point V w p b₂ :=
156+
begin
157+
apply eq_of_sub_eq_zero,
158+
erw ←finset.sum_sub_distrib,
159+
conv_lhs {
160+
congr,
161+
skip,
162+
funext,
163+
rw [←smul_sub, vsub_sub_vsub_cancel_left]
164+
},
165+
rw [←finset.sum_smul, h, zero_smul]
166+
end
167+
168+
/-- The weighted sum, added to the base point, is independent of the
169+
base point when the sum of the weights is 1. -/
170+
lemma weighted_vsub_of_point_vadd_eq_of_sum_eq_one (w : ι → k) (p : ι → P) (h : ∑ i, w i = 1)
171+
(b₁ b₂ : P) : weighted_vsub_of_point V w p b₁ +ᵥ b₁ = weighted_vsub_of_point V w p b₂ +ᵥ b₂ :=
172+
begin
173+
erw [←vsub_eq_zero_iff_eq V, vadd_vsub_assoc, vsub_vadd_eq_vsub_sub, ←add_sub_assoc, add_comm,
174+
add_sub_assoc, ←finset.sum_sub_distrib],
175+
conv_lhs {
176+
congr,
177+
skip,
178+
congr,
179+
skip,
180+
funext,
181+
rw [←smul_sub, vsub_sub_vsub_cancel_left]
182+
},
183+
rw [←finset.sum_smul, h, one_smul, vsub_add_vsub_cancel, vsub_self]
184+
end
185+
186+
/-- A weighted sum of the results of subtracting a default base point
187+
from the given points. This is intended to be used when the sum of
188+
the weights is 0; that condition is specified as a hypothesis on those
189+
lemmas that require it. -/
190+
def weighted_vsub (w : ι → k) (p : ι → P) : V :=
191+
weighted_vsub_of_point V w p (classical.choice S.nonempty)
192+
193+
/-- `weighted_vsub` gives the sum of the results of subtracting any
194+
base point, when the sum of the weights is 0. -/
195+
lemma weighted_vsub_eq_weighted_vsub_of_point_of_sum_eq_zero (w : ι → k) (p : ι → P)
196+
(h : ∑ i, w i = 0) (b : P) : weighted_vsub V w p = weighted_vsub_of_point V w p b :=
197+
weighted_vsub_of_point_eq_of_sum_eq_zero V w p h _ _
198+
199+
/-- The weighted sum when the weights are 0. -/
200+
@[simp] lemma weighted_vsub_zero (p : ι → P) : weighted_vsub V (0 : ι → k) p = 0 :=
201+
weighted_vsub_of_point_zero V p _
202+
203+
/-- The weighted sum, multiplied by a constant. -/
204+
lemma weighted_vsub_smul (r : k) (w : ι → k) (p : ι → P) :
205+
r • weighted_vsub V w p = weighted_vsub V (r • w) p :=
206+
weighted_vsub_of_point_smul V r w p _
207+
208+
/-- The weighted sum, negated. -/
209+
lemma weighted_vsub_neg (w : ι → k) (p : ι → P) :
210+
-weighted_vsub V w p = weighted_vsub V (-w) p :=
211+
weighted_vsub_of_point_neg V w p _
212+
213+
/-- Adding two weighted sums. -/
214+
lemma weighted_vsub_add (w₁ w₂ : ι → k) (p : ι → P) :
215+
weighted_vsub V w₁ p + weighted_vsub V w₂ p = weighted_vsub V (w₁ + w₂) p :=
216+
weighted_vsub_of_point_add V w₁ w₂ p _
217+
218+
/-- Subtracting two weighted sums. -/
219+
lemma weighted_vsub_sub (w₁ w₂ : ι → k) (p : ι → P) :
220+
weighted_vsub V w₁ p - weighted_vsub V w₂ p = weighted_vsub V (w₁ - w₂) p :=
221+
weighted_vsub_of_point_sub V w₁ w₂ p _
222+
223+
/-- A weighted sum of the results of subtracting a default base point
224+
from the given points, added to that base point. This is intended to
225+
be used when the sum of the weights is 1, in which case it is an
226+
affine combination (barycenter) of the points with the given weights;
227+
that condition is specified as a hypothesis on those lemmas that
228+
require it. -/
229+
def affine_combination (w : ι → k) (p : ι → P) : P :=
230+
weighted_vsub_of_point V w p (classical.choice S.nonempty) +ᵥ (classical.choice S.nonempty)
231+
232+
/-- `affine_combination` gives the sum with any base point, when the
233+
sum of the weights is 1. -/
234+
lemma affine_combination_eq_weighted_vsub_of_point_vadd_of_sum_eq_one (w : ι → k) (p : ι → P)
235+
(h : ∑ i, w i = 1) (b : P) : affine_combination V w p = weighted_vsub_of_point V w p b +ᵥ b :=
236+
weighted_vsub_of_point_vadd_eq_of_sum_eq_one V w p h _ _
237+
238+
/-- Adding a `weighted_vsub` to an `affine_combination`. -/
239+
lemma weighted_vsub_vadd_affine_combination (w₁ w₂ : ι → k) (p : ι → P) :
240+
weighted_vsub V w₁ p +ᵥ affine_combination V w₂ p = affine_combination V (w₁ + w₂) p :=
241+
begin
242+
erw vadd_assoc,
243+
congr,
244+
exact weighted_vsub_add V w₁ w₂ p
245+
end
246+
247+
/-- Subtracting two `affine_combination`s. -/
248+
lemma affine_combination_vsub (w₁ w₂ : ι → k) (p : ι → P) :
249+
affine_combination V w₁ p -ᵥ affine_combination V w₂ p = weighted_vsub V (w₁ - w₂) p :=
250+
begin
251+
erw vadd_vsub_vadd_cancel_right,
252+
exact weighted_vsub_sub V w₁ w₂ p
253+
end
254+
255+
end combination
256+
103257
end affine_space
104258

105259
open add_torsor affine_space
@@ -464,6 +618,23 @@ rfl
464618

465619
end affine_map
466620

621+
namespace affine_map
622+
variables {k : Type*} (V : Type*) (P : Type*) [comm_ring k] [add_comm_group V] [module k V]
623+
variables [affine_space k V P] {ι : Type*} [fintype ι]
624+
625+
-- TODO: define `affine_map.proj`, `affine_map.fst`, `affine_map.snd`
626+
/-- A weighted sum, as an affine map on the points involved. -/
627+
def weighted_vsub_of_point (w : ι → k) : affine_map k ((ι → V) × V) ((ι → P) × P) V V :=
628+
{ to_fun := λ p, weighted_vsub_of_point _ w p.fst p.snd,
629+
linear := ∑ i, w i • ((linear_map.proj i).comp (linear_map.fst _ _ _) - linear_map.snd _ _ _),
630+
map_vadd' := begin
631+
rintros ⟨p, b⟩ ⟨v, b'⟩,
632+
simp [linear_map.sum_apply, weighted_vsub_of_point, vsub_vadd_eq_vsub_sub, vadd_vsub_assoc,
633+
add_sub, ← sub_add_eq_add_sub, smul_add, finset.sum_add_distrib]
634+
end }
635+
636+
end affine_map
637+
467638
namespace linear_map
468639

469640
variables {k : Type*} {V₁ : Type*} {V₂ : Type*} [ring k] [add_comm_group V₁] [module k V₁]

0 commit comments

Comments
 (0)