Skip to content

Commit a7bbdb4

Browse files
committed
feat(Geometry/Convex): modules are convex spaces
1 parent 34f7a6c commit a7bbdb4

6 files changed

Lines changed: 170 additions & 41 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4511,6 +4511,7 @@ public import Mathlib.Geometry.Convex.Cone.Simplicial
45114511
public import Mathlib.Geometry.Convex.Cone.TensorProduct
45124512
public import Mathlib.Geometry.Convex.ConvexSpace.AffineSpace
45134513
public import Mathlib.Geometry.Convex.ConvexSpace.Defs
4514+
public import Mathlib.Geometry.Convex.ConvexSpace.Module
45144515
public import Mathlib.Geometry.Convex.ConvexSpace.Prod
45154516
public import Mathlib.Geometry.Diffeology.Basic
45164517
public import Mathlib.Geometry.Euclidean.Altitude

Mathlib/Data/Finsupp/Defs.lean

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,17 +234,17 @@ section OnFinset
234234
variable [Zero M]
235235

236236
/-- The (not exposed) support of `Finsupp.onFinset`. -/
237-
@[no_expose] def onFinset_support (s : Finset α) (f : α → M) : Finset α :=
237+
@[no_expose] def onFinsetSupport (s : Finset α) (f : α → M) : Finset α :=
238238
haveI := Classical.decEq M
239239
{a ∈ s | f a ≠ 0}
240240

241241
/-- `Finsupp.onFinset s f hf` is the finsupp function representing `f` restricted to the finset `s`.
242242
The function must be `0` outside of `s`. Use this when the set needs to be filtered anyways,
243243
otherwise a better set representation is often available. -/
244244
def onFinset (s : Finset α) (f : α → M) (hf : ∀ a, f a ≠ 0 → a ∈ s) : α →₀ M where
245-
support := onFinset_support s f
245+
support := onFinsetSupport s f
246246
toFun := f
247-
mem_support_toFun := by simpa [onFinset_support]
247+
mem_support_toFun := by simpa [onFinsetSupport]
248248

249249
@[simp, norm_cast] lemma coe_onFinset (s : Finset α) (f : α → M) (hf) : onFinset s f hf = f := rfl
250250

