-
Notifications
You must be signed in to change notification settings - Fork 259
/
Proper.lean
293 lines (229 loc) Β· 11.1 KB
/
Proper.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/-
Copyright (c) 2022 Apurva Nakade. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Apurva Nakade
-/
import Mathlib.Analysis.Convex.Cone.Closure
import Mathlib.Analysis.InnerProductSpace.Adjoint
#align_import analysis.convex.cone.proper from "leanprover-community/mathlib"@"147b294346843885f952c5171e9606616a8fd869"
/-!
# Proper cones
We define a *proper cone* as a closed, pointed cone. Proper cones are used in defining conic
programs which generalize linear programs. A linear program is a conic program for the positive
cone. We then prove Farkas' lemma for conic programs following the proof in the reference below.
Farkas' lemma is equivalent to strong duality. So, once we have the definitions of conic and
linear programs, the results from this file can be used to prove duality theorems.
## TODO
The next steps are:
- Add convex_cone_class that extends set_like and replace the below instance
- Define primal and dual cone programs and prove weak duality.
- Prove regular and strong duality for cone programs using Farkas' lemma (see reference).
- Define linear programs and prove LP duality as a special case of cone duality.
- Find a better reference (textbook instead of lecture notes).
## References
- [B. Gartner and J. Matousek, Cone Programming][gartnerMatousek]
-/
open ContinuousLinearMap Filter Set
/-- A proper cone is a pointed cone `K` that is closed. Proper cones have the nice property that
they are equal to their double dual, see `ProperCone.dual_dual`.
This makes them useful for defining cone programs and proving duality theorems. -/
structure ProperCone (π : Type*) (E : Type*) [OrderedSemiring π] [AddCommMonoid E]
[TopologicalSpace E] [Module π E] extends Submodule {c : π // 0 β€ c} E where
isClosed' : IsClosed (carrier : Set E)
#align proper_cone ProperCone
namespace ProperCone
section Module
variable {π : Type*} [OrderedSemiring π]
variable {E : Type*} [AddCommMonoid E] [TopologicalSpace E] [Module π E]
/-- A `PointedCone` is defined as an alias of submodule. We replicate the abbreviation here and
define `toPointedCone` as an alias of `toSubmodule`. -/
abbrev toPointedCone (C : ProperCone π E) := C.toSubmodule
attribute [coe] toPointedCone
instance : Coe (ProperCone π E) (PointedCone π E) :=
β¨toPointedConeβ©
-- Porting note: now a syntactic tautology
-- @[simp]
-- theorem toConvexCone_eq_coe (K : ProperCone π E) : K.toConvexCone = K :=
-- rfl
#noalign proper_cone.to_convex_cone_eq_coe
theorem toPointedCone_injective : Function.Injective ((β) : ProperCone π E β PointedCone π E) :=
fun S T h => by cases S; cases T; congr
#align proper_cone.ext' ProperCone.toPointedCone_injective
-- TODO: add `ConvexConeClass` that extends `SetLike` and replace the below instance
instance : SetLike (ProperCone π E) E where
coe K := K.carrier
coe_injective' _ _ h := ProperCone.toPointedCone_injective (SetLike.coe_injective h)
@[ext]
theorem ext {S T : ProperCone π E} (h : β x, x β S β x β T) : S = T :=
SetLike.ext h
#align proper_cone.ext ProperCone.ext
@[simp]
theorem mem_coe {x : E} {K : ProperCone π E} : x β (K : PointedCone π E) β x β K :=
Iff.rfl
#align proper_cone.mem_coe ProperCone.mem_coe
instance instZero (K : ProperCone π E) : Zero K := PointedCone.instZero (K.toSubmodule)
protected theorem nonempty (K : ProperCone π E) : (K : Set E).Nonempty :=
β¨0, by { simp_rw [SetLike.mem_coe, β ProperCone.mem_coe, Submodule.zero_mem] }β©
#align proper_cone.nonempty ProperCone.nonempty
protected theorem isClosed (K : ProperCone π E) : IsClosed (K : Set E) :=
K.isClosed'
#align proper_cone.is_closed ProperCone.isClosed
end Module
section PositiveCone
variable (π E)
variable [OrderedSemiring π] [OrderedAddCommGroup E] [Module π E] [OrderedSMul π E]
[TopologicalSpace E] [OrderClosedTopology E]
/-- The positive cone is the proper cone formed by the set of nonnegative elements in an ordered
module. -/
def positive : ProperCone π E where
toSubmodule := PointedCone.positive π E
isClosed' := isClosed_Ici
@[simp]
theorem mem_positive {x : E} : x β positive π E β 0 β€ x :=
Iff.rfl
@[simp]
theorem coe_positive : β(positive π E) = ConvexCone.positive π E :=
rfl
end PositiveCone
section Module
variable {π : Type*} [OrderedSemiring π]
variable {E : Type*} [AddCommMonoid E] [TopologicalSpace E] [T1Space E] [Module π E]
instance : Zero (ProperCone π E) :=
β¨{ toSubmodule := 0
isClosed' := isClosed_singleton }β©
instance : Inhabited (ProperCone π E) :=
β¨0β©
@[simp]
theorem mem_zero (x : E) : x β (0 : ProperCone π E) β x = 0 :=
Iff.rfl
#align proper_cone.mem_zero ProperCone.mem_zero
@[simp, norm_cast]
theorem coe_zero : β(0 : ProperCone π E) = (0 : ConvexCone π E) :=
rfl
#align proper_cone.coe_zero ProperCone.coe_zero
theorem pointed_zero : ((0 : ProperCone π E) : ConvexCone π E).Pointed := by
simp [ConvexCone.pointed_zero]
#align proper_cone.pointed_zero ProperCone.pointed_zero
end Module
section InnerProductSpace
variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace β E]
variable {F : Type*} [NormedAddCommGroup F] [InnerProductSpace β F]
variable {G : Type*} [NormedAddCommGroup G] [InnerProductSpace β G]
protected theorem pointed (K : ProperCone β E) : (K : ConvexCone β E).Pointed :=
(K : ConvexCone β E).pointed_of_nonempty_of_isClosed K.nonempty K.isClosed
#align proper_cone.pointed ProperCone.pointed
/-- The closure of image of a proper cone under a continuous `β`-linear map is a proper cone. We
use continuous maps here so that the comap of f is also a map between proper cones. -/
noncomputable def map (f : E βL[β] F) (K : ProperCone β E) : ProperCone β F where
toSubmodule := PointedCone.closure (PointedCone.map (f : E ββ[β] F) βK)
isClosed' := isClosed_closure
#align proper_cone.map ProperCone.map
@[simp, norm_cast]
theorem coe_map (f : E βL[β] F) (K : ProperCone β E) :
β(K.map f) = (PointedCone.map (f : E ββ[β] F) βK).closure :=
rfl
#align proper_cone.coe_map ProperCone.coe_map
@[simp]
theorem mem_map {f : E βL[β] F} {K : ProperCone β E} {y : F} :
y β K.map f β y β (PointedCone.map (f : E ββ[β] F) βK).closure :=
Iff.rfl
#align proper_cone.mem_map ProperCone.mem_map
@[simp]
theorem map_id (K : ProperCone β E) : K.map (ContinuousLinearMap.id β E) = K :=
ProperCone.toPointedCone_injective <| by simpa using IsClosed.closure_eq K.isClosed
#align proper_cone.map_id ProperCone.map_id
/-- The inner dual cone of a proper cone is a proper cone. -/
def dual (K : ProperCone β E) : ProperCone β E where
toSubmodule := PointedCone.dual (K : PointedCone β E)
isClosed' := isClosed_innerDualCone _
#align proper_cone.dual ProperCone.dual
@[simp, norm_cast]
theorem coe_dual (K : ProperCone β E) : K.dual = (K : Set E).innerDualCone :=
rfl
#align proper_cone.coe_dual ProperCone.coe_dual
@[simp]
theorem mem_dual {K : ProperCone β E} {y : E} : y β dual K β β β¦xβ¦, x β K β 0 β€ βͺx, yβ«_β := by
aesop
#align proper_cone.mem_dual ProperCone.mem_dual
/-- The preimage of a proper cone under a continuous `β`-linear map is a proper cone. -/
noncomputable def comap (f : E βL[β] F) (S : ProperCone β F) : ProperCone β E where
toSubmodule := PointedCone.comap (f : E ββ[β] F) S
isClosed' := by
rw [PointedCone.comap]
apply IsClosed.preimage f.2 S.isClosed
#align proper_cone.comap ProperCone.comap
@[simp]
theorem coe_comap (f : E βL[β] F) (S : ProperCone β F) : (S.comap f : Set E) = f β»ΒΉ' S :=
rfl
#align proper_cone.coe_comap ProperCone.coe_comap
@[simp]
theorem comap_id (S : ConvexCone β E) : S.comap LinearMap.id = S :=
SetLike.coe_injective preimage_id
#align proper_cone.comap_id ProperCone.comap_id
theorem comap_comap (g : F βL[β] G) (f : E βL[β] F) (S : ProperCone β G) :
(S.comap g).comap f = S.comap (g.comp f) :=
SetLike.coe_injective <| by congr
#align proper_cone.comap_comap ProperCone.comap_comap
@[simp]
theorem mem_comap {f : E βL[β] F} {S : ProperCone β F} {x : E} : x β S.comap f β f x β S :=
Iff.rfl
#align proper_cone.mem_comap ProperCone.mem_comap
end InnerProductSpace
section CompleteSpace
variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace β E] [CompleteSpace E]
variable {F : Type*} [NormedAddCommGroup F] [InnerProductSpace β F] [CompleteSpace F]
/-- The dual of the dual of a proper cone is itself. -/
@[simp]
theorem dual_dual (K : ProperCone β E) : K.dual.dual = K :=
ProperCone.toPointedCone_injective <| PointedCone.toConvexCone_injective <|
(K : ConvexCone β E).innerDualCone_of_innerDualCone_eq_self K.nonempty K.isClosed
#align proper_cone.dual_dual ProperCone.dual_dual
/-- This is a relative version of
`ConvexCone.hyperplane_separation_of_nonempty_of_isClosed_of_nmem`, which we recover by setting
`f` to be the identity map. This is also a geometric interpretation of the Farkas' lemma
stated using proper cones. -/
theorem hyperplane_separation (K : ProperCone β E) {f : E βL[β] F} {b : F} :
b β K.map f β β y : F, adjoint f y β K.dual β 0 β€ βͺy, bβ«_β :=
Iff.intro
(by
-- suppose `b β K.map f`
simp_rw [mem_map, PointedCone.mem_closure, PointedCone.coe_map, coe_coe,
mem_closure_iff_seq_limit, mem_image, SetLike.mem_coe, mem_coe, mem_dual,
adjoint_inner_right, forall_exists_index, and_imp]
-- there is a sequence `seq : β β F` in the image of `f` that converges to `b`
rintro seq hmem htends y hinner
suffices h : β n, 0 β€ βͺy, seq nβ«_β from
ge_of_tendsto'
(Continuous.seqContinuous (Continuous.inner (@continuous_const _ _ _ _ y) continuous_id)
htends)
h
intro n
obtain β¨_, h, hseqβ© := hmem n
simpa only [β hseq, real_inner_comm] using hinner h)
(by
-- proof by contradiction
-- suppose `b β K.map f`
intro h
contrapose! h
-- as `b β K.map f`, there is a hyperplane `y` separating `b` from `K.map f`
let C := @PointedCone.toConvexCone β F _ _ _ (K.map f)
obtain β¨y, hxy, hybβ© :=
@ConvexCone.hyperplane_separation_of_nonempty_of_isClosed_of_nmem
_ _ _ _ C (K.map f).nonempty (K.map f).isClosed b h
-- the rest of the proof is a straightforward algebraic manipulation
refine β¨y, ?_, hybβ©
simp_rw [ProperCone.mem_dual, adjoint_inner_right]
intro x hxK
apply hxy (f x)
simp_rw [C, coe_map]
apply subset_closure
simp_rw [PointedCone.toConvexCone_map, ConvexCone.coe_map, coe_coe, mem_image,
SetLike.mem_coe]
exact β¨x, hxK, rflβ©)
#align proper_cone.hyperplane_separation ProperCone.hyperplane_separation
theorem hyperplane_separation_of_nmem (K : ProperCone β E) {f : E βL[β] F} {b : F}
(disj : b β K.map f) : β y : F, adjoint f y β K.dual β§ βͺy, bβ«_β < 0 := by
contrapose! disj; rwa [K.hyperplane_separation]
#align proper_cone.hyperplane_separation_of_nmem ProperCone.hyperplane_separation_of_nmem
end CompleteSpace
end ProperCone