Skip to content

Commit fbefe80

Browse files
YaelDilliesBergschaf
authored andcommitted
feat(Geometry/Convex): convex sets in a ConvexSpace (leanprover-community#38905)
Define convex sets in a convex space. To allow full generality on the coefficients, for `s` to be convex we require that all finitary convex combinations of points of `s` lie in `s`, instead of merely binary ones as is customary. Since its body is an implementation detail, the predicate `IsConvexSet` is unexposed. `Convex` will be deprecated to `IsConvexSet` in a later PR. [Zulip](https://leanprover.zulipchat.com/#narrow/channel/144837-PR-reviews/topic/Convexity.20refactor/with/593967042)
1 parent a0112ec commit fbefe80

8 files changed

Lines changed: 326 additions & 53 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4522,6 +4522,7 @@ public import Mathlib.Geometry.Convex.ConvexSpace.AffineSpace
45224522
public import Mathlib.Geometry.Convex.ConvexSpace.Defs
45234523
public import Mathlib.Geometry.Convex.ConvexSpace.Module
45244524
public import Mathlib.Geometry.Convex.ConvexSpace.Prod
4525+
public import Mathlib.Geometry.Convex.Set
45254526
public import Mathlib.Geometry.Diffeology.Basic
45264527
public import Mathlib.Geometry.Euclidean.Altitude
45274528
public import Mathlib.Geometry.Euclidean.Angle.Bisector

Mathlib/Algebra/BigOperators/Finsupp/Basic.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ theorem prod_mapRange_index {f : M → M'} {hf : f 0 = 0} {g : α →₀ M} {h :
7878
(h0 : ∀ a, h a 0 = 1) : (mapRange f hf g).prod h = g.prod fun a b => h a (f b) :=
7979
Finset.prod_subset support_mapRange fun _ _ H => by rw [notMem_support_iff.1 H, h0]
8080

81+
@[to_additive (attr := simp)]
82+
lemma prod_onFinset (s : Finset α) (f : α → M) (hf) (g : α → M → N) (hg : ∀ i ∈ s, g i 0 = 1) :
83+
(onFinset s f hf).prod g = ∏ a ∈ s, g a (f a) :=
84+
prod_of_support_subset _ support_onFinset_subset _ hg
85+
8186
@[to_additive (attr := simp)]
8287
theorem prod_zero_index {h : α → M → N} : (0 : α →₀ M).prod h = 1 :=
8388
rfl

Mathlib/Analysis/Convex/MetricSpace.lean

Lines changed: 13 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ that has little to do with this definition.
3535
- Equip `StdSimplex` with a topology and show the analogous continuity result for n-ary
3636
convex combinations.
3737
- Tidy up the imports with `Mathlib.Geometric.Convex.ConvexSpace.AffineSpace`.
38+
- Define convex functions with domain a convex space, and redefine `IsConvexDist` as saying that
39+
`dist : X × X → ℝ` is convex.
3840
-/
3941

4042
public section
@@ -256,42 +258,6 @@ lemma continuous_convexCombPair' [BoundedSpace X]
256258
@[deprecated (since := "2026-05-15")]
257259
alias continuous_convexComboPair' := continuous_convexCombPair'
258260

259-
variable {R E : Type*} [LinearOrder R] [Field R] [IsStrictOrderedRing R] [AddCommGroup E]
260-
[Module R E] [ConvexSpace R E] [IsModuleConvexSpace R E] {S : Set E}
261-
262-
/-- A convex subset of a vector space is a convex space. -/
263-
-- TODO: this should generalize to arbitrary convex space once `Convex` is redefined.
264-
@[expose, implicit_reducible]
265-
noncomputable def ConvexSpace.ofConvex (H : Convex R S) : ConvexSpace R S where
266-
sConvexComb f :=
267-
⟨sConvexComb (f.map (↑)), by
268-
simpa [sConvexComb_eq_sum, StdSimplex.map, Finsupp.sum_mapDomain_index, add_smul] using
269-
H.sum_mem (fun _ _ ↦ f.nonneg _) f.total fun i _ ↦ i.2
270-
assoc f := by
271-
simp [sConvexComb_eq_sum, StdSimplex.map, Finsupp.sum_mapDomain_index, add_smul,
272-
StdSimplex.join, Finsupp.sum_sum_index, Finsupp.sum_smul_index, mul_smul, Finsupp.smul_sum]
273-
sConvexComb_single x := by simp [sConvexComb_eq_sum, ← StdSimplex.mk_single, StdSimplex.map]
274-
275-
lemma isAffineMap_coe (S : Set E) (H : Convex R S) :
276-
letI : ConvexSpace R S := .ofConvex H
277-
IsAffineMap R ((↑) : S → E) :=
278-
letI : ConvexSpace R S := .ofConvex H
279-
fun _ ↦ rfl⟩
280-
281-
@[simp]
282-
lemma ConvexSpace.ofConvex.coe_sConvexComb (S : Set E) (H : Convex R S) (f : StdSimplex R S) :
283-
letI : ConvexSpace R S := .ofConvex H
284-
(↑f.sConvexComb : E) = (f.map (↑)).sConvexComb :=
285-
rfl
286-
287-
@[simp]
288-
lemma ConvexSpace.ofConvex.coe_iConvexComb (S : Set E) (H : Convex R S) (f : StdSimplex R I)
289-
(g : I → S) :
290-
letI : ConvexSpace R S := .ofConvex H
291-
(↑(f.iConvexComb g) : E) = f.iConvexComb fun x ↦ ↑(g x) :=
292-
letI : ConvexSpace R S := .ofConvex H
293-
(isAffineMap_coe S H).map_iConvexComb f g
294-
295261
attribute [local instance] AddTorsor.toConvexSpace in
296262
instance (priority := low) {V P : Type*}
297263
[NormedAddCommGroup V] [NormedSpace ℝ V] [MetricSpace P] [NormedAddTorsor V P] :
@@ -307,14 +273,17 @@ instance (priority := low) {V P : Type*}
307273
grw [Finsupp.sum, Finsupp.sum, norm_sum_le]
308274
simp [norm_smul, abs_eq_self.mpr (f.nonneg _)]
309275

310-
instance IsConvexDist.of_convex {E : Type*} [NormedAddCommGroup E]
311-
[NormedSpace ℝ E] [ConvexSpace ℝ E] [IsModuleConvexSpace ℝ E] [IsConvexDist E] {S : Set E}
312-
(H : Convex ℝ S) :
313-
letI : ConvexSpace ℝ S := .ofConvex H
314-
IsConvexDist S := by
315-
letI : ConvexSpace ℝ S := .ofConvex H
276+
instance IsConvexDist.subtype (s : Set X) (hs : IsConvexSet ℝ s) :
277+
letI : ConvexSpace ℝ s := .subtype s hs
278+
IsConvexDist s := by
279+
letI : ConvexSpace ℝ s := .subtype s hs
316280
refine ⟨fun f ↦ ?_⟩
317-
convert dist_iConvexComb_fst_snd_le (X := E) (f.map fun x ↦ (x.1, x.2)) <;>
318-
simp [Subtype.dist_eq, Finsupp.sum_mapDomain_index, add_mul, add_smul]
281+
convert dist_iConvexComb_fst_snd_le (X := X) (f.map fun x ↦ (x.1, x.2)) <;>
282+
simp [Subtype.dist_eq, Finsupp.sum_mapDomain_index, add_mul]
283+
284+
instance IsConvexDist.submodule {F M : Type*} [AddCommGroup M] [MetricSpace M]
285+
[Module ℝ M] [ConvexSpace ℝ M] [IsModuleConvexSpace ℝ M] [IsConvexDist M]
286+
[SetLike F M] [AddSubmonoidClass F M] [SMulMemClass F ℝ M] {S : F} :
287+
IsConvexDist S := .subtype _ _
319288

320289
end Convexity

Mathlib/Data/Finsupp/Basic.lean

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,14 @@ def mapDomain (f : α → β) (v : α →₀ M) : β →₀ M :=
276276
· intro _
277277
rw [single_zero, coe_zero, Pi.zero_apply]
278278

279+
lemma mapDomain_of_not_mem_image_support {f : α → β} {x : α →₀ M} {b : β}
280+
(hb : b ∉ f '' x.support) : mapDomain f x b = 0 := by
281+
rw [mapDomain, sum_apply, sum, Finset.sum_eq_zero]
282+
exact fun a ha ↦ single_eq_of_ne fun eq => hb <| eq ▸ Set.mem_image_of_mem _ ha
283+
279284
theorem mapDomain_notin_range {f : α → β} (x : α →₀ M) (a : β) (h : a ∉ Set.range f) :
280-
mapDomain f x a = 0 := by
281-
rw [mapDomain, sum_apply, sum]
282-
exact Finset.sum_eq_zero fun a' _ => single_eq_of_ne fun eq => h <| eq ▸ Set.mem_range_self _
285+
mapDomain f x a = 0 :=
286+
mapDomain_of_not_mem_image_support <| by grw [Set.image_subset_range]; exact h
283287

284288
@[simp]
285289
theorem mapDomain_id : mapDomain id v = v :=

Mathlib/Geometry/Convex/ConvexSpace/Defs.lean

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ grind_pattern StdSimplex.total => self.weights
6262
initialize_simps_projections StdSimplex (as_prefix weights)
6363

6464
namespace StdSimplex
65+
section Semiring
6566
variable {R : Type u} [PartialOrder R] [Semiring R] {M N P : Type*} {w : StdSimplex R M} {x : M}
6667

6768
@[simp] lemma weights_nonneg {w : StdSimplex R M} (i : M) : 0 ≤ w.weights i := w.nonneg i
@@ -167,6 +168,56 @@ private lemma map_join (f : StdSimplex R (StdSimplex R M)) (g : M → N) :
167168
@[simp] private lemma join_single (x : StdSimplex R M) : join (.single x) = x := by
168169
ext; simp [join, ← mk_single]
169170

171+
end Semiring
172+
173+
section Semifield
174+
variable [Semifield K] [LinearOrder K] [IsStrictOrderedRing K]
175+
176+
private lemma restrict_nonneg_aux {w : StdSimplex K X} {p : X → Prop} [DecidablePred p] :
177+
0 ≤ (filter p w.weights).sum fun _x k ↦ k :=
178+
sum_nonneg <| by simp [filter_apply, apply_ite]
179+
180+
private lemma restrict_ne_zero_aux {w : StdSimplex K X} {p : X → Prop} [DecidablePred p]
181+
(hp : ∃ a, p a ∧ w.weights a ≠ 0) :
182+
(filter p w.weights).sum (fun _x k ↦ k) ≠ 0 :=
183+
(sum_pos (by simp +contextual [lt_iff_le_and_ne, eq_comm]) <| by simpa [ne_iff, filter_apply]).ne'
184+
185+
/-- Project an element of the standard simplex to a lower-dimensional standard simplex,
186+
assuming at least one non-zero weight subsists. -/
187+
def restrict (w : StdSimplex K X) (s : Set X) (hs : ∃ x ∈ s, w.weights x ≠ 0) : StdSimplex K X where
188+
weights := open scoped Classical in
189+
((w.weights.filter (· ∈ s)).sum fun x k ↦ k)⁻¹ • w.weights.filter (· ∈ s)
190+
nonneg := by
191+
classical
192+
exact smul_nonneg (inv_nonneg.2 restrict_nonneg_aux) fun _ ↦ by simp [filter_apply, apply_ite]
193+
total := by classical simp [sum_smul_index, ← mul_sum, restrict_ne_zero_aux hs]
194+
195+
lemma weights_restrict (w : StdSimplex K X) (s : Set X) (hs) [DecidablePred (· ∈ s)] :
196+
(w.restrict s hs).weights =
197+
((w.weights.filter (· ∈ s)).sum fun _x k ↦ k)⁻¹ • w.weights.filter (· ∈ s) := by
198+
simp [restrict]; congr
199+
200+
variable [IsDomain K]
201+
202+
@[simp]
203+
lemma support_weights_restrict (w : StdSimplex K X) (s : Set X) (hs) [DecidablePred (· ∈ s)] :
204+
(w.restrict s hs).weights.support = w.weights.support.filter (· ∈ s) := by
205+
have : (w.weights.filter (· ∈ s)).sum (fun x k ↦ k) ≠ 0 :=
206+
(sum_pos (by simp +contextual [lt_iff_le_and_ne, eq_comm]) <| by
207+
simpa [ne_iff, filter_apply]).ne'
208+
rw [weights_restrict, support_smul_eq (by convert inv_ne_zero this)]
209+
simp
210+
211+
@[simp] lemma restrict_singleton (w : StdSimplex K X) (x : X) (hx) :
212+
w.restrict {x} hx = single x := by
213+
classical
214+
simp only [← support_weights_eq_singleton, support_weights_restrict, Set.mem_singleton_iff]
215+
ext
216+
simp only [Finset.mem_filter, mem_support_iff, ne_eq, Finset.mem_singleton, and_iff_right_iff_imp]
217+
rintro rfl
218+
simpa using hx
219+
220+
end Semifield
170221
end StdSimplex
171222

172223
/--
@@ -240,6 +291,19 @@ lemma map_sConvexComb (s : StdSimplex R (StdSimplex R I)) (f : I → J) :
240291
s.sConvexComb.map f = (s.map (map f)).sConvexComb :=
241292
StdSimplex.map_join s f
242293

294+
variable [Semifield K] [LinearOrder K] [IsStrictOrderedRing K]
295+
296+
lemma convexCombPair_restrict_restrict_compl (w : StdSimplex K I) (s : Set I) (hs hs')
297+
[DecidablePred (· ∈ s)] :
298+
convexCombPair
299+
((w.weights.filter (· ∈ s)).sum fun _x k ↦ k)
300+
((w.weights.filter (· ∉ s)).sum fun _x k ↦ k)
301+
(by exact restrict_nonneg_aux) (by exact restrict_nonneg_aux) (by simp)
302+
(w.restrict s hs) (w.restrict sᶜ hs') = w := by
303+
ext : 1
304+
simp only [Set.mem_compl_iff] at hs'
305+
simp [weights_restrict, smul_inv_smul₀, restrict_ne_zero_aux, hs, hs']
306+
243307
end StdSimplex
244308

245309
lemma sConvexComb_sConvexComb (f : StdSimplex R (StdSimplex R M)) :
@@ -299,8 +363,8 @@ lemma iConvexComb_id (w : StdSimplex R M) : w.iConvexComb id = w.sConvexComb :=
299363
w.iConvexComb (fun x ↦ x) = w.sConvexComb := iConvexComb_id _
300364

301365
@[simp] lemma iConvexComb_map (s : StdSimplex R I) (f : I → J) (g : J → M) :
302-
(s.map f).iConvexComb g = s.iConvexComb (g ∘ f) := by
303-
simp only [iConvexComb, map_comp]
366+
(s.map f).iConvexComb g = s.iConvexComb (fun i ↦ g (f i)) := by
367+
simp only [iConvexComb, map_map]
304368

305369
@[congr] lemma iConvexComb_congr {w : StdSimplex R I} {f g : I → M}
306370
(hfg : ∀ i, w.weights i ≠ 0 → f i = g i) :

Mathlib/Geometry/Convex/ConvexSpace/Module.lean

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Authors: Yaël Dillies
55
-/
66
module
77

8-
public import Mathlib.Geometry.Convex.ConvexSpace.Prod
8+
public import Mathlib.Geometry.Convex.Set
99
public import Mathlib.LinearAlgebra.AffineSpace.Combination
1010
public import Mathlib.LinearAlgebra.AffineSpace.AffineMap
1111

@@ -21,11 +21,12 @@ This file shows that every module over ordered coefficients is a convex space.
2121
* `IsModuleConvexSpace`: Predicate for a convex space and module structures to be compatible.
2222
-/
2323

24-
public section
24+
public noncomputable section
2525

2626
namespace Convexity
27-
variable {R M N I : Type*} [Semiring R] [PartialOrder R] [IsStrictOrderedRing R]
28-
[AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N]
27+
variable {F R M N I : Type*} [Semiring R] [PartialOrder R] [IsStrictOrderedRing R]
28+
[AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N] [SetLike F M]
29+
[AddSubmonoidClass F M] [SMulMemClass F R M]
2930

3031
/-- Any semimodule over an ordered semiring is a convex space.
3132
@@ -75,6 +76,26 @@ lemma convexCombPair_eq_sum (a b : R) (ha hb hab) (x y : M) :
7576
convexCombPair a b ha hb hab x y = a • x + b • y := by
7677
classical simp [convexCombPair, sConvexComb_eq_sum, Finsupp.sum_add_index, add_smul]
7778

79+
@[simp] lemma isConvexSet_coe (S : F) : IsConvexSet R (S : Set M) := by
80+
refine .of_sConvexComb_mem fun w hw ↦ ?_
81+
rw [sConvexComb_eq_sum]
82+
exact AddSubmonoidClass.finsuppSum_mem _ _ _ fun m hm ↦ SMulMemClass.smul_mem _ <| hw <| by simpa
83+
84+
instance (S : F) : ConvexSpace R S := .subtype _ <| isConvexSet_coe _
85+
86+
@[simp]
87+
lemma subtypeVal_submodule_sConvexComb (S : F) (w : StdSimplex R S) :
88+
(w.sConvexComb : M) = w.iConvexComb (↑) := rfl
89+
90+
lemma subtypeVal_submodule_iConvexComb (S : F) (w : StdSimplex R I) (f : I → S) :
91+
(↑(w.iConvexComb f) : M) = w.iConvexComb (fun i ↦ (f i).val) := subtypeVal_iConvexComb ..
92+
93+
lemma subtypeVal_submodule_convexCombPair (S : F) (a b : R) (ha hb hab) (x y : S) :
94+
(↑(convexCombPair a b ha hb hab x y) : M) = convexCombPair a b ha hb hab x.val y.val :=
95+
subtypeVal_convexCombPair ..
96+
97+
instance (S : F) : IsModuleConvexSpace R S where sConvexComb_eq_sum w := by ext; simp [Finsupp.sum]
98+
7899
instance [ConvexSpace R N] [IsModuleConvexSpace R N] : IsModuleConvexSpace R (M × N) where
79100
sConvexComb_eq_sum w := by ext <;> simp [Finsupp.sum, Prod.fst_sum, Prod.snd_sum]
80101

Mathlib/Geometry/Convex/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ See the `Mathlib.Analysis.Convex` folder for the results that need a norm or an
88

99
The topics currently covered are:
1010
* Convex spaces
11+
* Convex sets
1112
* Cones

0 commit comments

Comments
 (0)