@@ -255,7 +255,9 @@ theorem onFinset_apply {s : Finset α} {f : α → M} {hf a} : (onFinset s f hf
255255
theorem support_onFinset [DecidableEq M] {s : Finset α} {f : α → M}
256256
(hf : ∀ a : α, f a ≠ 0 → a ∈ s) :
257257
(Finsupp.onFinset s f hf).support = {a ∈ s | f a ≠ 0} := by
258-
dsimp [onFinset]; rw [onFinset_support]; congr
258+
dsimp [onFinset]; rw [onFinsetSupport]; congr
259+
260+
@[simp] lemma onFinset_support (f : α →₀ M) : onFinset f.support f (by simp) = f := by ext; simp
259261

260262
@[simp]
261263
theorem support_onFinset_subset {s : Finset α} {f : α → M} {hf} :

Mathlib/Geometry/Convex/ConvexSpace/AffineSpace.lean

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ This file shows that every affine space is a convex space.
1616
1717
## Main results
1818
19-
* `AddTorsor.instConvexSpace`: An affine space over a module is a convex space.
20-
* `AddTorsor.convexCombination_eq_affineCombination`: The convex combination equals the affine
19+
* `AddTorsor.toConvexSpace`: An affine space over a module is a convex space.
20+
* `AddTorsor.sConvexComb_eq_affineCombination`: The convex combination equals the affine
2121
combination.
2222
* `AddTorsor.convexCombPair_eq_lineMap`: Binary convex combinations are given by `lineMap`.
2323
-/
@@ -158,33 +158,3 @@ theorem convexCombPair_eq_lineMap (s t : R) (hs : 0 ≤ s) (ht : 0 ≤ t)
158158
simp [vsub_self]
159159

160160
end AddTorsor
161-
162-
open Finsupp
163-
164-
namespace Convexity
165-
166-
attribute [local instance] AddTorsor.toConvexSpace
167-
168-
theorem sConvexComb_eq_sum (f : StdSimplex R V) :
169-
f.sConvexComb = f.weights.sum fun i r ↦ r • i := by
170-
simp [AddTorsor.sConvexComb_eq_affineCombination,
171-
Finset.affineCombination_eq_linear_combination _ _ _ f.total, Finsupp.sum]
172-
173-
@[deprecated (since := "2026-04-03")]
174-
alias _root_.convexCombination_eq_sum := sConvexComb_eq_sum
175-
176-
theorem iConvexComb_eq_sum (f : StdSimplex R I) (g : I → V) :
177-
f.iConvexComb g = f.weights.sum fun i r ↦ r • g i := by
178-
simp [iConvexComb, sConvexComb_eq_sum, add_smul, sum_mapDomain_index]
179-
180-
theorem convexCombPair_eq_add
181-
{s t : R} (hs : 0 ≤ s) (ht : 0 ≤ t) (h : s + t = 1) (x y : V) :
182-
convexCombPair s t hs ht h x y = s • x + t • y := by
183-
classical
184-
simp [convexCombPair, sConvexComb_eq_sum, sum_add_index, add_smul]
185-
186-
variable (R I) in
187-
lemma StdSimplex.isAffineMap_weights : IsAffineMap R (weights (R := R) (M := I)) where
188-
map_sConvexComb s := by simp [sConvexComb_eq_sum, StdSimplex.map, sum_mapDomain_index, add_smul]
189-
190-
end Convexity

Mathlib/Geometry/Convex/ConvexSpace/Defs.lean

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,20 @@ lemma sConvexComb_map (w : StdSimplex R I) (f : I → M) :
302302
(s.map f).iConvexComb g = s.iConvexComb (g ∘ f) := by
303303
simp only [iConvexComb, map_comp]
304304

305-
lemma iConvexComb_congr (s : StdSimplex R I) (f : I ≃ J) (g : I → M) :
305+
@[congr] lemma iConvexComb_congr {w : StdSimplex R I} {f g : I → M}
306+
(hfg : ∀ i, w.weights i ≠ 0 → f i = g i) :
307+
w.iConvexComb f = w.iConvexComb g := by
308+
refine congr(sConvexComb $(?_))
309+
ext i
310+
simp only [weights_map]
311+
-- TODO: This should just be `congr! 2 with i hi`.
312+
congr 1
313+
refine Finsupp.mapDomain_congr fun i hi ↦ ?_
314+
exact hfg i (by simpa using hi)
315+
316+
lemma iConvexComb_reindex (s : StdSimplex R I) (f : I ≃ J) (g : I → M) :
306317
s.iConvexComb g = (s.map f).iConvexComb (g ∘ f.symm) := by
307-
simp [iConvexComb_map, Function.comp_def]
318+
simp [iConvexComb_map]
308319

309320
/-- Flattening nested `iConvexComb`s.
310321
@@ -347,7 +358,7 @@ lemma iConvexComb_comm (f : StdSimplex R I) (g : StdSimplex R J)
347358
(e : I → J → M) :
348359
f.iConvexComb (fun i ↦ g.iConvexComb (e i)) =
349360
g.iConvexComb fun j ↦ f.iConvexComb fun i ↦ e i j := by
350-
rw [iConvexComb_assoc', iConvexComb_assoc', iConvexComb_congr _ (.prodComm ..)]
361+
rw [iConvexComb_assoc', iConvexComb_assoc', iConvexComb_reindex _ (.prodComm ..)]
351362
congr
352363
suffices (f.map fun x ↦ g.map (Prod.mk · x)).sConvexComb =
353364
(g.map (f.map ∘ Prod.mk)).sConvexComb by
@@ -494,7 +505,7 @@ lemma iConvexComb_convexCombPair_comm (f : StdSimplex R I) (e₁ e₂ : I → M)
494505
f.iConvexComb (fun x ↦ convexCombPair s t hs ht h (e₁ x) (e₂ x)) =
495506
convexCombPair s t hs ht h (f.iConvexComb e₁) (f.iConvexComb e₂) := by
496507
simp only [convexCombPair_def]
497-
convert (iConvexComb_comm (.duple 0 1 hs ht h) f ![e₁, e₂]).symm with i j j
508+
convert (iConvexComb_comm (.duple 0 1 hs ht h) f ![e₁, e₂]).symm with i _ j _ j
498509
· fin_cases j <;> simp
499510
· fin_cases j <;> simp
500511

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/-
2+
Copyright (c) 2026 Yaël Dillies. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Yaël Dillies
5+
-/
6+
module
7+
8+
public import Mathlib.Geometry.Convex.ConvexSpace.Prod
9+
public import Mathlib.LinearAlgebra.AffineSpace.Combination
10+
public import Mathlib.LinearAlgebra.AffineSpace.AffineMap
11+
12+
/-!
13+
# Modules are convex spaces
14+
15+
This file shows that every semimodule over an ordered semiring is a convex space.
16+
17+
## Main declarations
18+
19+
* `ConvexSpace.ofModule`: A semimodule space over a semiring is a convex space.
20+
* `convexSpaceSelf`: A semiring is a convex space over itself.
21+
* `IsModuleConvexSpace`: Predicate for a convex space and module structures to be compatible.
22+
23+
## Implementation notes
24+
25+
It is sadly impossible to make `ConvexSpace.ofModule` a global instance since it creates diamonds
26+
with structural instances such as `ConvexSpace R X → ConvexSpace R Y → ConvexSpace R (X × Y)`
27+
because `(∑ i, f i).fst = ∑ i, (f i).fst` isn't defeq, ultimately because `Finset.sum` isn't a field
28+
of `AddCommMonoid`.
29+
-/
30+
31+
public section
32+
33+
namespace Convexity
34+
variable {R M N I : Type*} [Semiring R] [PartialOrder R] [IsStrictOrderedRing R]
35+
[AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N]
36+
37+
/-- Any semimodule over an ordered semiring is a convex space.
38+
39+
This is not an instance because it creates a diamond. -/
40+
@[expose, implicit_reducible]
41+
def ConvexSpace.ofModule : ConvexSpace R M where
42+
sConvexComb w := w.weights.sum fun m r ↦ r • m
43+
sConvexComb_single := by simp
44+
assoc := by
45+
simp [Finsupp.sum_mapDomain_index, add_smul, Finsupp.sum_sum_index, Finsupp.sum_smul_index,
46+
mul_smul, Finsupp.smul_sum]
47+
48+
instance convexSpaceSelf : ConvexSpace R R := .ofModule
49+
50+
variable (R M) [ConvexSpace R M] in
51+
class IsModuleConvexSpace : Prop where
52+
sConvexComb_eq_sum (w : StdSimplex R M) : w.sConvexComb = w.weights.sum fun m r ↦ r • m
53+
54+
export IsModuleConvexSpace (sConvexComb_eq_sum)
55+
attribute [simp] sConvexComb_eq_sum
56+
57+
@[deprecated (since := "2026-04-03")]
58+
alias _root_.convexCombination_eq_sum := sConvexComb_eq_sum
59+
60+
attribute [local instance] ConvexSpace.ofModule in
61+
protected lemma IsModuleConvexSpace.ofModule : IsModuleConvexSpace R M where
62+
sConvexComb_eq_sum _ := rfl
63+
64+
instance isModuleConvexSpace_self : IsModuleConvexSpace R R := .ofModule
65+
66+
section IsModuleConvexSpace
67+
variable [ConvexSpace R M] [IsModuleConvexSpace R M]
68+
69+
/-- `iConvexComb` in a module can be expressed as a sum. -/
70+
@[simp]
71+
lemma iConvexComb_eq_sum (w : StdSimplex R I) (f : I → M) :
72+
w.iConvexComb f = w.weights.sum fun i r ↦ r • f i := by
73+
simp [iConvexComb, sConvexComb_eq_sum, Finsupp.sum_mapDomain_index, add_smul]
74+
75+
/-- `convexCombPair` in a module can be expressed as a sum. -/
76+
@[simp]
77+
lemma convexCombPair_eq_sum (a b : R) (ha hb hab) (x y : M) :
78+
convexCombPair a b ha hb hab x y = a • x + b • y := by
79+
classical simp [convexCombPair, sConvexComb_eq_sum, Finsupp.sum_add_index, add_smul]
80+
81+
instance [ConvexSpace R N] [IsModuleConvexSpace R N] : IsModuleConvexSpace R (M × N) where
82+
sConvexComb_eq_sum w := by ext <;> simp [Finsupp.sum, Prod.fst_sum, Prod.snd_sum]
83+
84+
instance {ι : Type*} {M : ι → Type*} [∀ i, AddCommMonoid (M i)] [∀ i, Module R (M i)]
85+
[∀ i, ConvexSpace R (M i)] [∀ i, IsModuleConvexSpace R (M i)] :
86+
IsModuleConvexSpace R (∀ i, M i) where
87+
sConvexComb_eq_sum w := by ext; simp [Finsupp.sum]
88+
89+
instance {ι : Type*} : IsModuleConvexSpace R (ι →₀ M) where
90+
sConvexComb_eq_sum w := by ext; simp [Finsupp.sum]
91+
92+
end IsModuleConvexSpace
93+
94+
variable (R I) in
95+
lemma StdSimplex.isAffineMap_weights : IsAffineMap R (weights (R := R) (M := I)) where
96+
map_sConvexComb s := by simp [sConvexComb_eq_sum, Finsupp.sum_mapDomain_index, add_smul]
97+
98+
end Convexity

Mathlib/Geometry/Convex/ConvexSpace/Prod.lean

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ lemma snd_iConvexComb (w : StdSimplex R I) (f : I → X × Y) :
4949
(w.iConvexComb f).snd = w.iConvexComb (fun i ↦ (f i).snd) :=
5050
isAffineMap_snd.map_iConvexComb ..
5151

52+
@[simp]
53+
lemma fst_convexCombPair (a b : R) (ha hb hab) (x y : X × Y) :
54+
(convexCombPair a b ha hb hab x y).fst = convexCombPair a b ha hb hab x.fst y.fst :=
55+
isAffineMap_fst.map_convexCombPair ..
56+
57+
@[simp]
58+
lemma snd_convexCombPair (a b : R) (ha hb hab) (x y : X × Y) :
59+
(convexCombPair a b ha hb hab x y).snd = convexCombPair a b ha hb hab x.snd y.snd :=
60+
isAffineMap_snd.map_convexCombPair ..
61+
5262
end Prod
5363

5464
namespace Pi
@@ -57,7 +67,7 @@ variable {ι : Type*} {X : ι → Type*} [∀ i, ConvexSpace R (X i)] {i : ι}
5767
instance : ConvexSpace R (∀ i, X i) := .mk
5868
(fun w i ↦ w.iConvexComb (· i))
5969
(by simp)
60-
(by simp [Function.comp_def, iConvexComb_assoc])
70+
(by simp [iConvexComb_assoc])
6171

6272
@[simp]
6373
lemma sConvexComb_apply (w : StdSimplex R (∀ i, X i)) (i : ι) :
@@ -71,4 +81,41 @@ lemma isAffineMap_eval : IsAffineMap R (· i : (∀ i, X i) → X i) where
7181
lemma iConvexComb_apply (w : StdSimplex R I) (f : I → ∀ i, X i) (i : ι) :
7282
w.iConvexComb f i = w.iConvexComb (fun j ↦ f j i) := isAffineMap_eval.map_iConvexComb ..
7383

84+
@[simp]
85+
lemma convexCombPair_apply (a b : R) (ha hb hab) (f g : ∀ i, X i) (i : ι) :
86+
convexCombPair a b ha hb hab f g i = convexCombPair a b ha hb hab (f i) (g i) :=
87+
isAffineMap_eval.map_convexCombPair ..
88+
7489
end Pi
90+
91+
namespace Finsupp
92+
variable {ι : Type*} {X : Type*} [Zero X] [ConvexSpace R X] {i : ι}
93+
94+
instance : ConvexSpace R (ι →₀ X) := .mk
95+
(fun w ↦ by
96+
classical
97+
refine .onFinset (w.weights.support.biUnion Finsupp.support) (fun i ↦ w.iConvexComb (· i)) ?_
98+
rintro i hi
99+
contrapose! hi
100+
simp_all)
101+
(by simp)
102+
(fun w ↦ by ext; simp [iConvexComb_assoc])
103+
104+
@[simp]
105+
lemma sConvexComb_apply (w : StdSimplex R (ι →₀ X)) (i : ι) :
106+
w.sConvexComb i = w.iConvexComb (· i) := rfl
107+
108+
@[fun_prop]
109+
lemma isAffineMap_eval : IsAffineMap R (· i : (ι →₀ X) → X) where
110+
map_sConvexComb _ := sConvexComb_apply ..
111+
112+
@[simp]
113+
lemma iConvexComb_apply (w : StdSimplex R I) (f : I → ι →₀ X) (i : ι) :
114+
w.iConvexComb f i = w.iConvexComb (fun j ↦ f j i) := isAffineMap_eval.map_iConvexComb ..
115+
116+
@[simp]
117+
lemma convexCombPair_apply (a b : R) (ha hb hab) (f g : ι →₀ X) (i : ι) :
118+
convexCombPair a b ha hb hab f g i = convexCombPair a b ha hb hab (f i) (g i) :=
119+
isAffineMap_eval.map_convexCombPair ..
120+
121+
end Finsupp

0 commit comments

Comments
 (0)