Update from HH
[Multivariate Analysis/.git] / Multivariate / convex.ml
1 (* ========================================================================= *)
2 (* Convex sets, functions and related things.                                *)
3 (*                                                                           *)
4 (*              (c) Copyright, John Harrison 1998-2008                       *)
5 (*                 (c) Copyright, Lars Schewe 2007                           *)
6 (*              (c) Copyright, Valentina Bruno 2010                          *)
7 (* ========================================================================= *)
8
9 needs "Multivariate/topology.ml";;
10
11 (* ------------------------------------------------------------------------- *)
12 (* Some miscelleneous things that are convenient to prove here.              *)
13 (* ------------------------------------------------------------------------- *)
14
15 let TRANSLATION_GALOIS = prove
16  (`!s t a:real^N. s = IMAGE (\x. a + x) t <=> t = IMAGE (\x. --a + x) s`,
17   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN
18   ASM_REWRITE_TAC[GSYM IMAGE_o; o_DEF] THEN
19   REWRITE_TAC[VECTOR_ARITH `--a + a + x:real^N = x`;
20               VECTOR_ARITH `a + --a + x:real^N = x`] THEN
21   REWRITE_TAC[IMAGE_ID]);;
22
23 let TRANSLATION_EQ_IMP = prove
24  (`!P:(real^N->bool)->bool.
25         (!a s. P(IMAGE (\x. a + x) s) <=> P s) <=>
26         (!a s. P s ==> P (IMAGE (\x. a + x) s))`,
27   REPEAT GEN_TAC THEN EQ_TAC THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
28   MAP_EVERY X_GEN_TAC [`a:real^N`; `s:real^N->bool`] THEN
29   EQ_TAC THEN ASM_REWRITE_TAC[] THEN DISCH_TAC THEN FIRST_X_ASSUM
30    (MP_TAC o SPECL [`--a:real^N`; `IMAGE (\x:real^N. a + x) s`]) THEN
31   ASM_REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID;
32                   VECTOR_ARITH `--a + a + x:real^N = x`]);;
33
34 let DIM_HYPERPLANE = prove
35  (`!a:real^N. ~(a = vec 0) ==> dim {x | a dot x = &0} = dimindex(:N) - 1`,
36   GEOM_BASIS_MULTIPLE_TAC 1 `a:real^N` THEN
37   SIMP_TAC[VECTOR_MUL_EQ_0; DE_MORGAN_THM; DOT_LMUL; DOT_BASIS;
38            DIMINDEX_GE_1; LE_REFL; REAL_ENTIRE; DIM_SPECIAL_HYPERPLANE]);;
39
40 let LOWDIM_EQ_HYPERPLANE = prove
41  (`!s. dim s = dimindex(:N) - 1
42        ==> ?a:real^N. ~(a = vec 0) /\ span s = {x | a dot x = &0}`,
43   REPEAT STRIP_TAC THEN
44   MP_TAC(ISPEC `s:real^N->bool` LOWDIM_SUBSET_HYPERPLANE) THEN
45   ASM_SIMP_TAC[DIMINDEX_GE_1; ARITH_RULE `1 <= a ==> a - 1 < a`] THEN
46   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN STRIP_TAC THEN
47   ASM_REWRITE_TAC[] THEN
48   MP_TAC(ISPEC `a:real^N` SUBSPACE_HYPERPLANE) THEN
49   ONCE_REWRITE_TAC[GSYM SPAN_EQ_SELF] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
50   MATCH_MP_TAC DIM_EQ_SPAN THEN
51   ASM_SIMP_TAC[DIM_HYPERPLANE; LE_REFL] THEN
52   ASM_MESON_TAC[SUBSET_TRANS; SPAN_INC]);;
53
54 let DIM_EQ_HYPERPLANE = prove
55  (`!s. dim s = dimindex(:N) - 1 <=>
56        ?a:real^N. ~(a = vec 0) /\ span s = {x | a dot x = &0}`,
57   MESON_TAC[DIM_HYPERPLANE; LOWDIM_EQ_HYPERPLANE; DIM_SPAN]);;
58
59 (* ------------------------------------------------------------------------- *)
60 (* Affine set and affine hull.                                               *)
61 (* ------------------------------------------------------------------------- *)
62
63 let affine = new_definition
64   `affine s <=> !x y u v. x IN s /\ y IN s /\ (u + v = &1)
65                           ==> (u % x + v % y) IN s`;;
66
67 let AFFINE_ALT = prove
68  (`affine s <=> !x y u. x IN s /\ y IN s ==> ((&1 - u) % x + u % y) IN s`,
69   REWRITE_TAC[affine] THEN
70   MESON_TAC[REAL_ARITH `(u + v = &1) <=> (u = &1 - v)`]);;
71
72 let AFFINE_SCALING = prove
73  (`!s c. affine s ==> affine (IMAGE (\x. c % x) s)`,
74   REWRITE_TAC[affine; IN_IMAGE] THEN REPEAT STRIP_TAC THEN
75   ASM_REWRITE_TAC[VECTOR_ARITH
76    `u % c % x + v % c % y = c % (u % x + v % y)`] THEN
77   ASM_MESON_TAC[]);;
78
79 let AFFINE_SCALING_EQ = prove
80  (`!s c. ~(c = &0) ==> (affine (IMAGE (\x. c % x) s) <=> affine s)`,
81   REPEAT STRIP_TAC THEN EQ_TAC THEN REWRITE_TAC[AFFINE_SCALING] THEN
82   DISCH_THEN(MP_TAC o SPEC `inv c` o MATCH_MP AFFINE_SCALING) THEN
83   ASM_SIMP_TAC[GSYM IMAGE_o; o_DEF; VECTOR_MUL_ASSOC;
84                REAL_MUL_LINV; VECTOR_MUL_LID; IMAGE_ID]);;
85
86 let AFFINE_NEGATIONS = prove
87  (`!s. affine s ==> affine (IMAGE (--) s)`,
88   REWRITE_TAC[affine; IN_IMAGE] THEN REPEAT STRIP_TAC THEN
89   ASM_REWRITE_TAC[VECTOR_ARITH
90    `u % --x + v % --y = --(u % x + v % y)`] THEN
91   ASM_MESON_TAC[]);;
92
93 let AFFINE_SUMS = prove
94  (`!s t. affine s /\ affine t ==> affine {x + y | x IN s /\ y IN t}`,
95   REWRITE_TAC[affine; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
96   ASM_REWRITE_TAC[VECTOR_ARITH
97     `u % (a + b) + v % (c + d) = (u % a + v % c) + (u % b + v % d)`] THEN
98   ASM_MESON_TAC[]);;
99
100 let AFFINE_DIFFERENCES = prove
101  (`!s t. affine s /\ affine t ==> affine {x - y | x IN s /\ y IN t}`,
102   REWRITE_TAC[affine; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
103   ASM_REWRITE_TAC[VECTOR_ARITH
104     `u % (a - b) + v % (c - d) = (u % a + v % c) - (u % b + v % d)`] THEN
105   ASM_MESON_TAC[]);;
106
107 let AFFINE_TRANSLATION_EQ = prove
108  (`!a:real^N s. affine (IMAGE (\x. a + x) s) <=> affine s`,
109   REWRITE_TAC[AFFINE_ALT; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
110   REWRITE_TAC[IN_IMAGE; UNWIND_THM1; VECTOR_ARITH
111    `(&1 - u) % (a + x) + u % (a + y) = a + z <=> (&1 - u) % x + u % y = z`]);;
112
113 add_translation_invariants [AFFINE_TRANSLATION_EQ];;
114
115 let AFFINE_TRANSLATION = prove
116  (`!s a:real^N. affine s ==> affine (IMAGE (\x. a + x) s)`,
117   REWRITE_TAC[AFFINE_TRANSLATION_EQ]);;
118
119 let AFFINE_AFFINITY = prove
120  (`!s a:real^N c.
121         affine s ==> affine (IMAGE (\x. a + c % x) s)`,
122   REPEAT STRIP_TAC THEN
123   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
124   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
125   ASM_SIMP_TAC[IMAGE_o; AFFINE_TRANSLATION; AFFINE_SCALING]);;
126
127 let AFFINE_LINEAR_IMAGE = prove
128  (`!f s. affine s /\ linear f ==> affine(IMAGE f s)`,
129   REWRITE_TAC[affine; FORALL_IN_IMAGE; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
130   REWRITE_TAC[IN_IMAGE; linear] THEN MESON_TAC[]);;
131
132 let AFFINE_LINEAR_IMAGE_EQ = prove
133  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
134          ==> (affine (IMAGE f s) <=> affine s)`,
135   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE AFFINE_LINEAR_IMAGE));;
136
137 add_linear_invariants [AFFINE_LINEAR_IMAGE_EQ];;
138
139 let AFFINE_EMPTY = prove
140  (`affine {}`,
141   REWRITE_TAC[affine; NOT_IN_EMPTY]);;
142
143 let AFFINE_SING = prove
144  (`!x. affine {x}`,
145   SIMP_TAC[AFFINE_ALT; IN_SING] THEN
146   REWRITE_TAC[GSYM VECTOR_ADD_RDISTRIB] THEN
147   REWRITE_TAC[REAL_SUB_ADD; VECTOR_MUL_LID]);;
148
149 let AFFINE_UNIV = prove
150  (`affine(UNIV:real^N->bool)`,
151   REWRITE_TAC[affine; IN_UNIV]);;
152
153 let AFFINE_HYPERPLANE = prove
154  (`!a b. affine {x | a dot x = b}`,
155   REWRITE_TAC[affine; IN_ELIM_THM; DOT_RADD; DOT_RMUL] THEN
156   CONV_TAC REAL_RING);;
157
158 let AFFINE_STANDARD_HYPERPLANE = prove
159  (`!a b k. affine {x:real^N | x$k = b}`,
160   REPEAT GEN_TAC THEN
161   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
162   CHOOSE_TAC THENL
163    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
164   MP_TAC(ISPECL [`basis i:real^N`; `b:real`] AFFINE_HYPERPLANE) THEN
165   ASM_SIMP_TAC[DOT_BASIS]);;
166
167 let AFFINE_INTERS = prove
168  (`(!s. s IN f ==> affine s) ==> affine(INTERS f)`,
169   REWRITE_TAC[affine; IN_INTERS] THEN MESON_TAC[]);;
170
171 let AFFINE_INTER = prove
172  (`!s t. affine s /\ affine t ==> affine(s INTER t)`,
173   REWRITE_TAC[affine; IN_INTER] THEN MESON_TAC[]);;
174
175 let AFFINE_AFFINE_HULL = prove
176  (`!s. affine(affine hull s)`,
177   SIMP_TAC[P_HULL; AFFINE_INTERS]);;
178
179 let AFFINE_HULL_EQ = prove
180  (`!s. (affine hull s = s) <=> affine s`,
181   SIMP_TAC[HULL_EQ; AFFINE_INTERS]);;
182
183 let IS_AFFINE_HULL = prove
184  (`!s. affine s <=> ?t. s = affine hull t`,
185   GEN_TAC THEN MATCH_MP_TAC IS_HULL THEN SIMP_TAC[AFFINE_INTERS]);;
186
187 let AFFINE_HULL_UNIV = prove
188  (`affine hull (:real^N) = (:real^N)`,
189   REWRITE_TAC[AFFINE_HULL_EQ; AFFINE_UNIV]);;
190
191 let AFFINE_HULLS_EQ = prove
192  (`!s t. s SUBSET affine hull t /\ t SUBSET affine hull s
193          ==> affine hull s = affine hull t`,
194   REPEAT STRIP_TAC THEN MATCH_MP_TAC HULLS_EQ THEN
195   ASM_SIMP_TAC[AFFINE_INTERS]);;
196
197 let AFFINE_HULL_TRANSLATION = prove
198  (`!a s. affine hull (IMAGE (\x. a + x) s) =
199          IMAGE (\x. a + x) (affine hull s)`,
200   REWRITE_TAC[hull] THEN GEOM_TRANSLATE_TAC[]);;
201
202 add_translation_invariants [AFFINE_HULL_TRANSLATION];;
203
204 let AFFINE_HULL_LINEAR_IMAGE = prove
205  (`!f s. linear f
206          ==> affine hull (IMAGE f s) = IMAGE f (affine hull s)`,
207   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
208   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
209   CONJ_TAC THEN MATCH_MP_TAC HULL_INDUCT THEN
210   REWRITE_TAC[FORALL_IN_IMAGE] THEN SIMP_TAC[FUN_IN_IMAGE; HULL_INC] THEN
211   REWRITE_TAC[affine; IN_ELIM_THM] THEN
212   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THENL
213    [FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_CMUL th)]) THEN
214     FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_ADD th)]) THEN
215     REWRITE_TAC[IN_IMAGE] THEN
216     MESON_TAC[REWRITE_RULE[affine] AFFINE_AFFINE_HULL];
217     ASM_SIMP_TAC[LINEAR_ADD; LINEAR_CMUL] THEN
218     MESON_TAC[REWRITE_RULE[affine] AFFINE_AFFINE_HULL]]);;
219
220 add_linear_invariants [AFFINE_HULL_LINEAR_IMAGE];;
221
222 let IN_AFFINE_HULL_LINEAR_IMAGE = prove
223  (`!f:real^M->real^N s x.
224         linear f /\ x IN affine hull s ==> (f x) IN affine hull (IMAGE f s)`,
225   SIMP_TAC[AFFINE_HULL_LINEAR_IMAGE] THEN SET_TAC[]);;
226
227 let SAME_DISTANCES_TO_AFFINE_HULL = prove
228  (`!s a b:real^N.
229         (!x. x IN s ==> dist(x,a) = dist(x,b))
230         ==> (!x. x IN affine hull s ==> dist(x,a) = dist(x,b))`,
231   REPEAT GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC HULL_INDUCT THEN
232   ASM_REWRITE_TAC[AFFINE_ALT; IN_ELIM_THM] THEN
233   REWRITE_TAC[dist; NORM_EQ_SQUARE; NORM_POS_LE; VECTOR_ARITH
234    `((&1 - u) % x + u % y) - a:real^N = (&1 - u) % (x - a) + u % (y - a)`] THEN
235   REWRITE_TAC[NORM_POW_2; DOT_LMUL; DOT_RMUL; VECTOR_ARITH
236    `(x + y) dot (x + y):real^N = (x dot x + y dot y) + &2 * x dot y`] THEN
237   SIMP_TAC[DOT_LSUB; DOT_RSUB; DOT_SYM] THEN CONV_TAC REAL_RING);;
238
239 (* ------------------------------------------------------------------------- *)
240 (* Some convenient lemmas about common affine combinations.                  *)
241 (* ------------------------------------------------------------------------- *)
242
243 let IN_AFFINE_ADD_MUL = prove
244  (`!s a x:real^N d. affine s /\ a IN s /\ (a + x) IN s ==> (a + d % x) IN s`,
245   REWRITE_TAC[affine] THEN REPEAT STRIP_TAC THEN
246   SUBST1_TAC(VECTOR_ARITH `a + d % x:real^N = (&1 - d) % a + d % (a + x)`) THEN
247   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
248
249 let IN_AFFINE_ADD_MUL_DIFF = prove
250  (`!s a x y z:real^N.
251         affine s /\ x IN s /\ y IN s /\ z IN s ==> (x + a % (y - z)) IN s`,
252   REWRITE_TAC[affine] THEN REPEAT STRIP_TAC THEN
253   REWRITE_TAC[VECTOR_ARITH
254    `x + a % (y - z):real^N =
255     &1 / &2 % ((&1 - &2 * a) % x + (&2 * a) % y) +
256     &1 / &2 % ((&1 + &2 * a) % x + (-- &2 * a) % z)`] THEN
257   FIRST_ASSUM MATCH_MP_TAC THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
258   CONJ_TAC THEN FIRST_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
259   REAL_ARITH_TAC);;
260
261 let IN_AFFINE_MUL_DIFF_ADD = prove
262  (`!s a x y z:real^N.
263         affine s /\ x IN s /\ y IN s /\ z IN s ==> a % (x - y) + z IN s`,
264   ONCE_REWRITE_TAC[VECTOR_ADD_SYM] THEN
265   SIMP_TAC[IN_AFFINE_ADD_MUL_DIFF]);;
266
267 let IN_AFFINE_SUB_MUL_DIFF = prove
268  (`!s a x y z:real^N.
269         affine s /\ x IN s /\ y IN s /\ z IN s ==> x - a % (y - z) IN s`,
270   REWRITE_TAC[VECTOR_ARITH `x - a % (y - z):real^N = x + a % (z - y)`] THEN
271   SIMP_TAC[IN_AFFINE_ADD_MUL_DIFF]);;
272
273 let AFFINE_DIFFS_SUBSPACE = prove
274  (`!s:real^N->bool a.
275         affine s /\ a IN s ==> subspace {x - a | x IN s}`,
276   REWRITE_TAC[subspace; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
277   REWRITE_TAC[FORALL_IN_GSPEC] THEN REWRITE_TAC[IN_ELIM_THM] THEN
278   REWRITE_TAC[VECTOR_ARITH `vec 0:real^N = x - a <=> x = a`;
279               VECTOR_ARITH `x - a + y - a:real^N = z - a <=>
280                             z = (a + &1 % (x - a)) + &1 % (y - a)`;
281               VECTOR_ARITH `c % (x - a):real^N = y - a <=>
282                             y = a + c % (x - a)`] THEN
283   MESON_TAC[IN_AFFINE_ADD_MUL_DIFF]);;
284
285 (* ------------------------------------------------------------------------- *)
286 (* Explicit formulations for affine combinations.                            *)
287 (* ------------------------------------------------------------------------- *)
288
289 let AFFINE_VSUM = prove
290  (`!s k u x:A->real^N.
291         FINITE k /\ affine s /\ sum k u = &1 /\ (!i. i IN k ==> x i IN s)
292         ==> vsum k (\i. u i % x i) IN s`,
293   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
294    [ASM_REWRITE_TAC[NOT_IN_EMPTY; GSYM NOT_EXISTS_THM; MEMBER_NOT_EMPTY] THEN
295     ASM_CASES_TAC `k:A->bool = {}` THEN ASM_REWRITE_TAC[SUM_CLAUSES] THEN
296     REAL_ARITH_TAC;
297     ALL_TAC] THEN
298   STRIP_TAC THEN
299   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
300   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
301   MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`] AFFINE_DIFFS_SUBSPACE) THEN
302   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
303   MP_TAC(ISPECL [`{x - a:real^N | x IN s}`;
304                  `(\i. u i % (x i - a)):A->real^N`;
305                  `k:A->bool`] SUBSPACE_VSUM) THEN
306   ANTS_TAC THENL
307    [ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
308     MATCH_MP_TAC SUBSPACE_MUL THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
309     ASM_SIMP_TAC[VSUM_SUB; IN_ELIM_THM; VECTOR_SUB_LDISTRIB; VSUM_RMUL] THEN
310     REWRITE_TAC[VECTOR_ARITH `x - &1 % a:real^N = y - a <=> x = y`] THEN
311     ASM_MESON_TAC[]]);;
312
313 let AFFINE_INDEXED = prove
314  (`!s:real^N->bool.
315         affine s <=>
316             !k u x. (!i:num. 1 <= i /\ i <= k ==> x(i) IN s) /\
317                     (sum (1..k) u = &1)
318                     ==> vsum (1..k) (\i. u(i) % x(i)) IN s`,
319   REPEAT GEN_TAC THEN EQ_TAC THENL
320    [REPEAT STRIP_TAC THEN MATCH_MP_TAC AFFINE_VSUM THEN
321     ASM_REWRITE_TAC[IN_NUMSEG; FINITE_NUMSEG];
322     DISCH_TAC THEN REWRITE_TAC[affine] THEN
323     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
324     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `2`) THEN
325     DISCH_THEN(MP_TAC o SPEC `\n. if n = 1 then u else v:real`) THEN
326     DISCH_THEN(MP_TAC o SPEC `\n. if n = 1 then x else y:real^N`) THEN
327     REWRITE_TAC[num_CONV `2`; SUM_CLAUSES_NUMSEG; VSUM_CLAUSES_NUMSEG;
328       NUMSEG_SING; VSUM_SING; SUM_SING] THEN REWRITE_TAC[ARITH] THEN
329     ASM_MESON_TAC[]]);;
330
331 let AFFINE_HULL_INDEXED = prove
332  (`!s. affine hull s =
333         {y:real^N | ?k u x. (!i. 1 <= i /\ i <= k ==> x i IN s) /\
334                             (sum (1..k) u = &1) /\
335                             (vsum (1..k) (\i. u i % x i) = y)}`,
336   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN REPEAT CONJ_TAC THENL
337    [REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
338     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
339     MAP_EVERY EXISTS_TAC [`1`; `\i:num. &1`; `\i:num. x:real^N`] THEN
340     ASM_SIMP_TAC[FINITE_RULES; IN_SING; SUM_SING; VECTOR_MUL_LID; VSUM_SING;
341                  REAL_POS; NUMSEG_SING];
342     ALL_TAC;
343     REWRITE_TAC[AFFINE_INDEXED; SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
344     MESON_TAC[]] THEN
345   REWRITE_TAC[affine; IN_ELIM_THM] THEN
346   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
347   REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
348   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC
349    [`k1:num`; `u1:num->real`; `x1:num->real^N`;
350     `k2:num`; `u2:num->real`; `x2:num->real^N`] THEN
351   STRIP_TAC THEN EXISTS_TAC `k1 + k2:num` THEN
352   EXISTS_TAC `\i:num. if i <= k1 then u * u1(i) else v * u2(i - k1):real` THEN
353   EXISTS_TAC `\i:num. if i <= k1 then x1(i) else x2(i - k1):real^N` THEN
354   ASM_SIMP_TAC[NUMSEG_ADD_SPLIT; ARITH_RULE `1 <= x + 1 /\ x < x + 1`;
355    IN_NUMSEG; SUM_UNION; VSUM_UNION; FINITE_NUMSEG; DISJOINT_NUMSEG;
356    ARITH_RULE `k1 + 1 <= i ==> ~(i <= k1)`] THEN
357   REWRITE_TAC[ONCE_REWRITE_RULE[ADD_SYM] NUMSEG_OFFSET_IMAGE] THEN
358   ASM_SIMP_TAC[SUM_IMAGE; VSUM_IMAGE; EQ_ADD_LCANCEL; FINITE_NUMSEG] THEN
359   ASM_SIMP_TAC[o_DEF; ADD_SUB2; SUM_LMUL; VSUM_LMUL; GSYM VECTOR_MUL_ASSOC;
360                FINITE_NUMSEG; REAL_MUL_RID] THEN
361   ASM_MESON_TAC[REAL_LE_MUL; ARITH_RULE
362     `i <= k1 + k2 /\ ~(i <= k1) ==> 1 <= i - k1 /\ i - k1 <= k2`]);;
363
364 let AFFINE = prove
365  (`!V:real^N->bool.
366      affine V <=>
367          !(s:real^N->bool) (u:real^N->real).
368              FINITE s /\ ~(s = {}) /\ s SUBSET V /\ sum s u = &1
369              ==> vsum s (\x. u x % x) IN V`,
370   GEN_TAC THEN EQ_TAC THENL
371    [REPEAT STRIP_TAC THEN MATCH_MP_TAC AFFINE_VSUM THEN
372     ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
373     REWRITE_TAC[affine] THEN DISCH_TAC THEN
374     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
375     STRIP_TAC THEN ASM_CASES_TAC `x:real^N = y` THENL
376      [FIRST_X_ASSUM SUBST_ALL_TAC THEN
377       ASM_REWRITE_TAC[GSYM VECTOR_ADD_RDISTRIB;VECTOR_MUL_LID];ALL_TAC] THEN
378      FIRST_X_ASSUM(MP_TAC o SPEC `{x:real^N,y}`) THEN
379     DISCH_THEN(MP_TAC o SPEC `\w. if w = x:real^N then u else v:real`) THEN
380     ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FINITE_RULES; NUMSEG_SING;
381                  VSUM_SING; SUM_SING;SUBSET;IN_INSERT;NOT_IN_EMPTY] THEN
382     ASM SET_TAC[]]);;
383
384 let AFFINE_EXPLICIT = prove
385  (`!s:real^N->bool.
386         affine s <=>
387             !t u. FINITE t /\ t SUBSET s /\ sum t u = &1
388                   ==> vsum t (\x. u(x) % x) IN s`,
389   GEN_TAC THEN REWRITE_TAC[AFFINE] THEN
390   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
391   X_GEN_TAC `t:real^N->bool` THEN REWRITE_TAC[] THEN
392   AP_TERM_TAC THEN ABS_TAC THEN
393   ASM_CASES_TAC `t:real^N->bool = {}` THEN
394   ASM_REWRITE_TAC[SUM_CLAUSES] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
395
396 let AFFINE_HULL_EXPLICIT = prove
397  (`!(p:real^N -> bool).
398         affine hull p =
399          {y | ?s u. FINITE s /\ ~(s = {}) /\ s SUBSET p /\
400                     sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
401   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN REPEAT CONJ_TAC THENL
402    [REWRITE_TAC[SUBSET;IN_ELIM_THM] THEN
403     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
404     MAP_EVERY EXISTS_TAC [`{x:real^N}`;`\v:real^N. &1:real`] THEN
405     ASM_SIMP_TAC[FINITE_RULES;IN_SING;SUM_SING;VSUM_SING;VECTOR_MUL_LID] THEN
406     SET_TAC[];
407     REWRITE_TAC[affine;IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
408     EXISTS_TAC `(s UNION s'):real^N->bool` THEN
409     EXISTS_TAC
410       `\a:real^N. (\b:real^N.if (b IN s) then (u * (u' b)) else &0) a +
411                   (\b:real^N.if (b IN s') then v * (u'' b) else &0) a` THEN
412     REPEAT CONJ_TAC THENL
413      [ASM_REWRITE_TAC[FINITE_UNION];
414       ASM SET_TAC[];
415       ASM_REWRITE_TAC[UNION_SUBSET];
416       ASM_SIMP_TAC[REWRITE_RULE[REAL_ARITH `a + b = c + d <=> c = a + b - d`]
417                    SUM_INCL_EXCL; GSYM SUM_RESTRICT_SET;
418                    SET_RULE `{a | a IN (s:A->bool) /\ a IN s'} = s INTER s'`;
419                    SUM_ADD;SUM_LMUL;REAL_MUL_RID;
420                    FINITE_INTER;INTER_IDEMPOT] THEN
421     ASM_REWRITE_TAC[SET_RULE `(a INTER b) INTER a = a INTER b`;
422                     SET_RULE `(a INTER b) INTER b = a INTER b`;
423                     REAL_ARITH `(a + b) + (c + d) - (e + b) = (a + d) + c - e`;
424                     REAL_ARITH `a + b - c = a <=> b = c`] THEN
425     AP_TERM_TAC THEN REWRITE_TAC[INTER_COMM];
426     ASM_SIMP_TAC[REWRITE_RULE
427                   [VECTOR_ARITH `(a:real^N) + b = c + d <=> c = a + b - d`]
428                   VSUM_INCL_EXCL;GSYM VSUM_RESTRICT_SET;
429                  SET_RULE `{a | a IN (s:A->bool) /\ a IN s'} = s INTER s'`;
430                  VSUM_ADD;FINITE_INTER;INTER_IDEMPOT;VECTOR_ADD_RDISTRIB;
431                  GSYM VECTOR_MUL_ASSOC;VSUM_LMUL;
432                  MESON[] `(if P then a else b) % (x:real^N) =
433                           (if P then a % x else b % x)`;
434                  VECTOR_MUL_LZERO;GSYM VSUM_RESTRICT_SET] THEN
435     ASM_REWRITE_TAC[SET_RULE `(a INTER b) INTER a = a INTER b`;
436                     SET_RULE `(a INTER b) INTER b = a INTER b`;
437                     VECTOR_ARITH
438                      `((a:real^N) + b) + (c + d) - (e + b) = (a + d) + c - e`;
439                     VECTOR_ARITH `(a:real^N) + b - c = a <=> b = c`] THEN
440     AP_TERM_TAC THEN REWRITE_TAC[INTER_COMM]];
441     ASM_CASES_TAC `(p:real^N->bool) = {}` THENL
442       [FIRST_X_ASSUM SUBST_ALL_TAC THEN
443        REWRITE_TAC[SUBSET_EMPTY;EMPTY_SUBSET] THEN ASM SET_TAC[];
444        ALL_TAC] THEN
445     REWRITE_TAC[AFFINE; SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
446     ASM SET_TAC[]]);;
447
448 let AFFINE_HULL_EXPLICIT_ALT = prove
449  (`!(p:real^N -> bool).
450         affine hull p =
451          {y | ?s u. FINITE s /\ s SUBSET p /\
452                     sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
453   GEN_TAC THEN REWRITE_TAC[AFFINE_HULL_EXPLICIT] THEN
454   GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[IN_ELIM_THM] THEN
455   GEN_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
456   EQ_TAC THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
457   POP_ASSUM MP_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
458   SIMP_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH_EQ]);;
459
460 let AFFINE_HULL_FINITE = prove
461  (`!s:real^N->bool.
462         affine hull s = {y | ?u. sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
463   GEN_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
464   REWRITE_TAC[AFFINE_HULL_EXPLICIT; IN_ELIM_THM] THEN
465   X_GEN_TAC `x:real^N` THEN EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
466    [MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `f:real^N->real`] THEN
467     STRIP_TAC THEN
468     EXISTS_TAC `\x:real^N. if x IN t then f x else &0` THEN
469     REWRITE_TAC[COND_RAND; COND_RATOR; VECTOR_MUL_LZERO] THEN
470     REWRITE_TAC[GSYM SUM_RESTRICT_SET; GSYM VSUM_RESTRICT_SET] THEN
471     ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`];
472     X_GEN_TAC `f:real^N->real` THEN
473     ASM_CASES_TAC `s:real^N->bool = {}` THEN
474     ASM_REWRITE_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH] THEN STRIP_TAC THEN
475     EXISTS_TAC `support (+) (f:real^N->real) s` THEN
476     EXISTS_TAC `f:real^N->real` THEN
477     MP_TAC(ASSUME `sum s (f:real^N->real) = &1`) THEN
478     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [sum] THEN
479     REWRITE_TAC[iterate] THEN COND_CASES_TAC THEN
480     ASM_REWRITE_TAC[NEUTRAL_REAL_ADD; REAL_OF_NUM_EQ; ARITH] THEN
481     DISCH_THEN(K ALL_TAC) THEN
482     UNDISCH_TAC `sum s (f:real^N->real) = &1` THEN
483     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM SUM_SUPPORT] THEN
484     ASM_CASES_TAC `support (+) (f:real^N->real) s = {}` THEN
485     ASM_SIMP_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH] THEN
486     DISCH_TAC THEN REWRITE_TAC[SUPPORT_SUBSET] THEN
487     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN
488     CONV_TAC SYM_CONV THEN MATCH_MP_TAC VSUM_SUPERSET THEN
489     REWRITE_TAC[SUPPORT_SUBSET] THEN
490     REWRITE_TAC[support; IN_ELIM_THM; NEUTRAL_REAL_ADD] THEN
491     MESON_TAC[VECTOR_MUL_LZERO]]);;
492
493 (* ------------------------------------------------------------------------- *)
494 (* Stepping theorems and hence small special cases.                          *)
495 (* ------------------------------------------------------------------------- *)
496
497 let AFFINE_HULL_EMPTY = prove
498  (`affine hull {} = {}`,
499   MATCH_MP_TAC HULL_UNIQUE THEN
500   REWRITE_TAC[SUBSET_REFL; AFFINE_EMPTY; EMPTY_SUBSET]);;
501
502 let AFFINE_HULL_EQ_EMPTY = prove
503  (`!s. (affine hull s = {}) <=> (s = {})`,
504   GEN_TAC THEN EQ_TAC THEN
505   MESON_TAC[SUBSET_EMPTY; HULL_SUBSET; AFFINE_HULL_EMPTY]);;
506
507 let AFFINE_HULL_FINITE_STEP_GEN = prove
508  (`!P:real^N->real->bool.
509         ((?u. (!x. x IN {} ==> P x (u x)) /\
510               sum {} u = w /\ vsum {} (\x. u(x) % x) = y) <=>
511          w = &0 /\ y = vec 0) /\
512         (FINITE(s:real^N->bool) /\
513          (!y. a IN s /\ P a y ==> P a (y / &2)) /\
514          (!x y. a IN s /\ P a x /\ P a y ==> P a (x + y))
515          ==> ((?u. (!x. x IN (a INSERT s) ==> P x (u x)) /\
516                    sum (a INSERT s) u = w /\
517                    vsum (a INSERT s) (\x. u(x) % x) = y) <=>
518               ?v u. P a v /\ (!x. x IN s ==> P x (u x)) /\
519                     sum s u = w - v /\
520                     vsum s (\x. u(x) % x) = y - v % a))`,
521   GEN_TAC THEN SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; NOT_IN_EMPTY] THEN
522   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN DISCH_TAC THEN
523   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_REWRITE_TAC[] THENL
524    [ASM_SIMP_TAC[SET_RULE `a IN s ==> a INSERT s = s`] THEN EQ_TAC THEN
525     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
526      [X_GEN_TAC `u:real^N->real` THEN STRIP_TAC THEN
527       EXISTS_TAC `(u:real^N->real) a / &2` THEN
528       EXISTS_TAC `\x:real^N. if x = a then u x / &2 else u x`;
529       MAP_EVERY X_GEN_TAC [`v:real`; `u:real^N->real`] THEN
530       STRIP_TAC THEN
531       EXISTS_TAC `\x:real^N. if x = a then u x + v else u x`] THEN
532     ASM_SIMP_TAC[] THEN (CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC]) THEN
533     ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
534     ASM_SIMP_TAC[VSUM_CASES; SUM_CASES] THEN
535     ASM_SIMP_TAC[GSYM DELETE; SUM_DELETE; VSUM_DELETE] THEN
536     ASM_SIMP_TAC[SET_RULE `a IN s ==> {x | x IN s /\ x = a} = {a}`] THEN
537     REWRITE_TAC[SUM_SING; VSUM_SING] THEN
538     (CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]);
539     EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
540      [X_GEN_TAC `u:real^N->real` THEN STRIP_TAC THEN
541       EXISTS_TAC `(u:real^N->real) a` THEN
542       EXISTS_TAC `u:real^N->real` THEN ASM_SIMP_TAC[IN_INSERT] THEN
543       REPEAT(FIRST_X_ASSUM(SUBST1_TAC o SYM)) THEN
544       CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC];
545       MAP_EVERY X_GEN_TAC [`v:real`; `u:real^N->real`] THEN
546       STRIP_TAC THEN
547       EXISTS_TAC `\x:real^N. if x = a then v:real else u x` THEN
548       ASM_SIMP_TAC[IN_INSERT] THEN CONJ_TAC THENL
549        [ASM_MESON_TAC[]; ALL_TAC] THEN
550       ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
551       ASM_SIMP_TAC[VSUM_CASES; SUM_CASES] THEN
552       ASM_SIMP_TAC[GSYM DELETE; SUM_DELETE; VSUM_DELETE] THEN
553       ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> {x | x IN s /\ x = a} = {}`] THEN
554       ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> s DELETE a = s`] THEN
555       REWRITE_TAC[SUM_CLAUSES; VSUM_CLAUSES] THEN
556       CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]]]);;
557
558 let AFFINE_HULL_FINITE_STEP = prove
559  (`((?u. sum {} u = w /\ vsum {} (\x. u(x) % x) = y) <=>
560     w = &0 /\ y = vec 0) /\
561    (FINITE(s:real^N->bool)
562     ==> ((?u. sum (a INSERT s) u = w /\
563               vsum (a INSERT s) (\x. u(x) % x) = y) <=>
564          ?v u.  sum s u = w - v /\
565                 vsum s (\x. u(x) % x) = y - v % a))`,
566   MATCH_ACCEPT_TAC (REWRITE_RULE[]
567    (ISPEC `\x:real^N y:real. T` AFFINE_HULL_FINITE_STEP_GEN)));;
568
569 let AFFINE_HULL_2 = prove
570  (`!a b. affine hull {a,b} =
571          {u % a + v % b | u + v = &1}`,
572   SIMP_TAC[AFFINE_HULL_FINITE; FINITE_INSERT; FINITE_RULES] THEN
573   SIMP_TAC[AFFINE_HULL_FINITE_STEP; FINITE_INSERT; FINITE_RULES] THEN
574   REWRITE_TAC[REAL_ARITH `x - y = z:real <=> x = y + z`;
575               VECTOR_ARITH `x - y = z:real^N <=> x = y + z`] THEN
576   REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN SET_TAC[]);;
577
578 let AFFINE_HULL_2_ALT = prove
579  (`!a b. affine hull {a,b} = {a + u % (b - a) | u IN (:real)}`,
580   REPEAT GEN_TAC THEN REWRITE_TAC[AFFINE_HULL_2] THEN
581   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
582   REWRITE_TAC[IN_ELIM_THM; IN_UNIV; ARITH_RULE `u + v = &1 <=> v = &1 - u`;
583     FORALL_UNWIND_THM2; UNWIND_THM2] THEN
584   CONJ_TAC THEN X_GEN_TAC `u:real` THEN EXISTS_TAC `&1 - u` THEN
585   VECTOR_ARITH_TAC);;
586
587 let AFFINE_HULL_3 = prove
588  (`affine hull {a,b,c} =
589     { u % a + v % b + w % c | u + v + w = &1}`,
590   SIMP_TAC[AFFINE_HULL_FINITE; FINITE_INSERT; FINITE_RULES] THEN
591   SIMP_TAC[AFFINE_HULL_FINITE_STEP; FINITE_INSERT; FINITE_RULES] THEN
592   REWRITE_TAC[REAL_ARITH `x - y = z:real <=> x = y + z`;
593               VECTOR_ARITH `x - y = z:real^N <=> x = y + z`] THEN
594   REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN SET_TAC[]);;
595
596 (* ------------------------------------------------------------------------- *)
597 (* Some relations between affine hull and subspaces.                         *)
598 (* ------------------------------------------------------------------------- *)
599
600 let AFFINE_HULL_INSERT_SUBSET_SPAN = prove
601  (`!a:real^N s.
602      affine hull (a INSERT s) SUBSET {a + v | v | v IN span {x - a | x IN s}}`,
603   REPEAT GEN_TAC THEN GEN_REWRITE_TAC I [SUBSET] THEN
604   REWRITE_TAC[AFFINE_HULL_EXPLICIT; SPAN_EXPLICIT; IN_ELIM_THM] THEN
605   REWRITE_TAC[SIMPLE_IMAGE; CONJ_ASSOC; FINITE_SUBSET_IMAGE] THEN
606   REWRITE_TAC[MESON[]
607    `(?s u. (?t. P t /\ s = f t) /\ Q s u) <=>
608     (?t u. P t /\ Q (f t) u)`] THEN
609   REWRITE_TAC[MESON[]
610    `(?v. (?s u. P s /\ f s u = v) /\ (x = g a v)) <=>
611     (?s u. ~(P s ==> ~(g a (f s u) = x)))`] THEN
612   SIMP_TAC[VSUM_IMAGE; VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
613   REWRITE_TAC[o_DEF] THEN X_GEN_TAC `y:real^N` THEN
614   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
615   MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `u:real^N->real`] THEN
616   DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC (SUBST1_TAC o SYM)) THEN
617   MAP_EVERY EXISTS_TAC
618    [`t DELETE (a:real^N)`; `\x. (u:real^N->real)(x + a)`] THEN
619   ASM_SIMP_TAC[FINITE_DELETE; VECTOR_SUB_ADD; SET_RULE
620    `t SUBSET (a INSERT s) ==> t DELETE a SUBSET s`] THEN
621   MATCH_MP_TAC EQ_TRANS THEN
622   EXISTS_TAC `a + vsum t (\x. u x % (x - a)):real^N` THEN CONJ_TAC THENL
623    [AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC VSUM_SUPERSET THEN
624     REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN SET_TAC[];
625     ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; FINITE_DELETE; VSUM_SUB] THEN
626     ASM_REWRITE_TAC[VSUM_RMUL] THEN
627     REWRITE_TAC[VECTOR_ARITH `a + x - &1 % a:real^N = x`]]);;
628
629 let AFFINE_HULL_INSERT_SPAN = prove
630  (`!a:real^N s.
631         ~(a IN s)
632         ==> affine hull (a INSERT s) =
633             {a + v | v | v IN span {x - a | x IN s}}`,
634   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
635   REWRITE_TAC[AFFINE_HULL_INSERT_SUBSET_SPAN] THEN REWRITE_TAC[SUBSET] THEN
636   REWRITE_TAC[AFFINE_HULL_EXPLICIT; SPAN_EXPLICIT; IN_ELIM_THM] THEN
637   REWRITE_TAC[SIMPLE_IMAGE; CONJ_ASSOC; FINITE_SUBSET_IMAGE] THEN
638   REWRITE_TAC[MESON[]
639    `(?s u. (?t. P t /\ s = f t) /\ Q s u) <=>
640     (?t u. P t /\ Q (f t) u)`] THEN
641   REWRITE_TAC[MESON[]
642    `(?v. (?s u. P s /\ f s u = v) /\ (x = g a v)) <=>
643     (?s u. ~(P s ==> ~(g a (f s u) = x)))`] THEN
644   SIMP_TAC[VSUM_IMAGE; VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
645   REWRITE_TAC[o_DEF] THEN X_GEN_TAC `y:real^N` THEN
646   REWRITE_TAC[NOT_IMP; LEFT_IMP_EXISTS_THM] THEN
647   MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `u:real^N->real`] THEN
648   DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC (SUBST1_TAC o SYM)) THEN
649   MAP_EVERY EXISTS_TAC
650    [`(a:real^N) INSERT t`;
651     `\x. if x = a then &1 - sum t (\x. u(x - a))
652          else (u:real^N->real)(x - a)`] THEN
653   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES] THEN
654   ASM_CASES_TAC `(a:real^N) IN t` THENL [ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
655   ASM_SIMP_TAC[FINITE_INSERT; NOT_INSERT_EMPTY;
656                SET_RULE `s SUBSET t ==> (a INSERT s) SUBSET (a INSERT t)`] THEN
657   SUBGOAL_THEN `!x:real^N. x IN t ==> ~(x = a)` MP_TAC THENL
658    [ASM SET_TAC[]; SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC)] THEN
659   CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
660   ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; FINITE_DELETE; VSUM_SUB] THEN
661   ASM_REWRITE_TAC[VSUM_RMUL] THEN VECTOR_ARITH_TAC);;
662
663 let AFFINE_HULL_SPAN = prove
664  (`!a:real^N s.
665         a IN s
666         ==> (affine hull s =
667              {a + v | v | v IN span {x - a | x | x IN (s DELETE a)}})`,
668   REPEAT STRIP_TAC THEN
669   MP_TAC(ISPECL [`a:real^N`; `s DELETE (a:real^N)`]
670     AFFINE_HULL_INSERT_SPAN) THEN
671   ASM_REWRITE_TAC[IN_DELETE] THEN
672   DISCH_THEN(SUBST1_TAC o SYM) THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
673
674 let DIFFS_AFFINE_HULL_SPAN = prove
675  (`!a:real^N s.
676         a IN s ==> {x - a | x IN affine hull s} = span {x - a | x IN s}`,
677   REPEAT STRIP_TAC THEN
678   FIRST_ASSUM(SUBST1_TAC o MATCH_MP AFFINE_HULL_SPAN) THEN
679   REWRITE_TAC[SIMPLE_IMAGE; GSYM IMAGE_o; o_DEF; VECTOR_ADD_SUB; IMAGE_ID] THEN
680   SIMP_TAC[IMAGE_DELETE_INJ;
681            VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
682   REWRITE_TAC[VECTOR_SUB_REFL; SPAN_DELETE_0]);;
683
684 let AFFINE_HULL_SING = prove
685  (`!a. affine hull {a} = {a}`,
686   SIMP_TAC[AFFINE_HULL_INSERT_SPAN; NOT_IN_EMPTY] THEN
687   REWRITE_TAC[SET_RULE `{f x | x | F} = {}`; SPAN_EMPTY] THEN
688   REWRITE_TAC[SET_RULE `{f x | x IN {a}} = {f a}`; VECTOR_ADD_RID]);;
689
690 let AFFINE_HULL_EQ_SING = prove
691  (`!s a:real^N. affine hull s = {a} <=> s = {a}`,
692   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
693   ASM_REWRITE_TAC[AFFINE_HULL_EMPTY] THEN
694   EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[AFFINE_HULL_SING] THEN
695   MATCH_MP_TAC(SET_RULE `~(s = {}) /\ s SUBSET {a} ==> s = {a}`) THEN
696   ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
697   REWRITE_TAC[HULL_SUBSET]);;
698
699 (* ------------------------------------------------------------------------- *)
700 (* Convexity.                                                                *)
701 (* ------------------------------------------------------------------------- *)
702
703 let convex = new_definition
704   `convex s <=>
705         !x y u v. x IN s /\ y IN s /\ &0 <= u /\ &0 <= v /\ (u + v = &1)
706                   ==> (u % x + v % y) IN s`;;
707
708 let CONVEX_ALT = prove
709  (`convex s <=> !x y u. x IN s /\ y IN s /\ &0 <= u /\ u <= &1
710                         ==> ((&1 - u) % x + u % y) IN s`,
711   REWRITE_TAC[convex] THEN
712   MESON_TAC[REAL_ARITH `&0 <= u /\ &0 <= v /\ (u + v = &1)
713                         ==> v <= &1 /\ (u = &1 - v)`;
714             REAL_ARITH `u <= &1 ==> &0 <= &1 - u /\ ((&1 - u) + u = &1)`]);;
715
716 let IN_CONVEX_SET = prove
717  (`!s a b u.
718         convex s /\ a IN s /\ b IN s /\ &0 <= u /\ u <= &1
719         ==> ((&1 - u) % a + u % b) IN s`,
720   MESON_TAC[CONVEX_ALT]);;
721
722 let CONVEX_EMPTY = prove
723  (`convex {}`,
724   REWRITE_TAC[convex; NOT_IN_EMPTY]);;
725
726 let CONVEX_SING = prove
727  (`!a. convex {a}`,
728   SIMP_TAC[convex; IN_SING; GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID]);;
729
730 let CONVEX_UNIV = prove
731  (`convex(UNIV:real^N->bool)`,
732   REWRITE_TAC[convex; IN_UNIV]);;
733
734 let CONVEX_INTERS = prove
735  (`(!s. s IN f ==> convex s) ==> convex(INTERS f)`,
736   REWRITE_TAC[convex; IN_INTERS] THEN MESON_TAC[]);;
737
738 let CONVEX_INTER = prove
739  (`!s t. convex s /\ convex t ==> convex(s INTER t)`,
740   REWRITE_TAC[convex; IN_INTER] THEN MESON_TAC[]);;
741
742 let CONVEX_HULLS_EQ = prove
743  (`!s t. s SUBSET convex hull t /\ t SUBSET convex hull s
744          ==> convex hull s = convex hull t`,
745   REPEAT STRIP_TAC THEN MATCH_MP_TAC HULLS_EQ THEN
746   ASM_SIMP_TAC[CONVEX_INTERS]);;
747
748 let CONVEX_HALFSPACE_LE = prove
749  (`!a b. convex {x | a dot x <= b}`,
750   REWRITE_TAC[convex; IN_ELIM_THM; DOT_RADD; DOT_RMUL] THEN
751   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN
752   EXISTS_TAC `(u + v) * b` THEN CONJ_TAC THENL
753    [ASM_MESON_TAC[REAL_ADD_RDISTRIB; REAL_LE_ADD2; REAL_LE_LMUL];
754     ASM_MESON_TAC[REAL_MUL_LID; REAL_LE_REFL]]);;
755
756 let CONVEX_HALFSPACE_COMPONENT_LE = prove
757  (`!a k. convex {x:real^N | x$k <= a}`,
758   REPEAT GEN_TAC THEN
759   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
760   CHOOSE_TAC THENL
761    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
762   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HALFSPACE_LE) THEN
763   ASM_SIMP_TAC[DOT_BASIS]);;
764
765 let CONVEX_HALFSPACE_GE = prove
766  (`!a b. convex {x:real^N | a dot x >= b}`,
767   REPEAT GEN_TAC THEN
768   SUBGOAL_THEN `{x:real^N | a dot x >= b} = {x | --a dot x <= --b}`
769    (fun th -> REWRITE_TAC[th; CONVEX_HALFSPACE_LE]) THEN
770   REWRITE_TAC[EXTENSION; IN_ELIM_THM; DOT_LNEG] THEN REAL_ARITH_TAC);;
771
772 let CONVEX_HALFSPACE_COMPONENT_GE = prove
773  (`!a k. convex {x:real^N | x$k >= a}`,
774   REPEAT GEN_TAC THEN
775   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
776   CHOOSE_TAC THENL
777    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
778   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HALFSPACE_GE) THEN
779   ASM_SIMP_TAC[DOT_BASIS]);;
780
781 let CONVEX_HYPERPLANE = prove
782  (`!a b. convex {x:real^N | a dot x = b}`,
783   REPEAT GEN_TAC THEN
784   SUBGOAL_THEN
785    `{x:real^N | a dot x = b} = {x | a dot x <= b} INTER {x | a dot x >= b}`
786    (fun th -> SIMP_TAC[th; CONVEX_INTER;
787                        CONVEX_HALFSPACE_LE; CONVEX_HALFSPACE_GE]) THEN
788   REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
789
790 let CONVEX_STANDARD_HYPERPLANE = prove
791  (`!k a. convex {x:real^N | x$k = a}`,
792   REPEAT GEN_TAC THEN
793   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
794   CHOOSE_TAC THENL
795    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
796   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HYPERPLANE) THEN
797   ASM_SIMP_TAC[DOT_BASIS]);;
798
799 let CONVEX_HALFSPACE_LT = prove
800  (`!a b. convex {x | a dot x < b}`,
801   REWRITE_TAC[convex; IN_ELIM_THM; DOT_RADD; DOT_RMUL] THEN
802   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONVEX_BOUND_LT THEN
803   ASM_REWRITE_TAC[]);;
804
805 let CONVEX_HALFSPACE_COMPONENT_LT = prove
806  (`!a k. convex {x:real^N | x$k < a}`,
807   REPEAT GEN_TAC THEN
808   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
809   CHOOSE_TAC THENL
810    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
811   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HALFSPACE_LT) THEN
812   ASM_SIMP_TAC[DOT_BASIS]);;
813
814 let CONVEX_HALFSPACE_GT = prove
815  (`!a b. convex {x | a dot x > b}`,
816   REWRITE_TAC[REAL_ARITH `ax > b <=> --ax < --b`] THEN
817   REWRITE_TAC[GSYM DOT_LNEG; CONVEX_HALFSPACE_LT]);;
818
819 let CONVEX_HALFSPACE_COMPONENT_GT = prove
820  (`!a k. convex {x:real^N | x$k > a}`,
821   REPEAT GEN_TAC THEN
822   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
823   CHOOSE_TAC THENL
824    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
825   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HALFSPACE_GT) THEN
826   ASM_SIMP_TAC[DOT_BASIS]);;
827
828 let CONVEX_POSITIVE_ORTHANT = prove
829  (`convex {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
830                           ==> &0 <= x$i}`,
831   SIMP_TAC[convex; IN_ELIM_THM; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
832            REAL_LE_MUL; REAL_LE_ADD]);;
833
834 let LIMPT_OF_CONVEX = prove
835  (`!s x:real^N.
836         convex s /\ x IN s ==> (x limit_point_of s <=> ~(s = {x}))`,
837   REPEAT STRIP_TAC THEN
838   ASM_CASES_TAC `s = {x:real^N}` THEN ASM_REWRITE_TAC[LIMPT_SING] THEN
839   SUBGOAL_THEN `?y:real^N. y IN s /\ ~(y = x)` STRIP_ASSUME_TAC THENL
840    [ASM SET_TAC[]; ALL_TAC] THEN
841   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
842   ABBREV_TAC `u = min (&1 / &2) (e / &2 / norm(y - x:real^N))` THEN
843   SUBGOAL_THEN `&0 < u /\ u < &1` STRIP_ASSUME_TAC THENL
844    [EXPAND_TAC "u" THEN REWRITE_TAC[REAL_LT_MIN; REAL_MIN_LT] THEN
845     CONV_TAC REAL_RAT_REDUCE_CONV THEN
846     ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ];
847     ALL_TAC] THEN
848   EXISTS_TAC `(&1 - u) % x + u % y:real^N` THEN REPEAT CONJ_TAC THENL
849    [FIRST_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
850     ASM_SIMP_TAC[REAL_LT_IMP_LE];
851     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ; VECTOR_ARITH
852      `(&1 - u) % x + u % y:real^N = x <=> u % (y - x) = vec 0`] THEN
853     ASM_REAL_ARITH_TAC;
854     REWRITE_TAC[dist; NORM_MUL; VECTOR_ARITH
855      `((&1 - u) % x + u % y) - x:real^N = u % (y - x)`] THEN
856     ASM_SIMP_TAC[REAL_ARITH `&0 < u ==> abs u = u`] THEN
857     MATCH_MP_TAC(REAL_ARITH `x <= e / &2 /\ &0 < e ==> x < e`) THEN
858     ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
859     ASM_REAL_ARITH_TAC]);;
860
861 let TRIVIAL_LIMIT_WITHIN_CONVEX = prove
862  (`!s x:real^N.
863         convex s /\ x IN s ==> (trivial_limit(at x within s) <=> s = {x})`,
864   SIMP_TAC[TRIVIAL_LIMIT_WITHIN; LIMPT_OF_CONVEX]);;
865
866 (* ------------------------------------------------------------------------- *)
867 (* Some invariance theorems for convex sets.                                 *)
868 (* ------------------------------------------------------------------------- *)
869
870 let CONVEX_TRANSLATION_EQ = prove
871  (`!a:real^N s. convex (IMAGE (\x. a + x) s) <=> convex s`,
872   REWRITE_TAC[CONVEX_ALT; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
873   REWRITE_TAC[IN_IMAGE; UNWIND_THM1; VECTOR_ARITH
874    `(&1 - u) % (a + x) + u % (a + y) = a + z <=> (&1 - u) % x + u % y = z`]);;
875
876 add_translation_invariants [CONVEX_TRANSLATION_EQ];;
877
878 let CONVEX_TRANSLATION = prove
879  (`!s a:real^N. convex s ==> convex (IMAGE (\x. a + x) s)`,
880   REWRITE_TAC[CONVEX_TRANSLATION_EQ]);;
881
882 let CONVEX_LINEAR_IMAGE = prove
883  (`!f s. convex s /\ linear f ==> convex(IMAGE f s)`,
884   REWRITE_TAC[convex; FORALL_IN_IMAGE; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
885   REWRITE_TAC[IN_IMAGE; linear] THEN MESON_TAC[]);;
886
887 let CONVEX_LINEAR_IMAGE_EQ = prove
888  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
889          ==> (convex (IMAGE f s) <=> convex s)`,
890   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE CONVEX_LINEAR_IMAGE));;
891
892 add_linear_invariants [CONVEX_LINEAR_IMAGE_EQ];;
893
894 (* ------------------------------------------------------------------------- *)
895 (* Explicit expressions for convexity in terms of arbitrary sums.            *)
896 (* ------------------------------------------------------------------------- *)
897
898 let CONVEX_VSUM = prove
899  (`!s k u x:A->real^N.
900         FINITE k /\ convex s /\ sum k u = &1 /\
901         (!i. i IN k ==> &0 <= u i /\ x i IN s)
902         ==> vsum k (\i. u i % x i) IN s`,
903   GEN_TAC THEN ASM_CASES_TAC `convex(s:real^N->bool)` THEN
904   ASM_REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
905   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
906   SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FORALL_IN_INSERT] THEN
907   CONV_TAC REAL_RAT_REDUCE_CONV THEN
908   MAP_EVERY X_GEN_TAC [`i:A`; `k:A->bool`] THEN
909   GEN_REWRITE_TAC (BINOP_CONV o DEPTH_CONV) [RIGHT_IMP_FORALL_THM] THEN
910   REWRITE_TAC[IMP_IMP] THEN STRIP_TAC THEN
911   MAP_EVERY X_GEN_TAC [`u:A->real`; `x:A->real^N`] THEN
912   ASM_CASES_TAC `(u:A->real) i = &1` THENL
913    [ASM_REWRITE_TAC[REAL_ARITH `&1 + a  = &1 <=> a = &0`] THEN
914     STRIP_TAC THEN
915     SUBGOAL_THEN `vsum k (\i:A. u i % x(i):real^N) = vec 0`
916      (fun th -> ASM_SIMP_TAC[th; VECTOR_ADD_RID; VECTOR_MUL_LID]) THEN
917     MATCH_MP_TAC VSUM_EQ_0 THEN REWRITE_TAC[VECTOR_MUL_EQ_0] THEN
918     REPEAT STRIP_TAC THEN DISJ1_TAC THEN
919     ASM_MESON_TAC[SUM_POS_EQ_0];
920     STRIP_TAC THEN
921     FIRST_X_ASSUM(MP_TAC o SPEC `\j:A. u(j) / (&1 - u(i))`) THEN
922     ASM_REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
923     ASM_SIMP_TAC[SUM_LMUL; VSUM_LMUL; GSYM VECTOR_MUL_ASSOC] THEN
924     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN
925     SUBGOAL_THEN `&0 < &1 - u(i:A)` ASSUME_TAC THENL
926      [ASM_MESON_TAC[SUM_POS_LE; REAL_ADD_SYM; REAL_ARITH
927        `&0 <= a /\ &0 <= b /\ b + a = &1 /\ ~(a = &1) ==> &0 < &1 - a`];
928       ALL_TAC] THEN
929     ASM_SIMP_TAC[REAL_LE_DIV; REAL_LT_IMP_LE] THEN
930     ASM_SIMP_TAC[REAL_EQ_LDIV_EQ; REAL_MUL_LID; REAL_EQ_SUB_LADD] THEN
931     DISCH_TAC THEN ONCE_REWRITE_TAC[VECTOR_ADD_SYM] THEN
932     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex]) THEN
933     DISCH_THEN(MP_TAC o SPECL
934      [`vsum k (\j. (u j / (&1 - u(i:A))) % x(j) :real^N)`;
935       `x(i:A):real^N`; `&1 - u(i:A)`; `u(i:A):real`]) THEN
936     REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
937     ASM_SIMP_TAC[GSYM VECTOR_MUL_ASSOC; VSUM_LMUL] THEN
938     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; REAL_LT_IMP_NZ] THEN
939     REWRITE_TAC[VECTOR_MUL_LID] THEN DISCH_THEN MATCH_MP_TAC THEN
940     ASM_SIMP_TAC[REAL_LT_IMP_LE; VSUM_LMUL] THEN
941     CONJ_TAC THENL [FIRST_X_ASSUM MATCH_MP_TAC; REAL_ARITH_TAC] THEN
942     ASM_MESON_TAC[REAL_ADD_SYM]]);;
943
944 let CONVEX_VSUM_STRONG = prove
945  (`!s k u x:A->real^N.
946         FINITE k /\
947         convex s /\
948         sum k u = &1 /\
949         (!i. i IN k ==> &0 <= u i /\ (u i = &0 \/ x i IN s))
950         ==> vsum k (\i. u i % x i) IN s`,
951   REPEAT STRIP_TAC THEN
952   SUBGOAL_THEN
953    `vsum k (\i. u i % (x:A->real^N) i) =
954     vsum {i | i IN k /\ ~(u i = &0)} (\i. u i % x i)`
955   SUBST1_TAC THENL
956    [MATCH_MP_TAC VSUM_SUPERSET THEN REWRITE_TAC[VECTOR_MUL_EQ_0] THEN
957     SET_TAC[];
958     MATCH_MP_TAC CONVEX_VSUM THEN
959     ASM_SIMP_TAC[FINITE_RESTRICT; IN_ELIM_THM] THEN
960     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
961     FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
962     CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_SUPERSET THEN ASM SET_TAC[]]);;
963
964 let CONVEX_INDEXED = prove
965  (`!s:real^N->bool.
966         convex s <=>
967             !k u x. (!i:num. 1 <= i /\ i <= k ==> &0 <= u(i) /\ x(i) IN s) /\
968                     (sum (1..k) u = &1)
969                     ==> vsum (1..k) (\i. u(i) % x(i)) IN s`,
970   REPEAT GEN_TAC THEN EQ_TAC THENL
971    [REPEAT STRIP_TAC THEN MATCH_MP_TAC CONVEX_VSUM THEN
972     ASM_REWRITE_TAC[IN_NUMSEG; FINITE_NUMSEG];
973     DISCH_TAC THEN REWRITE_TAC[convex] THEN
974     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
975     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `2`) THEN
976     DISCH_THEN(MP_TAC o SPEC `\n. if n = 1 then u else v:real`) THEN
977     DISCH_THEN(MP_TAC o SPEC `\n. if n = 1 then x else y:real^N`) THEN
978     REWRITE_TAC[num_CONV `2`; SUM_CLAUSES_NUMSEG; VSUM_CLAUSES_NUMSEG;
979       NUMSEG_SING; VSUM_SING; SUM_SING] THEN REWRITE_TAC[ARITH] THEN
980     ASM_MESON_TAC[]]);;
981
982 let CONVEX_EXPLICIT = prove
983  (`!s:real^N->bool.
984         convex s <=>
985         !t u. FINITE t /\ t SUBSET s /\ (!x. x IN t ==> &0 <= u x) /\
986               sum t u = &1
987               ==> vsum t (\x. u(x) % x) IN s`,
988   REPEAT GEN_TAC THEN EQ_TAC THENL
989    [REPEAT STRIP_TAC THEN MATCH_MP_TAC CONVEX_VSUM THEN
990     ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
991     DISCH_TAC THEN REWRITE_TAC[convex] THEN
992     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
993     ASM_CASES_TAC `x:real^N = y` THENL
994      [ASM_SIMP_TAC[GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID]; ALL_TAC] THEN
995     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `{x:real^N,y}`) THEN
996     DISCH_THEN(MP_TAC o SPEC `\z:real^N. if z = x then u else v:real`) THEN
997     ASM_SIMP_TAC[FINITE_INSERT; FINITE_RULES; SUM_CLAUSES; VSUM_CLAUSES;
998                  NOT_IN_EMPTY] THEN
999     ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; REAL_ADD_RID; SUBSET] THEN
1000     REWRITE_TAC[VECTOR_ADD_RID] THEN ASM_MESON_TAC[]]);;
1001
1002 let CONVEX = prove
1003  (`!V:real^N->bool.
1004      convex V <=>
1005          !(s:real^N->bool) (u:real^N->real).
1006              FINITE s /\ ~(s = {}) /\ s SUBSET V /\
1007              (!x. x IN s ==> &0 <= u x) /\ sum s u = &1
1008              ==> vsum s (\x. u x % x) IN V`,
1009   GEN_TAC THEN REWRITE_TAC[CONVEX_EXPLICIT] THEN
1010   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
1011   X_GEN_TAC `t:real^N->bool` THEN REWRITE_TAC[] THEN
1012   AP_TERM_TAC THEN ABS_TAC THEN
1013   ASM_CASES_TAC `t:real^N->bool = {}` THEN
1014   ASM_REWRITE_TAC[SUM_CLAUSES] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
1015
1016 let CONVEX_FINITE = prove
1017  (`!s:real^N->bool.
1018         FINITE s
1019         ==> (convex s <=>
1020                 !u. (!x. x IN s ==> &0 <= u x) /\
1021                     sum s u = &1
1022                     ==> vsum s (\x. u(x) % x) IN s)`,
1023   REPEAT STRIP_TAC THEN REWRITE_TAC[CONVEX_EXPLICIT] THEN
1024   EQ_TAC THENL [ASM_MESON_TAC[SUBSET_REFL]; ALL_TAC] THEN
1025   DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `u:real^N->real`] THEN
1026   STRIP_TAC THEN
1027   FIRST_X_ASSUM(MP_TAC o SPEC `\x:real^N. if x IN t then u x else &0`) THEN
1028   ASM_SIMP_TAC[GSYM SUM_RESTRICT_SET] THEN
1029   ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
1030   ASM_SIMP_TAC[VECTOR_MUL_LZERO; REAL_LE_REFL; GSYM VSUM_RESTRICT_SET] THEN
1031   ASM_SIMP_TAC[COND_ID; SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`]);;
1032
1033 let AFFINE_PCROSS = prove
1034  (`!s:real^M->bool t:real^N->bool.
1035         affine s /\ affine t ==> affine(s PCROSS t)`,
1036   REWRITE_TAC[affine; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1037   SIMP_TAC[FORALL_IN_PCROSS; GSYM PASTECART_CMUL; PASTECART_ADD] THEN
1038   SIMP_TAC[PASTECART_IN_PCROSS]);;
1039
1040 let AFFINE_PCROSS_EQ = prove
1041  (`!s:real^M->bool t:real^N->bool.
1042         affine(s PCROSS t) <=> s = {} \/ t = {} \/ affine s /\ affine t`,
1043   REPEAT GEN_TAC THEN
1044   ASM_CASES_TAC `s:real^M->bool = {}` THEN
1045   ASM_REWRITE_TAC[PCROSS_EMPTY; AFFINE_EMPTY] THEN
1046   ASM_CASES_TAC `t:real^N->bool = {}` THEN
1047   ASM_REWRITE_TAC[PCROSS_EMPTY; AFFINE_EMPTY] THEN
1048   EQ_TAC THEN REWRITE_TAC[AFFINE_PCROSS] THEN REPEAT STRIP_TAC THENL
1049    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
1050       `(s:real^M->bool) PCROSS (t:real^N->bool)`] AFFINE_LINEAR_IMAGE) THEN
1051     ASM_REWRITE_TAC[LINEAR_FSTCART];
1052     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
1053       `(s:real^M->bool) PCROSS (t:real^N->bool)`] AFFINE_LINEAR_IMAGE) THEN
1054     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
1055   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
1056   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
1057               FSTCART_PASTECART; SNDCART_PASTECART] THEN
1058   ASM SET_TAC[]);;
1059
1060 let CONVEX_PCROSS = prove
1061  (`!s:real^M->bool t:real^N->bool.
1062         convex s /\ convex t ==> convex(s PCROSS t)`,
1063   REWRITE_TAC[convex; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1064   SIMP_TAC[FORALL_IN_PCROSS; GSYM PASTECART_CMUL; PASTECART_ADD] THEN
1065   SIMP_TAC[PASTECART_IN_PCROSS]);;
1066
1067 let CONVEX_PCROSS_EQ = prove
1068  (`!s:real^M->bool t:real^N->bool.
1069         convex(s PCROSS t) <=> s = {} \/ t = {} \/ convex s /\ convex t`,
1070   REPEAT GEN_TAC THEN
1071   ASM_CASES_TAC `s:real^M->bool = {}` THEN
1072   ASM_REWRITE_TAC[PCROSS_EMPTY; CONVEX_EMPTY] THEN
1073   ASM_CASES_TAC `t:real^N->bool = {}` THEN
1074   ASM_REWRITE_TAC[PCROSS_EMPTY; CONVEX_EMPTY] THEN
1075   EQ_TAC THEN REWRITE_TAC[CONVEX_PCROSS] THEN REPEAT STRIP_TAC THENL
1076    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
1077       `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONVEX_LINEAR_IMAGE) THEN
1078     ASM_REWRITE_TAC[LINEAR_FSTCART];
1079     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
1080       `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONVEX_LINEAR_IMAGE) THEN
1081     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
1082   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
1083   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
1084               FSTCART_PASTECART; SNDCART_PASTECART] THEN
1085   ASM SET_TAC[]);;
1086
1087 (* ------------------------------------------------------------------------- *)
1088 (* Conic sets and conic hull.                                                *)
1089 (* ------------------------------------------------------------------------- *)
1090
1091 let conic = new_definition
1092   `conic s <=> !x c. x IN s /\ &0 <= c ==> (c % x) IN s`;;
1093
1094 let SUBSPACE_IMP_CONIC = prove
1095  (`!s. subspace s ==> conic s`,
1096   SIMP_TAC[subspace; conic]);;
1097
1098 let CONIC_EMPTY = prove
1099  (`conic {}`,
1100   REWRITE_TAC[conic; NOT_IN_EMPTY]);;
1101
1102 let CONIC_UNIV = prove
1103  (`conic (UNIV:real^N->bool)`,
1104   REWRITE_TAC[conic; IN_UNIV]);;
1105
1106 let CONIC_INTERS = prove
1107  (`(!s. s IN f ==> conic s) ==> conic(INTERS f)`,
1108   REWRITE_TAC[conic; IN_INTERS] THEN MESON_TAC[]);;
1109
1110 let CONIC_LINEAR_IMAGE = prove
1111  (`!f s. conic s /\ linear f ==> conic(IMAGE f s)`,
1112   REWRITE_TAC[conic; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
1113   REWRITE_TAC[IN_IMAGE] THEN MESON_TAC[LINEAR_CMUL]);;
1114
1115 let CONIC_LINEAR_IMAGE_EQ = prove
1116  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
1117          ==> (conic (IMAGE f s) <=> conic s)`,
1118   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE CONIC_LINEAR_IMAGE));;
1119
1120 add_linear_invariants [CONIC_LINEAR_IMAGE_EQ];;
1121
1122 let CONIC_CONIC_HULL = prove
1123  (`!s. conic(conic hull s)`,
1124   SIMP_TAC[P_HULL; CONIC_INTERS]);;
1125
1126 let CONIC_HULL_EQ = prove
1127  (`!s. (conic hull s = s) <=> conic s`,
1128   SIMP_TAC[HULL_EQ; CONIC_INTERS]);;
1129
1130 let CONIC_NEGATIONS = prove
1131  (`!s. conic s ==> conic (IMAGE (--) s)`,
1132   REWRITE_TAC[conic; RIGHT_FORALL_IMP_THM; IMP_CONJ; FORALL_IN_IMAGE] THEN
1133   REWRITE_TAC[IN_IMAGE; VECTOR_MUL_RNEG] THEN MESON_TAC[]);;
1134
1135 let CONIC_SPAN = prove
1136  (`!s. conic(span s)`,
1137   SIMP_TAC[SUBSPACE_IMP_CONIC; SUBSPACE_SPAN]);;
1138
1139 let CONIC_HULL_EXPLICIT = prove
1140  (`!s:real^N->bool. conic hull s = {c % x | &0 <= c /\ x IN s}`,
1141   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN
1142   REWRITE_TAC[conic; SUBSET; RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
1143   REWRITE_TAC[FORALL_IN_GSPEC] THEN
1144   REWRITE_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP; IN_ELIM_THM] THEN
1145   REPEAT CONJ_TAC THENL
1146    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1147     MAP_EVERY EXISTS_TAC [`&1`; `x:real^N`] THEN
1148     ASM_SIMP_TAC[REAL_POS; VECTOR_MUL_LID];
1149     REWRITE_TAC[VECTOR_MUL_ASSOC] THEN MESON_TAC[REAL_LE_MUL];
1150     MESON_TAC[]]);;
1151
1152 let CONIC_HULL_LINEAR_IMAGE = prove
1153  (`!f s. linear f ==> conic hull (IMAGE f s) = IMAGE f (conic hull s)`,
1154   REPEAT GEN_TAC THEN REWRITE_TAC[CONIC_HULL_EXPLICIT] THEN
1155   REWRITE_TAC[SET_RULE `IMAGE f {c % x | P c x} = {f(c % x) | P c x}`] THEN
1156   REWRITE_TAC[SET_RULE `{c % x | &0 <= c /\ x IN IMAGE f s} =
1157                         {c % f(x) | &0 <= c /\ x IN s}`] THEN
1158   DISCH_THEN(fun th -> REWRITE_TAC[MATCH_MP LINEAR_CMUL th]));;
1159
1160 add_linear_invariants [CONIC_HULL_LINEAR_IMAGE];;
1161
1162 let CONVEX_CONIC_HULL = prove
1163  (`!s:real^N->bool. convex s ==> convex (conic hull s)`,
1164   REWRITE_TAC[CONIC_HULL_EXPLICIT] THEN
1165   REWRITE_TAC[CONVEX_ALT; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1166   REWRITE_TAC[FORALL_IN_GSPEC] THEN REWRITE_TAC[IN_ELIM_THM; IMP_IMP] THEN
1167   X_GEN_TAC `s:real^N->bool` THEN DISCH_TAC THEN
1168   MAP_EVERY X_GEN_TAC [`c:real`; `x:real^N`] THEN STRIP_TAC THEN
1169   MAP_EVERY X_GEN_TAC [`d:real`; `y:real^N`] THEN STRIP_TAC THEN
1170   X_GEN_TAC `u:real` THEN STRIP_TAC THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN
1171   ASM_CASES_TAC `(&1 - u) * c = &0` THENL
1172    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN
1173     ASM_MESON_TAC[REAL_LE_MUL];
1174     ALL_TAC] THEN
1175   SUBGOAL_THEN `&0 < (&1 - u) * c + u * d` ASSUME_TAC THENL
1176    [MATCH_MP_TAC REAL_LTE_ADD THEN ASM_REWRITE_TAC[REAL_LT_LE] THEN
1177     CONJ_TAC THEN MATCH_MP_TAC REAL_LE_MUL THEN ASM_REAL_ARITH_TAC;
1178     ALL_TAC] THEN
1179   EXISTS_TAC `(&1 - u) * c + u * d:real` THEN
1180   EXISTS_TAC `((&1 - u) * c) / ((&1 - u) * c + u * d) % x +
1181               (u * d) / ((&1 - u) * c + u * d) % y:real^N` THEN
1182   REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC] THEN
1183   ASM_SIMP_TAC[REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
1184   ASM_SIMP_TAC[REAL_LE_ADD; REAL_LE_MUL; REAL_SUB_LE] THEN
1185   ASM_SIMP_TAC[REAL_FIELD
1186    `&0 < u + v ==> u / (u + v) = &1 - (v / (u + v))`] THEN
1187   RULE_ASSUM_TAC(REWRITE_RULE[RIGHT_IMP_FORALL_THM; IMP_IMP]) THEN
1188   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
1189   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ] THEN
1190   ASM_SIMP_TAC[REAL_MUL_LZERO; REAL_LE_MUL; REAL_MUL_LID; REAL_LE_ADDL;
1191                REAL_SUB_LE]);;
1192
1193 let CONIC_HALFSPACE_LE = prove
1194  (`!a. conic {x | a dot x <= &0}`,
1195   REWRITE_TAC[conic; IN_ELIM_THM; DOT_RMUL] THEN
1196   REWRITE_TAC[REAL_ARITH `a <= &0 <=> &0 <= --a`] THEN
1197   SIMP_TAC[GSYM REAL_MUL_RNEG; REAL_LE_MUL]);;
1198
1199 let CONIC_HALFSPACE_GE = prove
1200  (`!a. conic {x | a dot x >= &0}`,
1201   SIMP_TAC[conic; IN_ELIM_THM; DOT_RMUL; real_ge; REAL_LE_MUL]);;
1202
1203 let CONIC_HULL_EMPTY = prove
1204  (`conic hull {} = {}`,
1205   MATCH_MP_TAC HULL_UNIQUE THEN
1206   REWRITE_TAC[SUBSET_REFL; CONIC_EMPTY; EMPTY_SUBSET]);;
1207
1208 let CONIC_CONTAINS_0 = prove
1209  (`!s:real^N->bool. conic s ==> (vec 0 IN s <=> ~(s = {}))`,
1210   REPEAT STRIP_TAC THEN EQ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
1211   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
1212   DISCH_THEN(X_CHOOSE_TAC `x:real^N`) THEN
1213   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [conic]) THEN
1214   DISCH_THEN(MP_TAC o SPECL [`x:real^N`; `&0`]) THEN
1215   ASM_REWRITE_TAC[REAL_POS; VECTOR_MUL_LZERO]);;
1216
1217 let CONIC_HULL_EQ_EMPTY = prove
1218  (`!s. (conic hull s = {}) <=> (s = {})`,
1219   GEN_TAC THEN EQ_TAC THEN
1220   MESON_TAC[SUBSET_EMPTY; HULL_SUBSET; CONIC_HULL_EMPTY]);;
1221
1222 let CONIC_SUMS = prove
1223  (`!s t. conic s /\ conic t ==> conic {x + y:real^N | x IN s /\ y IN t}`,
1224   REWRITE_TAC[conic; IN_ELIM_THM] THEN
1225   MESON_TAC[VECTOR_ADD_LDISTRIB]);;
1226
1227 let CONIC_PCROSS = prove
1228  (`!s:real^M->bool t:real^N->bool.
1229         conic s /\ conic t ==> conic(s PCROSS t)`,
1230   REWRITE_TAC[conic; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1231   SIMP_TAC[FORALL_IN_PCROSS; GSYM PASTECART_CMUL; PASTECART_ADD] THEN
1232   SIMP_TAC[PASTECART_IN_PCROSS]);;
1233
1234 let CONIC_PCROSS_EQ = prove
1235  (`!s:real^M->bool t:real^N->bool.
1236         conic(s PCROSS t) <=> s = {} \/ t = {} \/ conic s /\ conic t`,
1237   REPEAT GEN_TAC THEN
1238   ASM_CASES_TAC `s:real^M->bool = {}` THEN
1239   ASM_REWRITE_TAC[PCROSS_EMPTY; CONIC_EMPTY] THEN
1240   ASM_CASES_TAC `t:real^N->bool = {}` THEN
1241   ASM_REWRITE_TAC[PCROSS_EMPTY; CONIC_EMPTY] THEN
1242   EQ_TAC THEN REWRITE_TAC[CONIC_PCROSS] THEN REPEAT STRIP_TAC THENL
1243    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
1244       `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONIC_LINEAR_IMAGE) THEN
1245     ASM_REWRITE_TAC[LINEAR_FSTCART];
1246     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
1247       `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONIC_LINEAR_IMAGE) THEN
1248     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
1249   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
1250   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
1251               FSTCART_PASTECART; SNDCART_PASTECART] THEN
1252   ASM SET_TAC[]);;
1253
1254 let CONIC_POSITIVE_ORTHANT = prove
1255  (`conic {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> &0 <= x$i}`,
1256   SIMP_TAC[conic; IN_ELIM_THM; REAL_LE_MUL; VECTOR_MUL_COMPONENT]);;
1257
1258 let SEPARATE_CLOSED_CONES = prove
1259  (`!c d:real^N->bool.
1260         conic c /\ closed c /\ conic d /\ closed d /\ c INTER d SUBSET {vec 0}
1261         ==> ?e. &0 < e /\
1262                 !x y. x IN c /\ y IN d
1263                       ==> dist(x,y) >= e * max (norm x) (norm y)`,
1264   SUBGOAL_THEN
1265    `!c d:real^N->bool.
1266         conic c /\ closed c /\ conic d /\ closed d /\ c INTER d SUBSET {vec 0}
1267         ==> ?e. &0 < e /\
1268                 !x y. x IN c /\ y IN d ==> dist(x,y)
1269                       >= e * norm x`
1270   ASSUME_TAC THENL
1271    [REPEAT STRIP_TAC THEN REWRITE_TAC[real_ge] THEN
1272     MP_TAC(ISPECL [`c INTER sphere(vec 0:real^N,&1)`; `d:real^N->bool`]
1273       SEPARATE_COMPACT_CLOSED) THEN
1274     ASM_SIMP_TAC[CLOSED_INTER_COMPACT; COMPACT_SPHERE] THEN ANTS_TAC THENL
1275      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
1276        `c INTER d SUBSET {a} ==> ~(a IN s) ==> (c INTER s) INTER d = {}`)) THEN
1277       REWRITE_TAC[IN_SPHERE_0; NORM_0] THEN REAL_ARITH_TAC;
1278       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN
1279       REWRITE_TAC[IN_INTER; IN_SPHERE_0] THEN STRIP_TAC THEN
1280       ASM_REWRITE_TAC[] THEN
1281       MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
1282       ASM_CASES_TAC `x:real^N = vec 0` THEN
1283       ASM_REWRITE_TAC[DIST_POS_LE; REAL_MUL_RZERO; NORM_0] THEN
1284       FIRST_X_ASSUM(MP_TAC o SPECL
1285        [`inv(norm x) % x:real^N`; `inv(norm(x:real^N)) % y:real^N`]) THEN
1286       REWRITE_TAC[dist; NORM_MUL; GSYM VECTOR_SUB_LDISTRIB] THEN
1287       REWRITE_TAC[REAL_ARITH `abs x * a = a * abs x`] THEN
1288       REWRITE_TAC[REAL_ABS_INV; GSYM real_div; REAL_ABS_NORM] THEN
1289       ASM_SIMP_TAC[REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
1290       DISCH_THEN MATCH_MP_TAC THEN
1291       ASM_SIMP_TAC[REAL_DIV_REFL; NORM_EQ_0] THEN
1292       RULE_ASSUM_TAC(REWRITE_RULE[conic]) THEN
1293       CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
1294       ASM_SIMP_TAC[REAL_LE_INV_EQ; NORM_POS_LE]];
1295     REPEAT STRIP_TAC THEN FIRST_X_ASSUM(fun th ->
1296       MP_TAC(SPECL [`c:real^N->bool`; `d:real^N->bool`] th) THEN
1297       MP_TAC(SPECL [`d:real^N->bool`; `c:real^N->bool`] th)) THEN
1298     ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[INTER_COMM] THEN
1299     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; real_ge] THEN
1300     X_GEN_TAC `d:real` THEN STRIP_TAC THEN
1301     X_GEN_TAC `e:real` THEN STRIP_TAC THEN
1302     EXISTS_TAC `min d e:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
1303     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
1304     REWRITE_TAC[real_max] THEN COND_CASES_TAC THEN
1305     MATCH_MP_TAC REAL_LE_TRANS THENL
1306      [EXISTS_TAC `d * norm(y:real^N)` THEN ONCE_REWRITE_TAC[DIST_SYM];
1307       EXISTS_TAC `e * norm(x:real^N)`] THEN
1308     ASM_SIMP_TAC[] THEN MATCH_MP_TAC REAL_LE_RMUL THEN NORM_ARITH_TAC]);;
1309
1310 let CONTINUOUS_ON_COMPACT_SURFACE_PROJECTION = prove
1311  (`!s:real^N->bool v d:real^N->real.
1312         compact s /\ s SUBSET (v DELETE (vec 0)) /\ conic v /\
1313         (!x k. x IN v DELETE (vec 0) ==> (&0 < k /\ (k % x) IN s <=> d x = k))
1314         ==> (\x. d x % x) continuous_on (v DELETE (vec 0))`,
1315   let lemma = prove
1316    (`!s:real^N->real^N p srf:real^N->bool pnc.
1317           compact srf /\ srf SUBSET pnc /\
1318           IMAGE s pnc SUBSET srf /\ (!x. x IN srf ==> s x = x) /\
1319           p continuous_on pnc /\
1320           (!x. x IN pnc ==> s(p x) = s x /\ p(s x) = p x)
1321           ==> s continuous_on pnc`,
1322     REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THEN
1323     EXISTS_TAC `(s:real^N->real^N) o (p:real^N->real^N)` THEN
1324     CONJ_TAC THENL [ASM_SIMP_TAC[o_DEF]; ALL_TAC] THEN
1325     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN
1326     SUBGOAL_THEN `IMAGE (p:real^N->real^N) pnc = IMAGE p srf` SUBST1_TAC THENL
1327      [ASM SET_TAC[];
1328       MATCH_MP_TAC CONTINUOUS_ON_INVERSE THEN ASM_REWRITE_TAC[] THEN
1329       CONJ_TAC THENL [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ASM SET_TAC[]]]) in
1330   REWRITE_TAC[conic; IN_DELETE; SUBSET] THEN
1331   REPEAT STRIP_TAC THEN MATCH_MP_TAC lemma THEN
1332   MAP_EVERY EXISTS_TAC [`\x:real^N. inv(norm x) % x`; `s:real^N->bool`] THEN
1333   ASM_REWRITE_TAC[] THEN
1334   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
1335   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
1336   ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN CONJ_TAC THENL
1337    [MATCH_MP_TAC CONTINUOUS_ON_MUL THEN SIMP_TAC[o_DEF; CONTINUOUS_ON_ID] THEN
1338     MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_INV) THEN
1339     SIMP_TAC[IN_DELETE; NORM_EQ_0; SIMP_RULE[o_DEF] CONTINUOUS_ON_LIFT_NORM];
1340     REWRITE_TAC[IN_UNIV; IN_DELETE]] THEN
1341   CONJ_TAC THENL
1342    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1343     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `&1`]) THEN
1344     ASM_REWRITE_TAC[VECTOR_MUL_LID; REAL_LT_01; IN_DELETE] THEN
1345     ASM_MESON_TAC[VECTOR_MUL_LID; SUBSET; IN_DELETE];
1346     ALL_TAC] THEN
1347   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN CONJ_TAC THENL
1348    [FIRST_ASSUM(MP_TAC o SPECL
1349      [`inv(norm x) % x:real^N`; `norm x * (d:real^N->real) x`]) THEN
1350     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `(d:real^N->real) x`]) THEN
1351     ASM_SIMP_TAC[VECTOR_MUL_EQ_0; REAL_INV_EQ_0; NORM_EQ_0] THEN STRIP_TAC THEN
1352     ASM_SIMP_TAC[REAL_LE_INV_EQ; NORM_POS_LE; REAL_LT_MUL; NORM_POS_LT] THEN
1353     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; NORM_EQ_0; REAL_FIELD
1354      `~(n = &0) ==> (n * d) * inv n = d`];
1355     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `(d:real^N->real) x`]) THEN
1356     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
1357     ASM_SIMP_TAC[NORM_MUL; VECTOR_MUL_ASSOC; REAL_INV_MUL] THEN
1358     ASM_SIMP_TAC[real_abs; REAL_LT_IMP_LE] THEN
1359     ASM_SIMP_TAC[REAL_FIELD `&0 < x ==> (inv(x) * y) * x = y`]]);;
1360
1361 (* ------------------------------------------------------------------------- *)
1362 (* Affine dependence and consequential theorems (from Lars Schewe).          *)
1363 (* ------------------------------------------------------------------------- *)
1364
1365 let affine_dependent = new_definition
1366  `affine_dependent (s:real^N -> bool) <=>
1367         ?x. x IN s /\ x IN (affine hull (s DELETE x))`;;
1368
1369 let AFFINE_DEPENDENT_EXPLICIT = prove
1370  (`!p. affine_dependent (p:real^N -> bool) <=>
1371             (?s u. FINITE s /\ s SUBSET p /\
1372                    sum s u = &0 /\
1373                    (?v. v IN s /\ ~(u v = &0)) /\
1374                    vsum s (\v. u v % v) = (vec 0):real^N)`,
1375   X_GEN_TAC `p:real^N->bool` THEN EQ_TAC THENL
1376    [REWRITE_TAC[affine_dependent;AFFINE_HULL_EXPLICIT;
1377                 IN_ELIM_THM] THEN
1378     REPEAT STRIP_TAC THEN
1379     EXISTS_TAC `(x:real^N) INSERT s` THEN
1380     EXISTS_TAC `\v:real^N.if v = x then -- &1 else u v` THEN
1381       ASM_SIMP_TAC[FINITE_INSERT;SUM_CLAUSES;VSUM_CLAUSES;INSERT_SUBSET] THEN
1382       REPEAT CONJ_TAC THENL
1383       [ASM SET_TAC[];
1384        COND_CASES_TAC THENL [ASM SET_TAC[];ALL_TAC] THEN
1385          ASM_SIMP_TAC[SUM_CASES; SUM_CLAUSES; SET_RULE
1386           `~((x:real^N) IN s) ==> {v | v IN s /\ v = x} = {} /\
1387                                   {v | v IN s /\ ~(v = x)} = s`] THEN
1388          REAL_ARITH_TAC;
1389        SET_TAC[REAL_ARITH `~(-- &1 = &0)`];
1390        MP_TAC (SET_RULE `s SUBSET p DELETE (x:real^N) ==> ~(x IN s)`) THEN
1391        ASM_REWRITE_TAC[] THEN
1392        DISCH_TAC THEN
1393        ASM_SIMP_TAC[VECTOR_ARITH
1394         `(-- &1 % (x:real^N)) + a = vec 0 <=> a = x`] THEN
1395        MATCH_MP_TAC EQ_TRANS THEN
1396        EXISTS_TAC `vsum s (\v:real^N. u v % v)` THEN
1397        CONJ_TAC THENL [
1398        MATCH_MP_TAC VSUM_EQ THEN
1399          ASM_SIMP_TAC[] THEN
1400          ASM SET_TAC[];
1401        ASM_REWRITE_TAC[]]];
1402        ALL_TAC] THEN
1403     REWRITE_TAC[affine_dependent;AFFINE_HULL_EXPLICIT;IN_ELIM_THM] THEN
1404     REPEAT STRIP_TAC THEN
1405     EXISTS_TAC `v:real^N` THEN
1406     CONJ_TAC THENL [ASM SET_TAC[];ALL_TAC] THEN
1407     EXISTS_TAC `s DELETE (v:real^N)` THEN
1408     EXISTS_TAC `\x:real^N. -- (&1 / (u v)) * u x` THEN
1409     ASM_SIMP_TAC[FINITE_DELETE;SUM_DELETE;VSUM_DELETE_CASES] THEN
1410     ASM_SIMP_TAC[SUM_LMUL;GSYM VECTOR_MUL_ASSOC;VSUM_LMUL;
1411             VECTOR_MUL_RZERO;VECTOR_ARITH `vec 0 - -- a % x = a % x:real^N`;
1412             REAL_MUL_RZERO;REAL_ARITH `&0 - -- a * b = a * b`] THEN
1413     ASM_SIMP_TAC[REAL_FIELD `~(x = &0) ==> &1 / x * x = &1`;
1414                  VECTOR_MUL_ASSOC;VECTOR_MUL_LID] THEN
1415     CONJ_TAC THENL [ALL_TAC;ASM SET_TAC[]] THEN
1416     ASM_SIMP_TAC[SET_RULE `v IN s ==> (s DELETE v = {} <=> s = {v})`] THEN
1417     ASM_CASES_TAC `s = {v:real^N}` THEN
1418     ASM_REWRITE_TAC[] THEN
1419     FIRST_X_ASSUM SUBST_ALL_TAC THEN
1420     FIND_ASSUM MP_TAC `sum {v:real^N} u = &0` THEN
1421     REWRITE_TAC[SUM_SING]
1422     THEN ASM_REWRITE_TAC[]);;
1423
1424 let AFFINE_DEPENDENT_EXPLICIT_FINITE = prove
1425  (`!s. FINITE(s:real^N -> bool)
1426        ==> (affine_dependent s <=>
1427             ?u. sum s u = &0 /\
1428                 (?v. v IN s /\ ~(u v = &0)) /\
1429                 vsum s (\v. u v % v) = vec 0)`,
1430   REPEAT STRIP_TAC THEN REWRITE_TAC[AFFINE_DEPENDENT_EXPLICIT] THEN
1431   EQ_TAC THENL [ALL_TAC; ASM_MESON_TAC[SUBSET_REFL]] THEN
1432   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool`
1433    (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC)) THEN
1434   EXISTS_TAC `\x:real^N. if x IN t then u(x) else &0` THEN
1435   REWRITE_TAC[COND_RAND; COND_RATOR; VECTOR_MUL_LZERO] THEN
1436   ASM_SIMP_TAC[GSYM SUM_RESTRICT_SET; GSYM VSUM_RESTRICT_SET] THEN
1437   ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
1438   ASM SET_TAC[]);;
1439
1440 let AFFINE_DEPENDENT_TRANSLATION_EQ = prove
1441  (`!a s. affine_dependent (IMAGE (\x. a + x) s) <=> affine_dependent s`,
1442   REWRITE_TAC[affine_dependent] THEN GEOM_TRANSLATE_TAC[]);;
1443
1444 add_translation_invariants [AFFINE_DEPENDENT_TRANSLATION_EQ];;
1445
1446 let AFFINE_DEPENDENT_TRANSLATION = prove
1447  (`!s a. affine_dependent s ==> affine_dependent (IMAGE (\x. a + x) s)`,
1448   REWRITE_TAC[AFFINE_DEPENDENT_TRANSLATION_EQ]);;
1449
1450 let AFFINE_DEPENDENT_LINEAR_IMAGE_EQ = prove
1451  (`!f:real^M->real^N s.
1452         linear f /\ (!x y. f x = f y ==> x = y)
1453         ==> (affine_dependent(IMAGE f s) <=> affine_dependent s)`,
1454   REWRITE_TAC[affine_dependent] THEN GEOM_TRANSFORM_TAC[]);;
1455
1456 add_linear_invariants [AFFINE_DEPENDENT_LINEAR_IMAGE_EQ];;
1457
1458 let AFFINE_DEPENDENT_LINEAR_IMAGE = prove
1459  (`!f:real^M->real^N s.
1460         linear f /\ (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) /\
1461         affine_dependent(s)
1462         ==> affine_dependent(IMAGE f s)`,
1463   REPEAT GEN_TAC THEN
1464   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
1465   REWRITE_TAC[affine_dependent; EXISTS_IN_IMAGE] THEN
1466   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^M` THEN
1467   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1468   SUBGOAL_THEN `IMAGE (f:real^M->real^N) s DELETE f a = IMAGE f (s DELETE a)`
1469    (fun t -> ASM_SIMP_TAC[FUN_IN_IMAGE; AFFINE_HULL_LINEAR_IMAGE; t]) THEN
1470   ASM SET_TAC[]);;
1471
1472 let AFFINE_DEPENDENT_MONO = prove
1473  (`!s t:real^N->bool. affine_dependent s /\ s SUBSET t ==> affine_dependent t`,
1474   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
1475   REWRITE_TAC[affine_dependent] THEN MATCH_MP_TAC MONO_EXISTS THEN
1476   X_GEN_TAC `x:real^N` THEN MATCH_MP_TAC MONO_AND THEN CONJ_TAC THEN
1477   FIRST_ASSUM(MP_TAC o MATCH_MP HULL_MONO o SPEC `x:real^N` o MATCH_MP
1478    (SET_RULE `!x. s SUBSET t ==> (s DELETE x) SUBSET (t DELETE x)`)) THEN
1479   ASM SET_TAC[]);;
1480
1481 let AFFINE_INDEPENDENT_EMPTY = prove
1482  (`~(affine_dependent {})`,
1483   REWRITE_TAC[affine_dependent; NOT_IN_EMPTY]);;
1484
1485 let AFFINE_INDEPENDENT_1 = prove
1486  (`!a:real^N. ~(affine_dependent {a})`,
1487   REWRITE_TAC[affine_dependent; EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN
1488   REWRITE_TAC[SET_RULE `{a} DELETE a = {}`; AFFINE_HULL_EMPTY; NOT_IN_EMPTY]);;
1489
1490 let AFFINE_INDEPENDENT_2 = prove
1491  (`!a b:real^N. ~(affine_dependent {a,b})`,
1492   REPEAT GEN_TAC THEN ASM_CASES_TAC `b:real^N = a` THENL
1493    [ASM_REWRITE_TAC[INSERT_AC; AFFINE_INDEPENDENT_1];
1494     REWRITE_TAC[affine_dependent; EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN
1495     ASM_SIMP_TAC[SET_RULE
1496      `~(a = b) ==> {a,b} DELETE a = {b} /\ {a,b} DELETE b = {a}`] THEN
1497     ASM_REWRITE_TAC[AFFINE_HULL_SING; IN_SING]]);;
1498
1499 let AFFINE_INDEPENDENT_SUBSET = prove
1500  (`!s t. ~affine_dependent t /\ s SUBSET t ==> ~affine_dependent s`,
1501   REWRITE_TAC[IMP_CONJ_ALT; CONTRAPOS_THM] THEN
1502   REWRITE_TAC[GSYM IMP_CONJ_ALT; AFFINE_DEPENDENT_MONO]);;
1503
1504 let AFFINE_INDEPENDENT_DELETE = prove
1505  (`!s a. ~affine_dependent s ==> ~affine_dependent(s DELETE a)`,
1506   REPEAT GEN_TAC THEN
1507   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_INDEPENDENT_SUBSET) THEN
1508   SET_TAC[]);;
1509
1510 (* ------------------------------------------------------------------------- *)
1511 (* Coplanarity, and collinearity in terms of affine hull.                    *)
1512 (* ------------------------------------------------------------------------- *)
1513
1514 let coplanar = new_definition
1515  `coplanar s <=> ?u v w. s SUBSET affine hull {u,v,w}`;;
1516
1517 let COLLINEAR_AFFINE_HULL = prove
1518  (`!s:real^N->bool. collinear s <=> ?u v. s SUBSET affine hull {u,v}`,
1519   GEN_TAC THEN REWRITE_TAC[collinear; AFFINE_HULL_2] THEN EQ_TAC THEN
1520   REWRITE_TAC[SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
1521   REWRITE_TAC[REAL_ARITH `u + v = &1 <=> &1 - u = v`; UNWIND_THM1] THENL
1522    [X_GEN_TAC `u:real^N` THEN DISCH_TAC THEN
1523     ASM_CASES_TAC `s:real^N->bool = {}` THEN
1524     ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
1525     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
1526     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN
1527     DISCH_TAC THEN EXISTS_TAC `x + u:real^N` THEN X_GEN_TAC `y:real^N` THEN
1528     DISCH_TAC THEN
1529     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `y:real^N`]) THEN
1530     ASM_REWRITE_TAC[VECTOR_ARITH `x - y:real^N = z <=> x = y + z`] THEN
1531     DISCH_THEN(X_CHOOSE_THEN `c:real` SUBST1_TAC) THEN
1532     EXISTS_TAC `&1 + c` THEN VECTOR_ARITH_TAC;
1533     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN DISCH_TAC THEN
1534     EXISTS_TAC `b - a:real^N` THEN
1535     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
1536     FIRST_X_ASSUM(fun th ->
1537       MP_TAC(SPEC `y:real^N` th) THEN MP_TAC(SPEC `x:real^N` th)) THEN
1538     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
1539     X_GEN_TAC `r:real` THEN DISCH_THEN SUBST1_TAC THEN
1540     X_GEN_TAC `s:real` THEN DISCH_THEN SUBST1_TAC THEN
1541     EXISTS_TAC `s - r:real` THEN VECTOR_ARITH_TAC]);;
1542
1543 let COLLINEAR_IMP_COPLANAR = prove
1544  (`!s. collinear s ==> coplanar s`,
1545   REWRITE_TAC[coplanar; COLLINEAR_AFFINE_HULL] THEN MESON_TAC[INSERT_AC]);;
1546
1547 let COPLANAR_SMALL = prove
1548  (`!s. FINITE s /\ CARD s <= 3 ==> coplanar s`,
1549   GEN_TAC THEN REWRITE_TAC[ARITH_RULE `s <= 3 <=> s <= 2 \/ s = 3`] THEN
1550   REWRITE_TAC[LEFT_OR_DISTRIB; GSYM HAS_SIZE] THEN
1551   DISCH_THEN(DISJ_CASES_THEN MP_TAC) THEN
1552   SIMP_TAC[COLLINEAR_IMP_COPLANAR; COLLINEAR_SMALL] THEN
1553   CONV_TAC(LAND_CONV HAS_SIZE_CONV) THEN REWRITE_TAC[coplanar] THEN
1554   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
1555   STRIP_TAC THEN ASM_REWRITE_TAC[HULL_INC; SUBSET]);;
1556
1557 let COPLANAR_EMPTY = prove
1558  (`coplanar {}`,
1559   SIMP_TAC[COLLINEAR_IMP_COPLANAR; COLLINEAR_EMPTY]);;
1560
1561 let COPLANAR_SING = prove
1562  (`!a. coplanar {a}`,
1563   SIMP_TAC[COLLINEAR_IMP_COPLANAR; COLLINEAR_SING]);;
1564
1565 let COPLANAR_2 = prove
1566  (`!a b. coplanar {a,b}`,
1567   SIMP_TAC[COLLINEAR_IMP_COPLANAR; COLLINEAR_2]);;
1568
1569 let COPLANAR_3 = prove
1570  (`!a b c. coplanar {a,b,c}`,
1571   REPEAT GEN_TAC THEN MATCH_MP_TAC COPLANAR_SMALL THEN
1572   SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_RULES] THEN ARITH_TAC);;
1573
1574 let COLLINEAR_AFFINE_HULL_COLLINEAR = prove
1575  (`!s. collinear(affine hull s) <=> collinear s`,
1576   REWRITE_TAC[COLLINEAR_AFFINE_HULL] THEN
1577   MESON_TAC[HULL_HULL; HULL_MONO; HULL_INC; SUBSET]);;
1578
1579 let COPLANAR_AFFINE_HULL_COPLANAR = prove
1580  (`!s. coplanar(affine hull s) <=> coplanar s`,
1581   REWRITE_TAC[coplanar] THEN
1582   MESON_TAC[HULL_HULL; HULL_MONO; HULL_INC; SUBSET]);;
1583
1584 let COPLANAR_TRANSLATION_EQ = prove
1585  (`!a:real^N s. coplanar(IMAGE (\x. a + x) s) <=> coplanar s`,
1586   REWRITE_TAC[coplanar] THEN GEOM_TRANSLATE_TAC[]);;
1587
1588 let COPLANAR_TRANSLATION = prove
1589  (`!a:real^N s. coplanar s ==> coplanar(IMAGE (\x. a + x) s)`,
1590   REWRITE_TAC[COPLANAR_TRANSLATION_EQ]);;
1591
1592 add_translation_invariants [COPLANAR_TRANSLATION_EQ];;
1593
1594 let COPLANAR_LINEAR_IMAGE = prove
1595  (`!f:real^M->real^N s. coplanar s /\ linear f ==> coplanar(IMAGE f s)`,
1596   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
1597   REWRITE_TAC[coplanar; LEFT_IMP_EXISTS_THM] THEN
1598   MAP_EVERY X_GEN_TAC [`a:real^M`; `b:real^M`; `c:real^M`] THEN STRIP_TAC THEN
1599   MAP_EVERY EXISTS_TAC
1600   [`(f:real^M->real^N) a`; `(f:real^M->real^N) b`; `(f:real^M->real^N) c`] THEN
1601   REWRITE_TAC[SET_RULE `{f a,f b,f c} = IMAGE f {a,b,c}`] THEN
1602   ASM_SIMP_TAC[AFFINE_HULL_LINEAR_IMAGE; IMAGE_SUBSET]);;
1603
1604 let COPLANAR_LINEAR_IMAGE_EQ = prove
1605  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
1606          ==> (coplanar (IMAGE f s) <=> coplanar s)`,
1607   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE COPLANAR_LINEAR_IMAGE));;
1608
1609 add_linear_invariants [COPLANAR_LINEAR_IMAGE_EQ];;
1610
1611 let COPLANAR_SUBSET = prove
1612  (`!s t. coplanar t /\ s SUBSET t ==> coplanar s`,
1613   REWRITE_TAC[coplanar] THEN SET_TAC[]);;
1614
1615 let AFFINE_HULL_3_IMP_COLLINEAR = prove
1616  (`!a b c. c IN affine hull {a,b} ==> collinear {a,b,c}`,
1617   ONCE_REWRITE_TAC[GSYM COLLINEAR_AFFINE_HULL_COLLINEAR] THEN
1618   SIMP_TAC[HULL_REDUNDANT_EQ; INSERT_AC] THEN
1619   REWRITE_TAC[COLLINEAR_AFFINE_HULL_COLLINEAR; COLLINEAR_2]);;
1620
1621 let COLLINEAR_3_AFFINE_HULL = prove
1622  (`!a b c:real^N.
1623         ~(a = b) ==> (collinear {a,b,c} <=> c IN affine hull {a,b})`,
1624   REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[AFFINE_HULL_3_IMP_COLLINEAR] THEN
1625   REWRITE_TAC[collinear] THEN
1626   DISCH_THEN(X_CHOOSE_THEN `u:real^N` STRIP_ASSUME_TAC) THEN
1627   FIRST_ASSUM(fun th -> MP_TAC(SPECL [`b:real^N`; `a:real^N`] th) THEN
1628                         MP_TAC(SPECL [`c:real^N`; `a:real^N`] th)) THEN
1629   REWRITE_TAC[IN_INSERT; AFFINE_HULL_2; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
1630   REWRITE_TAC[VECTOR_ARITH `a - b:real^N = c <=> a = b + c`] THEN
1631   X_GEN_TAC `x:real` THEN DISCH_TAC THEN X_GEN_TAC `y:real` THEN
1632   ASM_CASES_TAC `y = &0` THEN
1633   ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_RID] THEN DISCH_TAC THEN
1634   ASM_REWRITE_TAC[] THEN
1635   MAP_EVERY EXISTS_TAC [`&1 - x / y`; `x / y:real`] THEN
1636   CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
1637   REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC] THEN
1638   ASM_SIMP_TAC[REAL_DIV_RMUL] THEN VECTOR_ARITH_TAC);;
1639
1640 let COLLINEAR_3_EQ_AFFINE_DEPENDENT = prove
1641  (`!a b c:real^N.
1642         collinear{a,b,c} <=>
1643                 a = b \/ a = c \/ b = c \/ affine_dependent {a,b,c}`,
1644   REPEAT GEN_TAC THEN
1645   MAP_EVERY (fun t ->
1646     ASM_CASES_TAC t THENL [ASM_REWRITE_TAC[INSERT_AC; COLLINEAR_2]; ALL_TAC])
1647    [`a:real^N = b`; `a:real^N = c`; `b:real^N = c`] THEN
1648   ASM_REWRITE_TAC[affine_dependent] THEN EQ_TAC THENL
1649    [ASM_SIMP_TAC[COLLINEAR_3_AFFINE_HULL] THEN DISCH_TAC THEN
1650     EXISTS_TAC `c:real^N` THEN REWRITE_TAC[IN_INSERT];
1651     REWRITE_TAC[EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN STRIP_TAC THENL
1652      [ONCE_REWRITE_TAC[SET_RULE `{a,b,c} = {b,c,a}`];
1653       ONCE_REWRITE_TAC[SET_RULE `{a,b,c} = {c,a,b}`];
1654       ALL_TAC] THEN
1655     ASM_SIMP_TAC[COLLINEAR_3_AFFINE_HULL]] THEN
1656   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
1657    `x IN s ==> s SUBSET t ==> x IN t`)) THEN
1658   MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]);;
1659
1660 let AFFINE_DEPENDENT_IMP_COLLINEAR_3 = prove
1661  (`!a b c:real^N. affine_dependent {a,b,c} ==> collinear{a,b,c}`,
1662   REPEAT GEN_TAC THEN REWRITE_TAC[affine_dependent] THEN
1663   REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; RIGHT_OR_DISTRIB] THEN
1664   REWRITE_TAC[EXISTS_OR_THM; UNWIND_THM2; COLLINEAR_AFFINE_HULL] THEN
1665   STRIP_TAC THENL
1666    [MAP_EVERY EXISTS_TAC [`b:real^N`; `c:real^N`];
1667     MAP_EVERY EXISTS_TAC [`a:real^N`; `c:real^N`];
1668     MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real^N`]] THEN
1669   SIMP_TAC[INSERT_SUBSET; EMPTY_SUBSET; HULL_INC; IN_INSERT] THEN
1670   POP_ASSUM MP_TAC THEN
1671   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> a IN s ==> a IN t`) THEN
1672   MATCH_MP_TAC HULL_MONO THEN SET_TAC[]);;
1673
1674 let COLLINEAR_3_IN_AFFINE_HULL = prove
1675  (`!v0 v1 x:real^N.
1676         ~(v1 = v0)
1677         ==> (collinear {v0,v1,x} <=> x IN affine hull {v0,v1})`,
1678   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `v0:real^N` THEN
1679   REWRITE_TAC[COLLINEAR_LEMMA; AFFINE_HULL_2] THEN REPEAT STRIP_TAC THEN
1680   ASM_REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID; IN_ELIM_THM] THEN
1681   ASM_CASES_TAC `x:real^N = vec 0` THEN ASM_REWRITE_TAC[] THENL
1682    [MAP_EVERY EXISTS_TAC [`&1`; `&0`] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
1683     VECTOR_ARITH_TAC;
1684     MESON_TAC[REAL_ARITH `u + v = &1 <=> u = &1 - v`]]);;
1685
1686 (* ------------------------------------------------------------------------- *)
1687 (* A general lemma.                                                          *)
1688 (* ------------------------------------------------------------------------- *)
1689
1690 let CONVEX_CONNECTED = prove
1691  (`!s:real^N->bool. convex s ==> connected s`,
1692   REWRITE_TAC[CONVEX_ALT; connected; SUBSET; EXTENSION; IN_INTER;
1693               IN_UNION; NOT_IN_EMPTY; NOT_FORALL_THM; NOT_EXISTS_THM] THEN
1694   GEN_TAC THEN DISCH_TAC THEN REPEAT GEN_TAC THEN
1695   MAP_EVERY (K(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC))) (1--4) THEN
1696   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_THEN `x1:real^N` STRIP_ASSUME_TAC)
1697                          (X_CHOOSE_THEN `x2:real^N` STRIP_ASSUME_TAC)) THEN
1698   MP_TAC(ISPECL [`\u. (&1 - u) % x1 + u % (x2:real^N)`;
1699                  `&0`; `&1`; `e1:real^N->bool`; `e2:real^N->bool`]
1700          (REWRITE_RULE[GSYM open_def] CONNECTED_REAL_LEMMA)) THEN
1701   ASM_REWRITE_TAC[NOT_IMP; REAL_SUB_RZERO; VECTOR_MUL_LID; VECTOR_MUL_LZERO;
1702                   REAL_SUB_REFL; VECTOR_ADD_RID; VECTOR_ADD_LID; REAL_POS] THEN
1703   REPEAT(CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]]) THEN
1704   REPEAT STRIP_TAC THEN REWRITE_TAC[dist] THEN
1705   REWRITE_TAC[NORM_MUL; VECTOR_ARITH
1706    `((&1 - a) % x + a % y) - ((&1 - b) % x + b % y) = (a - b) % (y - x)`] THEN
1707   MP_TAC(ISPEC `(x2 - x1):real^N` NORM_POS_LE) THEN
1708   REWRITE_TAC[REAL_LE_LT] THEN STRIP_TAC THENL
1709    [ALL_TAC; ASM_MESON_TAC[REAL_MUL_RZERO; REAL_LT_01]] THEN
1710   EXISTS_TAC `e / norm((x2 - x1):real^N)` THEN
1711   ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LT_DIV]);;
1712
1713 (* ------------------------------------------------------------------------- *)
1714 (* Various topological facts are queued up here, just because they rely on   *)
1715 (* CONNECTED_UNIV, which is a trivial consequence of CONVEX_UNIV. It would   *)
1716 (* be fairly easy to prove it earlier and move these back to the topology.ml *)
1717 (* file, which is a bit tidier intellectually.                               *)
1718 (* ------------------------------------------------------------------------- *)
1719
1720 let CONNECTED_UNIV = prove
1721  (`connected (UNIV:real^N->bool)`,
1722   SIMP_TAC[CONVEX_CONNECTED; CONVEX_UNIV]);;
1723
1724 let CONNECTED_COMPONENT_UNIV = prove
1725  (`!x. connected_component(:real^N) x = (:real^N)`,
1726   MESON_TAC[CONNECTED_CONNECTED_COMPONENT_SET; CONNECTED_UNIV; IN_UNIV]);;
1727
1728 let CONNECTED_COMPONENT_EQ_UNIV = prove
1729  (`!s x. connected_component s x = (:real^N) <=> s = (:real^N)`,
1730   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CONNECTED_COMPONENT_UNIV] THEN
1731   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> s = UNIV ==> t = UNIV`) THEN
1732   REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]);;
1733
1734 let CLOPEN = prove
1735  (`!s. closed s /\ open s <=> s = {} \/ s = (:real^N)`,
1736   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
1737   ASM_REWRITE_TAC[CLOSED_EMPTY; OPEN_EMPTY; CLOSED_UNIV; OPEN_UNIV] THEN
1738   MATCH_MP_TAC(REWRITE_RULE[CONNECTED_CLOPEN] CONNECTED_UNIV) THEN
1739   ASM_REWRITE_TAC[SUBTOPOLOGY_UNIV; GSYM OPEN_IN; GSYM CLOSED_IN]);;
1740
1741 let COMPACT_OPEN = prove
1742  (`!s:real^N->bool. compact s /\ open s <=> s = {}`,
1743   MESON_TAC[COMPACT_EMPTY; OPEN_EMPTY; COMPACT_IMP_CLOSED; CLOPEN;
1744             COMPACT_IMP_BOUNDED; NOT_BOUNDED_UNIV]);;
1745
1746 let FRONTIER_NOT_EMPTY = prove
1747  (`!s. ~(s = {}) /\ ~(s = (:real^N)) ==> ~(frontier s = {})`,
1748   REPEAT STRIP_TAC THEN
1749   MP_TAC(ISPECL [`(:real^N)`; `s:real^N->bool`] CONNECTED_INTER_FRONTIER) THEN
1750   REWRITE_TAC[CONNECTED_UNIV] THEN ASM SET_TAC[]);;
1751
1752 let FRONTIER_EQ_EMPTY = prove
1753  (`!s. frontier s = {} <=> s = {} \/ s = (:real^N)`,
1754   MESON_TAC[FRONTIER_NOT_EMPTY; FRONTIER_EMPTY; FRONTIER_UNIV]);;
1755
1756 let EQ_INTERVAL = prove
1757  (`(!a b c d:real^N.
1758         interval[a,b] = interval[c,d] <=>
1759         interval[a,b] = {} /\ interval[c,d] = {} \/ a = c /\ b = d) /\
1760    (!a b c d:real^N.
1761         interval[a,b] = interval(c,d) <=>
1762         interval[a,b] = {} /\ interval(c,d) = {}) /\
1763    (!a b c d:real^N.
1764         interval(a,b) = interval[c,d] <=>
1765         interval(a,b) = {} /\ interval[c,d] = {}) /\
1766    (!a b c d:real^N.
1767         interval(a,b) = interval(c,d) <=>
1768         interval(a,b) = {} /\ interval(c,d) = {} \/ a = c /\ b = d)`,
1769   REPEAT CONJ_TAC THEN REPEAT GEN_TAC THEN
1770   (EQ_TAC THENL [ALL_TAC; STRIP_TAC THEN ASM_REWRITE_TAC[]]) THEN
1771   MATCH_MP_TAC(MESON[]
1772    `(p = {} /\ q = {} ==> r) /\ (~(p = {}) /\ ~(q = {}) ==> p = q ==> r)
1773     ==> p = q ==> r`) THEN
1774   SIMP_TAC[] THENL
1775    [REWRITE_TAC[INTERVAL_NE_EMPTY; CART_EQ] THEN
1776     REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
1777     SIMP_TAC[SUBSET_INTERVAL; GSYM REAL_LE_ANTISYM];
1778     STRIP_TAC THEN MATCH_MP_TAC(MESON[CLOPEN]
1779      `closed s /\ open t /\ ~(s = {}) /\ ~(s = UNIV) ==> ~(s = t)`) THEN
1780     ASM_REWRITE_TAC[CLOSED_INTERVAL; OPEN_INTERVAL; NOT_INTERVAL_UNIV];
1781     STRIP_TAC THEN MATCH_MP_TAC(MESON[CLOPEN]
1782      `closed s /\ open t /\ ~(s = {}) /\ ~(s = UNIV) ==> ~(t = s)`) THEN
1783     ASM_REWRITE_TAC[CLOSED_INTERVAL; OPEN_INTERVAL; NOT_INTERVAL_UNIV];
1784     REWRITE_TAC[INTERVAL_NE_EMPTY; CART_EQ] THEN
1785     REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
1786     SIMP_TAC[SUBSET_INTERVAL; GSYM REAL_LE_ANTISYM]]);;
1787
1788 let CLOSED_INTERVAL_EQ = prove
1789  (`(!a b:real^N. closed(interval[a,b])) /\
1790    (!a b:real^N. closed(interval(a,b)) <=> interval(a,b) = {})`,
1791   REWRITE_TAC[CLOSED_INTERVAL] THEN
1792   REPEAT GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
1793   ASM_REWRITE_TAC[CLOSED_EMPTY] THEN
1794   MP_TAC(ISPEC `interval(a:real^N,b)` CLOPEN) THEN
1795   ASM_REWRITE_TAC[OPEN_INTERVAL] THEN
1796   MESON_TAC[BOUNDED_INTERVAL; NOT_BOUNDED_UNIV]);;
1797
1798 let OPEN_INTERVAL_EQ = prove
1799  (`(!a b:real^N. open(interval[a,b]) <=> interval[a,b] = {}) /\
1800    (!a b:real^N. open(interval(a,b)))`,
1801   REWRITE_TAC[OPEN_INTERVAL] THEN
1802   REPEAT GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
1803   ASM_REWRITE_TAC[CLOSED_EMPTY] THEN
1804   MP_TAC(ISPEC `interval[a:real^N,b]` CLOPEN) THEN
1805   ASM_REWRITE_TAC[CLOSED_INTERVAL] THEN
1806   MESON_TAC[BOUNDED_INTERVAL; NOT_BOUNDED_UNIV]);;
1807
1808 let COMPACT_INTERVAL_EQ = prove
1809  (`(!a b:real^N. compact(interval[a,b])) /\
1810    (!a b:real^N. compact(interval(a,b)) <=> interval(a,b) = {})`,
1811   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_INTERVAL] THEN
1812   REWRITE_TAC[CLOSED_INTERVAL_EQ]);;
1813
1814 let CONNECTED_CHAIN = prove
1815  (`!f:(real^N->bool)->bool.
1816         (!s. s IN f ==> compact s /\ connected s) /\
1817         (!s t. s IN f /\ t IN f ==> s SUBSET t \/ t SUBSET s)
1818         ==> connected(INTERS f)`,
1819   REPEAT STRIP_TAC THEN
1820   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
1821   ASM_REWRITE_TAC[INTERS_0; CONNECTED_UNIV] THEN
1822   ABBREV_TAC `c:real^N->bool = INTERS f` THEN
1823   SUBGOAL_THEN `compact(c:real^N->bool)` ASSUME_TAC THENL
1824    [EXPAND_TAC "c" THEN MATCH_MP_TAC COMPACT_INTERS THEN ASM SET_TAC[];
1825     ALL_TAC] THEN
1826   ASM_SIMP_TAC[CONNECTED_CLOSED_SET; COMPACT_IMP_CLOSED; NOT_EXISTS_THM] THEN
1827   MAP_EVERY X_GEN_TAC [`a:real^N->bool`; `b:real^N->bool`] THEN STRIP_TAC THEN
1828   MP_TAC(ISPECL [`a:real^N->bool`; `b:real^N->bool`] SEPARATION_NORMAL) THEN
1829   ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
1830   MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
1831   STRIP_TAC THEN
1832   SUBGOAL_THEN `?k:real^N->bool. k IN f` STRIP_ASSUME_TAC THENL
1833    [ASM SET_TAC[]; ALL_TAC] THEN
1834   SUBGOAL_THEN `?n:real^N->bool. open n /\ k SUBSET n` MP_TAC THENL
1835    [ASM_MESON_TAC[BOUNDED_SUBSET_BALL; COMPACT_IMP_BOUNDED; OPEN_BALL];
1836     REWRITE_TAC[UNIONS_SUBSET] THEN STRIP_TAC] THEN
1837   MP_TAC(ISPEC `k:real^N->bool` COMPACT_IMP_HEINE_BOREL) THEN
1838   ASM_SIMP_TAC[] THEN DISCH_THEN(MP_TAC o SPEC
1839    `(u UNION v:real^N->bool) INSERT {n DIFF s | s IN f}`) THEN
1840   REWRITE_TAC[SIMPLE_IMAGE; FORALL_IN_INSERT; FORALL_IN_IMAGE] THEN
1841   ASM_SIMP_TAC[OPEN_UNION; OPEN_DIFF; COMPACT_IMP_CLOSED; NOT_IMP] THEN
1842   CONJ_TAC THENL
1843    [REWRITE_TAC[UNIONS_INSERT] THEN REWRITE_TAC[SUBSET] THEN
1844     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN ONCE_REWRITE_TAC[IN_UNION] THEN
1845     ASM_CASES_TAC `(x:real^N) IN c` THENL [ASM SET_TAC[]; DISJ2_TAC] THEN
1846     REWRITE_TAC[UNIONS_IMAGE; IN_ELIM_THM] THEN
1847     UNDISCH_TAC `~((x:real^N) IN c)` THEN
1848     SUBST1_TAC(SYM(ASSUME `INTERS f:real^N->bool = c`)) THEN
1849     REWRITE_TAC[IN_INTERS; NOT_FORALL_THM] THEN
1850     MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[];
1851     ALL_TAC] THEN
1852   DISCH_THEN(X_CHOOSE_THEN `g:(real^N->bool)->bool` MP_TAC) THEN
1853   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
1854   REWRITE_TAC[SUBSET_INSERT_DELETE] THEN
1855   SUBGOAL_THEN `FINITE(g DELETE (u UNION v:real^N->bool))` MP_TAC THENL
1856    [ASM_REWRITE_TAC[FINITE_DELETE];
1857     REWRITE_TAC[TAUT `p ==> ~q <=> ~(p /\ q)`]] THEN
1858   REWRITE_TAC[FINITE_SUBSET_IMAGE] THEN
1859   DISCH_THEN(X_CHOOSE_THEN `f':(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
1860   SUBGOAL_THEN
1861    `?j:real^N->bool. j IN f /\
1862                      UNIONS(IMAGE (\s. n DIFF s) f') SUBSET (n DIFF j)`
1863   STRIP_ASSUME_TAC THENL
1864    [ASM_CASES_TAC `f':(real^N->bool)->bool = {}` THEN
1865     ASM_REWRITE_TAC[IMAGE_CLAUSES; UNIONS_0; EMPTY_SUBSET] THENL
1866      [ASM SET_TAC[]; ALL_TAC] THEN
1867     SUBGOAL_THEN
1868      `?j:real^N->bool. j IN f' /\
1869                        UNIONS(IMAGE (\s. n DIFF s) f') SUBSET (n DIFF j)`
1870     MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[SUBSET]] THEN
1871     SUBGOAL_THEN
1872      `!s t:real^N->bool. s IN f' /\ t IN f' ==> s SUBSET t \/ t SUBSET s`
1873     MP_TAC THENL [ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
1874     UNDISCH_TAC `~(f':(real^N->bool)->bool = {})` THEN
1875     UNDISCH_TAC `FINITE(f':(real^N->bool)->bool)` THEN
1876     SPEC_TAC(`f':(real^N->bool)->bool`,`f':(real^N->bool)->bool`) THEN
1877     MATCH_MP_TAC FINITE_INDUCT_STRONG THEN REWRITE_TAC[] THEN
1878     REWRITE_TAC[EXISTS_IN_INSERT; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1879     REWRITE_TAC[FORALL_IN_INSERT] THEN POP_ASSUM_LIST(K ALL_TAC) THEN
1880     MAP_EVERY X_GEN_TAC [`i:real^N->bool`; `f:(real^N->bool)->bool`] THEN
1881     ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
1882     ASM_REWRITE_TAC[IMAGE_CLAUSES; UNIONS_INSERT; NOT_IN_EMPTY;
1883                     UNIONS_0; UNION_EMPTY; SUBSET_REFL] THEN
1884     DISCH_THEN(fun th -> REPEAT DISCH_TAC THEN MP_TAC th) THEN
1885     ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
1886     DISCH_THEN(X_CHOOSE_THEN `j:real^N->bool` STRIP_ASSUME_TAC) THEN
1887     SUBGOAL_THEN `(n DIFF j) SUBSET (n DIFF i) \/
1888                   (n DIFF i:real^N->bool) SUBSET (n DIFF j)`
1889     STRIP_ASSUME_TAC THENL
1890      [FIRST_X_ASSUM(MP_TAC o SPEC `j:real^N->bool` o CONJUNCT2) THEN
1891       ASM SET_TAC[];
1892       DISJ1_TAC THEN ASM SET_TAC[];
1893       DISJ2_TAC THEN EXISTS_TAC `j:real^N->bool` THEN ASM SET_TAC[]];
1894     ALL_TAC] THEN
1895   SUBGOAL_THEN `(j INTER k:real^N->bool) SUBSET (u UNION v)` ASSUME_TAC THENL
1896    [MATCH_MP_TAC(SET_RULE
1897      `k SUBSET (u UNION v) UNION (n DIFF j)
1898       ==> (j INTER k) SUBSET (u UNION v)`) THEN
1899     MATCH_MP_TAC SUBSET_TRANS THEN
1900     EXISTS_TAC `UNIONS g :real^N->bool` THEN ASM_REWRITE_TAC[] THEN
1901     MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC
1902      `UNIONS((u UNION v:real^N->bool) INSERT (g DELETE (u UNION v)))` THEN
1903     CONJ_TAC THENL [MATCH_MP_TAC SUBSET_UNIONS THEN SET_TAC[]; ALL_TAC] THEN
1904     ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[UNIONS_INSERT] THEN
1905     ASM SET_TAC[];
1906     ALL_TAC] THEN
1907   SUBGOAL_THEN `connected(j INTER k:real^N->bool)` MP_TAC THENL
1908    [ASM_MESON_TAC[SET_RULE `s SUBSET t ==> s INTER t = s`; INTER_COMM];
1909     REWRITE_TAC[connected] THEN
1910     MAP_EVERY EXISTS_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
1911     ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;
1912
1913 let CONNECTED_CHAIN_GEN = prove
1914  (`!f:(real^N->bool)->bool.
1915        (!s. s IN f ==> closed s /\ connected s) /\
1916        (?s. s IN f /\ compact s) /\
1917        (!s t. s IN f /\ t IN f ==> s SUBSET t \/ t SUBSET s)
1918        ==> connected(INTERS f)`,
1919   GEN_TAC THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
1920   FIRST_X_ASSUM(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
1921   SUBGOAL_THEN
1922    `INTERS f = INTERS(IMAGE (\t:real^N->bool. s INTER t) f)`
1923   SUBST1_TAC THENL
1924    [REWRITE_TAC[EXTENSION; INTERS_IMAGE] THEN ASM SET_TAC[];
1925     MATCH_MP_TAC CONNECTED_CHAIN THEN
1926     REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
1927     ASM_SIMP_TAC[COMPACT_INTER_CLOSED] THEN
1928     CONJ_TAC THENL [X_GEN_TAC `t:real^N->bool`; ASM SET_TAC[]] THEN
1929     DISCH_TAC THEN
1930     SUBGOAL_THEN `s INTER t:real^N->bool = s \/ s INTER t = t`
1931      (DISJ_CASES_THEN SUBST1_TAC) THEN
1932     ASM SET_TAC[]]);;
1933
1934 let CONNECTED_NEST = prove
1935  (`!s. (!n. compact(s n) /\ connected(s n)) /\
1936        (!m n. m <= n ==> s n SUBSET s m)
1937        ==> connected(INTERS {s n | n IN (:num)})`,
1938   GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC CONNECTED_CHAIN THEN
1939   ASM_SIMP_TAC[FORALL_IN_GSPEC; IN_UNIV; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1940   MATCH_MP_TAC WLOG_LE THEN ASM_MESON_TAC[]);;
1941
1942 let CONNECTED_NEST_GEN = prove
1943  (`!s. (!n. closed(s n) /\ connected(s n)) /\ (?n. compact(s n)) /\
1944        (!m n. m <= n ==> s n SUBSET s m)
1945        ==> connected(INTERS {s n | n IN (:num)})`,
1946   GEN_TAC THEN
1947   DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC) THEN
1948   MATCH_MP_TAC CONNECTED_CHAIN_GEN THEN
1949   ASM_SIMP_TAC[FORALL_IN_GSPEC; IN_UNIV; IMP_CONJ; RIGHT_FORALL_IMP_THM;
1950                EXISTS_IN_GSPEC] THEN
1951   MATCH_MP_TAC WLOG_LE THEN ASM_MESON_TAC[]);;
1952
1953 let EQ_BALLS = prove
1954  (`(!a a':real^N r r'.
1955       ball(a,r) = ball(a',r') <=> a = a' /\ r = r' \/ r <= &0 /\ r' <= &0) /\
1956    (!a a':real^N r r'.
1957       ball(a,r) = cball(a',r') <=> r <= &0 /\ r' < &0) /\
1958    (!a a':real^N r r'.
1959       cball(a,r) = ball(a',r') <=> r < &0 /\ r' <= &0) /\
1960    (!a a':real^N r r'.
1961       cball(a,r) = cball(a',r') <=> a = a' /\ r = r' \/ r < &0 /\ r' < &0)`,
1962   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT STRIP_TAC THEN
1963   (EQ_TAC THENL
1964     [ALL_TAC; REWRITE_TAC[EXTENSION; IN_BALL; IN_CBALL] THEN NORM_ARITH_TAC])
1965   THENL
1966    [REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; SUBSET_BALLS] THEN NORM_ARITH_TAC;
1967     ONCE_REWRITE_TAC[EQ_SYM_EQ];
1968     ALL_TAC;
1969     REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; SUBSET_BALLS] THEN NORM_ARITH_TAC] THEN
1970   DISCH_THEN(MP_TAC o MATCH_MP (MESON[CLOPEN; BOUNDED_BALL; NOT_BOUNDED_UNIV]
1971     `s = t ==> closed s /\ open t /\ bounded t ==> s = {} /\ t = {}`)) THEN
1972   REWRITE_TAC[OPEN_BALL; CLOSED_CBALL; BOUNDED_BALL;
1973               BALL_EQ_EMPTY; CBALL_EQ_EMPTY] THEN
1974   REAL_ARITH_TAC);;
1975
1976 let FINITE_CBALL = prove
1977  (`!a:real^N r. FINITE(cball(a,r)) <=> r <= &0`,
1978   REPEAT STRIP_TAC THEN ASM_CASES_TAC `r < &0` THEN
1979   ASM_SIMP_TAC[CBALL_EMPTY; REAL_LT_IMP_LE; FINITE_EMPTY] THEN
1980   ASM_CASES_TAC `r = &0` THEN
1981   ASM_REWRITE_TAC[CBALL_TRIVIAL; FINITE_SING; REAL_LE_REFL] THEN
1982   EQ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
1983   DISCH_THEN(MP_TAC o MATCH_MP EMPTY_INTERIOR_FINITE) THEN
1984   REWRITE_TAC[INTERIOR_CBALL; BALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC);;
1985
1986 let FINITE_BALL = prove
1987  (`!a:real^N r. FINITE(ball(a,r)) <=> r <= &0`,
1988   REPEAT STRIP_TAC THEN ASM_CASES_TAC `r <= &0` THEN
1989   ASM_SIMP_TAC[BALL_EMPTY; REAL_LT_IMP_LE; FINITE_EMPTY] THEN
1990   DISCH_THEN(MP_TAC o MATCH_MP (ONCE_REWRITE_RULE[IMP_CONJ]
1991         FINITE_IMP_NOT_OPEN)) THEN
1992   REWRITE_TAC[OPEN_BALL; BALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC);;
1993
1994 (* ------------------------------------------------------------------------- *)
1995 (* Convex functions into the reals.                                          *)
1996 (* ------------------------------------------------------------------------- *)
1997
1998 parse_as_infix ("convex_on",(12,"right"));;
1999
2000 let convex_on = new_definition
2001   `f convex_on s <=>
2002         !x y u v. x IN s /\ y IN s /\ &0 <= u /\ &0 <= v /\ (u + v = &1)
2003                   ==> f(u % x + v % y) <= u * f(x) + v * f(y)`;;
2004
2005 let CONVEX_ON_SUBSET = prove
2006  (`!f s t. f convex_on t /\ s SUBSET t ==> f convex_on s`,
2007   REWRITE_TAC[convex_on; SUBSET] THEN MESON_TAC[]);;
2008
2009 let CONVEX_ADD = prove
2010  (`!s f g. f convex_on s /\ g convex_on s ==> (\x. f(x) + g(x)) convex_on s`,
2011   REWRITE_TAC[convex_on; AND_FORALL_THM] THEN
2012   REPEAT(MATCH_MP_TAC MONO_FORALL ORELSE GEN_TAC) THEN
2013   MATCH_MP_TAC(TAUT
2014     `(b /\ c ==> d) ==> (a ==> b) /\ (a ==> c) ==> a ==> d`) THEN
2015   REAL_ARITH_TAC);;
2016
2017 let CONVEX_CMUL = prove
2018  (`!s c f. &0 <= c /\ f convex_on s ==> (\x. c * f(x)) convex_on s`,
2019   SIMP_TAC[convex_on; REAL_LE_LMUL;
2020            REAL_ARITH `u * c * fx + v * c * fy = c * (u * fx + v * fy)`]);;
2021
2022 let CONVEX_MAX = prove
2023  (`!f g s. f convex_on s /\ g convex_on s
2024            ==> (\x. max (f x) (g x)) convex_on s`,
2025   REWRITE_TAC[convex_on; REAL_MAX_LE] THEN REPEAT STRIP_TAC THEN
2026   FIRST_X_ASSUM(fun th ->
2027     W(MP_TAC o PART_MATCH (lhand o rand) th o lhand o snd)) THEN
2028   ASM_REWRITE_TAC[] THEN
2029   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
2030   MATCH_MP_TAC REAL_LE_ADD2 THEN CONJ_TAC THEN
2031   MATCH_MP_TAC REAL_LE_LMUL THEN ASM_REAL_ARITH_TAC);;
2032
2033 let CONVEX_LOWER = prove
2034  (`!f s x y. f convex_on s /\
2035              x IN s /\ y IN s /\ &0 <= u /\ &0 <= v /\ (u + v = &1)
2036              ==> f(u % x + v % y) <= max (f(x)) (f(y))`,
2037   REWRITE_TAC[convex_on] THEN REPEAT STRIP_TAC THEN
2038   GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN
2039   FIRST_ASSUM(fun th -> GEN_REWRITE_TAC (RAND_CONV o LAND_CONV) [SYM th]) THEN
2040   REWRITE_TAC[REAL_ADD_RDISTRIB] THEN MATCH_MP_TAC REAL_LE_TRANS THEN
2041   ASM_MESON_TAC[REAL_LE_ADD2; REAL_LE_LMUL; REAL_MAX_MAX]);;
2042
2043 let CONVEX_LOWER_SEGMENT = prove
2044  (`!f s a b x:real^N.
2045         f convex_on s /\ a IN s /\ b IN s /\ x IN segment[a,b]
2046         ==> f(x) <= max (f a) (f b)`,
2047   REWRITE_TAC[IN_SEGMENT] THEN REPEAT STRIP_TAC THEN
2048   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONVEX_LOWER THEN
2049   EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
2050
2051 let CONVEX_LOCAL_GLOBAL_MINIMUM = prove
2052  (`!f s t x:real^N.
2053        f convex_on s /\ x IN t /\ open t /\ t SUBSET s /\
2054        (!y. y IN t ==> f(x) <= f(y))
2055        ==> !y. y IN s ==> f(x) <= f(y)`,
2056   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
2057   SUBGOAL_THEN `&0 < dist(x:real^N,y)` ASSUME_TAC THENL
2058    [ASM_MESON_TAC[DIST_POS_LT; REAL_LT_REFL]; ALL_TAC] THEN
2059   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
2060   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
2061   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
2062   MP_TAC(SPECL [`&1`; `e / dist(x:real^N,y)`] REAL_DOWN2) THEN
2063   ANTS_TAC THENL [ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_01]; ALL_TAC] THEN
2064   DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
2065   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex_on]) THEN
2066   DISCH_THEN(MP_TAC o
2067     SPECL [`x:real^N`; `y:real^N`; `&1 - u`; `u:real`]) THEN
2068   ANTS_TAC THENL
2069    [ASM_SIMP_TAC[REAL_SUB_ADD; REAL_SUB_LE; REAL_LT_IMP_LE] THEN
2070     ASM_MESON_TAC[CENTRE_IN_BALL; SUBSET];
2071     ALL_TAC] THEN
2072   REWRITE_TAC[REAL_NOT_LE] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN
2073   EXISTS_TAC `(&1 - u) * f(x) + u * f(x:real^N):real` THEN
2074   ASM_SIMP_TAC[REAL_LT_LADD; REAL_LT_LMUL] THEN
2075   REWRITE_TAC[REAL_ARITH `(&1 - x) * a + x * a = a`] THEN
2076   FIRST_X_ASSUM MATCH_MP_TAC THEN
2077   FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
2078   REWRITE_TAC[IN_BALL; dist] THEN
2079   REWRITE_TAC[VECTOR_ARITH `x - ((&1 - u) % x + u % y):real^N =
2080                             u % (x - y)`] THEN
2081   REWRITE_TAC[NORM_MUL; GSYM dist] THEN
2082   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ;
2083                REAL_ARITH `&0 < x /\ x < b ==> abs x < b`]);;
2084
2085 let CONVEX_DISTANCE = prove
2086  (`!s a. (\x. dist(a,x)) convex_on s`,
2087   REWRITE_TAC[convex_on; dist] THEN REPEAT STRIP_TAC THEN
2088   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o LAND_CONV)
2089    [GSYM VECTOR_MUL_LID] THEN
2090   FIRST_ASSUM(SUBST1_TAC o SYM) THEN
2091   REWRITE_TAC[VECTOR_ARITH
2092    `(u + v) % z - (u % x + v % y) = u % (z - x) + v % (z - y)`] THEN
2093   ASM_MESON_TAC[NORM_TRIANGLE; NORM_MUL; REAL_ABS_REFL]);;
2094
2095 let CONVEX_NORM = prove
2096  (`!s:real^N->bool. norm convex_on s`,
2097   GEN_TAC THEN
2098   MP_TAC(ISPECL [`s:real^N->bool`; `vec 0:real^N`] CONVEX_DISTANCE) THEN
2099   REWRITE_TAC[DIST_0; ETA_AX]);;
2100
2101 let CONVEX_ON_COMPOSE_LINEAR = prove
2102  (`!f g:real^M->real^N s.
2103         f convex_on (IMAGE g s) /\ linear g ==> (f o g) convex_on s`,
2104   REWRITE_TAC[convex_on; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
2105   REWRITE_TAC[FORALL_IN_IMAGE; o_THM] THEN
2106   REWRITE_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP; GSYM CONJ_ASSOC] THEN
2107   REPEAT STRIP_TAC THEN
2108   FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP LINEAR_ADD th]) THEN
2109   FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP LINEAR_CMUL th]) THEN
2110   ASM_SIMP_TAC[]);;
2111
2112 let CONVEX_ON_TRANSLATION = prove
2113  (`!f a:real^N.
2114         f convex_on (IMAGE (\x. a + x) s) <=> (\x. f(a + x)) convex_on s`,
2115   REWRITE_TAC[convex_on; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
2116   REWRITE_TAC[FORALL_IN_IMAGE; o_THM] THEN
2117   REWRITE_TAC[VECTOR_ARITH
2118    `u % (a + x) + v % (a + y):real^N = (u + v) % a + u % x + v % y`] THEN
2119   SIMP_TAC[VECTOR_MUL_LID]);;
2120
2121 (* ------------------------------------------------------------------------- *)
2122 (* Open and closed balls are convex and hence connected.                     *)
2123 (* ------------------------------------------------------------------------- *)
2124
2125 let CONVEX_BALL = prove
2126  (`!x:real^N e. convex(ball(x,e))`,
2127   let lemma = REWRITE_RULE[convex_on; IN_UNIV]
2128    (ISPEC `(:real^N)` CONVEX_DISTANCE) in
2129   REWRITE_TAC[convex; IN_BALL] THEN REPEAT STRIP_TAC THEN
2130   W(MP_TAC o PART_MATCH (lhand o rand) lemma o lhand o snd) THEN
2131   ASM_MESON_TAC[REAL_LET_TRANS; REAL_CONVEX_BOUND_LT]);;
2132
2133 let CONNECTED_BALL = prove
2134  (`!x:real^N e. connected(ball(x,e))`,
2135   SIMP_TAC[CONVEX_CONNECTED; CONVEX_BALL]);;
2136
2137 let CONVEX_CBALL = prove
2138  (`!x:real^N e. convex(cball(x,e))`,
2139   REWRITE_TAC[convex; IN_CBALL; dist] THEN MAP_EVERY X_GEN_TAC
2140    [`x:real^N`; `e:real`; `y:real^N`; `z:real^N`; `u:real`; `v:real`] THEN
2141   STRIP_TAC THEN ONCE_REWRITE_TAC[VECTOR_ARITH `a - b = &1 % a - b`] THEN
2142   FIRST_ASSUM(SUBST1_TAC o SYM) THEN
2143   REWRITE_TAC[VECTOR_ARITH
2144    `(a + b) % x - (a % y + b % z) = a % (x - y) + b % (x - z)`] THEN
2145   MATCH_MP_TAC REAL_LE_TRANS THEN
2146   EXISTS_TAC `norm(u % (x - y)) + norm(v % (x - z):real^N)` THEN
2147   REWRITE_TAC[NORM_TRIANGLE; NORM_MUL] THEN
2148   MATCH_MP_TAC REAL_CONVEX_BOUND_LE THEN ASM_REWRITE_TAC[REAL_ABS_POS] THEN
2149   ASM_SIMP_TAC[REAL_ARITH
2150    `&0 <= u /\ &0 <= v /\ (u + v = &1) ==> (abs(u) + abs(v) = &1)`]);;
2151
2152 let CONNECTED_CBALL = prove
2153  (`!x:real^N e. connected(cball(x,e))`,
2154   SIMP_TAC[CONVEX_CONNECTED; CONVEX_CBALL]);;
2155
2156 let FRONTIER_OF_CONNECTED_COMPONENT_SUBSET = prove
2157  (`!s c x:real^N. frontier(connected_component s x) SUBSET frontier s`,
2158   REPEAT GEN_TAC THEN REWRITE_TAC[frontier; SUBSET; IN_DIFF] THEN
2159   X_GEN_TAC `y:real^N` THEN REPEAT STRIP_TAC THENL
2160    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
2161      `y IN s ==> s SUBSET t ==> y IN t`)) THEN
2162     MATCH_MP_TAC SUBSET_CLOSURE THEN REWRITE_TAC[CONNECTED_COMPONENT_SUBSET];
2163     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR]) THEN
2164     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
2165     SUBGOAL_THEN `ball(y:real^N,e) SUBSET connected_component s y`
2166     ASSUME_TAC THENL
2167      [MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
2168       ASM_REWRITE_TAC[CONNECTED_BALL; CENTRE_IN_BALL];
2169       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CLOSURE_APPROACHABLE]) THEN
2170       DISCH_THEN(MP_TAC o SPEC `e:real`) THEN
2171       ASM_REWRITE_TAC[ONCE_REWRITE_RULE[DIST_SYM] (GSYM IN_BALL)] THEN
2172       STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN
2173       REWRITE_TAC[IN_INTERIOR] THEN EXISTS_TAC `e:real` THEN
2174       MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`; `y:real^N`]
2175         CONNECTED_COMPONENT_OVERLAP) THEN
2176       MATCH_MP_TAC(TAUT `p /\ (q ==> r) ==> (p <=> q) ==> r`) THEN
2177       ASM_SIMP_TAC[] THEN ASM SET_TAC[]]]);;
2178
2179 let FRONTIER_OF_COMPONENTS_SUBSET = prove
2180  (`!s c:real^N->bool.
2181         c IN components s ==> frontier c SUBSET frontier s`,
2182   SIMP_TAC[components; FORALL_IN_GSPEC;
2183            FRONTIER_OF_CONNECTED_COMPONENT_SUBSET]);;
2184
2185 let FRONTIER_OF_COMPONENTS_CLOSED_COMPLEMENT = prove
2186  (`!s c. closed s /\ c IN components ((:real^N) DIFF s)
2187          ==> frontier c SUBSET s`,
2188   REPEAT STRIP_TAC THEN
2189   FIRST_ASSUM(MP_TAC o MATCH_MP FRONTIER_OF_COMPONENTS_SUBSET) THEN
2190   REWRITE_TAC[FRONTIER_COMPLEMENT] THEN
2191   ASM_MESON_TAC[FRONTIER_SUBSET_EQ; SUBSET_TRANS]);;
2192
2193 (* ------------------------------------------------------------------------- *)
2194 (* A couple of lemmas about components (see Newman IV, 3.3 and 3.4).         *)
2195 (* ------------------------------------------------------------------------- *)
2196
2197 let CONNECTED_UNION_CLOPEN_IN_COMPLEMENT = prove
2198  (`!s t u:real^N->bool.
2199         connected s /\ connected u /\ s SUBSET u /\
2200         open_in (subtopology euclidean (u DIFF s)) t /\
2201         closed_in (subtopology euclidean (u DIFF s)) t
2202         ==> connected (s UNION t)`,
2203   MAP_EVERY X_GEN_TAC
2204    [`c:real^N->bool`; `h:real^N->bool`; `s:real^N->bool`] THEN
2205   STRIP_TAC THEN
2206   REWRITE_TAC[CONNECTED_CLOSED_IN_EQ; NOT_EXISTS_THM] THEN
2207   MATCH_MP_TAC(MESON[]
2208    `!Q. (!x y. P x y <=> P y x) /\
2209         (!x y. P x y ==> Q x \/ Q y) /\
2210         (!x y. P x y /\ Q x ==> F)
2211         ==> (!x y. ~(P x y))`) THEN
2212   EXISTS_TAC `\x:real^N->bool. c SUBSET x` THEN
2213   CONJ_TAC THENL [MESON_TAC[INTER_COMM; UNION_COMM]; ALL_TAC] THEN
2214   REWRITE_TAC[] THEN CONJ_TAC THEN
2215   MAP_EVERY X_GEN_TAC [`h1:real^N->bool`; `h2:real^N->bool`] THENL
2216    [STRIP_TAC THEN UNDISCH_TAC `connected(c:real^N->bool)` THEN
2217     REWRITE_TAC[CONNECTED_CLOSED_IN; NOT_EXISTS_THM] THEN
2218     DISCH_THEN(MP_TAC o
2219       SPECL [`c INTER h1:real^N->bool`; `c INTER h2:real^N->bool`]) THEN
2220     MATCH_MP_TAC(TAUT
2221      `(p /\ q) /\ (~r ==> s) ==> ~(p /\ q /\ r) ==> s`) THEN
2222     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN CONJ_TAC THENL
2223      [UNDISCH_TAC
2224         `closed_in(subtopology euclidean (c UNION h)) (h1:real^N->bool)`;
2225       UNDISCH_TAC
2226         `closed_in(subtopology euclidean (c UNION h)) (h2:real^N->bool)`] THEN
2227     REWRITE_TAC[CLOSED_IN_CLOSED] THEN MATCH_MP_TAC MONO_EXISTS THEN
2228     ASM SET_TAC[];
2229     STRIP_TAC THEN
2230     FIRST_ASSUM(ASSUME_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN
2231     SUBGOAL_THEN `(h2:real^N->bool) SUBSET h` ASSUME_TAC THENL
2232      [ASM SET_TAC[]; ALL_TAC] THEN
2233     UNDISCH_TAC `connected(s:real^N->bool)` THEN
2234     REWRITE_TAC[CONNECTED_CLOPEN] THEN
2235     DISCH_THEN(MP_TAC o SPEC `h2:real^N->bool`) THEN REWRITE_TAC[NOT_IMP] THEN
2236     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
2237     SUBGOAL_THEN `s:real^N->bool = (s DIFF c) UNION (c UNION h)`
2238     SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN CONJ_TAC THENL
2239      [MATCH_MP_TAC OPEN_IN_SUBTOPOLOGY_UNION THEN
2240       MATCH_MP_TAC(TAUT `q /\ (q ==> p) ==> p /\ q`) THEN CONJ_TAC THENL
2241        [REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
2242         CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2243         SUBGOAL_THEN `(c UNION h) DIFF h2:real^N->bool = h1`
2244          (fun th -> ASM_REWRITE_TAC[th]) THEN ASM SET_TAC[];
2245         DISCH_TAC THEN MATCH_MP_TAC OPEN_IN_TRANS THEN
2246         EXISTS_TAC `h:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
2247         UNDISCH_TAC
2248          `open_in(subtopology euclidean (c UNION h)) (h2:real^N->bool)` THEN
2249         REWRITE_TAC[OPEN_IN_OPEN] THEN MATCH_MP_TAC MONO_EXISTS THEN
2250         ASM SET_TAC[]];
2251       MATCH_MP_TAC CLOSED_IN_SUBTOPOLOGY_UNION THEN ASM_REWRITE_TAC[] THEN
2252       MATCH_MP_TAC CLOSED_IN_TRANS THEN EXISTS_TAC `h:real^N->bool` THEN
2253       ASM_REWRITE_TAC[] THEN
2254       UNDISCH_TAC
2255        `closed_in(subtopology euclidean (c UNION h)) (h2:real^N->bool)` THEN
2256       REWRITE_TAC[CLOSED_IN_CLOSED] THEN MATCH_MP_TAC MONO_EXISTS THEN
2257       ASM SET_TAC[]]]);;
2258
2259 let COMPONENT_COMPLEMENT_CONNECTED = prove
2260  (`!s u c:real^N->bool.
2261         connected s /\ connected u /\ s SUBSET u /\ c IN components (u DIFF s)
2262         ==> connected(u DIFF c)`,
2263   MAP_EVERY X_GEN_TAC
2264    [`a:real^N->bool`; `s:real^N->bool`; `c:real^N->bool`] THEN
2265   STRIP_TAC THEN UNDISCH_TAC `connected(a:real^N->bool)` THEN
2266   REWRITE_TAC[CONNECTED_CLOSED_IN_EQ; NOT_EXISTS_THM] THEN
2267   DISCH_TAC THEN MAP_EVERY X_GEN_TAC
2268    [`h3:real^N->bool`; `h4:real^N->bool`] THEN STRIP_TAC THEN
2269   FIRST_X_ASSUM(MP_TAC o SPECL
2270    [`a INTER h3:real^N->bool`; `a INTER h4:real^N->bool`]) THEN
2271   FIRST_ASSUM(MP_TAC o MATCH_MP IN_COMPONENTS_NONEMPTY) THEN
2272   FIRST_ASSUM(MP_TAC o MATCH_MP IN_COMPONENTS_SUBSET) THEN
2273   EVERY_ASSUM(fun th -> try
2274         MP_TAC(CONJUNCT1(GEN_REWRITE_RULE I [closed_in] th))
2275         with Failure _ -> ALL_TAC) THEN
2276   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN REPEAT DISCH_TAC THEN
2277   REPEAT CONJ_TAC THENL
2278    [UNDISCH_TAC `closed_in (subtopology euclidean (s DIFF c))
2279                            (h3:real^N->bool)` THEN
2280     REWRITE_TAC[CLOSED_IN_CLOSED] THEN MATCH_MP_TAC MONO_EXISTS THEN
2281     ASM SET_TAC[];
2282     UNDISCH_TAC `closed_in (subtopology euclidean (s DIFF c))
2283                            (h4:real^N->bool)` THEN
2284     REWRITE_TAC[CLOSED_IN_CLOSED] THEN MATCH_MP_TAC MONO_EXISTS THEN
2285     ASM SET_TAC[];
2286     ASM SET_TAC[];
2287     ASM SET_TAC[];
2288     DISCH_TAC THEN
2289     MP_TAC(ISPECL [`s DIFF a:real^N->bool`; `c UNION h3:real^N->bool`;
2290                `c:real^N->bool`] COMPONENTS_MAXIMAL) THEN
2291     ASM_REWRITE_TAC[NOT_IMP; GSYM CONJ_ASSOC] THEN
2292     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
2293     MATCH_MP_TAC CONNECTED_UNION_CLOPEN_IN_COMPLEMENT THEN
2294     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
2295     REPEAT CONJ_TAC THENL
2296      [ASM_MESON_TAC[IN_COMPONENTS_CONNECTED];
2297       ASM SET_TAC[];
2298       REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
2299       CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2300       SUBGOAL_THEN `s DIFF c DIFF h3:real^N->bool = h4` SUBST1_TAC THEN
2301       ASM SET_TAC[]];
2302     DISCH_TAC THEN
2303     MP_TAC(ISPECL [`s DIFF a:real^N->bool`; `c UNION h4:real^N->bool`;
2304                `c:real^N->bool`] COMPONENTS_MAXIMAL) THEN
2305     ASM_REWRITE_TAC[NOT_IMP; GSYM CONJ_ASSOC] THEN
2306     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
2307     MATCH_MP_TAC CONNECTED_UNION_CLOPEN_IN_COMPLEMENT THEN
2308     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
2309     REPEAT CONJ_TAC THENL
2310      [ASM_MESON_TAC[IN_COMPONENTS_CONNECTED];
2311       ASM SET_TAC[];
2312       REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
2313       CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2314       SUBGOAL_THEN `s DIFF c DIFF h4:real^N->bool = h3` SUBST1_TAC THEN
2315       ASM SET_TAC[]]]);;
2316
2317 (* ------------------------------------------------------------------------- *)
2318 (* Sura-Bura's result about components of closed sets.                       *)
2319 (* ------------------------------------------------------------------------- *)
2320
2321 let SURA_BURA_COMPACT = prove
2322  (`!s c:real^N->bool.
2323         compact s /\ c IN components s
2324         ==> c = INTERS {t | c SUBSET t /\
2325                             open_in (subtopology euclidean s) t /\
2326                             closed_in (subtopology euclidean s) t}`,
2327   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
2328   CONJ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
2329   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [components]) THEN
2330   REWRITE_TAC[IN_ELIM_THM] THEN
2331   DISCH_THEN(X_CHOOSE_THEN `x:real^N` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
2332   DISCH_THEN(fun th -> SUBST1_TAC th THEN ASSUME_TAC(SYM th)) THEN
2333   MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
2334   SUBGOAL_THEN `(x:real^N) IN c` ASSUME_TAC THENL
2335    [ASM_MESON_TAC[CONNECTED_COMPONENT_REFL; IN]; ALL_TAC] THEN
2336   SUBGOAL_THEN `(c:real^N->bool) SUBSET s` ASSUME_TAC THENL
2337    [ASM_MESON_TAC[CONNECTED_COMPONENT_SUBSET]; ALL_TAC] THEN
2338   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN CONJ_TAC THENL
2339    [ASM_REWRITE_TAC[];
2340     MATCH_MP_TAC(SET_RULE `s IN t ==> INTERS t SUBSET s`) THEN
2341     REWRITE_TAC[IN_ELIM_THM; CONNECTED_COMPONENT_SUBSET;
2342                 OPEN_IN_SUBTOPOLOGY_REFL; CLOSED_IN_SUBTOPOLOGY_REFL] THEN
2343     REWRITE_TAC[TOPSPACE_EUCLIDEAN; SUBSET_UNIV]] THEN
2344   W(fun (asl,w) -> ABBREV_TAC(mk_eq(`k:real^N->bool`,rand w))) THEN
2345   SUBGOAL_THEN `closed(k:real^N->bool)` ASSUME_TAC THENL
2346    [EXPAND_TAC "k" THEN MATCH_MP_TAC CLOSED_INTERS THEN
2347     REWRITE_TAC[IN_ELIM_THM] THEN
2348     ASM_MESON_TAC[CLOSED_IN_CLOSED_TRANS; COMPACT_IMP_CLOSED];
2349     ALL_TAC] THEN
2350   REWRITE_TAC[CONNECTED_CLOSED_IN_EQ; NOT_EXISTS_THM] THEN
2351   MAP_EVERY X_GEN_TAC [`k1:real^N->bool`; `k2:real^N->bool`] THEN
2352   STRIP_TAC THEN
2353   MP_TAC(ISPECL [`k1:real^N->bool`; `k2:real^N->bool`] SEPARATION_NORMAL) THEN
2354   ASM_REWRITE_TAC[NOT_EXISTS_THM; NOT_IMP] THEN CONJ_TAC THENL
2355    [ASM_MESON_TAC[CLOSED_IN_CLOSED_TRANS; COMPACT_IMP_CLOSED]; ALL_TAC] THEN
2356   MAP_EVERY X_GEN_TAC [`v1:real^N->bool`; `v2:real^N->bool`] THEN
2357   STRIP_TAC THEN
2358   MP_TAC(ISPECL [`s DIFF (v1 UNION v2):real^N->bool`;
2359                  `{t:real^N->bool | connected_component s x SUBSET t /\
2360                                     open_in (subtopology euclidean s) t /\
2361                                     closed_in (subtopology euclidean s) t}`]
2362         COMPACT_IMP_FIP) THEN
2363   ASM_SIMP_TAC[NOT_IMP; COMPACT_DIFF; OPEN_UNION; IN_ELIM_THM] THEN
2364   REPEAT CONJ_TAC THENL
2365    [ASM_MESON_TAC[CLOSED_IN_CLOSED_TRANS; COMPACT_IMP_CLOSED];
2366     ONCE_REWRITE_TAC[SUBSET] THEN REWRITE_TAC[IN_ELIM_THM];
2367     ASM SET_TAC[]] THEN
2368   X_GEN_TAC `f:(real^N->bool)->bool` THEN REPEAT STRIP_TAC THEN
2369   SUBGOAL_THEN
2370    `?c0:real^N->bool.
2371         c SUBSET c0 /\ c0 SUBSET (v1 UNION v2) /\
2372         open_in (subtopology euclidean s) c0 /\
2373         closed_in (subtopology euclidean s) c0`
2374   STRIP_ASSUME_TAC THENL
2375    [ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
2376      [EXISTS_TAC `s:real^N->bool` THEN
2377       ASM_REWRITE_TAC[TOPSPACE_EUCLIDEAN; SUBSET_UNIV;
2378                 OPEN_IN_SUBTOPOLOGY_REFL; CLOSED_IN_SUBTOPOLOGY_REFL] THEN
2379       UNDISCH_TAC
2380        `(s DIFF (v1 UNION v2)) INTER INTERS f :real^N->bool = {}` THEN
2381       ASM_REWRITE_TAC[INTERS_0; INTER_UNIV] THEN SET_TAC[];
2382       EXISTS_TAC `INTERS f :real^N->bool` THEN REPEAT CONJ_TAC THENL
2383        [ASM SET_TAC[];
2384         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
2385          `(s DIFF u) INTER t = {}
2386           ==> t SUBSET s
2387               ==> t SUBSET u`)) THEN
2388         MATCH_MP_TAC(SET_RULE
2389          `~(f = {}) /\ (!s. s IN f ==> s SUBSET t) ==> INTERS f SUBSET t`) THEN
2390         ASM_MESON_TAC[CLOSED_IN_SUBSET; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY];
2391         MATCH_MP_TAC OPEN_IN_INTERS THEN ASM_SIMP_TAC[];
2392         MATCH_MP_TAC CLOSED_IN_INTERS THEN ASM_SIMP_TAC[]]];
2393     ALL_TAC] THEN
2394   SUBGOAL_THEN `connected(c:real^N->bool)` MP_TAC THENL
2395    [ASM_MESON_TAC[CONNECTED_CONNECTED_COMPONENT]; ALL_TAC] THEN
2396   SUBGOAL_THEN
2397    `closed_in (subtopology euclidean c0) (c0 INTER v1 :real^N->bool) /\
2398     closed_in (subtopology euclidean c0) (c0 INTER v2 :real^N->bool)`
2399   MP_TAC THENL
2400    [CONJ_TAC THEN
2401     MATCH_MP_TAC(MESON[]
2402      `closed_in top (c INTER closure v) /\
2403       c INTER closure v = c INTER v
2404       ==> closed_in top (c INTER v)`) THEN
2405     (CONJ_TAC THENL
2406       [MESON_TAC[CLOSED_IN_CLOSED; CLOSED_CLOSURE]; ALL_TAC]) THEN
2407     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
2408      `c0 SUBSET vv ==> c0 INTER (vv INTER v') = c0 INTER v
2409         ==> c0 INTER v' = c0 INTER v`)) THEN
2410     REWRITE_TAC[ONCE_REWRITE_RULE[INTER_COMM] UNION_OVER_INTER;
2411                 UNION_OVER_INTER] THEN
2412     SIMP_TAC[SET_RULE `s SUBSET t ==> s INTER t = s`; CLOSURE_SUBSET] THENL
2413      [ALL_TAC; ONCE_REWRITE_TAC[UNION_COMM]] THEN
2414     MATCH_MP_TAC(SET_RULE `t = {} ==> s UNION (u INTER t) = s`) THEN
2415     ASM_SIMP_TAC[OPEN_INTER_CLOSURE_EQ_EMPTY] THEN ASM SET_TAC[];
2416     ALL_TAC] THEN
2417   REWRITE_TAC[CLOSED_IN_CLOSED] THEN DISCH_THEN(CONJUNCTS_THEN2
2418    (X_CHOOSE_THEN `u1:real^N->bool` STRIP_ASSUME_TAC)
2419    (X_CHOOSE_THEN `u2:real^N->bool` STRIP_ASSUME_TAC)) THEN
2420   SUBGOAL_THEN `closed(c0:real^N->bool)` ASSUME_TAC THENL
2421    [ASM_MESON_TAC[CLOSED_IN_CLOSED_TRANS; COMPACT_IMP_CLOSED]; ALL_TAC] THEN
2422   REWRITE_TAC[CONNECTED_CLOSED] THEN MAP_EVERY EXISTS_TAC
2423    [`c0 INTER u1:real^N->bool`; `c0 INTER u2:real^N->bool`] THEN
2424   ASM_SIMP_TAC[CLOSED_INTER] THEN
2425   REPLICATE_TAC 2 (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN CONJ_TAC THENL
2426    [STRIP_TAC THEN
2427     SUBGOAL_THEN `c SUBSET (c0 INTER v2 :real^N->bool)` MP_TAC THENL
2428      [ASM SET_TAC[]; ALL_TAC] THEN
2429     SUBGOAL_THEN `k SUBSET (c0 INTER v2 :real^N->bool)` ASSUME_TAC THENL
2430      [ALL_TAC; ASM SET_TAC[]];
2431     STRIP_TAC THEN
2432     SUBGOAL_THEN `c SUBSET (c0 INTER v1 :real^N->bool)` ASSUME_TAC THENL
2433      [ASM SET_TAC[]; ALL_TAC] THEN
2434     SUBGOAL_THEN `k SUBSET (c0 INTER v1 :real^N->bool)` ASSUME_TAC THENL
2435      [ALL_TAC; ASM SET_TAC[]]] THEN
2436   (UNDISCH_THEN `k1 UNION k2 :real^N->bool = k` (K ALL_TAC) THEN
2437    EXPAND_TAC "k" THEN
2438    MATCH_MP_TAC(SET_RULE `s IN t ==> INTERS t SUBSET s`) THEN
2439    REWRITE_TAC[IN_ELIM_THM] THEN REPEAT CONJ_TAC THENL
2440     [ASM SET_TAC[];
2441      MATCH_MP_TAC OPEN_IN_INTER_OPEN THEN ASM_REWRITE_TAC[];
2442      ASM_REWRITE_TAC[] THEN
2443      MATCH_MP_TAC CLOSED_IN_INTER_CLOSED THEN ASM_REWRITE_TAC[]]));;
2444
2445 let SURA_BURA_CLOSED = prove
2446  (`!s c:real^N->bool.
2447         closed s /\ c IN components s /\ compact c
2448         ==> c = INTERS {k | c SUBSET k /\ compact k /\
2449                             open_in (subtopology euclidean s) k}`,
2450   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
2451    [SET_TAC[]; ALL_TAC] THEN
2452   SUBGOAL_THEN
2453    `!u:real^N->bool.
2454         open u /\ c SUBSET u
2455         ==> ?k. c SUBSET k /\ k SUBSET u /\ compact k /\
2456                 open_in (subtopology euclidean s) k`
2457   ASSUME_TAC THENL
2458    [ALL_TAC;
2459     REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN
2460     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
2461     MP_TAC(ISPECL [`{x:real^N}`; `c:real^N->bool`] SEPARATION_NORMAL) THEN
2462     ASM_SIMP_TAC[COMPACT_IMP_CLOSED; CLOSED_SING] THEN
2463     ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN
2464     MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
2465     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `v:real^N->bool`) THEN
2466     ASM_REWRITE_TAC[IN_INTERS; NOT_FORALL_THM; IN_ELIM_THM; NOT_IMP] THEN
2467     MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM SET_TAC[]] THEN
2468   REPEAT STRIP_TAC THEN
2469   SUBGOAL_THEN
2470    `?f. FINITE f /\ c SUBSET UNIONS f /\
2471         (!d:real^N->bool. d IN f ==> open d) /\
2472         (!d:real^N->bool. d IN f ==> bounded d) /\
2473         (!d. d IN f ==> closure d SUBSET u)`
2474   STRIP_ASSUME_TAC THENL
2475    [FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_HEINE_BOREL) THEN
2476     DISCH_THEN(MP_TAC o SPEC
2477      `{ ball(x:real^N,e) | x IN c /\ &0 < e /\ cball(x,e) SUBSET u}`) THEN
2478     ANTS_TAC THENL
2479      [REWRITE_TAC[FORALL_IN_GSPEC; UNIONS_GSPEC; OPEN_BALL] THEN
2480       REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN
2481       DISCH_TAC THEN EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[] THEN
2482       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
2483       DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
2484       ANTS_TAC THENL [ASM SET_TAC[]; MATCH_MP_TAC MONO_EXISTS] THEN
2485       REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[CENTRE_IN_BALL] THEN
2486       ASM SET_TAC[];
2487       MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN STRIP_TAC THEN
2488       ASM_SIMP_TAC[] THEN REPEAT CONJ_TAC THEN
2489       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
2490        (SET_RULE `t SUBSET s ==> (!x. x IN s ==> P x)
2491                     ==> (!x. x IN t ==> P x)`)) THEN
2492       SIMP_TAC[FORALL_IN_GSPEC; OPEN_BALL; BOUNDED_BALL; CLOSURE_BALL]];
2493     ALL_TAC] THEN
2494   ABBREV_TAC `v:real^N->bool = UNIONS f` THEN
2495   SUBGOAL_THEN `bounded(v:real^N->bool)` ASSUME_TAC THENL
2496    [EXPAND_TAC "v" THEN MATCH_MP_TAC BOUNDED_UNIONS THEN
2497     ASM_MESON_TAC[];
2498     ALL_TAC] THEN
2499   SUBGOAL_THEN `compact(closure v:real^N->bool)` ASSUME_TAC THENL
2500    [ASM_REWRITE_TAC[COMPACT_CLOSURE]; ALL_TAC] THEN
2501   SUBGOAL_THEN `(closure v:real^N->bool) SUBSET u` ASSUME_TAC THENL
2502    [EXPAND_TAC "v" THEN ASM_SIMP_TAC[CLOSURE_UNIONS] THEN
2503     ASM_REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC];
2504     ALL_TAC] THEN
2505   SUBGOAL_THEN `open(v:real^N->bool)` ASSUME_TAC THENL
2506    [EXPAND_TAC "v" THEN MATCH_MP_TAC OPEN_UNIONS THEN
2507     ASM_REWRITE_TAC[];
2508     ALL_TAC] THEN
2509   MP_TAC(ISPECL
2510    [`closure v INTER s:real^N->bool`; `c:real^N->bool`]
2511    SURA_BURA_COMPACT) THEN
2512   ANTS_TAC THENL
2513    [ASM_SIMP_TAC[COMPACT_INTER_CLOSED] THEN
2514     REWRITE_TAC[IN_COMPONENTS_MAXIMAL] THEN
2515     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_COMPONENTS_MAXIMAL]) THEN
2516     ASM_MESON_TAC[SUBSET_INTER; SUBSET_TRANS; CLOSURE_SUBSET];
2517     ALL_TAC] THEN
2518   SUBGOAL_THEN
2519    `!t:real^N->bool.
2520         c SUBSET t /\
2521         open_in (subtopology euclidean (closure v INTER s)) t /\
2522         closed_in (subtopology euclidean (closure v INTER s)) t <=>
2523         c SUBSET t /\ t SUBSET (closure v INTER s) /\ compact t /\
2524         open_in (subtopology euclidean (closure v INTER s)) t`
2525    (fun th -> REWRITE_TAC[th])
2526   THENL
2527    [GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THENL
2528      [MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
2529        [ASM_MESON_TAC[CLOSED_IN_SUBSET; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY];
2530         STRIP_TAC THEN REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
2531         CONJ_TAC THENL
2532          [ASM_MESON_TAC[BOUNDED_SUBSET; COMPACT_IMP_BOUNDED;
2533                         COMPACT_INTER_CLOSED];
2534           MATCH_MP_TAC CLOSED_IN_CLOSED_TRANS THEN
2535           EXISTS_TAC `closure v INTER s:real^N->bool` THEN
2536           ASM_MESON_TAC[COMPACT_IMP_CLOSED; CLOSED_INTER]]];
2537       MATCH_MP_TAC CLOSED_CLOSED_IN_TRANS THEN
2538       ASM_SIMP_TAC[COMPACT_IMP_CLOSED; CLOSED_INTER]];
2539     DISCH_THEN(ASSUME_TAC o SYM)] THEN
2540   MP_TAC(ISPECL
2541    [`(closure v INTER s) DIFF v:real^N->bool`;
2542     `{t:real^N->bool | c SUBSET t /\
2543                        t SUBSET (closure v INTER s) /\ compact t /\
2544            open_in (subtopology euclidean (closure v INTER s)) t}`]
2545         COMPACT_IMP_FIP) THEN
2546   ASM_SIMP_TAC[COMPACT_DIFF; COMPACT_INTER_CLOSED] THEN
2547   MATCH_MP_TAC(TAUT
2548    `p /\ r /\ (~q ==> s) ==> (p /\ q ==> ~r) ==> s`) THEN
2549   REWRITE_TAC[IN_ELIM_THM] THEN REPEAT CONJ_TAC THENL
2550    [MESON_TAC[COMPACT_IMP_CLOSED];
2551     ASM SET_TAC[];
2552     REWRITE_TAC[NOT_FORALL_THM; LEFT_IMP_EXISTS_THM]] THEN
2553   X_GEN_TAC `g:(real^N->bool)->bool` THEN
2554   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [SUBSET] THEN
2555   REWRITE_TAC[IN_ELIM_THM; NOT_IMP] THEN
2556   ASM_CASES_TAC `g:(real^N->bool)->bool = {}` THENL
2557    [ASM_REWRITE_TAC[FINITE_EMPTY; NOT_IN_EMPTY; INTERS_0; INTER_UNIV] THEN
2558     REWRITE_TAC[SET_RULE `s DIFF t = {} <=> s SUBSET t`] THEN
2559     STRIP_TAC THEN EXISTS_TAC `closure v INTER s :real^N->bool` THEN
2560     REPEAT CONJ_TAC THENL
2561      [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_COMPONENTS_MAXIMAL]) THEN
2562       MP_TAC(ISPEC `v:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
2563       ASM SET_TAC[];
2564       ASM_SIMP_TAC[COMPACT_INTER_CLOSED];
2565       SUBGOAL_THEN `closure v INTER s :real^N->bool = s INTER v`
2566       SUBST1_TAC THENL
2567        [MP_TAC(ISPEC `v:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
2568         ASM_SIMP_TAC[OPEN_IN_OPEN_INTER]]];
2569     STRIP_TAC THEN
2570     EXISTS_TAC `INTERS g :real^N->bool` THEN REPEAT CONJ_TAC THENL
2571      [ASM SET_TAC[];
2572       MP_TAC(ISPEC `v:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
2573       MATCH_MP_TAC COMPACT_INTERS THEN ASM_MESON_TAC[];
2574       SUBGOAL_THEN
2575        `open_in (subtopology euclidean (closure v INTER s))
2576                 (INTERS g:real^N->bool)`
2577       MP_TAC THENL
2578        [MATCH_MP_TAC OPEN_IN_INTERS THEN ASM_MESON_TAC[]; ALL_TAC] THEN
2579       FIRST_ASSUM(MP_TAC o MATCH_MP (SET_RULE
2580        `(s DIFF t) INTER u = {} ==> u SUBSET s ==> u SUBSET t`)) THEN
2581       ANTS_TAC THENL [ASM SET_TAC[]; DISCH_TAC] THEN
2582       REWRITE_TAC[OPEN_IN_OPEN] THEN
2583       DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
2584       ASM_REWRITE_TAC[] THEN
2585       EXISTS_TAC `(v:real^N->bool) INTER t` THEN ASM_SIMP_TAC[OPEN_INTER] THEN
2586       MP_TAC(ISPEC `v:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[]]]);;
2587
2588 (* ------------------------------------------------------------------------- *)
2589 (* Condition for an open map's image to contain a ball.                      *)
2590 (* ------------------------------------------------------------------------- *)
2591
2592 let BALL_SUBSET_OPEN_MAP_IMAGE = prove
2593  (`!f:real^M->real^N s a r.
2594         bounded s /\ f continuous_on closure s /\ open(IMAGE f (interior s)) /\
2595         a IN s /\ &0 < r /\ (!z. z IN frontier s ==> r <= norm(f z - f a))
2596         ==> ball(f(a),r) SUBSET IMAGE f s`,
2597   REPEAT STRIP_TAC THEN
2598   MP_TAC(ISPECL [`ball((f:real^M->real^N) a,r)`;
2599                  `(:real^N) DIFF IMAGE (f:real^M->real^N) s`]
2600     CONNECTED_INTER_FRONTIER) THEN
2601   REWRITE_TAC[CONNECTED_BALL] THEN MATCH_MP_TAC(SET_RULE
2602    `~(b INTER s = {}) /\ b INTER f = {} ==>
2603     (~(b INTER (UNIV DIFF s) = {}) /\ ~(b DIFF (UNIV DIFF s) = {})
2604      ==> ~(b INTER f = {}))
2605     ==> b SUBSET s`) THEN
2606   REWRITE_TAC[FRONTIER_COMPLEMENT] THEN CONJ_TAC THENL
2607    [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN
2608     EXISTS_TAC `(f:real^M->real^N) a` THEN
2609     ASM_REWRITE_TAC[CENTRE_IN_BALL] THEN ASM SET_TAC[];
2610     REWRITE_TAC[SET_RULE `s INTER t = {} <=> !x. x IN t ==> ~(x IN s)`] THEN
2611     REWRITE_TAC[IN_BALL; REAL_NOT_LT]] THEN
2612   MP_TAC(ISPECL[`frontier(IMAGE (f:real^M->real^N) s)`; `(f:real^M->real^N) a`]
2613     DISTANCE_ATTAINS_INF) THEN
2614   REWRITE_TAC[FRONTIER_CLOSED; FRONTIER_EQ_EMPTY] THEN ANTS_TAC THENL
2615    [SIMP_TAC[DE_MORGAN_THM] THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2616     MATCH_MP_TAC(MESON[NOT_BOUNDED_UNIV] `bounded s ==> ~(s = UNIV)`) THEN
2617     MATCH_MP_TAC BOUNDED_SUBSET THEN
2618     EXISTS_TAC `IMAGE (f:real^M->real^N) (closure s)` THEN
2619     SIMP_TAC[IMAGE_SUBSET; CLOSURE_SUBSET] THEN
2620     MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
2621     MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
2622     ASM_REWRITE_TAC[COMPACT_CLOSURE];
2623     DISCH_THEN(X_CHOOSE_THEN `w:real^N` STRIP_ASSUME_TAC)] THEN
2624   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [frontier]) THEN
2625   REWRITE_TAC[IN_DIFF] THEN
2626   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
2627   REWRITE_TAC[CLOSURE_SEQUENTIAL] THEN
2628   DISCH_THEN(X_CHOOSE_THEN `y:num->real^N`
2629    (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC)) THEN
2630   REWRITE_TAC[IN_IMAGE; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
2631   X_GEN_TAC `z:num->real^M` THEN REWRITE_TAC[FORALL_AND_THM] THEN
2632   ONCE_REWRITE_TAC[GSYM FUN_EQ_THM] THEN
2633   DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
2634   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM COMPACT_CLOSURE]) THEN
2635   REWRITE_TAC[compact] THEN
2636   DISCH_THEN(MP_TAC o SPEC `z:num->real^M`) THEN
2637   ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET; LEFT_IMP_EXISTS_THM] THEN
2638   MAP_EVERY X_GEN_TAC [`y:real^M`; `r:num->num`] THEN STRIP_TAC THEN
2639   SUBGOAL_THEN
2640    `(((\n. (f:real^M->real^N)(z n)) o (r:num->num)) --> w) sequentially`
2641   MP_TAC THENL
2642    [MATCH_MP_TAC LIM_SUBSEQUENCE THEN ASM_REWRITE_TAC[];
2643     ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[GSYM o_ASSOC]] THEN
2644   DISCH_TAC THEN
2645   SUBGOAL_THEN `!n. ((z:num->real^M) o (r:num->num)) n IN s` MP_TAC THENL
2646    [ASM_REWRITE_TAC[o_THM];
2647     UNDISCH_THEN `((\n. (f:real^M->real^N) ((z:num->real^M) n)) --> w)
2648                   sequentially` (K ALL_TAC) THEN
2649     UNDISCH_THEN `!n. (z:num->real^M) n IN s` (K ALL_TAC)] THEN
2650   POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
2651   SPEC_TAC(`(z:num->real^M) o (r:num->num)`, `z:num->real^M`) THEN
2652   REPEAT STRIP_TAC THEN
2653   SUBGOAL_THEN `w = (f:real^M->real^N) y` SUBST_ALL_TAC THENL
2654    [MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
2655     EXISTS_TAC `(f:real^M->real^N) o (z:num->real^M)` THEN
2656     ASM_REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY] THEN
2657     ASM_MESON_TAC[CONTINUOUS_ON_CLOSURE_SEQUENTIALLY];
2658     ALL_TAC] THEN
2659   MATCH_MP_TAC REAL_LE_TRANS THEN
2660   EXISTS_TAC `norm(f y - (f:real^M->real^N) a)` THEN CONJ_TAC THENL
2661    [FIRST_X_ASSUM MATCH_MP_TAC; ASM_MESON_TAC[dist; NORM_SUB]] THEN
2662   ASM_REWRITE_TAC[frontier; IN_DIFF] THEN DISCH_TAC THEN
2663   FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN
2664   REWRITE_TAC[interior; IN_ELIM_THM] THEN
2665   EXISTS_TAC `IMAGE (f:real^M->real^N) (interior s)` THEN
2666   ASM_SIMP_TAC[IMAGE_SUBSET; INTERIOR_SUBSET] THEN ASM SET_TAC[]);;
2667
2668 (* ------------------------------------------------------------------------- *)
2669 (* Arithmetic operations on sets preserve convexity.                         *)
2670 (* ------------------------------------------------------------------------- *)
2671
2672 let CONVEX_SCALING = prove
2673  (`!s c. convex s ==> convex (IMAGE (\x. c % x) s)`,
2674   REWRITE_TAC[convex; IN_IMAGE] THEN REPEAT STRIP_TAC THEN
2675   ASM_REWRITE_TAC[VECTOR_ARITH
2676    `u % c % x + v % c % y = c % (u % x + v % y)`] THEN
2677   ASM_MESON_TAC[]);;
2678
2679 let CONVEX_SCALING_EQ = prove
2680  (`!s c. ~(c = &0) ==> (convex (IMAGE (\x. c % x) s) <=> convex s)`,
2681   REPEAT STRIP_TAC THEN EQ_TAC THEN REWRITE_TAC[CONVEX_SCALING] THEN
2682   DISCH_THEN(MP_TAC o SPEC `inv c` o MATCH_MP CONVEX_SCALING) THEN
2683   ASM_SIMP_TAC[GSYM IMAGE_o; o_DEF; VECTOR_MUL_ASSOC;
2684                REAL_MUL_LINV; VECTOR_MUL_LID; IMAGE_ID]);;
2685
2686 let CONVEX_NEGATIONS = prove
2687  (`!s. convex s ==> convex (IMAGE (--) s)`,
2688   REWRITE_TAC[convex; IN_IMAGE] THEN REPEAT STRIP_TAC THEN
2689   ASM_REWRITE_TAC[VECTOR_ARITH
2690    `u % --x + v % --y = --(u % x + v % y)`] THEN
2691   ASM_MESON_TAC[]);;
2692
2693 let CONVEX_SUMS = prove
2694  (`!s t. convex s /\ convex t ==> convex {x + y | x IN s /\ y IN t}`,
2695   REWRITE_TAC[convex; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
2696   ASM_REWRITE_TAC[VECTOR_ARITH
2697     `u % (a + b) + v % (c + d) = (u % a + v % c) + (u % b + v % d)`] THEN
2698   ASM_MESON_TAC[]);;
2699
2700 let CONVEX_DIFFERENCES = prove
2701  (`!s t. convex s /\ convex t ==> convex {x - y | x IN s /\ y IN t}`,
2702   REWRITE_TAC[convex; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
2703   ASM_REWRITE_TAC[VECTOR_ARITH
2704     `u % (a - b) + v % (c - d) = (u % a + v % c) - (u % b + v % d)`] THEN
2705   ASM_MESON_TAC[]);;
2706
2707 let CONVEX_AFFINITY = prove
2708  (`!s a:real^N c.
2709         convex s ==> convex (IMAGE (\x. a + c % x) s)`,
2710   REPEAT STRIP_TAC THEN
2711   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
2712   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
2713   ASM_SIMP_TAC[IMAGE_o; CONVEX_TRANSLATION; CONVEX_SCALING]);;
2714
2715 let CONVEX_LINEAR_PREIMAGE = prove
2716  (`!f:real^M->real^N.
2717      linear f /\ convex s ==> convex {x | f(x) IN s}`,
2718   REWRITE_TAC[CONVEX_ALT; IN_ELIM_THM] THEN
2719   SIMP_TAC[LINEAR_ADD; LINEAR_CMUL]);;
2720
2721 (* ------------------------------------------------------------------------- *)
2722 (* Convex hull.                                                              *)
2723 (* ------------------------------------------------------------------------- *)
2724
2725 let CONVEX_CONVEX_HULL = prove
2726  (`!s. convex(convex hull s)`,
2727   SIMP_TAC[P_HULL; CONVEX_INTERS]);;
2728
2729 let CONVEX_HULL_EQ = prove
2730  (`!s. (convex hull s = s) <=> convex s`,
2731   SIMP_TAC[HULL_EQ; CONVEX_INTERS]);;
2732
2733 let IS_CONVEX_HULL = prove
2734  (`!s. convex s <=> ?t. s = convex hull t`,
2735   GEN_TAC THEN MATCH_MP_TAC IS_HULL THEN SIMP_TAC[CONVEX_INTERS]);;
2736
2737 let CONVEX_HULL_UNIV = prove
2738  (`convex hull (:real^N) = (:real^N)`,
2739   REWRITE_TAC[CONVEX_HULL_EQ; CONVEX_UNIV]);;
2740
2741 let BOUNDED_CONVEX_HULL = prove
2742  (`!s:real^N->bool. bounded s ==> bounded(convex hull s)`,
2743   GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [bounded] THEN
2744   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
2745   MATCH_MP_TAC BOUNDED_SUBSET THEN EXISTS_TAC `cball(vec 0:real^N,B)` THEN
2746   SIMP_TAC[BOUNDED_CBALL; SUBSET_HULL; CONVEX_CBALL] THEN
2747   ASM_REWRITE_TAC[IN_CBALL; SUBSET; dist; VECTOR_SUB_LZERO; NORM_NEG]);;
2748
2749 let BOUNDED_CONVEX_HULL_EQ = prove
2750  (`!s. bounded(convex hull s) <=> bounded s`,
2751   MESON_TAC[BOUNDED_CONVEX_HULL; HULL_SUBSET; BOUNDED_SUBSET]);;
2752
2753 let FINITE_IMP_BOUNDED_CONVEX_HULL = prove
2754  (`!s. FINITE s ==> bounded(convex hull s)`,
2755   SIMP_TAC[BOUNDED_CONVEX_HULL; FINITE_IMP_BOUNDED]);;
2756
2757 (* ------------------------------------------------------------------------- *)
2758 (* Stepping theorems for convex hulls of finite sets.                        *)
2759 (* ------------------------------------------------------------------------- *)
2760
2761 let CONVEX_HULL_EMPTY = prove
2762  (`convex hull {} = {}`,
2763   MATCH_MP_TAC HULL_UNIQUE THEN
2764   REWRITE_TAC[SUBSET_REFL; CONVEX_EMPTY; EMPTY_SUBSET]);;
2765
2766 let CONVEX_HULL_EQ_EMPTY = prove
2767  (`!s. (convex hull s = {}) <=> (s = {})`,
2768   GEN_TAC THEN EQ_TAC THEN
2769   MESON_TAC[SUBSET_EMPTY; HULL_SUBSET; CONVEX_HULL_EMPTY]);;
2770
2771 let CONVEX_HULL_SING = prove
2772  (`!a. convex hull {a} = {a}`,
2773   REWRITE_TAC[CONVEX_HULL_EQ; CONVEX_SING]);;
2774
2775 let CONVEX_HULL_EQ_SING = prove
2776  (`!s a:real^N. convex hull s = {a} <=> s = {a}`,
2777   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
2778   ASM_REWRITE_TAC[CONVEX_HULL_EMPTY] THEN
2779   EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[CONVEX_HULL_SING] THEN
2780   MATCH_MP_TAC(SET_RULE `~(s = {}) /\ s SUBSET {a} ==> s = {a}`) THEN
2781   ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
2782   REWRITE_TAC[HULL_SUBSET]);;
2783
2784 let CONVEX_HULL_INSERT = prove
2785  (`!s a. ~(s = {})
2786          ==> (convex hull (a INSERT s) =
2787                 {x:real^N | ?u v b. &0 <= u /\ &0 <= v /\ (u + v = &1) /\
2788                                     b IN (convex hull s) /\
2789                                     (x = u % a + v % b)})`,
2790   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
2791    [MATCH_MP_TAC HULL_MINIMAL THEN CONJ_TAC THENL
2792      [REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_INSERT] THEN
2793       X_GEN_TAC `x:real^N` THEN STRIP_TAC THENL
2794        [MAP_EVERY EXISTS_TAC [`&1`; `&0`];
2795         MAP_EVERY EXISTS_TAC [`&0`; `&1`]] THEN
2796       ASM_REWRITE_TAC[VECTOR_MUL_LID; VECTOR_MUL_LZERO] THEN
2797       ASM_REWRITE_TAC[VECTOR_ADD_LID; VECTOR_ADD_RID] THEN
2798       CONV_TAC REAL_RAT_REDUCE_CONV THEN
2799       ASM_MESON_TAC[MEMBER_NOT_EMPTY; HULL_SUBSET; SUBSET];
2800       ALL_TAC];
2801     REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
2802     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2803     MATCH_MP_TAC(REWRITE_RULE[convex] CONVEX_CONVEX_HULL) THEN
2804     ASM_REWRITE_TAC[] THEN
2805     ASM_MESON_TAC[HULL_SUBSET; SUBSET; IN_INSERT; HULL_MONO]] THEN
2806   REWRITE_TAC[convex; IN_ELIM_THM] THEN
2807   REWRITE_TAC[LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
2808   REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
2809   MAP_EVERY X_GEN_TAC
2810    [`x:real^N`; `y:real^N`; `u:real`; `v:real`; `u1:real`; `v1:real`;
2811     `b1:real^N`; `u2:real`; `v2:real`; `b2:real^N`] THEN
2812   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2813   MAP_EVERY EXISTS_TAC [`u * u1 + v * u2`; `u * v1 + v * v2`] THEN
2814   REWRITE_TAC[VECTOR_ARITH
2815    `u % (u1 % a + v1 % b1) + v % (u2 % a + v2 % b2) =
2816     (u * u1 + v * u2) % a + (u * v1) % b1 + (v * v2) % b2`] THEN
2817   ASM_SIMP_TAC[REAL_LE_ADD; REAL_LE_MUL] THEN
2818   ASM_REWRITE_TAC[REAL_MUL_RID; REAL_ARITH
2819    `(u * u1 + v * u2) + (u * v1 + v * v2) =
2820     u * (u1 + v1) + v * (u2 + v2)`] THEN
2821   ASM_CASES_TAC `u * v1 + v * v2 = &0` THENL
2822    [FIRST_X_ASSUM(MP_TAC o MATCH_MP (REAL_ARITH
2823      `(a + b = &0) ==> &0 <= a /\ &0 <= b ==> (a = &0) /\ (b = &0)`)) THEN
2824     ASM_SIMP_TAC[REAL_LE_MUL; REAL_ADD_LID; VECTOR_MUL_LZERO;
2825                  VECTOR_ADD_RID] THEN
2826     ASM_MESON_TAC[];
2827     ALL_TAC] THEN
2828   EXISTS_TAC `(u * v1) / (u * v1 + v * v2) % b1 +
2829               (v * v2) / (u * v1 + v * v2) % b2 :real^N` THEN
2830   ASM_SIMP_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC; REAL_DIV_LMUL] THEN
2831   MATCH_MP_TAC(REWRITE_RULE[convex] CONVEX_CONVEX_HULL) THEN
2832   ASM_SIMP_TAC[REAL_LE_DIV; REAL_LE_MUL; REAL_LE_ADD] THEN
2833   ASM_SIMP_TAC[real_div; GSYM REAL_ADD_RDISTRIB; REAL_MUL_RINV]);;
2834
2835 let CONVEX_HULL_INSERT_ALT = prove
2836  (`!s a:real^N.
2837       convex hull (a INSERT s) =
2838       if s = {} then {a}
2839       else {(&1 - u) % a + u % x | &0 <= u /\ u <= &1 /\ x IN convex hull s}`,
2840   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
2841   ASM_REWRITE_TAC[CONVEX_HULL_SING] THEN
2842   ASM_SIMP_TAC[CONVEX_HULL_INSERT] THEN
2843   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c /\ d <=> b /\ c /\ a /\ d`] THEN
2844   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
2845   REWRITE_TAC[RIGHT_EXISTS_AND_THM; UNWIND_THM2; REAL_SUB_LE;
2846               REAL_ARITH `u + v = &1 <=> u = &1 - v`] THEN
2847   SET_TAC[]);;
2848
2849 (* ------------------------------------------------------------------------- *)
2850 (* Explicit expression for convex hull.                                      *)
2851 (* ------------------------------------------------------------------------- *)
2852
2853 let CONVEX_HULL_INDEXED = prove
2854  (`!s. convex hull s =
2855         {y:real^N | ?k u x. (!i. 1 <= i /\ i <= k ==> &0 <= u i /\ x i IN s) /\
2856                             (sum (1..k) u = &1) /\
2857                             (vsum (1..k) (\i. u i % x i) = y)}`,
2858   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN REPEAT CONJ_TAC THENL
2859    [REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
2860     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
2861     MAP_EVERY EXISTS_TAC [`1`; `\i:num. &1`; `\i:num. x:real^N`] THEN
2862     ASM_SIMP_TAC[FINITE_RULES; IN_SING; SUM_SING; VECTOR_MUL_LID; VSUM_SING;
2863                  REAL_POS; NUMSEG_SING];
2864     ALL_TAC;
2865     REWRITE_TAC[CONVEX_INDEXED; SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
2866     MESON_TAC[]] THEN
2867   REWRITE_TAC[convex; IN_ELIM_THM] THEN
2868   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
2869   REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
2870   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC
2871    [`k1:num`; `u1:num->real`; `x1:num->real^N`;
2872     `k2:num`; `u2:num->real`; `x2:num->real^N`] THEN
2873   STRIP_TAC THEN EXISTS_TAC `k1 + k2:num` THEN
2874   EXISTS_TAC `\i:num. if i <= k1 then u * u1(i) else v * u2(i - k1):real` THEN
2875   EXISTS_TAC `\i:num. if i <= k1 then x1(i) else x2(i - k1):real^N` THEN
2876   ASM_SIMP_TAC[NUMSEG_ADD_SPLIT; ARITH_RULE `1 <= x + 1 /\ x < x + 1`;
2877    IN_NUMSEG; SUM_UNION; VSUM_UNION; FINITE_NUMSEG; DISJOINT_NUMSEG;
2878    ARITH_RULE `k1 + 1 <= i ==> ~(i <= k1)`] THEN
2879   REWRITE_TAC[ONCE_REWRITE_RULE[ADD_SYM] NUMSEG_OFFSET_IMAGE] THEN
2880   ASM_SIMP_TAC[SUM_IMAGE; VSUM_IMAGE; EQ_ADD_LCANCEL; FINITE_NUMSEG] THEN
2881   ASM_SIMP_TAC[o_DEF; ADD_SUB2; SUM_LMUL; VSUM_LMUL; GSYM VECTOR_MUL_ASSOC;
2882                FINITE_NUMSEG; REAL_MUL_RID] THEN
2883   ASM_MESON_TAC[REAL_LE_MUL; ARITH_RULE
2884     `i <= k1 + k2 /\ ~(i <= k1) ==> 1 <= i - k1 /\ i - k1 <= k2`]);;
2885
2886 (* ------------------------------------------------------------------------- *)
2887 (* Another formulation from Lars Schewe.                                     *)
2888 (* ------------------------------------------------------------------------- *)
2889
2890 let CONVEX_HULL_EXPLICIT = prove
2891   (`!p. convex hull p =
2892         {y:real^N | ?s u. FINITE s /\ s SUBSET p /\
2893              (!x. x IN s ==> &0 <= u x) /\
2894              sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
2895    REWRITE_TAC[CONVEX_HULL_INDEXED;EXTENSION;IN_ELIM_THM] THEN
2896    REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL
2897    [MAP_EVERY  EXISTS_TAC [`IMAGE (x':num->real^N) (1..k)`;
2898                            `\v:real^N.sum {i | i IN (1..k) /\ x' i = v} u`]
2899     THEN ASM_SIMP_TAC[FINITE_IMAGE;FINITE_NUMSEG;IN_IMAGE] THEN
2900     REPEAT STRIP_TAC THENL
2901     [REWRITE_TAC[IMAGE;SUBSET;IN_ELIM_THM;IN_NUMSEG] THEN
2902        ASM_MESON_TAC[];
2903      MATCH_MP_TAC SUM_POS_LE THEN
2904        ASM_SIMP_TAC[FINITE_NUMSEG;FINITE_RESTRICT;IN_ELIM_THM;IN_NUMSEG];
2905      ASM_SIMP_TAC[GSYM SUM_IMAGE_GEN;FINITE_IMAGE;FINITE_NUMSEG];
2906      FIRST_X_ASSUM (fun th -> REWRITE_TAC[GSYM th]) THEN
2907      ASM_SIMP_TAC[GSYM VSUM_IMAGE_GEN;FINITE_IMAGE;
2908                   FINITE_NUMSEG;VSUM_VMUL;FINITE_RESTRICT] THEN
2909        MP_TAC (ISPECL [`x':num->real^N`;`\i:num.u i % (x' i):real^N`;`(1..k)`]
2910                       (GSYM VSUM_IMAGE_GEN)) THEN
2911        ASM_SIMP_TAC[FINITE_NUMSEG]];ALL_TAC] THEN
2912    STRIP_ASSUME_TAC (ASM_REWRITE_RULE [ASSUME `FINITE (s:real^N->bool)`]
2913     (ISPEC `s:real^N->bool` FINITE_INDEX_NUMSEG)) THEN
2914    MAP_EVERY EXISTS_TAC [`CARD (s:real^N->bool)`;
2915                          `(u:real^N->real) o (f:num->real^N)`;
2916                          `(f:num->real^N)`] THEN
2917    REPEAT STRIP_TAC THENL
2918    [REWRITE_TAC[o_DEF] THEN FIRST_ASSUM MATCH_MP_TAC THEN
2919       FIRST_ASSUM SUBST1_TAC THEN
2920       REWRITE_TAC[IN_IMAGE;IN_NUMSEG] THEN
2921       ASM_MESON_TAC[];
2922     MATCH_MP_TAC (REWRITE_RULE [SUBSET]
2923       (ASSUME `(s:real^N->bool) SUBSET p`)) THEN
2924       FIRST_ASSUM SUBST1_TAC THEN
2925       REWRITE_TAC[IN_IMAGE;IN_NUMSEG] THEN
2926       ASM_MESON_TAC[];
2927     MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `sum (s:real^N->bool) u` THEN
2928       CONJ_TAC THENL [ALL_TAC;ASM_REWRITE_TAC[]] THEN
2929       GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV)
2930        [ASSUME `(s:real^N->bool) = IMAGE f (1..CARD s)`] THEN
2931       MATCH_MP_TAC (GSYM SUM_IMAGE) THEN
2932       ASM_MESON_TAC[];
2933     REWRITE_TAC[MESON [o_THM;FUN_EQ_THM]
2934      `(\i:num. (u o f) i % f i) = (\v:real^N. u v % v) o f`] THEN
2935       MATCH_MP_TAC EQ_TRANS THEN
2936       EXISTS_TAC `vsum (s:real^N->bool) (\v. u v % v)` THEN
2937       CONJ_TAC THENL [ALL_TAC;ASM_REWRITE_TAC[]] THEN
2938       GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV)
2939        [ASSUME `(s:real^N->bool) = IMAGE f (1..CARD s)`] THEN
2940       MATCH_MP_TAC (GSYM VSUM_IMAGE) THEN
2941       ASM SET_TAC[FINITE_NUMSEG]]);;
2942
2943 let CONVEX_HULL_FINITE = prove
2944  (`!s:real^N->bool.
2945         convex hull s =
2946           {y | ?u. (!x. x IN s ==> &0 <= u x) /\
2947                    sum s u = &1 /\
2948                    vsum s (\x. u x % x) = y}`,
2949   GEN_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
2950   REWRITE_TAC[CONVEX_HULL_EXPLICIT; IN_ELIM_THM] THEN
2951   X_GEN_TAC `x:real^N` THEN EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
2952    [MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `f:real^N->real`] THEN
2953     STRIP_TAC THEN
2954     EXISTS_TAC `\x:real^N. if x IN t then f x else &0` THEN
2955     REWRITE_TAC[COND_RAND; COND_RATOR; VECTOR_MUL_LZERO] THEN
2956     REWRITE_TAC[GSYM SUM_RESTRICT_SET; GSYM VSUM_RESTRICT_SET] THEN
2957     ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
2958     REWRITE_TAC[REAL_LE_REFL; COND_ID];
2959     X_GEN_TAC `f:real^N->real` THEN
2960     ASM_CASES_TAC `s:real^N->bool = {}` THEN
2961     ASM_REWRITE_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH] THEN STRIP_TAC THEN
2962     EXISTS_TAC `support (+) (f:real^N->real) s` THEN
2963     EXISTS_TAC `f:real^N->real` THEN
2964     MP_TAC(ASSUME `sum s (f:real^N->real) = &1`) THEN
2965     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [sum] THEN
2966     REWRITE_TAC[iterate] THEN COND_CASES_TAC THEN
2967     ASM_REWRITE_TAC[NEUTRAL_REAL_ADD; REAL_OF_NUM_EQ; ARITH] THEN
2968     DISCH_THEN(K ALL_TAC) THEN
2969     UNDISCH_TAC `sum s (f:real^N->real) = &1` THEN
2970     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM SUM_SUPPORT] THEN
2971     ASM_CASES_TAC `support (+) (f:real^N->real) s = {}` THEN
2972     ASM_SIMP_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH] THEN
2973     DISCH_TAC THEN REWRITE_TAC[SUPPORT_SUBSET] THEN CONJ_TAC THENL
2974      [ASM_SIMP_TAC[support; IN_ELIM_THM]; ALL_TAC] THEN
2975     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN
2976     CONV_TAC SYM_CONV THEN MATCH_MP_TAC VSUM_SUPERSET THEN
2977     REWRITE_TAC[SUPPORT_SUBSET] THEN
2978     REWRITE_TAC[support; IN_ELIM_THM; NEUTRAL_REAL_ADD] THEN
2979     MESON_TAC[VECTOR_MUL_LZERO]]);;
2980
2981 let CONVEX_HULL_UNION_EXPLICIT = prove
2982  (`!s t:real^N->bool.
2983         convex s /\ convex t
2984         ==> convex hull (s UNION t) =
2985              s UNION t UNION
2986              {(&1 - u) % x + u % y | x IN s /\ y IN t /\ &0 <= u /\ u <= &1}`,
2987   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
2988    [REWRITE_TAC[CONVEX_HULL_EXPLICIT] THEN GEN_REWRITE_TAC I [SUBSET] THEN
2989     REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
2990     MAP_EVERY X_GEN_TAC [`y:real^N`; `u:real^N->bool`; `f:real^N->real`] THEN
2991     REPLICATE_TAC 3 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
2992     SUBST1_TAC(SET_RULE `u:real^N->bool = (u INTER s) UNION (u DIFF s)`) THEN
2993     ASM_SIMP_TAC[SUM_UNION; VSUM_UNION; FINITE_INTER; FINITE_DIFF;
2994                  SET_RULE `DISJOINT (u INTER s) (u DIFF s)`] THEN
2995     ASM_CASES_TAC `sum (u INTER s) (f:real^N->real) = &0` THENL
2996      [SUBGOAL_THEN `!x. x IN (u INTER s) ==> (f:real^N->real) x = &0`
2997       ASSUME_TAC THENL
2998        [ASM_MESON_TAC[SUM_POS_EQ_0; FINITE_INTER; IN_INTER];
2999         ASM_SIMP_TAC[VECTOR_MUL_LZERO; VSUM_0] THEN
3000         REWRITE_TAC[VECTOR_ADD_LID; REAL_ADD_LID] THEN
3001         DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (SUBST1_TAC o SYM)) THEN
3002         REWRITE_TAC[IN_UNION] THEN DISJ2_TAC THEN DISJ1_TAC THEN
3003         FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
3004         ASM_SIMP_TAC[FINITE_DIFF; IN_DIFF] THEN ASM SET_TAC[]];
3005       ALL_TAC] THEN
3006     ASM_CASES_TAC `sum (u DIFF s) (f:real^N->real) = &0` THENL
3007      [SUBGOAL_THEN `!x. x IN (u DIFF s) ==> (f:real^N->real) x = &0`
3008       ASSUME_TAC THENL
3009        [ASM_MESON_TAC[SUM_POS_EQ_0; FINITE_DIFF; IN_DIFF];
3010         ASM_SIMP_TAC[VECTOR_MUL_LZERO; VSUM_0] THEN
3011         REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN
3012         DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (SUBST1_TAC o SYM)) THEN
3013         REWRITE_TAC[IN_UNION] THEN DISJ1_TAC THEN
3014         FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
3015         ASM_SIMP_TAC[FINITE_INTER; IN_INTER] THEN ASM SET_TAC[]];
3016       ALL_TAC] THEN
3017     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (SUBST1_TAC o SYM)) THEN
3018     REWRITE_TAC[IN_UNION; IN_ELIM_THM] THEN DISJ2_TAC THEN DISJ2_TAC THEN
3019     MAP_EVERY EXISTS_TAC
3020      [`vsum(u INTER s) (\v:real^N. (f v / sum(u INTER s) f) % v)`;
3021       `sum(u DIFF s) (f:real^N->real)`;
3022       `vsum(u DIFF s) (\v:real^N. (f v / sum(u DIFF s) f) % v)`] THEN
3023     REPEAT CONJ_TAC THENL
3024      [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
3025       ASM_SIMP_TAC[INTER_SUBSET; FINITE_INTER; SUM_POS_LE; REAL_LE_DIV;
3026                    IN_INTER; real_div; SUM_RMUL; REAL_MUL_RINV];
3027       FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
3028       ASM_SIMP_TAC[SUBSET_DIFF; FINITE_DIFF; SUM_POS_LE; REAL_LE_DIV;
3029                    IN_DIFF; real_div; SUM_RMUL; REAL_MUL_RINV] THEN
3030       ASM SET_TAC[];
3031       ASM_SIMP_TAC[SUM_POS_LE; IN_DIFF; FINITE_DIFF];
3032       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
3033        `a + b = &1 ==> &0 <= a ==> b <= &1`)) THEN
3034       ASM_SIMP_TAC[SUM_POS_LE; IN_INTER; FINITE_INTER];
3035       ASM_SIMP_TAC[GSYM VSUM_LMUL; FINITE_INTER; FINITE_DIFF] THEN
3036       SIMP_TAC[VECTOR_MUL_ASSOC; REAL_ARITH `a * b / c:real = a / c * b`] THEN
3037       FIRST_ASSUM(SUBST1_TAC o MATCH_MP (REAL_ARITH
3038        `a + b = &1 ==> &1 - b = a`)) THEN
3039       ASM_SIMP_TAC[REAL_DIV_REFL; REAL_MUL_LID]];
3040     REWRITE_TAC[GSYM UNION_ASSOC] THEN ONCE_REWRITE_TAC[UNION_SUBSET] THEN
3041     REWRITE_TAC[HULL_SUBSET] THEN REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3042     MAP_EVERY X_GEN_TAC [`x:real^N`; `u:real`; `y:real^N`] THEN STRIP_TAC THEN
3043     MATCH_MP_TAC(REWRITE_RULE[CONVEX_ALT] CONVEX_CONVEX_HULL) THEN
3044     ASM_SIMP_TAC[HULL_INC; IN_UNION]]);;
3045
3046 let CONVEX_HULL_UNION_NONEMPTY_EXPLICIT = prove
3047  (`!s t:real^N->bool.
3048         convex s /\ ~(s = {}) /\ convex t /\ ~(t = {})
3049         ==> convex hull (s UNION t) =
3050              {(&1 - u) % x + u % y | x IN s /\ y IN t /\ &0 <= u /\ u <= &1}`,
3051   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CONVEX_HULL_UNION_EXPLICIT] THEN
3052   SIMP_TAC[SET_RULE `s UNION t UNION u = u <=> s SUBSET u /\ t SUBSET u`] THEN
3053   CONJ_TAC THEN REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `z:real^N` THEN
3054   DISCH_TAC THENL
3055    [MAP_EVERY EXISTS_TAC [`z:real^N`; `&0`] THEN
3056     REWRITE_TAC[REAL_SUB_RZERO; VECTOR_MUL_LID; REAL_POS; VECTOR_MUL_LZERO;
3057                 VECTOR_ADD_RID] THEN
3058     ASM SET_TAC[];
3059     SUBGOAL_THEN `?a:real^N. a IN s` MP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3060     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN DISCH_TAC THEN
3061     MAP_EVERY EXISTS_TAC [`&1`; `z:real^N`] THEN
3062     ASM_REWRITE_TAC[REAL_POS; REAL_LE_REFL] THEN VECTOR_ARITH_TAC]);;
3063
3064 let CONVEX_HULL_UNION_UNIONS = prove
3065  (`!f s:real^N->bool.
3066         convex(UNIONS f) /\ ~(f = {})
3067         ==> convex hull (s UNION UNIONS f) =
3068             UNIONS {convex hull (s UNION t) | t IN f}`,
3069   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3070    [ALL_TAC;
3071     REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC] THEN
3072     REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]] THEN
3073   ASM_CASES_TAC `s:real^N->bool = {}` THENL
3074    [ASM_SIMP_TAC[UNION_EMPTY; HULL_P; UNIONS_SUBSET] THEN
3075     X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
3076     MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `convex hull u:real^N->bool` THEN
3077     REWRITE_TAC[HULL_SUBSET] THEN ASM SET_TAC[];
3078     ALL_TAC] THEN
3079   ASM_CASES_TAC `UNIONS f :real^N->bool = {}` THENL
3080    [ASM_REWRITE_TAC[UNION_EMPTY] THEN
3081     SUBGOAL_THEN `?u:real^N->bool. u IN f` CHOOSE_TAC THENL
3082      [ASM_REWRITE_TAC[MEMBER_NOT_EMPTY]; ALL_TAC] THEN
3083     MATCH_MP_TAC SUBSET_TRANS THEN
3084     EXISTS_TAC `convex hull (s UNION u:real^N->bool)` THEN
3085     ASM_SIMP_TAC[HULL_MONO; SUBSET_UNION] THEN ASM SET_TAC[];
3086     ALL_TAC] THEN
3087   GEN_REWRITE_TAC LAND_CONV [HULL_UNION_LEFT] THEN
3088   ASM_SIMP_TAC[CONVEX_HULL_UNION_NONEMPTY_EXPLICIT; CONVEX_HULL_EQ_EMPTY;
3089                CONVEX_CONVEX_HULL] THEN
3090   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3091   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_UNIONS] THEN
3092   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
3093   MAP_EVERY X_GEN_TAC [`a:real`; `u:real^N->bool`] THEN DISCH_TAC THEN
3094   X_GEN_TAC `y:real^N` THEN REPEAT STRIP_TAC THEN
3095   REWRITE_TAC[IN_UNIONS; EXISTS_IN_GSPEC] THEN
3096   EXISTS_TAC `u:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
3097   MATCH_MP_TAC(REWRITE_RULE[CONVEX_ALT] CONVEX_CONVEX_HULL) THEN
3098   ASM_MESON_TAC[HULL_MONO; IN_UNION; SUBSET; HULL_INC]);;
3099
3100 (* ------------------------------------------------------------------------- *)
3101 (* A stepping theorem for that expansion.                                    *)
3102 (* ------------------------------------------------------------------------- *)
3103
3104 let CONVEX_HULL_FINITE_STEP = prove
3105  (`((?u. (!x. x IN {} ==> &0 <= u x) /\
3106          sum {} u = w /\
3107          vsum {} (\x. u(x) % x) = y) <=> w = &0 /\ y = vec 0) /\
3108    (FINITE(s:real^N->bool)
3109     ==> ((?u. (!x. x IN (a INSERT s) ==> &0 <= u x) /\
3110               sum (a INSERT s) u = w /\
3111               vsum (a INSERT s) (\x. u(x) % x) = y) <=>
3112          ?v. &0 <= v /\
3113              ?u. (!x. x IN s ==> &0 <= u x) /\
3114               sum s u = w - v /\
3115               vsum s (\x. u(x) % x) = y - v % a))`,
3116   MP_TAC(ISPEC `\x:real^N y:real. &0 <= y` AFFINE_HULL_FINITE_STEP_GEN) THEN
3117   SIMP_TAC[REAL_ARITH `&0 <= x / &2 <=> &0 <= x`; REAL_LE_ADD] THEN
3118   REWRITE_TAC[RIGHT_AND_EXISTS_THM]);;
3119
3120 (* ------------------------------------------------------------------------- *)
3121 (* Hence some special cases.                                                 *)
3122 (* ------------------------------------------------------------------------- *)
3123
3124 let CONVEX_HULL_2 = prove
3125  (`!a b. convex hull {a,b} =
3126          {u % a + v % b | &0 <= u /\ &0 <= v /\ u + v = &1}`,
3127   SIMP_TAC[CONVEX_HULL_FINITE; FINITE_INSERT; FINITE_RULES] THEN
3128   SIMP_TAC[CONVEX_HULL_FINITE_STEP; FINITE_INSERT; FINITE_RULES] THEN
3129   REWRITE_TAC[REAL_ARITH `x - y = z:real <=> x = y + z`;
3130               VECTOR_ARITH `x - y = z:real^N <=> x = y + z`] THEN
3131   REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN SET_TAC[]);;
3132
3133 let CONVEX_HULL_2_ALT = prove
3134  (`!a b. convex hull {a,b} = {a + u % (b - a) | &0 <= u /\ u <= &1}`,
3135   ONCE_REWRITE_TAC[SET_RULE `{a,b} = {b,a}`] THEN
3136   REWRITE_TAC[CONVEX_HULL_2; EXTENSION; IN_ELIM_THM] THEN
3137   REWRITE_TAC[REAL_ADD_ASSOC; CONJ_ASSOC] THEN
3138   REWRITE_TAC[TAUT `(a /\ x + y = &1) /\ b <=> x + y = &1 /\ a /\ b`] THEN
3139   REWRITE_TAC[REAL_ARITH `x + y = &1 <=> y = &1 - x`; UNWIND_THM2] THEN
3140   REPEAT GEN_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
3141   BINOP_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]);;
3142
3143 let CONVEX_HULL_3 = prove
3144  (`convex hull {a,b,c} =
3145     { u % a + v % b + w % c |
3146       &0 <= u /\ &0 <= v /\ &0 <= w /\ u + v + w = &1}`,
3147   SIMP_TAC[CONVEX_HULL_FINITE; FINITE_INSERT; FINITE_RULES] THEN
3148   SIMP_TAC[CONVEX_HULL_FINITE_STEP; FINITE_INSERT; FINITE_RULES] THEN
3149   REWRITE_TAC[REAL_ARITH `x - y = z:real <=> x = y + z`;
3150               VECTOR_ARITH `x - y = z:real^N <=> x = y + z`] THEN
3151   REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN SET_TAC[]);;
3152
3153 let CONVEX_HULL_3_ALT = prove
3154  (`!a b c. convex hull {a,b,c} =
3155                 {a + u % (b - a) + v % (c - a) |
3156                    &0 <= u /\ &0 <= v /\ u + v <= &1}`,
3157   ONCE_REWRITE_TAC[SET_RULE `{a,b,c} = {b,c,a}`] THEN
3158   REWRITE_TAC[CONVEX_HULL_3; EXTENSION; IN_ELIM_THM] THEN
3159   REWRITE_TAC[REAL_ADD_ASSOC; CONJ_ASSOC] THEN
3160   REWRITE_TAC[TAUT `(a /\ x + y = &1) /\ b <=> x + y = &1 /\ a /\ b`] THEN
3161   REWRITE_TAC[REAL_ARITH `x + y = &1 <=> y = &1 - x`; UNWIND_THM2] THEN
3162   REPEAT GEN_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
3163   BINOP_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]);;
3164
3165 let CONVEX_HULL_SUMS = prove
3166  (`!s t:real^N->bool.
3167         convex hull {x + y | x IN s /\ y IN t} =
3168         {x + y | x IN convex hull s /\ y IN convex hull t}`,
3169   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3170    [MATCH_MP_TAC HULL_MINIMAL THEN
3171     SIMP_TAC[CONVEX_SUMS; CONVEX_CONVEX_HULL] THEN
3172     REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3173     REWRITE_TAC[IN_ELIM_THM] THEN MESON_TAC[HULL_INC];
3174     REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3175     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
3176     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [CONVEX_HULL_INDEXED] THEN
3177     REWRITE_TAC[IN_ELIM_THM; LEFT_AND_EXISTS_THM] THEN
3178     REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
3179     MAP_EVERY X_GEN_TAC
3180      [`k1:num`; `u1:num->real`; `x1:num->real^N`;
3181       `k2:num`; `u2:num->real`; `x2:num->real^N`] THEN
3182     STRIP_TAC THEN
3183     SUBGOAL_THEN
3184      `x + y:real^N =
3185       vsum(1..k1) (\i. vsum(1..k2) (\j. u1 i % u2 j % (x1 i + x2 j)))`
3186     SUBST1_TAC THENL
3187      [REWRITE_TAC[VECTOR_ADD_LDISTRIB; VSUM_ADD_NUMSEG] THEN
3188       ASM_SIMP_TAC[VSUM_LMUL; VSUM_RMUL; VECTOR_MUL_LID];
3189       REWRITE_TAC[VSUM_LMUL] THEN MATCH_MP_TAC CONVEX_VSUM THEN
3190       ASM_SIMP_TAC[FINITE_NUMSEG; CONVEX_CONVEX_HULL; IN_NUMSEG] THEN
3191       REPEAT STRIP_TAC THEN MATCH_MP_TAC CONVEX_VSUM THEN
3192       ASM_SIMP_TAC[FINITE_NUMSEG; CONVEX_CONVEX_HULL; IN_NUMSEG] THEN
3193       REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_INC THEN ASM SET_TAC[]]]);;
3194
3195 let AFFINE_HULL_PCROSS,CONVEX_HULL_PCROSS = (CONJ_PAIR o prove)
3196  (`(!s:real^M->bool t:real^N->bool.
3197         affine hull (s PCROSS t) =
3198         (affine hull s) PCROSS (affine hull t)) /\
3199    (!s:real^M->bool t:real^N->bool.
3200         convex hull (s PCROSS t) =
3201         (convex hull s) PCROSS (convex hull t))`,
3202   let lemma1 = prove
3203    (`!u v x y:real^M z:real^N.
3204        u + v = &1
3205           ==> pastecart z (u % x + v % y) =
3206               u % pastecart z x + v % pastecart z y /\
3207               pastecart (u % x + v % y) z =
3208               u % pastecart x z + v % pastecart y z`,
3209     REWRITE_TAC[PASTECART_ADD; GSYM PASTECART_CMUL] THEN
3210     SIMP_TAC[GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID])
3211   and lemma2 = prove
3212    (`INTERS {{x | pastecart x y IN u} | y IN t} =
3213      {x | !y. y IN t ==> pastecart x y IN u}`,
3214     REWRITE_TAC[INTERS_GSPEC; EXTENSION; IN_ELIM_THM] THEN SET_TAC[]) in
3215   CONJ_TAC THENL
3216    [REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3217      [MATCH_MP_TAC HULL_MINIMAL THEN
3218       SIMP_TAC[AFFINE_PCROSS; AFFINE_AFFINE_HULL; HULL_SUBSET; PCROSS_MONO];
3219       REWRITE_TAC[SUBSET; FORALL_IN_PCROSS] THEN
3220       REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
3221       MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
3222        [X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
3223         MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
3224          [X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
3225           SUBGOAL_THEN `pastecart (x:real^M) (y:real^N) IN s PCROSS t` MP_TAC
3226           THENL [ASM_REWRITE_TAC[PASTECART_IN_PCROSS]; ALL_TAC] THEN
3227           REWRITE_TAC[HULL_INC];
3228           ALL_TAC];
3229         REWRITE_TAC[GSYM lemma2] THEN MATCH_MP_TAC AFFINE_INTERS THEN
3230         REWRITE_TAC[FORALL_IN_GSPEC]] THEN
3231       SIMP_TAC[affine; IN_ELIM_THM; lemma1;
3232                ONCE_REWRITE_RULE[affine] AFFINE_AFFINE_HULL]];
3233     REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3234      [MATCH_MP_TAC HULL_MINIMAL THEN
3235       SIMP_TAC[CONVEX_PCROSS; CONVEX_CONVEX_HULL; HULL_SUBSET; PCROSS_MONO];
3236       REWRITE_TAC[SUBSET; FORALL_IN_PCROSS] THEN
3237       REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
3238       MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
3239        [X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
3240         MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
3241          [X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
3242           SUBGOAL_THEN `pastecart (x:real^M) (y:real^N) IN s PCROSS t` MP_TAC
3243           THENL [ASM_REWRITE_TAC[PASTECART_IN_PCROSS]; ALL_TAC] THEN
3244           REWRITE_TAC[HULL_INC];
3245           ALL_TAC];
3246         REWRITE_TAC[GSYM lemma2] THEN MATCH_MP_TAC CONVEX_INTERS THEN
3247         REWRITE_TAC[FORALL_IN_GSPEC]] THEN
3248       SIMP_TAC[convex; IN_ELIM_THM; lemma1;
3249                ONCE_REWRITE_RULE[convex] CONVEX_CONVEX_HULL]]]);;
3250
3251 (* ------------------------------------------------------------------------- *)
3252 (* Relations among closure notions and corresponding hulls.                  *)
3253 (* ------------------------------------------------------------------------- *)
3254
3255 let SUBSPACE_IMP_AFFINE = prove
3256  (`!s. subspace s ==> affine s`,
3257   REWRITE_TAC[subspace; affine] THEN MESON_TAC[]);;
3258
3259 let AFFINE_IMP_CONVEX = prove
3260  (`!s. affine s ==> convex s`,
3261   REWRITE_TAC[affine; convex] THEN MESON_TAC[]);;
3262
3263 let SUBSPACE_IMP_CONVEX = prove
3264  (`!s. subspace s ==> convex s`,
3265   MESON_TAC[SUBSPACE_IMP_AFFINE; AFFINE_IMP_CONVEX]);;
3266
3267 let AFFINE_HULL_SUBSET_SPAN = prove
3268  (`!s. (affine hull s) SUBSET (span s)`,
3269   GEN_TAC THEN REWRITE_TAC[span] THEN MATCH_MP_TAC HULL_ANTIMONO THEN
3270   REWRITE_TAC[SUBSET; IN; SUBSPACE_IMP_AFFINE]);;
3271
3272 let CONVEX_HULL_SUBSET_SPAN = prove
3273  (`!s. (convex hull s) SUBSET (span s)`,
3274   GEN_TAC THEN REWRITE_TAC[span] THEN MATCH_MP_TAC HULL_ANTIMONO THEN
3275   REWRITE_TAC[SUBSET; IN; SUBSPACE_IMP_CONVEX]);;
3276
3277 let CONVEX_HULL_SUBSET_AFFINE_HULL = prove
3278  (`!s. (convex hull s) SUBSET (affine hull s)`,
3279   GEN_TAC THEN REWRITE_TAC[span] THEN MATCH_MP_TAC HULL_ANTIMONO THEN
3280   REWRITE_TAC[SUBSET; IN; AFFINE_IMP_CONVEX]);;
3281
3282 let COLLINEAR_CONVEX_HULL_COLLINEAR = prove
3283  (`!s:real^N->bool. collinear(convex hull s) <=> collinear s`,
3284   MESON_TAC[COLLINEAR_SUBSET; HULL_SUBSET; SUBSET_TRANS;
3285             COLLINEAR_AFFINE_HULL_COLLINEAR; CONVEX_HULL_SUBSET_AFFINE_HULL]);;
3286
3287 let AFFINE_SPAN = prove
3288  (`!s. affine(span s)`,
3289   SIMP_TAC[SUBSPACE_IMP_AFFINE; SUBSPACE_SPAN]);;
3290
3291 let CONVEX_SPAN = prove
3292  (`!s. convex(span s)`,
3293   SIMP_TAC[SUBSPACE_IMP_CONVEX; SUBSPACE_SPAN]);;
3294
3295 let AFFINE_EQ_SUBSPACE = prove
3296  (`!s:real^N->bool. vec 0 IN s ==> (affine s <=> subspace s)`,
3297   REPEAT STRIP_TAC THEN EQ_TAC THEN ASM_SIMP_TAC[subspace; affine] THEN
3298   DISCH_TAC THEN MATCH_MP_TAC(TAUT `b /\ (b ==> a) ==> a /\ b`) THEN
3299   CONJ_TAC THENL
3300    [MAP_EVERY X_GEN_TAC [`c:real`; `x:real^N`] THEN STRIP_TAC THEN
3301     SUBST1_TAC(VECTOR_ARITH `c % x:real^N = c % x + (&1 - c) % vec 0`) THEN
3302     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
3303     DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
3304     STRIP_TAC THEN SUBST1_TAC(VECTOR_ARITH
3305      `x + y:real^N = &2 % (&1 / &2 % x + &1 / &2 % y)`) THEN
3306     FIRST_X_ASSUM MATCH_MP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
3307     ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC]);;
3308
3309 let AFFINE_IMP_SUBSPACE = prove
3310  (`!s. affine s /\ vec 0 IN s ==> subspace s`,
3311   SIMP_TAC[GSYM AFFINE_EQ_SUBSPACE]);;
3312
3313 let AFFINE_HULL_EQ_SPAN = prove
3314  (`!s:real^N->bool. (vec 0) IN affine hull s ==> affine hull s = span s`,
3315   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
3316   REWRITE_TAC[AFFINE_HULL_SUBSET_SPAN] THEN
3317   REWRITE_TAC[SUBSET] THEN MATCH_MP_TAC SPAN_INDUCT THEN
3318   ASM_REWRITE_TAC[SUBSET; subspace; IN_ELIM_THM; HULL_INC] THEN
3319   REPEAT STRIP_TAC THENL
3320    [SUBST1_TAC(VECTOR_ARITH
3321      `x + y:real^N = &2 % (&1 / &2 % x + &1 / &2 % y) + --(&1) % vec 0`) THEN
3322     MATCH_MP_TAC(REWRITE_RULE[affine] AFFINE_AFFINE_HULL) THEN
3323     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN
3324     MATCH_MP_TAC(REWRITE_RULE[affine] AFFINE_AFFINE_HULL) THEN
3325     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[];
3326     SUBST1_TAC(VECTOR_ARITH
3327      `c % x:real^N = c % x + (&1 - c) % vec 0`) THEN
3328     MATCH_MP_TAC(REWRITE_RULE[affine] AFFINE_AFFINE_HULL) THEN
3329     ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC]);;
3330
3331 let CLOSED_AFFINE = prove
3332  (`!s:real^N->bool. affine s ==> closed s`,
3333   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
3334   ASM_REWRITE_TAC[CLOSED_EMPTY] THEN
3335   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3336   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
3337   SUBGOAL_THEN `affine (IMAGE (\x:real^N. --a + x) s)
3338                 ==> closed (IMAGE (\x:real^N. --a + x) s)`
3339   MP_TAC THENL
3340    [DISCH_THEN(fun th -> MATCH_MP_TAC CLOSED_SUBSPACE THEN MP_TAC th) THEN
3341     MATCH_MP_TAC EQ_IMP THEN MATCH_MP_TAC AFFINE_EQ_SUBSPACE THEN
3342     REWRITE_TAC[IN_IMAGE] THEN EXISTS_TAC `a:real^N` THEN
3343     ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC;
3344     REWRITE_TAC[AFFINE_TRANSLATION_EQ; CLOSED_TRANSLATION_EQ]]);;
3345
3346 let CLOSED_AFFINE_HULL = prove
3347  (`!s. closed(affine hull s)`,
3348   SIMP_TAC[CLOSED_AFFINE; AFFINE_AFFINE_HULL]);;
3349
3350 let CLOSURE_SUBSET_AFFINE_HULL = prove
3351  (`!s. closure s SUBSET affine hull s`,
3352   GEN_TAC THEN MATCH_MP_TAC CLOSURE_MINIMAL THEN
3353   REWRITE_TAC[CLOSED_AFFINE_HULL; HULL_SUBSET]);;
3354
3355 let AFFINE_HULL_CLOSURE = prove
3356  (`!s:real^N->bool. affine hull (closure s) = affine hull s`,
3357   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN
3358   REWRITE_TAC[CLOSURE_SUBSET_AFFINE_HULL; AFFINE_AFFINE_HULL] THEN
3359   X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
3360   MATCH_MP_TAC HULL_MINIMAL THEN ASM_REWRITE_TAC[] THEN
3361   ASM_MESON_TAC[CLOSURE_SUBSET; SUBSET]);;
3362
3363 let AFFINE_HULL_EQ_SPAN_EQ = prove
3364  (`!s:real^N->bool. (affine hull s = span s) <=> (vec 0) IN affine hull s`,
3365   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[SPAN_0; AFFINE_HULL_EQ_SPAN]);;
3366
3367 let AFFINE_DEPENDENT_IMP_DEPENDENT = prove
3368  (`!s. affine_dependent s ==> dependent s`,
3369   REWRITE_TAC[affine_dependent; dependent] THEN
3370   MESON_TAC[SUBSET; AFFINE_HULL_SUBSET_SPAN]);;
3371
3372 let DEPENDENT_AFFINE_DEPENDENT_CASES = prove
3373  (`!s:real^N->bool.
3374         dependent s <=> affine_dependent s \/ (vec 0) IN affine hull s`,
3375   REWRITE_TAC[DEPENDENT_EXPLICIT; AFFINE_DEPENDENT_EXPLICIT;
3376               AFFINE_HULL_EXPLICIT_ALT; IN_ELIM_THM] THEN
3377   GEN_TAC THEN ONCE_REWRITE_TAC[OR_EXISTS_THM] THEN
3378   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
3379   X_GEN_TAC `t:real^N->bool` THEN
3380   ASM_CASES_TAC `FINITE(t:real^N->bool)` THEN ASM_REWRITE_TAC[] THEN
3381   EQ_TAC THEN DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN
3382    (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC))
3383   THENL
3384    [ASM_CASES_TAC `sum t (u:real^N->real) = &0` THENL
3385      [ASM_MESON_TAC[]; ALL_TAC] THEN
3386     DISJ2_TAC THEN EXISTS_TAC `\v:real^N. inv(sum t u) * u v` THEN
3387     ASM_SIMP_TAC[SUM_LMUL; VSUM_LMUL; GSYM VECTOR_MUL_ASSOC] THEN
3388     ASM_SIMP_TAC[VECTOR_MUL_RZERO; REAL_MUL_LINV];
3389     EXISTS_TAC `u:real^N->real` THEN ASM_MESON_TAC[];
3390     EXISTS_TAC `u:real^N->real` THEN
3391     ASM_REWRITE_TAC[SET_RULE
3392      `(?v. v IN t /\ ~p v) <=> ~(!v. v IN t ==> p v)`] THEN
3393     DISCH_TAC THEN
3394     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
3395      `x = &1 ==> x = &0 ==> F`)) THEN
3396     ASM_MESON_TAC[SUM_EQ_0]]);;
3397
3398 let DEPENDENT_IMP_AFFINE_DEPENDENT = prove
3399  (`!a:real^N s. dependent {x - a | x IN s} /\ ~(a IN s)
3400                 ==> affine_dependent(a INSERT s)`,
3401   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
3402   REWRITE_TAC[DEPENDENT_EXPLICIT; AFFINE_DEPENDENT_EXPLICIT] THEN
3403   REWRITE_TAC[SIMPLE_IMAGE; CONJ_ASSOC; FINITE_SUBSET_IMAGE] THEN
3404   REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN REWRITE_TAC[GSYM CONJ_ASSOC] THEN
3405   GEN_REWRITE_TAC LAND_CONV [SWAP_EXISTS_THM] THEN
3406   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [SWAP_EXISTS_THM] THEN
3407   REWRITE_TAC[TAUT `a /\ x = IMAGE f s /\ b <=> x = IMAGE f s /\ a /\ b`] THEN
3408   REWRITE_TAC[UNWIND_THM2; EXISTS_IN_IMAGE] THEN
3409   DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` (X_CHOOSE_THEN `t:real^N->bool`
3410     STRIP_ASSUME_TAC)) THEN
3411   FIRST_X_ASSUM(MP_TAC o check (is_eq o concl)) THEN
3412   ASM_SIMP_TAC[VSUM_IMAGE; VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
3413   ASM_SIMP_TAC[o_DEF; VECTOR_SUB_LDISTRIB; VSUM_SUB; VSUM_RMUL] THEN
3414   STRIP_TAC THEN
3415   MAP_EVERY EXISTS_TAC
3416    [`(a:real^N) INSERT t`;
3417     `\x. if x = a then --sum t (\x. u (x - a))
3418          else (u:real^N->real) (x - a)`] THEN
3419   ASM_REWRITE_TAC[FINITE_INSERT; SUBSET_REFL] THEN
3420   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES] THEN
3421   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3422   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THENL [ASM SET_TAC[]; ALL_TAC] THEN
3423   REPEAT CONJ_TAC THENL
3424    [MATCH_MP_TAC(REAL_ARITH `x = y ==> --x + y = &0`) THEN
3425     MATCH_MP_TAC SUM_EQ THEN ASM_MESON_TAC[];
3426     EXISTS_TAC `x:real^N` THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3427     COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[];
3428     MATCH_MP_TAC(VECTOR_ARITH
3429      `!s. s - t % a = vec 0 /\ s = u ==> --t % a + u = vec 0`) THEN
3430     EXISTS_TAC `vsum t (\x:real^N. u(x - a) % x)` THEN
3431     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC VSUM_EQ THEN
3432     REPEAT STRIP_TAC THEN REWRITE_TAC[] THEN COND_CASES_TAC THEN
3433     ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]]);;
3434
3435 let AFFINE_DEPENDENT_BIGGERSET = prove
3436  (`!s:real^N->bool.
3437         (FINITE s ==> CARD s >= dimindex(:N) + 2) ==> affine_dependent s`,
3438   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
3439   ASM_SIMP_TAC[CARD_CLAUSES; ARITH_RULE `~(0 >= n + 2)`; FINITE_RULES] THEN
3440   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3441   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
3442   FIRST_ASSUM(SUBST1_TAC o MATCH_MP (SET_RULE
3443    `x IN s ==> s = x INSERT (s DELETE x)`)) THEN
3444   SIMP_TAC[FINITE_INSERT; CARD_CLAUSES; IN_DELETE] THEN
3445   REWRITE_TAC[ARITH_RULE `SUC x >= n + 2 <=> x > n`] THEN DISCH_TAC THEN
3446   MATCH_MP_TAC DEPENDENT_IMP_AFFINE_DEPENDENT THEN
3447   REWRITE_TAC[IN_DELETE] THEN MATCH_MP_TAC DEPENDENT_BIGGERSET THEN
3448   REWRITE_TAC[SET_RULE `{x - a:real^N | x | x IN s /\ ~(x = a)} =
3449                         IMAGE (\x. x - a) (s DELETE a)`] THEN
3450   ASM_SIMP_TAC[FINITE_IMAGE_INJ_EQ;
3451                VECTOR_ARITH `x - a = y - a <=> x:real^N = y`;
3452                CARD_IMAGE_INJ]);;
3453
3454 let AFFINE_DEPENDENT_BIGGERSET_GENERAL = prove
3455  (`!s:real^N->bool. (FINITE s ==> CARD s >= dim s + 2) ==> affine_dependent s`,
3456   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
3457   ASM_SIMP_TAC[CARD_CLAUSES; ARITH_RULE `~(0 >= n + 2)`; FINITE_RULES] THEN
3458   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3459   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
3460   FIRST_ASSUM(SUBST1_TAC o MATCH_MP (SET_RULE
3461    `x IN s ==> s = x INSERT (s DELETE x)`)) THEN
3462   SIMP_TAC[FINITE_INSERT; CARD_CLAUSES; IN_DELETE] THEN
3463   REWRITE_TAC[ARITH_RULE `SUC x >= n + 2 <=> x > n`] THEN DISCH_TAC THEN
3464   MATCH_MP_TAC DEPENDENT_IMP_AFFINE_DEPENDENT THEN
3465   REWRITE_TAC[IN_DELETE] THEN
3466   MATCH_MP_TAC DEPENDENT_BIGGERSET_GENERAL THEN
3467   REWRITE_TAC[SET_RULE `{x - a:real^N | x | x IN s /\ ~(x = a)} =
3468                         IMAGE (\x. x - a) (s DELETE a)`] THEN
3469   ASM_SIMP_TAC[FINITE_IMAGE_INJ_EQ; FINITE_DELETE;
3470                VECTOR_ARITH `x - a = y - a <=> x:real^N = y`;
3471                CARD_IMAGE_INJ] THEN
3472   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o check(is_imp o concl)) THEN
3473   ASM_REWRITE_TAC[FINITE_DELETE] THEN
3474   MATCH_MP_TAC(ARITH_RULE `c:num <= b ==> (a > b ==> a > c)`) THEN
3475   MATCH_MP_TAC SUBSET_LE_DIM THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
3476   SIMP_TAC[SPAN_SUB; SPAN_SUPERSET; IN_INSERT]);;
3477
3478 let AFFINE_INDEPENDENT_IMP_FINITE = prove
3479  (`!s:real^N->bool. ~(affine_dependent s) ==> FINITE s`,
3480   MESON_TAC[AFFINE_DEPENDENT_BIGGERSET]);;
3481
3482 let AFFINE_INDEPENDENT_CARD_LE = prove
3483  (`!s:real^N->bool. ~(affine_dependent s) ==> CARD s <= dimindex(:N) + 1`,
3484   REWRITE_TAC[ARITH_RULE `s <= n + 1 <=> ~(n + 2 <= s)`; CONTRAPOS_THM] THEN
3485   REPEAT STRIP_TAC THEN MATCH_MP_TAC AFFINE_DEPENDENT_BIGGERSET THEN
3486   ASM_REWRITE_TAC[GE]);;
3487
3488 let AFFINE_INDEPENDENT_CONVEX_AFFINE_HULL = prove
3489  (`!s t:real^N->bool.
3490         ~affine_dependent s /\ t SUBSET s
3491         ==> convex hull t = affine hull t INTER convex hull s`,
3492   REPEAT STRIP_TAC THEN
3493   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3494   SUBGOAL_THEN `FINITE(t:real^N->bool)` ASSUME_TAC THENL
3495    [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
3496   MATCH_MP_TAC(SET_RULE
3497    `ct SUBSET a /\ ct SUBSET cs /\ a INTER cs SUBSET ct
3498     ==> ct = a INTER cs`) THEN
3499   ASM_SIMP_TAC[HULL_MONO; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
3500   REWRITE_TAC[SUBSET; IN_INTER; CONVEX_HULL_FINITE; AFFINE_HULL_FINITE] THEN
3501   X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
3502   DISCH_THEN(CONJUNCTS_THEN2
3503    (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC)
3504    (X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC)) THEN
3505   EXISTS_TAC `u:real^N->real` THEN ASM_REWRITE_TAC[] THEN
3506   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
3507   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
3508     [AFFINE_DEPENDENT_EXPLICIT]) THEN
3509   REWRITE_TAC[NOT_EXISTS_THM] THEN
3510   DISCH_THEN(MP_TAC o SPECL [`s:real^N->bool`;
3511         `\x:real^N. if x IN t then v x - u x:real else v x`]) THEN
3512   ASM_REWRITE_TAC[SUBSET_REFL] THEN REWRITE_TAC[MESON[]
3513    `(if p then a else b) % x = if p then a % x else b % x`] THEN
3514   ASM_SIMP_TAC[VSUM_CASES; SUM_CASES; SET_RULE
3515    `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
3516   ASM_SIMP_TAC[GSYM DIFF; SUM_DIFF; VSUM_DIFF; VECTOR_SUB_RDISTRIB;
3517                SUM_SUB; VSUM_SUB] THEN
3518   REWRITE_TAC[REAL_ARITH `a - b + b - a = &0`; NOT_EXISTS_THM;
3519               VECTOR_ARITH `a - b + b - a:real^N = vec 0`] THEN
3520   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
3521   ASM_REWRITE_TAC[REAL_SUB_0] THEN ASM SET_TAC[]);;
3522
3523 let DISJOINT_AFFINE_HULL = prove
3524  (`!s t u:real^N->bool.
3525         ~affine_dependent s /\ t SUBSET s /\ u SUBSET s /\ DISJOINT t u
3526         ==> DISJOINT (affine hull t) (affine hull u)`,
3527   REPEAT STRIP_TAC THEN
3528   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3529   SUBGOAL_THEN `FINITE(t:real^N->bool) /\ FINITE (u:real^N->bool)` ASSUME_TAC
3530   THENL [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
3531   REWRITE_TAC[IN_DISJOINT; AFFINE_HULL_FINITE; IN_ELIM_THM] THEN
3532   DISCH_THEN(X_CHOOSE_THEN `y:real^N` MP_TAC) THEN
3533   DISCH_THEN(CONJUNCTS_THEN2
3534    (X_CHOOSE_THEN `a:real^N->real` STRIP_ASSUME_TAC)
3535    (X_CHOOSE_THEN `b:real^N->real` STRIP_ASSUME_TAC)) THEN
3536   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
3537     [AFFINE_DEPENDENT_EXPLICIT]) THEN
3538   REWRITE_TAC[NOT_EXISTS_THM] THEN
3539   MAP_EVERY EXISTS_TAC
3540    [`s:real^N->bool`;
3541     `\x:real^N. if x IN t then a x else if x IN u then --(b x) else &0`] THEN
3542   ASM_REWRITE_TAC[SUBSET_REFL] THEN REWRITE_TAC[MESON[]
3543    `(if p then a else b) % x = if p then a % x else b % x`] THEN
3544   ASM_SIMP_TAC[SUM_CASES; SUBSET_REFL; VSUM_CASES; GSYM DIFF; SUM_DIFF;
3545       VSUM_DIFF; SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
3546   ASM_SIMP_TAC[SUM_0; VSUM_0; VECTOR_MUL_LZERO; SUM_NEG; VSUM_NEG;
3547     VECTOR_MUL_LNEG; SET_RULE `DISJOINT t u ==> ~(x IN t /\ x IN u)`] THEN
3548   REWRITE_TAC[EMPTY_GSPEC; SUM_CLAUSES; VSUM_CLAUSES] THEN
3549   CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
3550   CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
3551   UNDISCH_TAC `sum t (a:real^N->real) = &1` THEN
3552   ASM_CASES_TAC `!x:real^N. x IN t ==> a x = &0` THEN
3553   ASM_SIMP_TAC[SUM_EQ_0; REAL_OF_NUM_EQ; ARITH_EQ] THEN DISCH_TAC THEN
3554   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_FORALL_THM]) THEN
3555   MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[]);;
3556
3557 let AFFINE_INDEPENDENT_SPAN_EQ = prove
3558  (`!s. ~(affine_dependent s) /\ CARD s = dimindex(:N) + 1
3559        ==> affine hull s = (:real^N)`,
3560   MATCH_MP_TAC SET_PROVE_CASES THEN
3561   REWRITE_TAC[CARD_CLAUSES; ARITH_RULE `~(0 = n + 1)`] THEN
3562   SIMP_TAC[IMP_CONJ; AFFINE_INDEPENDENT_IMP_FINITE; MESON[HAS_SIZE]
3563    `FINITE s ==> (CARD s = n <=> s HAS_SIZE n)`] THEN
3564   X_GEN_TAC `orig:real^N` THEN GEOM_ORIGIN_TAC `orig:real^N` THEN
3565   SIMP_TAC[AFFINE_HULL_EQ_SPAN; IN_INSERT; SPAN_INSERT_0; HULL_INC] THEN
3566   SIMP_TAC[HAS_SIZE; CARD_CLAUSES; FINITE_INSERT; IMP_CONJ] THEN
3567   REWRITE_TAC[ARITH_RULE `SUC n = m + 1 <=> n = m`; GSYM UNIV_SUBSET] THEN
3568   REPEAT STRIP_TAC THEN MATCH_MP_TAC CARD_GE_DIM_INDEPENDENT THEN
3569   ASM_REWRITE_TAC[DIM_UNIV; SUBSET_UNIV; LE_REFL; independent] THEN
3570   UNDISCH_TAC `~affine_dependent((vec 0:real^N) INSERT s)` THEN
3571   REWRITE_TAC[CONTRAPOS_THM] THEN DISCH_TAC THEN
3572   MATCH_MP_TAC DEPENDENT_IMP_AFFINE_DEPENDENT THEN
3573   ASM_REWRITE_TAC[VECTOR_SUB_RZERO; SET_RULE `{x | x IN s} = s`]);;
3574
3575 let AFFINE_INDEPENDENT_SPAN_GT = prove
3576  (`!s:real^N->bool.
3577         ~(affine_dependent s) /\ dimindex(:N) < CARD s
3578         ==> affine hull s = (:real^N)`,
3579   REPEAT STRIP_TAC THEN MATCH_MP_TAC AFFINE_INDEPENDENT_SPAN_EQ THEN
3580   ASM_REWRITE_TAC[] THEN
3581   MP_TAC(SPEC `s:real^N->bool` AFFINE_DEPENDENT_BIGGERSET) THEN
3582   ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE] THEN ASM_ARITH_TAC);;
3583
3584 let EMPTY_INTERIOR_AFFINE_HULL = prove
3585  (`!s:real^N->bool.
3586         FINITE s /\ CARD(s) <= dimindex(:N)
3587         ==> interior(affine hull s) = {}`,
3588   REWRITE_TAC[IMP_CONJ] THEN  MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
3589   REWRITE_TAC[AFFINE_HULL_EMPTY; INTERIOR_EMPTY] THEN
3590   SUBGOAL_THEN
3591    `!x s:real^N->bool n.
3592         ~(x IN s) /\ (x INSERT s) HAS_SIZE n /\ n <= dimindex(:N)
3593         ==> interior(affine hull(x INSERT s)) = {}`
3594    (fun th -> MESON_TAC[th; HAS_SIZE; FINITE_INSERT]) THEN
3595   X_GEN_TAC `orig:real^N` THEN GEOM_ORIGIN_TAC `orig:real^N` THEN
3596   SIMP_TAC[AFFINE_HULL_EQ_SPAN; IN_INSERT; SPAN_INSERT_0; HULL_INC] THEN
3597   REWRITE_TAC[HAS_SIZE; FINITE_INSERT; IMP_CONJ] THEN
3598   SIMP_TAC[CARD_CLAUSES] THEN
3599   REPEAT STRIP_TAC THEN MATCH_MP_TAC EMPTY_INTERIOR_LOWDIM THEN
3600   MATCH_MP_TAC LET_TRANS THEN EXISTS_TAC `CARD(s:real^N->bool)` THEN
3601   ASM_SIMP_TAC[DIM_LE_CARD; DIM_SPAN] THEN ASM_ARITH_TAC);;
3602
3603 let EMPTY_INTERIOR_CONVEX_HULL = prove
3604  (`!s:real^N->bool.
3605         FINITE s /\ CARD(s) <= dimindex(:N)
3606         ==> interior(convex hull s) = {}`,
3607   REPEAT STRIP_TAC THEN
3608   MATCH_MP_TAC(SET_RULE `!t. s SUBSET t /\ t = {} ==> s = {}`) THEN
3609   EXISTS_TAC `interior(affine hull s):real^N->bool` THEN
3610   SIMP_TAC[SUBSET_INTERIOR; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
3611   ASM_SIMP_TAC[EMPTY_INTERIOR_AFFINE_HULL]);;
3612
3613 let AFFINE_DEPENDENT_CHOOSE = prove
3614  (`!s a:real^N.
3615        ~(affine_dependent s)
3616        ==> (affine_dependent(a INSERT s) <=> ~(a IN s) /\ a IN affine hull s)`,
3617   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(a:real^N) IN s` THEN
3618   ASM_SIMP_TAC[SET_RULE `a IN s ==> a INSERT s = s`] THEN
3619   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3620   EQ_TAC THENL
3621    [UNDISCH_TAC `~(affine_dependent(s:real^N->bool))` THEN
3622     ASM_SIMP_TAC[AFFINE_DEPENDENT_EXPLICIT_FINITE; AFFINE_HULL_FINITE;
3623                  FINITE_INSERT; IN_ELIM_THM; SUM_CLAUSES; VSUM_CLAUSES] THEN
3624     DISCH_TAC THEN REWRITE_TAC[EXISTS_IN_INSERT] THEN
3625     DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` MP_TAC) THEN
3626     ASM_CASES_TAC `(u:real^N->real) a = &0` THEN ASM_REWRITE_TAC[] THENL
3627      [REWRITE_TAC[REAL_ADD_LID; VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN
3628       DISCH_TAC THEN
3629       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
3630       DISCH_THEN(MP_TAC o SPEC `u:real^N->real`) THEN ASM_REWRITE_TAC[];
3631       ONCE_REWRITE_TAC[REAL_ARITH `ua + sa = &0 <=> sa = --ua`;
3632                    VECTOR_ARITH `va + sa:real^N = vec 0 <=> sa = --va`] THEN
3633       STRIP_TAC THEN EXISTS_TAC `(\x. --(inv(u a)) * u x):real^N->real` THEN
3634       ASM_SIMP_TAC[SUM_LMUL; GSYM VECTOR_MUL_ASSOC; VSUM_LMUL] THEN
3635       ASM_REWRITE_TAC[VECTOR_MUL_ASSOC; GSYM VECTOR_MUL_LNEG] THEN
3636       REWRITE_TAC[REAL_ARITH `--a * --b:real = a * b`] THEN
3637       ASM_SIMP_TAC[REAL_MUL_LINV; VECTOR_MUL_LID]];
3638     DISCH_TAC THEN REWRITE_TAC[affine_dependent] THEN
3639     EXISTS_TAC `a:real^N` THEN
3640     ASM_SIMP_TAC[IN_INSERT; SET_RULE
3641      `~(a IN s) ==> (a INSERT s) DELETE a = s`]]);;
3642
3643 let AFFINE_INDEPENDENT_INSERT = prove
3644  (`!s a:real^N.
3645         ~(affine_dependent s) /\ ~(a IN affine hull s)
3646         ==> ~(affine_dependent(a INSERT s))`,
3647   SIMP_TAC[AFFINE_DEPENDENT_CHOOSE]);;
3648
3649 let AFFINE_HULL_EXPLICIT_UNIQUE = prove
3650  (`!s:real^N->bool u u'.
3651       ~(affine_dependent s) /\
3652       sum s u = &1 /\ sum s u' = &1 /\
3653       vsum s (\x. u x % x) = vsum s (\x. u' x % x)
3654       ==> !x. x IN s ==> u x = u' x`,
3655   REPEAT GEN_TAC THEN STRIP_TAC THEN
3656   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3657   FIRST_ASSUM(MP_TAC o MATCH_MP AFFINE_DEPENDENT_EXPLICIT_FINITE) THEN
3658   ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
3659   DISCH_THEN(MP_TAC o SPEC `(\x. u x - u' x):real^N->real`) THEN
3660   ASM_SIMP_TAC[VSUM_SUB; SUM_SUB; REAL_SUB_REFL; VECTOR_SUB_RDISTRIB;
3661                VECTOR_SUB_REFL; VECTOR_SUB_EQ; REAL_SUB_0] THEN
3662   MESON_TAC[]);;
3663
3664 let INDEPENDENT_IMP_AFFINE_DEPENDENT_0 = prove
3665  (`!s. independent s ==> ~(affine_dependent(vec 0 INSERT s))`,
3666   REWRITE_TAC[independent; DEPENDENT_AFFINE_DEPENDENT_CASES] THEN
3667   SIMP_TAC[DE_MORGAN_THM; AFFINE_INDEPENDENT_INSERT]);;
3668
3669 let AFFINE_INDEPENDENT_STDBASIS = prove
3670  (`~(affine_dependent
3671       ((vec 0:real^N) INSERT {basis i | 1 <= i /\ i <= dimindex (:N)}))`,
3672   SIMP_TAC[INDEPENDENT_IMP_AFFINE_DEPENDENT_0; INDEPENDENT_STDBASIS]);;
3673
3674 (* ------------------------------------------------------------------------- *)
3675 (* Nonempty affine sets are translates of (unique) subspaces.                *)
3676 (* ------------------------------------------------------------------------- *)
3677
3678 let AFFINE_TRANSLATION_SUBSPACE = prove
3679  (`!t:real^N->bool.
3680         affine t /\ ~(t = {}) <=> ?a s. subspace s /\ t = IMAGE (\x. a + x) s`,
3681   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
3682   ASM_SIMP_TAC[SUBSPACE_IMP_NONEMPTY; IMAGE_EQ_EMPTY;
3683                AFFINE_TRANSLATION; SUBSPACE_IMP_AFFINE] THEN
3684   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3685   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
3686   ONCE_REWRITE_TAC[TRANSLATION_GALOIS] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
3687   REWRITE_TAC[UNWIND_THM2] THEN MATCH_MP_TAC AFFINE_IMP_SUBSPACE THEN
3688   ASM_REWRITE_TAC[AFFINE_TRANSLATION_EQ; IN_IMAGE] THEN
3689   EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC);;
3690
3691 let AFFINE_TRANSLATION_UNIQUE_SUBSPACE = prove
3692  (`!t:real^N->bool.
3693         affine t /\ ~(t = {}) <=>
3694         ?!s. ?a. subspace s /\ t = IMAGE (\x. a + x) s`,
3695   GEN_TAC THEN REWRITE_TAC[AFFINE_TRANSLATION_SUBSPACE] THEN
3696   MATCH_MP_TAC(MESON[]
3697    `(!a a' s s'. P s a /\ P s' a' ==> s = s')
3698     ==> ((?a s. P s a) <=> (?!s. ?a. P s a))`) THEN
3699   REPEAT GEN_TAC THEN
3700   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC)) THEN
3701   DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
3702   ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[TRANSLATION_GALOIS] THEN
3703   DISCH_THEN SUBST1_TAC THEN CONV_TAC SYM_CONV THEN
3704   REWRITE_TAC[GSYM IMAGE_o; o_DEF; VECTOR_ADD_ASSOC] THEN
3705   MATCH_MP_TAC SUBSPACE_TRANSLATION_SELF THEN ASM_REWRITE_TAC[] THEN
3706   ONCE_REWRITE_TAC[VECTOR_ARITH `--a' + a:real^N = --(a' - a)`] THEN
3707   MATCH_MP_TAC SUBSPACE_NEG THEN ASM_REWRITE_TAC[] THEN
3708   UNDISCH_TAC `t = IMAGE (\x:real^N. a' + x) s'` THEN
3709   DISCH_THEN(MP_TAC o AP_TERM `\s. (a':real^N) IN s`) THEN
3710   REWRITE_TAC[IN_IMAGE; VECTOR_ARITH `a:real^N = a + x <=> x = vec 0`] THEN
3711   ASM_SIMP_TAC[UNWIND_THM2; SUBSPACE_0] THEN
3712   REWRITE_TAC[IN_IMAGE; VECTOR_ARITH `a':real^N = a + x <=> x = a' - a`] THEN
3713   REWRITE_TAC[UNWIND_THM2]);;
3714
3715 let AFFINE_TRANSLATION_SUBSPACE_EXPLICIT = prove
3716  (`!t:real^N->bool a.
3717         affine t /\ a IN t
3718         ==> subspace {x - a | x IN t} /\
3719             t = IMAGE (\x. a + x) {x - a | x IN t}`,
3720   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[AFFINE_DIFFS_SUBSPACE] THEN
3721   ASM_REWRITE_TAC[SIMPLE_IMAGE; GSYM IMAGE_o] THEN
3722   REWRITE_TAC[o_DEF; VECTOR_SUB_ADD2; IMAGE_ID]);;
3723
3724 (* ------------------------------------------------------------------------- *)
3725 (* If we take a slice out of a set, we can do it perpendicularly,            *)
3726 (* with the normal vector to the slice parallel to the affine hull.          *)
3727 (* ------------------------------------------------------------------------- *)
3728
3729 let AFFINE_PARALLEL_SLICE = prove
3730   (`!s a:real^N b.
3731        affine s
3732        ==> s INTER {x | a dot x <= b} = {} \/ s SUBSET {x | a dot x <= b} \/
3733            ?a' b'. ~(a' = vec 0) /\
3734
3735                    s INTER {x | a' dot x <= b'} = s INTER {x | a dot x <= b} /\
3736                    s INTER {x | a' dot x = b'} = s INTER {x | a dot x = b} /\
3737                    !w. w IN s ==> (w + a') IN s`,
3738    REPEAT STRIP_TAC THEN
3739    ASM_CASES_TAC `s INTER {x:real^N | a dot x = b} = {}` THENL
3740     [MATCH_MP_TAC(TAUT `~(~p /\ ~q) ==> p \/ q \/ r`) THEN
3741      REPEAT STRIP_TAC THEN SUBGOAL_THEN
3742       `?u v:real^N. u IN s /\ v IN s /\
3743                     a dot u <= b /\ ~(a dot v <= b)`
3744      STRIP_ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3745      SUBGOAL_THEN `(a:real^N) dot u < b` ASSUME_TAC THENL
3746       [ASM_REWRITE_TAC[REAL_LT_LE] THEN ASM SET_TAC[]; ALL_TAC] THEN
3747      RULE_ASSUM_TAC(REWRITE_RULE[REAL_NOT_LE]) THEN
3748      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
3749      REWRITE_TAC[NOT_IN_EMPTY; IN_INTER; NOT_FORALL_THM; IN_ELIM_THM] THEN
3750      EXISTS_TAC
3751       `u + (b - a dot u) / (a dot v - a dot u) % (v - u):real^N` THEN
3752      ASM_SIMP_TAC[IN_AFFINE_ADD_MUL_DIFF] THEN
3753      REWRITE_TAC[DOT_RADD; DOT_RMUL; DOT_RSUB] THEN
3754      REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD;
3755      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3756      DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
3757      REWRITE_TAC[IN_INTER; IN_ELIM_THM] THEN POP_ASSUM MP_TAC THEN
3758      GEN_GEOM_ORIGIN_TAC `z:real^N` ["a"; "a'"; "b'"; "w"] THEN
3759      REPEAT STRIP_TAC THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
3760      REWRITE_TAC[VECTOR_ADD_RID; FORALL_IN_IMAGE] THEN
3761      REWRITE_TAC[DOT_RADD; REAL_ARITH `a + x <= a <=> x <= &0`] THEN
3762      SUBGOAL_THEN `subspace(s:real^N->bool) /\ span s = s`
3763      STRIP_ASSUME_TAC THENL
3764       [ASM_MESON_TAC[AFFINE_IMP_SUBSPACE; SPAN_EQ_SELF]; ALL_TAC] THEN
3765      MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`]
3766            ORTHOGONAL_SUBSPACE_DECOMP_EXISTS) THEN
3767      ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; orthogonal] THEN
3768      MAP_EVERY X_GEN_TAC [`a':real^N`; `a'':real^N`] THEN
3769      ASM_CASES_TAC `a':real^N = vec 0` THENL
3770       [ASM_REWRITE_TAC[VECTOR_ADD_LID] THEN
3771        ASM_CASES_TAC `a'':real^N = a` THEN ASM_REWRITE_TAC[] THEN
3772        SIMP_TAC[SUBSET; IN_ELIM_THM; REAL_LE_REFL];
3773        ALL_TAC] THEN
3774      STRIP_TAC THEN REPEAT DISJ2_TAC THEN
3775      EXISTS_TAC `a':real^N` THEN ASM_REWRITE_TAC[] THEN
3776      EXISTS_TAC `(a':real^N) dot z` THEN
3777      REPEAT(CONJ_TAC THENL
3778       [MATCH_MP_TAC(SET_RULE
3779         `(!x. x IN s ==> (p x <=> q x))
3780          ==> s INTER {x | p x} = s INTER {x | q x}`) THEN
3781        ASM_SIMP_TAC[DOT_LADD] THEN REAL_ARITH_TAC;
3782        ALL_TAC]) THEN
3783      X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_IMAGE] THEN
3784      EXISTS_TAC `x + a':real^N` THEN
3785      ASM_SIMP_TAC[SUBSPACE_ADD; VECTOR_ADD_ASSOC]]);;
3786
3787 (* ------------------------------------------------------------------------- *)
3788 (* Affine dimension.                                                         *)
3789 (* ------------------------------------------------------------------------- *)
3790
3791 let MAXIMAL_AFFINE_INDEPENDENT_SUBSET = prove
3792  (`!s b:real^N->bool.
3793         b SUBSET s /\ ~(affine_dependent b) /\
3794         (!b'. b SUBSET b' /\ b' SUBSET s /\ ~(affine_dependent b') ==> b' = b)
3795         ==> s SUBSET (affine hull b)`,
3796   REPEAT STRIP_TAC THEN
3797   MATCH_MP_TAC(SET_RULE `(!a. a IN t /\ ~(a IN s) ==> F) ==> t SUBSET s`) THEN
3798   X_GEN_TAC `a:real^N` THEN STRIP_TAC THEN
3799   FIRST_X_ASSUM(MP_TAC o SPEC `(a:real^N) INSERT b`) THEN
3800   FIRST_ASSUM(MP_TAC o MATCH_MP
3801    (ONCE_REWRITE_RULE[GSYM CONTRAPOS_THM] HULL_INC)) THEN
3802   ASM_SIMP_TAC[AFFINE_INDEPENDENT_INSERT; INSERT_SUBSET] THEN
3803   ASM SET_TAC[]);;
3804
3805 let MAXIMAL_AFFINE_INDEPENDENT_SUBSET_AFFINE = prove
3806  (`!s b:real^N->bool.
3807         affine s /\ b SUBSET s /\ ~(affine_dependent b) /\
3808         (!b'. b SUBSET b' /\ b' SUBSET s /\ ~(affine_dependent b') ==> b' = b)
3809         ==> affine hull b = s`,
3810   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3811    [ASM_MESON_TAC[HULL_MONO; HULL_P];
3812     ASM_MESON_TAC[MAXIMAL_AFFINE_INDEPENDENT_SUBSET]]);;
3813
3814 let EXTEND_TO_AFFINE_BASIS = prove
3815  (`!s u:real^N->bool.
3816         ~(affine_dependent s) /\ s SUBSET u
3817         ==> ?t. ~(affine_dependent t) /\ s SUBSET t /\ t SUBSET u /\
3818                 affine hull t = affine hull u`,
3819   REPEAT STRIP_TAC THEN
3820   MP_TAC(SPEC `\n. ?t:real^N->bool. ~(affine_dependent t) /\ s SUBSET t /\
3821                                     t SUBSET u /\ CARD t = n`
3822    num_MAX) THEN
3823   DISCH_THEN(MP_TAC o fst o EQ_IMP_RULE) THEN REWRITE_TAC[] THEN ANTS_TAC THENL
3824    [ASM_MESON_TAC[SUBSET_REFL; AFFINE_INDEPENDENT_CARD_LE]; ALL_TAC] THEN
3825   DISCH_THEN(X_CHOOSE_THEN `n:num` (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC)) THEN
3826   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
3827   ASM_REWRITE_TAC[] THEN
3828   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3829    [ASM_MESON_TAC[HULL_MONO; HULL_P]; ALL_TAC] THEN
3830   MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[AFFINE_AFFINE_HULL] THEN
3831   MATCH_MP_TAC MAXIMAL_AFFINE_INDEPENDENT_SUBSET THEN ASM_REWRITE_TAC[] THEN
3832   X_GEN_TAC `c:real^N->bool` THEN STRIP_TAC THEN
3833   FIRST_X_ASSUM(MP_TAC o SPEC `CARD(c:real^N->bool)`) THEN
3834   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
3835   DISCH_THEN(MP_TAC o SPEC `c:real^N->bool`) THEN
3836   ANTS_TAC THENL [ASM SET_TAC[]; DISCH_TAC] THEN
3837   CONV_TAC SYM_CONV THEN MATCH_MP_TAC CARD_SUBSET_LE THEN
3838   ASM_MESON_TAC[AFFINE_INDEPENDENT_IMP_FINITE]);;
3839
3840 let AFFINE_BASIS_EXISTS = prove
3841  (`!s:real^N->bool.
3842       ?b. ~(affine_dependent b) /\ b SUBSET s /\
3843           affine hull b = affine hull s`,
3844   GEN_TAC THEN
3845   MP_TAC(ISPECL [`{}:real^N->bool`; `s:real^N->bool`]
3846     EXTEND_TO_AFFINE_BASIS) THEN
3847   REWRITE_TAC[AFFINE_INDEPENDENT_EMPTY; EMPTY_SUBSET]);;
3848
3849 let aff_dim = new_definition
3850   `aff_dim s =
3851         @d:int. ?b. affine hull b = affine hull s /\ ~(affine_dependent b) /\
3852                     &(CARD b) = d + &1`;;
3853
3854 let AFF_DIM = prove
3855  (`!s. ?b. affine hull b = affine hull s /\
3856            ~(affine_dependent b) /\
3857            aff_dim s = &(CARD b) - &1`,
3858   GEN_TAC THEN
3859   REWRITE_TAC[aff_dim; INT_ARITH `y:int = x + &1 <=> x = y - &1`] THEN
3860   CONV_TAC SELECT_CONV THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
3861   REWRITE_TAC[RIGHT_EXISTS_AND_THM; EXISTS_REFL] THEN
3862   MESON_TAC[AFFINE_BASIS_EXISTS]);;
3863
3864 let AFF_DIM_EMPTY = prove
3865  (`aff_dim {} = -- &1`,
3866   REWRITE_TAC[aff_dim; AFFINE_HULL_EMPTY; AFFINE_HULL_EQ_EMPTY] THEN
3867   REWRITE_TAC[UNWIND_THM2; AFFINE_INDEPENDENT_EMPTY; CARD_CLAUSES] THEN
3868   REWRITE_TAC[INT_ARITH `&0 = d + &1 <=> d:int = -- &1`; SELECT_REFL]);;
3869
3870 let AFF_DIM_AFFINE_HULL = prove
3871  (`!s. aff_dim(affine hull s) = aff_dim s`,
3872   REWRITE_TAC[aff_dim; HULL_HULL]);;
3873
3874 let AFF_DIM_TRANSLATION_EQ = prove
3875  (`!a:real^N s. aff_dim (IMAGE (\x. a + x) s) = aff_dim s`,
3876   REWRITE_TAC[aff_dim] THEN GEOM_TRANSLATE_TAC[] THEN
3877   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> ~(a /\ b ==> ~c)`] THEN
3878   SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE; CARD_IMAGE_INJ;
3879            VECTOR_ARITH `a + x:real^N = a + y <=> x = y`]);;
3880
3881 add_translation_invariants [AFF_DIM_TRANSLATION_EQ];;
3882
3883 let AFFINE_INDEPENDENT_CARD_DIM_DIFFS = prove
3884  (`!s a:real^N.
3885         ~affine_dependent s /\ a IN s
3886         ==> CARD s = dim {x - a | x IN s} + 1`,
3887   REPEAT STRIP_TAC THEN
3888   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3889   MATCH_MP_TAC(ARITH_RULE `~(s = 0) /\ v = s - 1 ==> s = v + 1`) THEN
3890   ASM_SIMP_TAC[CARD_EQ_0] THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3891   MATCH_MP_TAC DIM_UNIQUE THEN
3892   EXISTS_TAC `{b - a:real^N |b| b IN (s DELETE a)}` THEN REPEAT CONJ_TAC THENL
3893    [SET_TAC[];
3894     REWRITE_TAC[SIMPLE_IMAGE; SUBSET; FORALL_IN_IMAGE] THEN
3895     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN ASM_CASES_TAC `x:real^N = a` THENL
3896      [ASM_REWRITE_TAC[VECTOR_SUB_REFL; SPAN_0];
3897       MATCH_MP_TAC SPAN_SUPERSET THEN ASM SET_TAC[]];
3898     UNDISCH_TAC `~affine_dependent(s:real^N->bool)` THEN
3899     REWRITE_TAC[independent; CONTRAPOS_THM] THEN DISCH_TAC THEN
3900     SUBGOAL_THEN `s = (a:real^N) INSERT (s DELETE a)` SUBST1_TAC THENL
3901      [ASM SET_TAC[]; ALL_TAC] THEN
3902     MATCH_MP_TAC DEPENDENT_IMP_AFFINE_DEPENDENT THEN
3903     ASM_REWRITE_TAC[IN_DELETE];
3904     REWRITE_TAC[SIMPLE_IMAGE] THEN MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN
3905     SIMP_TAC[VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
3906     ASM_SIMP_TAC[HAS_SIZE; FINITE_DELETE; CARD_DELETE]]);;
3907
3908 let AFF_DIM_DIM_AFFINE_DIFFS = prove
3909  (`!a:real^N s. affine s /\ a IN s ==> aff_dim s = &(dim {x - a | x IN s})`,
3910   REPEAT STRIP_TAC THEN
3911   MP_TAC(ISPEC `s:real^N->bool` AFF_DIM) THEN
3912   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` MP_TAC) THEN
3913   ASM_CASES_TAC `b:real^N->bool = {}` THENL
3914    [ASM_MESON_TAC[AFFINE_HULL_EQ_EMPTY; NOT_IN_EMPTY]; ALL_TAC] THEN
3915   STRIP_TAC THEN
3916   ASM_REWRITE_TAC[INT_EQ_SUB_RADD; INT_OF_NUM_ADD; INT_OF_NUM_EQ] THEN
3917   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3918   DISCH_THEN(X_CHOOSE_TAC `c:real^N`) THEN MATCH_MP_TAC EQ_TRANS THEN
3919   EXISTS_TAC `dim {x - c:real^N | x IN b} + 1` THEN CONJ_TAC THENL
3920    [MATCH_MP_TAC AFFINE_INDEPENDENT_CARD_DIM_DIFFS THEN ASM_REWRITE_TAC[];
3921     ALL_TAC] THEN
3922   MATCH_MP_TAC EQ_TRANS THEN
3923   EXISTS_TAC `dim {x - c:real^N | x IN affine hull b} + 1` THEN CONJ_TAC THENL
3924    [ASM_SIMP_TAC[DIFFS_AFFINE_HULL_SPAN; DIM_SPAN]; ALL_TAC] THEN
3925   ASM_REWRITE_TAC[] THEN AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
3926   SUBGOAL_THEN `affine hull s:real^N->bool = s` SUBST1_TAC THENL
3927    [ASM_MESON_TAC[AFFINE_HULL_EQ]; ALL_TAC] THEN
3928   SUBGOAL_THEN `(c:real^N) IN s` ASSUME_TAC THENL
3929    [ASM_MESON_TAC[AFFINE_HULL_EQ; HULL_INC]; ALL_TAC] THEN
3930   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3931   REWRITE_TAC[IN_ELIM_THM] THEN
3932   SIMP_TAC[VECTOR_ARITH `x - c:real^N = y - a <=> y = x + &1 % (a - c)`] THEN
3933   ASM_MESON_TAC[IN_AFFINE_ADD_MUL_DIFF]);;
3934
3935 let AFF_DIM_DIM_0 = prove
3936  (`!s:real^N->bool. vec 0 IN affine hull s ==> aff_dim s = &(dim s)`,
3937   REPEAT STRIP_TAC THEN
3938   MP_TAC(ISPECL [`vec 0:real^N`; `affine hull s:real^N->bool`]
3939     AFF_DIM_DIM_AFFINE_DIFFS) THEN
3940   ASM_REWRITE_TAC[AFFINE_AFFINE_HULL; VECTOR_SUB_RZERO] THEN
3941   REWRITE_TAC[AFF_DIM_AFFINE_HULL; SET_RULE `{x | x IN s} = s`] THEN
3942   ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; DIM_SPAN]);;
3943
3944 let AFF_DIM_DIM_SUBSPACE = prove
3945  (`!s:real^N->bool. subspace s ==> aff_dim s = &(dim s)`,
3946   MESON_TAC[AFF_DIM_DIM_0; SUBSPACE_0; HULL_INC]);;
3947
3948 let AFF_DIM_LINEAR_IMAGE_LE = prove
3949  (`!f:real^M->real^N s. linear f ==> aff_dim(IMAGE f s) <= aff_dim s`,
3950   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
3951   ASM_SIMP_TAC[AFFINE_HULL_LINEAR_IMAGE] THEN
3952   MP_TAC(ISPEC `s:real^M->bool` AFFINE_AFFINE_HULL) THEN
3953   SPEC_TAC(`affine hull s:real^M->bool`,`s:real^M->bool`) THEN
3954   GEN_TAC THEN DISCH_TAC THEN ASM_CASES_TAC `s:real^M->bool = {}` THEN
3955   ASM_REWRITE_TAC[IMAGE_CLAUSES; AFF_DIM_EMPTY; INT_LE_REFL] THEN
3956   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3957   DISCH_THEN(X_CHOOSE_TAC `a:real^M`) THEN
3958   SUBGOAL_THEN `dim {x - f(a) |x| x IN IMAGE (f:real^M->real^N) s} <=
3959                 dim {x - a | x IN s}`
3960   MP_TAC THENL
3961    [REWRITE_TAC[SET_RULE `{f x | x IN IMAGE g s} = {f (g x) | x IN s}`] THEN
3962     ASM_SIMP_TAC[GSYM LINEAR_SUB] THEN REWRITE_TAC[SIMPLE_IMAGE] THEN
3963     ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[IMAGE_o] THEN
3964     MATCH_MP_TAC DIM_LINEAR_IMAGE_LE THEN ASM_REWRITE_TAC[];
3965     MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[GSYM INT_OF_NUM_LE] THEN
3966     BINOP_TAC THEN CONV_TAC SYM_CONV THEN
3967     MATCH_MP_TAC AFF_DIM_DIM_AFFINE_DIFFS THEN
3968     ASM_SIMP_TAC[AFFINE_LINEAR_IMAGE; FUN_IN_IMAGE]]);;
3969
3970 let AFF_DIM_INJECTIVE_LINEAR_IMAGE = prove
3971  (`!f:real^M->real^N s.
3972         linear f /\ (!x y. f x = f y ==> x = y)
3973         ==> aff_dim(IMAGE f s) = aff_dim s`,
3974   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM INT_LE_ANTISYM] THEN
3975   CONJ_TAC THENL [ASM_MESON_TAC[AFF_DIM_LINEAR_IMAGE_LE]; ALL_TAC] THEN
3976   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_LEFT_INVERSE) THEN
3977   ASM_REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN
3978   DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^M` STRIP_ASSUME_TAC) THEN
3979   MATCH_MP_TAC INT_LE_TRANS THEN EXISTS_TAC
3980    `aff_dim(IMAGE (g:real^N->real^M) (IMAGE (f:real^M->real^N) s))` THEN
3981   CONJ_TAC THENL
3982    [ASM_REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID; INT_LE_REFL];
3983     MATCH_MP_TAC AFF_DIM_LINEAR_IMAGE_LE THEN ASM_REWRITE_TAC[]]);;
3984
3985 add_linear_invariants [AFF_DIM_INJECTIVE_LINEAR_IMAGE];;
3986
3987 let AFF_DIM_AFFINE_INDEPENDENT = prove
3988  (`!b:real^N->bool.
3989         ~(affine_dependent b) ==> aff_dim b = &(CARD b) - &1`,
3990   GEN_TAC THEN ASM_CASES_TAC `b:real^N->bool = {}` THENL
3991    [ASM_REWRITE_TAC[CARD_CLAUSES; AFF_DIM_EMPTY] THEN INT_ARITH_TAC;
3992     ALL_TAC] THEN
3993   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3994   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN DISCH_TAC THEN
3995   MP_TAC(ISPECL [`b:real^N->bool`; `a:real^N`]
3996    AFFINE_INDEPENDENT_CARD_DIM_DIFFS) THEN
3997   ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST1_TAC THEN
3998   REWRITE_TAC[GSYM INT_OF_NUM_ADD; INT_ARITH `(a + b) - b:int = a`] THEN
3999   MP_TAC(ISPECL [`a:real^N`; `affine hull b:real^N->bool`]
4000    AFF_DIM_DIM_AFFINE_DIFFS) THEN
4001   ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC; AFF_DIM_AFFINE_HULL] THEN
4002   DISCH_THEN(K ALL_TAC) THEN AP_TERM_TAC THEN
4003   ASM_MESON_TAC[DIFFS_AFFINE_HULL_SPAN; DIM_SPAN]);;
4004
4005 let AFF_DIM_UNIQUE = prove
4006  (`!s b:real^N->bool.
4007         affine hull b = affine hull s /\ ~(affine_dependent b)
4008         ==> aff_dim s = &(CARD b) - &1`,
4009   MESON_TAC[AFF_DIM_AFFINE_HULL; AFF_DIM_AFFINE_INDEPENDENT]);;
4010
4011 let AFF_DIM_SING = prove
4012  (`!a:real^N. aff_dim {a} = &0`,
4013   GEN_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
4014   EXISTS_TAC `&(CARD {a:real^N}) - &1:int` THEN CONJ_TAC THENL
4015    [MATCH_MP_TAC AFF_DIM_AFFINE_INDEPENDENT THEN
4016     REWRITE_TAC[AFFINE_INDEPENDENT_1];
4017     SIMP_TAC[CARD_CLAUSES; FINITE_RULES; ARITH; NOT_IN_EMPTY; INT_SUB_REFL]]);;
4018
4019 let AFF_DIM_LE_CARD = prove
4020  (`!s:real^N->bool. FINITE s ==> aff_dim s <= &(CARD s) - &1`,
4021   MATCH_MP_TAC SET_PROVE_CASES THEN
4022   SIMP_TAC[AFF_DIM_EMPTY; CARD_CLAUSES] THEN CONV_TAC INT_REDUCE_CONV THEN
4023   GEOM_ORIGIN_TAC `a:real^N` THEN
4024   SIMP_TAC[AFF_DIM_DIM_0; IN_INSERT; HULL_INC] THEN
4025   SIMP_TAC[CARD_IMAGE_INJ; VECTOR_ARITH `a + x:real^N = a + y <=> x = y`] THEN
4026   SIMP_TAC[DIM_INSERT_0; INT_LE_SUB_LADD; CARD_CLAUSES; FINITE_INSERT] THEN
4027   REWRITE_TAC[INT_OF_NUM_ADD; INT_OF_NUM_LE; ADD1; LE_ADD_RCANCEL] THEN
4028   SIMP_TAC[DIM_LE_CARD]);;
4029
4030 let AFF_DIM_GE = prove
4031  (`!s:real^N->bool. -- &1 <= aff_dim s`,
4032   GEN_TAC THEN MP_TAC(ISPEC `s:real^N->bool` AFF_DIM) THEN
4033   STRIP_TAC THEN ASM_REWRITE_TAC[INT_LE_SUB_LADD; INT_ADD_LINV; INT_POS]);;
4034
4035 let AFF_DIM_SUBSET = prove
4036  (`!s t:real^N->bool. s SUBSET t ==> aff_dim s <= aff_dim t`,
4037   MATCH_MP_TAC SET_PROVE_CASES THEN REWRITE_TAC[AFF_DIM_GE; AFF_DIM_EMPTY] THEN
4038   GEOM_ORIGIN_TAC `a:real^N` THEN REPEAT STRIP_TAC THEN
4039   SUBGOAL_THEN `(vec 0:real^N) IN t` ASSUME_TAC THENL
4040    [ASM SET_TAC[]; ALL_TAC] THEN
4041   ASM_SIMP_TAC[AFF_DIM_DIM_0; IN_INSERT; HULL_INC; INT_OF_NUM_LE; DIM_SUBSET]);;
4042
4043 let AFF_DIM_LE_DIM = prove
4044  (`!s:real^N->bool. aff_dim s <= &(dim s)`,
4045   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM DIM_SPAN] THEN
4046   ASM_SIMP_TAC[GSYM AFF_DIM_DIM_SUBSPACE; SUBSPACE_SPAN] THEN
4047   MATCH_MP_TAC AFF_DIM_SUBSET THEN REWRITE_TAC[SPAN_INC]);;
4048
4049 let AFF_DIM_CONVEX_HULL = prove
4050  (`!s:real^N->bool. aff_dim(convex hull s) = aff_dim s`,
4051   GEN_TAC THEN MATCH_MP_TAC(INT_ARITH
4052    `!c:int. c = a /\ a <= b /\ b <= c ==> b = a`) THEN
4053   EXISTS_TAC `aff_dim(affine hull s:real^N->bool)` THEN
4054   SIMP_TAC[AFF_DIM_AFFINE_HULL; AFF_DIM_SUBSET; HULL_SUBSET;
4055            CONVEX_HULL_SUBSET_AFFINE_HULL]);;
4056
4057 let AFF_DIM_CLOSURE = prove
4058  (`!s:real^N->bool. aff_dim(closure s) = aff_dim s`,
4059   GEN_TAC THEN MATCH_MP_TAC(INT_ARITH
4060    `!h. h = s /\ s <= c /\ c <= h ==> c:int = s`) THEN
4061   EXISTS_TAC `aff_dim(affine hull s:real^N->bool)` THEN
4062   REPEAT CONJ_TAC THENL
4063    [REWRITE_TAC[AFF_DIM_AFFINE_HULL];
4064     MATCH_MP_TAC AFF_DIM_SUBSET THEN REWRITE_TAC[CLOSURE_SUBSET];
4065     MATCH_MP_TAC AFF_DIM_SUBSET THEN
4066     MATCH_MP_TAC CLOSURE_MINIMAL THEN
4067     REWRITE_TAC[CLOSED_AFFINE_HULL; HULL_SUBSET]]);;
4068
4069 let AFF_DIM_2 = prove
4070  (`!a b:real^N. aff_dim {a,b} = if a = b then &0 else &1`,
4071   REPEAT GEN_TAC THEN COND_CASES_TAC THENL
4072    [ASM_REWRITE_TAC[INSERT_AC; AFF_DIM_SING]; ALL_TAC] THEN
4073   MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `&(CARD {a:real^N,b}) - &1:int` THEN
4074   ASM_SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; AFFINE_INDEPENDENT_2] THEN
4075   ASM_SIMP_TAC[CARD_CLAUSES; FINITE_RULES; IN_INSERT; NOT_IN_EMPTY] THEN
4076   CONV_TAC NUM_REDUCE_CONV THEN INT_ARITH_TAC);;
4077
4078 let AFF_DIM_EQ_MINUS1 = prove
4079  (`!s:real^N->bool. aff_dim s = -- &1 <=> s = {}`,
4080   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[AFF_DIM_EMPTY] THEN
4081   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4082   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN
4083   X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
4084   MATCH_MP_TAC(INT_ARITH `&0:int <= n ==> ~(n = -- &1)`) THEN
4085   MATCH_MP_TAC INT_LE_TRANS THEN EXISTS_TAC `aff_dim {a:real^N}` THEN
4086   ASM_SIMP_TAC[AFF_DIM_SUBSET; SING_SUBSET] THEN
4087   REWRITE_TAC[AFF_DIM_SING; INT_LE_REFL]);;
4088
4089 let AFF_DIM_POS_LE = prove
4090  (`!s:real^N->bool. &0 <= aff_dim s <=> ~(s = {})`,
4091   GEN_TAC THEN REWRITE_TAC[GSYM AFF_DIM_EQ_MINUS1] THEN
4092   MP_TAC(ISPEC `s:real^N->bool` AFF_DIM_GE) THEN INT_ARITH_TAC);;
4093
4094 let AFF_DIM_EQ_0 = prove
4095  (`!s:real^N->bool. aff_dim s = &0 <=> ?a. s = {a}`,
4096   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[AFF_DIM_SING; LEFT_IMP_EXISTS_THM] THEN
4097   ASM_CASES_TAC `s:real^N->bool = {}` THEN ASM_REWRITE_TAC[AFF_DIM_EMPTY] THEN
4098   CONV_TAC INT_REDUCE_CONV THEN DISCH_TAC THEN
4099   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
4100   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
4101   MATCH_MP_TAC(SET_RULE
4102    `(!b. ~(b = a) /\ {a,b} SUBSET s ==> F) ==> a IN s ==> s = {a}`) THEN
4103   X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
4104   FIRST_ASSUM(MP_TAC o MATCH_MP AFF_DIM_SUBSET) THEN
4105   MP_TAC(ISPECL [`a:real^N`; `b:real^N`] AFF_DIM_2) THEN
4106   ASM_SIMP_TAC[] THEN INT_ARITH_TAC);;
4107
4108 let CONNECTED_IMP_PERFECT_AFF_DIM = prove
4109  (`!s x:real^N.
4110         connected s /\ ~(aff_dim s = &0) /\ x IN s ==> x limit_point_of s`,
4111   REWRITE_TAC[AFF_DIM_EQ_0; CONNECTED_IMP_PERFECT]);;
4112
4113 let AFF_DIM_UNIV = prove
4114  (`aff_dim(:real^N) = &(dimindex(:N))`,
4115   SIMP_TAC[AFF_DIM_DIM_SUBSPACE; SUBSPACE_UNIV; DIM_UNIV]);;
4116
4117 let AFF_DIM_EQ_AFFINE_HULL = prove
4118  (`!s t:real^N->bool.
4119         s SUBSET t /\ aff_dim t <= aff_dim s
4120         ==> affine hull s = affine hull t`,
4121   MATCH_MP_TAC SET_PROVE_CASES THEN
4122   SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1; AFF_DIM_GE;
4123            INT_ARITH `a:int <= x ==> (x <= a <=> x = a)`] THEN
4124   X_GEN_TAC `a:real^N` THEN GEOM_ORIGIN_TAC `a:real^N` THEN
4125   SIMP_TAC[INSERT_SUBSET; IMP_CONJ; AFF_DIM_DIM_0; IN_INSERT; DIM_EQ_SPAN;
4126            HULL_INC; AFFINE_HULL_EQ_SPAN; INT_OF_NUM_LE]);;
4127
4128 let AFF_DIM_SUMS_INTER = prove
4129  (`!s t:real^N->bool.
4130         affine s /\ affine t /\ ~(s INTER t = {})
4131         ==> aff_dim {x + y | x IN s /\ y IN t} =
4132                 (aff_dim s + aff_dim t) - aff_dim(s INTER t)`,
4133   REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> c ==> a /\ b ==> d`] THEN
4134   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN
4135   GEN_REWRITE_TAC BINDER_CONV [SWAP_FORALL_THM] THEN
4136   GEN_REWRITE_TAC I [SWAP_FORALL_THM] THEN X_GEN_TAC `a:real^N` THEN
4137   GEOM_ORIGIN_TAC `a:real^N` THEN
4138   REWRITE_TAC[VECTOR_ARITH `(a + x) + (a + y):real^N = &2 % a + (x + y)`] THEN
4139   ONCE_REWRITE_TAC[SET_RULE `{a + x + y:real^N | x IN s /\ y IN t} =
4140                             IMAGE (\x. a + x) {x + y | x IN s /\ y IN t}`] THEN
4141   REWRITE_TAC[AFF_DIM_TRANSLATION_EQ; IN_INTER] THEN
4142   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `t:real^N->bool`] THEN STRIP_TAC THEN
4143   STRIP_TAC THEN
4144   SUBGOAL_THEN `(vec 0:real^N) IN {x + y | x IN s /\ y IN t}` ASSUME_TAC THENL
4145    [REWRITE_TAC[IN_ELIM_THM] THEN REPEAT(EXISTS_TAC `vec 0:real^N`) THEN
4146     ASM_REWRITE_TAC[VECTOR_ADD_LID];
4147     ALL_TAC] THEN
4148   ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; IN_INTER] THEN
4149   REWRITE_TAC[INT_EQ_SUB_LADD; INT_OF_NUM_ADD; INT_OF_NUM_EQ] THEN
4150   MATCH_MP_TAC DIM_SUMS_INTER THEN ASM_SIMP_TAC[AFFINE_IMP_SUBSPACE]);;
4151
4152 let AFF_DIM_PSUBSET = prove
4153  (`!s t. (affine hull s) PSUBSET (affine hull t) ==> aff_dim s < aff_dim t`,
4154   ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4155   SIMP_TAC[PSUBSET; AFF_DIM_SUBSET; INT_LT_LE] THEN
4156   MESON_TAC[INT_EQ_IMP_LE; AFF_DIM_EQ_AFFINE_HULL; HULL_HULL]);;
4157
4158 let AFF_DIM_EQ_FULL = prove
4159  (`!s. aff_dim s = &(dimindex(:N)) <=> affine hull s = (:real^N)`,
4160   GEN_TAC THEN EQ_TAC THENL
4161    [DISCH_TAC THEN ONCE_REWRITE_TAC[GSYM AFFINE_HULL_UNIV] THEN
4162     MATCH_MP_TAC AFF_DIM_EQ_AFFINE_HULL THEN
4163     ASM_REWRITE_TAC[SUBSET_UNIV; AFF_DIM_UNIV; INT_LE_REFL];
4164     ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4165     SIMP_TAC[AFF_DIM_UNIV]]);;
4166
4167 let AFF_DIM_LE_UNIV = prove
4168  (`!s:real^N->bool. aff_dim s <= &(dimindex(:N))`,
4169   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_UNIV] THEN
4170   MATCH_MP_TAC AFF_DIM_SUBSET THEN REWRITE_TAC[SUBSET_UNIV]);;
4171
4172 let AFFINE_INDEPENDENT_IFF_CARD = prove
4173  (`!s:real^N->bool.
4174         ~affine_dependent s <=> FINITE s /\ aff_dim s = &(CARD s) - &1`,
4175   GEN_TAC THEN EQ_TAC THEN
4176   SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; AFFINE_INDEPENDENT_IMP_FINITE] THEN
4177   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4178   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[] THEN DISCH_TAC THEN
4179   X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC
4180    (ISPEC `s:real^N->bool` AFFINE_BASIS_EXISTS) THEN
4181   MATCH_MP_TAC(ARITH_RULE `!b:int. a <= b - &1 /\ b < s ==> ~(a = s - &1)`) THEN
4182   EXISTS_TAC `&(CARD(b:real^N->bool)):int` THEN CONJ_TAC THENL
4183    [ASM_MESON_TAC[AFF_DIM_LE_CARD; FINITE_SUBSET; AFF_DIM_AFFINE_HULL];
4184     REWRITE_TAC[INT_OF_NUM_LT] THEN MATCH_MP_TAC CARD_PSUBSET THEN
4185     ASM_REWRITE_TAC[PSUBSET] THEN ASM_MESON_TAC[]]);;
4186
4187 let AFFINE_HULL_CONVEX_INTER_NONEMPTY_INTERIOR = prove
4188  (`!s t:real^N->bool.
4189         convex s /\ ~(s INTER interior t = {})
4190         ==> affine hull (s INTER t) = affine hull s`,
4191   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; RIGHT_AND_EXISTS_THM;
4192               LEFT_IMP_EXISTS_THM] THEN
4193   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `t:real^N->bool`; `a:real^N`] THEN
4194   GEOM_ORIGIN_TAC `a:real^N` THEN REWRITE_TAC[IN_INTER] THEN
4195   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
4196   SIMP_TAC[HULL_MONO; INTER_SUBSET] THEN
4197   SIMP_TAC[SUBSET_HULL; AFFINE_AFFINE_HULL] THEN
4198   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (SIMP_RULE[SUBSET] INTERIOR_SUBSET)) THEN
4199   ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC; IN_INTER] THEN
4200   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR_CBALL]) THEN
4201   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; SUBSET; IN_CBALL_0] THEN
4202   X_GEN_TAC `e:real` THEN STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_UNIV] THEN
4203   X_GEN_TAC `x:real^N` THEN ASM_CASES_TAC `x:real^N = vec 0` THEN
4204   ASM_SIMP_TAC[SPAN_SUPERSET; IN_INTER] THEN DISCH_TAC THEN
4205   ABBREV_TAC `k = min (&1 / &2) (e / norm(x:real^N))` THEN
4206   SUBGOAL_THEN `&0 < k /\ k < &1` STRIP_ASSUME_TAC THENL
4207    [EXPAND_TAC "k" THEN
4208     ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_DIV; NORM_POS_LT; REAL_MIN_LT] THEN
4209     CONV_TAC REAL_RAT_REDUCE_CONV;
4210     ALL_TAC] THEN
4211   SUBGOAL_THEN `x:real^N = inv k % k % x` SUBST1_TAC THENL
4212    [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID;
4213                  REAL_LT_IMP_NZ];
4214     ALL_TAC] THEN
4215   MATCH_MP_TAC SPAN_MUL THEN MATCH_MP_TAC SPAN_SUPERSET THEN
4216   REWRITE_TAC[IN_INTER] THEN CONJ_TAC THENL
4217    [ONCE_REWRITE_TAC[VECTOR_ARITH
4218      `k % x:real^N = (&1 - k) % vec 0 + k % x`] THEN
4219     MATCH_MP_TAC IN_CONVEX_SET THEN ASM_SIMP_TAC[REAL_LT_IMP_LE];
4220     FIRST_X_ASSUM MATCH_MP_TAC THEN EXPAND_TAC "k" THEN
4221     ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
4222     ASM_REAL_ARITH_TAC]);;
4223
4224 let AFFINE_HULL_CONVEX_INTER_OPEN = prove
4225  (`!s t:real^N->bool.
4226         convex s /\ open t /\ ~(s INTER t = {})
4227         ==> affine hull (s INTER t) = affine hull s`,
4228   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_INTER_NONEMPTY_INTERIOR; INTERIOR_OPEN]);;
4229
4230 let AFFINE_HULL_AFFINE_INTER_NONEMPTY_INTERIOR = prove
4231  (`!s t:real^N->bool.
4232         affine s /\ ~(s INTER interior t = {})
4233         ==> affine hull (s INTER t) = s`,
4234   SIMP_TAC[AFFINE_HULL_CONVEX_INTER_NONEMPTY_INTERIOR; AFFINE_IMP_CONVEX;
4235            HULL_P]);;
4236
4237 let AFFINE_HULL_AFFINE_INTER_OPEN = prove
4238  (`!s t:real^N->bool.
4239         affine s /\ open t /\ ~(s INTER t = {})
4240         ==> affine hull (s INTER t) = s`,
4241   SIMP_TAC[AFFINE_HULL_AFFINE_INTER_NONEMPTY_INTERIOR; INTERIOR_OPEN]);;
4242
4243 let CONVEX_AND_AFFINE_INTER_OPEN = prove
4244  (`!s t u:real^N->bool.
4245         convex s /\ affine t /\ open u /\
4246         s INTER u = t INTER u /\ ~(s INTER u = {})
4247         ==> affine hull s = t`,
4248   REPEAT STRIP_TAC THEN
4249   MATCH_MP_TAC(MESON[] `!u v. x = u /\ u = v /\ v = y ==> x = y`) THEN
4250   MAP_EVERY EXISTS_TAC
4251    [`affine hull (s INTER u:real^N->bool)`;
4252     `affine hull t:real^N->bool`] THEN
4253   REPEAT CONJ_TAC THENL
4254    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC AFFINE_HULL_CONVEX_INTER_OPEN THEN
4255     ASM_REWRITE_TAC[];
4256     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC AFFINE_HULL_CONVEX_INTER_OPEN THEN
4257     ASM_SIMP_TAC[AFFINE_IMP_CONVEX] THEN ASM SET_TAC[];
4258     ASM_REWRITE_TAC[AFFINE_HULL_EQ]]);;
4259
4260 let AFFINE_HULL_CONVEX_INTER_OPEN_IN = prove
4261  (`!s t:real^N->bool.
4262         convex s /\ open_in (subtopology euclidean (affine hull s)) t /\
4263         ~(s INTER t = {})
4264         ==> affine hull (s INTER t) = affine hull s`,
4265   REPEAT STRIP_TAC THEN
4266   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
4267   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
4268   ASM_SIMP_TAC[SET_RULE `s SUBSET t ==> s INTER t INTER u = s INTER u`;
4269                HULL_SUBSET] THEN
4270   MATCH_MP_TAC AFFINE_HULL_CONVEX_INTER_OPEN THEN ASM SET_TAC[]);;
4271
4272 let AFFINE_HULL_AFFINE_INTER_OPEN_IN = prove
4273  (`!s t:real^N->bool.
4274         affine s /\ open_in (subtopology euclidean s) t /\ ~(s INTER t = {})
4275         ==> affine hull (s INTER t) = s`,
4276   REPEAT STRIP_TAC THEN
4277   MP_TAC(ISPECL [`affine hull s:real^N->bool`; `t:real^N->bool`]
4278         AFFINE_HULL_CONVEX_INTER_OPEN_IN) THEN
4279   ASM_SIMP_TAC[HULL_HULL; AFFINE_IMP_CONVEX; AFFINE_AFFINE_HULL; HULL_P]);;
4280
4281 let AFFINE_HULL_CONVEX_INTER_OPEN_IN = prove
4282  (`!s t:real^N->bool.
4283         convex s /\ open_in (subtopology euclidean (affine hull s)) t /\
4284         ~(s INTER t = {})
4285         ==> affine hull (s INTER t) = affine hull s`,
4286   REPEAT STRIP_TAC THEN
4287   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
4288   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
4289   ASM_SIMP_TAC[SET_RULE `s SUBSET t ==> s INTER t INTER u = s INTER u`;
4290                HULL_SUBSET] THEN
4291   MATCH_MP_TAC AFFINE_HULL_CONVEX_INTER_OPEN THEN ASM SET_TAC[]);;
4292
4293 let AFFINE_HULL_AFFINE_INTER_OPEN_IN = prove
4294  (`!s t:real^N->bool.
4295         affine s /\ open_in (subtopology euclidean s) t /\ ~(s INTER t = {})
4296         ==> affine hull (s INTER t) = s`,
4297   REPEAT STRIP_TAC THEN
4298   MP_TAC(ISPECL [`affine hull s:real^N->bool`; `t:real^N->bool`]
4299         AFFINE_HULL_CONVEX_INTER_OPEN_IN) THEN
4300   ASM_SIMP_TAC[HULL_HULL; AFFINE_IMP_CONVEX; AFFINE_AFFINE_HULL; HULL_P]);;
4301
4302 let AFFINE_HULL_OPEN_IN = prove
4303  (`!s t:real^N->bool.
4304         open_in (subtopology euclidean (affine hull t)) s /\ ~(s = {})
4305         ==> affine hull s = affine hull t`,
4306   REPEAT STRIP_TAC THEN
4307   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
4308   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
4309   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC AFFINE_HULL_AFFINE_INTER_OPEN THEN
4310   REWRITE_TAC[AFFINE_AFFINE_HULL] THEN ASM SET_TAC[]);;
4311
4312 let AFFINE_HULL_OPEN = prove
4313  (`!s. open s /\ ~(s = {}) ==> affine hull s = (:real^N)`,
4314   GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4315   SUBST1_TAC(SET_RULE `s = (:real^N) INTER s`) THEN
4316   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_INTER_OPEN; CONVEX_UNIV] THEN
4317   REWRITE_TAC[AFFINE_HULL_UNIV]);;
4318
4319 let AFFINE_HULL_NONEMPTY_INTERIOR = prove
4320  (`!s. ~(interior s = {}) ==> affine hull s = (:real^N)`,
4321   REPEAT STRIP_TAC THEN
4322   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
4323   EXISTS_TAC `affine hull (interior s:real^N->bool)` THEN
4324   SIMP_TAC[HULL_MONO; INTERIOR_SUBSET] THEN
4325   ASM_SIMP_TAC[AFFINE_HULL_OPEN; OPEN_INTERIOR]);;
4326
4327 let AFF_DIM_OPEN = prove
4328  (`!s:real^N->bool. open s /\ ~(s = {}) ==> aff_dim s = &(dimindex(:N))`,
4329   SIMP_TAC[AFF_DIM_EQ_FULL; AFFINE_HULL_OPEN]);;
4330
4331 let AFF_DIM_NONEMPTY_INTERIOR = prove
4332  (`!s:real^N->bool. ~(interior s = {}) ==> aff_dim s = &(dimindex(:N))`,
4333   SIMP_TAC[AFF_DIM_EQ_FULL; AFFINE_HULL_NONEMPTY_INTERIOR]);;
4334
4335 let SPAN_OPEN = prove
4336  (`!s. open s /\ ~(s = {}) ==> span s = (:real^N)`,
4337   REPEAT STRIP_TAC THEN
4338   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
4339   EXISTS_TAC `affine hull s:real^N->bool` THEN
4340   ASM_SIMP_TAC[AFFINE_HULL_OPEN; AFFINE_HULL_SUBSET_SPAN]);;
4341
4342 let DIM_OPEN = prove
4343  (`!s:real^N->bool. open s /\ ~(s = {}) ==> dim s = dimindex(:N)`,
4344   SIMP_TAC[DIM_EQ_FULL; SPAN_OPEN]);;
4345
4346 let AFF_DIM_INSERT = prove
4347  (`!a:real^N s.
4348         aff_dim (a INSERT s) =
4349         if a IN affine hull s then aff_dim s else aff_dim s + &1`,
4350   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN MATCH_MP_TAC SET_PROVE_CASES THEN
4351   SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_SING; AFFINE_HULL_EMPTY; NOT_IN_EMPTY] THEN
4352   CONV_TAC INT_REDUCE_CONV THEN REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN
4353   MAP_EVERY X_GEN_TAC [`b:real^N`; `s:real^N->bool`; `a:real^N`] THEN
4354   GEOM_ORIGIN_TAC `b:real^N` THEN
4355   SIMP_TAC[AFFINE_HULL_EQ_SPAN; AFF_DIM_DIM_0; HULL_INC; IN_INSERT] THEN
4356   MAP_EVERY X_GEN_TAC [`a:real^N`; `s:real^N->bool`] THEN
4357   DISCH_THEN(K ALL_TAC) THEN
4358   SPEC_TAC(`(vec 0:real^N) INSERT s`,`s:real^N->bool`) THEN
4359   SIMP_TAC[DIM_INSERT; INT_OF_NUM_ADD] THEN MESON_TAC[]);;
4360
4361 let AFFINE_BOUNDED_EQ_TRIVIAL = prove
4362  (`!s:real^N->bool.
4363         affine s ==> (bounded s <=> s = {} \/ ?a. s = {a})`,
4364   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
4365   ASM_REWRITE_TAC[BOUNDED_EMPTY] THEN
4366   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
4367   DISCH_THEN(X_CHOOSE_THEN `b:real^N` MP_TAC) THEN
4368   GEOM_ORIGIN_TAC `b:real^N` THEN SIMP_TAC[AFFINE_EQ_SUBSPACE] THEN
4369   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[SUBSPACE_BOUNDED_EQ_TRIVIAL] THEN
4370   FIRST_ASSUM(MP_TAC o MATCH_MP SUBSPACE_0) THEN SET_TAC[]);;
4371
4372 let AFFINE_BOUNDED_EQ_LOWDIM = prove
4373  (`!s:real^N->bool.
4374         affine s ==> (bounded s <=> aff_dim s <= &0)`,
4375   SIMP_TAC[AFF_DIM_GE; INT_ARITH
4376    `--(&1):int <= x ==> (x <= &0 <=> x = --(&1) \/ x = &0)`] THEN
4377   SIMP_TAC[AFF_DIM_EQ_0; AFF_DIM_EQ_MINUS1; AFFINE_BOUNDED_EQ_TRIVIAL]);;
4378
4379 let COLLINEAR_AFF_DIM = prove
4380  (`!s:real^N->bool. collinear s <=> aff_dim s <= &1`,
4381   GEN_TAC THEN EQ_TAC THENL
4382    [REWRITE_TAC[COLLINEAR_AFFINE_HULL; LEFT_IMP_EXISTS_THM] THEN
4383     MAP_EVERY X_GEN_TAC [`u:real^N`; `v:real^N`] THEN STRIP_TAC THEN
4384     MATCH_MP_TAC INT_LE_TRANS THEN EXISTS_TAC `aff_dim{u:real^N,v}` THEN
4385     CONJ_TAC THENL
4386      [ASM_MESON_TAC[AFF_DIM_SUBSET; AFF_DIM_AFFINE_HULL];
4387       MATCH_MP_TAC INT_LE_TRANS THEN
4388       EXISTS_TAC `&(CARD{u:real^N,v}) - &1:int` THEN
4389       SIMP_TAC[AFF_DIM_LE_CARD; FINITE_INSERT; FINITE_EMPTY] THEN
4390       REWRITE_TAC[INT_ARITH `x - &1:int <= &1 <=> x <= &2`; INT_OF_NUM_LE] THEN
4391       SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN ARITH_TAC];
4392     ONCE_REWRITE_TAC[GSYM COLLINEAR_AFFINE_HULL_COLLINEAR;
4393                      GSYM AFF_DIM_AFFINE_HULL] THEN
4394     MP_TAC(ISPEC `s:real^N->bool` AFFINE_BASIS_EXISTS) THEN
4395     DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` (STRIP_ASSUME_TAC o GSYM)) THEN
4396     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I
4397      [AFFINE_INDEPENDENT_IFF_CARD]) THEN
4398     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4399     ASM_REWRITE_TAC[COLLINEAR_AFFINE_HULL_COLLINEAR;
4400                     AFF_DIM_AFFINE_HULL] THEN
4401     REWRITE_TAC[INT_ARITH `x - &1:int <= &1 <=> x <= &2`; INT_OF_NUM_LE] THEN
4402     ASM_SIMP_TAC[COLLINEAR_SMALL]]);;
4403
4404 let HOMEOMORPHIC_AFFINE_SETS = prove
4405  (`!s:real^M->bool t:real^N->bool.
4406         affine s /\ affine t /\ aff_dim s = aff_dim t ==> s homeomorphic t`,
4407   REPEAT GEN_TAC THEN
4408   ASM_CASES_TAC `t:real^N->bool = {}` THEN
4409   ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1; HOMEOMORPHIC_EMPTY] THEN
4410   POP_ASSUM MP_TAC THEN
4411   GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o ONCE_DEPTH_CONV) [EQ_SYM_EQ] THEN
4412   ASM_CASES_TAC `s:real^M->bool = {}` THEN
4413   ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1; HOMEOMORPHIC_EMPTY] THEN
4414   POP_ASSUM MP_TAC THEN REWRITE_TAC
4415    [GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM; RIGHT_IMP_FORALL_THM] THEN
4416   MAP_EVERY X_GEN_TAC [`a:real^M`; `b:real^N`] THEN
4417   GEOM_ORIGIN_TAC `a:real^M` THEN GEOM_ORIGIN_TAC `b:real^N` THEN
4418   SIMP_TAC[AFFINE_EQ_SUBSPACE; AFF_DIM_DIM_0; HULL_INC; INT_OF_NUM_EQ] THEN
4419   MESON_TAC[HOMEOMORPHIC_SUBSPACES]);;
4420
4421 let AFF_DIM_OPEN_IN = prove
4422  (`!s t:real^N->bool.
4423         ~(s = {}) /\ open_in (subtopology euclidean t) s /\ affine t
4424         ==> aff_dim s = aff_dim t`,
4425   REPEAT GEN_TAC THEN
4426   REWRITE_TAC[IMP_CONJ; GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN
4427   X_GEN_TAC `a:real^N` THEN GEOM_ORIGIN_TAC `a:real^N` THEN
4428   REPEAT GEN_TAC THEN STRIP_TAC THEN DISCH_TAC THEN
4429   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
4430   SUBGOAL_THEN `(vec 0:real^N) IN t` ASSUME_TAC THENL
4431    [ASM SET_TAC[]; ALL_TAC] THEN
4432   ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; AFFINE_EQ_SUBSPACE] THEN
4433   DISCH_TAC THEN AP_TERM_TAC THEN
4434   ASM_SIMP_TAC[GSYM LE_ANTISYM; DIM_SUBSET] THEN
4435   SUBGOAL_THEN `?e. &0 < e /\ cball(vec 0:real^N,e) INTER t SUBSET s`
4436   MP_TAC THENL
4437    [FIRST_X_ASSUM(STRIP_ASSUME_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
4438     FIRST_X_ASSUM(MP_TAC o SPEC `vec 0:real^N` o
4439       GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
4440     ASM SET_TAC[];
4441     REWRITE_TAC[SUBSET; IN_INTER; IN_CBALL_0] THEN
4442     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC)] THEN
4443   FIRST_ASSUM(MP_TAC o MATCH_MP ORTHONORMAL_BASIS_SUBSPACE) THEN
4444   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC) THEN
4445   MP_TAC(ISPECL [`s:real^N->bool`; `IMAGE (\x:real^N. e % x) b`]
4446    INDEPENDENT_CARD_LE_DIM) THEN
4447   RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
4448   ASM_SIMP_TAC[CARD_IMAGE_INJ; VECTOR_MUL_LCANCEL; REAL_LT_IMP_NZ] THEN
4449   ANTS_TAC THENL [REWRITE_TAC[SUBSET]; MESON_TAC[]] THEN CONJ_TAC THENL
4450    [REWRITE_TAC[FORALL_IN_IMAGE] THEN REPEAT STRIP_TAC THEN
4451     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[NORM_MUL] THEN
4452     CONJ_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC SUBSPACE_MUL] THEN
4453     ASM SET_TAC[];
4454     MATCH_MP_TAC INDEPENDENT_INJECTIVE_IMAGE THEN
4455     ASM_SIMP_TAC[VECTOR_MUL_LCANCEL; REAL_LT_IMP_NZ; LINEAR_SCALING]]);;
4456
4457 let DIM_OPEN_IN = prove
4458  (`!s t:real^N->bool.
4459         ~(s = {}) /\ open_in (subtopology euclidean t) s /\ subspace t
4460         ==> dim s = dim t`,
4461   REPEAT STRIP_TAC THEN
4462   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
4463   ASM_SIMP_TAC[GSYM LE_ANTISYM; DIM_SUBSET] THEN
4464   REWRITE_TAC[GSYM INT_OF_NUM_LE] THEN
4465   MATCH_MP_TAC INT_LE_TRANS THEN EXISTS_TAC `aff_dim(s:real^N->bool)` THEN
4466   REWRITE_TAC[AFF_DIM_LE_DIM] THEN ASM_SIMP_TAC[GSYM AFF_DIM_DIM_SUBSPACE] THEN
4467   MATCH_MP_TAC INT_EQ_IMP_LE THEN CONV_TAC SYM_CONV THEN
4468   MATCH_MP_TAC AFF_DIM_OPEN_IN THEN ASM_SIMP_TAC[SUBSPACE_IMP_AFFINE]);;
4469
4470 let AFF_DIM_CONVEX_INTER_NONEMPTY_INTERIOR = prove
4471  (`!s t:real^N->bool.
4472         convex s /\ ~(s INTER interior t = {})
4473         ==> aff_dim(s INTER t) = aff_dim s`,
4474   ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4475   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_INTER_NONEMPTY_INTERIOR] THEN
4476   REWRITE_TAC[AFF_DIM_AFFINE_HULL]);;
4477
4478 let AFF_DIM_CONVEX_INTER_OPEN = prove
4479  (`!s t:real^N->bool.
4480         convex s /\ open t /\ ~(s INTER t = {})
4481         ==> aff_dim(s INTER t) = aff_dim s`,
4482   ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4483   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_INTER_OPEN] THEN
4484   REWRITE_TAC[AFF_DIM_AFFINE_HULL]);;
4485
4486 let AFFINE_HULL_HALFSPACE_LT = prove
4487  (`!a b. affine hull {x | a dot x < b} =
4488          if a = vec 0 /\ b <= &0 then {} else (:real^N)`,
4489   REPEAT GEN_TAC THEN COND_CASES_TAC THEN
4490   ASM_SIMP_TAC[AFFINE_HULL_EQ_EMPTY; HALFSPACE_EQ_EMPTY_LT;
4491                AFFINE_HULL_OPEN; OPEN_HALFSPACE_LT]);;
4492
4493 let AFFINE_HULL_HALFSPACE_LE = prove
4494  (`!a b. affine hull {x | a dot x <= b} =
4495          if a = vec 0 /\ b < &0 then {} else (:real^N)`,
4496   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THENL
4497    [ASM_SIMP_TAC[DOT_LZERO; SET_RULE `{x | p} = if p then UNIV else {}`] THEN
4498     COND_CASES_TAC THEN ASM_SIMP_TAC[AFFINE_HULL_EMPTY; AFFINE_HULL_UNIV] THEN
4499     COND_CASES_TAC THEN REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
4500     ASM_SIMP_TAC[GSYM CLOSURE_HALFSPACE_LT; AFFINE_HULL_CLOSURE] THEN
4501     ASM_REWRITE_TAC[AFFINE_HULL_HALFSPACE_LT]]);;
4502
4503 let AFFINE_HULL_HALFSPACE_GT = prove
4504  (`!a b. affine hull {x | a dot x > b} =
4505          if a = vec 0 /\ b >= &0 then {} else (:real^N)`,
4506   REPEAT GEN_TAC THEN COND_CASES_TAC THEN
4507   ASM_SIMP_TAC[AFFINE_HULL_EQ_EMPTY; HALFSPACE_EQ_EMPTY_GT;
4508                AFFINE_HULL_OPEN; OPEN_HALFSPACE_GT]);;
4509
4510 let AFFINE_HULL_HALFSPACE_GE = prove
4511  (`!a b. affine hull {x | a dot x >= b} =
4512          if a = vec 0 /\ b > &0 then {} else (:real^N)`,
4513   REPEAT GEN_TAC THEN
4514   MP_TAC(ISPECL [`--a:real^N`; `--b:real`] AFFINE_HULL_HALFSPACE_LE) THEN
4515   SIMP_TAC[real_ge; DOT_LNEG; REAL_LE_NEG2; VECTOR_NEG_EQ_0] THEN
4516   REWRITE_TAC[REAL_ARITH `--b < &0 <=> b > &0`]);;
4517
4518 let AFF_DIM_HALFSPACE_LT = prove
4519  (`!a:real^N b.
4520         aff_dim {x | a dot x < b} =
4521         if a = vec 0 /\ b <= &0 then --(&1) else &(dimindex(:N))`,
4522   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4523   SIMP_TAC[AFFINE_HULL_HALFSPACE_LT] THEN COND_CASES_TAC THEN
4524   ASM_REWRITE_TAC[AFF_DIM_EMPTY; AFF_DIM_UNIV]);;
4525
4526 let AFF_DIM_HALFSPACE_LE = prove
4527  (`!a:real^N b.
4528         aff_dim {x | a dot x <= b} =
4529         if a = vec 0 /\ b < &0 then --(&1) else &(dimindex(:N))`,
4530   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4531   SIMP_TAC[AFFINE_HULL_HALFSPACE_LE] THEN COND_CASES_TAC THEN
4532   ASM_REWRITE_TAC[AFF_DIM_EMPTY; AFF_DIM_UNIV]);;
4533
4534 let AFF_DIM_HALFSPACE_GT = prove
4535  (`!a:real^N b.
4536         aff_dim {x | a dot x > b} =
4537         if a = vec 0 /\ b >= &0 then --(&1) else &(dimindex(:N))`,
4538   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4539   SIMP_TAC[AFFINE_HULL_HALFSPACE_GT] THEN COND_CASES_TAC THEN
4540   ASM_REWRITE_TAC[AFF_DIM_EMPTY; AFF_DIM_UNIV]);;
4541
4542 let AFF_DIM_HALFSPACE_GE = prove
4543  (`!a:real^N b.
4544         aff_dim {x | a dot x >= b} =
4545         if a = vec 0 /\ b > &0 then --(&1) else &(dimindex(:N))`,
4546   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4547   SIMP_TAC[AFFINE_HULL_HALFSPACE_GE] THEN COND_CASES_TAC THEN
4548   ASM_REWRITE_TAC[AFF_DIM_EMPTY; AFF_DIM_UNIV]);;
4549
4550 let CHOOSE_AFFINE_SUBSET = prove
4551  (`!s:real^N->bool d.
4552         affine s /\ --(&1) <= d /\ d <= aff_dim s
4553         ==> ?t. affine t /\ t SUBSET s /\ aff_dim t = d`,
4554   REPEAT GEN_TAC THEN ASM_CASES_TAC `d:int = --(&1)` THENL
4555    [STRIP_TAC THEN EXISTS_TAC `{}:real^N->bool` THEN
4556     ASM_REWRITE_TAC[EMPTY_SUBSET; AFFINE_EMPTY; AFF_DIM_EMPTY];
4557     ASM_SIMP_TAC[INT_ARITH
4558      `~(d:int = --(&1)) ==> (--(&1) <= d <=> &0 <= d)`] THEN
4559     POP_ASSUM(K ALL_TAC)] THEN
4560   ASM_CASES_TAC `s:real^N->bool = {}` THENL
4561    [ASM_REWRITE_TAC[AFF_DIM_EMPTY] THEN INT_ARITH_TAC;
4562     POP_ASSUM MP_TAC] THEN
4563   GEN_REWRITE_TAC LAND_CONV [GSYM MEMBER_NOT_EMPTY] THEN
4564   DISCH_THEN(X_CHOOSE_THEN `a:real^N` MP_TAC) THEN
4565   GEOM_ORIGIN_TAC `a:real^N` THEN
4566   SIMP_TAC[IMP_CONJ; AFF_DIM_DIM_SUBSPACE; AFFINE_EQ_SUBSPACE] THEN
4567   REPEAT GEN_TAC THEN DISCH_TAC THEN DISCH_TAC THEN
4568   REWRITE_TAC[GSYM INT_OF_NUM_EXISTS] THEN
4569   DISCH_THEN(X_CHOOSE_THEN `n:num` SUBST1_TAC) THEN
4570   REWRITE_TAC[INT_OF_NUM_LE] THEN DISCH_TAC THEN
4571   MP_TAC(ISPECL [`s:real^N->bool`; `n:num`]
4572         CHOOSE_SUBSPACE_OF_SUBSPACE) THEN
4573   ASM_SIMP_TAC[SPAN_OF_SUBSPACE] THEN
4574   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real^N->bool` THEN
4575   ASM_SIMP_TAC[AFF_DIM_DIM_SUBSPACE; SUBSPACE_IMP_AFFINE]);;
4576
4577 (* ------------------------------------------------------------------------- *)
4578 (* Existence of a rigid transform between congruent sets.                    *)
4579 (* ------------------------------------------------------------------------- *)
4580
4581 let RIGID_TRANSFORMATION_BETWEEN_CONGRUENT_SETS = prove
4582  (`!x:A->real^N y:A->real^N s.
4583         (!i j. i IN s /\ j IN s ==> dist(x i,x j) = dist(y i,y j))
4584         ==> ?a f. orthogonal_transformation f /\
4585                   !i. i IN s ==> y i = a + f(x i)`,
4586   let lemma = prove
4587    (`!x:(real^N)^M y:(real^N)^M.
4588           (!i j. 1 <= i /\ i <= dimindex(:M) /\
4589                  1 <= j /\ j <= dimindex(:M)
4590                  ==> dist(x$i,x$j) = dist(y$i,y$j))
4591           ==> ?a f. orthogonal_transformation f /\
4592                     !i. 1 <= i /\ i <= dimindex(:M)
4593                         ==> y$i = a + f(x$i)`,
4594     REPEAT STRIP_TAC THEN
4595     ABBREV_TAC `(X:real^M^N) = lambda i j. (x:real^N^M)$j$i - x$1$i` THEN
4596     ABBREV_TAC `(Y:real^M^N) = lambda i j. (y:real^N^M)$j$i - y$1$i` THEN
4597     SUBGOAL_THEN `transp(X:real^M^N) ** X = transp(Y:real^M^N) ** Y`
4598     ASSUME_TAC THENL
4599      [REWRITE_TAC[MATRIX_MUL_LTRANSP_DOT_COLUMN] THEN
4600       MAP_EVERY EXPAND_TAC ["X"; "Y"] THEN
4601       SIMP_TAC[CART_EQ; column; LAMBDA_BETA; dot] THEN
4602       REWRITE_TAC[GSYM VECTOR_SUB_COMPONENT; GSYM dot] THEN
4603       REWRITE_TAC[DOT_NORM_SUB; VECTOR_ARITH
4604        `(x - a) - (y - a):real^N = x - y`] THEN
4605       ASM_SIMP_TAC[GSYM dist; DIMINDEX_GE_1; LE_REFL];
4606       ALL_TAC] THEN
4607     SUBGOAL_THEN
4608      `?M:real^N^N. orthogonal_matrix M /\ (Y:real^M^N) = M ** (X:real^M^N)`
4609     (CHOOSE_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THENL
4610      [ALL_TAC;
4611       GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [CART_EQ] THEN
4612       MAP_EVERY EXPAND_TAC ["X"; "Y"] THEN
4613       SIMP_TAC[LAMBDA_BETA; matrix_mul] THEN
4614       REWRITE_TAC[REAL_ARITH `x - y:real = z <=> x = y + z`] THEN STRIP_TAC THEN
4615       EXISTS_TAC `(y:real^N^M)$1 - (M:real^N^N) ** (x:real^N^M)$1` THEN
4616       EXISTS_TAC `\x:real^N. (M:real^N^N) ** x` THEN
4617       ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_MATRIX;
4618                    MATRIX_OF_MATRIX_VECTOR_MUL; MATRIX_VECTOR_MUL_LINEAR] THEN
4619       SIMP_TAC[CART_EQ; matrix_vector_mul; LAMBDA_BETA;
4620                VECTOR_ADD_COMPONENT] THEN
4621       ASM_SIMP_TAC[REAL_SUB_LDISTRIB; SUM_SUB_NUMSEG] THEN
4622       REWRITE_TAC[VECTOR_SUB_COMPONENT; REAL_ARITH
4623        `a + y - b:real = a - z + y <=> z = b`] THEN
4624       SIMP_TAC[LAMBDA_BETA]] THEN
4625     MP_TAC(ISPEC `transp(X:real^M^N) ** X`
4626       SYMMETRIC_MATRIX_DIAGONALIZABLE_EXPLICIT) THEN
4627     REWRITE_TAC[MATRIX_TRANSP_MUL; TRANSP_TRANSP; LEFT_IMP_EXISTS_THM] THEN
4628     MAP_EVERY X_GEN_TAC [`P:real^M^M`; `d:num->real`] THEN
4629     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4630     DISCH_THEN(fun th -> MP_TAC th THEN ASM_REWRITE_TAC[] THEN MP_TAC th) THEN
4631     REWRITE_TAC[MATRIX_MUL_ASSOC; GSYM MATRIX_TRANSP_MUL] THEN
4632     REWRITE_TAC[GSYM MATRIX_MUL_ASSOC; LEFT_IMP_EXISTS_THM] THEN
4633     REWRITE_TAC[IMP_IMP] THEN
4634     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [CART_EQ] THEN
4635     SIMP_TAC[MATRIX_MUL_LTRANSP_DOT_COLUMN; LAMBDA_BETA] THEN STRIP_TAC THEN
4636     MP_TAC(ISPECL [`\i. column i ((X:real^M^N) ** (P:real^M^M))`;
4637                    `\i. column i ((Y:real^M^N) ** (P:real^M^M))`;
4638                    `1..dimindex(:M)`]
4639                   ORTHOGONAL_TRANSFORMATION_BETWEEN_ORTHOGONAL_SETS) THEN
4640     REWRITE_TAC[IN_NUMSEG] THEN ANTS_TAC THENL
4641      [ASM_SIMP_TAC[pairwise; IN_NUMSEG; NORM_EQ; orthogonal]; ALL_TAC] THEN
4642     DISCH_THEN(X_CHOOSE_THEN `f:real^N->real^N` (STRIP_ASSUME_TAC o GSYM)) THEN
4643     EXISTS_TAC `matrix(f:real^N->real^N)` THEN CONJ_TAC THENL
4644      [ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_MATRIX]; ALL_TAC] THEN
4645     SUBGOAL_THEN
4646      `!M:real^M^N. M = M ** (P:real^M^M) ** transp P`
4647      (fun th -> GEN_REWRITE_TAC BINOP_CONV [th])
4648     THENL
4649      [ASM_MESON_TAC[orthogonal_matrix; MATRIX_MUL_RID];
4650       REWRITE_TAC[MATRIX_MUL_ASSOC] THEN AP_THM_TAC THEN AP_TERM_TAC] THEN
4651     REWRITE_TAC[GSYM MATRIX_MUL_ASSOC] THEN
4652     ASM_SIMP_TAC[MATRIX_EQUAL_COLUMNS] THEN
4653     X_GEN_TAC `i:num` THEN STRIP_TAC THEN
4654     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [orthogonal_transformation]) THEN
4655     DISCH_THEN(ASSUME_TAC o GSYM o MATCH_MP MATRIX_WORKS o CONJUNCT1) THEN
4656     ASM_REWRITE_TAC[] THEN
4657     SIMP_TAC[CART_EQ; matrix_vector_mul; column; LAMBDA_BETA] THEN
4658     X_GEN_TAC `j:num` THEN STRIP_TAC THEN
4659     GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [matrix_mul] THEN
4660     ASM_SIMP_TAC[LAMBDA_BETA]) in
4661   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:A->bool = {}` THENL
4662    [REPEAT STRIP_TAC THEN
4663     MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `\x:real^N. x`] THEN
4664     ASM_REWRITE_TAC[NOT_IN_EMPTY; ORTHOGONAL_TRANSFORMATION_ID];
4665     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
4666     DISCH_THEN(X_CHOOSE_TAC `m:A`) THEN DISCH_TAC] THEN
4667   SUBGOAL_THEN
4668     `?r. IMAGE r (1..dimindex(:(N,1)finite_sum)) SUBSET s /\
4669          affine hull (IMAGE (y o r) (1..dimindex(:(N,1)finite_sum))) =
4670          affine hull (IMAGE (y:A->real^N) s)`
4671   MP_TAC THENL
4672    [REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
4673     SIMP_TAC[IMAGE_o; TAUT `p /\ q <=> ~(p ==> ~q)`;
4674              HULL_MONO; IMAGE_SUBSET] THEN REWRITE_TAC[NOT_IMP] THEN
4675     MP_TAC(ISPEC `IMAGE (y:A->real^N) s` AFFINE_BASIS_EXISTS) THEN
4676     DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC) THEN
4677     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [AFFINE_INDEPENDENT_IFF_CARD]) THEN
4678     STRIP_TAC THEN
4679     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [FINITE_INDEX_NUMSEG]) THEN
4680     DISCH_THEN(X_CHOOSE_THEN `f:num->real^N` STRIP_ASSUME_TAC) THEN
4681     SUBGOAL_THEN `CARD(b:real^N->bool) <= dimindex(:(N,1)finite_sum)`
4682     ASSUME_TAC THENL
4683      [REWRITE_TAC[GSYM INT_OF_NUM_LE] THEN
4684       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (INT_ARITH
4685        `a:int = c - &1 ==> a + &1 <= n ==> c <= n`)) THEN
4686       REWRITE_TAC[DIMINDEX_FINITE_SUM; DIMINDEX_1; GSYM INT_OF_NUM_ADD] THEN
4687       REWRITE_TAC[INT_LE_RADD; AFF_DIM_LE_UNIV];
4688       ALL_TAC] THEN
4689     UNDISCH_TAC `b SUBSET IMAGE (y:A->real^N) s` THEN
4690     ONCE_ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
4691     REWRITE_TAC[IN_IMAGE] THEN
4692     GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4693     REWRITE_TAC[SKOLEM_THM; IN_NUMSEG] THEN
4694     DISCH_THEN(X_CHOOSE_THEN `r:num->A` STRIP_ASSUME_TAC) THEN
4695     EXISTS_TAC `\i. if i <= CARD(b:real^N->bool) then r i else (m:A)` THEN
4696     CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
4697     UNDISCH_THEN `affine hull b:real^N->bool = affine hull IMAGE y (s:A->bool)`
4698      (SUBST1_TAC o SYM) THEN
4699     REWRITE_TAC[GSYM SUBSET] THEN MATCH_MP_TAC HULL_MONO THEN
4700     ONCE_ASM_REWRITE_TAC[] THEN
4701     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_NUMSEG] THEN
4702     X_GEN_TAC `i:num` THEN STRIP_TAC THEN REWRITE_TAC[GSYM IMAGE_o] THEN
4703     REWRITE_TAC[IN_IMAGE; IN_NUMSEG] THEN EXISTS_TAC `i:num` THEN
4704     ASM_REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[LE_TRANS];
4705     REWRITE_TAC[SUBSET; IN_NUMSEG; FORALL_IN_IMAGE] THEN
4706     STRIP_TAC THEN MP_TAC(ISPECL
4707      [`(lambda i. x(r i:A)):real^N^(N,1)finite_sum`;
4708       `(lambda i. y(r i:A)):real^N^(N,1)finite_sum`] lemma) THEN
4709     ASM_SIMP_TAC[LAMBDA_BETA] THEN
4710     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
4711     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^N->real^N` THEN
4712     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4713     X_GEN_TAC `k:A` THEN STRIP_TAC THEN
4714     SUBGOAL_THEN
4715      `!z. z IN
4716           affine hull IMAGE (y o (r:num->A)) (1..dimindex(:(N,1)finite_sum))
4717           ==> dist(z,y k) = dist(z,a + (f:real^N->real^N)(x k))`
4718     MP_TAC THENL
4719      [MATCH_MP_TAC SAME_DISTANCES_TO_AFFINE_HULL THEN
4720       REWRITE_TAC[FORALL_IN_IMAGE; o_THM; IN_NUMSEG] THEN
4721       X_GEN_TAC `j:num` THEN STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
4722       EXISTS_TAC `dist(x(r(j:num)),(x:A->real^N) k)` THEN CONJ_TAC THENL
4723        [CONV_TAC SYM_CONV THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[];
4724         REWRITE_TAC[dist] THEN ASM_SIMP_TAC[NORM_ARITH
4725          `(a + x) - (a + y):real^N = x - y`] THEN
4726         ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION; LINEAR_SUB]];
4727       ASM_SIMP_TAC[NORM_ARITH
4728        `a:real^N = b <=> dist(a:real^N,a) = dist(a,b)`] THEN
4729       DISCH_THEN MATCH_MP_TAC THEN  MATCH_MP_TAC HULL_INC THEN
4730       REWRITE_TAC[IN_IMAGE; IN_NUMSEG] THEN ASM_MESON_TAC[]]]);;
4731
4732 let RIGID_TRANSFORMATION_BETWEEN_CONGRUENT_SETS_STRONG = prove
4733  (`!x:A->real^N y:A->real^N s t.
4734         t SUBSET s /\ affine hull (IMAGE y t) = affine hull (IMAGE y s) /\
4735         (!i j. i IN s /\ j IN t ==> dist(x i,x j) = dist(y i,y j))
4736         ==> ?a f. orthogonal_transformation f /\
4737                   !i. i IN s ==> y i = a + f(x i)`,
4738   REPEAT STRIP_TAC THEN
4739   MP_TAC(ISPECL [`x:A->real^N`; `y:A->real^N`; `t:A->bool`]
4740         RIGID_TRANSFORMATION_BETWEEN_CONGRUENT_SETS) THEN
4741   ANTS_TAC THENL [ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
4742   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
4743   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^N->real^N` THEN
4744   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `i:A` THEN DISCH_TAC THEN
4745   SUBGOAL_THEN
4746    `!z. z IN affine hull (IMAGE (y:A->real^N) t)
4747         ==> dist(z,y i) = dist(z,a + (f:real^N->real^N)(x i))`
4748   MP_TAC THENL
4749    [MATCH_MP_TAC SAME_DISTANCES_TO_AFFINE_HULL THEN
4750     REWRITE_TAC[FORALL_IN_IMAGE; o_THM; IN_NUMSEG] THEN
4751     X_GEN_TAC `j:A` THEN STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
4752     EXISTS_TAC `dist(a + f(x(j:A):real^N):real^N,a + f(x i))` THEN
4753     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
4754     REWRITE_TAC[NORM_ARITH `dist(a + x:real^N,a + y) = dist(x,y)`] THEN
4755     ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_ISOMETRY; DIST_SYM];
4756     ASM_SIMP_TAC[NORM_ARITH
4757      `a:real^N = b <=> dist(a:real^N,a) = dist(a,b)`] THEN
4758     DISCH_THEN MATCH_MP_TAC THEN  MATCH_MP_TAC HULL_INC THEN
4759     REWRITE_TAC[IN_IMAGE] THEN ASM_MESON_TAC[]]);;
4760
4761 let RIGID_TRANSFORMATION_BETWEEN_3 = prove
4762  (`!a b c a' b' c':real^N.
4763         dist(a,b) = dist(a',b') /\
4764         dist(b,c) = dist(b',c') /\
4765         dist(c,a) = dist(c',a')
4766         ==> ?k f. orthogonal_transformation f /\
4767                   a' = k + f a /\ b' = k + f b /\ c' = k + f c`,
4768   REPEAT STRIP_TAC THEN
4769   MP_TAC(ISPECL
4770    [`FST:real^N#real^N->real^N`; `SND:real^N#real^N->real^N`;
4771     `{(a:real^N,a':real^N), (b,b'), (c,c')}`]
4772         RIGID_TRANSFORMATION_BETWEEN_CONGRUENT_SETS) THEN
4773   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_INSERT] THEN
4774   REWRITE_TAC[NOT_IN_EMPTY; IMP_IMP] THEN DISCH_THEN MATCH_MP_TAC THEN
4775   ASM_MESON_TAC[DIST_REFL; DIST_SYM]);;
4776
4777 let RIGID_TRANSFORMATION_BETWEEN_2 = prove
4778  (`!a b a' b':real^N.
4779         dist(a,b) = dist(a',b')
4780         ==> ?k f. orthogonal_transformation f /\
4781                   a' = k + f a /\ b' = k + f b`,
4782   REPEAT STRIP_TAC THEN
4783   MP_TAC(ISPECL [`a:real^N`; `b:real^N`; `a:real^N`;
4784                  `a':real^N`; `b':real^N`; `a':real^N`]
4785         RIGID_TRANSFORMATION_BETWEEN_3) THEN
4786   ASM_MESON_TAC[DIST_EQ_0; DIST_SYM]);;
4787
4788 (* ------------------------------------------------------------------------- *)
4789 (* Caratheodory's theorem.                                                   *)
4790 (* ------------------------------------------------------------------------- *)
4791
4792 let CONVEX_HULL_CARATHEODORY_AFF_DIM = prove
4793  (`!p. convex hull p =
4794         {y:real^N | ?s u. FINITE s /\ s SUBSET p /\
4795                           &(CARD s) <= aff_dim p + &1 /\
4796                           (!x. x IN s ==> &0 <= u x) /\
4797                           sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
4798   GEN_TAC THEN REWRITE_TAC[CONVEX_HULL_EXPLICIT] THEN
4799   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN X_GEN_TAC `y:real^N` THEN
4800   EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
4801   MATCH_MP_TAC(TAUT `!q. (p ==> q) /\ (q ==> r) ==> (p ==> r)`) THEN
4802   EXISTS_TAC `?n s u. CARD s = n /\
4803                       FINITE s /\ s SUBSET p /\
4804                       (!x. x IN s ==> &0 <= u x) /\
4805                       sum s u = &1 /\ vsum s (\v. u v % v) = (y:real^N)` THEN
4806   CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
4807   GEN_REWRITE_TAC LAND_CONV [num_WOP] THEN
4808   DISCH_THEN(X_CHOOSE_THEN `n:num` MP_TAC) THEN
4809   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
4810   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
4811   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4812   GEN_REWRITE_TAC I [GSYM INT_NOT_LT] THEN DISCH_TAC THEN
4813   FIRST_X_ASSUM(MP_TAC o SPEC `n - 1`) THEN REWRITE_TAC[NOT_IMP] THEN
4814   CONJ_TAC THENL
4815    [MATCH_MP_TAC(ARITH_RULE `~(n = 0) ==> n - 1 < n`) THEN
4816     DISCH_THEN SUBST_ALL_TAC THEN
4817     UNDISCH_TAC `aff_dim(p:real^N->bool) + &1 < &0` THEN
4818     REWRITE_TAC[INT_ARITH `p + &1:int < &0 <=> ~(-- &1 <= p)`] THEN
4819     REWRITE_TAC[AFF_DIM_GE];
4820     ALL_TAC] THEN
4821   MP_TAC(ISPEC `s:real^N->bool` AFF_DIM_AFFINE_INDEPENDENT) THEN
4822   ASM_REWRITE_TAC[] THEN
4823   SUBGOAL_THEN `~(aff_dim(s:real^N->bool) = &n - &1)` ASSUME_TAC THENL
4824    [FIRST_ASSUM(MP_TAC o MATCH_MP AFF_DIM_SUBSET) THEN
4825
4826     UNDISCH_TAC `aff_dim(p:real^N->bool) + &1 < &n` THEN
4827     INT_ARITH_TAC;
4828     ALL_TAC] THEN
4829   ASM_SIMP_TAC[AFFINE_DEPENDENT_EXPLICIT_FINITE] THEN
4830   DISCH_THEN(X_CHOOSE_THEN `w:real^N->real` STRIP_ASSUME_TAC) THEN
4831   SUBGOAL_THEN
4832    `?t. (!v:real^N. v IN s ==> u(v) + t * w(v) >= &0) /\
4833         ?a. a IN s /\ u(a) + t * w(a) = &0`
4834   STRIP_ASSUME_TAC THENL
4835    [ABBREV_TAC
4836      `i = IMAGE (\v. u(v) / --w(v)) {v:real^N | v IN s /\ w v < &0}` THEN
4837     EXISTS_TAC `inf i` THEN MP_TAC(SPEC `i:real->bool` INF_FINITE) THEN
4838     ANTS_TAC THENL
4839      [EXPAND_TAC "i" THEN
4840       ASM_SIMP_TAC[FINITE_IMAGE; FINITE_RESTRICT; IMAGE_EQ_EMPTY] THEN
4841       REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
4842       MP_TAC(ISPECL [`w:real^N->real`; `s:real^N->bool`] SUM_ZERO_EXISTS) THEN
4843       ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[];
4844       ALL_TAC] THEN
4845     ABBREV_TAC `t = inf i` THEN
4846     EXPAND_TAC "i" THEN REWRITE_TAC[FORALL_IN_IMAGE] THEN
4847     REWRITE_TAC[IN_IMAGE; IN_ELIM_THM] THEN
4848     DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_THEN `a:real^N`
4849       STRIP_ASSUME_TAC) MP_TAC) THEN
4850     SIMP_TAC[REAL_LE_RDIV_EQ; REAL_ARITH `x < &0 ==> &0 < --x`; real_ge] THEN
4851     REWRITE_TAC[REAL_ARITH `t * --w <= u <=> &0 <= u + t * w`] THEN
4852     STRIP_TAC THEN CONJ_TAC THENL
4853      [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4854       DISJ_CASES_TAC(REAL_ARITH `(w:real^N->real) x < &0 \/ &0 <= w x`) THEN
4855       ASM_SIMP_TAC[] THEN MATCH_MP_TAC REAL_LE_ADD THEN ASM_SIMP_TAC[] THEN
4856       MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[] THEN
4857       MATCH_MP_TAC REAL_LE_DIV THEN ASM_SIMP_TAC[] THEN
4858       MATCH_MP_TAC(REAL_ARITH `w < &0 ==> &0 <= --w`) THEN ASM_REWRITE_TAC[];
4859       EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN
4860       UNDISCH_TAC `w(a:real^N) < &0` THEN CONV_TAC REAL_FIELD];
4861     ALL_TAC] THEN
4862   MAP_EVERY EXISTS_TAC
4863    [`s DELETE (a:real^N)`; `(\v. u(v) + t * w(v)):real^N->real`] THEN
4864   ASM_SIMP_TAC[SUM_DELETE; VSUM_DELETE; CARD_DELETE; FINITE_DELETE] THEN
4865   ASM_SIMP_TAC[SUM_ADD; VECTOR_ADD_RDISTRIB; VSUM_ADD] THEN
4866   ASM_SIMP_TAC[GSYM VECTOR_MUL_ASSOC; SUM_LMUL; VSUM_LMUL] THEN
4867   REPEAT CONJ_TAC THENL
4868    [ASM SET_TAC[]; ASM SET_TAC[real_ge]; REAL_ARITH_TAC; VECTOR_ARITH_TAC]);;
4869
4870 let CARATHEODORY_AFF_DIM = prove
4871  (`!p. convex hull p =
4872         {x:real^N | ?s. FINITE s /\ s SUBSET p /\
4873                          &(CARD s) <= aff_dim p + &1 /\
4874                         x IN convex hull s}`,
4875   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REPEAT GEN_TAC THEN EQ_TAC THENL
4876    [GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
4877      [CONVEX_HULL_CARATHEODORY_AFF_DIM] THEN
4878     REWRITE_TAC[IN_ELIM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
4879     ASM_MESON_TAC[HULL_SUBSET; CONVEX_EXPLICIT; CONVEX_CONVEX_HULL];
4880     MESON_TAC[SUBSET; HULL_MONO]]);;
4881
4882 let CONVEX_HULL_CARATHEODORY = prove
4883  (`!p. convex hull p =
4884         {y:real^N | ?s u. FINITE s /\ s SUBSET p /\
4885                           CARD(s) <= dimindex(:N) + 1 /\
4886                           (!x. x IN s ==> &0 <= u x) /\
4887                           sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
4888
4889   GEN_TAC THEN REWRITE_TAC[EXTENSION] THEN X_GEN_TAC `y:real^N` THEN
4890   EQ_TAC THENL
4891    [REWRITE_TAC[CONVEX_HULL_CARATHEODORY_AFF_DIM; IN_ELIM_THM] THEN
4892     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
4893     STRIP_TAC THEN
4894     ASM_REWRITE_TAC[GSYM INT_OF_NUM_LE; GSYM INT_OF_NUM_ADD] THEN
4895     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (INT_ARITH
4896      `a:int <= x + &1 ==> x <= y ==> a <= y + &1`)) THEN
4897     REWRITE_TAC[AFF_DIM_LE_UNIV];
4898     REWRITE_TAC[CONVEX_HULL_EXPLICIT; IN_ELIM_THM] THEN MESON_TAC[]]);;
4899
4900 let CARATHEODORY = prove
4901  (`!p. convex hull p =
4902         {x:real^N | ?s. FINITE s /\ s SUBSET p /\
4903                         CARD(s) <= dimindex(:N) + 1 /\
4904                         x IN convex hull s}`,
4905   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REPEAT GEN_TAC THEN EQ_TAC THENL
4906    [GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
4907      [CONVEX_HULL_CARATHEODORY] THEN
4908     REWRITE_TAC[IN_ELIM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
4909     ASM_MESON_TAC[HULL_SUBSET; CONVEX_EXPLICIT; CONVEX_CONVEX_HULL];
4910     MESON_TAC[SUBSET; HULL_MONO]]);;
4911
4912 (* ------------------------------------------------------------------------- *)
4913 (* Some results on decomposing convex hulls, e.g. simplicial subdivision.    *)
4914 (* ------------------------------------------------------------------------- *)
4915
4916 let AFFINE_HULL_INTER,CONVEX_HULL_INTER = (CONJ_PAIR o prove)
4917  (`(!s t:real^N->bool.
4918         ~(affine_dependent(s UNION t))
4919         ==> affine hull s INTER affine hull t = affine hull (s INTER t)) /\
4920    (!s t:real^N->bool.
4921         ~(affine_dependent (s UNION t))
4922         ==> convex hull s INTER convex hull t = convex hull (s INTER t))`,
4923   CONJ_TAC THEN
4924   (REPEAT STRIP_TAC THEN
4925    FIRST_ASSUM(MP_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
4926    REWRITE_TAC[FINITE_UNION] THEN STRIP_TAC THEN
4927    MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET_INTER] THEN
4928    SIMP_TAC[HULL_MONO; INTER_SUBSET] THEN
4929    REWRITE_TAC[SUBSET; AFFINE_HULL_FINITE; CONVEX_HULL_FINITE;
4930                IN_ELIM_THM; IN_INTER] THEN
4931    X_GEN_TAC `y:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2
4932     (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC)
4933     (X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC)) THEN
4934    FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
4935      [AFFINE_DEPENDENT_EXPLICIT]) THEN
4936    REWRITE_TAC[NOT_EXISTS_THM] THEN
4937    DISCH_THEN(MP_TAC o SPEC `(s UNION t):real^N->bool`) THEN
4938    ASM_REWRITE_TAC[SUBSET_REFL] THEN
4939    DISCH_THEN(MP_TAC o SPEC
4940     `\x:real^N. (if x IN s then u x else &0) -
4941                 (if x IN t then v x else &0)`) THEN
4942    ASM_SIMP_TAC[SUM_SUB; FINITE_UNION; VSUM_SUB; VECTOR_SUB_RDISTRIB] THEN
4943    REWRITE_TAC[MESON[]
4944     `(if p then a else b) % x = (if p then a % x else b % x)`] THEN
4945    ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; VECTOR_MUL_LZERO; FINITE_UNION] THEN
4946    ASM_REWRITE_TAC[SUM_0; VSUM_0;
4947      SET_RULE `{x | x IN (s UNION t) /\ x IN s} = s`;
4948      SET_RULE `{x | x IN (s UNION t) /\ x IN t} = t`] THEN
4949    MATCH_MP_TAC(TAUT `a /\ c /\ (~b ==> d) ==> ~(a /\ b /\ c) ==> d`) THEN
4950    REPEAT CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC; ALL_TAC] THEN
4951    DISCH_TAC THEN EXISTS_TAC `u:real^N->real` THEN ASM_SIMP_TAC[] THEN
4952    CONJ_TAC THEN MATCH_MP_TAC EQ_TRANS THENL
4953     [EXISTS_TAC `sum s (u:real^N->real)`;
4954      EXISTS_TAC `vsum s (\x. (u:real^N->real) x % x)`] THEN
4955    (CONJ_TAC THENL [ALL_TAC; FIRST_X_ASSUM ACCEPT_TAC]) THEN
4956    CONV_TAC SYM_CONV THENL
4957     [MATCH_MP_TAC SUM_EQ_SUPERSET; MATCH_MP_TAC VSUM_EQ_SUPERSET] THEN
4958    ASM_SIMP_TAC[FINITE_INTER; INTER_SUBSET; IN_INTER] THEN
4959    X_GEN_TAC `x:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4960    ASM_REWRITE_TAC[VECTOR_MUL_EQ_0] THEN DISCH_TAC THEN
4961    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
4962    DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
4963    ASM_REWRITE_TAC[REAL_SUB_RZERO] THEN ASM SET_TAC[]));;
4964
4965 let AFFINE_HULL_INTERS = prove
4966  (`!s:(real^N->bool)->bool.
4967         ~(affine_dependent(UNIONS s))
4968         ==> affine hull (INTERS s) = INTERS {affine hull t | t IN s}`,
4969   REPEAT STRIP_TAC THEN FIRST_X_ASSUM(fun th ->
4970    MP_TAC th THEN MP_TAC(MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE th)) THEN
4971   SPEC_TAC(`s:(real^N->bool)->bool`,`s:(real^N->bool)->bool`) THEN
4972   REWRITE_TAC[FINITE_UNIONS; IMP_CONJ] THEN
4973   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
4974   REWRITE_TAC[UNIONS_0; INTERS_0; UNIONS_INSERT; INTERS_INSERT;
4975               SET_RULE `{f x | x IN {}} = {}`; AFFINE_HULL_UNIV] THEN
4976   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `f:(real^N->bool)->bool`] THEN
4977   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
4978   REWRITE_TAC[FORALL_IN_INSERT] THEN
4979   DISCH_THEN(fun th -> STRIP_TAC THEN STRIP_TAC THEN MP_TAC th) THEN
4980   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
4981    [UNDISCH_TAC `~affine_dependent((s UNION UNIONS f):real^N->bool)` THEN
4982     REWRITE_TAC[CONTRAPOS_THM] THEN
4983     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO) THEN
4984     SET_TAC[];
4985     DISCH_TAC] THEN
4986   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
4987    [ASM_REWRITE_TAC[INTERS_0; INTER_UNIV; IN_SING] THEN
4988     REWRITE_TAC[SET_RULE `{f x | x = a} = {f a}`; INTERS_1];
4989     ALL_TAC] THEN
4990   W(MP_TAC o PART_MATCH (rhs o rand) AFFINE_HULL_INTER o lhand o snd) THEN
4991   ANTS_TAC THENL
4992    [UNDISCH_TAC `~affine_dependent((s UNION UNIONS f):real^N->bool)` THEN
4993     REWRITE_TAC[CONTRAPOS_THM] THEN
4994     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO) THEN
4995     UNDISCH_TAC `~(f:(real^N->bool)->bool = {})` THEN SET_TAC[];
4996     DISCH_THEN(SUBST1_TAC o SYM)] THEN
4997   REWRITE_TAC[SET_RULE
4998    `{f x | x IN (a INSERT s)} = (f a) INSERT {f x | x IN s}`] THEN
4999   ASM_REWRITE_TAC[INTERS_INSERT]);;
5000
5001 let CONVEX_HULL_INTERS = prove
5002  (`!s:(real^N->bool)->bool.
5003         ~(affine_dependent(UNIONS s))
5004         ==> convex hull (INTERS s) = INTERS {convex hull t | t IN s}`,
5005   REPEAT STRIP_TAC THEN FIRST_X_ASSUM(fun th ->
5006    MP_TAC th THEN MP_TAC(MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE th)) THEN
5007   SPEC_TAC(`s:(real^N->bool)->bool`,`s:(real^N->bool)->bool`) THEN
5008   REWRITE_TAC[FINITE_UNIONS; IMP_CONJ] THEN
5009   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5010   REWRITE_TAC[UNIONS_0; INTERS_0; UNIONS_INSERT; INTERS_INSERT;
5011               SET_RULE `{f x | x IN {}} = {}`; CONVEX_HULL_UNIV] THEN
5012   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `f:(real^N->bool)->bool`] THEN
5013   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
5014   REWRITE_TAC[FORALL_IN_INSERT] THEN
5015   DISCH_THEN(fun th -> STRIP_TAC THEN STRIP_TAC THEN MP_TAC th) THEN
5016   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
5017    [UNDISCH_TAC `~affine_dependent((s UNION UNIONS f):real^N->bool)` THEN
5018     REWRITE_TAC[CONTRAPOS_THM] THEN
5019     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO) THEN
5020     SET_TAC[];
5021     DISCH_TAC] THEN
5022   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
5023    [ASM_REWRITE_TAC[INTERS_0; INTER_UNIV; IN_SING] THEN
5024     REWRITE_TAC[SET_RULE `{f x | x = a} = {f a}`; INTERS_1];
5025     ALL_TAC] THEN
5026   W(MP_TAC o PART_MATCH (rhs o rand) CONVEX_HULL_INTER o lhand o snd) THEN
5027   ANTS_TAC THENL
5028    [UNDISCH_TAC `~affine_dependent((s UNION UNIONS f):real^N->bool)` THEN
5029     REWRITE_TAC[CONTRAPOS_THM] THEN
5030     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO) THEN
5031     UNDISCH_TAC `~(f:(real^N->bool)->bool = {})` THEN SET_TAC[];
5032     DISCH_THEN(SUBST1_TAC o SYM)] THEN
5033   REWRITE_TAC[SET_RULE
5034    `{f x | x IN (a INSERT s)} = (f a) INSERT {f x | x IN s}`] THEN
5035   ASM_REWRITE_TAC[INTERS_INSERT]);;
5036
5037 let IN_CONVEX_HULL_EXCHANGE = prove
5038  (`!s a x:real^N.
5039         a IN convex hull s /\ x IN convex hull s
5040         ==> ?b. b IN s /\ x IN convex hull (a INSERT (s DELETE b))`,
5041   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(a:real^N) IN s` THENL
5042    [EXISTS_TAC `a:real^N` THEN ASM_SIMP_TAC[INSERT_DELETE]; ALL_TAC] THEN
5043   ASM_CASES_TAC `FINITE(s:real^N->bool) /\ CARD s <= dimindex(:N) + 1` THENL
5044    [ALL_TAC;
5045     UNDISCH_TAC `(x:real^N) IN convex hull s` THEN
5046     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [CARATHEODORY] THEN
5047     REWRITE_TAC[LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN
5048     X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
5049     ASM_CASES_TAC `t:real^N->bool = s` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
5050     SUBGOAL_THEN `?b:real^N. b IN s /\ ~(b IN t)` MP_TAC THENL
5051      [ASM SET_TAC[]; ALL_TAC] THEN
5052     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN
5053     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
5054     UNDISCH_TAC `(x:real^N) IN convex hull t` THEN
5055     SPEC_TAC(`x:real^N`,`x:real^N`) THEN REWRITE_TAC[GSYM SUBSET] THEN
5056     MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]] THEN
5057   MP_TAC(ASSUME `(a:real^N) IN convex hull s`) THEN
5058   MP_TAC(ASSUME `(x:real^N) IN convex hull s`) THEN
5059   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
5060   X_GEN_TAC `v:real^N->real` THEN STRIP_TAC THEN
5061   X_GEN_TAC `u:real^N->real` THEN STRIP_TAC THEN
5062   ASM_CASES_TAC `?b. b IN s /\ (v:real^N->real) b = &0` THENL
5063    [FIRST_X_ASSUM(fun th -> MP_TAC th THEN MATCH_MP_TAC MONO_EXISTS) THEN
5064     X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
5065     EXISTS_TAC `\x:real^N. if x = a then &0 else v x` THEN
5066     ASM_SIMP_TAC[FORALL_IN_INSERT; REAL_LE_REFL] THEN
5067     ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FINITE_DELETE] THEN
5068     ASM_REWRITE_TAC[IN_DELETE] THEN
5069     ASM_SIMP_TAC[SUM_DELETE; VSUM_DELETE; COND_ID] THEN
5070     ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
5071     ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; REAL_LE_REFL; COND_ID] THEN
5072     REWRITE_TAC[VECTOR_MUL_LZERO; SUM_0; VSUM_0] THEN
5073     ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> {x | x IN s /\ ~(x = a)} = s`] THEN
5074     CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC];
5075     ALL_TAC] THEN
5076   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
5077   REWRITE_TAC[TAUT `~(a /\ b) <=> a ==> ~b`] THEN DISCH_TAC THEN
5078   MP_TAC(ISPEC `IMAGE (\b. (u:real^N->real) b / v b) s` SUP_FINITE) THEN
5079   ASM_CASES_TAC `s:real^N->bool = {}` THENL
5080    [ASM_MESON_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY]; ALL_TAC] THEN
5081   ASM_SIMP_TAC[FINITE_IMAGE; IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
5082   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
5083   REWRITE_TAC[IN_IMAGE] THEN MATCH_MP_TAC MONO_EXISTS THEN
5084   X_GEN_TAC `b:real^N` THEN
5085   DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
5086   ASM_REWRITE_TAC[] THEN
5087   SUBGOAL_THEN `!b. b IN s ==> &0 < (v:real^N->real) b` ASSUME_TAC THENL
5088    [ASM_SIMP_TAC[REAL_LT_LE]; ALL_TAC] THEN
5089   SUBGOAL_THEN `&0 < (u:real^N->real) b /\ &0 < v b` STRIP_ASSUME_TAC THENL
5090    [ASM_SIMP_TAC[REAL_LT_LE] THEN
5091     UNDISCH_TAC `!x. x IN s ==> (u:real^N->real) x / v x <= u b / v b` THEN
5092     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[] THEN
5093     DISCH_THEN(SUBST1_TAC o SYM) THEN ASM_SIMP_TAC[REAL_LE_LDIV_EQ] THEN
5094     REWRITE_TAC[real_div; REAL_MUL_LZERO] THEN
5095     ASM_SIMP_TAC[REAL_ARITH `&0 <= x ==> (x <= &0 <=> x = &0)`] THEN
5096     DISCH_TAC THEN UNDISCH_TAC `sum s (u:real^N->real) = &1` THEN
5097     MATCH_MP_TAC(REAL_ARITH `x = &0 ==> x = &1 ==> F`) THEN
5098     ASM_SIMP_TAC[SUM_EQ_0];
5099     ALL_TAC] THEN
5100   EXISTS_TAC `(\x. if x = a then v b / u b else v x - (v b / u b) * u x):
5101               real^N->real` THEN
5102   ASM_SIMP_TAC[FORALL_IN_INSERT; REAL_LE_DIV; REAL_LT_IMP_LE] THEN
5103   ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
5104   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FINITE_DELETE] THEN
5105   ASM_SIMP_TAC[SUM_DELETE; VSUM_DELETE; IN_DELETE] THEN
5106   ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; FINITE_DELETE] THEN
5107   ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> {x | x IN s /\ ~(x = a)} = s`;
5108                SET_RULE `~(a IN s) ==> {x | x IN s /\ x = a} = {}`] THEN
5109   REWRITE_TAC[VSUM_CLAUSES; SUM_CLAUSES] THEN
5110   ASM_CASES_TAC `b:real^N = a` THENL [ASM_MESON_TAC[]; ASM_REWRITE_TAC[]] THEN
5111   ASM_SIMP_TAC[VECTOR_SUB_RDISTRIB; VSUM_SUB; SUM_SUB] THEN
5112   REWRITE_TAC[GSYM VECTOR_MUL_ASSOC; VECTOR_ADD_LID; REAL_ADD_LID] THEN
5113   ASM_SIMP_TAC[SUM_LMUL; VSUM_LMUL] THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN
5114   ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_LT_IMP_NZ] THEN REPEAT CONJ_TAC THENL
5115    [ALL_TAC; REAL_ARITH_TAC; VECTOR_ARITH_TAC] THEN
5116   X_GEN_TAC `c:real^N` THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
5117   STRIP_TAC THEN ASM_CASES_TAC `(u:real^N->real) c = &0` THENL
5118    [ASM_SIMP_TAC[REAL_MUL_RZERO; REAL_SUB_RZERO]; ALL_TAC] THEN
5119   REWRITE_TAC[REAL_SUB_LE] THEN
5120   ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; REAL_LT_LE] THEN
5121   ONCE_REWRITE_TAC[GSYM REAL_INV_DIV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
5122   ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_LE]);;
5123
5124 let IN_CONVEX_HULL_EXCHANGE_UNIQUE = prove
5125  (`!s t t' a x:real^N.
5126         ~(affine_dependent s) /\
5127         a IN convex hull s /\
5128         t SUBSET s /\ t' SUBSET s /\
5129         x IN convex hull (a INSERT t) /\
5130         x IN convex hull (a INSERT t')
5131         ==> x IN convex hull (a INSERT (t INTER t'))`,
5132   REPEAT GEN_TAC THEN ASM_CASES_TAC `(a:real^N) IN s` THENL
5133    [REPEAT STRIP_TAC THEN REWRITE_TAC[SET_RULE
5134      `a INSERT (s INTER t) = (a INSERT s) INTER (a INSERT t)`] THEN
5135     W(MP_TAC o PART_MATCH (rand o rand)  CONVEX_HULL_INTER o rand o snd) THEN
5136     ANTS_TAC THENL
5137      [UNDISCH_TAC `~(affine_dependent(s:real^N->bool))` THEN
5138       REWRITE_TAC[CONTRAPOS_THM] THEN
5139       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO);
5140       DISCH_THEN(SUBST1_TAC o SYM)] THEN
5141     ASM SET_TAC[];
5142     ALL_TAC] THEN
5143   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5144   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
5145   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
5146   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_THEN `b:real^N->real` STRIP_ASSUME_TAC)
5147     MP_TAC) THEN
5148   REPLICATE_TAC 2 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5149   SUBGOAL_THEN `~((a:real^N) IN t) /\ ~(a IN t')` STRIP_ASSUME_TAC THENL
5150    [ASM SET_TAC[]; ALL_TAC] THEN
5151   SUBGOAL_THEN `FINITE(t:real^N->bool) /\ FINITE(t':real^N->bool)`
5152   STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
5153   ASM_SIMP_TAC[AFFINE_HULL_FINITE_STEP_GEN; REAL_LE_ADD;
5154                REAL_ARITH `&0 <= a / &2 <=> &0 <= a`] THEN
5155   REWRITE_TAC[IMP_CONJ; LEFT_IMP_EXISTS_THM] THEN
5156   MAP_EVERY X_GEN_TAC [`u':real`; `u:real^N->real`] THEN REPEAT DISCH_TAC THEN
5157   MAP_EVERY X_GEN_TAC [`v':real`; `v:real^N->real`] THEN REPEAT DISCH_TAC THEN
5158   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
5159     [AFFINE_DEPENDENT_EXPLICIT]) THEN
5160   REWRITE_TAC[NOT_EXISTS_THM] THEN
5161   DISCH_THEN(MP_TAC o SPEC `s:real^N->bool`) THEN
5162   ASM_REWRITE_TAC[SUBSET_REFL] THEN
5163   DISCH_THEN(MP_TAC o SPEC
5164    `\x:real^N. (if x IN t then u x else &0) - (if x IN t' then v x else &0) +
5165                (u' - v') * b x`) THEN
5166   ASM_SIMP_TAC[SUM_ADD; VSUM_ADD; SUM_LMUL; VSUM_LMUL; VECTOR_ADD_RDISTRIB] THEN
5167   ASM_SIMP_TAC[SUM_SUB; VSUM_SUB; VECTOR_SUB_RDISTRIB] THEN
5168   REWRITE_TAC[MESON[]
5169    `(if p then a else b) % x = (if p then a % x else b % x)`] THEN
5170   ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; VECTOR_MUL_LZERO; SUM_0; VSUM_0] THEN
5171   ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
5172   ASM_SIMP_TAC[SUM_ADD; SUM_LMUL; VSUM_ADD; VSUM_LMUL; VECTOR_ADD_RDISTRIB;
5173                GSYM VECTOR_MUL_ASSOC] THEN
5174   MATCH_MP_TAC(TAUT `a /\ c /\ (~b ==> d) ==> ~(a /\ b /\ c) ==> d`) THEN
5175   REPEAT CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC; ALL_TAC] THEN
5176   DISCH_TAC THEN
5177   SUBGOAL_THEN
5178    `(!x. x IN s ==> (if x IN t then u x else &0) <=
5179                     (if x IN t' then v x else &0)) \/
5180     (!x:real^N. x IN s ==> (if x IN t' then v x else &0) <=
5181                            (if x IN t then u x else &0))`
5182   (DISJ_CASES_THEN(LABEL_TAC "*")) THENL
5183    [MP_TAC(REAL_ARITH `&0 <= (u' - v') \/ &0 <= (v' - u')`) THEN
5184     MATCH_MP_TAC MONO_OR THEN CONJ_TAC THEN
5185     DISCH_TAC THEN X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
5186     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
5187     DISCH_THEN(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THENL
5188      [MATCH_MP_TAC(REAL_ARITH `&0 <= c ==> a - b + c = &0 ==> a <= b`);
5189       MATCH_MP_TAC(REAL_ARITH `&0 <= --c ==> a - b + c = &0 ==> b <= a`)] THEN
5190     ASM_SIMP_TAC[REAL_LE_MUL; GSYM REAL_MUL_LNEG; REAL_NEG_SUB];
5191     EXISTS_TAC `(\x. if x = a then u' else u x):real^N->real`;
5192     EXISTS_TAC `(\x. if x = a then v' else v x):real^N->real`] THEN
5193   ASM_SIMP_TAC[FORALL_IN_INSERT] THEN
5194   (CONJ_TAC THENL [ASM_MESON_TAC[IN_INTER]; ALL_TAC]) THEN
5195   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FINITE_INTER] THEN
5196   ASM_REWRITE_TAC[IN_INTER] THEN
5197   REWRITE_TAC[REAL_ARITH `u' + u = &1 <=> u = &1 - u'`;
5198               VECTOR_ARITH `u' + u:real^N = y <=> u = y - u'`] THEN
5199   (CONJ_TAC THEN
5200    FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN
5201    CONV_TAC SYM_CONV THENL
5202     [MATCH_MP_TAC SUM_EQ_SUPERSET; MATCH_MP_TAC VSUM_EQ_SUPERSET]) THEN
5203   ASM_SIMP_TAC[FINITE_INTER; INTER_SUBSET; IN_INTER] THEN
5204   (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
5205   X_GEN_TAC `y:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5206   ASM_REWRITE_TAC[VECTOR_MUL_EQ_0] THEN DISCH_TAC THEN
5207   REMOVE_THEN "*" (MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THEN
5208   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN ASM SET_TAC[]);;
5209
5210 let CONVEX_HULL_EXCHANGE_UNION = prove
5211  (`!s a:real^N.
5212         a IN convex hull s
5213         ==> convex hull s =
5214             UNIONS {convex hull (a INSERT (s DELETE b)) |b| b IN s}`,
5215   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
5216    [ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN REWRITE_TAC[UNIONS_IMAGE] THEN
5217     REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
5218     ASM_MESON_TAC[IN_CONVEX_HULL_EXCHANGE];
5219     REWRITE_TAC[SUBSET; FORALL_IN_UNIONS; FORALL_IN_GSPEC;
5220                 IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
5221     GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[GSYM SUBSET] THEN
5222     ASM_SIMP_TAC[SUBSET_HULL; CONVEX_CONVEX_HULL] THEN
5223     ASM_REWRITE_TAC[INSERT_SUBSET] THEN
5224     MESON_TAC[HULL_INC; SUBSET; IN_DELETE]]);;
5225
5226 let CONVEX_HULL_EXCHANGE_INTER = prove
5227  (`!s a:real^N t t'.
5228          ~affine_dependent s /\
5229          a IN convex hull s /\
5230          t SUBSET s /\
5231          t' SUBSET s
5232          ==> (convex hull (a INSERT t)) INTER (convex hull (a INSERT t')) =
5233              convex hull (a INSERT (t INTER t'))`,
5234   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
5235    [REWRITE_TAC[SUBSET; IN_INTER] THEN REPEAT STRIP_TAC THEN
5236     MATCH_MP_TAC IN_CONVEX_HULL_EXCHANGE_UNIQUE THEN
5237     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[];
5238     REWRITE_TAC[SUBSET_INTER] THEN CONJ_TAC THEN
5239     MATCH_MP_TAC HULL_MONO THEN SET_TAC[]]);;
5240
5241 (* ------------------------------------------------------------------------- *)
5242 (* Representing affine hull as hyperplane or finite intersection of them.    *)
5243 (* ------------------------------------------------------------------------- *)
5244
5245 let AFF_DIM_EQ_HYPERPLANE = prove
5246  (`!s. aff_dim s = &(dimindex(:N)) - &1 <=>
5247        ?a b. ~(a = vec 0) /\ affine hull s = {x:real^N | a dot x = b}`,
5248   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
5249    [ASM_REWRITE_TAC[AFF_DIM_EMPTY; INT_ARITH `--a:int = b - a <=> b = &0`] THEN
5250     SIMP_TAC[INT_OF_NUM_EQ; LE_1; DIMINDEX_GE_1; AFFINE_HULL_EMPTY] THEN
5251     REWRITE_TAC[EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY; NOT_EXISTS_THM] THEN
5252     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN
5253     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5254     DISCH_THEN(MP_TAC o SPEC `(b / (a dot a)) % a:real^N`) THEN
5255     ASM_SIMP_TAC[DOT_RMUL; REAL_DIV_RMUL; DOT_EQ_0];
5256     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
5257     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `c:real^N` THEN
5258     GEN_GEOM_ORIGIN_TAC `c:real^N` ["a"] THEN
5259     SIMP_TAC[AFF_DIM_DIM_0; HULL_INC] THEN
5260     SIMP_TAC[INT_OF_NUM_SUB; DIMINDEX_GE_1; INT_OF_NUM_EQ] THEN
5261     SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC; DIM_EQ_HYPERPLANE] THEN
5262     REPEAT STRIP_TAC THEN AP_TERM_TAC THEN
5263     GEN_REWRITE_TAC I [FUN_EQ_THM] THEN X_GEN_TAC `a:real^N` THEN
5264     REWRITE_TAC[] THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
5265     ASM_REWRITE_TAC[DOT_RADD; REAL_ARITH `a + b:real = c <=> b = c - a`] THEN
5266     EQ_TAC THEN STRIP_TAC THENL
5267      [EXISTS_TAC `(a:real^N) dot c` THEN ASM_REWRITE_TAC[REAL_SUB_REFL];
5268       ASM_REWRITE_TAC[] THEN
5269       FIRST_X_ASSUM(MP_TAC o AP_TERM `\s. (vec 0:real^N) IN s`) THEN
5270       ASM_SIMP_TAC[SPAN_SUPERSET; IN_ELIM_THM; DOT_RZERO]]]);;
5271
5272 let AFF_DIM_HYPERPLANE = prove
5273  (`!a b. ~(a = vec 0)
5274          ==> aff_dim {x:real^N | a dot x = b} = &(dimindex(:N)) - &1`,
5275   REPEAT STRIP_TAC THEN REWRITE_TAC[AFF_DIM_EQ_HYPERPLANE] THEN
5276   MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real`] THEN
5277   ASM_REWRITE_TAC[AFFINE_HULL_EQ; AFFINE_HYPERPLANE]);;
5278
5279 let BOUNDED_HYPERPLANE_EQ_TRIVIAL = prove
5280  (`!a b. bounded {x:real^N | a dot x = b} <=>
5281          if a = vec 0 then ~(b = &0) else dimindex(:N) = 1`,
5282   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
5283   ASM_REWRITE_TAC[DOT_LZERO] THENL
5284    [ASM_CASES_TAC `b = &0` THEN
5285     ASM_REWRITE_TAC[EMPTY_GSPEC; BOUNDED_EMPTY] THEN
5286     REWRITE_TAC[NOT_BOUNDED_UNIV; SET_RULE `{x | T} = UNIV`];
5287     ASM_SIMP_TAC[AFFINE_BOUNDED_EQ_LOWDIM; AFF_DIM_HYPERPLANE;
5288                  AFFINE_HYPERPLANE] THEN
5289     REWRITE_TAC[INT_ARITH `a - &1:int <= &0 <=> a <= &1`; INT_OF_NUM_LE] THEN
5290     MATCH_MP_TAC(ARITH_RULE `1 <= n ==> (n <= 1 <=> n = 1)`) THEN
5291     REWRITE_TAC[DIMINDEX_GE_1]]);;
5292
5293 let AFFINE_HULL_FINITE_INTERSECTION_HYPERPLANES = prove
5294  (`!s:real^N->bool.
5295         ?f. FINITE f /\
5296             &(CARD f) + aff_dim s = &(dimindex(:N)) /\
5297             affine hull s = INTERS f /\
5298             (!h. h IN f ==> ?a b. ~(a = vec 0) /\ h = {x | a dot x = b})`,
5299   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
5300   MP_TAC(ISPEC `s:real^N->bool` AFFINE_BASIS_EXISTS) THEN
5301   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC) THEN
5302   FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
5303   MP_TAC(ISPECL [`b:real^N->bool`; `(:real^N)`] EXTEND_TO_AFFINE_BASIS) THEN
5304   ASM_REWRITE_TAC[SUBSET_UNIV; AFFINE_HULL_UNIV] THEN
5305   DISCH_THEN(X_CHOOSE_THEN `c:real^N->bool` STRIP_ASSUME_TAC) THEN
5306   SUBGOAL_THEN `FINITE(c:real^N->bool)` ASSUME_TAC THENL
5307    [ASM_MESON_TAC[AFFINE_INDEPENDENT_IMP_FINITE]; ALL_TAC] THEN
5308   REWRITE_TAC[GSYM AFF_DIM_UNIV] THEN FIRST_ASSUM(SUBST1_TAC o SYM) THEN
5309   REWRITE_TAC[AFF_DIM_AFFINE_HULL] THEN
5310   ASM_SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; CARD_DIFF] THEN
5311   REWRITE_TAC[INT_ARITH `f + b - &1:int = c - &1 <=> f = c - b`] THEN
5312   ASM_SIMP_TAC[INT_OF_NUM_SUB; CARD_SUBSET; GSYM CARD_DIFF; INT_OF_NUM_EQ] THEN
5313   ASM_CASES_TAC `c:real^N->bool = b` THENL
5314    [EXISTS_TAC `{}:(real^N->bool)->bool` THEN
5315     ASM_REWRITE_TAC[CARD_CLAUSES; FINITE_RULES; NOT_IN_EMPTY; INTERS_0;
5316                     DIFF_EQ_EMPTY] THEN
5317     ASM_MESON_TAC[];
5318     ALL_TAC] THEN
5319   EXISTS_TAC `{affine hull (c DELETE a) |a| (a:real^N) IN (c DIFF b)}` THEN
5320   REWRITE_TAC[FORALL_IN_GSPEC] THEN REWRITE_TAC[SIMPLE_IMAGE] THEN
5321   ASM_SIMP_TAC[FINITE_IMAGE; FINITE_DIFF] THEN REPEAT CONJ_TAC THENL
5322    [MATCH_MP_TAC CARD_IMAGE_INJ THEN ASM_SIMP_TAC[FINITE_DIFF] THEN
5323     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN REWRITE_TAC[IN_DIFF] THEN
5324     STRIP_TAC THEN ASM_CASES_TAC `x:real^N = y` THEN ASM_REWRITE_TAC[] THEN
5325     UNDISCH_TAC `~affine_dependent(c:real^N->bool)` THEN
5326     REWRITE_TAC[affine_dependent] THEN EXISTS_TAC `x:real^N` THEN
5327     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC HULL_INC THEN ASM SET_TAC[];
5328     ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[IMAGE_o] THEN
5329     ONCE_REWRITE_TAC[GSYM SIMPLE_IMAGE] THEN
5330     W(MP_TAC o PART_MATCH (rhs o rand) AFFINE_HULL_INTERS o rand o snd) THEN
5331     ANTS_TAC THENL
5332      [MATCH_MP_TAC AFFINE_INDEPENDENT_SUBSET THEN
5333       EXISTS_TAC `c:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
5334       REWRITE_TAC[SUBSET; FORALL_IN_UNIONS; FORALL_IN_IMAGE;
5335                   IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN SET_TAC[];
5336       DISCH_THEN(SUBST1_TAC o SYM) THEN AP_TERM_TAC THEN
5337       GEN_REWRITE_TAC I [EXTENSION] THEN
5338       REWRITE_TAC[IN_INTERS; FORALL_IN_IMAGE] THEN ASM SET_TAC[]];
5339     REWRITE_TAC[GSYM AFF_DIM_EQ_HYPERPLANE] THEN
5340     ASM_SIMP_TAC[IN_DIFF; AFFINE_INDEPENDENT_DELETE;
5341                  AFF_DIM_AFFINE_INDEPENDENT; CARD_DELETE] THEN
5342     REWRITE_TAC[GSYM AFF_DIM_UNIV] THEN FIRST_ASSUM(SUBST1_TAC o SYM) THEN
5343     REWRITE_TAC[AFF_DIM_AFFINE_HULL] THEN
5344     ASM_SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; CARD_DIFF] THEN
5345     REPEAT STRIP_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
5346     MATCH_MP_TAC(GSYM INT_OF_NUM_SUB) THEN
5347     MATCH_MP_TAC(ARITH_RULE `~(c = 0) ==> 1 <= c`) THEN
5348     ASM_SIMP_TAC[CARD_EQ_0] THEN ASM SET_TAC[]]);;
5349
5350 let AFFINE_HYPERPLANE_SUMS_EQ_UNIV = prove
5351  (`!a b s.
5352         affine s /\
5353         ~(s INTER {v | a dot v = b} = {}) /\
5354         ~(s DIFF {v | a dot v = b} = {})
5355         ==> {x + y | x IN s /\ y IN {v | a dot v = b}} = (:real^N)`,
5356   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THENL
5357    [ASM_REWRITE_TAC[DOT_LZERO] THEN SET_TAC[]; ALL_TAC] THEN
5358   REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> b ==> a /\ c ==> d`] THEN
5359   GEN_REWRITE_TAC LAND_CONV [GSYM MEMBER_NOT_EMPTY] THEN
5360   REWRITE_TAC[LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN X_GEN_TAC `c:real^N` THEN
5361   ONCE_REWRITE_TAC[SET_RULE
5362    `{x + y:real^N | x IN s /\ P y} =
5363         {z | ?x y. x IN s /\ P y /\ z = x + y}`] THEN
5364   GEOM_ORIGIN_TAC `c:real^N` THEN REPEAT GEN_TAC THEN
5365   REWRITE_TAC[DOT_RADD; REAL_ARITH `b dot c + a = d <=> a = d - b dot c`] THEN
5366   REWRITE_TAC[IN_INTER; IN_ELIM_THM; DOT_RZERO] THEN
5367   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (SUBST1_TAC o SYM)) THEN
5368   ASM_SIMP_TAC[AFFINE_EQ_SUBSPACE; HULL_INC] THEN STRIP_TAC THEN
5369   REWRITE_TAC[VECTOR_ARITH `c + z:real^N = (c + x) + (c + y) <=>
5370                             z = c + x + y`] THEN
5371   REWRITE_TAC[SET_RULE
5372    `{z | ?x y. x IN s /\ P y /\ z = c + x + y} =
5373     IMAGE (\x. c + x) {x + y:real^N | x IN s /\ y IN {v | P v}}`] THEN
5374   MATCH_MP_TAC(SET_RULE
5375    `!f. (!x. g(f x) = x) /\ s = UNIV ==> IMAGE g s = UNIV`) THEN
5376   EXISTS_TAC `\x:real^N. x - c` THEN
5377   REWRITE_TAC[VECTOR_ARITH `c + x - c:real^N = x`] THEN
5378   MATCH_MP_TAC(MESON[SPAN_EQ_SELF] `subspace s /\ span s = t ==> s = t`) THEN
5379   CONJ_TAC THENL
5380    [ASM_SIMP_TAC[SUBSPACE_SUMS; SUBSPACE_HYPERPLANE];
5381     ALL_TAC] THEN
5382   REWRITE_TAC[GSYM DIM_EQ_FULL] THEN
5383   REWRITE_TAC[GSYM LE_ANTISYM; DIM_SUBSET_UNIV] THEN
5384   MATCH_MP_TAC(ARITH_RULE `m - 1 < n ==> m <= n`) THEN
5385   MATCH_MP_TAC LET_TRANS THEN EXISTS_TAC `dim {x:real^N | a dot x = &0}` THEN
5386   CONJ_TAC THENL [ASM_SIMP_TAC[DIM_HYPERPLANE; LE_REFL]; ALL_TAC] THEN
5387   MATCH_MP_TAC DIM_PSUBSET THEN
5388   ASM_SIMP_TAC[snd(EQ_IMP_RULE(SPEC_ALL SPAN_EQ_SELF));
5389                SUBSPACE_SUMS; SUBSPACE_HYPERPLANE] THEN
5390   REWRITE_TAC[PSUBSET; SUBSET; FORALL_IN_GSPEC] THEN
5391   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN CONJ_TAC THENL
5392    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
5393     MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `x:real^N`] THEN
5394     ASM_SIMP_TAC[SUBSPACE_0; VECTOR_ADD_LID];
5395     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
5396     REWRITE_TAC[NOT_FORALL_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
5397     X_GEN_TAC `x:real^N` THEN SIMP_TAC[IN_DIFF; IN_ELIM_THM] THEN
5398     DISCH_TAC THEN MAP_EVERY EXISTS_TAC [`x:real^N`; `vec 0:real^N`] THEN
5399     ASM_REWRITE_TAC[DOT_RZERO; VECTOR_ADD_RID]]);;
5400
5401 let AFF_DIM_AFFINE_INTER_HYPERPLANE = prove
5402  (`!a b s:real^N->bool.
5403         affine s
5404         ==> aff_dim(s INTER {x | a dot x = b}) =
5405                 if s INTER {v | a dot v = b} = {} then -- &1
5406                 else if s SUBSET {v | a dot v = b} then aff_dim s
5407                 else aff_dim s - &1`,
5408   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THENL
5409    [ASM_REWRITE_TAC[DOT_LZERO] THEN ASM_CASES_TAC `b = &0` THEN
5410     ASM_REWRITE_TAC[EMPTY_GSPEC; INTER_EMPTY; AFF_DIM_EMPTY] THEN
5411     SIMP_TAC[SET_RULE `{x | T} = UNIV`; IN_UNIV; INTER_UNIV; SUBSET_UNIV] THEN
5412     COND_CASES_TAC THEN ASM_REWRITE_TAC[AFF_DIM_EMPTY];
5413     STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[AFF_DIM_EMPTY] THEN
5414     COND_CASES_TAC THENL [AP_TERM_TAC THEN ASM SET_TAC[]; ALL_TAC] THEN
5415     MP_TAC(ISPECL [`s:real^N->bool`; `{x:real^N | a dot x = b}`]
5416         AFF_DIM_SUMS_INTER) THEN
5417     ASM_SIMP_TAC[AFFINE_HYPERPLANE; AFF_DIM_HYPERPLANE] THEN
5418     ASM_SIMP_TAC[AFFINE_HYPERPLANE_SUMS_EQ_UNIV; AFF_DIM_UNIV;
5419                  SET_RULE `~(s SUBSET t) ==> ~(s DIFF t = {})`] THEN
5420     SPEC_TAC(`aff_dim (s INTER {x:real^N | a dot x = b})`,`i:int`) THEN
5421     INT_ARITH_TAC]);;
5422
5423 let AFF_DIM_LT_FULL = prove
5424  (`!s. aff_dim s < &(dimindex(:N)) <=> ~(affine hull s = (:real^N))`,
5425   GEN_TAC THEN REWRITE_TAC[GSYM AFF_DIM_EQ_FULL] THEN
5426   MP_TAC(ISPEC `s:real^N->bool` AFF_DIM_LE_UNIV) THEN ARITH_TAC);;
5427
5428 let AFF_LOWDIM_SUBSET_HYPERPLANE = prove
5429  (`!s:real^N->bool.
5430         aff_dim s < &(dimindex(:N))
5431         ==> ?a b. ~(a = vec 0) /\ s SUBSET {x | a dot x = b}`,
5432   MATCH_MP_TAC SET_PROVE_CASES THEN CONJ_TAC THENL
5433    [DISCH_TAC THEN EXISTS_TAC `basis 1:real^N` THEN
5434     SIMP_TAC[EMPTY_SUBSET; BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1];
5435     MAP_EVERY X_GEN_TAC [`c:real^N`; `s:real^N->bool`] THEN
5436     CONV_TAC(ONCE_DEPTH_CONV(GEN_ALPHA_CONV `a:real^N`)) THEN
5437     GEN_GEOM_ORIGIN_TAC `c:real^N` ["a"] THEN
5438     SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; IN_INSERT; INT_OF_NUM_LT] THEN
5439     REPEAT GEN_TAC THEN DISCH_TAC THEN
5440     DISCH_THEN(MP_TAC o MATCH_MP LOWDIM_SUBSET_HYPERPLANE) THEN
5441     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^N` THEN
5442     STRIP_TAC THEN EXISTS_TAC `(u:real^N) dot c` THEN
5443     ASM_REWRITE_TAC[DOT_RADD; REAL_EQ_ADD_LCANCEL_0] THEN
5444     ASM_MESON_TAC[SPAN_INC; SUBSET_TRANS]]);;
5445
5446 (* ------------------------------------------------------------------------- *)
5447 (* An additional lemma about hyperplanes.                                    *)
5448 (* ------------------------------------------------------------------------- *)
5449
5450 let SUBSET_HYPERPLANES = prove
5451  (`!a b a' b'.
5452         {x | a dot x = b} SUBSET {x | a' dot x = b'} <=>
5453         {x | a dot x = b} = {} \/ {x | a' dot x = b'} = (:real^N) \/
5454         {x | a dot x = b} = {x | a' dot x = b'}`,
5455   REPEAT GEN_TAC THEN
5456   ASM_CASES_TAC `{x:real^N | a dot x = b} = {}` THEN
5457   ASM_REWRITE_TAC[EMPTY_SUBSET] THEN
5458   ASM_CASES_TAC `{x | a' dot x = b'} = (:real^N)` THEN
5459   ASM_REWRITE_TAC[SUBSET_UNIV] THEN
5460   RULE_ASSUM_TAC(REWRITE_RULE
5461    [HYPERPLANE_EQ_EMPTY; HYPERPLANE_EQ_UNIV]) THEN
5462   REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
5463   ASM_CASES_TAC `{x:real^N | a dot x = b} SUBSET {x | a' dot x = b'}` THEN
5464   ASM_REWRITE_TAC[] THEN
5465   MP_TAC(ISPECL [`{x:real^N | a dot x = b}`; `{x:real^N | a' dot x = b'}`]
5466         AFF_DIM_PSUBSET) THEN
5467   ASM_SIMP_TAC[PSUBSET;
5468                REWRITE_RULE[GSYM AFFINE_HULL_EQ] AFFINE_HYPERPLANE] THEN
5469   ASM_CASES_TAC `{x:real^N | a dot x = b} = {x | a' dot x = b'}` THEN
5470   ASM_REWRITE_TAC[SUBSET_REFL] THEN ASM_CASES_TAC `a':real^N = vec 0` THENL
5471    [ASM_CASES_TAC `b' = &0` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
5472     ASM_REWRITE_TAC[DOT_LZERO] THEN SET_TAC[];
5473     ALL_TAC] THEN
5474   ASM_CASES_TAC `a:real^N = vec 0` THENL
5475    [ASM_CASES_TAC `b = &0` THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
5476     ASM_REWRITE_TAC[DOT_LZERO] THEN SET_TAC[];
5477     ALL_TAC] THEN
5478   ASM_SIMP_TAC[AFF_DIM_HYPERPLANE; INT_LT_REFL]);;
5479
5480 (* ------------------------------------------------------------------------- *)
5481 (* Openness and compactness are preserved by convex hull operation.          *)
5482 (* ------------------------------------------------------------------------- *)
5483
5484 let OPEN_CONVEX_HULL = prove
5485  (`!s:real^N->bool. open s ==> open(convex hull s)`,
5486   REPEAT GEN_TAC THEN
5487   REWRITE_TAC[CONVEX_HULL_EXPLICIT; OPEN_CONTAINS_CBALL] THEN
5488   REWRITE_TAC[IN_ELIM_THM; SUBSET; LEFT_IMP_EXISTS_THM] THEN DISCH_TAC THEN
5489   MAP_EVERY X_GEN_TAC [`a:real^N`; `t:real^N->bool`; `u:real^N->real`] THEN
5490   STRIP_TAC THEN
5491   SUBGOAL_THEN `?b. !x:real^N. x IN t ==> &0 < b(x) /\ cball(x,b(x)) SUBSET s`
5492   STRIP_ASSUME_TAC THENL
5493    [REWRITE_TAC[GSYM SKOLEM_THM] THEN ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
5494   ABBREV_TAC `i = IMAGE (b:real^N->real) t` THEN
5495   EXISTS_TAC `inf i` THEN MP_TAC(SPEC `i:real->bool` INF_FINITE) THEN
5496   EXPAND_TAC "i" THEN ASM_REWRITE_TAC[FORALL_IN_IMAGE; IN_IMAGE] THEN
5497   ANTS_TAC THENL
5498    [EXPAND_TAC "i" THEN CONJ_TAC THENL
5499      [ASM_SIMP_TAC[FINITE_IMAGE]; ALL_TAC] THEN
5500     REWRITE_TAC[IMAGE_EQ_EMPTY] THEN
5501     ASM_MESON_TAC[SUM_CLAUSES; REAL_ARITH `~(&1 = &0)`];
5502     ALL_TAC] THEN
5503   STRIP_TAC THEN CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
5504   X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_CBALL; dist] THEN
5505   DISCH_TAC THEN EXISTS_TAC `IMAGE (\v:real^N. v + (y - a)) t` THEN
5506   EXISTS_TAC `\v. (u:real^N->real)(v - (y - a))` THEN
5507   ASM_SIMP_TAC[FINITE_IMAGE; FORALL_IN_IMAGE; SUM_IMAGE; VSUM_IMAGE;
5508                VECTOR_ARITH `v + a:real^N = w + a <=> v = w`] THEN
5509   ASM_REWRITE_TAC[o_DEF; VECTOR_ARITH `(v + a) - a:real^N = v`] THEN
5510   ASM_REWRITE_TAC[VECTOR_ADD_LDISTRIB; ETA_AX] THEN
5511   ASM_SIMP_TAC[VSUM_ADD; VSUM_RMUL] THEN
5512   CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
5513   X_GEN_TAC `z:real^N` THEN STRIP_TAC THEN
5514   SUBGOAL_THEN `z + (y - a) IN cball(z:real^N,b z)`
5515    (fun th -> ASM_MESON_TAC[th; SUBSET]) THEN
5516   REWRITE_TAC[IN_CBALL; dist; NORM_ARITH
5517    `norm(z - (z + a - y)) = norm(y - a)`] THEN
5518   ASM_MESON_TAC[REAL_LE_TRANS]);;
5519
5520 let COMPACT_CONVEX_COMBINATIONS = prove
5521  (`!s t. compact s /\ compact t
5522          ==> compact { (&1 - u) % x + u % y :real^N |
5523                       &0 <= u /\ u <= &1 /\ x IN s /\ y IN t}`,
5524   REPEAT STRIP_TAC THEN SUBGOAL_THEN
5525    `{ (&1 - u) % x + u % y :real^N | &0 <= u /\ u <= &1 /\ x IN s /\ y IN t} =
5526     IMAGE (\z. (&1 - drop(fstcart z)) % fstcart(sndcart z) +
5527                drop(fstcart z) % sndcart(sndcart z))
5528           { pastecart u w | u IN interval[vec 0,vec 1] /\
5529                             w IN { pastecart x y | x IN s /\ y IN t} }`
5530   SUBST1_TAC THENL
5531    [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE] THEN
5532     X_GEN_TAC `x:real^N` THEN
5533     REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
5534     CONV_TAC(ONCE_DEPTH_CONV UNWIND_CONV) THEN
5535     REWRITE_TAC[FSTCART_PASTECART; SNDCART_PASTECART] THEN
5536     REWRITE_TAC[IN_INTERVAL_1; GSYM EXISTS_DROP; DROP_VEC] THEN MESON_TAC[];
5537     ALL_TAC] THEN
5538   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
5539   ASM_SIMP_TAC[COMPACT_PCROSS; GSYM PCROSS; COMPACT_INTERVAL] THEN
5540   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
5541   X_GEN_TAC `z:real^(1,(N,N)finite_sum)finite_sum` THEN
5542   DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[PCROSS] THEN
5543   MATCH_MP_TAC CONTINUOUS_ADD THEN CONJ_TAC THEN
5544   MATCH_MP_TAC CONTINUOUS_MUL THEN REWRITE_TAC[o_DEF; LIFT_SUB; LIFT_DROP] THEN
5545   CONJ_TAC THEN TRY(MATCH_MP_TAC CONTINUOUS_SUB) THEN
5546   REWRITE_TAC[CONTINUOUS_CONST] THEN
5547   MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
5548   REWRITE_TAC[LINEAR_FSTCART; LINEAR_SNDCART; ETA_AX] THEN
5549   GEN_REWRITE_TAC RAND_CONV [GSYM o_DEF] THEN
5550   MATCH_MP_TAC LINEAR_COMPOSE THEN
5551   REWRITE_TAC[LINEAR_FSTCART; LINEAR_SNDCART]);;
5552
5553 let COMPACT_CONVEX_HULL = prove
5554  (`!s:real^N->bool. compact s ==> compact(convex hull s)`,
5555   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[CARATHEODORY] THEN
5556   SPEC_TAC(`dimindex(:N) + 1`,`n:num`) THEN
5557   ASM_CASES_TAC `s:real^N->bool = {}` THENL
5558    [ASM_REWRITE_TAC[SUBSET_EMPTY] THEN
5559     CONV_TAC(ONCE_DEPTH_CONV UNWIND_CONV) THEN
5560     REWRITE_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY] THEN
5561     REWRITE_TAC[SET_RULE `{x | F} = {}`; COMPACT_EMPTY];
5562     ALL_TAC] THEN
5563   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
5564   DISCH_THEN(X_CHOOSE_TAC `w:real^N`) THEN INDUCT_TAC THENL
5565    [SUBGOAL_THEN
5566      `{x:real^N | ?t. FINITE t /\ t SUBSET s /\ CARD t <= 0 /\
5567                       x IN convex hull t} = {}`
5568      (fun th -> REWRITE_TAC[th; COMPACT_EMPTY]) THEN
5569     REWRITE_TAC[EXTENSION; NOT_IN_EMPTY; LE; IN_ELIM_THM] THEN
5570     MESON_TAC[CARD_EQ_0; CONVEX_HULL_EMPTY; NOT_IN_EMPTY];
5571     ALL_TAC] THEN
5572   ASM_CASES_TAC `n = 0` THENL
5573    [ASM_REWRITE_TAC[ARITH_RULE `s <= SUC 0 <=> s = 0 \/ s = 1`] THEN
5574     UNDISCH_TAC `compact(s:real^N->bool)` THEN
5575     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
5576     REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
5577     REWRITE_TAC[TAUT `a /\ b /\ (c \/ d) /\ e <=>
5578                       (a /\ c) /\ (b /\ e) \/ (a /\ d) /\ (b /\ e)`] THEN
5579     REWRITE_TAC[GSYM HAS_SIZE; num_CONV `1`; HAS_SIZE_CLAUSES] THEN
5580     REWRITE_TAC[EXISTS_OR_THM; LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
5581     CONV_TAC(TOP_DEPTH_CONV UNWIND_CONV) THEN
5582     REWRITE_TAC[NOT_IN_EMPTY; CONVEX_HULL_EMPTY] THEN
5583     REWRITE_TAC[CONVEX_HULL_SING] THEN SET_TAC[];
5584     ALL_TAC] THEN
5585   SUBGOAL_THEN
5586    `{x:real^N | ?t. FINITE t /\ t SUBSET s /\ CARD t <= SUC n /\
5587                     x IN convex hull t} =
5588     { (&1 - u) % x + u % y :real^N |
5589                       &0 <= u /\ u <= &1 /\ x IN s /\
5590                       y IN {x | ?t. FINITE t /\ t SUBSET s /\
5591                                     CARD t <= n /\ x IN convex hull t}}`
5592    (fun th -> ASM_SIMP_TAC[th; COMPACT_CONVEX_COMBINATIONS]) THEN
5593   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
5594   X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
5595    [ALL_TAC;
5596     REWRITE_TAC[LEFT_IMP_EXISTS_THM; RIGHT_AND_EXISTS_THM;
5597                 LEFT_AND_EXISTS_THM] THEN
5598     MAP_EVERY X_GEN_TAC [`u:real^N`; `c:real`; `v:real^N`;
5599                          `t:real^N->bool`] THEN
5600     STRIP_TAC THEN EXISTS_TAC `(u:real^N) INSERT t` THEN
5601     ASM_REWRITE_TAC[FINITE_INSERT; INSERT_SUBSET] THEN
5602     ASM_SIMP_TAC[CARD_CLAUSES] THEN CONJ_TAC THENL
5603      [ASM_ARITH_TAC; ALL_TAC] THEN
5604     MATCH_MP_TAC IN_CONVEX_SET THEN
5605     ASM_REWRITE_TAC[CONVEX_CONVEX_HULL] THEN CONJ_TAC THEN
5606     ASM_MESON_TAC[HULL_SUBSET; SUBSET; IN_INSERT; HULL_MONO]] THEN
5607   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
5608   ASM_CASES_TAC `CARD(t:real^N->bool) <= n` THENL
5609    [MAP_EVERY EXISTS_TAC [`w:real^N`; `&1`; `x:real^N`] THEN
5610     ASM_REWRITE_TAC[REAL_POS; REAL_LE_REFL] THEN
5611     CONJ_TAC THENL [ASM_MESON_TAC[]; VECTOR_ARITH_TAC];
5612     ALL_TAC] THEN
5613   SUBGOAL_THEN `(t:real^N->bool) HAS_SIZE (SUC n)` MP_TAC THENL
5614    [ASM_REWRITE_TAC[HAS_SIZE] THEN ASM_ARITH_TAC;
5615     ALL_TAC] THEN
5616   REWRITE_TAC[HAS_SIZE_CLAUSES] THEN
5617   DISCH_THEN(X_CHOOSE_THEN `a:real^N` (X_CHOOSE_THEN `u:real^N->bool`
5618     STRIP_ASSUME_TAC)) THEN
5619   FIRST_X_ASSUM SUBST_ALL_TAC THEN
5620   UNDISCH_TAC `(x:real^N) IN convex hull (a INSERT u)` THEN
5621   RULE_ASSUM_TAC(REWRITE_RULE[FINITE_INSERT]) THEN
5622   ASM_CASES_TAC `(u:real^N->bool) = {}` THENL
5623    [ASM_REWRITE_TAC[CONVEX_HULL_SING; IN_SING] THEN
5624     DISCH_THEN SUBST_ALL_TAC THEN
5625     MAP_EVERY EXISTS_TAC [`a:real^N`; `&1`; `a:real^N`] THEN
5626     ASM_REWRITE_TAC[REAL_POS; REAL_LE_REFL] THEN
5627     CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
5628     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5629     EXISTS_TAC `{a:real^N}` THEN SIMP_TAC[FINITE_RULES] THEN
5630     REWRITE_TAC[CONVEX_HULL_SING; IN_SING] THEN
5631     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5632     SIMP_TAC[CARD_CLAUSES; FINITE_RULES; NOT_IN_EMPTY] THEN
5633     UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC;
5634     ALL_TAC] THEN
5635   ASM_SIMP_TAC[CONVEX_HULL_INSERT; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
5636   MAP_EVERY X_GEN_TAC [`c:real`; `d:real`; `z:real^N`] THEN STRIP_TAC THEN
5637   MAP_EVERY EXISTS_TAC [`a:real^N`; `d:real`; `z:real^N`] THEN
5638   FIRST_X_ASSUM(SUBST_ALL_TAC o MATCH_MP (REAL_ARITH
5639    `c + d = &1 ==> c = (&1 - d)`)) THEN
5640   ASM_REWRITE_TAC[REAL_ARITH `d <= &1 <=> &0 <= &1 - d`] THEN
5641   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5642   EXISTS_TAC `u:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
5643   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5644   UNDISCH_TAC `CARD ((a:real^N) INSERT u) <= SUC n` THEN
5645   ASM_SIMP_TAC[CARD_CLAUSES; LE_SUC]);;
5646
5647 let FINITE_IMP_COMPACT_CONVEX_HULL = prove
5648  (`!s:real^N->bool. FINITE s ==> compact(convex hull s)`,
5649   SIMP_TAC[FINITE_IMP_COMPACT; COMPACT_CONVEX_HULL]);;
5650
5651 (* ------------------------------------------------------------------------- *)
5652 (* Extremal points of a simplex are some vertices.                           *)
5653 (* ------------------------------------------------------------------------- *)
5654
5655 let DIST_INCREASES_ONLINE = prove
5656  (`!a b d. ~(d = vec 0)
5657            ==> dist(a,b + d) > dist(a,b) \/ dist(a,b - d) > dist(a,b)`,
5658   REWRITE_TAC[dist; vector_norm; real_gt; GSYM NORM_POS_LT] THEN
5659   SIMP_TAC[SQRT_MONO_LT_EQ; DOT_POS_LE; SQRT_LT_0] THEN
5660   REWRITE_TAC[DOT_RSUB; DOT_RADD; DOT_LSUB; DOT_LADD] THEN REAL_ARITH_TAC);;
5661
5662 let NORM_INCREASES_ONLINE = prove
5663  (`!a:real^N d. ~(d = vec 0)
5664                 ==> norm(a + d) > norm(a) \/ norm(a - d) > norm(a)`,
5665   MP_TAC(ISPEC `vec 0 :real^N` DIST_INCREASES_ONLINE) THEN
5666   REWRITE_TAC[dist; VECTOR_SUB_LZERO; NORM_NEG]);;
5667
5668 let SIMPLEX_FURTHEST_LT = prove
5669  (`!a:real^N s.
5670         FINITE s
5671         ==> !x. x IN (convex hull s) /\ ~(x IN s)
5672                 ==> ?y. y IN (convex hull s) /\ norm(x - a) < norm(y - a)`,
5673   GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5674   REWRITE_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY] THEN
5675   MAP_EVERY X_GEN_TAC [`x:real^N`; `s:real^N->bool`] THEN
5676   ASM_CASES_TAC `s:real^N->bool = {}` THENL
5677    [ASM_REWRITE_TAC[CONVEX_HULL_SING; IN_SING] THEN MESON_TAC[];
5678     ALL_TAC] THEN
5679   ASM_SIMP_TAC[CONVEX_HULL_INSERT] THEN
5680   STRIP_TAC THEN X_GEN_TAC `y:real^N` THEN
5681   REWRITE_TAC[IN_ELIM_THM; LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
5682   MAP_EVERY X_GEN_TAC [`u:real`; `v:real`; `b:real^N`] THEN
5683   ASM_CASES_TAC `y:real^N IN (convex hull s)` THENL
5684    [REWRITE_TAC[IN_INSERT; DE_MORGAN_THM] THEN STRIP_TAC THEN
5685     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN
5686     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN
5687     X_GEN_TAC `c:real^N` THEN STRIP_TAC THEN
5688     MAP_EVERY EXISTS_TAC [`&0`; `&1`; `c:real^N`] THEN
5689     ASM_REWRITE_TAC[REAL_ADD_LID; REAL_POS] THEN VECTOR_ARITH_TAC;
5690     ALL_TAC] THEN
5691   ASM_CASES_TAC `u = &0` THENL
5692    [ASM_SIMP_TAC[REAL_ADD_LID; VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN
5693     ASM_MESON_TAC[VECTOR_MUL_LID];
5694     ALL_TAC] THEN
5695   ASM_CASES_TAC `v = &0` THENL
5696    [ASM_SIMP_TAC[REAL_ADD_RID; VECTOR_MUL_LZERO; VECTOR_ADD_RID] THEN
5697     ASM_CASES_TAC `u = &1` THEN ASM_REWRITE_TAC[VECTOR_MUL_LID] THEN
5698     ASM_CASES_TAC `y = a:real^N` THEN ASM_REWRITE_TAC[IN_INSERT] THEN
5699     ASM_MESON_TAC[];
5700     ALL_TAC] THEN
5701   REWRITE_TAC[IN_INSERT; DE_MORGAN_THM] THEN STRIP_TAC THEN
5702   MP_TAC(SPECL [`u:real`; `v:real`] REAL_DOWN2) THEN ANTS_TAC THENL
5703    [ASM_REWRITE_TAC[REAL_LT_LE]; ALL_TAC] THEN
5704   DISCH_THEN(X_CHOOSE_THEN `w:real` STRIP_ASSUME_TAC) THEN
5705   MP_TAC(ISPECL [`a:real^N`; `y:real^N`; `w % (x - b):real^N`]
5706                 DIST_INCREASES_ONLINE) THEN
5707   ANTS_TAC THENL
5708    [ASM_SIMP_TAC[VECTOR_MUL_EQ_0; REAL_LT_IMP_NZ] THEN
5709     REWRITE_TAC[VECTOR_ARITH `(x - y = vec 0) <=> (x = y)`] THEN
5710     DISCH_THEN SUBST_ALL_TAC THEN
5711     UNDISCH_TAC `~(y:real^N IN convex hull s)` THEN
5712     ASM_REWRITE_TAC[GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID];
5713     ALL_TAC] THEN
5714   ASM_REWRITE_TAC[dist; real_gt] THEN
5715   REWRITE_TAC[VECTOR_ARITH
5716    `((u % x + v % b) + w % (x - b) = (u + w) % x + (v - w) % b) /\
5717     ((u % x + v % b) - w % (x - b) = (u - w) % x + (v + w) % b)`] THEN
5718   STRIP_TAC THENL
5719    [MAP_EVERY EXISTS_TAC
5720      [`(u + w) % x + (v - w) % b:real^N`; `u + w`; `v - w`; `b:real^N`];
5721     MAP_EVERY EXISTS_TAC
5722      [`(u - w) % x + (v + w) % b:real^N`; `u - w`; `v + w`; `b:real^N`]] THEN
5723   ONCE_REWRITE_TAC[NORM_SUB] THEN ASM_REWRITE_TAC[] THEN
5724   ASM_SIMP_TAC[REAL_LE_ADD; REAL_LT_IMP_LE; REAL_SUB_LE] THEN
5725   UNDISCH_TAC `u + v = &1` THEN REAL_ARITH_TAC);;
5726
5727 let SIMPLEX_FURTHEST_LE = prove
5728  (`!a:real^N s.
5729         FINITE s /\ ~(s = {})
5730         ==> ?y. y IN s /\
5731                 !x. x IN (convex hull s) ==> norm(x - a) <= norm(y - a)`,
5732   REPEAT GEN_TAC THEN DISCH_TAC THEN
5733   MP_TAC(ISPEC `convex hull (s:real^N->bool)` DISTANCE_ATTAINS_SUP) THEN
5734   DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN ANTS_TAC THENL
5735    [ASM_SIMP_TAC[FINITE_IMP_COMPACT_CONVEX_HULL] THEN
5736     ASM_MESON_TAC[SUBSET_EMPTY; HULL_SUBSET];
5737     ALL_TAC] THEN
5738   ONCE_REWRITE_TAC[DIST_SYM] THEN REWRITE_TAC[dist] THEN
5739   ASM_MESON_TAC[SIMPLEX_FURTHEST_LT; REAL_NOT_LE]);;
5740
5741 let SIMPLEX_FURTHEST_LE_EXISTS = prove
5742  (`!a:real^N s.
5743         FINITE s
5744         ==> !x. x IN (convex hull s)
5745                 ==> ?y. y IN s /\ norm(x - a) <= norm(y - a)`,
5746   MESON_TAC[NOT_IN_EMPTY; CONVEX_HULL_EMPTY; SIMPLEX_FURTHEST_LE]);;
5747
5748 let SIMPLEX_EXTREMAL_LE = prove
5749  (`!s:real^N->bool.
5750         FINITE s /\ ~(s = {})
5751          ==> ?u v. u IN s /\ v IN s /\
5752                    !x y. x IN convex hull s /\ y IN convex hull s
5753                          ==> norm(x - y) <= norm(u - v)`,
5754   REPEAT STRIP_TAC THEN
5755   MP_TAC(ISPEC `convex hull (s:real^N->bool)` COMPACT_SUP_MAXDISTANCE) THEN
5756   ANTS_TAC THENL
5757    [ASM_SIMP_TAC[FINITE_IMP_COMPACT_CONVEX_HULL] THEN
5758     ASM_MESON_TAC[SUBSET_EMPTY; HULL_SUBSET];
5759     ALL_TAC] THEN
5760   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
5761   SIMP_TAC[] THEN ASM_MESON_TAC[SIMPLEX_FURTHEST_LT; REAL_NOT_LE; NORM_SUB]);;
5762
5763 let SIMPLEX_EXTREMAL_LE_EXISTS = prove
5764  (`!s:real^N->bool x y. FINITE s /\ x IN convex hull s /\ y IN convex hull s
5765                         ==> ?u v. u IN s /\ v IN s /\
5766                                   norm(x - y) <= norm(u - v)`,
5767   MESON_TAC[NOT_IN_EMPTY; CONVEX_HULL_EMPTY; SIMPLEX_EXTREMAL_LE]);;
5768
5769 let DIAMETER_CONVEX_HULL = prove
5770  (`!s:real^N->bool. diameter(convex hull s) = diameter s`,
5771   let lemma = prove
5772    (`!a b s. (!x. x IN s ==> dist(a,x) <= b)
5773              ==> (!x. x IN convex hull s ==> dist(a,x) <= b)`,
5774     REPEAT GEN_TAC THEN DISCH_TAC THEN
5775     MATCH_MP_TAC HULL_INDUCT THEN ASM_REWRITE_TAC[GSYM cball; CONVEX_CBALL]) in
5776   GEN_TAC THEN REWRITE_TAC[diameter; CONVEX_HULL_EQ_EMPTY] THEN
5777   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUP_EQ THEN
5778   REWRITE_TAC[FORALL_IN_GSPEC] THEN X_GEN_TAC `b:real` THEN
5779   EQ_TAC THENL [MESON_TAC[SUBSET; HULL_SUBSET]; ALL_TAC] THEN
5780   MATCH_MP_TAC(TAUT `!b. (a ==> b) /\ (b ==> c) ==> a ==> c`) THEN
5781   EXISTS_TAC `!x:real^N y. x IN s /\ y IN convex hull s ==> norm(x - y) <= b`
5782   THEN CONJ_TAC THENL
5783    [MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `x:real^N` THEN
5784     ASM_CASES_TAC `(x:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
5785     REWRITE_TAC[GSYM dist; lemma];
5786     ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
5787     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `y:real^N` THEN
5788     ASM_CASES_TAC `(y:real^N) IN convex hull s` THEN ASM_REWRITE_TAC[] THEN
5789     REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[DIST_SYM] dist); lemma]]);;
5790
5791 let DIAMETER_SIMPLEX = prove
5792  (`!s:real^N->bool.
5793         ~(s = {})
5794         ==> diameter(convex hull s) = sup { dist(x,y) | x IN s /\ y IN s}`,
5795   REWRITE_TAC[DIAMETER_CONVEX_HULL] THEN SIMP_TAC[diameter; dist]);;
5796
5797 (* ------------------------------------------------------------------------- *)
5798 (* Closest point of a convex set is unique, with a continuous projection.    *)
5799 (* ------------------------------------------------------------------------- *)
5800
5801 let CLOSER_POINTS_LEMMA = prove
5802  (`!y:real^N z.
5803         y dot z > &0
5804         ==> ?u. &0 < u /\
5805                 !v. &0 < v /\ v <= u ==> norm(v % z - y) < norm y`,
5806   REWRITE_TAC[NORM_LT; DOT_LSUB; DOT_RSUB; DOT_LMUL; DOT_RMUL;
5807               REAL_SUB_LDISTRIB; real_gt] THEN REPEAT GEN_TAC THEN
5808   REWRITE_TAC[REAL_ARITH `(a - b) - (c - d) < d <=> a < b + c`] THEN
5809   STRIP_TAC THEN SUBST1_TAC(VECTOR_ARITH `(z:real^N) dot y = y dot z`) THEN
5810   SIMP_TAC[GSYM REAL_ADD_LDISTRIB; REAL_LT_LMUL_EQ] THEN
5811   EXISTS_TAC `(y dot (z:real^N)) / (z dot z)` THEN
5812   SUBGOAL_THEN `&0 < z dot (z:real^N)` ASSUME_TAC THENL
5813    [ASM_MESON_TAC[DOT_POS_LT; DOT_RZERO; REAL_LT_REFL]; ALL_TAC] THEN
5814   ASM_SIMP_TAC[REAL_LT_DIV; REAL_LE_RDIV_EQ] THEN
5815   ASM_SIMP_TAC[REAL_ARITH `&0 < y /\ x <= y ==> x < y + y`; REAL_LT_MUL]);;
5816
5817 let CLOSER_POINT_LEMMA = prove
5818  (`!x y z. (y - x) dot (z - x) > &0
5819            ==> ?u. &0 < u /\ u <= &1 /\ dist(x + u % (z - x),y) < dist(x,y)`,
5820   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP CLOSER_POINTS_LEMMA) THEN
5821   ONCE_REWRITE_TAC[DIST_SYM] THEN REWRITE_TAC[dist; NORM_LT] THEN
5822   REWRITE_TAC[VECTOR_ARITH
5823    `(y - (x + z)) dot (y - (x + z)) = (z - (y - x)) dot (z - (y - x))`] THEN
5824   DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
5825   EXISTS_TAC `min u (&1)` THEN
5826   ASM_SIMP_TAC[REAL_LT_MIN; REAL_MIN_LE; REAL_LT_01; REAL_LE_REFL]);;
5827
5828 let ANY_CLOSEST_POINT_DOT = prove
5829  (`!s a x y:real^N.
5830         convex s /\ closed s /\ x IN s /\ y IN s /\
5831         (!z. z IN s ==> dist(a,x) <= dist(a,z))
5832         ==> (a - x) dot (y - x) <= &0`,
5833   REPEAT STRIP_TAC THEN REWRITE_TAC[REAL_ARITH `x <= &0 <=> ~(x > &0)`] THEN
5834   DISCH_THEN(MP_TAC o MATCH_MP CLOSER_POINT_LEMMA) THEN
5835   DISCH_THEN(X_CHOOSE_THEN `u:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5836   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5837   REWRITE_TAC[REAL_NOT_LT] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
5838   FIRST_X_ASSUM MATCH_MP_TAC THEN
5839   REWRITE_TAC[VECTOR_ARITH `x + u % (y - x) = (&1 - u) % x + u % y`] THEN
5840   MATCH_MP_TAC IN_CONVEX_SET THEN ASM_SIMP_TAC[REAL_LT_IMP_LE]);;
5841
5842 let ANY_CLOSEST_POINT_UNIQUE = prove
5843  (`!s a x y:real^N.
5844         convex s /\ closed s /\ x IN s /\ y IN s /\
5845         (!z. z IN s ==> dist(a,x) <= dist(a,z)) /\
5846         (!z. z IN s ==> dist(a,y) <= dist(a,z))
5847         ==> x = y`,
5848   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
5849   REWRITE_TAC[GSYM NORM_LE_0; NORM_LE_SQUARE] THEN
5850   SUBGOAL_THEN `(a - x:real^N) dot (y - x) <= &0 /\ (a - y) dot (x - y) <= &0`
5851   MP_TAC THENL [ASM_MESON_TAC[ANY_CLOSEST_POINT_DOT]; ALL_TAC] THEN
5852   REWRITE_TAC[NORM_LT; DOT_LSUB; DOT_RSUB] THEN REAL_ARITH_TAC);;
5853
5854 let CLOSEST_POINT_UNIQUE = prove
5855  (`!s a x:real^N.
5856         convex s /\ closed s /\ x IN s /\
5857         (!z. z IN s ==> dist(a,x) <= dist(a,z))
5858         ==> x = closest_point s a`,
5859   REPEAT STRIP_TAC THEN MATCH_MP_TAC ANY_CLOSEST_POINT_UNIQUE THEN
5860   MAP_EVERY EXISTS_TAC [`s:real^N->bool`; `a:real^N`] THEN
5861   ASM_MESON_TAC[CLOSEST_POINT_EXISTS; MEMBER_NOT_EMPTY]);;
5862
5863 let CLOSEST_POINT_DOT = prove
5864  (`!s a x:real^N.
5865         convex s /\ closed s /\ x IN s
5866         ==> (a - closest_point s a) dot (x - closest_point s a) <= &0`,
5867   REPEAT STRIP_TAC THEN MATCH_MP_TAC ANY_CLOSEST_POINT_DOT THEN
5868   EXISTS_TAC `s:real^N->bool` THEN
5869   ASM_MESON_TAC[CLOSEST_POINT_EXISTS; MEMBER_NOT_EMPTY]);;
5870
5871 let CLOSEST_POINT_LT = prove
5872  (`!s a x. convex s /\ closed s /\ x IN s /\ ~(x = closest_point s a)
5873            ==> dist(a,closest_point s a) < dist(a,x)`,
5874   REPEAT GEN_TAC THEN
5875   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5876   REWRITE_TAC[GSYM REAL_NOT_LE; CONTRAPOS_THM] THEN
5877   DISCH_TAC THEN MATCH_MP_TAC CLOSEST_POINT_UNIQUE THEN
5878   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[CLOSEST_POINT_LE; REAL_LE_TRANS]);;
5879
5880 let CLOSEST_POINT_LIPSCHITZ = prove
5881  (`!s x y:real^N.
5882         convex s /\ closed s /\ ~(s = {})
5883         ==> dist(closest_point s x,closest_point s y) <= dist(x,y)`,
5884   REPEAT STRIP_TAC THEN REWRITE_TAC[dist; NORM_LE] THEN
5885   SUBGOAL_THEN
5886    `(x - closest_point s x :real^N) dot
5887     (closest_point s y - closest_point s x) <= &0 /\
5888     (y - closest_point s y) dot
5889     (closest_point s x - closest_point s y) <= &0`
5890   MP_TAC THENL
5891    [CONJ_TAC THEN MATCH_MP_TAC ANY_CLOSEST_POINT_DOT THEN
5892     EXISTS_TAC `s:real^N->bool` THEN ASM_MESON_TAC[CLOSEST_POINT_EXISTS];
5893     MP_TAC(ISPEC `(x - closest_point s x :real^N) - (y - closest_point s y)`
5894                  DOT_POS_LE) THEN
5895     REWRITE_TAC[NORM_LT; DOT_LSUB; DOT_RSUB; DOT_SYM] THEN REAL_ARITH_TAC]);;
5896
5897 let CONTINUOUS_AT_CLOSEST_POINT = prove
5898  (`!s x. convex s /\ closed s /\ ~(s = {})
5899          ==> (closest_point s) continuous (at x)`,
5900   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_at] THEN
5901   ASM_MESON_TAC[CLOSEST_POINT_LIPSCHITZ; REAL_LET_TRANS]);;
5902
5903 let CONTINUOUS_ON_CLOSEST_POINT = prove
5904  (`!s t. convex s /\ closed s /\ ~(s = {})
5905          ==> (closest_point s) continuous_on t`,
5906   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CLOSEST_POINT]);;
5907
5908 (* ------------------------------------------------------------------------- *)
5909 (* Relating closest points and orthogonality.                                *)
5910 (* ------------------------------------------------------------------------- *)
5911
5912 let ANY_CLOSEST_POINT_AFFINE_ORTHOGONAL = prove
5913  (`!s a b:real^N.
5914         affine s /\ b IN s /\ (!x. x IN s ==> dist(a,b) <= dist(a,x))
5915         ==> (!x. x IN s ==> orthogonal (x - b) (a - b))`,
5916   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `b:real^N` THEN
5917   REWRITE_TAC[DIST_0; VECTOR_SUB_RZERO; orthogonal; dist; NORM_LE] THEN
5918   REWRITE_TAC[DOT_LSUB] THEN REWRITE_TAC[DOT_RSUB] THEN
5919   REWRITE_TAC[DOT_SYM; REAL_ARITH `a <= a - y - (y - x) <=> &2 * y <= x`] THEN
5920   REPEAT STRIP_TAC THEN ASM_CASES_TAC `x:real^N = vec 0` THEN
5921   ASM_REWRITE_TAC[DOT_RZERO] THEN FIRST_X_ASSUM(fun th ->
5922    MP_TAC(SPEC `vec 0 + --((a dot x) / (x dot x)) % (x - vec 0:real^N)` th) THEN
5923    MP_TAC(SPEC `vec 0 + (a dot x) / (x dot x) % (x - vec 0:real^N)` th)) THEN
5924   ASM_SIMP_TAC[IN_AFFINE_ADD_MUL_DIFF] THEN
5925   REWRITE_TAC[VECTOR_SUB_RZERO; VECTOR_ADD_LID; DOT_RMUL] THEN
5926   REWRITE_TAC[DOT_LMUL; IMP_IMP] THEN DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
5927    `&2 * x * a <= b * c * z /\ &2 * --x * a <= --b * --c * z
5928     ==> &2 * abs(x * a) <= b * c * z`)) THEN
5929   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
5930   ASM_SIMP_TAC[REAL_NOT_LE; REAL_DIV_RMUL; DOT_EQ_0] THEN
5931   MATCH_MP_TAC(REAL_ARITH `~(x = &0) ==> x < &2 * abs x`) THEN
5932   RULE_ASSUM_TAC(REWRITE_RULE[GSYM DOT_EQ_0]) THEN
5933   REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD);;
5934
5935 let ORTHOGONAL_ANY_CLOSEST_POINT = prove
5936  (`!s a b:real^N.
5937         b IN s /\ (!x. x IN s ==> orthogonal (x - b) (a - b))
5938         ==> (!x. x IN s ==> dist(a,b) <= dist(a,x))`,
5939   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `b:real^N` THEN
5940   REWRITE_TAC[dist; NORM_LE; orthogonal; VECTOR_SUB_RZERO] THEN
5941   SIMP_TAC[DOT_LSUB; DOT_RSUB; DOT_SYM] THEN
5942   REWRITE_TAC[DOT_POS_LE; REAL_ARITH `a <= a - &0 - (&0 - x) <=> &0 <= x`]);;
5943
5944 let CLOSEST_POINT_AFFINE_ORTHOGONAL = prove
5945  (`!s a:real^N x.
5946         affine s /\ ~(s = {}) /\ x IN s
5947         ==> orthogonal (x - closest_point s a) (a - closest_point s a)`,
5948   GEN_TAC THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
5949   DISCH_TAC THEN DISCH_TAC THEN GEN_TAC THEN
5950   MATCH_MP_TAC ANY_CLOSEST_POINT_AFFINE_ORTHOGONAL THEN
5951   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CLOSEST_POINT_EXISTS THEN
5952   ASM_SIMP_TAC[CLOSED_AFFINE]);;
5953
5954 let CLOSEST_POINT_AFFINE_ORTHOGONAL_EQ = prove
5955  (`!s a b:real^N.
5956         affine s /\ b IN s
5957         ==> (closest_point s a = b <=>
5958              !x. x IN s ==> orthogonal (x - b) (a - b))`,
5959   REPEAT STRIP_TAC THEN EQ_TAC THENL
5960    [ASM_MESON_TAC[CLOSEST_POINT_AFFINE_ORTHOGONAL; MEMBER_NOT_EMPTY];
5961     DISCH_TAC THEN CONV_TAC SYM_CONV THEN
5962     MATCH_MP_TAC CLOSEST_POINT_UNIQUE THEN
5963     ASM_SIMP_TAC[CLOSED_AFFINE; AFFINE_IMP_CONVEX] THEN
5964     MATCH_MP_TAC ORTHOGONAL_ANY_CLOSEST_POINT THEN ASM_REWRITE_TAC[]]);;
5965
5966 (* ------------------------------------------------------------------------- *)
5967 (* Various point-to-set separating/supporting hyperplane theorems.           *)
5968 (* ------------------------------------------------------------------------- *)
5969
5970 let SUPPORTING_HYPERPLANE_COMPACT_POINT_SUP = prove
5971  (`!a c s:real^N->bool.
5972         compact s /\ ~(s = {})
5973         ==> ?b y. y IN s /\ a dot (y - c) = b /\
5974                   (!x. x IN s ==> a dot (x - c) <= b)`,
5975   REPEAT STRIP_TAC THEN
5976   MP_TAC(ISPECL [`\x:real^N. a dot (x - c)`; `s:real^N->bool`]
5977         CONTINUOUS_ATTAINS_SUP) THEN
5978   ASM_REWRITE_TAC[] THEN
5979   ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
5980   SUBGOAL_THEN `(\x:real^N. a dot (x - c)) = (\x. a dot x) o (\x. x - c)`
5981   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
5982   REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
5983   SIMP_TAC[CONTINUOUS_ON_LIFT_DOT; CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST;
5984            CONTINUOUS_ON_ID]);;
5985
5986 let SUPPORTING_HYPERPLANE_COMPACT_POINT_INF = prove
5987  (`!a c s:real^N->bool.
5988         compact s /\ ~(s = {})
5989         ==> ?b y. y IN s /\ a dot (y - c) = b /\
5990                   (!x. x IN s ==> a dot (x - c) >= b)`,
5991   REPEAT STRIP_TAC THEN
5992   MP_TAC(ISPECL [`--a:real^N`; `c:real^N`; `s:real^N->bool`]
5993     SUPPORTING_HYPERPLANE_COMPACT_POINT_SUP) THEN
5994   ASM_REWRITE_TAC[] THEN
5995   DISCH_THEN(X_CHOOSE_THEN `b:real`
5996    (fun th -> EXISTS_TAC `--b:real` THEN MP_TAC th)) THEN
5997   REWRITE_TAC[DOT_LNEG; REAL_ARITH `x >= -- b <=> --x <= b`] THEN
5998   REWRITE_TAC[REAL_NEG_EQ]);;
5999
6000 let SUPPORTING_HYPERPLANE_CLOSED_POINT = prove
6001  (`!s z:real^N. convex s /\ closed s /\ ~(s = {}) /\ ~(z IN s)
6002                 ==> ?a b y. a dot z < b /\ y IN s /\ (a dot y = b) /\
6003                             (!x. x IN s ==> a dot x >= b)`,
6004   REPEAT STRIP_TAC THEN
6005   MP_TAC(ISPECL [`s:real^N->bool`; `z:real^N`] DISTANCE_ATTAINS_INF) THEN
6006   ASM_REWRITE_TAC[] THEN
6007   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
6008   EXISTS_TAC `y - z:real^N` THEN EXISTS_TAC `(y - z:real^N) dot y` THEN
6009   EXISTS_TAC `y:real^N` THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
6010   ASM_REWRITE_TAC[GSYM DOT_RSUB; DOT_POS_LT; VECTOR_SUB_EQ] THEN
6011   CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN X_GEN_TAC `x:real^N` THEN
6012   DISCH_TAC THEN SUBGOAL_THEN
6013    `!u. &0 <= u /\ u <= &1 ==> dist(z:real^N,y) <= dist(z,(&1 - u) % y + u % x)`
6014   MP_TAC THENL [ASM_MESON_TAC[CONVEX_ALT]; ALL_TAC] THEN
6015   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
6016   REWRITE_TAC[real_ge; REAL_NOT_LE; NOT_FORALL_THM; NOT_IMP] THEN
6017   GEN_REWRITE_TAC LAND_CONV [REAL_ARITH `x < y <=> y - x > &0`] THEN
6018   REWRITE_TAC[VECTOR_ARITH
6019    `(a - b) dot x - (a - b) dot y = (b - a) dot (y - x)`] THEN
6020   DISCH_THEN(MP_TAC o MATCH_MP CLOSER_POINT_LEMMA) THEN
6021   REWRITE_TAC[VECTOR_ARITH `y + u % (x - y) = (&1 - u) % y + u % x`] THEN
6022   MESON_TAC[REAL_LT_IMP_LE]);;
6023
6024 let SEPARATING_HYPERPLANE_CLOSED_POINT_INSET = prove
6025  (`!s z:real^N. convex s /\ closed s /\ ~(s = {}) /\ ~(z IN s)
6026                 ==> ?a b. a IN s /\
6027                           (a - z) dot z < b /\
6028                           (!x. x IN s ==> (a - z) dot x > b)`,
6029   REPEAT STRIP_TAC THEN
6030   MP_TAC(ISPECL [`s:real^N->bool`; `z:real^N`] DISTANCE_ATTAINS_INF) THEN
6031   ASM_REWRITE_TAC[] THEN
6032   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
6033   EXISTS_TAC `y:real^N` THEN ASM_REWRITE_TAC[] THEN
6034   EXISTS_TAC `(y - z:real^N) dot z + norm(y - z) pow 2 / &2` THEN
6035   SUBGOAL_THEN `&0 < norm(y - z:real^N)` ASSUME_TAC THENL
6036    [ASM_MESON_TAC[NORM_POS_LT; VECTOR_SUB_EQ]; ALL_TAC] THEN
6037   ASM_SIMP_TAC[REAL_LT_ADDR; REAL_LT_DIV; REAL_POW_LT;
6038                REAL_OF_NUM_LT; ARITH] THEN
6039   REWRITE_TAC[NORM_POW_2; REAL_ARITH `a > b + c <=> c < a - b`] THEN
6040   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
6041   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
6042   ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
6043   REWRITE_TAC[VECTOR_ARITH
6044    `((y - z) dot x - (y - z) dot z) * &2 - (y - z) dot (y - z) =
6045     &2 * ((y - z) dot (x - y)) + (y - z) dot (y - z)`] THEN
6046   MATCH_MP_TAC(REAL_ARITH `~(--x > &0) /\ &0 < y ==> &0 < &2 * x + y`) THEN
6047   ASM_SIMP_TAC[GSYM NORM_POW_2; REAL_POW_LT] THEN
6048   REWRITE_TAC[GSYM DOT_LNEG; VECTOR_NEG_SUB] THEN
6049   DISCH_THEN(MP_TAC o MATCH_MP CLOSER_POINT_LEMMA) THEN
6050   REWRITE_TAC[NOT_EXISTS_THM] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
6051   GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6052   REWRITE_TAC[REAL_NOT_LT] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
6053   REWRITE_TAC[VECTOR_ARITH `y + u % (x - y) = (&1 - u) % y + u % x`] THEN
6054   ASM_MESON_TAC[CONVEX_ALT; REAL_LT_IMP_LE]);;
6055
6056 let SEPARATING_HYPERPLANE_CLOSED_0_INSET = prove
6057  (`!s:real^N->bool.
6058         convex s /\ closed s /\ ~(s = {}) /\ ~(vec 0 IN s)
6059         ==> ?a b. a IN s /\ ~(a = vec 0) /\ &0 < b /\
6060                   (!x. x IN s ==> a dot x > b)`,
6061   REPEAT GEN_TAC THEN DISCH_TAC THEN
6062   FIRST_ASSUM(MP_TAC o MATCH_MP SEPARATING_HYPERPLANE_CLOSED_POINT_INSET) THEN
6063   REWRITE_TAC[DOT_RZERO; real_gt] THEN
6064   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
6065   SIMP_TAC[VECTOR_SUB_RZERO] THEN ASM_MESON_TAC[]);;
6066
6067 let SEPARATING_HYPERPLANE_CLOSED_POINT = prove
6068  (`!s z:real^N. convex s /\ closed s /\ ~(z IN s)
6069                 ==> ?a b. a dot z < b /\ (!x. x IN s ==> a dot x > b)`,
6070   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
6071    [MAP_EVERY EXISTS_TAC [`--z:real^N`; `&1`] THEN
6072     SIMP_TAC[DOT_LNEG; REAL_ARITH `&0 <= x ==> --x < &1`; DOT_POS_LE] THEN
6073     ASM_MESON_TAC[NOT_IN_EMPTY];
6074     ALL_TAC] THEN
6075   ASM_MESON_TAC[SEPARATING_HYPERPLANE_CLOSED_POINT_INSET]);;
6076
6077 let SEPARATING_HYPERPLANE_CLOSED_0 = prove
6078  (`!s:real^N->bool.
6079         convex s /\ closed s /\ ~(vec 0 IN s)
6080         ==> ?a b. ~(a = vec 0) /\ &0 < b /\ (!x. x IN s ==> a dot x > b)`,
6081   REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
6082    [EXISTS_TAC `basis 1:real^N` THEN EXISTS_TAC `&1` THEN
6083     ASM_REWRITE_TAC[NOT_IN_EMPTY; REAL_LT_01; GSYM NORM_POS_LT] THEN
6084     ASM_SIMP_TAC[NORM_BASIS; DIMINDEX_GE_1; LE_REFL; REAL_LT_01];
6085     FIRST_X_ASSUM(MP_TAC o MATCH_MP SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
6086     REWRITE_TAC[DOT_RZERO; real_gt] THEN
6087     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
6088     ASM_MESON_TAC[MEMBER_NOT_EMPTY; DOT_LZERO; REAL_LT_ANTISYM]]);;
6089
6090 (* ------------------------------------------------------------------------- *)
6091 (* Now set-to-set for closed/compact sets.                                   *)
6092 (* ------------------------------------------------------------------------- *)
6093
6094 let SEPARATING_HYPERPLANE_CLOSED_COMPACT = prove
6095  (`!s t. convex s /\ closed s /\
6096          convex t /\ compact t /\ ~(t = {}) /\ DISJOINT s t
6097          ==> ?a:real^N b. (!x. x IN s ==> a dot x < b) /\
6098                           (!x. x IN t ==> a dot x > b)`,
6099   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
6100    [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
6101     FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN
6102     REWRITE_TAC[BOUNDED_POS] THEN
6103     DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THEN
6104     SUBGOAL_THEN `?z:real^N. norm(z) = b + &1` CHOOSE_TAC THENL
6105      [ASM_SIMP_TAC[VECTOR_CHOOSE_SIZE; REAL_ARITH `&0 < b ==> &0 <= b + &1`];
6106       ALL_TAC] THEN
6107     MP_TAC(SPECL [`t:real^N->bool`; `z:real^N`]
6108        SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
6109     ANTS_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
6110     ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN
6111     ASM_MESON_TAC[REAL_ARITH `~(b + &1 <= b)`];
6112     ALL_TAC] THEN
6113   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN t}`; `vec 0 :real^N`]
6114                 SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
6115   ASM_SIMP_TAC[CLOSED_COMPACT_DIFFERENCES; CONVEX_DIFFERENCES] THEN
6116   ANTS_TAC THENL
6117    [REWRITE_TAC[IN_ELIM_THM] THEN ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN
6118     REWRITE_TAC[VECTOR_SUB_EQ] THEN
6119     ASM_MESON_TAC[DISJOINT; NOT_IN_EMPTY; IN_INTER; EXTENSION];
6120     ALL_TAC] THEN
6121   SIMP_TAC[DOT_RZERO; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
6122   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN
6123   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6124   GEN_REWRITE_TAC LAND_CONV [SWAP_FORALL_THM] THEN
6125   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [SWAP_FORALL_THM] THEN
6126   ONCE_REWRITE_TAC[IMP_CONJ] THEN REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN
6127   REWRITE_TAC[LEFT_FORALL_IMP_THM; EXISTS_REFL; DOT_RSUB] THEN
6128   REWRITE_TAC[real_gt; REAL_LT_SUB_LADD] THEN DISCH_TAC THEN
6129   EXISTS_TAC `--a:real^N` THEN
6130   MP_TAC(SPEC `IMAGE (\x:real^N. a dot x) t` SUP) THEN
6131   ABBREV_TAC `k = sup (IMAGE (\x:real^N. a dot x) t)` THEN
6132   ASM_REWRITE_TAC[FORALL_IN_IMAGE; IMAGE_EQ_EMPTY] THEN ANTS_TAC THENL
6133    [ASM_MESON_TAC[REAL_ARITH `b + x < y ==> x <= y - b`; MEMBER_NOT_EMPTY];
6134     ALL_TAC] THEN
6135   STRIP_TAC THEN EXISTS_TAC `--(k + b / &2)` THEN
6136   REWRITE_TAC[DOT_LNEG; REAL_LT_NEG2] THEN REPEAT STRIP_TAC THEN
6137   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH;
6138                REAL_ARITH `&0 < b /\ x <= k ==> x < k + b`] THEN
6139   FIRST_X_ASSUM(MP_TAC o SPEC `k - b / &2`) THEN
6140   ASM_SIMP_TAC[REAL_ARITH `k <= k - b2 <=> ~(&0 < b2)`; REAL_LT_DIV;
6141      REAL_OF_NUM_LT; ARITH; NOT_FORALL_THM; LEFT_IMP_EXISTS_THM; NOT_IMP] THEN
6142   X_GEN_TAC `y:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6143   MATCH_MP_TAC(REAL_ARITH
6144    `!b. (b2 + b2 = b) /\ b + ay < ax ==> ~(ay <= k - b2) ==> k + b2 < ax`) THEN
6145   ASM_MESON_TAC[REAL_HALF]);;
6146
6147 let SEPARATING_HYPERPLANE_COMPACT_CLOSED = prove
6148  (`!s t. convex s /\ compact s /\ ~(s = {}) /\
6149          convex t /\ closed t /\ DISJOINT s t
6150          ==> ?a:real^N b. (!x. x IN s ==> a dot x < b) /\
6151                           (!x. x IN t ==> a dot x > b)`,
6152   REPEAT STRIP_TAC THEN
6153   MP_TAC(ISPECL [`t:real^N->bool`; `s:real^N->bool`]
6154       SEPARATING_HYPERPLANE_CLOSED_COMPACT) THEN
6155   ANTS_TAC THENL [ASM_MESON_TAC[DISJOINT_SYM]; ALL_TAC] THEN
6156   REWRITE_TAC[real_gt] THEN
6157   DISCH_THEN(X_CHOOSE_THEN `a:real^N` (X_CHOOSE_THEN `b:real`
6158     STRIP_ASSUME_TAC)) THEN
6159   MAP_EVERY EXISTS_TAC [`--a:real^N`; `--b:real`] THEN
6160   ASM_REWRITE_TAC[REAL_LT_NEG2; DOT_LNEG]);;
6161
6162 let SEPARATING_HYPERPLANE_COMPACT_CLOSED_NONZERO = prove
6163  (`!s t:real^N->bool.
6164            convex s /\ compact s /\ ~(s = {}) /\
6165            convex t /\ closed t /\ DISJOINT s t
6166            ==> ?a b. ~(a = vec 0) /\
6167                      (!x. x IN s ==> a dot x < b) /\
6168                      (!x. x IN t ==> a dot x > b)`,
6169   REPEAT GEN_TAC THEN ASM_CASES_TAC `t:real^N->bool = {}` THENL
6170    [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN STRIP_TAC THEN
6171     EXISTS_TAC `basis 1:real^N` THEN
6172     SUBGOAL_THEN
6173      `bounded(IMAGE (\x:real^N. lift(basis 1 dot x)) s)`
6174     MP_TAC THENL
6175      [MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
6176       MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
6177       ASM_SIMP_TAC[REWRITE_RULE[o_DEF] CONTINUOUS_ON_LIFT_DOT];
6178       REWRITE_TAC[BOUNDED_POS_LT; FORALL_IN_IMAGE; NORM_LIFT] THEN
6179       SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL] THEN
6180       MESON_TAC[REAL_ARITH `abs x < b ==> x < b`]];
6181     STRIP_TAC THEN
6182     MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`]
6183         SEPARATING_HYPERPLANE_COMPACT_CLOSED) THEN
6184     ASM_REWRITE_TAC[] THEN
6185     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
6186     ASM_CASES_TAC `a:real^N = vec 0` THEN ASM_REWRITE_TAC[] THEN
6187     REWRITE_TAC[DOT_LZERO; real_gt] THEN
6188     ASM_MESON_TAC[REAL_LT_ANTISYM; MEMBER_NOT_EMPTY]]);;
6189
6190 let SEPARATING_HYPERPLANE_COMPACT_COMPACT = prove
6191  (`!s t:real^N->bool.
6192            convex s /\ compact s /\ convex t /\ compact t /\ DISJOINT s t
6193            ==> ?a b. ~(a = vec 0) /\
6194                      (!x. x IN s ==> a dot x < b) /\
6195                      (!x. x IN t ==> a dot x > b)`,
6196   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
6197    [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN STRIP_TAC THEN
6198     EXISTS_TAC `--basis 1:real^N` THEN
6199     SUBGOAL_THEN
6200      `bounded(IMAGE (\x:real^N. lift(basis 1 dot x)) t)`
6201     MP_TAC THENL
6202      [MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
6203       MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
6204       ASM_SIMP_TAC[REWRITE_RULE[o_DEF] CONTINUOUS_ON_LIFT_DOT];
6205       REWRITE_TAC[BOUNDED_POS_LT; FORALL_IN_IMAGE; NORM_LIFT] THEN
6206       SIMP_TAC[VECTOR_NEG_EQ_0; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL] THEN
6207       DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THEN
6208       EXISTS_TAC `--b:real` THEN REWRITE_TAC[DOT_LNEG] THEN
6209       REWRITE_TAC[REAL_ARITH `--x > --y <=> x < y`] THEN
6210       ASM_MESON_TAC[REAL_ARITH `abs x < b ==> x < b`]];
6211     STRIP_TAC THEN
6212     MATCH_MP_TAC SEPARATING_HYPERPLANE_COMPACT_CLOSED_NONZERO THEN
6213     ASM_SIMP_TAC[COMPACT_IMP_CLOSED]]);;
6214
6215 (* ------------------------------------------------------------------------- *)
6216 (* General case without assuming closure and getting non-strict separation.  *)
6217 (* ------------------------------------------------------------------------- *)
6218
6219 let SEPARATING_HYPERPLANE_SET_0_INSPAN = prove
6220  (`!s:real^N->bool.
6221         convex s /\ ~(s = {}) /\ ~(vec 0 IN s)
6222         ==> ?a b. a IN span s /\ ~(a = vec 0) /\
6223                   !x. x IN s ==> &0 <= a dot x`,
6224   REPEAT STRIP_TAC THEN
6225   ABBREV_TAC `k = \c:real^N. {x | &0 <= c dot x}` THEN
6226   SUBGOAL_THEN
6227    `~((span s INTER frontier(cball(vec 0:real^N,&1))) INTER
6228       (INTERS (IMAGE k (s:real^N->bool))) = {})`
6229   MP_TAC THENL
6230    [ALL_TAC;
6231     SIMP_TAC[EXTENSION; NOT_IN_EMPTY; IN_INTER; IN_INTERS; NOT_FORALL_THM;
6232              FORALL_IN_IMAGE; FRONTIER_CBALL; REAL_LT_01] THEN
6233     EXPAND_TAC "k" THEN REWRITE_TAC[IN_SPHERE_0; IN_ELIM_THM; NORM_NEG] THEN
6234     MESON_TAC[NORM_EQ_0; REAL_ARITH `~(&1 = &0)`; DOT_SYM]] THEN
6235   MATCH_MP_TAC COMPACT_IMP_FIP THEN
6236   SIMP_TAC[COMPACT_CBALL; COMPACT_FRONTIER; FORALL_IN_IMAGE;
6237            CLOSED_INTER_COMPACT; CLOSED_SPAN] THEN
6238   CONJ_TAC THENL
6239    [EXPAND_TAC "k" THEN REWRITE_TAC[GSYM real_ge; CLOSED_HALFSPACE_GE];
6240     ALL_TAC] THEN
6241   REWRITE_TAC[FINITE_SUBSET_IMAGE] THEN GEN_TAC THEN
6242   DISCH_THEN(X_CHOOSE_THEN `c:real^N->bool` MP_TAC) THEN
6243   ASM_CASES_TAC `c:real^N->bool = {}` THENL
6244    [ASM_SIMP_TAC[INTERS_0; INTER_UNIV; IMAGE_CLAUSES] THEN
6245     DISCH_THEN(K ALL_TAC) THEN
6246     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
6247     DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
6248     SUBGOAL_THEN `~(a:real^N = vec 0)` ASSUME_TAC THENL
6249      [ASM_MESON_TAC[]; ALL_TAC] THEN
6250     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
6251     EXISTS_TAC `inv(norm a) % a:real^N` THEN
6252     ASM_SIMP_TAC[IN_INTER; FRONTIER_CBALL; SPAN_CLAUSES; IN_SPHERE_0] THEN
6253     REWRITE_TAC[DIST_0; NORM_MUL; REAL_ABS_INV; REAL_ABS_NORM] THEN
6254     ASM_SIMP_TAC[REAL_MUL_LINV; NORM_EQ_0];
6255     ALL_TAC] THEN
6256   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
6257   MP_TAC(ISPEC `convex hull (c:real^N->bool)`
6258       SEPARATING_HYPERPLANE_CLOSED_0_INSET) THEN
6259   ANTS_TAC THENL
6260    [ASM_REWRITE_TAC[CONVEX_HULL_EQ_EMPTY] THEN
6261     ASM_MESON_TAC[CONVEX_CONVEX_HULL; SUBSET; SUBSET_HULL; HULL_SUBSET;
6262                   FINITE_IMP_COMPACT_CONVEX_HULL; COMPACT_IMP_CLOSED];
6263     ALL_TAC] THEN
6264   REWRITE_TAC[DOT_RZERO; real_gt] THEN
6265   DISCH_THEN(X_CHOOSE_THEN `a:real^N` (X_CHOOSE_THEN `b:real`
6266     STRIP_ASSUME_TAC)) THEN
6267   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER; IN_INTERS; FORALL_IN_IMAGE] THEN
6268   EXPAND_TAC "k" THEN SIMP_TAC[IN_ELIM_THM; FRONTIER_CBALL; REAL_LT_01] THEN
6269   REWRITE_TAC[dist; VECTOR_SUB_LZERO; NORM_NEG] THEN
6270   EXISTS_TAC `inv(norm(a)) % a:real^N` THEN REWRITE_TAC[DOT_RMUL] THEN
6271   SUBGOAL_THEN `(a:real^N) IN s` ASSUME_TAC THENL
6272    [ASM_MESON_TAC[SUBSET; HULL_MINIMAL]; ASM_SIMP_TAC[SPAN_CLAUSES]] THEN
6273   REWRITE_TAC[IN_SPHERE_0; VECTOR_SUB_LZERO; NORM_NEG; NORM_MUL] THEN
6274   REWRITE_TAC[REAL_ABS_INV; REAL_ABS_NORM] THEN
6275   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN
6276   ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_EQ_LDIV_EQ; NORM_POS_LT] THEN
6277   REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID] THEN
6278   ASM_MESON_TAC[REAL_LT_IMP_LE; REAL_LE_TRANS; HULL_SUBSET; SUBSET; DOT_SYM]);;
6279
6280 let SEPARATING_HYPERPLANE_SET_POINT_INAFF = prove
6281  (`!s z:real^N.
6282         convex s /\ ~(s = {}) /\ ~(z IN s)
6283         ==> ?a b. (z + a) IN affine hull (z INSERT s) /\ ~(a = vec 0) /\
6284                   a dot z <= b /\ (!x. x IN s ==> a dot x >= b)`,
6285   REPEAT STRIP_TAC THEN
6286   MP_TAC(ISPEC `IMAGE (\x:real^N. --z + x) s`
6287      SEPARATING_HYPERPLANE_SET_0_INSPAN) THEN
6288   ASM_SIMP_TAC[FORALL_IN_IMAGE; CONVEX_TRANSLATION; IMAGE_EQ_EMPTY] THEN
6289   REWRITE_TAC[IN_IMAGE; VECTOR_ARITH `vec 0:real^N = --z + x <=> x = z`] THEN
6290   ASM_SIMP_TAC[UNWIND_THM2; AFFINE_HULL_INSERT_SPAN; IN_ELIM_THM] THEN
6291   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
6292   REWRITE_TAC[GSYM SIMPLE_IMAGE; VECTOR_ARITH `--x + y:real^N = y - x`] THEN
6293   STRIP_TAC THEN ASM_REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN
6294   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
6295   EXISTS_TAC `(a:real^N) dot z` THEN REWRITE_TAC[REAL_LE_REFL] THEN
6296   ASM_REWRITE_TAC[REAL_ARITH `x >= y <=> &0 <= x - y`; GSYM DOT_RSUB]);;
6297
6298 let SEPARATING_HYPERPLANE_SET_0 = prove
6299  (`!s:real^N->bool.
6300         convex s /\ ~(vec 0 IN s)
6301         ==> ?a b. ~(a = vec 0) /\ !x. x IN s ==> &0 <= a dot x`,
6302   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
6303    [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
6304     MESON_TAC[BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1];
6305     ASM_MESON_TAC[SEPARATING_HYPERPLANE_SET_0_INSPAN]]);;
6306
6307 let SEPARATING_HYPERPLANE_SETS = prove
6308  (`!s t. convex s /\ convex t /\ ~(s = {}) /\ ~(t = {}) /\ DISJOINT s t
6309          ==> ?a:real^N b. ~(a = vec 0) /\
6310                           (!x. x IN s ==> a dot x <= b) /\
6311                           (!x. x IN t ==> a dot x >= b)`,
6312   REPEAT STRIP_TAC THEN
6313   MP_TAC(ISPEC `{y - x:real^N | y IN t /\ x IN s}`
6314                 SEPARATING_HYPERPLANE_SET_0) THEN
6315   ASM_SIMP_TAC[CONVEX_DIFFERENCES] THEN ANTS_TAC THENL
6316    [REWRITE_TAC[IN_ELIM_THM] THEN ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN
6317     REWRITE_TAC[VECTOR_SUB_EQ] THEN
6318     ASM_MESON_TAC[DISJOINT; NOT_IN_EMPTY; IN_INTER; EXTENSION];
6319     ALL_TAC] THEN
6320   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
6321   SIMP_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
6322   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6323   GEN_REWRITE_TAC LAND_CONV [SWAP_FORALL_THM] THEN
6324   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [SWAP_FORALL_THM] THEN
6325   ONCE_REWRITE_TAC[IMP_CONJ] THEN REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN
6326   REWRITE_TAC[LEFT_FORALL_IMP_THM; EXISTS_REFL; DOT_RSUB; REAL_SUB_LE] THEN
6327   DISCH_TAC THEN
6328   MP_TAC(SPEC `IMAGE (\x:real^N. a dot x) s` SUP) THEN
6329   ABBREV_TAC `k = sup (IMAGE (\x:real^N. a dot x) s)` THEN
6330   ASM_REWRITE_TAC[FORALL_IN_IMAGE; IMAGE_EQ_EMPTY; real_ge] THEN ANTS_TAC THENL
6331    [ASM_MESON_TAC[MEMBER_NOT_EMPTY]; ASM_MESON_TAC[]]);;
6332
6333 (* ------------------------------------------------------------------------- *)
6334 (* More convexity generalities.                                              *)
6335 (* ------------------------------------------------------------------------- *)
6336
6337 let CONVEX_CLOSURE = prove
6338  (`!s:real^N->bool. convex s ==> convex(closure s)`,
6339   REWRITE_TAC[convex; CLOSURE_SEQUENTIAL] THEN
6340   GEN_TAC THEN DISCH_TAC THEN
6341   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
6342   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `a:num->real^N`) MP_TAC) THEN
6343   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `b:num->real^N`) MP_TAC) THEN
6344   STRIP_TAC THEN EXISTS_TAC `\n:num. u % a(n) + v % b(n) :real^N` THEN
6345   ASM_SIMP_TAC[LIM_ADD; LIM_CMUL]);;
6346
6347 let CONVEX_INTERIOR = prove
6348  (`!s:real^N->bool. convex s ==> convex(interior s)`,
6349   REWRITE_TAC[CONVEX_ALT; IN_INTERIOR; SUBSET; IN_BALL; dist] THEN
6350   REPEAT GEN_TAC THEN STRIP_TAC THEN REPEAT GEN_TAC THEN
6351   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `d:real`) MP_TAC) THEN
6352   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `e:real`) STRIP_ASSUME_TAC) THEN
6353   EXISTS_TAC `min d e` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
6354   X_GEN_TAC `z:real^N` THEN STRIP_TAC THEN
6355   SUBST1_TAC(VECTOR_ARITH `z:real^N =
6356    (&1 - u) % (z - u % (y - x)) + u % (z + (&1 - u) % (y - x))`) THEN
6357   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
6358   ASM_MESON_TAC[VECTOR_ARITH `x - (z - u % (y - x)) =
6359                                 ((&1 - u) % x + u % y) - z:real^N`;
6360                 VECTOR_ARITH `y - (z + (&1 - u) % (y - x)) =
6361                                 ((&1 - u) % x + u % y) - z:real^N`]);;
6362
6363 (* ------------------------------------------------------------------------- *)
6364 (* Moving and scaling convex hulls.                                          *)
6365 (* ------------------------------------------------------------------------- *)
6366
6367 let CONVEX_HULL_TRANSLATION = prove
6368  (`!a:real^N s.
6369        convex hull (IMAGE (\x. a + x) s) = IMAGE (\x. a + x) (convex hull s)`,
6370   REPEAT GEN_TAC THEN MATCH_MP_TAC HULL_IMAGE THEN
6371   REWRITE_TAC[CONVEX_TRANSLATION_EQ; CONVEX_CONVEX_HULL] THEN
6372   REWRITE_TAC[VECTOR_ARITH `a + x:real^N = y <=> x = y - a`; EXISTS_REFL] THEN
6373   VECTOR_ARITH_TAC);;
6374
6375 add_translation_invariants [CONVEX_HULL_TRANSLATION];;
6376
6377 let CONVEX_HULL_SCALING = prove
6378  (`!s:real^N->bool c.
6379        convex hull (IMAGE (\x. c % x) s) = IMAGE (\x. c % x) (convex hull s)`,
6380   REPEAT GEN_TAC THEN ASM_CASES_TAC `c = &0` THENL
6381    [ASM_SIMP_TAC[IMAGE_CONST; VECTOR_MUL_LZERO; CONVEX_HULL_EQ_EMPTY] THEN
6382     COND_CASES_TAC THEN REWRITE_TAC[CONVEX_HULL_EMPTY; CONVEX_HULL_SING];
6383     ALL_TAC] THEN
6384   MATCH_MP_TAC HULL_IMAGE THEN
6385   ASM_SIMP_TAC[CONVEX_SCALING_EQ; CONVEX_CONVEX_HULL] THEN
6386   REWRITE_TAC[VECTOR_ARITH `c % x = c % y <=> c % (x - y) = vec 0`] THEN
6387   ASM_SIMP_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
6388   X_GEN_TAC `x:real^N` THEN EXISTS_TAC `inv c % x:real^N` THEN
6389   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; VECTOR_MUL_LID]);;
6390
6391 let CONVEX_HULL_AFFINITY = prove
6392  (`!s a:real^N c.
6393         convex hull (IMAGE (\x. a + c % x) s) =
6394         IMAGE (\x. a + c % x) (convex hull s)`,
6395   REPEAT GEN_TAC THEN
6396   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
6397   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
6398   ASM_SIMP_TAC[IMAGE_o; CONVEX_HULL_TRANSLATION; CONVEX_HULL_SCALING]);;
6399
6400 (* ------------------------------------------------------------------------- *)
6401 (* Convex set as intersection of halfspaces.                                 *)
6402 (* ------------------------------------------------------------------------- *)
6403
6404 let CONVEX_HALFSPACE_INTERSECTION = prove
6405  (`!s. closed(s:real^N->bool) /\ convex s
6406        ==> s = INTERS {h | s SUBSET h /\ ?a b. h = {x | a dot x <= b}}`,
6407   REPEAT STRIP_TAC THEN
6408   GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[IN_INTERS] THEN
6409   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
6410   REWRITE_TAC[MESON[] `(!t. (P t /\ ?a b. t = x a b) ==> Q t) <=>
6411                        (!a b. P(x a b) ==> Q(x a b))`] THEN
6412   EQ_TAC THENL [SET_TAC[]; ALL_TAC] THEN STRIP_TAC THEN
6413   MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
6414   MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`]
6415     SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
6416   ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
6417   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN STRIP_TAC THEN
6418   FIRST_X_ASSUM(MP_TAC o SPECL [`--a:real^N`; `--b:real`]) THEN
6419   ASM_SIMP_TAC[SUBSET; IN_ELIM_THM; DOT_LNEG; NOT_IMP] THEN
6420   ASM_SIMP_TAC[REAL_LE_NEG2; REAL_LT_NEG2; REAL_NOT_LE;
6421                REAL_ARITH `a > b ==> b <= a`]);;
6422
6423 (* ------------------------------------------------------------------------- *)
6424 (* Radon's theorem (from Lars Schewe).                                       *)
6425 (* ------------------------------------------------------------------------- *)
6426
6427 let RADON_EX_LEMMA = prove
6428  (`!(c:real^N->bool).
6429         FINITE c /\ affine_dependent c
6430         ==> (?u. sum c u = &0 /\ (?v. v IN c /\ ~(u v = &0)) /\
6431                                       vsum c (\v. u v % v) = (vec 0):real^N)`,
6432   REWRITE_TAC[AFFINE_DEPENDENT_EXPLICIT] THEN
6433   REPEAT STRIP_TAC THEN
6434   EXISTS_TAC `\v:real^N. if v IN s then u v else &0` THEN
6435   ASM_SIMP_TAC[GSYM SUM_RESTRICT_SET] THEN
6436   ASM_SIMP_TAC[COND_RAND;COND_RATOR;
6437                VECTOR_MUL_LZERO;GSYM VSUM_RESTRICT_SET] THEN
6438   ASM_SIMP_TAC[SET_RULE `s SUBSET c ==> {x | x IN c /\ x IN s} = s`] THEN
6439   EXISTS_TAC `v:real^N` THEN
6440   ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;
6441
6442 let RADON_S_LEMMA = prove
6443  (`!(s:A->bool) f.
6444         FINITE s /\ sum s f = &0
6445         ==> sum {x | x IN s /\ &0 < f x} f =
6446             -- sum {x | x IN s /\ f x < &0} f`,
6447   REWRITE_TAC[REAL_ARITH `a = --b <=> a + b = &0`] THEN
6448   REPEAT STRIP_TAC THEN
6449   ASM_SIMP_TAC[FINITE_RESTRICT;GSYM SUM_UNION;
6450     REWRITE_RULE [REAL_ARITH `&0 < f x ==> ~(f x < &0)`]
6451      (SET_RULE `(!x:A. &0 < f x ==> ~(f x < &0))
6452                 ==>  DISJOINT {x | x IN s /\ &0 < f x}
6453                               {x | x IN s /\ f x < &0}`)] THEN
6454   MATCH_MP_TAC (REAL_ARITH `!a b.a = &0 /\ a + b = &0 ==> b = &0`) THEN
6455   EXISTS_TAC `sum {x:A | x IN s /\ f x = &0} f` THEN
6456   CONJ_TAC THENL
6457   [ASM_SIMP_TAC[SUM_RESTRICT_SET] THEN REWRITE_TAC[COND_ID;SUM_0];
6458    ALL_TAC] THEN
6459   SUBGOAL_THEN `DISJOINT {x:A | x IN s /\ f x = &0}
6460                          ({x | x IN s /\ &0 < f x} UNION
6461                           {x | x IN s /\ f x < &0})` ASSUME_TAC THENL
6462   [REWRITE_TAC[DISJOINT;UNION;INTER;IN_ELIM_THM;EXTENSION;NOT_IN_EMPTY] THEN
6463    REAL_ARITH_TAC;
6464    ALL_TAC] THEN
6465    ASM_SIMP_TAC[FINITE_UNION;FINITE_RESTRICT;GSYM SUM_UNION] THEN
6466   FIRST_X_ASSUM (SUBST1_TAC o GSYM) THEN
6467   MATCH_MP_TAC (MESON[] `a = b ==> sum a f = sum b f`) THEN
6468   REWRITE_TAC[EXTENSION;IN_ELIM_THM;UNION] THEN
6469   MESON_TAC[REAL_LT_TOTAL]);;
6470
6471 let RADON_V_LEMMA = prove
6472  (`!(s:A->bool) f g.
6473         FINITE s /\ vsum s f = vec 0 /\ (!x. g x = &0 ==> f x = vec 0)
6474         ==> (vsum {x | x IN s /\ &0 < g x} f) :real^N =
6475              -- vsum {x | x IN s /\ g x < &0} f`,
6476   REWRITE_TAC[VECTOR_ARITH `a:real^N = --b <=> a + b = vec 0`] THEN
6477   REPEAT STRIP_TAC THEN
6478   ASM_SIMP_TAC[FINITE_RESTRICT;GSYM VSUM_UNION;
6479                REWRITE_RULE [REAL_ARITH `&0 < f x ==> ~(f x < &0)`]
6480                  (SET_RULE `(!x:A. &0 < f x ==> ~(f x < &0))
6481                             ==>  DISJOINT {x | x IN s /\ &0 < f x}
6482                                           {x | x IN s /\ f x < &0}`)] THEN
6483   MATCH_MP_TAC (VECTOR_ARITH
6484     `!a b. (a:real^N) = vec 0 /\ a + b = vec 0 ==> b = vec 0`) THEN
6485   EXISTS_TAC `(vsum {x:A | x IN s /\ g x = &0} f):real^N` THEN
6486   CONJ_TAC THENL
6487    [ASM_SIMP_TAC[VSUM_RESTRICT_SET;COND_ID;VSUM_0];ALL_TAC] THEN
6488     SUBGOAL_THEN `DISJOINT {x:A | x IN s /\ g x = &0}
6489                            ({x | x IN s /\ &0 < g x} UNION
6490                             {x | x IN s /\ g x < &0})` ASSUME_TAC THENL
6491      [REWRITE_TAC[DISJOINT;UNION;INTER;IN_ELIM_THM;EXTENSION;NOT_IN_EMPTY] THEN
6492       REAL_ARITH_TAC;
6493       ALL_TAC] THEN
6494   ASM_SIMP_TAC[FINITE_UNION;FINITE_RESTRICT;GSYM VSUM_UNION] THEN
6495   FIRST_X_ASSUM (SUBST1_TAC o GSYM) THEN
6496   MATCH_MP_TAC (MESON[] `a = b ==> vsum a f = vsum b f`) THEN
6497   REWRITE_TAC[EXTENSION;IN_ELIM_THM;UNION] THEN
6498   MESON_TAC[REAL_LT_TOTAL]);;
6499
6500 let RADON_PARTITION = prove
6501  (`!(c:real^N->bool).
6502         FINITE c /\ affine_dependent c
6503         ==> ?(m:real^N->bool) (p:real^N->bool).
6504                 (DISJOINT m p) /\
6505                 (m UNION p = c) /\
6506                 ~(DISJOINT (convex hull m) (convex hull p))`,
6507   REPEAT STRIP_TAC THEN
6508   MP_TAC (ISPEC `c:real^N->bool` RADON_EX_LEMMA) THEN
6509   ASM_REWRITE_TAC[] THEN
6510   REPEAT STRIP_TAC THEN
6511   MAP_EVERY EXISTS_TAC [`{v:real^N | v IN c /\ u v <= &0}`;
6512                         `{v:real^N | v IN c /\ u v > &0}`] THEN
6513   REPEAT CONJ_TAC THENL
6514    [REWRITE_TAC[DISJOINT;INTER;
6515                IN_ELIM_THM;REAL_ARITH `x <= &0 <=> ~(x > &0)`] THEN
6516     SET_TAC[];
6517     REWRITE_TAC[UNION;IN_ELIM_THM;REAL_ARITH `x <= &0 <=> ~(x > &0)`] THEN
6518     SET_TAC[];
6519     ALL_TAC] THEN
6520   SUBGOAL_THEN `~(sum {x:real^N | x IN c /\ u x > &0} u = &0)` ASSUME_TAC THENL
6521    [MATCH_MP_TAC (REAL_ARITH `a > &0 ==> ~(a = &0)`) THEN
6522     REWRITE_TAC[REAL_ARITH `a > &0 <=> &0 < a`]        THEN
6523     MATCH_MP_TAC (REWRITE_RULE[SUM_0] (ISPEC `\x. &0` SUM_LT_ALL)) THEN
6524     ASM_SIMP_TAC[FINITE_RESTRICT;IN_ELIM_THM;EXTENSION;NOT_IN_EMPTY] THEN
6525     REWRITE_TAC[MESON[]`~(!x. ~(P x /\ Q x)) = ?x. P x /\ Q x`] THEN
6526        ASM_CASES_TAC `&0 < u (v:real^N)` THENL
6527     [ASM SET_TAC[];ALL_TAC] THEN
6528     POP_ASSUM MP_TAC THEN POP_ASSUM (K ALL_TAC) THEN POP_ASSUM MP_TAC THEN
6529     REWRITE_TAC[IMP_IMP;REAL_ARITH `~(a = &0) /\ ~(&0 < a) <=> a < &0`] THEN
6530     DISCH_TAC THEN
6531     REWRITE_TAC[MESON[REAL_NOT_LT]
6532      `(?x:real^N. P x /\ &0 < u x) <=> (!x. P x ==> u x <= &0) ==> F`]  THEN
6533     DISCH_TAC THEN
6534        MP_TAC (ISPECL [`u:real^N->real`;`\x:real^N. &0`;`c:real^N->bool`]
6535                       SUM_LT) THEN
6536     ASM_REWRITE_TAC[SUM_0;REAL_ARITH `~(&0 < &0)`] THEN
6537     ASM_MESON_TAC[];ALL_TAC] THEN
6538   REWRITE_TAC[SET_RULE `~DISJOINT a b <=> ?y. y IN a /\ y IN b`] THEN
6539   EXISTS_TAC `&1 / (sum {x:real^N | x IN c /\ u x > &0} u) %
6540               vsum {x:real^N | x IN c /\ u x > &0} (\x. u x % x)` THEN
6541   REWRITE_TAC[CONVEX_HULL_EXPLICIT;IN_ELIM_THM] THEN
6542   CONJ_TAC THENL
6543   [MAP_EVERY EXISTS_TAC [`{v:real^N | v IN c /\ u v < &0}`;
6544                          `\y:real^N.
6545                          &1 / (sum {x:real^N | x IN c /\ u x > &0} u) *
6546                            (--(u y))`] THEN
6547    ASM_SIMP_TAC[FINITE_RESTRICT;SUBSET;IN_ELIM_THM] THEN
6548    REPEAT CONJ_TAC THENL
6549     [REAL_ARITH_TAC;
6550      REPEAT STRIP_TAC THEN
6551      MATCH_MP_TAC REAL_LE_MUL THEN
6552      CONJ_TAC THENL [ALL_TAC;
6553                      ASM_REWRITE_TAC[REAL_NEG_GE0;REAL_LE_LT]] THEN
6554      MATCH_MP_TAC REAL_LE_DIV THEN
6555      REWRITE_TAC[REAL_LE_01] THEN
6556      MATCH_MP_TAC SUM_POS_LE THEN
6557      ASM_SIMP_TAC[FINITE_RESTRICT;IN_ELIM_THM] THEN
6558      REAL_ARITH_TAC;
6559      ASM_SIMP_TAC[FINITE_RESTRICT;SUM_LMUL] THEN
6560      MATCH_MP_TAC (REAL_FIELD `!a. ~(a = &0) /\ a * b = a * c ==> b = c`) THEN
6561      EXISTS_TAC `sum {x:real^N | x IN c /\ u x > &0} u` THEN
6562      REWRITE_TAC[SUM_LMUL] THEN
6563      ASM_SIMP_TAC[REAL_FIELD `~(a = &0) ==> a * &1 / a * b = b`]  THEN
6564      REWRITE_TAC[SUM_NEG;REAL_MUL_RID] THEN
6565      REWRITE_TAC[REAL_ARITH `a > &0 <=> &0 < a`] THEN
6566      MATCH_MP_TAC (GSYM RADON_S_LEMMA) THEN
6567      ASM_REWRITE_TAC[];
6568      ALL_TAC] THEN
6569     REWRITE_TAC[GSYM VECTOR_MUL_ASSOC;VSUM_LMUL;VECTOR_MUL_LCANCEL] THEN
6570     REWRITE_TAC[VECTOR_MUL_LNEG;VSUM_NEG] THEN
6571     DISJ2_TAC THEN
6572     MATCH_MP_TAC (REWRITE_RULE[REAL_ARITH `&0 < a <=>  a > &0`]
6573      (GSYM RADON_V_LEMMA)) THEN
6574     ASM_REWRITE_TAC[] THEN
6575     MESON_TAC[VECTOR_MUL_LZERO];ALL_TAC] THEN
6576   MAP_EVERY EXISTS_TAC [`{v:real^N | v IN c /\ u v > &0}`;
6577                         `\y:real^N.
6578                            &1 / (sum {x:real^N | x IN c /\ u x > &0} u) *
6579                            (u y)`] THEN
6580   ASM_SIMP_TAC[FINITE_RESTRICT;SUBSET;IN_ELIM_THM] THEN
6581   REPEAT CONJ_TAC THENL
6582    [REPEAT STRIP_TAC THEN
6583     MATCH_MP_TAC REAL_LE_MUL THEN
6584     CONJ_TAC THENL [ALL_TAC;
6585                     ASM_SIMP_TAC[REAL_ARITH `a > &0 ==> &0 <= a`]] THEN
6586     MATCH_MP_TAC REAL_LE_DIV THEN
6587     REWRITE_TAC[REAL_LE_01] THEN
6588     MATCH_MP_TAC SUM_POS_LE THEN
6589     ASM_SIMP_TAC[FINITE_RESTRICT;IN_ELIM_THM] THEN
6590     REAL_ARITH_TAC;
6591     ASM_SIMP_TAC[FINITE_RESTRICT;SUM_LMUL] THEN
6592     MATCH_MP_TAC (REAL_FIELD `!a. ~(a = &0) /\ a * b = a * c ==> b = c`) THEN
6593     EXISTS_TAC `sum {x:real^N | x IN c /\ u x > &0} u` THEN
6594     REWRITE_TAC[SUM_LMUL] THEN
6595     ASM_SIMP_TAC[REAL_FIELD `~(a = &0) ==> a * &1 / a * b = b`]  THEN
6596     REWRITE_TAC[SUM_NEG;REAL_MUL_RID] THEN
6597     REWRITE_TAC[REAL_ARITH `a > &0 <=> &0 < a`] THEN
6598     MATCH_MP_TAC (GSYM RADON_S_LEMMA) THEN
6599     ASM_REWRITE_TAC[];
6600     ALL_TAC] THEN
6601   REWRITE_TAC[GSYM VECTOR_MUL_ASSOC;VSUM_LMUL;VECTOR_MUL_LCANCEL] THEN
6602   REWRITE_TAC[VECTOR_MUL_LNEG;VSUM_NEG] THEN
6603   DISJ2_TAC THEN
6604   MATCH_MP_TAC (REWRITE_RULE[REAL_ARITH `&0 < a <=>  a > &0`]
6605     (GSYM RADON_V_LEMMA)) THEN
6606   ASM_REWRITE_TAC[] THEN
6607   MESON_TAC[VECTOR_MUL_LZERO]);;
6608
6609 let RADON = prove
6610  (`!(c:real^N->bool).
6611         affine_dependent c
6612         ==> ?(m:real^N->bool) (p:real^N->bool).
6613                 m SUBSET c /\
6614                 p SUBSET c /\
6615                 DISJOINT m p /\
6616                 ~(DISJOINT (convex hull m) (convex hull p))`,
6617   REPEAT STRIP_TAC THEN MP_TAC
6618     (ISPEC `c:real^N->bool` AFFINE_DEPENDENT_EXPLICIT) THEN
6619   ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN MP_TAC
6620   (ISPEC `s:real^N->bool` RADON_PARTITION) THEN
6621   ANTS_TAC THENL
6622   [ASM_SIMP_TAC[AFFINE_DEPENDENT_EXPLICIT] THEN
6623      MAP_EVERY EXISTS_TAC [`s:real^N->bool`;`u:real^N->real`] THEN
6624      ASM SET_TAC[];ALL_TAC] THEN
6625   DISCH_THEN STRIP_ASSUME_TAC THEN
6626   MAP_EVERY EXISTS_TAC [`m:real^N->bool`;`p:real^N->bool`] THEN
6627   ASM SET_TAC[]);;
6628
6629 (* ------------------------------------------------------------------------- *)
6630 (* Helly's theorem.                                                          *)
6631 (* ------------------------------------------------------------------------- *)
6632
6633 let HELLY_INDUCT = prove
6634  (`!n f. f HAS_SIZE n /\ n >= dimindex(:N) + 1 /\
6635          (!s:real^N->bool. s IN f ==> convex s) /\
6636          (!t. t SUBSET f /\ CARD(t) = dimindex(:N) + 1
6637               ==> ~(INTERS t = {}))
6638          ==> ~(INTERS f = {})`,
6639   INDUCT_TAC THEN REWRITE_TAC[ARITH_RULE `~(0 >= n + 1)`] THEN GEN_TAC THEN
6640   POP_ASSUM(LABEL_TAC "*") THEN STRIP_TAC THEN
6641   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [HAS_SIZE_SUC]) THEN
6642   STRIP_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
6643   FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP (ARITH_RULE
6644     `SUC n >= m + 1 ==> m = n \/ n >= m + 1`))
6645   THENL
6646    [FIRST_X_ASSUM MATCH_MP_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
6647     ASM_SIMP_TAC[CARD_CLAUSES; SUBSET_REFL] THEN ARITH_TAC;
6648     ALL_TAC] THEN
6649   SUBGOAL_THEN
6650    `?X. !s:real^N->bool. s IN f ==> X(s) IN INTERS (f DELETE s)`
6651   STRIP_ASSUME_TAC THENL
6652    [REWRITE_TAC[GSYM SKOLEM_THM; MEMBER_NOT_EMPTY; RIGHT_EXISTS_IMP_THM] THEN
6653     GEN_TAC THEN STRIP_TAC THEN REMOVE_THEN "*" MATCH_MP_TAC THEN
6654     ASM_SIMP_TAC[FINITE_DELETE; CARD_DELETE] THEN ASM SET_TAC[];
6655     ALL_TAC] THEN
6656   ASM_CASES_TAC
6657    `?s t:real^N->bool. s IN f /\ t IN f /\ ~(s = t) /\ X s:real^N = X t`
6658   THENL
6659    [FIRST_X_ASSUM(CHOOSE_THEN STRIP_ASSUME_TAC) THEN
6660     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
6661     EXISTS_TAC `(X:(real^N->bool)->real^N) t` THEN
6662     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC ONCE_DEPTH_CONV
6663      [MATCH_MP
6664        (SET_RULE`~(s = t)
6665                ==> INTERS f = INTERS(f DELETE s) INTER INTERS(f DELETE t)`)
6666        th]) THEN
6667     REWRITE_TAC[IN_INTER] THEN ASM_MESON_TAC[];
6668     ALL_TAC] THEN
6669   MP_TAC(ISPEC `IMAGE (X:(real^N->bool)->real^N) f` RADON_PARTITION) THEN
6670   ANTS_TAC THENL
6671    [ASM_SIMP_TAC[FINITE_IMAGE] THEN
6672     MATCH_MP_TAC AFFINE_DEPENDENT_BIGGERSET THEN
6673     ASM_SIMP_TAC[FINITE_IMAGE] THEN
6674     MATCH_MP_TAC(ARITH_RULE
6675      `!f n. n >= d + 1 /\ f = SUC n /\ c = f ==> c >= d + 2`) THEN
6676     MAP_EVERY EXISTS_TAC [`CARD(f:(real^N->bool)->bool)`; `n:num`] THEN
6677     REPEAT(CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC]) THEN
6678     MATCH_MP_TAC CARD_IMAGE_INJ THEN ASM_MESON_TAC[];
6679     ALL_TAC] THEN
6680   ONCE_REWRITE_TAC[SET_RULE
6681    `P /\ m UNION p = s /\ Q <=>
6682     m SUBSET s /\ p SUBSET s /\ m UNION p = s /\ P /\ Q`] THEN
6683   REWRITE_TAC[SUBSET_IMAGE; DISJOINT] THEN
6684   REWRITE_TAC[MESON[]
6685    `(?m p. (?u. P u /\ m = t u) /\ (?u. P u /\ p = t u) /\ Q m p) ==> r <=>
6686     (!u v. P u /\ P v /\ Q (t u) (t v) ==> r)`] THEN
6687   MAP_EVERY X_GEN_TAC [`g:(real^N->bool)->bool`; `h:(real^N->bool)->bool`] THEN
6688   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6689   SUBGOAL_THEN `(f:(real^N->bool)->bool) = h UNION g` SUBST1_TAC THENL
6690    [MATCH_MP_TAC SUBSET_ANTISYM THEN ASM_REWRITE_TAC[UNION_SUBSET] THEN
6691     REWRITE_TAC[SUBSET; IN_UNION] THEN X_GEN_TAC `s:real^N->bool` THEN
6692     DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
6693     DISCH_THEN(MP_TAC o ISPEC `X:(real^N->bool)->real^N` o
6694       MATCH_MP FUN_IN_IMAGE) THEN
6695     FIRST_X_ASSUM(fun th ->
6696       GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM th]) THEN
6697     ONCE_REWRITE_TAC[DISJ_SYM] THEN REWRITE_TAC[IN_UNION; IN_IMAGE] THEN
6698     MATCH_MP_TAC MONO_OR THEN ASM_MESON_TAC[SUBSET];
6699     ALL_TAC] THEN
6700   MATCH_MP_TAC(SET_RULE
6701    `g SUBSET INTERS g' /\ h SUBSET INTERS h'
6702     ==> ~(g INTER h = {}) ==> ~(INTERS(g' UNION h') = {})`) THEN
6703   FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP (SET_RULE
6704    `IMAGE X s INTER IMAGE X t = {} ==> s INTER t = {}`)) THEN
6705   CONJ_TAC THEN MATCH_MP_TAC HULL_MINIMAL THEN
6706   (CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[SUBSET; CONVEX_INTERS]]) THEN
6707   REWRITE_TAC[SUBSET; IN_INTERS; FORALL_IN_IMAGE] THEN ASM SET_TAC[]);;
6708
6709 let HELLY = prove
6710  (`!f:(real^N->bool)->bool.
6711         FINITE f /\ CARD(f) >= dimindex(:N) + 1 /\
6712         (!s. s IN f ==> convex s) /\
6713         (!t. t SUBSET f /\ CARD(t) = dimindex(:N) + 1 ==> ~(INTERS t = {}))
6714         ==> ~(INTERS f = {})`,
6715   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC HELLY_INDUCT THEN
6716   ASM_REWRITE_TAC[HAS_SIZE] THEN ASM_MESON_TAC[]);;
6717
6718 let HELLY_ALT = prove
6719  (`!f:(real^N->bool)->bool.
6720         FINITE f /\
6721         (!s. s IN f ==> convex s) /\
6722         (!t. t SUBSET f /\ CARD(t) <= dimindex(:N) + 1 ==> ~(INTERS t = {}))
6723         ==> ~(INTERS f = {})`,
6724   GEN_TAC THEN STRIP_TAC THEN
6725   ASM_CASES_TAC `CARD(f:(real^N->bool)->bool) < dimindex(:N) + 1` THEN
6726   ASM_SIMP_TAC[SUBSET_REFL; LT_IMP_LE] THEN MATCH_MP_TAC HELLY THEN
6727   ASM_SIMP_TAC[GE; GSYM NOT_LT] THEN ASM_MESON_TAC[LE_REFL]);;
6728
6729 let HELLY_CLOSED_ALT = prove
6730  (`!f:(real^N->bool)->bool.
6731         (!s. s IN f ==> convex s /\ closed s) /\ (?s. s IN f /\ bounded s) /\
6732         (!t. t SUBSET f /\ FINITE t /\ CARD(t) <= dimindex(:N) + 1
6733              ==> ~(INTERS t = {}))
6734         ==> ~(INTERS f = {})`,
6735   GEN_TAC THEN
6736   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
6737   MATCH_MP_TAC CLOSED_FIP THEN ASM_SIMP_TAC[] THEN
6738   X_GEN_TAC `g:(real^N->bool)->bool` THEN STRIP_TAC THEN
6739   MATCH_MP_TAC HELLY_ALT THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
6740    [ASM SET_TAC[];
6741     ASM_MESON_TAC[SUBSET_TRANS; FINITE_SUBSET]]);;
6742
6743 let HELLY_COMPACT_ALT = prove
6744  (`!f:(real^N->bool)->bool.
6745         (!s. s IN f ==> convex s /\ compact s) /\
6746         (!t. t SUBSET f /\ FINITE t /\ CARD(t) <= dimindex(:N) + 1
6747              ==> ~(INTERS t = {}))
6748         ==> ~(INTERS f = {})`,
6749   GEN_TAC THEN STRIP_TAC THEN
6750   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
6751   ASM_REWRITE_TAC[INTERS_0; UNIV_NOT_EMPTY] THEN
6752   MATCH_MP_TAC HELLY_CLOSED_ALT THEN
6753   ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN
6754   ASM_MESON_TAC[MEMBER_NOT_EMPTY; COMPACT_IMP_BOUNDED]);;
6755
6756 let HELLY_CLOSED = prove
6757  (`!f:(real^N->bool)->bool.
6758         (FINITE f ==> CARD f >= dimindex (:N) + 1) /\
6759         (!s. s IN f ==> convex s /\ closed s) /\ (?s. s IN f /\ bounded s) /\
6760         (!t. t SUBSET f /\ FINITE t /\ CARD(t) = dimindex(:N) + 1
6761              ==> ~(INTERS t = {}))
6762         ==> ~(INTERS f = {})`,
6763   GEN_TAC THEN REWRITE_TAC[GE] THEN
6764   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
6765   MATCH_MP_TAC HELLY_CLOSED_ALT THEN ASM_REWRITE_TAC[] THEN
6766   X_GEN_TAC `g:(real^N->bool)->bool` THEN STRIP_TAC THEN
6767   MP_TAC(ISPECL [`dimindex(:N) + 1`; `g:(real^N->bool)->bool`;
6768                  `f:(real^N->bool)->bool`] CHOOSE_SUBSET_BETWEEN) THEN
6769   ASM_REWRITE_TAC[] THEN
6770   DISCH_THEN(X_CHOOSE_THEN `h:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
6771   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ ~(s = {}) ==> ~(t = {})`) THEN
6772   EXISTS_TAC `INTERS h: real^N->bool` THEN
6773   CONJ_TAC THENL [ASM SET_TAC[]; FIRST_X_ASSUM MATCH_MP_TAC] THEN
6774   ASM_MESON_TAC[HAS_SIZE]);;
6775
6776 let HELLY_COMPACT = prove
6777  (`!f:(real^N->bool)->bool.
6778         (FINITE f ==> CARD f >= dimindex (:N) + 1) /\
6779         (!s. s IN f ==> convex s /\ compact s) /\
6780         (!t. t SUBSET f /\ FINITE t /\ CARD(t) = dimindex(:N) + 1
6781              ==> ~(INTERS t = {}))
6782         ==> ~(INTERS f = {})`,
6783   GEN_TAC THEN STRIP_TAC THEN
6784   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
6785   ASM_REWRITE_TAC[INTERS_0; UNIV_NOT_EMPTY] THEN
6786   MATCH_MP_TAC HELLY_CLOSED THEN
6787   ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN
6788   ASM_MESON_TAC[MEMBER_NOT_EMPTY; COMPACT_IMP_BOUNDED]);;
6789
6790 (* ------------------------------------------------------------------------- *)
6791 (* Kirchberger's theorem                                                     *)
6792 (* ------------------------------------------------------------------------- *)
6793
6794 let KIRCHBERGER = prove
6795  (`!s t:real^N->bool.
6796         compact s /\ compact t /\
6797         (!s' t'. s' SUBSET s /\ t' SUBSET t /\ FINITE s' /\ FINITE t' /\
6798                  CARD(s') + CARD(t') <= dimindex(:N) + 2
6799                  ==> ?a b. (!x. x IN s' ==> a dot x < b) /\
6800                            (!x. x IN t' ==> a dot x > b))
6801         ==> ?a b. ~(a = vec 0) /\
6802                   (!x. x IN s ==> a dot x < b) /\
6803                   (!x. x IN t ==> a dot x > b)`,
6804   let lemma = prove
6805    (`(!x. x IN convex hull s ==> a dot x < b) /\
6806      (!x. x IN convex hull t ==> a dot x > b) <=>
6807      (!x. x IN s ==> a dot x < b) /\ (!x. x IN t ==> a dot x > b)`,
6808     REWRITE_TAC[SET_RULE `(!x. x IN s ==> P x) <=> s SUBSET {x | P x}`] THEN
6809     SIMP_TAC[SUBSET_HULL; CONVEX_HALFSPACE_LT; CONVEX_HALFSPACE_GT])
6810   and KIRCH_LEMMA = prove
6811    (`!s t:real^N->bool.
6812           FINITE s /\ FINITE t /\
6813           (!s' t'. s' SUBSET s /\ t' SUBSET t /\
6814                    CARD(s') + CARD(t') <= dimindex(:N) + 2
6815                    ==> ?a b. (!x. x IN s' ==> a dot x < b) /\
6816                              (!x. x IN t' ==> a dot x > b))
6817           ==> ?a b. (!x. x IN s ==> a dot x < b) /\
6818                     (!x. x IN t ==> a dot x > b)`,
6819     REPEAT STRIP_TAC THEN MP_TAC(ISPECL
6820      [`IMAGE (\r. {z:real^(N,1)finite_sum |
6821                           fstcart z dot r < drop(sndcart z)}) s UNION
6822        IMAGE (\r. {z:real^(N,1)finite_sum |
6823                           fstcart z dot r > drop(sndcart z)}) t`]
6824      HELLY_ALT) THEN
6825     REWRITE_TAC[FORALL_SUBSET_UNION; IN_UNION; IMP_CONJ] THEN
6826     REWRITE_TAC[RIGHT_FORALL_IMP_THM; FORALL_SUBSET_IMAGE] THEN
6827     ASM_SIMP_TAC[FINITE_UNION; FINITE_IMAGE; INTERS_UNION] THEN
6828     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; INTERS_IMAGE; IN_INTER;
6829                 EXISTS_PASTECART; IN_ELIM_PASTECART_THM;
6830                 FSTCART_PASTECART; SNDCART_PASTECART] THEN
6831     REWRITE_TAC[TAUT `p \/ q ==> r <=> (p ==> r) /\ (q ==> r)`] THEN
6832     REWRITE_TAC[FORALL_AND_THM; FORALL_IN_IMAGE; RIGHT_IMP_FORALL_THM] THEN
6833     REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC; GSYM EXISTS_DROP] THEN
6834     DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL
6835      [REWRITE_TAC[REAL_ARITH `a > b <=> --a < --b`; GSYM DOT_RNEG] THEN
6836       REWRITE_TAC[convex; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_GSPEC] THEN
6837       SIMP_TAC[PASTECART_ADD; GSYM PASTECART_CMUL; IN_ELIM_PASTECART_THM] THEN
6838       SIMP_TAC[DOT_LADD; DOT_LMUL; DROP_ADD; DROP_CMUL; GSYM FORALL_DROP] THEN
6839       REWRITE_TAC[REAL_ARITH `--(a * x + b * y):real = a * --x + b * --y`] THEN
6840       REPEAT STRIP_TAC THEN
6841       FIRST_ASSUM(MP_TAC o MATCH_MP (REAL_ARITH
6842        `u + v = &1
6843         ==> &0 <= u /\ &0 <= v
6844            ==> u = &0 /\ v = &1 \/ u = &1 /\ v = &0 \/ &0 < u /\ &0 < v`)) THEN
6845       ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
6846       ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID;
6847                       REAL_ADD_LID; REAL_ADD_RID] THEN
6848       MATCH_MP_TAC REAL_LT_ADD2 THEN ASM_SIMP_TAC[REAL_LT_LMUL_EQ];
6849       REWRITE_TAC[DIMINDEX_FINITE_SUM; DIMINDEX_1;
6850                   ARITH_RULE `(n + 1) + 1 = n + 2`] THEN
6851       MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
6852       DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
6853       SUBGOAL_THEN `FINITE(u:real^N->bool) /\ FINITE(v:real^N->bool)`
6854       STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
6855       W(MP_TAC o PART_MATCH (lhs o rand) CARD_UNION o lhand o lhand o snd) THEN
6856       ASM_SIMP_TAC[FINITE_IMAGE] THEN ANTS_TAC THENL
6857        [REWRITE_TAC[SET_RULE `IMAGE f s INTER IMAGE g t = {} <=>
6858                               !x y. x IN s /\ y IN t ==> ~(f x = g y)`] THEN
6859         MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
6860         REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
6861         DISCH_THEN(MP_TAC o SPEC `vec 0:real^N`) THEN
6862         REWRITE_TAC[GSYM FORALL_DROP; DOT_LZERO] THEN
6863         DISCH_THEN(MP_TAC o SPEC `&1`) THEN REAL_ARITH_TAC;
6864         DISCH_THEN SUBST1_TAC] THEN
6865       DISCH_THEN(fun th -> FIRST_X_ASSUM MATCH_MP_TAC THEN MP_TAC th) THEN
6866       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(ARITH_RULE
6867        `a = a' /\ b = b' ==> a + b <= n + 2 ==> a' + b' <= n + 2`) THEN
6868       CONJ_TAC THEN MATCH_MP_TAC CARD_IMAGE_INJ THEN
6869       ASM_REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
6870       SIMP_TAC[GSYM FORALL_DROP; real_gt; VECTOR_EQ_LDOT;
6871         MESON[REAL_LT_TOTAL; REAL_LT_REFL]
6872          `((!y:real. a < y <=> b < y) <=> a = b) /\
6873           ((!y:real. y < a <=> y < b) <=> a = b)`]]) in
6874   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM lemma] THEN
6875   MATCH_MP_TAC SEPARATING_HYPERPLANE_COMPACT_COMPACT THEN
6876   ASM_SIMP_TAC[CONVEX_CONVEX_HULL; COMPACT_CONVEX_HULL;
6877                CONVEX_HULL_EQ_EMPTY] THEN
6878   SUBGOAL_THEN
6879    `!s' t'. (s':real^N->bool) SUBSET s /\ t' SUBSET t /\
6880             FINITE s' /\ CARD(s') <= dimindex(:N) + 1 /\
6881             FINITE t' /\ CARD(t') <= dimindex(:N) + 1
6882             ==> DISJOINT (convex hull s') (convex hull t')`
6883   MP_TAC THENL
6884    [REPEAT STRIP_TAC THEN
6885     MP_TAC(ISPECL [`s':real^N->bool`; `t':real^N->bool`] KIRCH_LEMMA) THEN
6886     ANTS_TAC THENL
6887      [ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
6888       FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_MESON_TAC[SUBSET; FINITE_SUBSET];
6889       ONCE_REWRITE_TAC[GSYM lemma] THEN SET_TAC[REAL_LT_ANTISYM; real_gt]];
6890     POP_ASSUM_LIST(K ALL_TAC) THEN STRIP_TAC THEN
6891     REWRITE_TAC[SET_RULE `DISJOINT s t <=> !x. x IN s /\ x IN t ==> F`] THEN
6892     X_GEN_TAC `x:real^N` THEN ONCE_REWRITE_TAC[CARATHEODORY] THEN
6893     REWRITE_TAC[IN_ELIM_THM] THEN
6894     DISCH_THEN(CONJUNCTS_THEN2
6895       (X_CHOOSE_THEN `s':real^N->bool` STRIP_ASSUME_TAC)
6896       (X_CHOOSE_THEN `t':real^N->bool` STRIP_ASSUME_TAC)) THEN
6897     FIRST_X_ASSUM(MP_TAC o SPECL [`s':real^N->bool`; `t':real^N->bool`]) THEN
6898     ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;
6899
6900 (* ------------------------------------------------------------------------- *)
6901 (* Convex hull is "preserved" by a linear function.                          *)
6902 (* ------------------------------------------------------------------------- *)
6903
6904 let CONVEX_HULL_LINEAR_IMAGE = prove
6905  (`!f s. linear f ==> convex hull (IMAGE f s) = IMAGE f (convex hull s)`,
6906   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
6907   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
6908   CONJ_TAC THEN MATCH_MP_TAC HULL_INDUCT THEN
6909   REWRITE_TAC[FORALL_IN_IMAGE] THEN SIMP_TAC[FUN_IN_IMAGE; HULL_INC] THEN
6910   REWRITE_TAC[convex; IN_ELIM_THM] THEN
6911   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THENL
6912    [FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_CMUL th)]) THEN
6913     FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_ADD th)]) THEN
6914     REWRITE_TAC[IN_IMAGE] THEN
6915     MESON_TAC[REWRITE_RULE[convex] CONVEX_CONVEX_HULL];
6916     ASM_SIMP_TAC[LINEAR_ADD; LINEAR_CMUL] THEN
6917     MESON_TAC[REWRITE_RULE[convex] CONVEX_CONVEX_HULL]]);;
6918
6919 add_linear_invariants [CONVEX_HULL_LINEAR_IMAGE];;
6920
6921 let IN_CONVEX_HULL_LINEAR_IMAGE = prove
6922  (`!f:real^M->real^N s x.
6923         linear f /\ x IN convex hull s ==> (f x) IN convex hull (IMAGE f s)`,
6924   SIMP_TAC[CONVEX_HULL_LINEAR_IMAGE] THEN SET_TAC[]);;
6925
6926 (* ------------------------------------------------------------------------- *)
6927 (* Convexity of general and special intervals.                               *)
6928 (* ------------------------------------------------------------------------- *)
6929
6930 let IS_INTERVAL_CONVEX = prove
6931  (`!s:real^N->bool. is_interval s ==> convex s`,
6932   REWRITE_TAC[is_interval; convex] THEN
6933   REPEAT STRIP_TAC THEN FIRST_ASSUM MATCH_MP_TAC THEN
6934   MAP_EVERY EXISTS_TAC [`x:real^N`; `y:real^N`] THEN
6935   ASM_SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN
6936   GEN_TAC THEN STRIP_TAC THEN
6937   DISJ_CASES_TAC(SPECL [`(x:real^N)$i`; `(y:real^N)$i`] REAL_LE_TOTAL) THENL
6938    [DISJ1_TAC; DISJ2_TAC] THEN
6939   MATCH_MP_TAC(REAL_ARITH
6940    `&1 * a <= b /\ b <= &1 * c ==> a <= b /\ b <= c`) THEN
6941   FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
6942   ASM_SIMP_TAC[GSYM VECTOR_MUL_COMPONENT;
6943                VECTOR_ADD_RDISTRIB; VECTOR_ADD_COMPONENT] THEN
6944   ASM_SIMP_TAC[VECTOR_MUL_COMPONENT; REAL_LE_LMUL;
6945                REAL_LE_LADD; REAL_LE_RADD]);;
6946
6947 let IS_INTERVAL_CONNECTED = prove
6948  (`!s:real^N->bool. is_interval s ==> connected s`,
6949   MESON_TAC[IS_INTERVAL_CONVEX; CONVEX_CONNECTED]);;
6950
6951 let IS_INTERVAL_CONNECTED_1 = prove
6952  (`!s:real^1->bool. is_interval s <=> connected s`,
6953   GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[IS_INTERVAL_CONNECTED] THEN
6954   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
6955   REWRITE_TAC[IS_INTERVAL_1; connected; NOT_FORALL_THM; LEFT_IMP_EXISTS_THM;
6956               NOT_IMP; FORALL_LIFT; LIFT_DROP] THEN
6957   MAP_EVERY X_GEN_TAC [`a:real`; `b:real`; `x:real`] THEN STRIP_TAC THEN
6958   MAP_EVERY EXISTS_TAC
6959    [`{z:real^1 | basis 1 dot z < x}`; `{z:real^1 | basis 1 dot z > x}`] THEN
6960   REWRITE_TAC[OPEN_HALFSPACE_LT; OPEN_HALFSPACE_GT] THEN
6961   SIMP_TAC[SUBSET; EXTENSION; IN_UNION; IN_INTER; GSYM drop; NOT_FORALL_THM;
6962    real_gt; NOT_IN_EMPTY; IN_ELIM_THM; DOT_BASIS; DIMINDEX_1; ARITH] THEN
6963   REPEAT CONJ_TAC THENL
6964    [ASM_MESON_TAC[REAL_LT_TOTAL; LIFT_DROP];
6965     REAL_ARITH_TAC;
6966     EXISTS_TAC `lift a`;
6967     EXISTS_TAC `lift b`] THEN
6968   ASM_REWRITE_TAC[REAL_LT_LE; LIFT_DROP] THEN ASM_MESON_TAC[]);;
6969
6970 let CONVEX_INTERVAL = prove
6971  (`!a b:real^N. convex(interval [a,b]) /\ convex(interval (a,b))`,
6972   SIMP_TAC[IS_INTERVAL_CONVEX; IS_INTERVAL_INTERVAL]);;
6973
6974 let CONNECTED_INTERVAL = prove
6975  (`(!a b:real^N. connected(interval[a,b])) /\
6976    (!a b:real^N. connected(interval(a,b)))`,
6977   SIMP_TAC[CONVEX_CONNECTED; CONVEX_INTERVAL]);;
6978
6979 (* ------------------------------------------------------------------------- *)
6980 (* On real^1, is_interval, convex and connected are all equivalent.          *)
6981 (* ------------------------------------------------------------------------- *)
6982
6983 let IS_INTERVAL_CONVEX_1 = prove
6984  (`!s:real^1->bool. is_interval s <=> convex s`,
6985   MESON_TAC[IS_INTERVAL_CONVEX; CONVEX_CONNECTED; IS_INTERVAL_CONNECTED_1]);;
6986
6987 let CONVEX_CONNECTED_1 = prove
6988  (`!s:real^1->bool. convex s <=> connected s`,
6989   REWRITE_TAC[GSYM IS_INTERVAL_CONVEX_1; GSYM IS_INTERVAL_CONNECTED_1]);;
6990
6991 let CONNECTED_CONVEX_1 = prove
6992  (`!s:real^1->bool. connected s <=> convex s`,
6993   REWRITE_TAC[GSYM IS_INTERVAL_CONVEX_1; GSYM IS_INTERVAL_CONNECTED_1]);;
6994
6995 let CONNECTED_COMPACT_INTERVAL_1 = prove
6996  (`!s:real^1->bool. connected s /\ compact s <=> ?a b. s = interval[a,b]`,
6997   REWRITE_TAC[GSYM IS_INTERVAL_CONNECTED_1; IS_INTERVAL_COMPACT]);;
6998
6999 let CONVEX_CONNECTED_1_GEN = prove
7000  (`!s:real^N->bool.
7001         dimindex(:N) = 1 ==> (convex s <=> connected s)`,
7002   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN
7003   REWRITE_TAC[GSYM DIMINDEX_1] THEN
7004   DISCH_THEN(ACCEPT_TAC o C GEOM_EQUAL_DIMENSION_RULE CONVEX_CONNECTED_1));;
7005
7006 let CONNECTED_CONVEX_1_GEN = prove
7007  (`!s:real^N->bool.
7008         dimindex(:N) = 1 ==> (convex s <=> connected s)`,
7009   SIMP_TAC[CONVEX_CONNECTED_1_GEN]);;
7010
7011 (* ------------------------------------------------------------------------- *)
7012 (* Jung's theorem.                                                           *)
7013 (* Proof taken from http://cstheory.wordpress.com/2010/08/07/jungs-theorem/  *)
7014 (* ------------------------------------------------------------------------- *)
7015
7016 let JUNG = prove
7017  (`!s:real^N->bool r.
7018         bounded s /\
7019         sqrt(&(dimindex(:N)) / &(2 * dimindex(:N) + 2)) * diameter s <= r
7020         ==> ?a. s SUBSET cball(a,r)`,
7021   let lemma = prove
7022    (`&0 < x /\ x <= y ==> (x - &1) / x <= (y - &1) / y`,
7023     SIMP_TAC[REAL_LE_LDIV_EQ] THEN REPEAT STRIP_TAC THEN
7024     ONCE_REWRITE_TAC[REAL_ARITH `x / y * z:real = (x * z) / y`] THEN
7025     SUBGOAL_THEN `&0 < y` ASSUME_TAC THENL
7026      [ASM_REAL_ARITH_TAC; ASM_SIMP_TAC[REAL_LE_RDIV_EQ]] THEN
7027     ASM_REAL_ARITH_TAC) in
7028   REPEAT STRIP_TAC THEN
7029   SUBGOAL_THEN `&0 <= r` ASSUME_TAC THENL
7030    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
7031         REAL_LE_TRANS)) THEN
7032     MATCH_MP_TAC REAL_LE_MUL THEN ASM_SIMP_TAC[DIAMETER_POS_LE] THEN
7033     SIMP_TAC[SQRT_POS_LE; REAL_LE_DIV; REAL_POS];
7034     ALL_TAC] THEN
7035   MP_TAC(ISPEC `IMAGE (\x:real^N. cball(x,r)) s` HELLY_COMPACT_ALT) THEN
7036   REWRITE_TAC[FORALL_IN_IMAGE; COMPACT_CBALL; CONVEX_CBALL] THEN
7037   REWRITE_TAC[TAUT `p /\ q /\ r ==> s <=> q /\ p ==> r ==> s`] THEN
7038   REWRITE_TAC[FORALL_FINITE_SUBSET_IMAGE] THEN
7039   REWRITE_TAC[INTERS_IMAGE; GSYM MEMBER_NOT_EMPTY] THEN
7040   REWRITE_TAC[SUBSET; IN_CBALL; IN_ELIM_THM] THEN
7041   ANTS_TAC THENL [ALL_TAC; MESON_TAC[DIST_SYM]] THEN
7042   X_GEN_TAC `t:real^N->bool` THEN REWRITE_TAC[GSYM SUBSET] THEN
7043   STRIP_TAC THEN
7044   ASM_SIMP_TAC[CARD_IMAGE_INJ; EQ_BALLS; GSYM REAL_NOT_LE] THEN
7045   UNDISCH_TAC `FINITE(t:real^N->bool)` THEN
7046   SUBGOAL_THEN `bounded(t:real^N->bool)` MP_TAC THENL
7047    [ASM_MESON_TAC[BOUNDED_SUBSET]; ALL_TAC] THEN
7048   UNDISCH_TAC `&0 <= r` THEN
7049   SUBGOAL_THEN
7050    `sqrt(&(dimindex(:N)) / &(2 * dimindex(:N) + 2)) *
7051     diameter(t:real^N->bool) <= r`
7052   MP_TAC THENL
7053    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
7054         REAL_LE_TRANS)) THEN
7055     MATCH_MP_TAC REAL_LE_LMUL THEN
7056     ASM_SIMP_TAC[DIAMETER_SUBSET; SQRT_POS_LE; REAL_POS; REAL_LE_DIV];
7057     POP_ASSUM_LIST(K ALL_TAC) THEN
7058     SPEC_TAC(`t:real^N->bool`,`s:real^N->bool`) THEN
7059     REPEAT STRIP_TAC] THEN
7060   ASM_CASES_TAC `s:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
7061   MP_TAC(ISPEC `{d | &0 <= d /\ ?a:real^N. s SUBSET cball(a,d)}` INF) THEN
7062   ABBREV_TAC `d = inf {d | &0 <= d /\ ?a:real^N. s SUBSET cball(a,d)}` THEN
7063   REWRITE_TAC[IN_ELIM_THM] THEN ANTS_TAC THENL
7064    [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
7065     ASM_MESON_TAC[BOUNDED_SUBSET_CBALL; REAL_LT_IMP_LE];
7066     DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "P") (LABEL_TAC "M"))] THEN
7067   SUBGOAL_THEN `&0 <= d` ASSUME_TAC THENL
7068    [ASM_MESON_TAC[REAL_LE_REFL]; ALL_TAC] THEN
7069   SUBGOAL_THEN `?a:real^N. s SUBSET cball(a,d)` MP_TAC THENL
7070    [SUBGOAL_THEN
7071      `!n. ?a:real^N. s SUBSET cball(a,d + inv(&n + &1))`
7072     MP_TAC THENL
7073      [X_GEN_TAC `n:num` THEN
7074       REMOVE_THEN "M" (MP_TAC o SPEC `d + inv(&n + &1)`) THEN
7075       REWRITE_TAC[REAL_ARITH `d + i <= d <=> ~(&0 < i)`] THEN
7076       REWRITE_TAC[REAL_LT_INV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
7077       REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; REAL_NOT_LE] THEN
7078       MESON_TAC[SUBSET_CBALL; REAL_LT_IMP_LE; SUBSET_TRANS];
7079       ALL_TAC] THEN
7080     REWRITE_TAC[LEFT_IMP_EXISTS_THM; SKOLEM_THM] THEN
7081     X_GEN_TAC `aa:num->real^N` THEN DISCH_TAC THEN
7082     SUBGOAL_THEN `?t. compact t /\ !n. (aa:num->real^N) n IN t` MP_TAC THENL
7083      [FIRST_X_ASSUM(MP_TAC o SPEC `vec 0:real^N` o
7084         MATCH_MP BOUNDED_SUBSET_CBALL) THEN
7085       REWRITE_TAC[LEFT_IMP_EXISTS_THM; SUBSET; IN_CBALL_0] THEN
7086       X_GEN_TAC `B:real` THEN STRIP_TAC THEN
7087       EXISTS_TAC `cball(vec 0:real^N,B + d + &1)` THEN
7088       REWRITE_TAC[COMPACT_CBALL; IN_CBALL_0] THEN X_GEN_TAC `n:num` THEN
7089       RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; IN_CBALL]) THEN
7090       MATCH_MP_TAC(NORM_ARITH
7091        `(?x:real^N. norm(x) <= B /\ dist(a,x) <= d) ==> norm(a) <= B + d`) THEN
7092       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
7093       MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM_SIMP_TAC[] THEN
7094       MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `d + inv(&n + &1)` THEN
7095       ASM_SIMP_TAC[REAL_LE_LADD] THEN
7096       MATCH_MP_TAC REAL_INV_LE_1 THEN REAL_ARITH_TAC;
7097       ALL_TAC] THEN
7098     REWRITE_TAC[compact; LEFT_IMP_EXISTS_THM] THEN
7099     X_GEN_TAC `t:real^N->bool` THEN
7100     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
7101     DISCH_THEN(MP_TAC o SPEC `aa:num->real^N`) THEN ASM_REWRITE_TAC[] THEN
7102     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
7103     DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN
7104     REWRITE_TAC[SUBSET; IN_CBALL] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7105     REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
7106     MP_TAC(SPEC `(dist(a:real^N,x) - d) / &2` REAL_ARCH_INV) THEN
7107     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
7108     DISCH_THEN(MP_TAC o SPEC `(dist(a:real^N,x) - d) / &2`) THEN
7109     ASM_SIMP_TAC[REAL_SUB_LT; REAL_HALF; o_THM] THEN
7110     DISCH_THEN(X_CHOOSE_THEN `N1:num` STRIP_ASSUME_TAC) THEN
7111     DISCH_THEN(X_CHOOSE_THEN `N2:num` STRIP_ASSUME_TAC) THEN
7112     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE BINDER_CONV [SUBSET]) THEN
7113     DISCH_THEN(MP_TAC o SPECL [`(r:num->num)(N1 + N2)`; `x:real^N`]) THEN
7114     ASM_REWRITE_TAC[IN_CBALL; REAL_NOT_LE] THEN
7115     FIRST_X_ASSUM(MP_TAC o SPEC `N1 + N2:num`) THEN
7116     ASM_REWRITE_TAC[LE_ADD] THEN
7117     SUBGOAL_THEN `inv(&(r (N1 + N2:num)) + &1) < (dist(a:real^N,x) - d) / &2`
7118     MP_TAC THENL [ALL_TAC; NORM_ARITH_TAC] THEN
7119     MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&N2)` THEN
7120     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
7121     CONJ_TAC THENL [ASM_MESON_TAC[REAL_LT_INV_EQ]; ALL_TAC] THEN
7122     REWRITE_TAC[REAL_OF_NUM_LE; REAL_OF_NUM_ADD] THEN
7123     MATCH_MP_TAC(ARITH_RULE
7124       `N1 + N2 <= r(N1 + N2) ==> N2 <= r(N1 + N2) + 1`) THEN
7125     ASM_MESON_TAC[MONOTONE_BIGGER];
7126     ALL_TAC] THEN
7127   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
7128   ONCE_REWRITE_TAC[DIST_SYM] THEN
7129   REWRITE_TAC[GSYM IN_CBALL; GSYM SUBSET] THEN
7130   DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
7131   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] SUBSET_TRANS) THEN
7132   MATCH_MP_TAC SUBSET_CBALL THEN
7133   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
7134    `a * s <= r ==> d <= a * s ==> d <= r`)) THEN
7135   UNDISCH_THEN `&0 <= r` (K ALL_TAC) THEN REMOVE_THEN "M" (K ALL_TAC) THEN
7136   FIRST_X_ASSUM(K ALL_TAC o SYM) THEN REMOVE_THEN "P" MP_TAC THEN
7137   REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
7138   ABBREV_TAC `n = CARD(s:real^N->bool)` THEN
7139   SUBGOAL_THEN `(s:real^N->bool) HAS_SIZE n` MP_TAC THENL
7140    [ASM_REWRITE_TAC[HAS_SIZE]; ALL_TAC] THEN
7141   UNDISCH_THEN `CARD(s:real^N->bool) = n` (K ALL_TAC) THEN
7142   POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
7143   SPEC_TAC(`d:real`,`r:real`) THEN GEN_TAC THEN
7144   GEOM_ORIGIN_TAC `a:real^N` THEN SIMP_TAC[HAS_SIZE] THEN
7145   REPEAT STRIP_TAC THEN FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN
7146   ABBREV_TAC `t = {x:real^N | x IN s /\ norm(x) = r}` THEN
7147   SUBGOAL_THEN `FINITE(t:real^N->bool)` ASSUME_TAC THENL
7148    [EXPAND_TAC "t" THEN ASM_SIMP_TAC[FINITE_RESTRICT]; ALL_TAC] THEN
7149   SUBGOAL_THEN `(vec 0:real^N) IN convex hull t` MP_TAC THENL
7150    [MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
7151     MP_TAC(ISPEC `convex hull t:real^N->bool`
7152       SEPARATING_HYPERPLANE_CLOSED_0) THEN
7153     ASM_SIMP_TAC[CONVEX_CONVEX_HULL; NOT_IMP; COMPACT_CONVEX_HULL;
7154                  FINITE_IMP_COMPACT; COMPACT_IMP_CLOSED] THEN
7155     REWRITE_TAC[NOT_EXISTS_THM; TAUT `~(p /\ q) <=> p ==> ~q`] THEN
7156     X_GEN_TAC `v:real^N` THEN
7157     ABBREV_TAC `k = CARD(s:real^N->bool)` THEN
7158     SUBGOAL_THEN `(s:real^N->bool) HAS_SIZE k` MP_TAC THENL
7159      [ASM_REWRITE_TAC[HAS_SIZE]; ALL_TAC] THEN
7160     UNDISCH_THEN `CARD(s:real^N->bool) = k` (K ALL_TAC) THEN
7161     POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
7162     GEOM_BASIS_MULTIPLE_TAC 1 `v:real^N` THEN X_GEN_TAC `m:real` THEN
7163     GEN_REWRITE_TAC LAND_CONV [REAL_ARITH `&0 <= x <=> x = &0 \/ &0 < x`] THEN
7164     STRIP_TAC THEN ASM_REWRITE_TAC[VECTOR_MUL_EQ_0] THEN
7165     ASM_SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL; REAL_LT_IMP_NZ] THEN
7166     REPEAT GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[HAS_SIZE] THEN
7167     DISCH_THEN(SUBST_ALL_TAC o SYM) THEN X_GEN_TAC `b:real` THEN DISCH_TAC THEN
7168     ASM_SIMP_TAC[DOT_LMUL; DOT_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
7169     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
7170     ASM_SIMP_TAC[real_gt; GSYM REAL_LT_LDIV_EQ] THEN
7171     SUBGOAL_THEN `&0 < b / m` MP_TAC THENL
7172      [ASM_SIMP_TAC[REAL_LT_DIV];
7173       UNDISCH_THEN `&0 < b` (K ALL_TAC) THEN
7174       SPEC_TAC(`b / m:real`,`b:real`)] THEN
7175     X_GEN_TAC `b:real` THEN DISCH_TAC THEN DISCH_TAC THEN
7176     SUBGOAL_THEN
7177      `!x:real^N e. &0 < e /\ e < b /\ x IN t ==> norm(x - e % basis 1) < r`
7178     ASSUME_TAC THENL
7179      [MAP_EVERY X_GEN_TAC [`x:real^N`; `e:real`] THEN STRIP_TAC THEN
7180       SUBGOAL_THEN `r = norm(x:real^N)` SUBST1_TAC THENL
7181        [ASM SET_TAC[]; REWRITE_TAC[NORM_LT; dot]] THEN
7182       SIMP_TAC[SUM_CLAUSES_LEFT; DIMINDEX_GE_1] THEN
7183       SIMP_TAC[VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT;
7184                BASIS_COMPONENT; DIMINDEX_GE_1; LE_REFL;
7185                ARITH_RULE `2 <= n ==> 1 <= n /\ ~(n = 1)`; ARITH] THEN
7186       REWRITE_TAC[REAL_MUL_RZERO; REAL_SUB_RZERO; REAL_LT_RADD] THEN
7187       REWRITE_TAC[GSYM REAL_POW_2; GSYM REAL_LT_SQUARE_ABS] THEN
7188       MATCH_MP_TAC(REAL_ARITH
7189        `!b. &0 < e /\ e < b /\ b < x ==> abs(x - e * &1) < abs x`) THEN
7190       EXISTS_TAC `b:real` THEN ASM_REWRITE_TAC[] THEN
7191       ASM_MESON_TAC[HULL_INC];
7192       ALL_TAC] THEN
7193     SUBGOAL_THEN
7194      `?d. &0 < d /\
7195           !x:real^N a. x IN (s DIFF t) /\ norm(a) < d ==> norm(x - a) < r`
7196     STRIP_ASSUME_TAC THENL
7197      [ASM_CASES_TAC `s DIFF t:real^N->bool = {}` THENL
7198        [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN MESON_TAC[REAL_LT_01]; ALL_TAC] THEN
7199       EXISTS_TAC `inf (IMAGE (\x:real^N. r - norm x) (s DIFF t))` THEN
7200       SUBGOAL_THEN `FINITE(s DIFF t:real^N->bool)` ASSUME_TAC THENL
7201        [ASM_MESON_TAC[FINITE_DIFF]; ALL_TAC] THEN
7202       ASM_SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
7203       REWRITE_TAC[FORALL_IN_IMAGE] THEN SIMP_TAC
7204        [NORM_ARITH `norm a < r - norm x ==> norm(x - a:real^N) < r`] THEN
7205       EXPAND_TAC "t" THEN REWRITE_TAC[IN_DIFF; IN_ELIM_THM; REAL_SUB_LT] THEN
7206       RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; IN_CBALL_0]) THEN
7207       ASM_MESON_TAC[REAL_LT_LE];
7208       ALL_TAC] THEN
7209     SUBGOAL_THEN
7210      `?a. !x. x IN s ==> norm(x - a:real^N) < r`
7211     STRIP_ASSUME_TAC THENL
7212      [EXISTS_TAC `min (b / &2) (d / &2) % basis 1:real^N` THEN
7213       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7214       ASM_CASES_TAC `(x:real^N) IN t` THENL
7215        [MATCH_MP_TAC(ASSUME
7216          `!x:real^N e. &0 < e /\ e < b /\ x IN t
7217                        ==> norm (x - e % basis 1) < r`) THEN
7218         ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
7219         MATCH_MP_TAC(ASSUME
7220          `!x:real^N a. x IN s DIFF t /\ norm a < d ==> norm (x - a) < r`) THEN
7221         ASM_SIMP_TAC[IN_DIFF; NORM_MUL; LE_REFL; NORM_BASIS;
7222                      DIMINDEX_GE_1] THEN
7223         ASM_REAL_ARITH_TAC];
7224       SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL
7225        [ASM_MESON_TAC[MEMBER_NOT_EMPTY; NORM_ARITH
7226          `norm(x:real^N) < r ==> &0 < r`];
7227         ALL_TAC] THEN
7228       UNDISCH_THEN
7229         `!x a:real^N. &0 <= x /\ s SUBSET cball (a,x) ==> r <= x` (MP_TAC o
7230         SPECL [`max (&0) (r - inf (IMAGE (\x:real^N. r - norm(x - a)) s))`;
7231                `a:real^N`]) THEN
7232       ASM_SIMP_TAC[REAL_ARITH `&0 < r ==> (r <= max (&0) a <=> r <= a)`] THEN
7233       REWRITE_TAC[SUBSET; IN_CBALL; REAL_ARITH `a <= max a b`] THEN
7234       REWRITE_TAC[NOT_IMP; REAL_ARITH `~(r <= r - x) <=> &0 < x`] THEN
7235       ASM_SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
7236       ASM_REWRITE_TAC[FORALL_IN_IMAGE; REAL_SUB_LT] THEN
7237       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7238       MATCH_MP_TAC(REAL_ARITH `d <= b ==> d <= max a b`) THEN
7239       ONCE_REWRITE_TAC[REAL_ARITH `a <= b - c <=> c <= b - a`] THEN
7240       ASM_SIMP_TAC[REAL_INF_LE_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
7241       REWRITE_TAC[EXISTS_IN_IMAGE; ONCE_REWRITE_RULE[NORM_SUB] dist] THEN
7242       ASM_MESON_TAC[REAL_LE_REFL]];
7243     ALL_TAC] THEN
7244   ASM_CASES_TAC `t:real^N->bool = {}` THEN
7245   ASM_REWRITE_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY] THEN
7246   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
7247   DISCH_THEN(X_CHOOSE_THEN `l:real^N->real` STRIP_ASSUME_TAC) THEN
7248   MATCH_MP_TAC REAL_LE_TRANS THEN
7249   EXISTS_TAC `sqrt((&(dimindex (:N)) / &(2 * dimindex (:N) + 2)) *
7250                    diameter(s:real^N->bool) pow 2)` THEN
7251   CONJ_TAC THENL
7252    [MATCH_MP_TAC REAL_LE_RSQRT;
7253     ASM_SIMP_TAC[SQRT_MUL; DIAMETER_POS_LE; REAL_POW_LE; REAL_LE_DIV;
7254                  REAL_POS; POW_2_SQRT; REAL_LE_REFL]] THEN
7255
7256   SUBGOAL_THEN
7257    `sum t (\y:real^N. &2 * r pow 2) <=
7258     sum t (\y. (&1 - l y) * diameter(s:real^N->bool) pow 2)`
7259   MP_TAC THENL
7260    [MATCH_MP_TAC SUM_LE THEN ASM_REWRITE_TAC[] THEN
7261     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7262     MATCH_MP_TAC REAL_LE_TRANS THEN
7263     EXISTS_TAC `sum (t DELETE x) (\x:real^N. l(x)) *
7264                 diameter(s:real^N->bool) pow 2` THEN CONJ_TAC THENL
7265      [ALL_TAC; ASM_SIMP_TAC[SUM_DELETE; ETA_AX; REAL_LE_REFL]] THEN
7266     REWRITE_TAC[GSYM SUM_RMUL] THEN MATCH_MP_TAC REAL_LE_TRANS THEN
7267     EXISTS_TAC `sum (t DELETE x) (\y:real^N. l y * norm(y - x) pow 2)` THEN
7268     CONJ_TAC THENL
7269      [ALL_TAC;
7270       MATCH_MP_TAC SUM_LE THEN ASM_REWRITE_TAC[FINITE_DELETE; IN_DELETE] THEN
7271       X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN MATCH_MP_TAC REAL_LE_LMUL THEN
7272       ASM_SIMP_TAC[] THEN MATCH_MP_TAC REAL_POW_LE2 THEN
7273       REWRITE_TAC[NORM_POS_LE] THEN
7274       MATCH_MP_TAC DIAMETER_BOUNDED_BOUND THEN ASM SET_TAC[]] THEN
7275     MATCH_MP_TAC REAL_LE_TRANS THEN
7276     EXISTS_TAC `sum t (\y:real^N. l y * norm (y - x) pow 2)` THEN
7277     CONJ_TAC THENL
7278      [ALL_TAC;
7279       MATCH_MP_TAC REAL_EQ_IMP_LE THEN MATCH_MP_TAC SUM_EQ_SUPERSET THEN
7280       ASM_REWRITE_TAC[FINITE_DELETE] THEN
7281       CONJ_TAC THENL [SET_TAC[]; REWRITE_TAC[IN_DELETE]] THEN
7282       SIMP_TAC[TAUT `p /\ ~(p /\ ~q) <=> p /\ q`] THEN
7283       REWRITE_TAC[VECTOR_SUB_REFL; NORM_0] THEN REAL_ARITH_TAC] THEN
7284     REWRITE_TAC[NORM_POW_2; VECTOR_ARITH
7285      `(y - x:real^N) dot (y - x) = (x dot x + y dot y) - &2 * x dot y`] THEN
7286     MATCH_MP_TAC REAL_LE_TRANS THEN
7287     EXISTS_TAC `sum t (\y:real^N. l y * (&2 * r pow 2 - &2 * (x dot y)))` THEN
7288     CONJ_TAC THENL
7289      [ALL_TAC;
7290       MATCH_MP_TAC REAL_EQ_IMP_LE THEN MATCH_MP_TAC SUM_EQ THEN
7291       UNDISCH_TAC `(x:real^N) IN t` THEN EXPAND_TAC "t" THEN
7292       REWRITE_TAC[IN_DELETE; IN_ELIM_THM] THEN
7293       SIMP_TAC[NORM_EQ_SQUARE; NORM_POW_2] THEN REAL_ARITH_TAC] THEN
7294     REWRITE_TAC[REAL_ARITH `x * (&2 * y - &2 * z) = &2 * (x * y - x * z)`] THEN
7295     REWRITE_TAC[SUM_LMUL] THEN MATCH_MP_TAC REAL_LE_LMUL THEN
7296     REWRITE_TAC[REAL_POS] THEN
7297     ASM_SIMP_TAC[SUM_SUB; FINITE_DELETE; SUM_RMUL] THEN
7298     REWRITE_TAC[GSYM DOT_RMUL] THEN
7299     ASM_SIMP_TAC[GSYM DOT_RSUM; DOT_RZERO] THEN REAL_ARITH_TAC;
7300     ASM_SIMP_TAC[SUM_CONST; SUM_RMUL; SUM_SUB] THEN
7301     REWRITE_TAC[REAL_OF_NUM_MUL; MULT_CLAUSES] THEN
7302     GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [REAL_MUL_SYM] THEN
7303     SUBGOAL_THEN `&0 < &(CARD(t:real^N->bool) * 2)` ASSUME_TAC THENL
7304      [REWRITE_TAC[REAL_OF_NUM_LT; ARITH_RULE `0 < n * 2 <=> ~(n = 0)`] THEN
7305       ASM_SIMP_TAC[CARD_EQ_0];
7306       ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ] THEN
7307       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
7308       REWRITE_TAC[REAL_ARITH `(a * b) / c:real = a / c * b`] THEN
7309       MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_LE_POW_2] THEN
7310       REWRITE_TAC[ARITH_RULE `2 * n + 2 = (n + 1) * 2`; GSYM REAL_OF_NUM_MUL;
7311                   real_div; REAL_INV_MUL; REAL_MUL_ASSOC] THEN
7312       MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[GSYM real_div] THEN
7313       CONV_TAC REAL_RAT_REDUCE_CONV THEN
7314       SUBGOAL_THEN `&(dimindex(:N)) = &(dimindex(:N) + 1) - &1`
7315       SUBST1_TAC THENL
7316        [REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN REAL_ARITH_TAC;
7317         MATCH_MP_TAC lemma THEN
7318         ASM_SIMP_TAC[REAL_OF_NUM_LE; REAL_OF_NUM_LT; CARD_EQ_0;
7319                      ARITH_RULE `0 < n <=> ~(n = 0)`] THEN
7320         MATCH_MP_TAC LE_TRANS THEN EXISTS_TAC `CARD(s:real^N->bool)` THEN
7321         ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CARD_SUBSET THEN
7322         ASM SET_TAC[]]]]);;
7323
7324 (* ------------------------------------------------------------------------- *)
7325 (* Convex cones and corresponding hulls.                                     *)
7326 (* ------------------------------------------------------------------------- *)
7327
7328 let convex_cone = new_definition
7329  `convex_cone s <=> ~(s = {}) /\ convex s /\ conic s`;;
7330
7331 let CONVEX_CONE = prove
7332  (`!s:real^N->bool.
7333      convex_cone s <=>
7334         vec 0 IN s /\
7335         (!x y. x IN s /\ y IN s ==> (x + y) IN s) /\
7336         (!x c. x IN s /\ &0 <= c ==> (c % x) IN s)`,
7337   GEN_TAC THEN REWRITE_TAC[convex_cone; GSYM conic] THEN
7338   ASM_CASES_TAC `conic(s:real^N->bool)` THEN
7339   ASM_SIMP_TAC[CONIC_CONTAINS_0] THEN AP_TERM_TAC THEN
7340   RULE_ASSUM_TAC(REWRITE_RULE[conic]) THEN
7341   REWRITE_TAC[convex] THEN EQ_TAC THEN
7342   ASM_SIMP_TAC[REAL_SUB_LE] THEN DISCH_TAC THEN
7343   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
7344   FIRST_X_ASSUM(MP_TAC o SPECL
7345    [`&2 % (x:real^N)`; `&2 % (y:real^N)`; `&1 / &2`; `&1 / &2`]) THEN
7346   REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
7347   ASM_SIMP_TAC[VECTOR_MUL_LID; REAL_POS]);;
7348
7349 let CONVEX_CONE_LINEAR_IMAGE = prove
7350  (`!f:real^M->real^N s.
7351         convex_cone s /\ linear f ==> convex_cone(IMAGE f s)`,
7352   SIMP_TAC[convex_cone; CONVEX_LINEAR_IMAGE; IMAGE_EQ_EMPTY;
7353            CONIC_LINEAR_IMAGE]);;
7354
7355 let CONVEX_CONE_LINEAR_IMAGE_EQ = prove
7356  (`!f:real^M->real^N s.
7357         linear f /\ (!x y. f x = f y ==> x = y)
7358         ==> (convex_cone(IMAGE f s) <=> convex_cone s)`,
7359   REWRITE_TAC[convex_cone] THEN
7360   MESON_TAC[IMAGE_EQ_EMPTY; CONVEX_LINEAR_IMAGE_EQ; CONIC_LINEAR_IMAGE_EQ]);;
7361
7362 add_linear_invariants [CONVEX_CONE_LINEAR_IMAGE_EQ];;
7363
7364 let CONVEX_CONE_HALFSPACE_GE = prove
7365  (`!a. convex_cone {x | a dot x >= &0}`,
7366   SIMP_TAC[CONVEX_CONE; real_ge; IN_ELIM_THM; DOT_RZERO; DOT_RADD; DOT_RMUL;
7367            REAL_LE_ADD; REAL_LE_MUL; REAL_LE_REFL]);;
7368
7369 let CONVEX_CONE_HALFSPACE_LE = prove
7370  (`!a. convex_cone {x | a dot x <= &0}`,
7371   REWRITE_TAC[REAL_ARITH `x <= &0 <=> &0 <= --x`; GSYM DOT_LNEG] THEN
7372   REWRITE_TAC[GSYM real_ge; CONVEX_CONE_HALFSPACE_GE]);;
7373
7374 let CONVEX_CONE_CONTAINS_0 = prove
7375  (`!s:real^N->bool. convex_cone s ==> vec 0 IN s`,
7376   SIMP_TAC[CONVEX_CONE]);;
7377
7378 let CONVEX_CONE_INTERS = prove
7379  (`!f. (!s:real^N->bool. s IN f ==> convex_cone s) ==> convex_cone(INTERS f)`,
7380   SIMP_TAC[convex_cone; CONIC_INTERS; CONVEX_INTERS] THEN
7381   REWRITE_TAC[GSYM convex_cone] THEN GEN_TAC THEN DISCH_TAC THEN
7382   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `vec 0:real^N` THEN
7383   ASM_SIMP_TAC[IN_INTERS; CONVEX_CONE_CONTAINS_0]);;
7384
7385 let CONVEX_CONE_CONVEX_CONE_HULL = prove
7386  (`!s. convex_cone(convex_cone hull s)`,
7387   SIMP_TAC[P_HULL; CONVEX_CONE_INTERS]);;
7388
7389 let CONVEX_CONVEX_CONE_HULL = prove
7390  (`!s. convex(convex_cone hull s)`,
7391   MESON_TAC[CONVEX_CONE_CONVEX_CONE_HULL; convex_cone]);;
7392
7393 let CONIC_CONVEX_CONE_HULL = prove
7394  (`!s. conic(convex_cone hull s)`,
7395   MESON_TAC[CONVEX_CONE_CONVEX_CONE_HULL; convex_cone]);;
7396
7397 let CONVEX_CONE_HULL_NONEMPTY = prove
7398  (`!s. ~(convex_cone hull s = {})`,
7399   MESON_TAC[CONVEX_CONE_CONVEX_CONE_HULL; convex_cone]);;
7400
7401 let CONVEX_CONE_HULL_CONTAINS_0 = prove
7402  (`!s. vec 0 IN convex_cone hull s`,
7403   MESON_TAC[CONVEX_CONE_CONVEX_CONE_HULL; CONVEX_CONE]);;
7404
7405 let CONVEX_CONE_HULL_ADD = prove
7406  (`!s x y:real^N.
7407         x IN convex_cone hull s /\ y IN convex_cone hull s
7408         ==> x + y IN convex_cone hull s`,
7409   MESON_TAC[CONVEX_CONE; CONVEX_CONE_CONVEX_CONE_HULL]);;
7410
7411 let CONVEX_CONE_HULL_MUL = prove
7412  (`!s c x:real^N.
7413         &0 <= c /\ x IN convex_cone hull s
7414         ==> (c % x) IN convex_cone hull s`,
7415   MESON_TAC[CONVEX_CONE; CONVEX_CONE_CONVEX_CONE_HULL]);;
7416
7417 let CONVEX_CONE_SUMS = prove
7418  (`!s t. convex_cone s /\ convex_cone t
7419          ==> convex_cone {x + y:real^N | x IN s /\ y IN t}`,
7420   SIMP_TAC[convex_cone; CONIC_SUMS; CONVEX_SUMS] THEN SET_TAC[]);;
7421
7422 let CONVEX_CONE_PCROSS = prove
7423  (`!s:real^M->bool t:real^N->bool.
7424         convex_cone s /\ convex_cone t ==> convex_cone(s PCROSS t)`,
7425   SIMP_TAC[convex_cone; CONVEX_PCROSS; CONIC_PCROSS; PCROSS_EQ_EMPTY]);;
7426
7427 let CONVEX_CONE_PCROSS_EQ = prove
7428  (`!s:real^M->bool t:real^N->bool.
7429         convex_cone(s PCROSS t) <=> convex_cone s /\ convex_cone t`,
7430   REPEAT GEN_TAC THEN
7431   ASM_CASES_TAC `s:real^M->bool = {}` THENL
7432    [ASM_REWRITE_TAC[PCROSS_EMPTY; convex_cone]; ALL_TAC] THEN
7433   ASM_CASES_TAC `t:real^N->bool = {}` THENL
7434    [ASM_REWRITE_TAC[PCROSS_EMPTY; convex_cone]; ALL_TAC] THEN
7435   EQ_TAC THEN REWRITE_TAC[CONVEX_CONE_PCROSS] THEN REPEAT STRIP_TAC THENL
7436    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
7437      `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONVEX_CONE_LINEAR_IMAGE) THEN
7438     ASM_REWRITE_TAC[LINEAR_FSTCART];
7439     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
7440      `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONVEX_CONE_LINEAR_IMAGE) THEN
7441     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
7442   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
7443   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
7444               FSTCART_PASTECART; SNDCART_PASTECART] THEN
7445   ASM SET_TAC[]);;
7446
7447 let CONVEX_CONE_HULL_UNION = prove
7448  (`!s t. convex_cone hull(s UNION t) =
7449          {x + y:real^N | x IN convex_cone hull s /\ y IN convex_cone hull t}`,
7450   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
7451    [MATCH_MP_TAC HULL_MINIMAL THEN
7452     SIMP_TAC[CONVEX_CONE_SUMS; CONVEX_CONE_CONVEX_CONE_HULL] THEN
7453     REWRITE_TAC[SUBSET; IN_UNION; IN_ELIM_THM] THEN
7454     X_GEN_TAC `x:real^N` THEN STRIP_TAC THENL
7455      [MAP_EVERY EXISTS_TAC [`x:real^N`; `vec 0:real^N`] THEN
7456       ASM_SIMP_TAC[HULL_INC; CONVEX_CONE_HULL_CONTAINS_0; VECTOR_ADD_RID];
7457       MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `x:real^N`] THEN
7458       ASM_SIMP_TAC[HULL_INC; CONVEX_CONE_HULL_CONTAINS_0; VECTOR_ADD_LID]];
7459     REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
7460     REPEAT STRIP_TAC THEN MATCH_MP_TAC CONVEX_CONE_HULL_ADD THEN
7461     ASM_MESON_TAC[HULL_MONO; SUBSET_UNION; SUBSET]]);;
7462
7463 let CONVEX_CONE_SING = prove
7464  (`convex_cone {vec 0}`,
7465   SIMP_TAC[CONVEX_CONE; IN_SING; VECTOR_ADD_LID; VECTOR_MUL_RZERO]);;
7466
7467 let CONVEX_HULL_SUBSET_CONVEX_CONE_HULL = prove
7468  (`!s. convex hull s SUBSET convex_cone hull s`,
7469   GEN_TAC THEN MATCH_MP_TAC HULL_ANTIMONO THEN
7470   SIMP_TAC[convex_cone; SUBSET; IN]);;
7471
7472 let CONIC_HULL_SUBSET_CONVEX_CONE_HULL = prove
7473  (`!s. conic hull s SUBSET convex_cone hull s`,
7474   GEN_TAC THEN MATCH_MP_TAC HULL_ANTIMONO THEN
7475   SIMP_TAC[convex_cone; SUBSET; IN]);;
7476
7477 let CONVEX_CONE_HULL_SEPARATE_NONEMPTY = prove
7478  (`!s:real^N->bool.
7479     ~(s = {})
7480     ==> convex_cone hull s = conic hull (convex hull s)`,
7481   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THEN
7482   MATCH_MP_TAC HULL_MINIMAL THEN
7483   REWRITE_TAC[CONIC_CONVEX_CONE_HULL; CONVEX_HULL_SUBSET_CONVEX_CONE_HULL] THEN
7484   ASM_SIMP_TAC[CONVEX_CONIC_HULL; CONVEX_CONVEX_HULL; CONIC_CONIC_HULL;
7485                convex_cone; CONIC_HULL_EQ_EMPTY; CONVEX_HULL_EQ_EMPTY] THEN
7486   ASM_MESON_TAC[HULL_SUBSET; SUBSET_REFL; SUBSET_TRANS]);;
7487
7488 let CONVEX_CONE_HULL_EMPTY = prove
7489  (`convex_cone hull {} = {vec 0}`,
7490   MATCH_MP_TAC HULL_UNIQUE THEN
7491   REWRITE_TAC[CONVEX_CONE_CONTAINS_0; EMPTY_SUBSET; CONVEX_CONE_SING;
7492               SET_RULE `{a} SUBSET s <=> a IN s`; CONVEX_CONE_CONTAINS_0]);;
7493
7494 let CONVEX_CONE_HULL_SEPARATE = prove
7495  (`!s:real^N->bool.
7496     convex_cone hull s = vec 0 INSERT conic hull (convex hull s)`,
7497   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
7498   ASM_SIMP_TAC[CONVEX_CONE_HULL_EMPTY; CONVEX_HULL_EMPTY; CONIC_HULL_EMPTY] THEN
7499   ASM_SIMP_TAC[CONVEX_CONE_HULL_SEPARATE_NONEMPTY] THEN
7500   MATCH_MP_TAC(SET_RULE `a IN s ==> s = a INSERT s`) THEN
7501   ASM_SIMP_TAC[CONIC_CONTAINS_0; CONIC_CONIC_HULL] THEN
7502   ASM_REWRITE_TAC[CONIC_HULL_EQ_EMPTY; CONVEX_HULL_EQ_EMPTY]);;
7503
7504 let CONVEX_CONE_HULL_CONVEX_HULL_NONEMPTY = prove
7505  (`!s:real^N->bool.
7506         ~(s = {})
7507         ==> convex_cone hull s = {c % x | &0 <= c /\ x IN convex hull s}`,
7508   SIMP_TAC[CONVEX_CONE_HULL_SEPARATE_NONEMPTY; CONIC_HULL_EXPLICIT]);;
7509
7510 let CONVEX_CONE_HULL_CONVEX_HULL = prove
7511  (`!s:real^N->bool.
7512         convex_cone hull s =
7513         vec 0 INSERT {c % x | &0 <= c /\ x IN convex hull s}`,
7514   REWRITE_TAC[CONVEX_CONE_HULL_SEPARATE; CONIC_HULL_EXPLICIT]);;
7515
7516 let CONVEX_CONE_HULL_LINEAR_IMAGE = prove
7517  (`!f:real^M->real^N s.
7518         linear f
7519         ==> convex_cone hull (IMAGE f s) = IMAGE f (convex_cone hull s)`,
7520   REPEAT STRIP_TAC THEN
7521   ASM_CASES_TAC `s:real^M-> bool = {}` THEN
7522   ASM_SIMP_TAC[CONVEX_CONE_HULL_SEPARATE_NONEMPTY; IMAGE_EQ_EMPTY;
7523                CONVEX_HULL_LINEAR_IMAGE; CONIC_HULL_LINEAR_IMAGE] THEN
7524   REWRITE_TAC[IMAGE_CLAUSES; CONVEX_CONE_HULL_EMPTY] THEN
7525   MATCH_MP_TAC(SET_RULE `f x = y ==> {y} = {f x}`) THEN
7526   ASM_MESON_TAC[LINEAR_0]);;
7527
7528 add_linear_invariants [CONVEX_CONE_HULL_LINEAR_IMAGE];;
7529
7530 let SUBSPACE_IMP_CONVEX_CONE = prove
7531  (`!s. subspace s ==> convex_cone s`,
7532   SIMP_TAC[subspace; CONVEX_CONE]);;
7533
7534 let CONVEX_CONE_SPAN = prove
7535  (`!s. convex_cone(span s)`,
7536   SIMP_TAC[convex_cone; CONVEX_SPAN; CONIC_SPAN; GSYM MEMBER_NOT_EMPTY] THEN
7537   MESON_TAC[SPAN_0]);;
7538
7539 let CONVEX_CONE_NEGATIONS = prove
7540  (`!s. convex_cone s ==> convex_cone (IMAGE (--) s)`,
7541   SIMP_TAC[convex_cone; IMAGE_EQ_EMPTY; CONIC_NEGATIONS; CONVEX_NEGATIONS]);;
7542
7543 let SUBSPACE_CONVEX_CONE_SYMMETRIC = prove
7544  (`!s:real^N->bool.
7545         subspace s <=> convex_cone s /\ (!x. x IN s ==> --x IN s)`,
7546   GEN_TAC THEN REWRITE_TAC[subspace; CONVEX_CONE] THEN
7547   EQ_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[] THENL
7548    [ASM_MESON_TAC[VECTOR_ARITH `--x:real^N = -- &1 % x`];
7549     MAP_EVERY X_GEN_TAC [`c:real`; `x:real^N`] THEN DISCH_TAC THEN
7550     DISJ_CASES_TAC(SPEC `c:real` REAL_LE_NEGTOTAL) THEN ASM_SIMP_TAC[] THEN
7551     ASM_MESON_TAC[VECTOR_ARITH `c % x:real^N = --(--c % x)`]]);;
7552
7553 let SPAN_CONVEX_CONE_ALLSIGNS = prove
7554  (`!s:real^N->bool. span s = convex_cone hull (s UNION IMAGE (--) s)`,
7555   GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
7556    [MATCH_MP_TAC SPAN_SUBSET_SUBSPACE THEN CONJ_TAC THENL
7557      [MESON_TAC[HULL_SUBSET; SUBSET_UNION; SUBSET_TRANS]; ALL_TAC] THEN
7558     REWRITE_TAC[SUBSPACE_CONVEX_CONE_SYMMETRIC;
7559                 CONVEX_CONE_CONVEX_CONE_HULL] THEN
7560     MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
7561      [X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_UNION; IN_IMAGE] THEN
7562       DISCH_TAC THEN MATCH_MP_TAC HULL_INC THEN
7563       REWRITE_TAC[IN_UNION; IN_IMAGE] THEN ASM_MESON_TAC[VECTOR_NEG_NEG];
7564       SUBGOAL_THEN `!s. {x:real^N | (--x) IN s} = IMAGE (--) s`
7565        (fun th -> SIMP_TAC[th; CONVEX_CONE_NEGATIONS;
7566                            CONVEX_CONE_CONVEX_CONE_HULL]) THEN
7567       GEN_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
7568       REWRITE_TAC[IN_ELIM_THM] THEN MESON_TAC[VECTOR_NEG_NEG]];
7569     MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_CONE_SPAN] THEN
7570     REWRITE_TAC[UNION_SUBSET; SPAN_INC] THEN
7571     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
7572     MESON_TAC[SPAN_SUPERSET; SPAN_NEG]]);;
7573
7574 (* ------------------------------------------------------------------------- *)
7575 (* Epigraphs of convex functions.                                            *)
7576 (* ------------------------------------------------------------------------- *)
7577
7578 let epigraph = new_definition
7579   `epigraph s (f:real^N->real) =
7580        {xy:real^((N,1)finite_sum) |
7581              fstcart xy IN s /\ f(fstcart xy) <= drop(sndcart xy)}`;;
7582
7583 let IN_EPIGRAPH = prove
7584  (`!x y. (pastecart x (lift y)) IN epigraph s f <=> x IN s /\ f(x) <= y`,
7585   REWRITE_TAC[epigraph; IN_ELIM_THM; FSTCART_PASTECART; SNDCART_PASTECART;
7586               LIFT_DROP]);;
7587
7588 let CONVEX_EPIGRAPH = prove
7589  (`!f s. f convex_on s /\ convex s <=> convex(epigraph s f)`,
7590   REWRITE_TAC[convex; convex_on; IN_ELIM_THM; SNDCART_ADD; SNDCART_CMUL;
7591    epigraph; FSTCART_ADD; FSTCART_CMUL; FORALL_PASTECART; FSTCART_PASTECART;
7592    SNDCART_PASTECART] THEN
7593   REWRITE_TAC[GSYM FORALL_DROP; DROP_ADD; DROP_CMUL] THEN
7594   MESON_TAC[REAL_LE_REFL; REAL_LE_ADD2; REAL_LE_LMUL; REAL_LE_TRANS]);;
7595
7596 let CONVEX_EPIGRAPH_CONVEX = prove
7597  (`!f s. convex s ==> (f convex_on s <=> convex(epigraph s f))`,
7598   REWRITE_TAC[GSYM CONVEX_EPIGRAPH] THEN CONV_TAC TAUT);;
7599
7600 let CONVEX_ON_EPIGRAPH_SLICE_LE = prove
7601  (`!f:real^N->real s a.
7602         f convex_on s /\ convex s ==> convex {x | x IN s /\ f(x) <= a}`,
7603   SIMP_TAC[convex_on; convex; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
7604   FIRST_X_ASSUM(fun th ->
7605     W(MP_TAC o PART_MATCH (lhand o rand) th o lhand o snd)) THEN
7606   ASM_REWRITE_TAC[] THEN
7607   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
7608   MATCH_MP_TAC REAL_CONVEX_BOUND_LE THEN ASM_REWRITE_TAC[]);;
7609
7610 let CONVEX_ON_EPIGRAPH_SLICE_LT = prove
7611  (`!f:real^N->real s a.
7612         f convex_on s /\ convex s ==> convex {x | x IN s /\ f(x) < a}`,
7613   SIMP_TAC[convex_on; convex; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
7614   FIRST_X_ASSUM(fun th ->
7615     W(MP_TAC o PART_MATCH (lhand o rand) th o lhand o snd)) THEN
7616   ASM_REWRITE_TAC[] THEN
7617   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LET_TRANS) THEN
7618   MATCH_MP_TAC REAL_CONVEX_BOUND_LT THEN ASM_REWRITE_TAC[]);;
7619
7620 (* ------------------------------------------------------------------------- *)
7621 (* Use this to derive general bound property of convex function.             *)
7622 (* ------------------------------------------------------------------------- *)
7623
7624 let FORALL_OF_PASTECART = prove
7625  (`(!p. P (fstcart o p) (sndcart o p)) <=> (!x:A->B^M y:A->B^N. P x y)`,
7626   EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN REPEAT STRIP_TAC THEN
7627   FIRST_ASSUM(MP_TAC o SPEC `\a:A. pastecart (x a :B^M) (y a :B^N)`) THEN
7628   REWRITE_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART; ETA_AX]);;
7629
7630 let FORALL_OF_DROP = prove
7631  (`(!v. P (drop o v)) <=> (!x:A->real. P x)`,
7632   EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN REPEAT STRIP_TAC THEN
7633   FIRST_ASSUM(MP_TAC o SPEC `\a:A. lift(x a)`) THEN
7634   REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX]);;
7635
7636 let CONVEX_ON_JENSEN = prove
7637  (`!f:real^N->real s.
7638         convex s
7639         ==> (f convex_on s <=>
7640                 !k u x.
7641                    (!i:num. 1 <= i /\ i <= k ==> &0 <= u(i) /\ x(i) IN s) /\
7642                    (sum (1..k) u = &1)
7643                    ==> f(vsum (1..k) (\i. u(i) % x(i)))
7644                            <= sum (1..k) (\i. u(i) * f(x(i))))`,
7645   let lemma = prove
7646    (`(!x. P x ==> (Q x = R x)) ==> (!x. P x) ==> ((!x. Q x) <=> (!x. R x))`,
7647     MESON_TAC[]) in
7648   REPEAT STRIP_TAC THEN FIRST_ASSUM
7649    (fun th -> REWRITE_TAC[MATCH_MP CONVEX_EPIGRAPH_CONVEX th]) THEN
7650   REWRITE_TAC[CONVEX_INDEXED; epigraph] THEN
7651   SIMP_TAC[IN_ELIM_THM; SNDCART_ADD; SNDCART_CMUL; FINITE_NUMSEG;
7652            FSTCART_ADD; FSTCART_CMUL; FORALL_PASTECART; DROP_CMUL;
7653            FSTCART_PASTECART; SNDCART_PASTECART;
7654            FSTCART_VSUM; SNDCART_VSUM; DROP_VSUM; o_DEF] THEN
7655   REWRITE_TAC[GSYM(ISPEC `fstcart` o_THM); GSYM(ISPEC `sndcart` o_THM)] THEN
7656   REWRITE_TAC[GSYM(ISPEC `drop` o_THM)] THEN
7657   REWRITE_TAC[FORALL_OF_PASTECART; FORALL_OF_DROP] THEN
7658   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONVEX_INDEXED]) THEN
7659   REPEAT(MATCH_MP_TAC lemma THEN GEN_TAC) THEN SIMP_TAC[] THEN
7660   REWRITE_TAC[TAUT `a ==> b /\ c <=> (a ==> b) /\ (a ==> c)`] THEN
7661   REWRITE_TAC[FORALL_AND_THM] THEN DISCH_THEN(K ALL_TAC) THEN
7662   EQ_TAC THEN SIMP_TAC[REAL_LE_REFL] THEN
7663   DISCH_THEN(fun th -> REPEAT STRIP_TAC THEN MP_TAC th) THEN
7664   ASM_REWRITE_TAC[] THEN
7665   MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN
7666   ASM_SIMP_TAC[SUM_LE_NUMSEG; REAL_LE_LMUL]);;
7667
7668 (* ------------------------------------------------------------------------- *)
7669 (* Another intermediate value theorem formulation.                           *)
7670 (* ------------------------------------------------------------------------- *)
7671
7672 let IVT_INCREASING_COMPONENT_ON_1 = prove
7673  (`!f:real^1->real^N a b y k.
7674         drop a <= drop b /\ 1 <= k /\ k <= dimindex(:N) /\
7675         f continuous_on interval[a,b] /\
7676         f(a)$k <= y /\ y <= f(b)$k
7677         ==> ?x. x IN interval[a,b] /\ f(x)$k = y`,
7678   REPEAT STRIP_TAC THEN
7679   MP_TAC(ISPECL [`IMAGE (f:real^1->real^N) (interval[a,b])`]
7680         CONNECTED_IVT_COMPONENT) THEN
7681   REWRITE_TAC[EXISTS_IN_IMAGE] THEN DISCH_THEN MATCH_MP_TAC THEN
7682   REWRITE_TAC[RIGHT_EXISTS_AND_THM; EXISTS_IN_IMAGE] THEN
7683   ASM_SIMP_TAC[CONNECTED_CONTINUOUS_IMAGE; CONVEX_CONNECTED;
7684                CONVEX_INTERVAL] THEN
7685   EXISTS_TAC `a:real^1` THEN ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL] THEN
7686   EXISTS_TAC `b:real^1` THEN ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL]);;
7687
7688 let IVT_INCREASING_COMPONENT_1 = prove
7689  (`!f:real^1->real^N a b y k.
7690         drop a <= drop b /\ 1 <= k /\ k <= dimindex(:N) /\
7691         (!x. x IN interval[a,b] ==> f continuous at x) /\
7692         f(a)$k <= y /\ y <= f(b)$k
7693         ==> ?x. x IN interval[a,b] /\ f(x)$k = y`,
7694   REPEAT STRIP_TAC THEN MATCH_MP_TAC IVT_INCREASING_COMPONENT_ON_1 THEN
7695   ASM_SIMP_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
7696
7697 let IVT_DECREASING_COMPONENT_ON_1 = prove
7698  (`!f:real^1->real^N a b y k.
7699         drop a <= drop b /\ 1 <= k /\ k <= dimindex(:N) /\
7700         f continuous_on interval[a,b] /\
7701         f(b)$k <= y /\ y <= f(a)$k
7702         ==> ?x. x IN interval[a,b] /\ f(x)$k = y`,
7703   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EQ_NEG2] THEN
7704   ASM_SIMP_TAC[GSYM VECTOR_NEG_COMPONENT] THEN
7705   MATCH_MP_TAC IVT_INCREASING_COMPONENT_ON_1 THEN
7706   ASM_SIMP_TAC[VECTOR_NEG_COMPONENT; CONTINUOUS_ON_NEG; REAL_LE_NEG2]);;
7707
7708 let IVT_DECREASING_COMPONENT_1 = prove
7709  (`!f:real^1->real^N a b y k.
7710         drop a <= drop b /\ 1 <= k /\ k <= dimindex(:N) /\
7711         (!x. x IN interval[a,b] ==> f continuous at x) /\
7712         f(b)$k <= y /\ y <= f(a)$k
7713         ==> ?x. x IN interval[a,b] /\ f(x)$k = y`,
7714   REPEAT STRIP_TAC THEN MATCH_MP_TAC IVT_DECREASING_COMPONENT_ON_1 THEN
7715   ASM_SIMP_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
7716
7717 (* ------------------------------------------------------------------------- *)
7718 (* A bound within a convex hull, and so an interval.                         *)
7719 (* ------------------------------------------------------------------------- *)
7720
7721 let CONVEX_ON_CONVEX_HULL_BOUND = prove
7722  (`!f s b. f convex_on (convex hull s) /\
7723            (!x:real^N. x IN s ==> f(x) <= b)
7724            ==> !x. x IN convex hull s ==> f(x) <= b`,
7725   REPEAT GEN_TAC THEN SIMP_TAC[CONVEX_ON_JENSEN; CONVEX_CONVEX_HULL] THEN
7726   STRIP_TAC THEN GEN_TAC THEN REWRITE_TAC[CONVEX_HULL_INDEXED] THEN
7727   REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
7728   MAP_EVERY X_GEN_TAC [`k:num`; `u:num->real`; `v:num->real^N`] THEN
7729   DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN ASM_REWRITE_TAC[] THEN
7730   MATCH_MP_TAC REAL_LE_TRANS THEN
7731   EXISTS_TAC `sum(1..k) (\i. u i * f(v i :real^N))` THEN CONJ_TAC THENL
7732    [FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_MESON_TAC[SUBSET; HULL_SUBSET];
7733     ALL_TAC] THEN
7734   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(1..k) (\i. u i * b)` THEN
7735   CONJ_TAC THENL
7736    [MATCH_MP_TAC SUM_LE_NUMSEG THEN ASM_SIMP_TAC[REAL_LE_LMUL];
7737     ALL_TAC] THEN
7738   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[SUM_LMUL] THEN
7739   ASM_MESON_TAC[REAL_LE_REFL; REAL_MUL_RID]);;
7740
7741 let UNIT_INTERVAL_CONVEX_HULL = prove
7742  (`interval [vec 0,vec 1:real^N] =
7743      convex hull
7744        {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
7745                            ==> ((x$i = &0) \/ (x$i = &1))}`,
7746   let lemma = prove
7747    (`FINITE {i | 1 <= i /\ i <= n /\ P(i)} /\
7748      CARD {i | 1 <= i /\ i <= n /\ P(i)} <= n`,
7749     CONJ_TAC THENL
7750      [MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `1..n`;
7751       GEN_REWRITE_TAC RAND_CONV [ARITH_RULE `x = (x + 1) - 1`] THEN
7752       REWRITE_TAC[GSYM CARD_NUMSEG] THEN MATCH_MP_TAC CARD_SUBSET] THEN
7753     SIMP_TAC[FINITE_NUMSEG; IN_NUMSEG; SUBSET; IN_ELIM_THM]) in
7754   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
7755    [ALL_TAC;
7756     MATCH_MP_TAC HULL_MINIMAL THEN
7757     REWRITE_TAC[CONVEX_INTERVAL; SUBSET; IN_INTERVAL; IN_ELIM_THM] THEN
7758     SIMP_TAC[VEC_COMPONENT] THEN MESON_TAC[REAL_LE_REFL; REAL_POS]] THEN
7759   SUBGOAL_THEN
7760    `!n x:real^N.
7761         x IN interval[vec 0,vec 1] /\
7762         n <= dimindex(:N) /\
7763         CARD {i | 1 <= i /\ i <= dimindex(:N) /\ ~(x$i = &0)} <= n
7764         ==> x IN convex hull
7765                   {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
7766                                   ==> ((x$i = &0) \/ (x$i = &1))}`
7767   MP_TAC THENL
7768    [ALL_TAC;
7769     REWRITE_TAC[SUBSET] THEN REPEAT STRIP_TAC THEN
7770     FIRST_X_ASSUM MATCH_MP_TAC THEN EXISTS_TAC `dimindex(:N)` THEN
7771     ASM_REWRITE_TAC[LE_REFL; lemma]] THEN
7772   INDUCT_TAC THEN X_GEN_TAC `x:real^N` THENL
7773    [SIMP_TAC[LE; lemma; CARD_EQ_0] THEN
7774     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
7775      [EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY; BETA_THM] THEN
7776     REWRITE_TAC[TAUT `~(a /\ b /\ c) <=> a /\ b ==> ~c`] THEN STRIP_TAC THEN
7777     SUBGOAL_THEN `x = vec 0:real^N` SUBST1_TAC THENL
7778      [ASM_SIMP_TAC[CART_EQ; VEC_COMPONENT]; ALL_TAC] THEN
7779     MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
7780     SIMP_TAC[IN_ELIM_THM; VEC_COMPONENT];
7781     ALL_TAC] THEN
7782   ASM_CASES_TAC
7783    `{i | 1 <= i /\ i <= dimindex(:N) /\ ~((x:real^N)$i = &0)} = {}`
7784   THENL
7785    [DISCH_THEN(K ALL_TAC) THEN
7786     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
7787     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
7788      [EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY; BETA_THM] THEN
7789     REWRITE_TAC[TAUT `~(a /\ b /\ c) <=> a /\ b ==> ~c`] THEN STRIP_TAC THEN
7790     SUBGOAL_THEN `x = vec 0:real^N` SUBST1_TAC THENL
7791      [ASM_SIMP_TAC[CART_EQ; VEC_COMPONENT]; ALL_TAC] THEN
7792     MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
7793     SIMP_TAC[IN_ELIM_THM; VEC_COMPONENT];
7794     ALL_TAC] THEN
7795   MP_TAC(ISPEC
7796    `IMAGE (\i. x$i)
7797       {i | 1 <= i /\ i <= dimindex(:N) /\ ~((x:real^N)$i = &0)}`
7798    INF_FINITE) THEN
7799   ABBREV_TAC `xi = inf
7800    (IMAGE (\i. x$i)
7801      {i | 1 <= i /\ i <= dimindex(:N) /\ ~((x:real^N)$i = &0)})` THEN
7802   ASM_SIMP_TAC[FINITE_IMAGE; IMAGE_EQ_EMPTY; lemma] THEN
7803   REWRITE_TAC[FORALL_IN_IMAGE] THEN
7804   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [IN_IMAGE; IN_ELIM_THM] THEN
7805   REWRITE_TAC[] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
7806   FIRST_X_ASSUM(X_CHOOSE_THEN `i:num` STRIP_ASSUME_TAC) THEN
7807   FIRST_X_ASSUM SUBST_ALL_TAC THEN REPEAT STRIP_TAC THEN
7808   SUBGOAL_THEN `&0 <= (x:real^N)$i /\ x$i <= &1` STRIP_ASSUME_TAC THENL
7809    [UNDISCH_TAC `x:real^N IN interval [vec 0,vec 1]` THEN
7810     ASM_SIMP_TAC[IN_INTERVAL; VEC_COMPONENT];
7811     ALL_TAC] THEN
7812   FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
7813    `x <= &1 ==> (x = &1) \/ x < &1`))
7814   THENL
7815    [SUBGOAL_THEN
7816      `x = lambda i. if (x:real^N)$i = &0 then &0 else &1`
7817     SUBST1_TAC THENL
7818      [UNDISCH_TAC `x:real^N IN interval [vec 0,vec 1]` THEN
7819       ASM_SIMP_TAC[CART_EQ; IN_INTERVAL; VEC_COMPONENT; LAMBDA_BETA] THEN
7820       ASM_MESON_TAC[REAL_LE_ANTISYM];
7821       ALL_TAC] THEN
7822     MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
7823     SIMP_TAC[IN_ELIM_THM; LAMBDA_BETA] THEN MESON_TAC[];
7824     ALL_TAC] THEN
7825   SUBGOAL_THEN
7826    `x:real^N =
7827         x$i % (lambda j. if x$j = &0 then &0 else &1) +
7828         (&1 - x$i) %
7829         (lambda j. if x$j = &0 then &0 else (x$j - x$i) / (&1 - x$i))`
7830   SUBST1_TAC THENL
7831    [SIMP_TAC[CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
7832              LAMBDA_BETA; VEC_COMPONENT] THEN
7833     REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
7834     ASM_REWRITE_TAC[REAL_MUL_RZERO; REAL_ADD_LID] THEN
7835     ASM_SIMP_TAC[REAL_DIV_LMUL; ARITH_RULE `x < &1 ==> ~(&1 - x = &0)`] THEN
7836     REPEAT STRIP_TAC THEN REAL_ARITH_TAC;
7837     ALL_TAC] THEN
7838   MATCH_MP_TAC(REWRITE_RULE[convex] CONVEX_CONVEX_HULL) THEN
7839   ASM_SIMP_TAC[REAL_ARITH `x < &1 ==> &0 <= &1 - x`;
7840                REAL_ARITH `x + &1 - x = &1`] THEN
7841   CONJ_TAC THENL
7842    [MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
7843     SIMP_TAC[LAMBDA_BETA; IN_ELIM_THM] THEN MESON_TAC[];
7844     ALL_TAC] THEN
7845   FIRST_X_ASSUM MATCH_MP_TAC THEN
7846   ASM_SIMP_TAC[ARITH_RULE `SUC k <= n ==> k <= n`] THEN CONJ_TAC THENL
7847    [SIMP_TAC[IN_INTERVAL; LAMBDA_BETA; VEC_COMPONENT] THEN
7848     GEN_TAC THEN STRIP_TAC THEN
7849     COND_CASES_TAC THEN REWRITE_TAC[REAL_LE_REFL; REAL_POS] THEN
7850     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ;
7851                  REAL_ARITH `x < &1 ==> &0 < &1 - x`] THEN
7852     ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_SUB_LE; REAL_MUL_LID] THEN
7853     ASM_SIMP_TAC[REAL_ARITH `a - b <= &1 - b <=> a <= &1`] THEN
7854     UNDISCH_TAC `x:real^N IN interval [vec 0,vec 1]` THEN
7855     ASM_SIMP_TAC[CART_EQ; IN_INTERVAL; VEC_COMPONENT; LAMBDA_BETA];
7856     ALL_TAC] THEN
7857   MATCH_MP_TAC LE_TRANS THEN
7858   EXISTS_TAC
7859    `CARD({i | 1 <= i /\ i <= dimindex(:N) /\ ~((x:real^N)$i = &0)}
7860          DELETE i)` THEN
7861   CONJ_TAC THENL
7862    [MATCH_MP_TAC CARD_SUBSET THEN REWRITE_TAC[lemma; FINITE_DELETE] THEN
7863     REWRITE_TAC[SUBSET; IN_DELETE; IN_ELIM_THM] THEN
7864     GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
7865     ASM_SIMP_TAC[LAMBDA_BETA] THEN
7866     COND_CASES_TAC THEN ASM_REWRITE_TAC[CONTRAPOS_THM] THEN
7867     SIMP_TAC[real_div; REAL_SUB_REFL; REAL_MUL_LZERO];
7868     SIMP_TAC[lemma; CARD_DELETE] THEN COND_CASES_TAC THEN
7869     ASM_SIMP_TAC[ARITH_RULE `x <= SUC n ==> x - 1 <= n`] THEN
7870     RULE_ASSUM_TAC(REWRITE_RULE[IN_ELIM_THM]) THEN
7871     ASM_MESON_TAC[]]);;
7872
7873 (* ------------------------------------------------------------------------- *)
7874 (* Representation of any interval as a finite convex hull.                   *)
7875 (* ------------------------------------------------------------------------- *)
7876
7877 let CLOSED_INTERVAL_AS_CONVEX_HULL = prove
7878  (`!a b:real^N. ?s. FINITE s /\ interval[a,b] = convex hull s`,
7879   REPEAT GEN_TAC THEN ASM_CASES_TAC `interval[a:real^N,b] = {}` THENL
7880    [ASM_MESON_TAC[CONVEX_HULL_EMPTY; FINITE_EMPTY]; ALL_TAC] THEN
7881   ASM_SIMP_TAC[CLOSED_INTERVAL_IMAGE_UNIT_INTERVAL] THEN
7882   SUBGOAL_THEN
7883    `?s:real^N->bool. FINITE s /\ interval[vec 0,vec 1] = convex hull s`
7884   STRIP_ASSUME_TAC THENL
7885    [EXISTS_TAC
7886      `{x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
7887                       ==> ((x$i = &0) \/ (x$i = &1))}` THEN
7888     REWRITE_TAC[UNIT_INTERVAL_CONVEX_HULL] THEN
7889     MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC
7890      `IMAGE (\s. (lambda i. if i IN s then &1 else &0):real^N)
7891             {t | t SUBSET (1..dimindex(:N))}` THEN
7892     ASM_SIMP_TAC[FINITE_POWERSET; FINITE_IMAGE; FINITE_NUMSEG] THEN
7893     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_IMAGE] THEN
7894     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN EXISTS_TAC
7895      `{i | 1 <= i /\ i <= dimindex(:N) /\ ((x:real^N)$i = &1)}` THEN
7896     SIMP_TAC[CART_EQ; IN_ELIM_THM; IN_NUMSEG; LAMBDA_BETA] THEN
7897     ASM_MESON_TAC[];
7898     EXISTS_TAC `IMAGE (\x:real^N. a + x)
7899                       (IMAGE (\x. (lambda i. ((b:real^N)$i - a$i) * x$i))
7900                              (s:real^N->bool))` THEN
7901     ASM_SIMP_TAC[FINITE_IMAGE; CONVEX_HULL_TRANSLATION] THEN
7902     AP_TERM_TAC THEN MATCH_MP_TAC(GSYM CONVEX_HULL_LINEAR_IMAGE) THEN
7903     SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
7904              VECTOR_MUL_COMPONENT] THEN
7905     REPEAT STRIP_TAC THEN REAL_ARITH_TAC]);;
7906
7907 (* ------------------------------------------------------------------------- *)
7908 (* Bounded convex function on open set is continuous.                        *)
7909 (* ------------------------------------------------------------------------- *)
7910
7911 let CONVEX_ON_BOUNDED_CONTINUOUS = prove
7912  (`!f:real^N->real s b.
7913         open s /\ f convex_on s /\ (!x. x IN s ==> abs(f x) <= b)
7914         ==> (lift o f) continuous_on s`,
7915   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
7916   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7917   REWRITE_TAC[CONTINUOUS_AT_LIFT_RANGE] THEN
7918   ABBREV_TAC `B = abs(b) + &1` THEN
7919   SUBGOAL_THEN `&0 < B /\ !x:real^N. x IN s ==> abs(f x) <= B`
7920   STRIP_ASSUME_TAC THENL
7921    [EXPAND_TAC "B" THEN CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
7922     ASM_MESON_TAC[REAL_ARITH `x <= b ==> x <= abs b + &1`];
7923     ALL_TAC] THEN
7924   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
7925   REWRITE_TAC[REAL_ARITH `abs(x - y) < e <=> x - y < e /\ y - x < e`] THEN
7926   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
7927   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN REWRITE_TAC[SUBSET; IN_CBALL] THEN
7928   ASM_REWRITE_TAC[] THEN
7929   DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
7930   EXISTS_TAC `min (k / &2) (e / (&2 * B) * k)` THEN
7931   ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_DIV; REAL_LT_MUL;
7932                REAL_OF_NUM_LT; ARITH] THEN
7933   X_GEN_TAC `y:real^N` THEN
7934   ASM_CASES_TAC `y:real^N = x` THEN ASM_REWRITE_TAC[REAL_SUB_REFL] THEN
7935   STRIP_TAC THEN
7936   ABBREV_TAC `t = k / norm(y - x:real^N)` THEN
7937   SUBGOAL_THEN `&2 < t` ASSUME_TAC THENL
7938    [EXPAND_TAC "t" THEN
7939     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
7940     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
7941     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH];
7942     ALL_TAC] THEN
7943   FIRST_ASSUM(STRIP_ASSUME_TAC o MATCH_MP (REAL_ARITH
7944    `&2 < t ==> &0 < t /\ ~(t = &0) /\ &0 < t - &1 /\
7945                &0 < &1 + t /\ ~(&1 + t = &0)`)) THEN
7946   SUBGOAL_THEN `y:real^N IN s` ASSUME_TAC THENL
7947    [FIRST_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[dist] THEN
7948     ONCE_REWRITE_TAC[NORM_SUB] THEN
7949     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
7950      `x < k / &2 ==> k / &2 <= k ==> x <= k`)) THEN
7951     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
7952     UNDISCH_TAC `&0 < k` THEN REAL_ARITH_TAC;
7953     ALL_TAC] THEN
7954   CONJ_TAC THENL
7955    [ABBREV_TAC `w:real^N = x + t % (y - x)` THEN
7956     SUBGOAL_THEN `w:real^N IN s` STRIP_ASSUME_TAC THENL
7957      [FIRST_ASSUM MATCH_MP_TAC THEN EXPAND_TAC "w" THEN
7958       REWRITE_TAC[dist; VECTOR_ARITH `x - (x + t) = --t:real^N`] THEN
7959       EXPAND_TAC "t" THEN REWRITE_TAC[NORM_NEG; NORM_MUL; REAL_ABS_DIV] THEN
7960       REWRITE_TAC[REAL_ABS_NORM; real_div; GSYM REAL_MUL_ASSOC] THEN
7961       ASM_SIMP_TAC[REAL_MUL_LINV; REAL_LT_IMP_NZ; NORM_POS_LT; VECTOR_SUB_EQ;
7962         REAL_MUL_RID; REAL_ARITH `&0 < x ==> abs(x) <= x`];
7963       ALL_TAC] THEN
7964     SUBGOAL_THEN `(&1 / t) % w + (t - &1) / t % x = y:real^N` ASSUME_TAC THENL
7965      [EXPAND_TAC "w" THEN
7966       REWRITE_TAC[VECTOR_ARITH
7967        `b % (x + c % (y - x)) + a % x =
7968         (a + b - b * c) % x + (b * c) % y`] THEN
7969       ASM_SIMP_TAC[REAL_DIV_RMUL; VECTOR_MUL_LID] THEN
7970       ASM_SIMP_TAC[real_div; REAL_MUL_RINV; REAL_SUB_REFL;
7971                    VECTOR_MUL_LZERO; VECTOR_ADD_LID;
7972                    REAL_ARITH `(a - &1) * b + &1 * b - &1 = a * b - &1`];
7973       ALL_TAC] THEN
7974     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex_on]) THEN
7975     DISCH_THEN(MP_TAC o SPECL
7976      [`w:real^N`; `x:real^N`; `&1 / t`; `(t - &1) / t`]) THEN
7977     ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LT_DIV; REAL_LT_01] THEN
7978     REWRITE_TAC[real_div; GSYM REAL_ADD_RDISTRIB] THEN
7979     ASM_SIMP_TAC[REAL_SUB_ADD2; REAL_MUL_RINV] THEN
7980     MATCH_MP_TAC(REAL_ARITH
7981      `a * fw + (b - &1) * fx < e
7982       ==> fy <= a * fw + b * fx ==> fy - fx < e`) THEN
7983     ASM_SIMP_TAC[real_div; REAL_SUB_RDISTRIB; REAL_MUL_RINV; REAL_MUL_LID;
7984                  REAL_ARITH `a * x + y - a * y - y = a * (x - y)`] THEN
7985     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
7986     ASM_SIMP_TAC[GSYM real_div; REAL_LT_LDIV_EQ] THEN
7987     MATCH_MP_TAC(REAL_ARITH
7988      `!b. abs(x) <= b /\ abs(y) <= b /\ &2 * b < z ==> x - y < z`) THEN
7989     EXISTS_TAC `B:real` THEN ASM_SIMP_TAC[] THEN EXPAND_TAC "t" THEN
7990     REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN
7991     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
7992     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
7993     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_LT_MUL; REAL_OF_NUM_LT; ARITH] THEN
7994     REWRITE_TAC[real_div; REAL_ARITH `(a * b) * inv c = (b * inv c) * a`] THEN
7995     ASM_REWRITE_TAC[GSYM real_div];
7996
7997     ABBREV_TAC `w:real^N = x - t % (y - x)` THEN
7998     SUBGOAL_THEN `w:real^N IN s` STRIP_ASSUME_TAC THENL
7999      [FIRST_ASSUM MATCH_MP_TAC THEN EXPAND_TAC "w" THEN
8000       REWRITE_TAC[dist; VECTOR_ARITH `x - (x - t) = t:real^N`] THEN
8001       EXPAND_TAC "t" THEN REWRITE_TAC[NORM_MUL; REAL_ABS_DIV] THEN
8002       REWRITE_TAC[REAL_ABS_NORM; real_div; GSYM REAL_MUL_ASSOC] THEN
8003       ASM_SIMP_TAC[REAL_MUL_LINV; REAL_LT_IMP_NZ; NORM_POS_LT; VECTOR_SUB_EQ;
8004         REAL_MUL_RID; REAL_ARITH `&0 < x ==> abs(x) <= x`];
8005       ALL_TAC] THEN
8006     SUBGOAL_THEN `(&1 / (&1 + t)) % w + t / (&1 + t) % y = x:real^N`
8007     ASSUME_TAC THENL
8008      [EXPAND_TAC "w" THEN
8009       REWRITE_TAC[VECTOR_ARITH
8010        `b % (x - c % (y - x)) + a % y =
8011         (b * (&1 + c)) % x + (a - b * c) % y`] THEN
8012       ASM_SIMP_TAC[REAL_DIV_RMUL; VECTOR_MUL_LID] THEN
8013       REWRITE_TAC[real_div; REAL_MUL_AC; REAL_MUL_LID; REAL_MUL_RID] THEN
8014       REWRITE_TAC[REAL_SUB_REFL; VECTOR_MUL_LZERO; VECTOR_ADD_RID];
8015       ALL_TAC] THEN
8016     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex_on]) THEN
8017     DISCH_THEN(MP_TAC o SPECL
8018      [`w:real^N`; `y:real^N`; `&1 / (&1 + t)`; `t / (&1 + t)`]) THEN
8019     ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LT_DIV; REAL_LT_01] THEN
8020     REWRITE_TAC[real_div; GSYM REAL_ADD_RDISTRIB] THEN
8021     ASM_SIMP_TAC[REAL_SUB_ADD2; REAL_MUL_RINV] THEN
8022     MATCH_MP_TAC(REAL_ARITH
8023      `a * fw + (b - &1) * fx < e
8024       ==> fy <= a * fw + b * fx ==> fy - fx < e`) THEN
8025     SUBGOAL_THEN `t * inv(&1 + t) - &1 = --(inv(&1 + t))` SUBST1_TAC THENL
8026      [REWRITE_TAC[REAL_ARITH `(a * b - &1 = --b) <=> ((&1 + a) * b = &1)`] THEN
8027       ASM_SIMP_TAC[REAL_MUL_RINV];
8028       ALL_TAC] THEN
8029     REWRITE_TAC[REAL_ARITH `(&1 * a) * x + --a * y = a * (x - y)`] THEN
8030     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8031     ASM_SIMP_TAC[GSYM real_div; REAL_LT_LDIV_EQ] THEN
8032     MATCH_MP_TAC(REAL_ARITH
8033      `!b. abs(x) <= b /\ abs(y) <= b /\ &2 * b < z ==> x - y < z`) THEN
8034     EXISTS_TAC `B:real` THEN ASM_SIMP_TAC[] THEN
8035     MATCH_MP_TAC(REAL_ARITH `&0 < e /\ x < e * k ==> x < e * (&1 + k)`) THEN
8036     EXPAND_TAC "t" THEN REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN
8037     REWRITE_TAC[GSYM real_div] THEN
8038     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
8039     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8040     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_LT_MUL; REAL_OF_NUM_LT; ARITH] THEN
8041     REWRITE_TAC[real_div; REAL_ARITH `(a * b) * inv c = (b * inv c) * a`] THEN
8042     ASM_REWRITE_TAC[GSYM real_div]]);;
8043
8044 (* ------------------------------------------------------------------------- *)
8045 (* Upper bound on a ball implies upper and lower bounds.                     *)
8046 (* ------------------------------------------------------------------------- *)
8047
8048 let CONVEX_BOUNDS_LEMMA = prove
8049  (`!f x:real^N e.
8050         f convex_on cball(x,e) /\
8051         (!y. y IN cball(x,e) ==> f(y) <= b)
8052         ==> !y. y IN cball(x,e) ==> abs(f(y)) <= b + &2 * abs(f(x))`,
8053   REPEAT GEN_TAC THEN ASM_CASES_TAC `&0 <= e` THENL
8054    [ALL_TAC;
8055     REWRITE_TAC[IN_CBALL] THEN ASM_MESON_TAC[DIST_POS_LE; REAL_LE_TRANS]] THEN
8056   REPEAT STRIP_TAC THEN
8057   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex_on]) THEN
8058   DISCH_THEN(MP_TAC o SPECL
8059    [`y:real^N`; `&2 % x - y:real^N`; `&1 / &2`; `&1 / &2`]) THEN
8060   REWRITE_TAC[GSYM VECTOR_ADD_LDISTRIB; GSYM REAL_ADD_LDISTRIB] THEN
8061   REWRITE_TAC[VECTOR_ARITH `y + x - y = x:real^N`] THEN
8062   REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
8063   ABBREV_TAC `z = &2 % x - y:real^N` THEN
8064   SUBGOAL_THEN `z:real^N IN cball(x,e)` ASSUME_TAC THENL
8065    [UNDISCH_TAC `y:real^N IN cball(x,e)`  THEN
8066     EXPAND_TAC "z" THEN REWRITE_TAC[dist; IN_CBALL] THEN
8067     REWRITE_TAC[VECTOR_ARITH `x - (&2 % x - y) = y - x`] THEN
8068     REWRITE_TAC[NORM_SUB];
8069     ALL_TAC] THEN
8070   ASM_REWRITE_TAC[VECTOR_MUL_LID] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8071   REWRITE_TAC[real_div; REAL_MUL_LID] THEN REWRITE_TAC[GSYM real_div] THEN
8072   ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
8073   FIRST_X_ASSUM(fun th ->
8074     MAP_EVERY (MP_TAC o C SPEC th) [`y:real^N`; `z:real^N`]) THEN
8075   ASM_REWRITE_TAC[CENTRE_IN_CBALL] THEN REAL_ARITH_TAC);;
8076
8077 (* ------------------------------------------------------------------------- *)
8078 (* Hence a convex function on an open set is continuous.                     *)
8079 (* ------------------------------------------------------------------------- *)
8080
8081 let CONVEX_ON_CONTINUOUS = prove
8082  (`!f s:real^N->bool. open s /\ f convex_on s ==> lift o f continuous_on s`,
8083   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT] THEN
8084   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
8085   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
8086   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
8087   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
8088   ABBREV_TAC `d = e / &(dimindex(:N))` THEN
8089   SUBGOAL_THEN `&0 < d` ASSUME_TAC THENL
8090    [EXPAND_TAC "d" THEN MATCH_MP_TAC REAL_LT_DIV THEN
8091     ASM_REWRITE_TAC[REAL_OF_NUM_LT; DIMINDEX_GE_1;
8092                     ARITH_RULE `0 < d <=> 1 <= d`];
8093     ALL_TAC] THEN
8094   SUBGOAL_THEN
8095    `?b. !y:real^N. y IN interval[(x - lambda i. d),(x + lambda i. d)]
8096                    ==> f(y) <= b`
8097   STRIP_ASSUME_TAC THENL
8098    [MP_TAC(ISPECL [`x - (lambda i. d):real^N`; `x + (lambda i. d):real^N`]
8099         CLOSED_INTERVAL_AS_CONVEX_HULL) THEN
8100     DISCH_THEN(X_CHOOSE_THEN `c:real^N->bool` STRIP_ASSUME_TAC) THEN
8101     ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `c = {}:real^N->bool` THEN
8102     ASM_REWRITE_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY] THEN
8103     MP_TAC(ISPEC `IMAGE (f:real^N->real) c` SUP_FINITE) THEN
8104     ASM_SIMP_TAC[FINITE_IMAGE; IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
8105     ABBREV_TAC `k = sup(IMAGE (f:real^N->real) c)` THEN
8106     STRIP_TAC THEN EXISTS_TAC `k:real` THEN
8107     MATCH_MP_TAC CONVEX_ON_CONVEX_HULL_BOUND THEN
8108     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONVEX_ON_SUBSET THEN
8109     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
8110     MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `cball (x:real^N,e)` THEN
8111     ASM_REWRITE_TAC[] THEN
8112     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [SYM th]) THEN
8113     REWRITE_TAC[SUBSET; IN_INTERVAL; IN_CBALL] THEN
8114     SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_SUB_COMPONENT; LAMBDA_BETA] THEN
8115     X_GEN_TAC `z:real^N` THEN
8116     REWRITE_TAC[REAL_ARITH `x - d <= z /\ z <= x + d <=> abs(x - z) <= d`] THEN
8117     DISCH_TAC THEN REWRITE_TAC[dist] THEN
8118     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
8119      `sum(1..dimindex(:N)) (\i. abs((x - z:real^N)$i))` THEN
8120     REWRITE_TAC[NORM_LE_L1] THEN
8121     MATCH_MP_TAC SUM_BOUND_GEN THEN
8122     REWRITE_TAC[FINITE_NUMSEG; NUMSEG_EMPTY; CARD_NUMSEG] THEN
8123     ASM_SIMP_TAC[IN_NUMSEG; NOT_LT; DIMINDEX_GE_1; ADD_SUB;
8124                  VECTOR_SUB_COMPONENT];
8125     ALL_TAC] THEN
8126   SUBGOAL_THEN `cball(x:real^N,d) SUBSET cball(x,e)` ASSUME_TAC THENL
8127    [REWRITE_TAC[SUBSET; IN_CBALL] THEN GEN_TAC THEN
8128     MATCH_MP_TAC(REAL_ARITH `d <= e ==> x <= d ==> x <= e`) THEN
8129     EXPAND_TAC "d" THEN
8130     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; DIMINDEX_GE_1;
8131                  ARITH_RULE `0 < x <=> 1 <= x`] THEN
8132     GEN_REWRITE_TAC LAND_CONV [GSYM REAL_MUL_RID] THEN
8133     ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_OF_NUM_LE; DIMINDEX_GE_1];
8134     ALL_TAC] THEN
8135   SUBGOAL_THEN
8136    `!y:real^N. y IN cball(x,d) ==> abs(f(y)) <= b + &2 * abs(f(x))`
8137   ASSUME_TAC THENL
8138    [MATCH_MP_TAC CONVEX_BOUNDS_LEMMA THEN CONJ_TAC THENL
8139      [ASM_MESON_TAC[CONVEX_ON_SUBSET; SUBSET_TRANS]; ALL_TAC] THEN
8140     REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
8141     UNDISCH_TAC `y:real^N IN cball(x,d)` THEN REWRITE_TAC[IN_CBALL] THEN
8142     REWRITE_TAC[IN_INTERVAL; IN_CBALL; dist] THEN DISCH_TAC THEN
8143     SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_SUB_COMPONENT; LAMBDA_BETA] THEN
8144     REWRITE_TAC[REAL_ARITH `x - d <= z /\ z <= x + d <=> abs(x - z) <= d`] THEN
8145     SIMP_TAC[GSYM VECTOR_SUB_COMPONENT] THEN REPEAT STRIP_TAC THEN
8146     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `norm(x - y:real^N)` THEN
8147     ASM_SIMP_TAC[COMPONENT_LE_NORM];
8148     ALL_TAC] THEN
8149   SUBGOAL_THEN `(lift o f) continuous_on (ball(x:real^N,d))` MP_TAC THENL
8150    [MATCH_MP_TAC CONVEX_ON_BOUNDED_CONTINUOUS THEN REWRITE_TAC[OPEN_BALL] THEN
8151     EXISTS_TAC `b + &2 * abs(f(x:real^N))` THEN
8152     ASM_MESON_TAC[SUBSET; CONVEX_ON_SUBSET; SUBSET_TRANS; BALL_SUBSET_CBALL];
8153     ALL_TAC] THEN
8154   ASM_SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT; OPEN_BALL; CENTRE_IN_BALL]);;
8155
8156 (* ------------------------------------------------------------------------- *)
8157 (* Characterizations of convex functions in terms of sequents.               *)
8158 (* ------------------------------------------------------------------------- *)
8159
8160 let CONVEX_ON_LEFT_SECANT_MUL,CONVEX_ON_RIGHT_SECANT_MUL = (CONJ_PAIR o prove)
8161  (`(!f s:real^N->bool.
8162         f convex_on s <=>
8163           !a b x. a IN s /\ b IN s /\ x IN segment[a,b]
8164                   ==> (f x - f a) * norm(b - a) <= (f b - f a) * norm(x - a)) /\
8165    (!f s:real^N->bool.
8166         f convex_on s <=>
8167           !a b x. a IN s /\ b IN s /\ x IN segment[a,b]
8168                   ==> (f b - f a) * norm(b - x) <= (f b - f x) * norm(b - a))`,
8169   CONJ_TAC THEN
8170   REPEAT GEN_TAC THEN REWRITE_TAC[convex_on] THEN
8171   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8172   X_GEN_TAC `a:real^N` THEN REWRITE_TAC[] THEN
8173   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8174   X_GEN_TAC `b:real^N` THEN REWRITE_TAC[] THEN
8175   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
8176   ASM_CASES_TAC `(b:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
8177   REWRITE_TAC[IN_SEGMENT; LEFT_IMP_EXISTS_THM] THEN
8178   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
8179   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8180   X_GEN_TAC `u:real` THEN REWRITE_TAC[] THEN
8181   REWRITE_TAC[TAUT `a /\ x = y <=> x = y /\ a`;
8182               TAUT `a /\ x = y /\ b <=> x = y /\ a /\ b`] THEN
8183   REWRITE_TAC[REAL_ARITH `v + u = &1 <=> v = &1 - u`] THEN
8184   REWRITE_TAC[FORALL_UNWIND_THM2; IMP_CONJ] THEN
8185   REWRITE_TAC[REAL_SUB_LE] THEN
8186   ASM_CASES_TAC `&0 <= u` THEN ASM_REWRITE_TAC[] THEN
8187   ASM_CASES_TAC `u <= &1` THEN ASM_REWRITE_TAC[] THEN
8188   REWRITE_TAC[VECTOR_ARITH `((&1 - u) % a + u % b) - a:real^N = u % (b - a)`;
8189    VECTOR_ARITH `b - ((&1 - u) % a + u % b):real^N = (&1 - u) % (b - a)`] THEN
8190   REWRITE_TAC[NORM_MUL; REAL_MUL_ASSOC] THEN
8191   (ASM_CASES_TAC `b:real^N = a` THENL
8192    [ASM_REWRITE_TAC[VECTOR_SUB_REFL; REAL_SUB_REFL;
8193                     VECTOR_ARITH `(&1 - u) % a + u % a:real^N = a`] THEN
8194     REAL_ARITH_TAC;
8195     ASM_SIMP_TAC[REAL_LE_RMUL_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
8196     ASM_SIMP_TAC[REAL_ARITH
8197      `&0 <= u /\ u <= &1 ==> abs u = u /\ abs(&1 - u) = &1 - u`] THEN
8198     REAL_ARITH_TAC]));;
8199
8200 let CONVEX_ON_LEFT_SECANT,CONVEX_ON_RIGHT_SECANT = (CONJ_PAIR o prove)
8201  (`(!f s:real^N->bool.
8202       f convex_on s <=>
8203         !a b x. a IN s /\ b IN s /\ x IN segment(a,b)
8204                 ==> (f x - f a) / norm(x - a) <= (f b - f a) / norm(b - a)) /\
8205    (!f s:real^N->bool.
8206       f convex_on s <=>
8207         !a b x. a IN s /\ b IN s /\ x IN segment(a,b)
8208                 ==> (f b - f a) / norm(b - a) <= (f b - f x) / norm(b - x))`,
8209   CONJ_TAC THEN REPEAT GEN_TAC THENL
8210    [REWRITE_TAC[CONVEX_ON_LEFT_SECANT_MUL];
8211     REWRITE_TAC[CONVEX_ON_RIGHT_SECANT_MUL]] THEN
8212   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8213   X_GEN_TAC `a:real^N` THEN REWRITE_TAC[] THEN
8214   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8215   X_GEN_TAC `b:real^N` THEN REWRITE_TAC[] THEN
8216   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
8217   ASM_CASES_TAC `(b:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
8218   ASM_CASES_TAC `a:real^N = b` THEN
8219   ASM_REWRITE_TAC[SEGMENT_REFL; NOT_IN_EMPTY; REAL_SUB_REFL; VECTOR_SUB_REFL;
8220                   NORM_0; REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_LE_REFL] THEN
8221   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8222   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[] THEN
8223   REWRITE_TAC[open_segment; IN_DIFF; IN_INSERT; NOT_IN_EMPTY] THEN
8224   MAP_EVERY ASM_CASES_TAC [`x:real^N = a`; `x:real^N = b`] THEN
8225   ASM_REWRITE_TAC[REAL_LE_REFL; REAL_SUB_REFL; VECTOR_SUB_REFL; NORM_0;
8226                   REAL_MUL_LZERO; REAL_MUL_RZERO] THEN
8227   ASM_SIMP_TAC[REAL_LE_RDIV_EQ; GSYM REAL_LE_LDIV_EQ; NORM_POS_LT;
8228                VECTOR_SUB_EQ] THEN
8229   AP_TERM_TAC THEN REAL_ARITH_TAC);;
8230
8231 (* ------------------------------------------------------------------------- *)
8232 (* Starlike sets and more stuff about line segments.                         *)
8233 (* ------------------------------------------------------------------------- *)
8234
8235 let starlike = new_definition
8236  `starlike s <=> ?a. a IN s /\ !x. x IN s ==> segment[a,x] SUBSET s`;;
8237
8238 let CONVEX_CONTAINS_SEGMENT = prove
8239  (`!s. convex s <=> !a b. a IN s /\ b IN s ==> segment[a,b] SUBSET s`,
8240   REWRITE_TAC[CONVEX_ALT; segment; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
8241
8242 let CONVEX_CONTAINS_SEGMENT_EQ = prove
8243  (`!s:real^N->bool.
8244         convex s <=> !a b. segment[a,b] SUBSET s <=> a IN s /\ b IN s`,
8245   REWRITE_TAC[CONVEX_CONTAINS_SEGMENT; SUBSET] THEN
8246   MESON_TAC[ENDS_IN_SEGMENT]);;
8247
8248 let CONVEX_CONTAINS_SEGMENT_IMP = prove
8249  (`!s a b. convex s ==> (segment[a,b] SUBSET s <=> a IN s /\ b IN s)`,
8250   SIMP_TAC[CONVEX_CONTAINS_SEGMENT_EQ]);;
8251
8252 let CONVEX_IMP_STARLIKE = prove
8253  (`!s. convex s /\ ~(s = {}) ==> starlike s`,
8254   REWRITE_TAC[CONVEX_CONTAINS_SEGMENT; starlike; GSYM MEMBER_NOT_EMPTY] THEN
8255   MESON_TAC[]);;
8256
8257 let SEGMENT_CONVEX_HULL = prove
8258  (`!a b. segment[a,b] = convex hull {a,b}`,
8259   REPEAT GEN_TAC THEN
8260   SIMP_TAC[CONVEX_HULL_INSERT; CONVEX_HULL_SING; NOT_INSERT_EMPTY] THEN
8261   REWRITE_TAC[IN_SING; RIGHT_EXISTS_AND_THM; UNWIND_THM2] THEN
8262   REWRITE_TAC[segment; EXTENSION; IN_ELIM_THM] THEN
8263   REWRITE_TAC[REAL_ARITH `u + v = &1 <=> u = &1 - v`] THEN
8264   REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
8265   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c /\ d <=> c /\ a /\ b /\ d`] THEN
8266   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[UNWIND_THM2] THEN
8267   REWRITE_TAC[REAL_LE_SUB_LADD; REAL_ADD_LID] THEN MESON_TAC[]);;
8268
8269 let SEGMENT_FURTHEST_LE = prove
8270  (`!a b x y:real^N.
8271         x IN segment[a,b] ==> norm(y - x) <= norm(y - a) \/
8272                               norm(y - x) <= norm(y - b)`,
8273   REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN REPEAT STRIP_TAC THEN
8274   MP_TAC(ISPECL [`y:real^N`; `{a:real^N,b}`] SIMPLEX_FURTHEST_LE) THEN
8275   ASM_REWRITE_TAC[FINITE_INSERT; FINITE_RULES; NOT_INSERT_EMPTY] THEN
8276   REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN STRIP_TAC THEN
8277   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
8278   ASM_MESON_TAC[NORM_SUB]);;
8279
8280 let SEGMENT_BOUND = prove
8281  (`!a b x:real^N.
8282         x IN segment[a,b] ==> norm(x - a) <= norm(b - a) /\
8283                               norm(x - b) <= norm(b - a)`,
8284   REPEAT STRIP_TAC THEN
8285   MP_TAC(SPECL [`a:real^N`; `b:real^N`; `x:real^N`] SEGMENT_FURTHEST_LE) THENL
8286    [DISCH_THEN(MP_TAC o SPEC `a:real^N`);
8287     DISCH_THEN(MP_TAC o SPEC `b:real^N`)] THEN
8288   REWRITE_TAC[VECTOR_SUB_REFL; NORM_0] THEN
8289   ASM_MESON_TAC[NORM_POS_LE; REAL_LE_TRANS; NORM_SUB]);;
8290
8291 let BETWEEN_IN_CONVEX_HULL = prove
8292  (`!x a b:real^N. between x (a,b) <=> x IN convex hull {a,b}`,
8293   REWRITE_TAC[BETWEEN_IN_SEGMENT; SEGMENT_CONVEX_HULL]);;
8294
8295 let STARLIKE_LINEAR_IMAGE = prove
8296  (`!f s. starlike s /\ linear f ==> starlike(IMAGE f s)`,
8297   REWRITE_TAC[starlike; FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
8298   SIMP_TAC[CLOSED_SEGMENT_LINEAR_IMAGE] THEN SET_TAC[]);;
8299
8300 let STARLIKE_LINEAR_IMAGE_EQ = prove
8301  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
8302          ==> (starlike (IMAGE f s) <=> starlike s)`,
8303   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE STARLIKE_LINEAR_IMAGE));;
8304
8305 add_linear_invariants [STARLIKE_LINEAR_IMAGE_EQ];;
8306
8307 let STARLIKE_TRANSLATION_EQ = prove
8308  (`!a s. starlike (IMAGE (\x. a + x) s) <=> starlike s`,
8309   REWRITE_TAC[starlike] THEN GEOM_TRANSLATE_TAC[]);;
8310
8311 add_translation_invariants [STARLIKE_TRANSLATION_EQ];;
8312
8313 let BETWEEN_LINEAR_IMAGE_EQ = prove
8314  (`!f x y z. linear f /\ (!x y. f x = f y ==> x = y)
8315              ==> (between (f x) (f y,f z) <=> between x (y,z))`,
8316   SIMP_TAC[BETWEEN_IN_SEGMENT; CLOSED_SEGMENT_LINEAR_IMAGE] THEN SET_TAC[]);;
8317
8318 add_linear_invariants [BETWEEN_LINEAR_IMAGE_EQ];;
8319
8320 let BETWEEN_TRANSLATION = prove
8321  (`!a x y. between (a + x) (a + y,a + z) <=> between x (y,z)`,
8322   REWRITE_TAC[between] THEN NORM_ARITH_TAC);;
8323
8324 add_translation_invariants [STARLIKE_TRANSLATION_EQ];;
8325
8326 let STARLIKE_CLOSURE = prove
8327  (`!s:real^N->bool. starlike s ==> starlike(closure s)`,
8328   GEN_TAC THEN REWRITE_TAC[starlike; SUBSET; segment; FORALL_IN_GSPEC] THEN
8329   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
8330   STRIP_TAC THEN ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN
8331   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE] THEN
8332   DISCH_TAC THEN X_GEN_TAC `u:real` THEN STRIP_TAC THEN X_GEN_TAC `e:real` THEN
8333   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN
8334   ASM_REWRITE_TAC[] THEN
8335   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
8336   EXISTS_TAC `(&1 - u) % a + u % y:real^N` THEN
8337   ASM_SIMP_TAC[dist; NORM_MUL; VECTOR_ARITH
8338    `(v % a + u % y) - (v % a + u % z):real^N = u % (y - z)`] THEN
8339   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
8340         REAL_LET_TRANS)) THEN
8341   REWRITE_TAC[dist; REAL_ARITH `u * n <= n <=> &0 <= n * (&1 - u)`] THEN
8342   MATCH_MP_TAC REAL_LE_MUL THEN REWRITE_TAC[NORM_POS_LE] THEN
8343   ASM_REAL_ARITH_TAC);;
8344
8345 let STARLIKE_UNIV = prove
8346  (`starlike(:real^N)`,
8347   MESON_TAC[CONVEX_IMP_STARLIKE; CONVEX_UNIV;
8348             BOUNDED_EMPTY; NOT_BOUNDED_UNIV]);;
8349
8350 let STARLIKE_PCROSS = prove
8351  (`!s:real^M->bool t:real^N->bool.
8352         starlike s /\ starlike t ==> starlike(s PCROSS t)`,
8353   SIMP_TAC[starlike; EXISTS_IN_PCROSS; SUBSET; IN_SEGMENT] THEN
8354   REPEAT GEN_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
8355   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
8356   REWRITE_TAC[FORALL_IN_PCROSS; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
8357   REWRITE_TAC[FORALL_UNWIND_THM2; IMP_IMP] THEN
8358   REWRITE_TAC[GSYM PASTECART_CMUL; PASTECART_ADD] THEN
8359   REWRITE_TAC[PASTECART_IN_PCROSS] THEN MESON_TAC[]);;
8360
8361 let STARLIKE_PCROSS_EQ = prove
8362  (`!s:real^M->bool t:real^N->bool.
8363         starlike(s PCROSS t) <=> starlike s /\ starlike t`,
8364   REPEAT GEN_TAC THEN
8365   ASM_CASES_TAC `s:real^M->bool = {}` THENL
8366    [ASM_REWRITE_TAC[PCROSS_EMPTY] THEN MESON_TAC[starlike; NOT_IN_EMPTY];
8367     ALL_TAC] THEN
8368   ASM_CASES_TAC `t:real^N->bool = {}` THENL
8369    [ASM_REWRITE_TAC[PCROSS_EMPTY] THEN MESON_TAC[starlike; NOT_IN_EMPTY];
8370     ALL_TAC] THEN
8371   EQ_TAC THEN REWRITE_TAC[STARLIKE_PCROSS] THEN REPEAT STRIP_TAC THENL
8372    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
8373      `(s:real^M->bool) PCROSS (t:real^N->bool)`] STARLIKE_LINEAR_IMAGE) THEN
8374     ASM_REWRITE_TAC[LINEAR_FSTCART];
8375     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
8376      `(s:real^M->bool) PCROSS (t:real^N->bool)`] STARLIKE_LINEAR_IMAGE) THEN
8377     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
8378   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
8379   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
8380               FSTCART_PASTECART; SNDCART_PASTECART] THEN
8381   ASM SET_TAC[]);;
8382
8383 let BETWEEN_DIST_LT = prove
8384  (`!r a b c:real^N.
8385         dist(c,a) < r /\ dist(c,b) < r /\ between x (a,b) ==> dist(c,x) < r`,
8386   REPEAT STRIP_TAC THEN
8387   SUBGOAL_THEN `convex hull {a,b} SUBSET ball(c:real^N,r)` MP_TAC THENL
8388    [MATCH_MP_TAC HULL_MINIMAL THEN
8389     ASM_REWRITE_TAC[CONVEX_BALL; INSERT_SUBSET; EMPTY_SUBSET; IN_BALL];
8390     ASM_SIMP_TAC[SUBSET; GSYM BETWEEN_IN_CONVEX_HULL; IN_BALL]]);;
8391
8392 let BETWEEN_DIST_LE = prove
8393  (`!r a b c:real^N.
8394       dist(c,a) <= r /\ dist(c,b) <= r /\ between x (a,b) ==> dist(c,x) <= r`,
8395
8396   REPEAT STRIP_TAC THEN
8397   SUBGOAL_THEN `convex hull {a,b} SUBSET cball(c:real^N,r)` MP_TAC THENL
8398    [MATCH_MP_TAC HULL_MINIMAL THEN
8399     ASM_REWRITE_TAC[CONVEX_CBALL; INSERT_SUBSET; EMPTY_SUBSET; IN_CBALL];
8400     ASM_SIMP_TAC[SUBSET; GSYM BETWEEN_IN_CONVEX_HULL; IN_CBALL]]);;
8401
8402 let BETWEEN_NORM_LT = prove
8403  (`!r a b x:real^N.
8404         norm a < r /\ norm b < r /\ between x (a,b) ==> norm x < r`,
8405   REWRITE_TAC[GSYM(CONJUNCT2(SPEC_ALL DIST_0)); BETWEEN_DIST_LT]);;
8406
8407 let BETWEEN_NORM_LE = prove
8408  (`!r a b x:real^N.
8409         norm a <= r /\ norm b <= r /\ between x (a,b) ==> norm x <= r`,
8410   REWRITE_TAC[GSYM(CONJUNCT2(SPEC_ALL DIST_0)); BETWEEN_DIST_LE]);;
8411
8412 (* ------------------------------------------------------------------------- *)
8413 (* Shrinking towards the interior of a convex set.                           *)
8414 (* ------------------------------------------------------------------------- *)
8415
8416 let IN_INTERIOR_CONVEX_SHRINK = prove
8417  (`!s e x c:real^N.
8418      convex s /\ c IN interior s /\
8419      x IN s /\ &0 < e /\ e <= &1
8420      ==> x - e % (x - c) IN interior s`,
8421   REPEAT STRIP_TAC THEN
8422   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR]) THEN
8423   REWRITE_TAC[IN_INTERIOR; SUBSET; IN_BALL; dist] THEN
8424   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
8425   EXISTS_TAC `e * d:real` THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
8426   X_GEN_TAC `y':real^N` THEN DISCH_TAC THEN
8427   FIRST_X_ASSUM(MP_TAC o SPEC `(&1 / e) % y' - ((&1 - e) / e) % x:real^N`) THEN
8428   ANTS_TAC THENL
8429    [UNDISCH_TAC `norm (x - e % (x - c) - y':real^N) < e * d` THEN
8430     SUBGOAL_THEN `x - e % (x - c) - y':real^N =
8431                   e % (c - (&1 / e % y' - (&1 - e) / e % x))`
8432     SUBST1_TAC THENL
8433      [ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; VECTOR_MUL_ASSOC;
8434                    REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN VECTOR_ARITH_TAC;
8435       ASM_SIMP_TAC[NORM_MUL; REAL_LT_LMUL_EQ; real_abs; REAL_LT_IMP_LE]];
8436     DISCH_TAC THEN
8437     SUBGOAL_THEN `y' = (&1 - (&1 - e)) % (&1 / e % y' - (&1 - e) / e % x) +
8438                        (&1 - e) % x:real^N`
8439     SUBST1_TAC THENL
8440      [ASM_SIMP_TAC[REAL_ARITH `&1 - (&1 - e) = e`; VECTOR_SUB_LDISTRIB;
8441                    VECTOR_MUL_ASSOC; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
8442       VECTOR_ARITH_TAC;
8443       FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
8444       ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC]]);;
8445
8446 let IN_INTERIOR_CLOSURE_CONVEX_SHRINK = prove
8447  (`!s e x c:real^N.
8448      convex s /\ c IN interior s /\
8449      x IN closure s /\ &0 < e /\ e <= &1
8450      ==> x - e % (x - c) IN interior s`,
8451   REPEAT STRIP_TAC THEN
8452   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR]) THEN
8453   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
8454   SUBGOAL_THEN `?y:real^N. y IN s /\ norm(y - x) * (&1 - e) < e * d`
8455   STRIP_ASSUME_TAC THENL
8456    [ASM_CASES_TAC `(x:real^N) IN s` THENL
8457      [EXISTS_TAC `x:real^N` THEN
8458       ASM_SIMP_TAC[REAL_LT_MUL; VECTOR_SUB_REFL; NORM_0; REAL_MUL_LZERO];
8459       ALL_TAC] THEN
8460     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [closure]) THEN
8461     ASM_REWRITE_TAC[IN_UNION; IN_ELIM_THM; LIMPT_APPROACHABLE; dist] THEN
8462     FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
8463      `e <= &1 ==> e = &1 \/ e < &1`)) THEN
8464     ASM_SIMP_TAC[REAL_SUB_REFL; GSYM REAL_LT_RDIV_EQ; REAL_SUB_LT] THENL
8465      [DISCH_THEN(MP_TAC o SPEC `&1`) THEN
8466       REWRITE_TAC[REAL_MUL_RZERO; REAL_LT_01];
8467       DISCH_THEN(MP_TAC o SPEC `(e * d) / (&1 - e)`)] THEN
8468     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_SUB_LT; REAL_MUL_LZERO; REAL_LT_MUL;
8469                  REAL_MUL_LID] THEN
8470     MATCH_MP_TAC MONO_EXISTS THEN MESON_TAC[];
8471     ALL_TAC] THEN
8472   ABBREV_TAC `z:real^N = c + ((&1 - e) / e) % (x - y)` THEN
8473   SUBGOAL_THEN `x - e % (x - c):real^N = y - e % (y - z)` SUBST1_TAC THENL
8474    [EXPAND_TAC "z" THEN
8475     REWRITE_TAC[VECTOR_SUB_LDISTRIB; VECTOR_ADD_LDISTRIB] THEN
8476     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
8477     VECTOR_ARITH_TAC;
8478     ALL_TAC] THEN
8479   MATCH_MP_TAC IN_INTERIOR_CONVEX_SHRINK THEN ASM_REWRITE_TAC[] THEN
8480   FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET] o
8481      MATCH_MP SUBSET_INTERIOR) THEN
8482   SIMP_TAC[INTERIOR_OPEN; OPEN_BALL] THEN
8483   REWRITE_TAC[IN_BALL; dist] THEN EXPAND_TAC "z" THEN
8484   REWRITE_TAC[NORM_ARITH `norm(c - (c + x)) = norm(x)`] THEN
8485   REWRITE_TAC[NORM_MUL; REAL_ABS_DIV] THEN
8486   ASM_SIMP_TAC[real_abs; REAL_LT_IMP_LE; REAL_SUB_LE] THEN
8487   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8488   REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN
8489   ASM_SIMP_TAC[GSYM real_div; REAL_LT_LDIV_EQ] THEN
8490   ASM_MESON_TAC[REAL_MUL_SYM; NORM_SUB]);;
8491
8492 let IN_INTERIOR_CLOSURE_CONVEX_SEGMENT = prove
8493  (`!s a b:real^N.
8494         convex s /\ a IN interior s /\ b IN closure s
8495         ==> segment(a,b) SUBSET interior s`,
8496   REWRITE_TAC[SUBSET; IN_SEGMENT] THEN REPEAT STRIP_TAC THEN
8497   ASM_REWRITE_TAC[VECTOR_ARITH
8498    `(&1 - u) % a + u % b:real^N = b - (&1 - u) % (b - a)`] THEN
8499   MATCH_MP_TAC IN_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
8500   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
8501
8502 (* ------------------------------------------------------------------------- *)
8503 (* Relative interior of a set.                                               *)
8504 (* ------------------------------------------------------------------------- *)
8505
8506 let relative_interior = new_definition
8507  `relative_interior s =
8508    {x | ?t. open_in (subtopology euclidean (affine hull s)) t /\
8509             x IN t /\ t SUBSET s}`;;
8510
8511 let relative_frontier = new_definition
8512  `relative_frontier s = closure s DIFF relative_interior s`;;
8513
8514 let RELATIVE_INTERIOR = prove
8515  (`!s. relative_interior s =
8516           {x | x IN s /\
8517                ?t. open t /\ x IN t /\ t INTER (affine hull s) SUBSET s}`,
8518   REWRITE_TAC[EXTENSION; relative_interior; IN_ELIM_THM] THEN
8519   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN; LEFT_AND_EXISTS_THM] THEN
8520   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
8521   ONCE_REWRITE_TAC[TAUT `(a /\ b) /\ c /\ d <=> b /\ a /\ c /\ d`] THEN
8522   REWRITE_TAC[UNWIND_THM2; SUBSET; IN_INTER; RIGHT_AND_EXISTS_THM] THEN
8523   AP_TERM_TAC THEN ABS_TAC THEN MESON_TAC[HULL_INC]);;
8524
8525 let RELATIVE_INTERIOR_EQ = prove
8526  (`!s. relative_interior s = s <=>
8527        open_in(subtopology euclidean (affine hull s)) s`,
8528   GEN_TAC THEN REWRITE_TAC[EXTENSION; relative_interior; IN_ELIM_THM] THEN
8529   GEN_REWRITE_TAC RAND_CONV [OPEN_IN_SUBOPEN] THEN MESON_TAC[SUBSET]);;
8530
8531 let RELATIVE_INTERIOR_OPEN_IN = prove
8532  (`!s. open_in(subtopology euclidean (affine hull s)) s
8533        ==> relative_interior s = s`,
8534   REWRITE_TAC[RELATIVE_INTERIOR_EQ]);;
8535
8536 let RELATIVE_INTERIOR_EMPTY = prove
8537  (`relative_interior {} = {}`,
8538   SIMP_TAC[RELATIVE_INTERIOR_OPEN_IN; OPEN_IN_EMPTY]);;
8539
8540 let RELATIVE_FRONTIER_EMPTY = prove
8541  (`relative_frontier {} = {}`,
8542   REWRITE_TAC[relative_frontier; CLOSURE_EMPTY; EMPTY_DIFF]);;
8543
8544 let RELATIVE_INTERIOR_AFFINE = prove
8545  (`!s:real^N->bool. affine s ==> relative_interior s = s`,
8546   SIMP_TAC[RELATIVE_INTERIOR_EQ; OPEN_IN_SUBTOPOLOGY_REFL; HULL_P] THEN
8547   REWRITE_TAC[TOPSPACE_EUCLIDEAN; SUBSET_UNIV]);;
8548
8549 let RELATIVE_INTERIOR_UNIV = prove
8550  (`!s. relative_interior(affine hull s) = affine hull s`,
8551   REPEAT STRIP_TAC THEN MATCH_MP_TAC RELATIVE_INTERIOR_OPEN_IN THEN
8552   REWRITE_TAC[HULL_HULL; OPEN_IN_SUBTOPOLOGY_REFL] THEN
8553   REWRITE_TAC[TOPSPACE_EUCLIDEAN; SUBSET_UNIV]);;
8554
8555 let OPEN_IN_RELATIVE_INTERIOR = prove
8556  (`!s. open_in (subtopology euclidean (affine hull s))
8557                (relative_interior s)`,
8558   GEN_TAC THEN REWRITE_TAC[relative_interior] THEN
8559   GEN_REWRITE_TAC I [OPEN_IN_SUBOPEN] THEN
8560   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
8561
8562 let RELATIVE_INTERIOR_SUBSET = prove
8563  (`!s. (relative_interior s) SUBSET s`,
8564   REWRITE_TAC[SUBSET; relative_interior; IN_ELIM_THM] THEN MESON_TAC[]);;
8565
8566 let SUBSET_RELATIVE_INTERIOR = prove
8567  (`!s t. s SUBSET t /\ affine hull s = affine hull t
8568          ==> (relative_interior s) SUBSET (relative_interior t)`,
8569   REWRITE_TAC[relative_interior; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
8570
8571 let RELATIVE_INTERIOR_MAXIMAL = prove
8572  (`!s t. t SUBSET s /\
8573          open_in(subtopology euclidean (affine hull s)) t
8574          ==> t SUBSET (relative_interior s)`,
8575   REWRITE_TAC[relative_interior; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
8576
8577 let RELATIVE_INTERIOR_UNIQUE = prove
8578  (`!s t. t SUBSET s /\
8579          open_in(subtopology euclidean (affine hull s)) t /\
8580          (!t'. t' SUBSET s /\
8581                open_in(subtopology euclidean (affine hull s)) t'
8582                ==> t' SUBSET t)
8583          ==> (relative_interior s = t)`,
8584   MESON_TAC[SUBSET_ANTISYM; RELATIVE_INTERIOR_MAXIMAL; RELATIVE_INTERIOR_SUBSET;
8585             OPEN_IN_RELATIVE_INTERIOR]);;
8586
8587 let IN_RELATIVE_INTERIOR = prove
8588  (`!x:real^N s.
8589         x IN relative_interior s <=>
8590         x IN s /\ ?e. &0 < e /\ (ball(x,e) INTER (affine hull s)) SUBSET s`,
8591   REPEAT GEN_TAC THEN REWRITE_TAC[relative_interior; IN_ELIM_THM] THEN
8592   REWRITE_TAC[OPEN_IN_OPEN; LEFT_AND_EXISTS_THM] THEN
8593   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
8594   ONCE_REWRITE_TAC[TAUT `(a /\ b) /\ c /\ d <=> b /\ a /\ c /\ d`] THEN
8595   REWRITE_TAC[UNWIND_THM2; SUBSET; IN_INTER] THEN EQ_TAC THENL
8596    [ASM_MESON_TAC[SUBSET; OPEN_CONTAINS_BALL];
8597     STRIP_TAC THEN EXISTS_TAC `ball(x:real^N,e)` THEN
8598     ASM_SIMP_TAC[OPEN_BALL; CENTRE_IN_BALL; HULL_INC]]);;
8599
8600 let IN_RELATIVE_INTERIOR_CBALL = prove
8601  (`!x:real^N s.
8602         x IN relative_interior s <=>
8603         x IN s /\ ?e. &0 < e /\ (cball(x,e) INTER affine hull s) SUBSET s`,
8604   REPEAT GEN_TAC THEN REWRITE_TAC[IN_RELATIVE_INTERIOR] THEN
8605   AP_TERM_TAC THEN EQ_TAC THEN
8606   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THENL
8607    [EXISTS_TAC `e / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
8608     MATCH_MP_TAC SUBSET_TRANS THEN
8609     EXISTS_TAC `ball(x:real^N,e) INTER affine hull s` THEN
8610     ASM_REWRITE_TAC[] THEN
8611     REWRITE_TAC[SUBSET; IN_INTER; IN_BALL; IN_CBALL] THEN
8612     ASM_SIMP_TAC[REAL_ARITH `&0 < e /\ x <= e / &2 ==> x < e`];
8613     EXISTS_TAC `e:real` THEN ASM_REWRITE_TAC[] THEN
8614     MATCH_MP_TAC SUBSET_TRANS THEN
8615     EXISTS_TAC `cball(x:real^N,e) INTER affine hull s` THEN
8616     ASM_REWRITE_TAC[] THEN
8617     SIMP_TAC[SUBSET; IN_INTER; IN_BALL; IN_CBALL; REAL_LT_IMP_LE]]);;
8618
8619 let OPEN_IN_SUBSET_RELATIVE_INTERIOR = prove
8620  (`!s t. open_in(subtopology euclidean (affine hull t)) s
8621          ==> (s SUBSET relative_interior t <=> s SUBSET t)`,
8622   MESON_TAC[RELATIVE_INTERIOR_MAXIMAL; RELATIVE_INTERIOR_SUBSET;
8623             SUBSET_TRANS]);;
8624
8625 let RELATIVE_INTERIOR_TRANSLATION = prove
8626  (`!a:real^N s.
8627         relative_interior (IMAGE (\x. a + x) s) =
8628         IMAGE (\x. a + x) (relative_interior s)`,
8629   REWRITE_TAC[relative_interior; OPEN_IN_OPEN] THEN GEOM_TRANSLATE_TAC[]);;
8630
8631 add_translation_invariants [RELATIVE_INTERIOR_TRANSLATION];;
8632
8633 let RELATIVE_FRONTIER_TRANSLATION = prove
8634  (`!a:real^N s.
8635         relative_frontier (IMAGE (\x. a + x) s) =
8636         IMAGE (\x. a + x) (relative_frontier s)`,
8637   REWRITE_TAC[relative_frontier] THEN GEOM_TRANSLATE_TAC[]);;
8638
8639 add_translation_invariants [RELATIVE_FRONTIER_TRANSLATION];;
8640
8641 let RELATIVE_INTERIOR_INJECTIVE_LINEAR_IMAGE = prove
8642  (`!f:real^M->real^N s.
8643         linear f /\ (!x y. f x = f y ==> x = y)
8644         ==> relative_interior(IMAGE f s) = IMAGE f (relative_interior s)`,
8645   REPEAT GEN_TAC THEN DISCH_TAC THEN
8646   ASM_SIMP_TAC[relative_interior; AFFINE_HULL_LINEAR_IMAGE] THEN
8647   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> c /\ a /\ b`] THEN
8648   REWRITE_TAC[EXISTS_SUBSET_IMAGE] THEN
8649   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_INJECTIVE_LINEAR_IMAGE) THEN
8650   ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;
8651
8652 add_linear_invariants [RELATIVE_INTERIOR_INJECTIVE_LINEAR_IMAGE];;
8653
8654 let RELATIVE_FRONTIER_INJECTIVE_LINEAR_IMAGE = prove
8655  (`!f:real^M->real^N s.
8656         linear f /\ (!x y. f x = f y ==> x = y)
8657         ==> relative_frontier(IMAGE f s) = IMAGE f (relative_frontier s)`,
8658   REWRITE_TAC[relative_frontier] THEN GEOM_TRANSFORM_TAC[]);;
8659
8660 add_linear_invariants [RELATIVE_FRONTIER_INJECTIVE_LINEAR_IMAGE];;
8661
8662 let RELATIVE_INTERIOR_EQ_EMPTY = prove
8663  (`!s:real^N->bool.
8664         convex s ==> (relative_interior s = {} <=> s = {})`,
8665   SUBGOAL_THEN
8666    `!s:real^N->bool.
8667         vec 0 IN s /\ convex s ==> ~(relative_interior s = {})`
8668   ASSUME_TAC THENL
8669    [ALL_TAC;
8670     GEN_TAC THEN DISCH_TAC THEN
8671     ASM_CASES_TAC `s:real^N->bool = {}` THEN
8672     ASM_REWRITE_TAC[RELATIVE_INTERIOR_EMPTY] THEN
8673     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
8674     DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
8675     FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (\x:real^N. --a + x) s`) THEN
8676     REWRITE_TAC[CONVEX_TRANSLATION_EQ; RELATIVE_INTERIOR_TRANSLATION] THEN
8677     ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; IN_IMAGE] THEN
8678     DISCH_THEN MATCH_MP_TAC THEN EXISTS_TAC `a:real^N` THEN
8679     ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC] THEN
8680   GEN_TAC THEN STRIP_TAC THEN
8681   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_RELATIVE_INTERIOR] THEN
8682   ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC] THEN
8683   X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC
8684    (ISPEC `s:real^N->bool` BASIS_EXISTS) THEN
8685   SUBGOAL_THEN `span(s:real^N->bool) = span b` SUBST_ALL_TAC THENL
8686    [ASM_SIMP_TAC[SPAN_EQ] THEN ASM_MESON_TAC[SPAN_INC; SUBSET_TRANS];
8687     ALL_TAC] THEN
8688   RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
8689   ABBREV_TAC `n = dim(s:real^N->bool)` THEN
8690   SUBGOAL_THEN
8691    `!c. (!v. v IN b ==> &0 <= c(v)) /\ sum b c <= &1
8692         ==> vsum b (\v:real^N. c(v) % v) IN s`
8693   ASSUME_TAC THENL
8694    [REPEAT STRIP_TAC THEN SUBGOAL_THEN
8695      `vsum (vec 0 INSERT b :real^N->bool)
8696            (\v. (if v = vec 0 then &1 - sum b c else c v) % v) IN s`
8697     MP_TAC THENL
8698      [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
8699       ASM_SIMP_TAC[INSERT_SUBSET; FINITE_INSERT; SUM_CLAUSES;
8700                    INDEPENDENT_NONZERO; IN_INSERT] THEN
8701       CONJ_TAC THENL [ASM_MESON_TAC[REAL_SUB_LE]; ALL_TAC] THEN
8702       REWRITE_TAC[REAL_ARITH `&1 - x + y = &1 <=> x = y`] THEN
8703       MATCH_MP_TAC SUM_EQ THEN ASM_MESON_TAC[INDEPENDENT_NONZERO];
8704       MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN
8705       ASM_SIMP_TAC[VSUM_CLAUSES; INDEPENDENT_NONZERO] THEN
8706       REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
8707       MATCH_MP_TAC VSUM_EQ THEN ASM_MESON_TAC[INDEPENDENT_NONZERO]];
8708     ALL_TAC] THEN
8709   ABBREV_TAC `a:real^N = vsum b (\v. inv(&2 * &n + &1) % v)` THEN
8710   EXISTS_TAC `a:real^N` THEN CONJ_TAC THENL
8711    [EXPAND_TAC "a" THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
8712     ASM_SIMP_TAC[SUM_CONST; REAL_LE_INV_EQ; REAL_ARITH `&0 < &2 * &n + &1`;
8713                  GSYM real_div; REAL_LT_IMP_LE; REAL_LE_LDIV_EQ] THEN
8714     REAL_ARITH_TAC;
8715     ALL_TAC] THEN
8716   MP_TAC(ISPECL [`b:real^N->bool`; `inv(&2 * &n + &1)`]
8717         BASIS_COORDINATES_CONTINUOUS) THEN
8718   ASM_REWRITE_TAC[REAL_LT_INV_EQ] THEN
8719   ANTS_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
8720   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN STRIP_TAC THEN
8721   ASM_SIMP_TAC[SUBSET; IN_INTER; IMP_CONJ_ALT] THEN
8722   ASM_SIMP_TAC[SPAN_FINITE; LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN
8723   GEN_TAC THEN X_GEN_TAC `u:real^N->real` THEN
8724   DISCH_THEN(SUBST1_TAC o SYM) THEN REWRITE_TAC[IN_BALL; dist] THEN
8725   EXPAND_TAC "a" THEN ASM_SIMP_TAC[GSYM VSUM_SUB] THEN
8726   DISCH_THEN(fun th -> FIRST_X_ASSUM MATCH_MP_TAC THEN MP_TAC th) THEN
8727   REWRITE_TAC[GSYM VECTOR_SUB_RDISTRIB] THEN
8728   DISCH_THEN(fun th -> FIRST_X_ASSUM(MP_TAC o C MATCH_MP th)) THEN
8729   REWRITE_TAC[REAL_ARITH `abs(x - y) < x <=> &0 < y /\ abs(y) < &2 * x`] THEN
8730   SIMP_TAC[REAL_LT_IMP_LE] THEN DISCH_TAC THEN
8731   MATCH_MP_TAC REAL_LE_TRANS THEN
8732   EXISTS_TAC `&(CARD(b:real^N->bool)) * &2 * inv(&2 * &n + &1)` THEN
8733   CONJ_TAC THENL
8734    [MATCH_MP_TAC SUM_BOUND THEN
8735     ASM_SIMP_TAC[REAL_ARITH `abs x < a ==> x <= a`];
8736     ASM_REWRITE_TAC[REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN
8737     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_ARITH `&0 < &2 * &n + &1`] THEN
8738     REAL_ARITH_TAC]);;
8739
8740 let RELATIVE_INTERIOR_INTERIOR = prove
8741  (`!s. affine hull s = (:real^N)
8742        ==> relative_interior s = interior s`,
8743   SIMP_TAC[relative_interior; interior; SUBTOPOLOGY_UNIV; OPEN_IN]);;
8744
8745 let RELATIVE_INTERIOR_OPEN = prove
8746  (`!s:real^N->bool. open s ==> relative_interior s = s`,
8747   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
8748   ASM_REWRITE_TAC[RELATIVE_INTERIOR_EMPTY] THEN
8749   ASM_SIMP_TAC[RELATIVE_INTERIOR_INTERIOR; AFFINE_HULL_OPEN; INTERIOR_EQ]);;
8750
8751 let RELATIVE_INTERIOR_NONEMPTY_INTERIOR = prove
8752  (`!s. ~(interior s = {}) ==> relative_interior s = interior s`,
8753   MESON_TAC[RELATIVE_INTERIOR_INTERIOR; AFFINE_HULL_NONEMPTY_INTERIOR]);;
8754
8755 let RELATIVE_FRONTIER_NONEMPTY_INTERIOR = prove
8756  (`!s. ~(interior s = {}) ==> relative_frontier s = frontier s`,
8757   SIMP_TAC[relative_frontier; frontier; RELATIVE_INTERIOR_NONEMPTY_INTERIOR]);;
8758
8759 let RELATIVE_FRONTIER_FRONTIER = prove
8760  (`!s. affine hull s = (:real^N) ==> relative_frontier s = frontier s`,
8761   SIMP_TAC[relative_frontier; frontier; RELATIVE_INTERIOR_INTERIOR]);;
8762
8763 let AFFINE_HULL_CONVEX_HULL = prove
8764  (`!s. affine hull (convex hull s) = affine hull s`,
8765   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN
8766   REWRITE_TAC[AFFINE_AFFINE_HULL; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
8767   REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_MINIMAL THEN
8768   ASM_MESON_TAC[SUBSET_TRANS; HULL_SUBSET]);;
8769
8770 let INTERIOR_SIMPLEX_NONEMPTY = prove
8771  (`!s:real^N->bool.
8772         independent s /\ s HAS_SIZE (dimindex(:N))
8773         ==> ?a. a IN interior(convex hull (vec 0 INSERT s))`,
8774   REPEAT STRIP_TAC THEN
8775   MP_TAC(ISPEC `convex hull (vec 0 INSERT s):real^N->bool`
8776     RELATIVE_INTERIOR_EQ_EMPTY) THEN
8777   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_HULL] THEN
8778   REWRITE_TAC[CONVEX_HULL_EQ_EMPTY; CONVEX_CONVEX_HULL; NOT_INSERT_EMPTY] THEN
8779   REWRITE_TAC[MEMBER_NOT_EMPTY] THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
8780   AP_THM_TAC THEN AP_TERM_TAC THEN MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
8781   SIMP_TAC[AFFINE_HULL_EQ_SPAN; IN_INSERT; HULL_INC] THEN
8782   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
8783   EXISTS_TAC `span s:real^N->bool` THEN CONJ_TAC THENL
8784    [MATCH_MP_TAC SPAN_MONO THEN MATCH_MP_TAC(SET_RULE
8785      `(a INSERT s) SUBSET P hull (a INSERT s)
8786       ==> s SUBSET P hull (a INSERT s)`) THEN REWRITE_TAC[HULL_SUBSET];
8787     MATCH_MP_TAC(SET_RULE `UNIV SUBSET s ==> s = UNIV`) THEN
8788     MATCH_MP_TAC CARD_GE_DIM_INDEPENDENT THEN
8789     ASM_REWRITE_TAC[DIM_UNIV; SUBSET_UNIV] THEN
8790     ASM_MESON_TAC[LE_REFL;HAS_SIZE]]);;
8791
8792 let INTERIOR_SUBSET_RELATIVE_INTERIOR = prove
8793  (`!s. interior s SUBSET relative_interior s`,
8794   REWRITE_TAC[SUBSET; IN_INTERIOR; IN_RELATIVE_INTERIOR; IN_INTER] THEN
8795   MESON_TAC[CENTRE_IN_BALL]);;
8796
8797 let CONVEX_RELATIVE_INTERIOR = prove
8798  (`!s:real^N->bool. convex s ==> convex(relative_interior s)`,
8799   REWRITE_TAC[CONVEX_ALT; IN_RELATIVE_INTERIOR; IN_INTER;
8800               SUBSET; IN_BALL; dist] THEN
8801   GEN_TAC THEN DISCH_TAC THEN REPEAT GEN_TAC THEN
8802   REWRITE_TAC[TAUT `(a /\ b) /\ (c /\ d) /\ e ==> f <=>
8803                     a /\ c /\ e ==> b /\ d ==> f`] THEN
8804   STRIP_TAC THEN ASM_SIMP_TAC[] THEN
8805   MATCH_MP_TAC(MESON[] `(!d e. P d /\ Q e ==> R(min d e))
8806                         ==> (?e. P e) /\ (?e. Q e) ==> (?e. R e)`) THEN
8807   REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
8808   X_GEN_TAC `z:real^N` THEN STRIP_TAC THEN
8809   SUBST1_TAC(VECTOR_ARITH `z:real^N =
8810    (&1 - u) % (z - u % (y - x)) + u % (z + (&1 - u) % (y - x))`) THEN
8811   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
8812   FIRST_X_ASSUM(CONJUNCTS_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
8813   REWRITE_TAC[GSYM IMP_CONJ_ALT] THEN MATCH_MP_TAC MONO_AND THEN
8814   CONJ_TAC THEN DISCH_THEN MATCH_MP_TAC THEN
8815   (CONJ_TAC THENL
8816     [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
8817       `norm x < e ==> norm x = y ==> y < e`)) THEN
8818      AP_TERM_TAC THEN VECTOR_ARITH_TAC;
8819      REWRITE_TAC[VECTOR_ARITH `a - b % c:real^N = a + --b % c`] THEN
8820      MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
8821      ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC]]));;
8822
8823 let IN_RELATIVE_INTERIOR_CONVEX_SHRINK = prove
8824  (`!s e x c:real^N.
8825      convex s /\ c IN relative_interior s /\
8826      x IN s /\ &0 < e /\ e <= &1
8827      ==> x - e % (x - c) IN relative_interior s`,
8828   REPEAT STRIP_TAC THEN
8829   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR]) THEN
8830   REWRITE_TAC[IN_RELATIVE_INTERIOR; SUBSET; IN_INTER; IN_BALL; dist] THEN
8831   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
8832   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN CONJ_TAC THENL
8833    [REWRITE_TAC[VECTOR_ARITH
8834      `x - e % (x - c):real^N = (&1 - e) % x + e % c`] THEN
8835     FIRST_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [convex]) THEN
8836     ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
8837     ALL_TAC] THEN
8838   EXISTS_TAC `e * d:real` THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
8839   X_GEN_TAC `y':real^N` THEN STRIP_TAC THEN
8840   FIRST_X_ASSUM(MP_TAC o SPEC `(&1 / e) % y' - ((&1 - e) / e) % x:real^N`) THEN
8841   ANTS_TAC THENL
8842    [CONJ_TAC THENL
8843      [UNDISCH_TAC `norm (x - e % (x - c) - y':real^N) < e * d` THEN
8844       SUBGOAL_THEN `x - e % (x - c) - y':real^N =
8845                     e % (c - (&1 / e % y' - (&1 - e) / e % x))`
8846       SUBST1_TAC THENL
8847        [ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; VECTOR_MUL_ASSOC;
8848                      REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN VECTOR_ARITH_TAC;
8849         ASM_SIMP_TAC[NORM_MUL; REAL_LT_LMUL_EQ; real_abs; REAL_LT_IMP_LE]];
8850       REWRITE_TAC[real_div; REAL_SUB_RDISTRIB] THEN
8851       ASM_SIMP_TAC[REAL_MUL_RINV; REAL_LT_IMP_NZ] THEN
8852       REWRITE_TAC[VECTOR_ARITH `a % y - (b - c) % x:real^N =
8853                                 (c - b) % x + a % y`] THEN
8854       MATCH_MP_TAC(REWRITE_RULE[AFFINE_ALT] AFFINE_AFFINE_HULL) THEN
8855       ASM_SIMP_TAC[HULL_INC]];
8856     DISCH_TAC THEN
8857     SUBGOAL_THEN `y' = (&1 - (&1 - e)) % (&1 / e % y' - (&1 - e) / e % x) +
8858                        (&1 - e) % x:real^N`
8859     SUBST1_TAC THENL
8860      [ASM_SIMP_TAC[REAL_ARITH `&1 - (&1 - e) = e`; VECTOR_SUB_LDISTRIB;
8861                    VECTOR_MUL_ASSOC; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
8862       VECTOR_ARITH_TAC;
8863       FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
8864       ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC]]);;
8865
8866 let IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK = prove
8867  (`!s e x c:real^N.
8868      convex s /\ c IN relative_interior s /\
8869      x IN closure s /\ &0 < e /\ e <= &1
8870      ==> x - e % (x - c) IN relative_interior s`,
8871   REPEAT STRIP_TAC THEN
8872   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR]) THEN
8873   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
8874   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
8875   SUBGOAL_THEN `?y:real^N. y IN s /\ norm(y - x) * (&1 - e) < e * d`
8876   STRIP_ASSUME_TAC THENL
8877    [ASM_CASES_TAC `(x:real^N) IN s` THENL
8878      [EXISTS_TAC `x:real^N` THEN
8879       ASM_SIMP_TAC[REAL_LT_MUL; VECTOR_SUB_REFL; NORM_0; REAL_MUL_LZERO];
8880       ALL_TAC] THEN
8881     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [closure]) THEN
8882     ASM_REWRITE_TAC[IN_UNION; IN_ELIM_THM; LIMPT_APPROACHABLE; dist] THEN
8883     FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
8884      `e <= &1 ==> e = &1 \/ e < &1`)) THEN
8885     ASM_SIMP_TAC[REAL_SUB_REFL; GSYM REAL_LT_RDIV_EQ; REAL_SUB_LT] THENL
8886      [DISCH_THEN(MP_TAC o SPEC `&1`) THEN
8887       REWRITE_TAC[REAL_MUL_RZERO; REAL_LT_01];
8888       DISCH_THEN(MP_TAC o SPEC `(e * d) / (&1 - e)`)] THEN
8889     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_SUB_LT; REAL_MUL_LZERO; REAL_LT_MUL;
8890                  REAL_MUL_LID] THEN
8891     MATCH_MP_TAC MONO_EXISTS THEN MESON_TAC[];
8892     ALL_TAC] THEN
8893   ABBREV_TAC `z:real^N = c + ((&1 - e) / e) % (x - y)` THEN
8894   SUBGOAL_THEN `x - e % (x - c):real^N = y - e % (y - z)` SUBST1_TAC THENL
8895    [EXPAND_TAC "z" THEN
8896     REWRITE_TAC[VECTOR_SUB_LDISTRIB; VECTOR_ADD_LDISTRIB] THEN
8897     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
8898     VECTOR_ARITH_TAC;
8899     ALL_TAC] THEN
8900   MATCH_MP_TAC IN_RELATIVE_INTERIOR_CONVEX_SHRINK THEN ASM_REWRITE_TAC[] THEN
8901   SUBGOAL_THEN `dist(c:real^N,z) < d` ASSUME_TAC THENL
8902    [EXPAND_TAC "z" THEN
8903     REWRITE_TAC[NORM_ARITH `dist(c:real^N,c + x) = norm x`] THEN
8904     REWRITE_TAC[NORM_MUL; REAL_ABS_DIV] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN
8905     REWRITE_TAC[REAL_ARITH `a / b * c:real = (c * a) / b`] THEN
8906     ASM_SIMP_TAC[real_abs; REAL_SUB_LE; REAL_LT_IMP_LE; REAL_LT_LDIV_EQ] THEN
8907     ASM_REAL_ARITH_TAC;
8908     ALL_TAC] THEN
8909   SUBGOAL_THEN `(z:real^N) IN affine hull s` ASSUME_TAC THENL
8910    [EXPAND_TAC "z" THEN MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
8911     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC] THEN
8912     MATCH_MP_TAC(SET_RULE `!t. x IN t /\ t = s ==> x IN s`) THEN
8913     EXISTS_TAC `closure(affine hull s):real^N->bool` THEN
8914     SIMP_TAC[CLOSURE_EQ; CLOSED_AFFINE_HULL] THEN
8915     ASM_MESON_TAC[SUBSET_CLOSURE; HULL_INC; SUBSET];
8916     ALL_TAC] THEN
8917   ASM_REWRITE_TAC[IN_RELATIVE_INTERIOR] THEN CONJ_TAC THENL
8918    [ASM_MESON_TAC[IN_BALL; IN_INTER; SUBSET]; ALL_TAC] THEN
8919   EXISTS_TAC `d - dist(c:real^N,z)` THEN ASM_REWRITE_TAC[REAL_SUB_LT] THEN
8920   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
8921    (REWRITE_RULE[IMP_CONJ_ALT] SUBSET_TRANS)) THEN
8922   REWRITE_TAC[SUBSET; IN_INTER] THEN GEN_TAC THEN
8923   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
8924   UNDISCH_TAC `dist(c:real^N,z) < d` THEN REWRITE_TAC[IN_BALL] THEN
8925   NORM_ARITH_TAC);;
8926
8927 let IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT = prove
8928  (`!s a b:real^N.
8929         convex s /\ a IN relative_interior s /\ b IN closure s
8930         ==> segment(a,b) SUBSET relative_interior s`,
8931   REWRITE_TAC[SUBSET; IN_SEGMENT] THEN REPEAT STRIP_TAC THEN
8932   ASM_REWRITE_TAC[VECTOR_ARITH
8933    `(&1 - u) % a + u % b:real^N = b - (&1 - u) % (b - a)`] THEN
8934   MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
8935   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
8936
8937 let RELATIVE_INTERIOR_SING = prove
8938  (`!a. relative_interior {a} = {a}`,
8939   GEN_TAC THEN MATCH_MP_TAC(SET_RULE
8940    `s SUBSET {a} /\ ~(s = {}) ==> s = {a}`) THEN
8941   SIMP_TAC[RELATIVE_INTERIOR_SUBSET; RELATIVE_INTERIOR_EQ_EMPTY;
8942            CONVEX_SING] THEN
8943   SET_TAC[]);;
8944
8945 let RELATIVE_FRONTIER_SING = prove
8946  (`!a:real^N. relative_frontier {a} = {}`,
8947   REWRITE_TAC[relative_frontier; RELATIVE_INTERIOR_SING; CLOSURE_SING] THEN
8948   SET_TAC[]);;
8949
8950 let RELATIVE_FRONTIER_CBALL = prove
8951  (`!a:real^N r. relative_frontier(cball(a,r)) =
8952                 if r = &0 then {} else sphere(a,r)`,
8953   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
8954   ASM_SIMP_TAC[CBALL_SING; RELATIVE_FRONTIER_SING] THEN
8955   ASM_CASES_TAC `r < &0` THEN
8956   ASM_SIMP_TAC[CBALL_EMPTY; SPHERE_EMPTY; RELATIVE_FRONTIER_EMPTY] THEN
8957   SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
8958   ASM_SIMP_TAC[RELATIVE_FRONTIER_NONEMPTY_INTERIOR; INTERIOR_CBALL;
8959                BALL_EQ_EMPTY; GSYM REAL_NOT_LT; FRONTIER_CBALL]);;
8960
8961 let RELATIVE_FRONTIER_BALL = prove
8962  (`!a:real^N r. relative_frontier(ball(a,r)) =
8963                 if r = &0 then {} else sphere(a,r)`,
8964   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
8965   ASM_SIMP_TAC[BALL_EMPTY; REAL_LE_REFL; RELATIVE_FRONTIER_EMPTY] THEN
8966   ASM_CASES_TAC `r < &0` THEN
8967   ASM_SIMP_TAC[BALL_EMPTY; REAL_LT_IMP_LE; SPHERE_EMPTY;
8968                RELATIVE_FRONTIER_EMPTY] THEN
8969   SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
8970   ASM_SIMP_TAC[RELATIVE_FRONTIER_NONEMPTY_INTERIOR; INTERIOR_OPEN; OPEN_BALL;
8971                BALL_EQ_EMPTY; GSYM REAL_NOT_LT; FRONTIER_BALL]);;
8972
8973 let STARLIKE_CONVEX_TWEAK_BOUNDARY_POINTS = prove
8974  (`!s t:real^N->bool.
8975         convex s /\ ~(s = {}) /\
8976         relative_interior s SUBSET t /\ t SUBSET closure s
8977         ==> starlike t`,
8978   REPEAT STRIP_TAC THEN
8979   SUBGOAL_THEN `~(relative_interior s:real^N->bool = {})` MP_TAC THENL
8980    [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY]; REWRITE_TAC[starlike]] THEN
8981   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN MATCH_MP_TAC MONO_EXISTS THEN
8982   X_GEN_TAC `a:real^N` THEN
8983   REPEAT STRIP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
8984   MATCH_MP_TAC(SET_RULE
8985    `a IN s /\ b IN s /\ segment[a,b] DIFF {a,b} SUBSET s
8986     ==> segment[a:real^N,b] SUBSET s`) THEN
8987   ASM_REWRITE_TAC[GSYM open_segment] THEN
8988   ASM_MESON_TAC[IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT; SUBSET]);;
8989
8990 let RELATIVE_INTERIOR_PROLONG = prove
8991  (`!s x y:real^N.
8992         x IN relative_interior s /\ y IN s
8993         ==> ?t. &1 < t /\ (y + t % (x - y)) IN s`,
8994   REPEAT GEN_TAC THEN
8995   REWRITE_TAC[IN_RELATIVE_INTERIOR_CBALL; IN_ELIM_THM] THEN
8996   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
8997   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `e:real`
8998   STRIP_ASSUME_TAC)) THEN
8999   ASM_CASES_TAC `y:real^N = x` THENL
9000    [ASM_REWRITE_TAC[VECTOR_ARITH `y + t % (x - x):real^N = y`] THEN
9001     EXISTS_TAC `&2` THEN CONV_TAC REAL_RAT_REDUCE_CONV;
9002     EXISTS_TAC `&1 + e / norm(x - y:real^N)` THEN
9003     ASM_SIMP_TAC[REAL_LT_ADDR; REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ] THEN
9004     REWRITE_TAC[VECTOR_ARITH
9005      `y + (&1 + e) % (x - y):real^N = x + e % (x - y)`] THEN
9006     FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET]) THEN
9007     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; IN_INTER; IN_AFFINE_ADD_MUL_DIFF;
9008                  HULL_INC; IN_CBALL] THEN
9009     REWRITE_TAC[NORM_ARITH `dist(x:real^N,x + y) = norm y`] THEN
9010     REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
9011     ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ] THEN
9012     ASM_REAL_ARITH_TAC]);;
9013
9014 let RELATIVE_INTERIOR_CONVEX_PROLONG = prove
9015  (`!s. convex s
9016        ==> relative_interior s =
9017            {x:real^N | x IN s /\
9018                        !y. y IN s ==> ?t. &1 < t /\ (y + t % (x - y)) IN s}`,
9019   REPEAT STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
9020   X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
9021    [SIMP_TAC[RELATIVE_INTERIOR_PROLONG] THEN
9022     MESON_TAC[SUBSET; RELATIVE_INTERIOR_SUBSET];
9023     STRIP_TAC THEN
9024     SUBGOAL_THEN `?y:real^N. y IN relative_interior s` STRIP_ASSUME_TAC THENL
9025      [ASM_SIMP_TAC[MEMBER_NOT_EMPTY; RELATIVE_INTERIOR_EQ_EMPTY] THEN
9026       ASM SET_TAC[];
9027       ALL_TAC] THEN
9028     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ANTS_TAC THENL
9029      [ASM_MESON_TAC[RELATIVE_INTERIOR_SUBSET; SUBSET]; ALL_TAC] THEN
9030     ASM_CASES_TAC `y:real^N = x` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
9031     DISCH_THEN(X_CHOOSE_THEN `t:real` STRIP_ASSUME_TAC) THEN
9032     MP_TAC(ISPECL [`s:real^N->bool`; `y:real^N`; `y + t % (x - y):real^N`]
9033         IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT) THEN
9034     ANTS_TAC THENL [ASM_MESON_TAC[SUBSET; CLOSURE_SUBSET]; ALL_TAC] THEN
9035     REWRITE_TAC[SUBSET] THEN DISCH_THEN MATCH_MP_TAC THEN
9036     REWRITE_TAC[IN_SEGMENT; IN_ELIM_THM] THEN
9037     ASM_REWRITE_TAC[VECTOR_ARITH `y:real^N = y + x <=> x = vec 0`;
9038       VECTOR_ARITH `(&1 - u) % y + u % (y + t % (x - y)):real^N =
9039                     y + t % u % (x - y)`] THEN
9040     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
9041     CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
9042     EXISTS_TAC `inv t:real` THEN
9043     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; REAL_LT_INV_EQ;
9044       REAL_INV_LT_1; REAL_LT_IMP_NZ; REAL_ARITH `&1 < x ==> &0 < x`] THEN
9045     VECTOR_ARITH_TAC]);;
9046
9047 let RELATIVE_INTERIOR_EQ_CLOSURE = prove
9048  (`!s:real^N->bool.
9049         relative_interior s = closure s <=> affine s`,
9050   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9051   ASM_REWRITE_TAC[RELATIVE_INTERIOR_EMPTY; CLOSURE_EMPTY; AFFINE_EMPTY] THEN
9052   EQ_TAC THEN
9053   SIMP_TAC[RELATIVE_INTERIOR_AFFINE; CLOSURE_CLOSED; CLOSED_AFFINE] THEN
9054   DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
9055    `relative_interior s = closure s
9056     ==> relative_interior s SUBSET s /\ s SUBSET closure s
9057         ==> relative_interior s = s /\ closure s = s`)) THEN
9058   REWRITE_TAC[RELATIVE_INTERIOR_SUBSET; CLOSURE_SUBSET] THEN
9059   REWRITE_TAC[RELATIVE_INTERIOR_EQ; CLOSURE_EQ; GSYM AFFINE_HULL_EQ] THEN
9060   STRIP_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
9061    `~(s = {}) ==> s = {} \/ s = a ==> a = s`)) THEN
9062   MP_TAC(ISPEC `affine hull s:real^N->bool` CONNECTED_CLOPEN) THEN
9063   SIMP_TAC[AFFINE_IMP_CONVEX; CONVEX_CONNECTED; AFFINE_AFFINE_HULL] THEN
9064   DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
9065   MATCH_MP_TAC CLOSED_SUBSET THEN ASM_REWRITE_TAC[HULL_SUBSET]);;
9066
9067 let RAY_TO_RELATIVE_FRONTIER = prove
9068  (`!s a l:real^N.
9069         bounded s /\ a IN relative_interior s /\
9070         (a + l) IN affine hull s /\ ~(l = vec 0)
9071         ==> ?d. &0 < d /\
9072                 (a + d % l) IN relative_frontier s /\
9073                 !e. &0 <= e /\ e < d ==> (a + e % l) IN relative_interior s`,
9074   REPEAT STRIP_TAC THEN REWRITE_TAC[relative_frontier] THEN
9075   MP_TAC(ISPEC
9076    `{d | &0 < d /\ ~((a + d % l:real^N) IN relative_interior(s))}` INF) THEN
9077   ABBREV_TAC
9078    `d = inf {d | &0 < d /\ ~((a + d % l:real^N) IN relative_interior(s))}` THEN
9079   SUBGOAL_THEN
9080    `?e. &0 < e /\ !d. &0 <= d /\ d < e
9081                       ==> (a + d % l:real^N) IN relative_interior s`
9082    (X_CHOOSE_THEN `k:real` (LABEL_TAC "0"))
9083   THENL
9084    [MP_TAC(ISPEC `s:real^N->bool` OPEN_IN_RELATIVE_INTERIOR) THEN
9085     REWRITE_TAC[open_in; GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
9086     DISCH_THEN(MP_TAC o SPEC `a:real^N` o CONJUNCT2) THEN
9087     ASM_REWRITE_TAC[] THEN
9088     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
9089     EXISTS_TAC `e / norm(l:real^N)` THEN
9090     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT] THEN X_GEN_TAC `x:real` THEN
9091     STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
9092      [MATCH_MP_TAC IN_AFFINE_ADD_MUL THEN
9093       ASM_REWRITE_TAC[AFFINE_AFFINE_HULL] THEN
9094       ASM_MESON_TAC[SUBSET; HULL_SUBSET; RELATIVE_INTERIOR_SUBSET];
9095       REWRITE_TAC[NORM_ARITH `dist(a + x:real^N,a) = norm x`] THEN
9096       ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LT_RDIV_EQ; NORM_POS_LT] THEN
9097       ASM_REAL_ARITH_TAC];
9098     ALL_TAC] THEN
9099   ANTS_TAC THENL
9100    [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
9101     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[REAL_NOT_LT; REAL_LT_IMP_LE]] THEN
9102     FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N` o
9103        MATCH_MP BOUNDED_SUBSET_BALL) THEN
9104     REWRITE_TAC[SUBSET; IN_BALL] THEN
9105     DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
9106     EXISTS_TAC `B / norm(l:real^N)` THEN
9107     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT] THEN
9108     DISCH_THEN(MP_TAC o MATCH_MP
9109      (REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET)) THEN
9110     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE BINDER_CONV
9111      [GSYM CONTRAPOS_THM]) THEN
9112     REWRITE_TAC[REAL_NOT_LT] THEN DISCH_THEN MATCH_MP_TAC THEN
9113     REWRITE_TAC[NORM_ARITH `dist(a:real^N,a + x) = norm x`] THEN
9114     ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM;
9115                  REAL_DIV_RMUL; NORM_EQ_0] THEN
9116     ASM_REAL_ARITH_TAC;
9117     REWRITE_TAC[IN_ELIM_THM] THEN
9118     DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "1") (LABEL_TAC "2")) THEN
9119     EXISTS_TAC `d:real` THEN
9120     MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
9121      [MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `k:real` THEN
9122       ASM_MESON_TAC[REAL_NOT_LT; REAL_LT_IMP_LE];
9123       DISCH_TAC] THEN
9124     MATCH_MP_TAC(TAUT `b /\ (b ==> a) ==> a /\ b`) THEN CONJ_TAC THENL
9125      [REWRITE_TAC[REAL_LE_LT] THEN
9126       ASM_MESON_TAC[VECTOR_ARITH `a + &0 % l:real^N = a`;
9127                     REAL_NOT_LT; REAL_LT_IMP_LE];
9128       DISCH_TAC] THEN
9129     REWRITE_TAC[IN_DIFF] THEN CONJ_TAC THENL
9130      [REWRITE_TAC[CLOSURE_APPROACHABLE] THEN
9131       X_GEN_TAC `x:real` THEN DISCH_TAC THEN
9132       EXISTS_TAC `a + (d - min d (x / &2 / norm(l:real^N))) % l` THEN
9133       CONJ_TAC THENL
9134        [MATCH_MP_TAC(REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET) THEN
9135         FIRST_X_ASSUM MATCH_MP_TAC THEN
9136         CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
9137         MATCH_MP_TAC(REAL_ARITH `&0 < x /\ &0 < d ==> d - min d x < d`) THEN
9138         ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT];
9139         REWRITE_TAC[NORM_ARITH `dist(a + x:real^N,a + y) = norm(x - y)`] THEN
9140         REWRITE_TAC[GSYM VECTOR_SUB_RDISTRIB; NORM_MUL] THEN
9141         ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT] THEN
9142         MATCH_MP_TAC(REAL_ARITH
9143          `&0 < x /\ x < y /\ &0 < d ==> abs((d - min d x) - d) < y`) THEN
9144         REWRITE_TAC[REAL_ARITH `x / &2 / y < x / y <=> &0 < x / y`] THEN
9145         ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT]];
9146       DISCH_TAC THEN
9147       MP_TAC(ISPEC `s:real^N->bool` OPEN_IN_RELATIVE_INTERIOR) THEN
9148       REWRITE_TAC[open_in; GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
9149       DISCH_THEN(MP_TAC o SPEC `a + d % l:real^N` o CONJUNCT2) THEN
9150       ASM_REWRITE_TAC[] THEN
9151       DISCH_THEN(X_CHOOSE_THEN `e:real`
9152        (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "3"))) THEN
9153       REMOVE_THEN "2" (MP_TAC o SPEC `d + e / norm(l:real^N)`) THEN
9154       ASM_SIMP_TAC[NOT_IMP; REAL_ARITH `~(d + l <= d) <=> &0 < l`;
9155                    REAL_LT_DIV; NORM_POS_LT] THEN
9156       X_GEN_TAC `x:real` THEN
9157       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9158       ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
9159       REWRITE_TAC[REAL_NOT_LE] THEN DISCH_TAC THEN
9160       ASM_CASES_TAC `x < d` THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN
9161       REMOVE_THEN "3" MATCH_MP_TAC THEN CONJ_TAC THENL
9162        [MATCH_MP_TAC IN_AFFINE_ADD_MUL THEN
9163         ASM_REWRITE_TAC[AFFINE_AFFINE_HULL] THEN
9164         ASM_MESON_TAC[SUBSET; HULL_SUBSET; RELATIVE_INTERIOR_SUBSET];
9165         REWRITE_TAC[NORM_ARITH `dist(a + x:real^N,a + y) = norm(x - y)`] THEN
9166         REWRITE_TAC[GSYM VECTOR_SUB_RDISTRIB; NORM_MUL] THEN
9167         ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT] THEN
9168         ASM_REAL_ARITH_TAC]]]);;
9169
9170 let RAY_TO_FRONTIER = prove
9171  (`!s a l:real^N.
9172         bounded s /\ a IN interior s /\ ~(l = vec 0)
9173         ==> ?d. &0 < d /\ (a + d % l) IN frontier s /\
9174                 !e. &0 <= e /\ e < d ==> (a + e % l) IN interior s`,
9175   REPEAT STRIP_TAC THEN REWRITE_TAC[frontier] THEN
9176   SUBGOAL_THEN `interior s:real^N->bool = relative_interior s` SUBST1_TAC THENL
9177    [ALL_TAC;
9178     REWRITE_TAC[GSYM relative_frontier] THEN
9179     MATCH_MP_TAC RAY_TO_RELATIVE_FRONTIER THEN ASM_REWRITE_TAC[]] THEN
9180   ASM_MESON_TAC[NOT_IN_EMPTY; RELATIVE_INTERIOR_NONEMPTY_INTERIOR; IN_UNIV;
9181                 AFFINE_HULL_NONEMPTY_INTERIOR]);;
9182
9183 let RELATIVE_FRONTIER_NOT_SING = prove
9184  (`!s a:real^N. bounded s ==> ~(relative_frontier s = {a})`,
9185   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9186   ASM_REWRITE_TAC[RELATIVE_FRONTIER_EMPTY; NOT_INSERT_EMPTY] THEN
9187   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9188   DISCH_THEN(X_CHOOSE_TAC `z:real^N`) THEN
9189   ASM_CASES_TAC `s = {z:real^N}` THEN
9190   ASM_REWRITE_TAC[RELATIVE_FRONTIER_SING; NOT_INSERT_EMPTY] THEN
9191   SUBGOAL_THEN `?w:real^N. w IN s /\ ~(w = z)` STRIP_ASSUME_TAC THENL
9192    [ASM SET_TAC[]; REPEAT STRIP_TAC] THEN
9193   SUBGOAL_THEN
9194     `~((w:real^N) IN relative_frontier s /\ z IN relative_frontier s)`
9195   MP_TAC THENL [ASM SET_TAC[]; DISCH_TAC] THEN
9196   MAP_EVERY UNDISCH_TAC
9197    [`relative_frontier s = {a:real^N}`; `bounded(s:real^N->bool)`;
9198     `~(w:real^N = z)`; `(z:real^N) IN s`; `(w:real^N) IN s`;
9199     `~((w:real^N) IN relative_frontier s /\ z IN relative_frontier s)`] THEN
9200   POP_ASSUM_LIST(K ALL_TAC) THEN REWRITE_TAC[DE_MORGAN_THM] THEN
9201   MAP_EVERY (fun t -> SPEC_TAC(t,t)) [`z:real^N`; `w:real^N`] THEN
9202   MATCH_MP_TAC(MESON[]
9203    `(!w z. Q w z <=> Q z w) /\ (!w z. P z ==> Q w z)
9204     ==> !w z. P w \/ P z ==> Q w z`) THEN
9205   CONJ_TAC THENL [MESON_TAC[]; REPEAT GEN_TAC] THEN
9206   DISCH_THEN(fun th -> REPEAT STRIP_TAC THEN MP_TAC th) THEN
9207   REWRITE_TAC[relative_frontier; IN_DIFF] THEN
9208   CONJ_TAC THENL [ASM_MESON_TAC[SUBSET; CLOSURE_SUBSET]; DISCH_TAC] THEN
9209   MP_TAC(GEN `d:real`
9210    (ISPECL [`s:real^N->bool`; `z:real^N`; `d % (w - z):real^N`]
9211    RAY_TO_RELATIVE_FRONTIER)) THEN
9212   ASM_SIMP_TAC[VECTOR_SUB_EQ; IN_AFFINE_ADD_MUL_DIFF; AFFINE_AFFINE_HULL;
9213                HULL_INC; VECTOR_MUL_EQ_0] THEN
9214   DISCH_THEN(fun th -> MP_TAC(SPEC `&1` th) THEN MP_TAC(SPEC `--(&1)` th)) THEN
9215   CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[IN_SING] THEN
9216   DISCH_THEN(X_CHOOSE_THEN `e:real` (STRIP_ASSUME_TAC o GSYM)) THEN
9217   ASM_REWRITE_TAC[VECTOR_MUL_RCANCEL; VECTOR_MUL_ASSOC; VECTOR_SUB_EQ;
9218                   VECTOR_ARITH `a + x:real^N = a + y <=> x = y`] THEN
9219   ASM_REAL_ARITH_TAC);;
9220
9221 let RELATIVE_INTERIOR_PCROSS = prove
9222  (`!s:real^M->bool t:real^N->bool.
9223         relative_interior(s PCROSS t) =
9224         relative_interior s PCROSS relative_interior t`,
9225   REPEAT STRIP_TAC THEN MAP_EVERY ASM_CASES_TAC
9226    [`s:real^M->bool = {}`; `t:real^N->bool = {}`] THEN
9227   ASM_REWRITE_TAC[PCROSS_EMPTY; RELATIVE_INTERIOR_EMPTY] THEN
9228   REWRITE_TAC[relative_interior; AFFINE_HULL_PCROSS] THEN
9229   REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_THM;
9230               PASTECART_IN_PCROSS] THEN
9231   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^N`] THEN EQ_TAC THENL
9232    [ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> r /\ q /\ p`] THEN
9233     DISCH_THEN(X_CHOOSE_THEN `u:real^(M,N)finite_sum->bool`
9234      (CONJUNCTS_THEN ASSUME_TAC)) THEN
9235     FIRST_ASSUM(MP_TAC o MATCH_MP PASTECART_IN_INTERIOR_SUBTOPOLOGY) THEN
9236     REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN
9237     REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
9238     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
9239     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
9240     W(MP_TAC o PART_MATCH (funpow 3 rand) SUBSET_PCROSS o snd) THEN
9241     ASM SET_TAC[];
9242     DISCH_THEN(CONJUNCTS_THEN2
9243      (X_CHOOSE_THEN `v:real^M->bool` STRIP_ASSUME_TAC)
9244      (X_CHOOSE_THEN `w:real^N->bool` STRIP_ASSUME_TAC)) THEN
9245     EXISTS_TAC `(v:real^M->bool) PCROSS (w:real^N->bool)` THEN
9246     ASM_SIMP_TAC[PASTECART_IN_PCROSS; SUBSET_PCROSS; OPEN_IN_PCROSS]]);;
9247
9248 let RELATIVE_FRONTIER_EQ_EMPTY = prove
9249  (`!s:real^N->bool. relative_frontier s = {} <=> affine s`,
9250   GEN_TAC THEN REWRITE_TAC[relative_frontier] THEN
9251   REWRITE_TAC[GSYM RELATIVE_INTERIOR_EQ_CLOSURE] THEN
9252   MP_TAC(ISPEC `s:real^N->bool` RELATIVE_INTERIOR_SUBSET) THEN
9253   MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[]);;
9254
9255 let DIAMETER_BOUNDED_BOUND_LT = prove
9256  (`!s x y:real^N.
9257         bounded s /\ x IN relative_interior s /\ y IN closure s /\
9258         ~(diameter s = &0)
9259         ==> norm(x - y) < diameter s`,
9260   let lemma = prove
9261    (`!s x y:real^N.
9262           bounded s /\ x IN relative_interior s /\ y IN s /\
9263           ~(diameter s = &0)
9264           ==> norm(x - y) < diameter s`,
9265     REPEAT STRIP_TAC THEN FIRST_X_ASSUM
9266      (MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR_CBALL]) THEN
9267     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `e:real`
9268      STRIP_ASSUME_TAC)) THEN
9269     ASM_SIMP_TAC[REAL_LT_LE; DIAMETER_BOUNDED_BOUND] THEN
9270     ASM_CASES_TAC `y:real^N = x` THEN
9271     ASM_SIMP_TAC[VECTOR_SUB_REFL; NORM_0] THEN
9272     DISCH_TAC THEN
9273     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
9274     DISCH_THEN(MP_TAC o SPEC `x + e / norm(x - y) % (x - y):real^N`) THEN
9275     REWRITE_TAC[NOT_IMP; IN_INTER] THEN REPEAT CONJ_TAC THENL
9276      [REWRITE_TAC[IN_CBALL; NORM_ARITH `dist(x:real^M,x + y) = norm y`] THEN
9277       ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL;
9278                    NORM_EQ_0; VECTOR_SUB_EQ] THEN ASM_REAL_ARITH_TAC;
9279       MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
9280       ASM_SIMP_TAC[HULL_INC; AFFINE_AFFINE_HULL];
9281       DISCH_TAC THEN MP_TAC(ISPECL
9282        [`s:real^N->bool`; `x + e / norm(x - y) % (x - y):real^N`; `y:real^N`]
9283           DIAMETER_BOUNDED_BOUND) THEN
9284       ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
9285       REWRITE_TAC[VECTOR_ARITH
9286        `(x + e % (x - y)) - y:real^N = (&1 + e) % (x - y)`] THEN
9287       SIMP_TAC[NORM_MUL; REAL_ARITH `~(a * n <= n) <=> &0 < n * (a - &1)`] THEN
9288       MATCH_MP_TAC REAL_LT_MUL THEN
9289       ASM_REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
9290       MATCH_MP_TAC(REAL_ARITH `&0 < e ==> &0 < abs(&1 + e) - &1`) THEN
9291       MATCH_MP_TAC REAL_LT_DIV THEN
9292       ASM_REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ]]) in
9293   REPEAT STRIP_TAC THEN
9294   MP_TAC(ISPECL [`closure s:real^N->bool`; `x:real^N`; `y:real^N`]
9295         lemma) THEN
9296   ASM_SIMP_TAC[DIAMETER_CLOSURE; BOUNDED_CLOSURE] THEN
9297   DISCH_THEN MATCH_MP_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
9298    (SET_RULE `x IN s ==> s SUBSET t ==> x IN t`)) THEN
9299   MATCH_MP_TAC SUBSET_RELATIVE_INTERIOR THEN
9300   REWRITE_TAC[CLOSURE_SUBSET; AFFINE_HULL_CLOSURE]);;
9301
9302 let DIAMETER_ATTAINED_RELATIVE_FRONTIER = prove
9303  (`!s:real^N->bool.
9304         bounded s /\ ~(diameter s = &0)
9305         ==> ?x y. x IN relative_frontier s /\
9306                   y IN relative_frontier s /\
9307                   norm(x - y) = diameter s`,
9308   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9309   ASM_REWRITE_TAC[DIAMETER_EMPTY; relative_frontier] THEN REPEAT STRIP_TAC THEN
9310   MP_TAC(ISPEC `closure s:real^N->bool` DIAMETER_COMPACT_ATTAINED) THEN
9311   ASM_SIMP_TAC[COMPACT_CLOSURE; CLOSURE_EQ_EMPTY; DIAMETER_CLOSURE] THEN
9312   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
9313   STRIP_TAC THEN ASM_REWRITE_TAC[IN_DIFF] THEN REPEAT STRIP_TAC THEN
9314   MP_TAC(ISPEC `s:real^N->bool` DIAMETER_BOUNDED_BOUND_LT) THENL
9315    [DISCH_THEN(MP_TAC o SPECL [`x:real^N`; `y:real^N`]);
9316     DISCH_THEN(MP_TAC o SPECL [`y:real^N`; `x:real^N`])] THEN
9317   ASM_MESON_TAC[REAL_LT_REFL; NORM_SUB]);;
9318
9319 let DIAMETER_RELATIVE_FRONTIER = prove
9320  (`!s:real^N->bool.
9321         bounded s /\ ~(?a. s = {a})
9322         ==> diameter(relative_frontier s) = diameter s`,
9323   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9324   ASM_REWRITE_TAC[RELATIVE_FRONTIER_EMPTY] THEN
9325   REWRITE_TAC[relative_frontier] THEN
9326   ASM_SIMP_TAC[GSYM DIAMETER_CLOSURE; GSYM REAL_LE_ANTISYM] THEN
9327   ASM_SIMP_TAC[SUBSET_DIFF; DIAMETER_SUBSET; BOUNDED_CLOSURE] THEN
9328   ASM_SIMP_TAC[DIAMETER_CLOSURE] THEN
9329   MP_TAC(ISPEC `s:real^N->bool` DIAMETER_ATTAINED_RELATIVE_FRONTIER) THEN
9330   ASM_SIMP_TAC[DIAMETER_EQ_0; relative_frontier] THEN STRIP_TAC THEN
9331   FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN MATCH_MP_TAC DIAMETER_BOUNDED_BOUND THEN
9332   ASM_SIMP_TAC[BOUNDED_CLOSURE; BOUNDED_DIFF]);;
9333
9334 let DIAMETER_ATTAINED_FRONTIER = prove
9335  (`!s:real^N->bool.
9336         bounded s /\ ~(diameter s = &0)
9337         ==> ?x y. x IN frontier s /\ y IN frontier s /\
9338                   norm(x - y) = diameter s`,
9339   REPEAT GEN_TAC THEN
9340   DISCH_THEN(MP_TAC o MATCH_MP DIAMETER_ATTAINED_RELATIVE_FRONTIER) THEN
9341   REWRITE_TAC[frontier; relative_frontier; IN_DIFF] THEN
9342   MESON_TAC[REWRITE_RULE[SUBSET] INTERIOR_SUBSET_RELATIVE_INTERIOR]);;
9343
9344 let DIAMETER_FRONTIER = prove
9345  (`!s:real^N->bool. bounded s ==> diameter(frontier s) = diameter s`,
9346   REPEAT STRIP_TAC THEN ASM_CASES_TAC `?a:real^N. s = {a}` THENL
9347    [ASM_MESON_TAC[FRONTIER_SING]; ALL_TAC] THEN
9348   MATCH_MP_TAC(REAL_ARITH
9349    `!r. r <= f /\ f <= s /\ r = s ==> f = s`) THEN
9350   EXISTS_TAC `diameter(closure s DIFF relative_interior s:real^N->bool)` THEN
9351   REPEAT CONJ_TAC THENL
9352    [ASM_SIMP_TAC[GSYM DIAMETER_CLOSURE] THEN MATCH_MP_TAC DIAMETER_SUBSET THEN
9353     ASM_SIMP_TAC[BOUNDED_FRONTIER] THEN REWRITE_TAC[frontier] THEN
9354     MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET_RELATIVE_INTERIOR) THEN
9355     SET_TAC[];
9356     ASM_SIMP_TAC[GSYM DIAMETER_CLOSURE] THEN MATCH_MP_TAC DIAMETER_SUBSET THEN
9357     ASM_SIMP_TAC[BOUNDED_CLOSURE; frontier; SUBSET_DIFF];
9358     ASM_SIMP_TAC[DIAMETER_RELATIVE_FRONTIER; GSYM relative_frontier]]);;
9359
9360 let DIAMETER_SPHERE = prove
9361  (`!a:real^N r. diameter(sphere(a,r)) = if r < &0 then &0 else &2 * r`,
9362   REWRITE_TAC[GSYM FRONTIER_CBALL] THEN
9363   ASM_SIMP_TAC[DIAMETER_FRONTIER; BOUNDED_CBALL; DIAMETER_CBALL]);;
9364
9365 let CLOSEST_POINT_IN_RELATIVE_INTERIOR = prove
9366  (`!s x:real^N.
9367         closed s /\ ~(s = {}) /\ x IN affine hull s
9368         ==> ((closest_point s x) IN relative_interior s <=>
9369              x IN relative_interior s)`,
9370   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THEN
9371   ASM_SIMP_TAC[CLOSEST_POINT_SELF] THEN
9372   MATCH_MP_TAC(TAUT `~q /\ ~p ==> (p <=> q)`) THEN CONJ_TAC THENL
9373    [ASM_MESON_TAC[RELATIVE_INTERIOR_SUBSET; SUBSET]; STRIP_TAC] THEN
9374   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR_CBALL]) THEN
9375   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9376   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
9377   SUBGOAL_THEN `~(closest_point s (x:real^N) = x)` ASSUME_TAC THENL
9378    [ASM_MESON_TAC[]; ALL_TAC] THEN
9379   MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`;
9380    `closest_point s x -
9381     (min (&1) (e / norm(closest_point s x - x))) %
9382     (closest_point s x - x):real^N`]
9383     CLOSEST_POINT_LE) THEN
9384   ASM_REWRITE_TAC[dist; NOT_IMP; VECTOR_ARITH
9385    `x - (y - e % (y - x)):real^N = (&1 - e) % (x - y)`] THEN
9386   CONJ_TAC THENL
9387    [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
9388     REWRITE_TAC[IN_CBALL; IN_INTER] THEN CONJ_TAC THENL
9389      [REWRITE_TAC[NORM_ARITH `dist(a:real^N,a - x) = norm x`] THEN
9390       REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
9391       ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
9392       MATCH_MP_TAC(REAL_ARITH `&0 <= a ==> abs(min (&1) a) <= a`) THEN
9393       ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LE_DIV; NORM_POS_LE];
9394       MATCH_MP_TAC IN_AFFINE_SUB_MUL_DIFF THEN
9395       ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC]];
9396     REWRITE_TAC[NORM_MUL; REAL_ARITH
9397      `~(n <= a * n) <=> &0 < (&1 - a) * n`] THEN
9398     MATCH_MP_TAC REAL_LT_MUL THEN
9399     ASM_SIMP_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
9400     MATCH_MP_TAC(REAL_ARITH
9401      `&0 < e /\ e <= &1 ==> &0 < &1 - abs(&1 - e)`) THEN
9402     REWRITE_TAC[REAL_MIN_LE; REAL_LT_MIN; REAL_LT_01; REAL_LE_REFL] THEN
9403     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ]]);;
9404
9405 let CLOSEST_POINT_IN_RELATIVE_FRONTIER = prove
9406  (`!s x:real^N.
9407         closed s /\ ~(s = {}) /\ x IN affine hull s DIFF relative_interior s
9408         ==> closest_point s x IN relative_frontier s`,
9409   SIMP_TAC[relative_frontier; IN_DIFF; CLOSEST_POINT_IN_RELATIVE_INTERIOR] THEN
9410   MESON_TAC[CLOSURE_SUBSET; CLOSEST_POINT_IN_SET; SUBSET]);;
9411
9412 (* ------------------------------------------------------------------------- *)
9413 (* Interior, relative interior and closure interrelations.                   *)
9414 (* ------------------------------------------------------------------------- *)
9415
9416 let CONVEX_CLOSURE_INTERIOR = prove
9417  (`!s:real^N->bool.
9418         convex s /\ ~(interior s = {})
9419         ==> closure(interior s) = closure s`,
9420   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9421   SIMP_TAC[SUBSET_CLOSURE; INTERIOR_SUBSET] THEN
9422   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9423   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN REWRITE_TAC[SUBSET] THEN
9424   X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN ASM_CASES_TAC `b:real^N = a` THENL
9425    [ASM_MESON_TAC[CLOSURE_SUBSET; SUBSET]; ALL_TAC] THEN
9426   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM] THEN DISJ2_TAC THEN
9427   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
9428   EXISTS_TAC `b - min (e / &2 / norm(b - a)) (&1) % (b - a):real^N` THEN
9429   REPEAT CONJ_TAC THENL
9430    [MATCH_MP_TAC IN_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
9431     ASM_REWRITE_TAC[REAL_MIN_LE; REAL_LT_MIN; REAL_LE_REFL; REAL_LT_01];
9432     REWRITE_TAC[VECTOR_ARITH `b - x:real^N = b <=> x = vec 0`] THEN
9433     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
9434     MATCH_MP_TAC(REAL_ARITH `&0 < x ==> ~(min x (&1) = &0)`);
9435     REWRITE_TAC[NORM_ARITH `dist(b - x:real^N,b) = norm x`] THEN
9436     REWRITE_TAC[NORM_MUL] THEN MATCH_MP_TAC REAL_LET_TRANS THEN
9437     EXISTS_TAC `e / &2 / norm(b - a:real^N) * norm(b - a)` THEN CONJ_TAC THENL
9438      [MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[NORM_POS_LE] THEN
9439       MATCH_MP_TAC(REAL_ARITH `&0 < x ==> abs(min x (&1)) <= x`);
9440       ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_POS_LT; REAL_LT_IMP_NZ;
9441                    VECTOR_SUB_EQ] THEN
9442       ASM_REAL_ARITH_TAC]] THEN
9443   ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; REAL_OF_NUM_LT;
9444                  VECTOR_SUB_EQ; ARITH]);;
9445
9446 let EMPTY_INTERIOR_SUBSET_HYPERPLANE = prove
9447  (`!s. convex s /\ interior s = {}
9448        ==> ?a:real^N b. ~(a = vec 0) /\ s SUBSET {x | a dot x = b}`,
9449   let lemma = prove
9450    (`!s. convex s /\ (vec 0) IN s /\ interior s = {}
9451          ==> ?a:real^N b. ~(a = vec 0) /\ s SUBSET {x | a dot x = b}`,
9452     GEN_TAC THEN
9453     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
9454     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
9455     SUBGOAL_THEN `~(relative_interior(s:real^N->bool) = {})` MP_TAC THENL
9456      [ASM_MESON_TAC[RELATIVE_INTERIOR_EQ_EMPTY; MEMBER_NOT_EMPTY]; ALL_TAC] THEN
9457     ASM_REWRITE_TAC[CONTRAPOS_THM] THEN MATCH_MP_TAC EQ_IMP THEN
9458     AP_THM_TAC THEN AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN
9459     MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
9460     ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC] THEN
9461     ONCE_REWRITE_TAC[GSYM SPAN_UNIV] THEN MATCH_MP_TAC DIM_EQ_SPAN THEN
9462     REWRITE_TAC[SUBSET_UNIV; DIM_UNIV; GSYM NOT_LT] THEN
9463     DISCH_THEN(MP_TAC o MATCH_MP LOWDIM_SUBSET_HYPERPLANE) THEN
9464     DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
9465     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
9466     DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN
9467     ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN EXISTS_TAC `&0` THEN
9468     ASM_MESON_TAC[SUBSET_TRANS; SPAN_INC]) in
9469   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
9470    [ASM_MESON_TAC[EMPTY_SUBSET; BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1];
9471     ALL_TAC] THEN
9472   STRIP_TAC THEN
9473   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9474   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
9475   MP_TAC(ISPEC `IMAGE (\x:real^N. --a + x) s` lemma) THEN
9476   ASM_REWRITE_TAC[CONVEX_TRANSLATION_EQ; INTERIOR_TRANSLATION;
9477                   IMAGE_EQ_EMPTY; IN_IMAGE; UNWIND_THM2;
9478                   VECTOR_ARITH `vec 0:real^N = --a + x <=> x = a`] THEN
9479   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `c:real^N` THEN
9480   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM; DOT_RADD] THEN
9481   MESON_TAC[REAL_ARITH `a + x:real = b <=> x = b - a`]);;
9482
9483 let CONVEX_INTERIOR_CLOSURE = prove
9484  (`!s:real^N->bool. convex s ==> interior(closure s) = interior s`,
9485   REPEAT STRIP_TAC THEN
9486   ASM_CASES_TAC `interior(s:real^N->bool) = {}` THENL
9487    [MP_TAC(ISPEC `s:real^N->bool` EMPTY_INTERIOR_SUBSET_HYPERPLANE) THEN
9488     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
9489     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN STRIP_TAC THEN
9490     MATCH_MP_TAC(SET_RULE `!t. s SUBSET t /\ t = {} ==> s = {}`) THEN
9491     EXISTS_TAC `interior {x:real^N | a dot x = b}` THEN CONJ_TAC THENL
9492      [ALL_TAC;  ASM_SIMP_TAC[INTERIOR_HYPERPLANE]] THEN
9493     MATCH_MP_TAC SUBSET_INTERIOR THEN MATCH_MP_TAC CLOSURE_MINIMAL THEN
9494     ASM_REWRITE_TAC[CLOSED_HYPERPLANE];
9495     ALL_TAC] THEN
9496   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9497   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
9498   MATCH_MP_TAC SUBSET_ANTISYM THEN
9499   SIMP_TAC[SUBSET_INTERIOR; CLOSURE_SUBSET] THEN
9500   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN
9501   MP_TAC(ASSUME `(b:real^N) IN interior(closure s)`) THEN
9502   GEN_REWRITE_TAC LAND_CONV [IN_INTERIOR_CBALL] THEN
9503   REWRITE_TAC[SUBSET; IN_CBALL; LEFT_IMP_EXISTS_THM] THEN
9504   X_GEN_TAC `e:real` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9505   ASM_CASES_TAC `b:real^N = a` THEN ASM_REWRITE_TAC[] THEN
9506   DISCH_THEN(MP_TAC o SPEC `b + e / norm(b - a) % (b - a):real^N`) THEN
9507   ASM_SIMP_TAC[NORM_ARITH `dist(b:real^N,b + e) = norm e`; NORM_MUL;
9508     REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ;
9509     REAL_ARITH `&0 < e ==> abs e <= e`] THEN
9510   DISCH_TAC THEN
9511   SUBGOAL_THEN
9512    `b = (b + e / norm(b - a) % (b - a)) -
9513         e / norm(b - a) / (&1 + e / norm(b - a)) %
9514         ((b + e / norm(b - a) % (b - a)) - a):real^N`
9515   SUBST1_TAC THENL
9516    [REWRITE_TAC[VECTOR_ARITH
9517      `b = (b + e % (b - a)) - d % ((b + e % (b - a)) - a) <=>
9518       (e - d * (&1 + e)) % (b - a) = vec 0`] THEN
9519     ASM_REWRITE_TAC[VECTOR_SUB_EQ; VECTOR_MUL_EQ_0];
9520     MATCH_MP_TAC IN_INTERIOR_CLOSURE_CONVEX_SHRINK] THEN
9521   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LT_DIV; NORM_POS_LT;
9522                VECTOR_SUB_EQ; REAL_ARITH `&0 < x ==> &0 < &1 + x`;
9523                REAL_ARITH `&0 < x ==> ~(&1 + x = &0)`;
9524                REAL_MUL_LID; REAL_ADD_RDISTRIB; REAL_DIV_RMUL;
9525                REAL_LT_IMP_NZ; REAL_LE_ADDL; NORM_POS_LE; REAL_SUB_REFL]);;
9526
9527 let FRONTIER_CLOSURE_CONVEX = prove
9528  (`!s:real^N->bool. convex s ==> frontier(closure s) = frontier s`,
9529   SIMP_TAC[frontier; CLOSURE_CLOSURE; CONVEX_INTERIOR_CLOSURE]);;
9530
9531 let CONVEX_CLOSURE_RELATIVE_INTERIOR = prove
9532  (`!s:real^N->bool.
9533         convex s ==> closure(relative_interior s) = closure s`,
9534   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9535   SIMP_TAC[SUBSET_CLOSURE; RELATIVE_INTERIOR_SUBSET] THEN
9536   ASM_CASES_TAC `relative_interior(s:real^N->bool) = {}` THENL
9537    [ASM_MESON_TAC[RELATIVE_INTERIOR_EQ_EMPTY; SUBSET_REFL]; ALL_TAC] THEN
9538   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9539   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN REWRITE_TAC[SUBSET] THEN
9540   X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN ASM_CASES_TAC `b:real^N = a` THENL
9541    [ASM_MESON_TAC[CLOSURE_SUBSET; SUBSET]; ALL_TAC] THEN
9542   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM] THEN DISJ2_TAC THEN
9543   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
9544   EXISTS_TAC `b - min (e / &2 / norm(b - a)) (&1) % (b - a):real^N` THEN
9545   REPEAT CONJ_TAC THENL
9546    [MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
9547     ASM_REWRITE_TAC[REAL_MIN_LE; REAL_LT_MIN; REAL_LE_REFL; REAL_LT_01];
9548     REWRITE_TAC[VECTOR_ARITH `b - x:real^N = b <=> x = vec 0`] THEN
9549     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
9550     MATCH_MP_TAC(REAL_ARITH `&0 < x ==> ~(min x (&1) = &0)`);
9551     REWRITE_TAC[NORM_ARITH `dist(b - x:real^N,b) = norm x`] THEN
9552     REWRITE_TAC[NORM_MUL] THEN MATCH_MP_TAC REAL_LET_TRANS THEN
9553     EXISTS_TAC `e / &2 / norm(b - a:real^N) * norm(b - a)` THEN CONJ_TAC THENL
9554      [MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[NORM_POS_LE] THEN
9555       MATCH_MP_TAC(REAL_ARITH `&0 < x ==> abs(min x (&1)) <= x`);
9556       ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_POS_LT; REAL_LT_IMP_NZ;
9557                    VECTOR_SUB_EQ] THEN
9558       ASM_REAL_ARITH_TAC]] THEN
9559   ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; REAL_OF_NUM_LT;
9560                  VECTOR_SUB_EQ; ARITH]);;
9561
9562 let AFFINE_HULL_RELATIVE_INTERIOR = prove
9563  (`!s. convex s
9564        ==> affine hull (relative_interior s) = affine hull s`,
9565   MESON_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR; AFFINE_HULL_CLOSURE]);;
9566
9567 let CONVEX_RELATIVE_INTERIOR_CLOSURE = prove
9568  (`!s:real^N->bool.
9569         convex s ==> relative_interior(closure s) = relative_interior s`,
9570   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9571   ASM_REWRITE_TAC[CLOSURE_EMPTY; RELATIVE_INTERIOR_EMPTY] THEN
9572   SUBGOAL_THEN `?a:real^N. a IN relative_interior s` STRIP_ASSUME_TAC THENL
9573    [ASM_SIMP_TAC[MEMBER_NOT_EMPTY; RELATIVE_INTERIOR_EQ_EMPTY];
9574     ALL_TAC] THEN
9575   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET] THEN CONJ_TAC THENL
9576    [ALL_TAC;
9577     REWRITE_TAC[IN_RELATIVE_INTERIOR; AFFINE_HULL_CLOSURE; SUBSET] THEN
9578     MESON_TAC[CLOSURE_SUBSET; SUBSET]] THEN
9579   X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN
9580   MP_TAC(ASSUME `(b:real^N) IN relative_interior(closure s)`) THEN
9581   GEN_REWRITE_TAC LAND_CONV [IN_RELATIVE_INTERIOR_CBALL] THEN
9582   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9583   REWRITE_TAC[SUBSET; IN_CBALL; IN_INTER; LEFT_IMP_EXISTS_THM;
9584               AFFINE_HULL_CLOSURE] THEN
9585   X_GEN_TAC `e:real` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9586   ASM_CASES_TAC `b:real^N = a` THEN ASM_REWRITE_TAC[] THEN
9587   DISCH_THEN(MP_TAC o SPEC `b + e / norm(b - a) % (b - a):real^N`) THEN
9588   ASM_SIMP_TAC[NORM_ARITH `dist(b:real^N,b + e) = norm e`; NORM_MUL;
9589     REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ;
9590     REAL_ARITH `&0 < e ==> abs e <= e`] THEN
9591   ANTS_TAC THENL
9592    [MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
9593     ASM_MESON_TAC[SUBSET; AFFINE_AFFINE_HULL; RELATIVE_INTERIOR_SUBSET;
9594                   CLOSURE_SUBSET_AFFINE_HULL; HULL_INC];
9595     ALL_TAC] THEN
9596   DISCH_TAC THEN
9597   SUBGOAL_THEN
9598    `b = (b + e / norm(b - a) % (b - a)) -
9599         e / norm(b - a) / (&1 + e / norm(b - a)) %
9600         ((b + e / norm(b - a) % (b - a)) - a):real^N`
9601   SUBST1_TAC THENL
9602    [REWRITE_TAC[VECTOR_ARITH
9603      `b = (b + e % (b - a)) - d % ((b + e % (b - a)) - a) <=>
9604       (e - d * (&1 + e)) % (b - a) = vec 0`] THEN
9605     ASM_REWRITE_TAC[VECTOR_SUB_EQ; VECTOR_MUL_EQ_0];
9606     MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK] THEN
9607   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LT_DIV; NORM_POS_LT;
9608                VECTOR_SUB_EQ; REAL_ARITH `&0 < x ==> &0 < &1 + x`;
9609                REAL_ARITH `&0 < x ==> ~(&1 + x = &0)`;
9610                REAL_MUL_LID; REAL_ADD_RDISTRIB; REAL_DIV_RMUL;
9611                REAL_LT_IMP_NZ; REAL_LE_ADDL; NORM_POS_LE; REAL_SUB_REFL]);;
9612
9613 let RELATIVE_FRONTIER_CLOSURE = prove
9614  (`!s. convex s ==> relative_frontier(closure s) = relative_frontier s`,
9615   SIMP_TAC[relative_frontier; CLOSURE_CLOSURE;
9616            CONVEX_RELATIVE_INTERIOR_CLOSURE]);;
9617
9618 let CONNECTED_INTER_RELATIVE_FRONTIER = prove
9619  (`!s t:real^N->bool.
9620         connected s /\ s SUBSET affine hull t /\
9621         ~(s INTER t = {}) /\ ~(s DIFF t = {})
9622         ==> ~(s INTER relative_frontier t = {})`,
9623   REWRITE_TAC[relative_frontier] THEN REPEAT STRIP_TAC THEN
9624   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONNECTED_OPEN_IN]) THEN
9625   REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
9626    [`s INTER relative_interior t:real^N->bool`;
9627     `s DIFF closure t:real^N->bool`] THEN
9628   REPEAT CONJ_TAC THENL
9629    [MATCH_MP_TAC OPEN_IN_SUBTOPOLOGY_INTER_SUBSET THEN
9630     EXISTS_TAC `affine hull t:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
9631     MATCH_MP_TAC OPEN_IN_INTER THEN
9632     REWRITE_TAC[OPEN_IN_RELATIVE_INTERIOR; OPEN_IN_SUBTOPOLOGY_REFL] THEN
9633     REWRITE_TAC[TOPSPACE_EUCLIDEAN; SUBSET_UNIV];
9634     ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
9635     MATCH_MP_TAC OPEN_IN_OPEN_INTER THEN
9636     REWRITE_TAC[GSYM closed; CLOSED_CLOSURE];
9637     ASM SET_TAC[];
9638     MATCH_MP_TAC(SET_RULE
9639      `i SUBSET t /\ t SUBSET c ==> (s INTER i) INTER (s DIFF c) = {}`) THEN
9640     REWRITE_TAC[RELATIVE_INTERIOR_SUBSET; CLOSURE_SUBSET];
9641     MP_TAC(ISPEC `t:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
9642     MP_TAC(ISPEC `t:real^N->bool` RELATIVE_INTERIOR_SUBSET) THEN
9643     ASM SET_TAC[]]);;
9644
9645 let CLOSED_RELATIVE_FRONTIER = prove
9646  (`!s:real^N->bool. closed(relative_frontier s)`,
9647   REPEAT GEN_TAC THEN REWRITE_TAC[relative_frontier] THEN
9648   MATCH_MP_TAC CLOSED_IN_CLOSED_TRANS THEN
9649   EXISTS_TAC `affine hull s:real^N->bool` THEN
9650   REWRITE_TAC[CLOSED_AFFINE_HULL] THEN MATCH_MP_TAC CLOSED_IN_DIFF THEN
9651   REWRITE_TAC[OPEN_IN_RELATIVE_INTERIOR] THEN
9652   MATCH_MP_TAC CLOSED_SUBSET THEN REWRITE_TAC[CLOSED_CLOSURE] THEN
9653   MATCH_MP_TAC(SET_RULE
9654    `s SUBSET closure t /\ closure t = t ==> s SUBSET t`) THEN
9655   SIMP_TAC[SUBSET_CLOSURE; HULL_SUBSET; CLOSURE_EQ; CLOSED_AFFINE_HULL]);;
9656
9657 let CLOSED_RELATIVE_BOUNDARY = prove
9658  (`!s. closed s ==> closed(s DIFF relative_interior s)`,
9659   MESON_TAC[CLOSED_RELATIVE_FRONTIER; relative_frontier; CLOSURE_CLOSED]);;
9660
9661 let COMPACT_RELATIVE_BOUNDARY = prove
9662  (`!s. compact s ==> compact(s DIFF relative_interior s)`,
9663   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_RELATIVE_BOUNDARY;
9664            BOUNDED_DIFF]);;
9665
9666 let BOUNDED_RELATIVE_FRONTIER = prove
9667  (`!s:real^N->bool. bounded s ==> bounded(relative_frontier s)`,
9668   REWRITE_TAC[relative_frontier] THEN
9669   MESON_TAC[BOUNDED_CLOSURE; BOUNDED_SUBSET; SUBSET_DIFF]);;
9670
9671 let COMPACT_RELATIVE_FRONTIER_BOUNDED = prove
9672  (`!s:real^N->bool. bounded s ==> compact(relative_frontier s)`,
9673   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_RELATIVE_FRONTIER;
9674            BOUNDED_RELATIVE_FRONTIER]);;
9675
9676 let COMPACT_RELATIVE_FRONTIER = prove
9677  (`!s:real^N->bool. compact s ==> compact(relative_frontier s)`,
9678   SIMP_TAC[COMPACT_RELATIVE_FRONTIER_BOUNDED; COMPACT_IMP_BOUNDED]);;
9679
9680 let CONVEX_SAME_RELATIVE_INTERIOR_CLOSURE = prove
9681  (`!s t. convex s /\ convex t
9682          ==> (relative_interior s = relative_interior t <=>
9683               closure s = closure t)`,
9684   MESON_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR;
9685             CONVEX_RELATIVE_INTERIOR_CLOSURE]);;
9686
9687 let CONVEX_SAME_RELATIVE_INTERIOR_CLOSURE_STRADDLE = prove
9688  (`!s t. convex s /\ convex t
9689          ==> (relative_interior s = relative_interior t <=>
9690               relative_interior s SUBSET t /\ t SUBSET closure s)`,
9691   MESON_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR;
9692             CONVEX_RELATIVE_INTERIOR_CLOSURE; SUBSET_CLOSURE;
9693                 SUBSET_ANTISYM; RELATIVE_INTERIOR_SUBSET;
9694                 CLOSURE_SUBSET; CLOSURE_CLOSURE]);;
9695
9696 let RELATIVE_INTERIOR_LINEAR_IMAGE_CONVEX = prove
9697  (`!f:real^M->real^N s.
9698         linear f /\ convex s
9699         ==> relative_interior(IMAGE f s) = IMAGE f (relative_interior s)`,
9700   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
9701    [SUBGOAL_THEN
9702      `relative_interior (IMAGE f (relative_interior s)) =
9703       relative_interior (IMAGE (f:real^M->real^N) s)`
9704      (fun th -> REWRITE_TAC[SYM th; RELATIVE_INTERIOR_SUBSET]) THEN
9705     ASM_SIMP_TAC[CONVEX_SAME_RELATIVE_INTERIOR_CLOSURE_STRADDLE;
9706                  CONVEX_RELATIVE_INTERIOR; CONVEX_LINEAR_IMAGE] THEN
9707     CONJ_TAC THENL
9708      [MATCH_MP_TAC SUBSET_TRANS THEN
9709       EXISTS_TAC `IMAGE (f:real^M->real^N) (relative_interior s)` THEN
9710       SIMP_TAC[RELATIVE_INTERIOR_SUBSET; IMAGE_SUBSET];
9711       MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC
9712         `IMAGE (f:real^M->real^N) (closure(relative_interior s))` THEN
9713       ASM_SIMP_TAC[CLOSURE_LINEAR_IMAGE_SUBSET] THEN
9714       ASM_SIMP_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR] THEN
9715       MATCH_MP_TAC IMAGE_SUBSET THEN REWRITE_TAC[CLOSURE_SUBSET]];
9716     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN X_GEN_TAC `z:real^M` THEN
9717     DISCH_TAC THEN
9718     ASM_SIMP_TAC[RELATIVE_INTERIOR_CONVEX_PROLONG; CONVEX_LINEAR_IMAGE] THEN
9719     REWRITE_TAC[IN_ELIM_THM; FORALL_IN_IMAGE] THEN CONJ_TAC THENL
9720      [MATCH_MP_TAC FUN_IN_IMAGE THEN
9721       ASM_MESON_TAC[SUBSET; RELATIVE_INTERIOR_SUBSET];
9722       ALL_TAC] THEN
9723     X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
9724     MP_TAC(ISPECL [`s:real^M->bool`; `z:real^M`; `x:real^M`]
9725         RELATIVE_INTERIOR_PROLONG) THEN ASM_REWRITE_TAC[] THEN
9726     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real` THEN
9727     MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
9728     DISCH_THEN(MP_TAC o ISPEC `f:real^M->real^N` o MATCH_MP FUN_IN_IMAGE) THEN
9729     ASM_MESON_TAC[LINEAR_ADD; LINEAR_SUB; LINEAR_CMUL]]);;
9730
9731 let CLOSURE_INTERS_CONVEX = prove
9732  (`!f:(real^N->bool)->bool.
9733         (!s. s IN f ==> convex s) /\
9734         ~(INTERS(IMAGE relative_interior f) = {})
9735         ==> closure(INTERS f) = INTERS(IMAGE closure f)`,
9736   REPEAT STRIP_TAC THEN
9737   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[CLOSURE_INTERS_SUBSET] THEN
9738   REWRITE_TAC[SUBSET; IN_INTERS; FORALL_IN_IMAGE] THEN
9739   X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
9740   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9741   REWRITE_TAC[INTERS_IMAGE; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
9742   X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
9743   REWRITE_TAC[CLOSURE_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
9744   ASM_CASES_TAC `b:real^N = a` THENL
9745    [EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[DIST_REFL; IN_INTERS] THEN
9746     ASM_MESON_TAC[SUBSET; RELATIVE_INTERIOR_SUBSET];
9747     ALL_TAC] THEN
9748   EXISTS_TAC `b - min (&1 / &2) (e / &2 / norm(b - a)) % (b - a):real^N` THEN
9749   CONJ_TAC THENL
9750    [ALL_TAC;
9751     REWRITE_TAC[NORM_ARITH `dist(b - a:real^N,b) = norm a`; NORM_MUL] THEN
9752     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
9753     MATCH_MP_TAC(REAL_ARITH
9754      `&0 < a /\ &0 < x /\ x < y ==> abs(min a x) < y`) THEN
9755     ASM_SIMP_TAC[REAL_LT_DIV2_EQ; REAL_HALF; REAL_LT_DIV; NORM_POS_LT;
9756                  VECTOR_SUB_EQ] THEN
9757     ASM_REAL_ARITH_TAC] THEN
9758   REWRITE_TAC[IN_INTERS] THEN X_GEN_TAC `s:real^N->bool` THEN DISCH_TAC THEN
9759   MATCH_MP_TAC
9760    (MESON[RELATIVE_INTERIOR_SUBSET; SUBSET]
9761          `!x. x IN relative_interior s ==> x IN s`) THEN
9762   MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
9763   ASM_SIMP_TAC[REAL_LT_MIN; REAL_HALF; REAL_LT_DIV; NORM_POS_LT;
9764                VECTOR_SUB_EQ] THEN
9765   REAL_ARITH_TAC);;
9766
9767 let CLOSURE_INTERS_CONVEX_OPEN = prove
9768  (`!f:(real^N->bool)->bool.
9769         (!s. s IN f ==> convex s /\ open s)
9770         ==> closure(INTERS f) =
9771                 if INTERS f = {} then {}
9772                 else INTERS(IMAGE closure f)`,
9773   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[CLOSURE_EMPTY] THEN
9774   MATCH_MP_TAC CLOSURE_INTERS_CONVEX THEN ASM_SIMP_TAC[] THEN
9775   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
9776    `~(s = {}) ==> s = t ==> ~(t = {})`)) THEN
9777   AP_TERM_TAC THEN MATCH_MP_TAC(SET_RULE
9778    `(!x. x IN s ==> f x = x) ==> s = IMAGE f s`) THEN
9779   ASM_SIMP_TAC[RELATIVE_INTERIOR_OPEN; INTERIOR_EQ]);;
9780
9781 let CLOSURE_INTER_CONVEX = prove
9782  (`!s t:real^N->bool.
9783         convex s /\ convex t /\
9784         ~(relative_interior s INTER relative_interior t = {})
9785         ==> closure(s INTER t) = closure(s) INTER closure(t)`,
9786   REPEAT STRIP_TAC THEN
9787   MP_TAC(ISPEC `{s:real^N->bool,t}` CLOSURE_INTERS_CONVEX) THEN
9788   ASM_SIMP_TAC[IMAGE_CLAUSES; INTERS_2] THEN
9789   ASM_REWRITE_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY]);;
9790
9791 let CLOSURE_INTER_CONVEX_OPEN = prove
9792  (`!s t. convex s /\ open s /\ convex t /\ open t
9793          ==> closure(s INTER t) =
9794                 if s INTER t = {} then {} else closure(s) INTER closure(t)`,
9795   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[CLOSURE_EMPTY] THEN
9796   MATCH_MP_TAC CLOSURE_INTER_CONVEX THEN
9797   ASM_SIMP_TAC[RELATIVE_INTERIOR_OPEN]);;
9798
9799 let CLOSURE_CONVEX_INTER_SUPERSET = prove
9800  (`!s t:real^N->bool.
9801         convex s /\ ~(interior s = {}) /\ interior s SUBSET closure t
9802         ==> closure(s INTER t) = closure s`,
9803   REPEAT GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9804   SIMP_TAC[SUBSET_CLOSURE; INTER_SUBSET; SUBSET_INTER] THEN
9805   MATCH_MP_TAC SUBSET_TRANS THEN
9806   EXISTS_TAC `closure(interior s):real^N->bool` THEN CONJ_TAC THENL
9807    [ASM_SIMP_TAC[CONVEX_CLOSURE_INTERIOR; SUBSET_REFL];
9808     ASM_SIMP_TAC[GSYM CLOSURE_OPEN_INTER_SUPERSET; OPEN_INTERIOR] THEN
9809     MATCH_MP_TAC SUBSET_CLOSURE THEN
9810     MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET) THEN SET_TAC[]]);;
9811
9812 let CLOSURE_DYADIC_RATIONALS_IN_CONVEX_SET = prove
9813  (`!s:real^N->bool.
9814         convex s /\ ~(interior s = {})
9815         ==> closure(s INTER
9816                     { inv(&2 pow n) % x | n,x |
9817                       !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }) =
9818             closure s`,
9819   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_CONVEX_INTER_SUPERSET THEN
9820   ASM_REWRITE_TAC[CLOSURE_DYADIC_RATIONALS; SUBSET_UNIV]);;
9821
9822 let CLOSURE_RATIONALS_IN_CONVEX_SET = prove
9823  (`!s:real^N->bool.
9824       convex s /\ ~(interior s = {})
9825       ==> closure(s INTER
9826                   { x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) }) =
9827           closure s`,
9828   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_CONVEX_INTER_SUPERSET THEN
9829   ASM_REWRITE_TAC[CLOSURE_RATIONAL_COORDINATES; SUBSET_UNIV]);;
9830
9831 let RELATIVE_INTERIOR_CONVEX_INTER_AFFINE = prove
9832  (`!s t:real^N->bool.
9833         convex s /\ affine t /\ ~(interior s INTER t = {})
9834         ==> relative_interior(s INTER t) = interior s INTER t`,
9835   REPEAT GEN_TAC THEN
9836   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; RIGHT_AND_EXISTS_THM] THEN
9837   DISCH_THEN(X_CHOOSE_THEN `a:real^N` MP_TAC) THEN
9838   GEOM_ORIGIN_TAC `a:real^N` THEN REWRITE_TAC[IN_INTER] THEN
9839   REPEAT GEN_TAC THEN ASM_CASES_TAC `(vec 0:real^N) IN t` THEN
9840   ASM_SIMP_TAC[AFFINE_EQ_SUBSPACE] THEN STRIP_TAC THEN
9841   GEN_REWRITE_TAC I [EXTENSION] THEN X_GEN_TAC `x:real^N` THEN
9842   MP_TAC(ISPECL [`t:real^N->bool`; `s:real^N->bool`]
9843         (ONCE_REWRITE_RULE[INTER_COMM]
9844            AFFINE_HULL_AFFINE_INTER_NONEMPTY_INTERIOR)) THEN
9845   ASM_SIMP_TAC[SUBSPACE_IMP_AFFINE; IN_RELATIVE_INTERIOR_CBALL] THEN
9846   ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[IN_INTER; IN_INTERIOR_CBALL]] THEN
9847   DISCH_THEN SUBST1_TAC THEN
9848   ASM_CASES_TAC `(x:real^N) IN t` THEN ASM_REWRITE_TAC[] THEN
9849   SIMP_TAC[SUBSET; IN_INTER] THEN
9850   ASM_CASES_TAC `(x:real^N) IN s` THENL
9851    [ASM_REWRITE_TAC[]; ASM_MESON_TAC[CENTRE_IN_CBALL; REAL_LT_IMP_LE]] THEN
9852   EQ_TAC THENL [REWRITE_TAC[IN_CBALL]; MESON_TAC[]] THEN
9853   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
9854   ASM_CASES_TAC `x:real^N = vec 0` THENL
9855    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR_CBALL]) THEN
9856     ASM_REWRITE_TAC[SUBSET; IN_CBALL];
9857     ALL_TAC] THEN
9858   MP_TAC(ISPECL
9859    [`s:real^N->bool`; `vec 0:real^N`; `(&1 + e / norm x) % x:real^N`]
9860    IN_INTERIOR_CLOSURE_CONVEX_SEGMENT) THEN
9861   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
9862    [MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN
9863     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[SUBSPACE_MUL] THEN
9864     REWRITE_TAC[VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID;
9865                 NORM_ARITH `dist(a:real^N,a + x) = norm x`] THEN
9866     ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM;
9867                  REAL_DIV_RMUL; NORM_EQ_0] THEN
9868     ASM_REAL_ARITH_TAC;
9869     REWRITE_TAC[SUBSET; IN_INTERIOR_CBALL; IN_CBALL] THEN
9870     DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[IN_SEGMENT] THEN
9871     CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN
9872     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
9873     REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
9874     EXISTS_TAC `inv(&1 + e / norm(x:real^N))` THEN
9875     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_LT_DIV; NORM_POS_LT; VECTOR_MUL_LID;
9876                  REAL_LT_INV_EQ; REAL_MUL_LINV; REAL_INV_LT_1; REAL_ARITH
9877                  `&0 < x ==> &1 < &1 + x /\ &0 < &1 + x /\ ~(&1 + x = &0)`]]);;
9878
9879 (* ------------------------------------------------------------------------- *)
9880 (* Homeomorphism of all convex compact sets with same affine dimension, and  *)
9881 (* in particular all those with nonempty interior.                           *)
9882 (* ------------------------------------------------------------------------- *)
9883
9884 let COMPACT_FRONTIER_LINE_LEMMA = prove
9885  (`!s x. compact s /\ (vec 0 IN s) /\ ~(x = vec 0 :real^N)
9886          ==> ?u. &0 <= u /\ (u % x) IN frontier s /\
9887                  !v. u < v ==> ~((v % x) IN s)`,
9888   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN
9889   REWRITE_TAC[BOUNDED_POS] THEN
9890   DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THEN
9891   MP_TAC(ISPECL
9892     [`{y:real^N | ?u. &0 <= u /\ u <= b / norm(x) /\ (y = u % x)} INTER s`;
9893      `vec 0:real^N`]
9894    DISTANCE_ATTAINS_SUP) THEN
9895   ANTS_TAC THENL
9896    [CONJ_TAC THENL
9897      [ALL_TAC;
9898       REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `vec 0:real^N` THEN
9899       ASM_REWRITE_TAC[IN_INTER; IN_ELIM_THM] THEN
9900       EXISTS_TAC `&0` THEN
9901       ASM_SIMP_TAC[VECTOR_MUL_LZERO; REAL_LE_REFL; REAL_LT_IMP_LE;
9902                    REAL_LT_DIV; NORM_POS_LT]] THEN
9903     MATCH_MP_TAC COMPACT_INTER THEN ASM_REWRITE_TAC[] THEN
9904     SUBGOAL_THEN
9905      `{y:real^N | ?u. &0 <= u /\ u <= b / norm(x) /\ (y = u % x)} =
9906       IMAGE (\u. drop u % x) (interval [vec 0,lambda i. b / norm(x:real^N)])`
9907     SUBST1_TAC THENL
9908      [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; IN_INTERVAL] THEN
9909       SIMP_TAC[LAMBDA_BETA] THEN
9910       SIMP_TAC[DIMINDEX_1; ARITH_RULE `1 <= i /\ i <= 1 <=> (i = 1)`] THEN
9911       REWRITE_TAC[GSYM drop; LEFT_FORALL_IMP_THM; EXISTS_REFL; DROP_VEC] THEN
9912       REWRITE_TAC[EXISTS_LIFT; LIFT_DROP] THEN MESON_TAC[];
9913       ALL_TAC] THEN
9914     MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
9915     REWRITE_TAC[COMPACT_INTERVAL] THEN
9916     MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN REPEAT STRIP_TAC THEN
9917     MATCH_MP_TAC CONTINUOUS_VMUL THEN
9918     REWRITE_TAC[o_DEF; LIFT_DROP; CONTINUOUS_AT_ID];
9919     ALL_TAC] THEN
9920   REWRITE_TAC[IN_INTER; IN_ELIM_THM; LEFT_AND_EXISTS_THM] THEN
9921   ONCE_REWRITE_TAC[TAUT `(a /\ b /\ c) /\ d <=> c /\ a /\ b /\ d`] THEN
9922   SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
9923   GEN_REWRITE_TAC (BINDER_CONV o ONCE_DEPTH_CONV) [SWAP_FORALL_THM] THEN
9924   SIMP_TAC[IMP_CONJ] THEN
9925   REWRITE_TAC[LEFT_FORALL_IMP_THM; EXISTS_REFL] THEN
9926   REWRITE_TAC[IMP_IMP] THEN REWRITE_TAC[LEFT_FORALL_IMP_THM] THEN
9927   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real` THEN
9928   REWRITE_TAC[dist; VECTOR_SUB_LZERO; NORM_NEG; NORM_MUL] THEN
9929   ASM_SIMP_TAC[REAL_LE_RMUL_EQ; NORM_POS_LT] THEN
9930   DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
9931   ASM_SIMP_TAC[real_abs] THEN REPEAT STRIP_TAC THENL
9932    [REWRITE_TAC[FRONTIER_STRADDLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
9933     CONJ_TAC THENL
9934      [EXISTS_TAC `u % x :real^N` THEN ASM_REWRITE_TAC[DIST_REFL];
9935       ALL_TAC] THEN
9936     EXISTS_TAC `(u + (e / &2) / norm(x)) % x :real^N` THEN
9937     REWRITE_TAC[dist; VECTOR_ARITH `u % x - (u + a) % x = --(a % x)`] THEN
9938     ASM_SIMP_TAC[NORM_NEG; NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; NORM_EQ_0;
9939                  REAL_DIV_RMUL; REAL_ABS_NUM; REAL_LT_LDIV_EQ; REAL_OF_NUM_LT;
9940                  ARITH; REAL_ARITH `abs e < e * &2 <=> &0 < e`] THEN
9941     DISCH_TAC THEN
9942     FIRST_X_ASSUM(MP_TAC o SPEC `u + (e / &2) / norm(x:real^N)`) THEN
9943     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(REAL_ARITH
9944      `&0 < e /\ &0 <= u /\ u + e <= b
9945       ==> ~(&0 <= u + e /\ u + e <= b ==> u + e <= u)`) THEN
9946     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; NORM_POS_LT] THEN
9947     FIRST_X_ASSUM(MP_TAC o SPEC `(u + (e / &2) / norm(x:real^N)) % x`) THEN
9948     ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
9949     REAL_ARITH_TAC;
9950     ALL_TAC] THEN
9951   FIRST_X_ASSUM(MP_TAC o SPEC `v:real`) THEN
9952   ASM_REWRITE_TAC[GSYM REAL_NOT_LT] THEN ASM_REWRITE_TAC[REAL_NOT_LT] THEN
9953   CONJ_TAC THENL [ASM_MESON_TAC[REAL_LET_TRANS; REAL_LT_IMP_LE]; ALL_TAC] THEN
9954   FIRST_X_ASSUM(MP_TAC o SPEC `v % x:real^N`) THEN
9955   ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
9956   REAL_ARITH_TAC);;
9957
9958 let STARLIKE_COMPACT_PROJECTIVE = prove
9959  (`!s:real^N->bool a.
9960         compact s /\ a IN relative_interior s /\
9961         (!x. x IN s ==> segment(a,x) SUBSET relative_interior s)
9962         ==> s DIFF relative_interior s homeomorphic
9963             sphere(a,&1) INTER affine hull s /\
9964             s homeomorphic cball(a,&1) INTER affine hull s`,
9965   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN
9966   REWRITE_TAC[SUBSET; IMP_IMP; RIGHT_IMP_FORALL_THM] THEN
9967   GEN_TAC THEN STRIP_TAC THEN
9968   SUBGOAL_THEN
9969    `!x:real^N u. x IN s /\ &0 <= u /\ u < &1
9970                  ==> (u % x) IN relative_interior s`
9971   ASSUME_TAC THENL
9972    [REWRITE_TAC[REAL_ARITH `&0 <= u <=> u = &0 \/ &0 < u`] THEN
9973     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[VECTOR_MUL_LZERO] THEN
9974     ASM_CASES_TAC `x:real^N = vec 0` THEN
9975     ASM_REWRITE_TAC[VECTOR_MUL_RZERO] THEN
9976     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[IN_SEGMENT] THEN
9977     REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN ASM_MESON_TAC[];
9978     FIRST_X_ASSUM(K ALL_TAC o SPECL [`x:real^N`; `x:real^N`])] THEN
9979   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REWRITE_RULE[SUBSET]
9980     RELATIVE_INTERIOR_SUBSET)) THEN
9981   ABBREV_TAC `proj = \x:real^N. inv(norm(x)) % x` THEN
9982   SUBGOAL_THEN
9983    `!x:real^N y. (proj(x) = proj(y):real^N) /\ (norm x = norm y) <=> (x = y)`
9984   ASSUME_TAC THENL
9985    [REPEAT GEN_TAC THEN EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
9986     ASM_CASES_TAC `y:real^N = vec 0` THEN
9987     ASM_SIMP_TAC[NORM_EQ_0; NORM_0] THEN
9988     ASM_CASES_TAC `x:real^N = vec 0` THENL
9989      [ASM_MESON_TAC[NORM_EQ_0]; ALL_TAC] THEN
9990     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
9991     EXPAND_TAC "proj" THEN REWRITE_TAC[] THEN
9992     ASM_REWRITE_TAC[VECTOR_ARITH
9993      `a % x = a % y <=> a % (x - y):real^N = vec 0`] THEN
9994     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; REAL_INV_EQ_0; NORM_EQ_0; VECTOR_SUB_EQ];
9995     ALL_TAC] THEN
9996   SUBGOAL_THEN
9997    `(!x. x IN affine hull s ==> proj x IN affine hull s) /\
9998     (!x. ~(x = vec 0) ==> norm(proj x) = &1) /\
9999     (!x:real^N. proj x = vec 0 <=> x = vec 0)`
10000   STRIP_ASSUME_TAC THENL
10001    [EXPAND_TAC "proj" THEN REWRITE_TAC[NORM_MUL; VECTOR_MUL_EQ_0] THEN
10002     REWRITE_TAC[REAL_INV_EQ_0; NORM_EQ_0; REAL_ABS_INV; REAL_ABS_NORM] THEN
10003     SIMP_TAC[REAL_MUL_LINV; NORM_EQ_0] THEN REPEAT STRIP_TAC THEN
10004     GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_ADD_LID] THEN
10005     MATCH_MP_TAC IN_AFFINE_ADD_MUL THEN
10006     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; VECTOR_ADD_LID; HULL_INC];
10007     ALL_TAC] THEN
10008   SUBGOAL_THEN `(proj:real^N->real^N) continuous_on (UNIV DELETE vec 0)`
10009   ASSUME_TAC THENL
10010    [MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
10011     REWRITE_TAC[IN_DELETE; IN_UNIV] THEN EXPAND_TAC "proj" THEN
10012     REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
10013     ASM_SIMP_TAC[CONTINUOUS_AT_ID] THEN
10014     REWRITE_TAC[GSYM(ISPEC `lift` o_DEF);
10015                 GSYM(ISPEC `inv:real->real` o_DEF)] THEN
10016     MATCH_MP_TAC CONTINUOUS_AT_INV THEN
10017     ASM_REWRITE_TAC[NORM_EQ_0; VECTOR_SUB_EQ; CONTINUOUS_AT_LIFT_NORM];
10018     ALL_TAC] THEN
10019   ABBREV_TAC `usph = {x:real^N | x IN affine hull s /\ norm x = &1}` THEN
10020   SUBGOAL_THEN ` sphere(vec 0:real^N,&1) INTER affine hull s = usph`
10021   SUBST1_TAC THENL
10022    [EXPAND_TAC "usph" THEN REWRITE_TAC[EXTENSION; IN_INTER; IN_SPHERE_0] THEN
10023     SET_TAC[];
10024     ALL_TAC] THEN
10025   SUBGOAL_THEN
10026    `!x. x IN affine hull s /\ ~(x = vec 0)
10027         ==> (proj:real^N->real^N) x IN usph`
10028   ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10029   SUBGOAL_THEN `?surf. homeomorphism (s DIFF relative_interior s,usph)
10030                                      (proj:real^N->real^N,surf)`
10031   MP_TAC THENL
10032    [MATCH_MP_TAC HOMEOMORPHISM_COMPACT THEN
10033     ASM_SIMP_TAC[COMPACT_RELATIVE_BOUNDARY] THEN REPEAT CONJ_TAC THENL
10034      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10035           CONTINUOUS_ON_SUBSET)) THEN
10036       ASM SET_TAC[];
10037       MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
10038        [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_DIFF] THEN
10039         EXPAND_TAC "usph" THEN REWRITE_TAC[IN_ELIM_THM] THEN
10040         ASM_MESON_TAC[HULL_INC];
10041         MAP_EVERY EXPAND_TAC ["proj"; "usph"] THEN
10042         REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN
10043         ASM_CASES_TAC `x:real^N = vec 0` THEN
10044         ASM_REWRITE_TAC[NORM_0; REAL_OF_NUM_EQ; ARITH_EQ] THEN STRIP_TAC THEN
10045         MP_TAC(ISPECL [`s:real^N->bool`; `vec 0:real^N`; `x:real^N`]
10046             RAY_TO_RELATIVE_FRONTIER) THEN
10047         REWRITE_TAC[relative_frontier] THEN
10048         ASM_SIMP_TAC[COMPACT_IMP_BOUNDED; CLOSURE_CLOSED; COMPACT_IMP_CLOSED;
10049                      VECTOR_ADD_LID] THEN
10050         DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
10051         EXPAND_TAC "proj" THEN REWRITE_TAC[IN_IMAGE] THEN
10052         EXISTS_TAC `d % x:real^N` THEN ASM_REWRITE_TAC[NORM_MUL] THEN
10053         ASM_SIMP_TAC[REAL_MUL_RID; real_abs; REAL_LT_IMP_LE] THEN
10054         ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_LT_IMP_NZ;
10055                      VECTOR_MUL_LID]];
10056       MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
10057       REWRITE_TAC[IN_DIFF] THEN STRIP_TAC THEN
10058       ASM_CASES_TAC `x:real^N = vec 0` THENL [ASM SET_TAC[]; ALL_TAC] THEN
10059       ASM_CASES_TAC `y:real^N = vec 0` THENL [ASM SET_TAC[]; ALL_TAC] THEN
10060       UNDISCH_TAC `(proj:real^N->real^N) x = proj y` THEN
10061       EXPAND_TAC "proj" THEN
10062       REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC (REAL_ARITH
10063        `norm(x:real^N) = norm(y:real^N) \/
10064         norm x < norm y \/ norm y < norm x`)
10065       THENL
10066        [ASM_REWRITE_TAC[VECTOR_MUL_LCANCEL; REAL_INV_EQ_0; NORM_EQ_0];
10067         DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL
10068          [`y:real^N`; `norm(x:real^N) / norm(y:real^N)`]);
10069         DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL
10070          [`x:real^N`; `norm(y:real^N) / norm(x:real^N)`])] THEN
10071       ASM_SIMP_TAC[REAL_LE_DIV; NORM_POS_LE; REAL_LT_LDIV_EQ; NORM_POS_LT;
10072                    REAL_MUL_LID] THEN
10073       ASM_REWRITE_TAC[real_div; GSYM VECTOR_MUL_ASSOC] THENL
10074        [FIRST_X_ASSUM(SUBST1_TAC o SYM); ALL_TAC] THEN
10075       ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; NORM_EQ_0] THEN
10076       ASM_REWRITE_TAC[VECTOR_MUL_LID]];
10077     DISCH_THEN(fun th ->
10078       CONJ_TAC THENL
10079        [MESON_TAC[homeomorphic; th];
10080         ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
10081         MATCH_MP_TAC HOMEOMORPHIC_COMPACT THEN
10082         SIMP_TAC[COMPACT_INTER_CLOSED; CLOSED_AFFINE_HULL; COMPACT_CBALL] THEN
10083         MP_TAC th]) THEN
10084     REWRITE_TAC[HOMEOMORPHISM; LEFT_IMP_EXISTS_THM] THEN
10085     X_GEN_TAC `surf:real^N->real^N` THEN STRIP_TAC THEN
10086     EXISTS_TAC `\x:real^N. norm(x) % (surf:real^N->real^N)(proj(x))` THEN
10087     REWRITE_TAC[]] THEN
10088   UNDISCH_THEN
10089    `(proj:real^N->real^N) continuous_on s DIFF relative_interior s`
10090    (K ALL_TAC) THEN
10091   REWRITE_TAC[] THEN CONJ_TAC THENL
10092    [REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; IN_INTER] THEN
10093     X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
10094     ASM_CASES_TAC `x = vec 0:real^N` THENL
10095      [ASM_REWRITE_TAC[CONTINUOUS_WITHIN; VECTOR_MUL_LZERO; NORM_0] THEN
10096       MATCH_MP_TAC LIM_NULL_VMUL_BOUNDED THEN
10097       FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN
10098       REWRITE_TAC[BOUNDED_POS] THEN MATCH_MP_TAC MONO_EXISTS THEN
10099       REPEAT STRIP_TAC THENL
10100        [REWRITE_TAC[LIM_WITHIN; o_THM; DIST_0; NORM_LIFT; REAL_ABS_NORM] THEN
10101         MESON_TAC[];
10102         REWRITE_TAC[EVENTUALLY_WITHIN] THEN EXISTS_TAC `&1` THEN
10103         REWRITE_TAC[REAL_LT_01; IN_INTER; DIST_0; NORM_POS_LT] THEN
10104         ASM SET_TAC[]];
10105       MATCH_MP_TAC CONTINUOUS_WITHIN_SUBSET THEN
10106       EXISTS_TAC `affine hull s:real^N->bool` THEN
10107       REWRITE_TAC[INTER_SUBSET] THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
10108       SIMP_TAC[CONTINUOUS_LIFT_NORM_COMPOSE; CONTINUOUS_WITHIN_ID; o_DEF] THEN
10109       SUBGOAL_THEN
10110        `((surf:real^N->real^N) o (proj:real^N->real^N)) continuous_on
10111         (affine hull s DELETE vec 0)`
10112       MP_TAC THENL
10113        [MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
10114         ASM_REWRITE_TAC[] THEN CONJ_TAC THEN
10115         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10116             CONTINUOUS_ON_SUBSET)) THEN
10117         SIMP_TAC[SUBSET; IN_DELETE; IN_UNIV; FORALL_IN_IMAGE] THEN
10118         EXPAND_TAC "usph" THEN ASM_SIMP_TAC[IN_ELIM_THM];
10119         SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
10120         DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_SIMP_TAC[IN_DELETE] THEN
10121         REWRITE_TAC[CONTINUOUS_WITHIN; o_DEF] THEN MATCH_MP_TAC EQ_IMP THEN
10122         MATCH_MP_TAC LIM_TRANSFORM_WITHIN_SET THEN
10123         REWRITE_TAC[EVENTUALLY_AT] THEN EXISTS_TAC `norm(x:real^N)` THEN
10124         ASM_REWRITE_TAC[IN_DELETE; IN_INTER; IN_CBALL; NORM_POS_LT] THEN
10125         X_GEN_TAC `y:real^N` THEN
10126         ASM_CASES_TAC `(y:real^N) IN affine hull s` THEN ASM_REWRITE_TAC[] THEN
10127         CONV_TAC NORM_ARITH]];
10128     ALL_TAC] THEN
10129   SUBGOAL_THEN
10130    `!a x. &0 < a ==> (proj:real^N->real^N)(a % x) = proj x`
10131   ASSUME_TAC THENL
10132    [REPEAT GEN_TAC THEN EXPAND_TAC "proj" THEN
10133     REWRITE_TAC[NORM_MUL; REAL_INV_MUL; VECTOR_MUL_ASSOC] THEN
10134     SIMP_TAC[REAL_FIELD `&0 < a ==> (inv(a) * x) * a = x`; real_abs;
10135              REAL_LT_IMP_LE];
10136     ALL_TAC] THEN
10137   CONJ_TAC THENL
10138    [ALL_TAC;
10139     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
10140     ASM_CASES_TAC `y:real^N = vec 0` THENL
10141      [ASM_SIMP_TAC[VECTOR_MUL_LZERO; VECTOR_MUL_EQ_0; NORM_0; NORM_EQ_0] THEN
10142       ASM SET_TAC[];
10143       ALL_TAC] THEN
10144     ASM_CASES_TAC `x:real^N = vec 0` THENL
10145      [CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN
10146       ASM_SIMP_TAC[VECTOR_MUL_LZERO; VECTOR_MUL_EQ_0; NORM_0; NORM_EQ_0] THEN
10147       ASM SET_TAC[];
10148       ALL_TAC] THEN
10149     REWRITE_TAC[IN_INTER; IN_CBALL_0] THEN
10150     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC)) THEN
10151     DISCH_THEN(fun th -> MP_TAC th THEN
10152              MP_TAC(AP_TERM `proj:real^N->real^N` th)) THEN
10153     ASM_SIMP_TAC[NORM_POS_LT; VECTOR_MUL_RCANCEL] THEN ASM SET_TAC[]] THEN
10154   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
10155    [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_CBALL_0] THEN
10156     X_GEN_TAC `x:real^N` THEN ASM_CASES_TAC `x:real^N = vec 0` THEN
10157     ASM_REWRITE_TAC[NORM_0; VECTOR_MUL_LZERO; IN_INTER] THEN
10158     REWRITE_TAC[IN_CBALL_0; REAL_LE_LT] THEN STRIP_TAC  THENL
10159      [MATCH_MP_TAC(REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET) THEN
10160       FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[NORM_POS_LE] THEN
10161       ASM SET_TAC[];
10162       ASM_REWRITE_TAC[VECTOR_MUL_LID] THEN ASM SET_TAC[]];
10163     ALL_TAC] THEN
10164   REWRITE_TAC[SUBSET; IN_IMAGE; IN_CBALL_0; IN_INTER] THEN
10165   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
10166   ASM_CASES_TAC `x:real^N = vec 0` THENL
10167    [EXISTS_TAC `vec 0:real^N` THEN
10168     ASM_SIMP_TAC[NORM_0; VECTOR_MUL_LZERO; HULL_INC; REAL_POS];
10169     ALL_TAC] THEN
10170   SUBGOAL_THEN
10171    `!x. x IN usph ==> ~((surf:real^N->real^N) x = vec 0)`
10172   ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10173   EXISTS_TAC `inv(norm(surf(proj x:real^N):real^N)) % x:real^N` THEN
10174   FIRST_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [GSYM th]) THEN
10175   REWRITE_TAC[GSYM CONJ_ASSOC] THEN
10176   ASM (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 5)
10177    [NORM_POS_LT; REAL_LT_INV_EQ; HULL_INC; REAL_LT_MUL; NORM_MUL;
10178     REAL_ABS_INV; REAL_ABS_NORM] THEN
10179   REPEAT CONJ_TAC THENL
10180    [MATCH_MP_TAC(REAL_FIELD `~(y = &0) ==> x = (inv y * x) * y`) THEN
10181     ASM_SIMP_TAC[NORM_EQ_0; HULL_INC];
10182     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
10183     ASM (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 5)
10184      [GSYM real_div; REAL_LE_LDIV_EQ; NORM_POS_LT; HULL_INC; REAL_MUL_LID] THEN
10185     FIRST_X_ASSUM(MP_TAC o SPECL
10186      [`x:real^N`; `norm(surf(proj x:real^N):real^N) / norm(x:real^N)`]) THEN
10187     ASM_SIMP_TAC[REAL_LE_DIV; NORM_POS_LE; REAL_LT_LDIV_EQ; NORM_POS_LT] THEN
10188     GEN_REWRITE_TAC LAND_CONV [GSYM CONTRAPOS_THM] THEN
10189     REWRITE_TAC[REAL_NOT_LT; REAL_MUL_LID] THEN DISCH_THEN MATCH_MP_TAC THEN
10190     SUBGOAL_THEN
10191      `norm(surf(proj x)) / norm x % x:real^N = surf(proj x:real^N)`
10192     SUBST1_TAC THENL
10193      [FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC I [GSYM th]) THEN
10194       ASM (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 5)
10195        [NORM_POS_LT; REAL_LT_INV_EQ; HULL_INC; REAL_LT_MUL; NORM_MUL;
10196         REAL_ABS_INV; REAL_ABS_NORM; REAL_ABS_DIV; REAL_LT_DIV;
10197         REAL_DIV_RMUL; NORM_EQ_0];
10198       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
10199        `IMAGE f s SUBSET t DIFF u ==> x IN s ==> ~(f x IN u)`)) THEN
10200       ASM_SIMP_TAC[HULL_INC]];
10201     GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_ADD_LID] THEN
10202     MATCH_MP_TAC IN_AFFINE_ADD_MUL THEN
10203     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; VECTOR_ADD_LID; HULL_INC]]);;
10204
10205 let HOMEOMORPHIC_CONVEX_COMPACT_SETS,
10206     HOMEOMORPHIC_RELATIVE_FRONTIERS_CONVEX_BOUNDED_SETS = (CONJ_PAIR o prove)
10207  (`(!s:real^M->bool t:real^N->bool.
10208         convex s /\ compact s /\ convex t /\ compact t /\ aff_dim s = aff_dim t
10209         ==> s homeomorphic t) /\
10210    (!s:real^M->bool t:real^N->bool.
10211         convex s /\ bounded s /\ convex t /\ bounded t /\ aff_dim s = aff_dim t
10212         ==> relative_frontier s homeomorphic relative_frontier t)`,
10213   let lemma = prove
10214    (`!s:real^M->bool t:real^N->bool.
10215           convex s /\ compact s /\ convex t /\ compact t /\
10216           aff_dim s = aff_dim t
10217           ==> (s DIFF relative_interior s) homeomorphic
10218               (t DIFF relative_interior t) /\
10219               s homeomorphic t`,
10220     REPEAT GEN_TAC THEN
10221     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
10222     ASM_CASES_TAC `relative_interior t:real^N->bool = {}` THENL
10223      [UNDISCH_TAC `relative_interior t:real^N->bool = {}` THEN
10224       ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1;
10225                    EMPTY_DIFF; HOMEOMORPHIC_EMPTY; RELATIVE_INTERIOR_EQ_EMPTY];
10226        FIRST_X_ASSUM(X_CHOOSE_THEN `b:real^N` MP_TAC o
10227           GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY])] THEN
10228     CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN
10229     ASM_CASES_TAC `relative_interior s:real^M->bool = {}` THENL
10230      [UNDISCH_TAC `relative_interior s:real^M->bool = {}` THEN
10231       ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1;
10232                    EMPTY_DIFF; HOMEOMORPHIC_EMPTY; RELATIVE_INTERIOR_EQ_EMPTY];
10233       FIRST_X_ASSUM(X_CHOOSE_THEN `a:real^M` MP_TAC o
10234           GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY])] THEN
10235     REPEAT(POP_ASSUM MP_TAC) THEN
10236     GEOM_ORIGIN_TAC `b:real^N` THEN REPEAT GEN_TAC THEN
10237     GEOM_ORIGIN_TAC `a:real^M` THEN REPEAT GEN_TAC THEN
10238     REPEAT DISCH_TAC THEN
10239     MP_TAC(ISPECL [`s:real^M->bool`; `vec 0:real^M`]
10240           STARLIKE_COMPACT_PROJECTIVE) THEN
10241     MP_TAC(ISPECL [`t:real^N->bool`; `vec 0:real^N`]
10242           STARLIKE_COMPACT_PROJECTIVE) THEN
10243     ASM_SIMP_TAC[IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT;
10244                  REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN
10245     DISCH_THEN(fun th -> MATCH_MP_TAC MONO_AND THEN MP_TAC th) THEN
10246     MATCH_MP_TAC MONO_AND THEN CONJ_TAC THEN
10247     DISCH_THEN(fun th ->
10248      MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ_ALT] HOMEOMORPHIC_TRANS) THEN
10249      MP_TAC(ONCE_REWRITE_RULE[HOMEOMORPHIC_SYM] th)) THEN
10250     MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ] HOMEOMORPHIC_TRANS) THEN
10251     REPEAT(FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP (REWRITE_RULE[SUBSET]
10252           RELATIVE_INTERIOR_SUBSET))) THEN
10253     FIRST_X_ASSUM(MP_TAC o SYM) THEN
10254     ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC; AFF_DIM_DIM_0] THEN
10255     REWRITE_TAC[INT_OF_NUM_EQ] THEN DISCH_TAC THEN
10256     MP_TAC(ISPECL [`span s:real^M->bool`; `span t:real^N->bool`]
10257             ISOMETRIES_SUBSPACES) THEN
10258     ASM_REWRITE_TAC[SUBSPACE_SPAN; DIM_SPAN; homeomorphic; HOMEOMORPHISM] THEN
10259     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^M->real^N` THEN
10260     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^M` THEN
10261     SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_CBALL_0; IN_SPHERE_0] THEN
10262     SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN ASM SET_TAC[]) in
10263   SIMP_TAC[lemma; relative_frontier] THEN REPEAT STRIP_TAC THEN
10264   MP_TAC(SPECL [`closure s:real^M->bool`; `closure t:real^N->bool`] lemma) THEN
10265   ASM_SIMP_TAC[CONVEX_CLOSURE; COMPACT_CLOSURE; AFF_DIM_CLOSURE] THEN
10266   ASM_SIMP_TAC[CONVEX_RELATIVE_INTERIOR_CLOSURE]);;
10267
10268 let HOMEOMORPHIC_CONVEX_COMPACT = prove
10269  (`!s:real^N->bool t:real^N->bool.
10270         convex s /\ compact s /\ ~(interior s = {}) /\
10271         convex t /\ compact t /\ ~(interior t = {})
10272         ==> s homeomorphic t`,
10273   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHIC_CONVEX_COMPACT_SETS THEN
10274   ASM_SIMP_TAC[AFF_DIM_NONEMPTY_INTERIOR]);;
10275
10276 let HOMEOMORPHIC_CONVEX_COMPACT_CBALL = prove
10277  (`!s:real^N->bool b:real^N e.
10278         convex s /\ compact s /\ ~(interior s = {}) /\ &0 < e
10279         ==> s homeomorphic cball(b,e)`,
10280   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHIC_CONVEX_COMPACT THEN
10281   ASM_REWRITE_TAC[COMPACT_CBALL; INTERIOR_CBALL; CONVEX_CBALL] THEN
10282   ASM_REWRITE_TAC[BALL_EQ_EMPTY; REAL_NOT_LE]);;
10283
10284 let HOMEOMORPHIC_CLOSED_INTERVALS = prove
10285  (`!a b:real^N c d:real^N.
10286         ~(interval(a,b) = {}) /\ ~(interval(c,d) = {})
10287         ==> interval[a,b] homeomorphic interval[c,d]`,
10288   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHIC_CONVEX_COMPACT THEN
10289   REWRITE_TAC[CONVEX_INTERVAL; COMPACT_INTERVAL] THEN
10290   ASM_REWRITE_TAC[INTERIOR_CLOSED_INTERVAL]);;
10291
10292 (* ------------------------------------------------------------------------- *)
10293 (* More about affine dimension of special sets.                              *)
10294 (* ------------------------------------------------------------------------- *)
10295
10296 let AFF_DIM_NONEMPTY_INTERIOR_EQ = prove
10297  (`!s:real^N->bool.
10298         convex s ==> (aff_dim s = &(dimindex (:N)) <=> ~(interior s = {}))`,
10299   REPEAT STRIP_TAC THEN EQ_TAC THEN
10300   ASM_SIMP_TAC[AFF_DIM_NONEMPTY_INTERIOR] THEN
10301   REPEAT STRIP_TAC THEN
10302   MP_TAC(ISPEC `s:real^N->bool` EMPTY_INTERIOR_SUBSET_HYPERPLANE) THEN
10303   ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
10304   FIRST_ASSUM(MP_TAC o MATCH_MP AFF_DIM_SUBSET) THEN
10305   ASM_SIMP_TAC[AFF_DIM_HYPERPLANE] THEN INT_ARITH_TAC);;
10306
10307 let AFF_DIM_BALL = prove
10308  (`!a:real^N r.
10309         aff_dim(ball(a,r)) = if &0 < r then &(dimindex(:N)) else --(&1)`,
10310   REPEAT GEN_TAC THEN COND_CASES_TAC THENL
10311    [MATCH_MP_TAC AFF_DIM_OPEN THEN
10312     ASM_REWRITE_TAC[OPEN_BALL; BALL_EQ_EMPTY; REAL_NOT_LE];
10313     RULE_ASSUM_TAC(REWRITE_RULE[REAL_NOT_LT; GSYM BALL_EQ_EMPTY]) THEN
10314     ASM_REWRITE_TAC[AFF_DIM_EMPTY]]);;
10315
10316 let AFF_DIM_CBALL = prove
10317  (`!a:real^N r.
10318         aff_dim(cball(a,r)) =
10319             if &0 < r then &(dimindex(:N))
10320             else if r = &0 then &0 else --(&1)`,
10321   REPEAT GEN_TAC THEN REPEAT COND_CASES_TAC THENL
10322    [MATCH_MP_TAC AFF_DIM_NONEMPTY_INTERIOR THEN
10323     ASM_REWRITE_TAC[INTERIOR_CBALL; BALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC;
10324     ASM_SIMP_TAC[CBALL_SING; AFF_DIM_SING];
10325     MATCH_MP_TAC(MESON[AFF_DIM_EMPTY] `s = {} ==> aff_dim s = --(&1)`) THEN
10326     REWRITE_TAC[CBALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC]);;
10327
10328 let AFF_DIM_INTERVAL = prove
10329  (`(!a b:real^N.
10330         aff_dim(interval[a,b]) =
10331                 if interval[a,b] = {} then --(&1)
10332                 else &(CARD {i | 1 <= i /\ i <= dimindex(:N) /\ a$i < b$i})) /\
10333    (!a b:real^N.
10334          aff_dim(interval(a,b)) =
10335                 if interval(a,b) = {} then --(&1)
10336                 else &(dimindex(:N)))`,
10337   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
10338   ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_OPEN; OPEN_INTERVAL] THEN
10339   POP_ASSUM MP_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN
10340   REPEAT STRIP_TAC THEN
10341   REWRITE_TAC[VECTOR_ADD_COMPONENT; VEC_COMPONENT; REAL_LT_LADD] THEN
10342   ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; ENDS_IN_INTERVAL] THEN AP_TERM_TAC THEN
10343   ONCE_REWRITE_TAC[GSYM DIM_SPAN] THEN MATCH_MP_TAC DIM_UNIQUE THEN EXISTS_TAC
10344    `{basis i:real^N | 1 <= i /\ i <= dimindex(:N) /\ &0 < (b:real^N)$i}` THEN
10345   RULE_ASSUM_TAC(REWRITE_RULE[INTERVAL_NE_EMPTY; VEC_COMPONENT]) THEN
10346   REPEAT CONJ_TAC THENL
10347    [REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
10348     X_GEN_TAC `i:num` THEN STRIP_TAC THEN
10349     SUBGOAL_THEN `basis i:real^N = inv(b$i) % (b:real^N)$i % basis i`
10350     SUBST1_TAC THENL
10351      [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_LT_IMP_NZ] THEN
10352       REWRITE_TAC[VECTOR_MUL_LID];
10353       MATCH_MP_TAC SPAN_MUL THEN MATCH_MP_TAC SPAN_SUPERSET THEN
10354       SIMP_TAC[IN_INTERVAL; VECTOR_MUL_COMPONENT; BASIS_COMPONENT] THEN
10355       X_GEN_TAC `j:num` THEN REWRITE_TAC[VEC_COMPONENT] THEN
10356       COND_CASES_TAC THEN
10357       ASM_SIMP_TAC[REAL_MUL_RZERO; REAL_MUL_RID; REAL_LE_REFL]];
10358     MATCH_MP_TAC SPAN_SUBSET_SUBSPACE THEN
10359     REWRITE_TAC[SUBSPACE_SPAN; SUBSET; IN_INTERVAL; VEC_COMPONENT] THEN
10360     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
10361     GEN_REWRITE_TAC LAND_CONV [GSYM BASIS_EXPANSION] THEN
10362     MATCH_MP_TAC SPAN_VSUM THEN REWRITE_TAC[FINITE_NUMSEG] THEN
10363     X_GEN_TAC `i:num` THEN REWRITE_TAC[IN_NUMSEG] THEN STRIP_TAC THEN
10364     ASM_CASES_TAC `&0 < (b:real^N)$i` THENL
10365      [MATCH_MP_TAC SPAN_MUL THEN MATCH_MP_TAC SPAN_SUPERSET THEN ASM SET_TAC[];
10366       SUBGOAL_THEN `(x:real^N)$i = &0`
10367         (fun th -> REWRITE_TAC[th; VECTOR_MUL_LZERO; SPAN_0]) THEN
10368       REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `i:num`)) THEN
10369       ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC];
10370     MATCH_MP_TAC PAIRWISE_ORTHOGONAL_INDEPENDENT THEN
10371     REWRITE_TAC[SET_RULE `~(a IN {f x | P x}) <=> !x. P x ==> ~(f x = a)`] THEN
10372     SIMP_TAC[BASIS_NONZERO; pairwise; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
10373     SIMP_TAC[FORALL_IN_GSPEC; BASIS_INJ_EQ; ORTHOGONAL_BASIS_BASIS];
10374     GEN_REWRITE_TAC LAND_CONV [SIMPLE_IMAGE_GEN] THEN
10375     MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN
10376     SIMP_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_GSPEC; BASIS_INJ_EQ;
10377              HAS_SIZE] THEN
10378     SIMP_TAC[CONJ_ASSOC; GSYM IN_NUMSEG; FINITE_RESTRICT; FINITE_NUMSEG]]);;
10379
10380 (* ------------------------------------------------------------------------- *)
10381 (* Deducing convexity from midpoint convexity in common cases.               *)
10382 (* ------------------------------------------------------------------------- *)
10383
10384 let MIDPOINT_CONVEX_DYADIC_RATIONALS = prove
10385  (`!f:real^N->real s.
10386         (!x y. x IN s /\ y IN s
10387                ==> midpoint(x,y) IN s /\
10388                    f(midpoint(x,y)) <= (f(x) + f(y)) / &2)
10389         ==> !n m p x y.
10390                 x IN s /\ y IN s /\ m + p = 2 EXP n
10391                 ==> (&m / &2 pow n % x + &p / &2 pow n % y) IN s /\
10392                     f(&m / &2 pow n % x + &p / &2 pow n % y)
10393                     <= &m / &2 pow n * f x + &p / &2 pow n * f y`,
10394   REPEAT GEN_TAC THEN DISCH_TAC THEN INDUCT_TAC THENL
10395    [REWRITE_TAC[ARITH_RULE
10396      `m + p = 2 EXP 0 <=> m = 0 /\ p = 1 \/ m = 1 /\ p = 0`] THEN
10397     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
10398     CONV_TAC REAL_RAT_REDUCE_CONV THEN
10399     ASM_REWRITE_TAC[VECTOR_MUL_LID; VECTOR_MUL_LZERO;
10400                   VECTOR_ADD_LID; VECTOR_ADD_RID] THEN
10401     REAL_ARITH_TAC;
10402     MATCH_MP_TAC WLOG_LE THEN CONJ_TAC THENL
10403      [REWRITE_TAC[VECTOR_ADD_SYM; REAL_ADD_SYM; ADD_SYM] THEN MESON_TAC[];
10404       ALL_TAC] THEN
10405     MAP_EVERY X_GEN_TAC [`m:num`; `p:num`] THEN DISCH_TAC THEN
10406     REPEAT GEN_TAC THEN REWRITE_TAC[EXP; real_pow] THEN STRIP_TAC THEN
10407     REWRITE_TAC[real_div; REAL_INV_MUL] THEN
10408     ONCE_REWRITE_TAC[REAL_ARITH `x * inv(&2) * y = inv(&2) * x * y`] THEN
10409     ONCE_REWRITE_TAC[GSYM REAL_MUL_ASSOC; GSYM VECTOR_MUL_ASSOC] THEN
10410     REWRITE_TAC[GSYM REAL_ADD_LDISTRIB; GSYM VECTOR_ADD_LDISTRIB] THEN
10411     SUBGOAL_THEN `2 EXP n <= p` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
10412     SUBGOAL_THEN `&p * inv(&2 pow n) = &(p - 2 EXP n) * inv(&2 pow n) + &1`
10413     SUBST1_TAC THENL
10414      [ASM_SIMP_TAC[GSYM REAL_OF_NUM_SUB; GSYM REAL_OF_NUM_POW] THEN
10415       ASM_SIMP_TAC[REAL_SUB_RDISTRIB; REAL_MUL_RINV; REAL_LT_IMP_NZ;
10416                    REAL_LT_POW2] THEN REAL_ARITH_TAC;
10417       REWRITE_TAC[VECTOR_ADD_RDISTRIB; REAL_ADD_RDISTRIB] THEN
10418       REWRITE_TAC[VECTOR_MUL_LID; REAL_MUL_LID] THEN
10419       REWRITE_TAC[VECTOR_ADD_ASSOC; REAL_ADD_ASSOC] THEN
10420       REWRITE_TAC[GSYM midpoint; GSYM real_div] THEN FIRST_X_ASSUM(fun th ->
10421         W(MP_TAC o PART_MATCH (lhand o rand) th o lhand o snd)) THEN
10422       FIRST_X_ASSUM(fun th ->
10423         W(MP_TAC o PART_MATCH (lhand o rand) th o funpow 3 lhand o  snd)) THEN
10424       ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
10425        [ASM_ARITH_TAC; SIMP_TAC[] THEN REAL_ARITH_TAC]]]);;
10426
10427 let CONTINUOUS_MIDPOINT_CONVEX = prove
10428  (`!f:real^N->real s.
10429         (lift o f) continuous_on s /\ convex s /\
10430         (!x y. x IN s /\ y IN s ==> f(midpoint(x,y)) <= (f(x) + f(y)) / &2)
10431          ==> f convex_on s`,
10432   REWRITE_TAC[midpoint] THEN REPEAT STRIP_TAC THEN REWRITE_TAC[convex_on] THEN
10433   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
10434   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[GSYM IMP_CONJ_ALT] THEN
10435   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
10436   REWRITE_TAC[REAL_ARITH `u + v = &1 <=> v = &1 - u`; IMP_CONJ] THEN
10437   REWRITE_TAC[FORALL_UNWIND_THM2; REAL_SUB_LE] THEN
10438   REWRITE_TAC[FORALL_DROP; GSYM DROP_VEC; IMP_IMP; GSYM IN_INTERVAL_1] THEN
10439   MP_TAC(ISPEC `interval[vec 0:real^1,vec 1]`
10440         CLOSURE_DYADIC_RATIONALS_IN_CONVEX_SET) THEN
10441   SIMP_TAC[CONVEX_INTERVAL; INTERIOR_CLOSED_INTERVAL;
10442            CLOSURE_CLOSED; CLOSED_INTERVAL; UNIT_INTERVAL_NONEMPTY] THEN
10443   REWRITE_TAC[DIMINDEX_1; FORALL_1; GSYM drop] THEN
10444   DISCH_THEN(fun th -> SUBST1_TAC(SYM th) THEN ASSUME_TAC th) THEN
10445   ONCE_REWRITE_TAC[REAL_ARITH `a <= b <=> a - b <= &0`] THEN
10446   MATCH_MP_TAC CONTINUOUS_LE_ON_CLOSURE THEN
10447   REWRITE_TAC[IN_INTER; IMP_CONJ_ALT; FORALL_IN_GSPEC] THEN
10448   FIRST_X_ASSUM SUBST1_TAC THEN
10449   REWRITE_TAC[IN_INTERVAL_1; DROP_CMUL; GSYM FORALL_DROP; DROP_VEC] THEN
10450   CONJ_TAC THENL
10451    [REWRITE_TAC[o_DEF; LIFT_SUB; LIFT_ADD; LIFT_CMUL] THEN
10452     MATCH_MP_TAC CONTINUOUS_ON_SUB THEN CONJ_TAC THENL
10453      [REPLICATE_TAC 2 (ONCE_REWRITE_TAC[GSYM o_DEF]) THEN
10454       REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
10455       CONJ_TAC THENL
10456        [ALL_TAC;
10457         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10458           CONTINUOUS_ON_SUBSET)) THEN
10459         REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1; GSYM FORALL_DROP;
10460                     DROP_VEC] THEN REPEAT STRIP_TAC THEN
10461         FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [convex]) THEN
10462         ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC];
10463       ALL_TAC] THEN
10464     MATCH_MP_TAC CONTINUOUS_ON_ADD THEN CONJ_TAC THEN
10465     MATCH_MP_TAC CONTINUOUS_ON_MUL THEN
10466     SIMP_TAC[o_DEF; LIFT_DROP; CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST;
10467              LIFT_SUB; CONTINUOUS_ON_SUB];
10468     MAP_EVERY X_GEN_TAC [`n:num`; `i:real`] THEN
10469     ASM_SIMP_TAC[REAL_LE_MUL_EQ; REAL_LT_INV_EQ; REAL_LT_POW2] THEN
10470     ASM_CASES_TAC `&0 <= i` THEN ASM_SIMP_TAC[INTEGER_POS] THEN
10471     DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST_ALL_TAC) THEN
10472     REWRITE_TAC[ONCE_REWRITE_RULE[REAL_MUL_SYM] (GSYM real_div)] THEN
10473     SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LT_POW2; REAL_MUL_LID] THEN
10474     GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV)
10475      [REAL_OF_NUM_POW; REAL_OF_NUM_LE] THEN DISCH_TAC THEN
10476     MP_TAC(ISPECL [`f:real^N->real`; `s:real^N->bool`]
10477         MIDPOINT_CONVEX_DYADIC_RATIONALS) THEN
10478     ANTS_TAC THENL
10479      [ASM_SIMP_TAC[midpoint] THEN REWRITE_TAC[VECTOR_ADD_LDISTRIB] THEN
10480       REPEAT STRIP_TAC THEN
10481       FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [convex]) THEN
10482       ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
10483       DISCH_THEN(MP_TAC o SPECL
10484        [`n:num`; `m:num`; `2 EXP n - m`; `x:real^N`; `y:real^N`]) THEN
10485       ASM_REWRITE_TAC[] THEN
10486       ANTS_TAC THENL [ASM_ARITH_TAC; DISCH_THEN(MP_TAC o CONJUNCT2)] THEN
10487       ASM_SIMP_TAC[GSYM REAL_OF_NUM_SUB; GSYM REAL_OF_NUM_POW] THEN
10488       ASM_SIMP_TAC[REAL_LT_POW2; REAL_FIELD
10489        `&0 < y ==> (y - x) / y = &1 - x / y`] THEN
10490       REAL_ARITH_TAC]]);;
10491
10492 (* ------------------------------------------------------------------------- *)
10493 (* Slightly shaper separating/supporting hyperplane results.                 *)
10494 (* ------------------------------------------------------------------------- *)
10495
10496 let SEPARATING_HYPERPLANE_RELATIVE_INTERIORS = prove
10497  (`!s t. convex s /\ convex t /\
10498          ~(s = {} /\ t = (:real^N) \/ s = (:real^N) /\ t = {}) /\
10499          DISJOINT (relative_interior s) (relative_interior t)
10500          ==> ?a b. ~(a = vec 0) /\
10501                    (!x. x IN s ==> a dot x <= b) /\
10502                    (!x. x IN t ==> a dot x >= b)`,
10503   REPEAT GEN_TAC THEN MAP_EVERY ASM_CASES_TAC
10504    [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
10505   ASM_REWRITE_TAC[NOT_IN_EMPTY; UNIV_NOT_EMPTY; CONVEX_EMPTY;
10506                   RELATIVE_INTERIOR_EMPTY] THEN
10507   STRIP_TAC THENL
10508    [EXISTS_TAC `basis 1:real^N` THEN
10509     SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL];
10510     FIRST_X_ASSUM(X_CHOOSE_TAC `x:real^N` o MATCH_MP (SET_RULE
10511      `~(s = UNIV) ==> ?a. ~(a IN s)`)) THEN
10512     MP_TAC(ISPECL [`t:real^N->bool`; `x:real^N`]
10513         SEPARATING_HYPERPLANE_SET_POINT_INAFF) THEN
10514     ASM_MESON_TAC[];
10515     FIRST_X_ASSUM(X_CHOOSE_TAC `x:real^N` o MATCH_MP (SET_RULE
10516      `~(s = UNIV) ==> ?a. ~(a IN s)`)) THEN
10517     MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`]
10518         SEPARATING_HYPERPLANE_SET_POINT_INAFF) THEN
10519     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; real_ge] THEN
10520     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN STRIP_TAC THEN
10521     MAP_EVERY EXISTS_TAC [`--a:real^N`; `--b:real`] THEN
10522     ASM_REWRITE_TAC[VECTOR_NEG_EQ_0; DOT_LNEG; REAL_LE_NEG2];
10523     MP_TAC(ISPECL [`relative_interior s:real^N->bool`;
10524                    `relative_interior t:real^N->bool`]
10525           SEPARATING_HYPERPLANE_SETS) THEN
10526     ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY; CONVEX_RELATIVE_INTERIOR] THEN
10527     SIMP_TAC[real_ge] THEN MATCH_MP_TAC MONO_EXISTS THEN
10528     X_GEN_TAC `a:real^N` THEN MATCH_MP_TAC MONO_EXISTS THEN
10529     X_GEN_TAC `b:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
10530     CONJ_TAC THEN MATCH_MP_TAC
10531     (MESON[CONVEX_CLOSURE_RELATIVE_INTERIOR; CLOSURE_SUBSET; SUBSET]
10532       `convex s /\ (!x. x IN closure(relative_interior s) ==> P x)
10533        ==> !x. x IN s ==> P x`) THEN
10534     ASM_REWRITE_TAC[] THENL
10535      [MATCH_MP_TAC CONTINUOUS_LE_ON_CLOSURE;
10536       MATCH_MP_TAC CONTINUOUS_GE_ON_CLOSURE] THEN
10537     ASM_REWRITE_TAC[CONTINUOUS_ON_LIFT_DOT]]);;
10538
10539 let SUPPORTING_HYPERPLANE_RELATIVE_BOUNDARY = prove
10540  (`!s x:real^N.
10541         convex s /\ x IN s /\ ~(x IN relative_interior s)
10542         ==> ?a. ~(a = vec 0) /\
10543                 (!y. y IN s ==> a dot x <= a dot y) /\
10544                 (!y. y IN relative_interior s ==> a dot x < a dot y)`,
10545   REPEAT STRIP_TAC THEN
10546   MP_TAC(ISPECL [`relative_interior s:real^N->bool`; `x:real^N`]
10547         SEPARATING_HYPERPLANE_SET_POINT_INAFF) THEN
10548   ASM_SIMP_TAC[CONVEX_SING; CONVEX_RELATIVE_INTERIOR;
10549                RELATIVE_INTERIOR_EQ_EMPTY; real_ge] THEN
10550   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10551   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
10552   REWRITE_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY] THEN
10553   DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THEN ASM_SIMP_TAC[] THEN
10554   MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
10555    [X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
10556     MP_TAC(ISPECL [`lift o (\x:real^N. a dot x)`;
10557                    `relative_interior s:real^N->bool`;
10558                    `y:real^N`; `(a:real^N) dot x`; `1`]
10559       CONTINUOUS_ON_CLOSURE_COMPONENT_GE) THEN
10560     REWRITE_TAC[CONTINUOUS_ON_LIFT_DOT; GSYM drop; o_THM; LIFT_DROP] THEN
10561     ASM_SIMP_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR] THEN
10562     ASM_MESON_TAC[CLOSURE_SUBSET; REAL_LE_TRANS; SUBSET];
10563     DISCH_TAC] THEN
10564   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
10565   REWRITE_TAC[REAL_LT_LE] THEN CONJ_TAC THENL
10566    [ASM_MESON_TAC[REAL_LE_TRANS]; ALL_TAC] THEN
10567   DISCH_TAC THEN UNDISCH_TAC `(y:real^N) IN relative_interior s` THEN
10568   REWRITE_TAC[IN_RELATIVE_INTERIOR_CBALL] THEN
10569   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
10570   REWRITE_TAC[LEFT_IMP_EXISTS_THM; SUBSET; IN_INTER; IN_CBALL] THEN
10571   X_GEN_TAC `e:real` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
10572   DISCH_THEN(MP_TAC o SPEC `y + --(e / norm(a)) % ((x + a) - x):real^N`) THEN
10573   REWRITE_TAC[NOT_IMP] THEN REPEAT CONJ_TAC THENL
10574    [SIMP_TAC[NORM_ARITH `dist(y:real^N,y + e) = norm e`; VECTOR_ADD_SUB] THEN
10575     REWRITE_TAC[NORM_MUL; REAL_ABS_NEG; REAL_ABS_DIV; REAL_ABS_NORM] THEN
10576     ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN ASM_REAL_ARITH_TAC;
10577     MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
10578     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC] THEN
10579     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
10580      `x IN s ==> s SUBSET t ==> x IN t`)) THEN
10581     MATCH_MP_TAC HULL_MONO THEN
10582     ASM_REWRITE_TAC[INSERT_SUBSET; RELATIVE_INTERIOR_SUBSET];
10583     REWRITE_TAC[VECTOR_ADD_SUB] THEN DISCH_TAC THEN
10584     UNDISCH_TAC `!y:real^N. y IN s ==> a dot x <= a dot y` THEN
10585     DISCH_THEN(MP_TAC o SPEC `y + --(e / norm(a)) % a:real^N`) THEN
10586     ASM_REWRITE_TAC[DOT_RMUL; DOT_RNEG; DOT_RADD] THEN
10587     MATCH_MP_TAC(REAL_ARITH `&0 < x * y ==> ~(a <= a + --x * y)`) THEN
10588     ASM_SIMP_TAC[REAL_LT_MUL; REAL_LT_DIV; NORM_POS_LT; DOT_POS_LT]]);;
10589
10590 let SUPPORTING_HYPERPLANE_RELATIVE_FRONTIER = prove
10591  (`!s x:real^N.
10592         convex s /\ x IN closure s /\ ~(x IN relative_interior s)
10593         ==> ?a. ~(a = vec 0) /\
10594                 (!y. y IN closure s ==> a dot x <= a dot y) /\
10595                 (!y. y IN relative_interior s ==> a dot x < a dot y)`,
10596   REPEAT STRIP_TAC THEN
10597   MP_TAC(ISPECL [`closure s:real^N->bool`; `x:real^N`]
10598     SUPPORTING_HYPERPLANE_RELATIVE_BOUNDARY) THEN
10599   ASM_SIMP_TAC[CONVEX_CLOSURE; CONVEX_RELATIVE_INTERIOR_CLOSURE]);;
10600
10601 (* ------------------------------------------------------------------------- *)
10602 (* Containment of rays in unbounded convex sets.                             *)
10603 (* ------------------------------------------------------------------------- *)
10604
10605 let UNBOUNDED_CONVEX_CLOSED_CONTAINS_RAY = prove
10606  (`!s a:real^N.
10607         convex s /\ ~bounded s /\ closed s /\ a IN s
10608         ==> ?l. ~(l = vec 0) /\ !t. &0 <= t ==> (a + t % l) IN s`,
10609   GEN_GEOM_ORIGIN_TAC `a:real^N` ["l"] THEN
10610   REWRITE_TAC[VECTOR_ADD_LID] THEN REPEAT STRIP_TAC THEN
10611   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [BOUNDED_POS]) THEN
10612   REWRITE_TAC[NOT_EXISTS_THM; TAUT `~(p /\ q) <=> p ==> ~q`] THEN
10613   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC `&n + &1:real`) THEN
10614   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; REAL_ARITH `&0 < &n + &1`] THEN
10615   REWRITE_TAC[REAL_NOT_LE; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
10616   X_GEN_TAC `x:num->real^N` THEN REWRITE_TAC[FORALL_AND_THM] THEN
10617   STRIP_TAC THEN
10618   SUBGOAL_THEN `!n. ~((x:num->real^N) n = vec 0)` ASSUME_TAC THENL
10619    [ASM_MESON_TAC[NORM_ARITH `~(&n + &1 < norm(vec 0:real^N))`]; ALL_TAC] THEN
10620   MP_TAC(ISPEC `sphere(vec 0:real^N,&1)` compact) THEN
10621   REWRITE_TAC[COMPACT_SPHERE] THEN
10622   DISCH_THEN(MP_TAC o SPEC `\n. inv(norm(x n)) % (x:num->real^N) n`) THEN
10623   ASM_SIMP_TAC[IN_SPHERE_0; NORM_MUL; REAL_ABS_INV; REAL_ABS_NORM;
10624                REAL_MUL_LINV; NORM_EQ_0; o_DEF] THEN
10625   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real^N` THEN
10626   DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN CONJ_TAC THENL
10627    [ASM_MESON_TAC[NORM_ARITH `~(norm(vec 0:real^N) = &1)`]; ALL_TAC] THEN
10628   X_GEN_TAC `t:real` THEN DISCH_TAC THEN
10629   MATCH_MP_TAC CLOSED_CONTAINS_SEQUENTIAL_LIMIT THEN
10630   SUBGOAL_THEN
10631    `?N:num. !n. N <= n ==> t / norm(x n:real^N) <= &1`
10632   STRIP_ASSUME_TAC THENL
10633    [ASM_SIMP_TAC[REAL_LE_LDIV_EQ; NORM_POS_LT] THEN
10634     MP_TAC(SPEC `t:real` REAL_ARCH_SIMPLE) THEN
10635     MATCH_MP_TAC MONO_EXISTS THEN
10636     REWRITE_TAC[GSYM REAL_OF_NUM_LE; REAL_MUL_LID] THEN
10637     ASM_MESON_TAC[REAL_ARITH `t <= m /\ m <= n /\ n + &1 < x ==> t <= x`];
10638     EXISTS_TAC `\n:num. t / norm((x:num->real^N)(r(N + n))) % x(r(N + n))` THEN
10639     ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
10640      [X_GEN_TAC `n:num` THEN
10641       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
10642       DISCH_THEN(MP_TAC o SPEC `vec 0:real^N`) THEN
10643       ASM_REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
10644       DISCH_THEN MATCH_MP_TAC THEN ASM_SIMP_TAC[REAL_LE_DIV; NORM_POS_LE] THEN
10645       FIRST_X_ASSUM MATCH_MP_TAC THEN
10646       FIRST_ASSUM(MP_TAC o SPEC `N + n:num` o MATCH_MP MONOTONE_BIGGER) THEN
10647       ARITH_TAC;
10648       REWRITE_TAC[real_div; GSYM VECTOR_MUL_ASSOC] THEN
10649       MATCH_MP_TAC LIM_CMUL THEN ONCE_REWRITE_TAC[ADD_SYM] THEN
10650       FIRST_ASSUM(MP_TAC o SPEC `N:num` o MATCH_MP SEQ_OFFSET) THEN
10651       ASM_REWRITE_TAC[]]]);;
10652
10653 let CONVEX_CLOSED_CONTAINS_SAME_RAY = prove
10654  (`!s a b l:real^N.
10655         convex s /\ closed s /\ b IN s /\ (!t. &0 <= t ==> (a + t % l) IN s)
10656         ==> !t. &0 <= t ==> (b + t % l) IN s`,
10657   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `&0`) THEN
10658   REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_RID] THEN DISCH_TAC THEN
10659   MATCH_MP_TAC(ISPEC `sequentially` LIM_IN_CLOSED_SET) THEN
10660   EXISTS_TAC `\n. (&1 - t / (&n + &1)) % b +
10661                   t / (&n + &1) % (a + (&n + &1) % l):real^N` THEN
10662   ASM_REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY] THEN CONJ_TAC THENL
10663    [REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
10664     MP_TAC(SPEC `t:real` REAL_ARCH_SIMPLE) THEN
10665     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
10666     DISCH_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
10667     FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
10668     ASM_SIMP_TAC[REAL_LE_DIV; REAL_ARITH `&0 <= &n + &1`] THEN
10669     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
10670     RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC;
10671     REWRITE_TAC[VECTOR_ARITH
10672      `(&1 - u) % b + u % c:real^N = b + u % (c - b)`] THEN
10673     MATCH_MP_TAC LIM_ADD THEN REWRITE_TAC[LIM_CONST] THEN
10674     REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_SUB_LDISTRIB] THEN
10675     SIMP_TAC[VECTOR_MUL_ASSOC; REAL_FIELD `t / (&n + &1) * (&n + &1) = t`] THEN
10676     SIMP_TAC[VECTOR_ARITH `(v % a + b) - v % c:real^N = b + v % (a - c)`] THEN
10677     GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_ADD_RID] THEN
10678     MATCH_MP_TAC LIM_ADD THEN REWRITE_TAC[LIM_CONST] THEN
10679     REWRITE_TAC[real_div; VECTOR_ARITH `(x * y) % a:real^N = y % x % a`] THEN
10680     MATCH_MP_TAC LIM_NULL_VMUL_BOUNDED THEN
10681     EXISTS_TAC `norm(t % (a - b):real^N)` THEN
10682     REWRITE_TAC[REAL_LE_REFL; EVENTUALLY_TRUE; o_DEF] THEN
10683     MP_TAC(MATCH_MP SEQ_OFFSET SEQ_HARMONIC) THEN
10684     SIMP_TAC[REAL_OF_NUM_ADD]]);;
10685
10686 let UNBOUNDED_CONVEX_CLOSED_CONTAINS_RAYS = prove
10687  (`!s:real^N->bool.
10688         convex s /\ ~bounded s /\ closed s
10689         ==> ?l. ~(l = vec 0) /\ !a t. a IN s /\ &0 <= t ==> (a + t % l) IN s`,
10690   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
10691   ASM_REWRITE_TAC[BOUNDED_EMPTY] THEN
10692   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
10693   ASM_MESON_TAC[UNBOUNDED_CONVEX_CLOSED_CONTAINS_RAY;
10694                 CONVEX_CLOSED_CONTAINS_SAME_RAY]);;
10695
10696 let RELATIVE_INTERIOR_UNBOUNDED_CONVEX_CONTAINS_RAY = prove
10697  (`!s a:real^N.
10698         convex s /\ ~bounded s /\ a IN relative_interior s
10699         ==> ?l. ~(l = vec 0) /\
10700                 !t. &0 <= t ==> (a + t % l) IN relative_interior s`,
10701   REPEAT STRIP_TAC THEN
10702   MP_TAC(ISPECL [`closure s:real^N->bool`; `a:real^N`]
10703         UNBOUNDED_CONVEX_CLOSED_CONTAINS_RAY) THEN
10704   ASM_SIMP_TAC[CONVEX_CLOSURE; CLOSED_CLOSURE] THEN ANTS_TAC THENL
10705    [ASM_MESON_TAC[BOUNDED_SUBSET; SUBSET; CLOSURE_SUBSET;
10706                   RELATIVE_INTERIOR_SUBSET];
10707     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real^N` THEN STRIP_TAC THEN
10708     ASM_REWRITE_TAC[] THEN
10709     ONCE_REWRITE_TAC[VECTOR_ARITH
10710       `a + t % l:real^N =
10711        (a + (&2 * t) % l) - inv(&2) % ((a + (&2 * t) % l) - a)`] THEN
10712     REPEAT STRIP_TAC THEN
10713     MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
10714     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN
10715     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC]);;
10716
10717 let RELATIVE_INTERIOR_CONVEX_CONTAINS_SAME_RAY = prove
10718  (`!s a b l:real^N.
10719         convex s /\ b IN relative_interior s /\
10720         (!t. &0 <= t ==> (a + t % l) IN relative_interior s)
10721         ==> !t. &0 <= t ==> (b + t % l) IN relative_interior s`,
10722   REPEAT STRIP_TAC THEN
10723   MP_TAC(ISPECL [`closure s:real^N->bool`; `a:real^N`; `b:real^N`; `l:real^N`]
10724         CONVEX_CLOSED_CONTAINS_SAME_RAY) THEN
10725   ASM_SIMP_TAC[CONVEX_CLOSURE; CLOSED_CLOSURE] THEN ANTS_TAC THENL
10726    [ASM_MESON_TAC[BOUNDED_SUBSET; SUBSET; CLOSURE_SUBSET;
10727                   RELATIVE_INTERIOR_SUBSET];
10728     DISCH_TAC THEN
10729     ONCE_REWRITE_TAC[VECTOR_ARITH
10730       `a + t % l:real^N =
10731        (a + (&2 * t) % l) - inv(&2) % ((a + (&2 * t) % l) - a)`] THEN
10732     REPEAT STRIP_TAC THEN
10733     MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
10734     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN
10735     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC]);;
10736
10737 let RELATIVE_INTERIOR_UNBOUNDED_CONVEX_CONTAINS_RAYS = prove
10738  (`!s:real^N->bool.
10739         convex s /\ ~bounded s
10740         ==> ?l. ~(l = vec 0) /\
10741                 !a t. a IN relative_interior s /\ &0 <= t
10742                       ==> (a + t % l) IN relative_interior s`,
10743   REPEAT GEN_TAC THEN
10744   ASM_CASES_TAC `relative_interior s:real^N->bool = {}` THENL
10745    [ASM_MESON_TAC[RELATIVE_INTERIOR_EQ_EMPTY; BOUNDED_EMPTY]; ALL_TAC] THEN
10746   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
10747   ASM_MESON_TAC[RELATIVE_INTERIOR_UNBOUNDED_CONVEX_CONTAINS_RAY;
10748                 RELATIVE_INTERIOR_CONVEX_CONTAINS_SAME_RAY]);;
10749
10750 (* ------------------------------------------------------------------------- *)
10751 (* Explicit formulas for interior and relative interior of convex hull.      *)
10752 (* ------------------------------------------------------------------------- *)
10753
10754 let EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL = prove
10755  (`!s. FINITE s
10756        ==> {y:real^N | ?u. (!x. x IN s ==> &0 < u x /\ u x < &1) /\
10757                            sum s u = &1 /\
10758                            vsum s (\x. u x % x) = y}
10759        SUBSET relative_interior(convex hull s)`,
10760   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
10761   ASM_REWRITE_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH_EQ] THEN
10762   REWRITE_TAC[EMPTY_GSPEC; EMPTY_SUBSET] THEN
10763   REPEAT STRIP_TAC THEN MATCH_MP_TAC RELATIVE_INTERIOR_MAXIMAL THEN
10764   REWRITE_TAC[AFFINE_HULL_CONVEX_HULL] THEN CONJ_TAC THENL
10765    [REWRITE_TAC[CONVEX_HULL_FINITE; SUBSET; IN_ELIM_THM] THEN
10766     GEN_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[REAL_LT_IMP_LE];
10767     ALL_TAC] THEN
10768   REWRITE_TAC[open_in; IN_ELIM_THM] THEN CONJ_TAC THENL
10769    [REWRITE_TAC[AFFINE_HULL_FINITE; SUBSET; IN_ELIM_THM] THEN
10770     GEN_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[REAL_LT_IMP_LE];
10771     ALL_TAC] THEN
10772   X_GEN_TAC `y:real^N` THEN
10773   DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC) THEN
10774   ABBREV_TAC `e = inf (IMAGE (\x:real^N. min (&1 - u x) (u x)) s)` THEN
10775   SUBGOAL_THEN `&0 < e` ASSUME_TAC THENL
10776    [EXPAND_TAC "e" THEN
10777     ASM_SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
10778     ASM_SIMP_TAC[REAL_LT_MIN; REAL_SUB_LT; FORALL_IN_IMAGE];
10779     ALL_TAC] THEN
10780   MP_TAC(ISPEC `IMAGE (\z:real^N. z - y) (affine hull s)` BASIS_EXISTS) THEN
10781   REWRITE_TAC[SUBSET_IMAGE] THEN
10782   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool`
10783    (CONJUNCTS_THEN2 (X_CHOOSE_THEN `c:real^N->bool` (STRIP_ASSUME_TAC o GSYM))
10784                     MP_TAC)) THEN
10785   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; HAS_SIZE] THEN
10786   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
10787   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
10788   ASM_SIMP_TAC[SPAN_FINITE; IN_ELIM_THM] THEN
10789   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
10790   REWRITE_TAC[SKOLEM_THM] THEN
10791   DISCH_THEN(X_CHOOSE_TAC `compo:real^N->real^N->real`) THEN
10792   FIRST_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o
10793     MATCH_MP BASIS_COORDINATES_LIPSCHITZ) THEN
10794   SUBGOAL_THEN
10795    `!i. i IN b ==> ?u. sum s u = &0 /\ vsum s (\x:real^N. u x % x) = i`
10796   MP_TAC THENL
10797    [EXPAND_TAC "b" THEN REWRITE_TAC[FORALL_IN_IMAGE] THEN
10798     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
10799     SUBGOAL_THEN `(x:real^N) IN affine hull s` MP_TAC THENL
10800      [ASM SET_TAC[]; REWRITE_TAC[AFFINE_HULL_FINITE; IN_ELIM_THM]] THEN
10801     DISCH_THEN(X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC) THEN
10802     EXISTS_TAC `(\x. v x - u x):real^N->real` THEN
10803     ASM_SIMP_TAC[SUM_SUB; VSUM_SUB; VECTOR_SUB_RDISTRIB] THEN
10804     REWRITE_TAC[REAL_SUB_REFL; VECTOR_SUB_RZERO];
10805     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
10806      [RIGHT_IMP_EXISTS_THM; SKOLEM_THM; FORALL_AND_THM;
10807                 TAUT `(a ==> b /\ c) <=> (a ==> b) /\ (a ==> c)`] THEN
10808     DISCH_THEN(X_CHOOSE_THEN `w:real^N->real^N->real` STRIP_ASSUME_TAC)] THEN
10809   EXISTS_TAC `e / B /
10810               (&1 + sum (b:real^N->bool)
10811                    (\i. abs(sup(IMAGE (abs o w i) (s:real^N->bool)))))` THEN
10812   ASM_SIMP_TAC[REAL_LT_DIV; REAL_ARITH `&0 <= x ==> &0 < &1 + x`;
10813                SUM_POS_LE; REAL_ABS_POS] THEN
10814   X_GEN_TAC `z:real^N` THEN STRIP_TAC THEN
10815   EXISTS_TAC
10816    `\x:real^N. u x + sum (b:real^N->bool)
10817                          (\i. compo (z:real^N) i * w i x)` THEN
10818   REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
10819    [ALL_TAC;
10820     ASM_SIMP_TAC[SUM_ADD; REAL_ARITH `&1 + x = &1 <=> x = &0`] THEN
10821     W(MP_TAC o PART_MATCH (lhs o rand) SUM_SWAP o lhand o snd) THEN
10822     ASM_REWRITE_TAC[FINITE_NUMSEG] THEN DISCH_THEN SUBST1_TAC THEN
10823     MATCH_MP_TAC SUM_EQ_0 THEN
10824     ASM_SIMP_TAC[SUM_LMUL; ETA_AX; REAL_MUL_RZERO; SUM_0];
10825     ASM_SIMP_TAC[VSUM_ADD; VECTOR_ADD_RDISTRIB] THEN
10826     ONCE_REWRITE_TAC[VECTOR_ARITH `y + w:real^N = z <=> w = z - y`] THEN
10827     ASM_SIMP_TAC[GSYM VSUM_LMUL; GSYM VSUM_RMUL; GSYM VECTOR_MUL_ASSOC] THEN
10828     W(MP_TAC o PART_MATCH (lhs o rand) VSUM_SWAP o lhand o snd) THEN
10829     ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST1_TAC THEN
10830     ASM_SIMP_TAC[VSUM_LMUL] THEN MATCH_MP_TAC EQ_TRANS THEN
10831     EXISTS_TAC `vsum b (\v:real^N. compo (z:real^N) v % v)` THEN
10832     CONJ_TAC THENL [ALL_TAC; ASM_SIMP_TAC[]] THEN
10833     MATCH_MP_TAC VSUM_EQ THEN ASM_SIMP_TAC[]] THEN
10834   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[] THEN
10835   MATCH_MP_TAC(REAL_ARITH
10836    `abs(x) < min u (&1 - u) ==> &0 < u + x /\ u + x < &1`) THEN
10837   MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC
10838     `B * norm(z - y:real^N) * sum (b:real^N->bool)
10839                    (\i. abs(sup(IMAGE (abs o w i) (s:real^N->bool))))` THEN
10840   CONJ_TAC THENL
10841    [REWRITE_TAC[GSYM SUM_LMUL] THEN MATCH_MP_TAC SUM_ABS_LE THEN
10842     ASM_REWRITE_TAC[REAL_ABS_MUL; REAL_MUL_ASSOC] THEN
10843     X_GEN_TAC `i:real^N` THEN STRIP_TAC THEN MATCH_MP_TAC REAL_LE_MUL2 THEN
10844     REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL
10845      [FIRST_X_ASSUM(MP_TAC o SPECL [`(compo:real^N->real^N->real) z`;
10846                                   `i:real^N`]) THEN
10847       ASM_SIMP_TAC[];
10848       MATCH_MP_TAC(REAL_ARITH `x <= a ==> x <= abs a`) THEN
10849       ASM_SIMP_TAC[REAL_LE_SUP_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
10850       REWRITE_TAC[EXISTS_IN_IMAGE; o_THM] THEN ASM_MESON_TAC[REAL_LE_REFL]];
10851     ALL_TAC] THEN
10852   GEN_REWRITE_TAC LAND_CONV [REAL_MUL_SYM] THEN
10853   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ] THEN
10854   MATCH_MP_TAC(REAL_ARITH
10855    `&0 <= x /\ x * (&1 + e) < d ==> x * e < d`) THEN
10856   REWRITE_TAC[NORM_POS_LE] THEN
10857   ASM_SIMP_TAC[NORM_POS_LE; GSYM REAL_LT_RDIV_EQ;
10858                REAL_ARITH `&0 <= x ==> &0 < &1 + x`;
10859                SUM_POS_LE; REAL_ABS_POS] THEN
10860   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (NORM_ARITH
10861    `dist(z:real^N,y) < k ==> k <= d ==> norm(z - y) < d`)) THEN
10862   ASM_SIMP_TAC[REAL_LE_DIV2_EQ; REAL_ARITH `&0 <= x ==> &0 < &1 + x`;
10863                SUM_POS_LE; REAL_ABS_POS] THEN
10864   EXPAND_TAC "e" THEN
10865   ASM_SIMP_TAC[REAL_INF_LE_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
10866   REWRITE_TAC[EXISTS_IN_IMAGE] THEN EXISTS_TAC `x:real^N` THEN
10867   ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
10868
10869 let EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL_MINIMAL = prove
10870  (`!s. FINITE s
10871        ==> {y:real^N | ?u. (!x. x IN s ==> &0 < u x) /\
10872                            sum s u = &1 /\
10873                            vsum s (\x. u x % x) = y}
10874        SUBSET relative_interior(convex hull s)`,
10875   REPEAT STRIP_TAC THEN
10876   ASM_CASES_TAC `s:real^N->bool = {}` THEN
10877   ASM_REWRITE_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH_EQ] THEN
10878   REWRITE_TAC[EMPTY_GSPEC; EMPTY_SUBSET] THEN
10879   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
10880   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
10881   ASM_CASES_TAC `s = {a:real^N}` THENL
10882    [ASM_REWRITE_TAC[SUM_SING; VSUM_SING; FORALL_IN_INSERT; NOT_IN_EMPTY] THEN
10883     REWRITE_TAC[RELATIVE_INTERIOR_SING; CONVEX_HULL_SING] THEN
10884     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_SING] THEN
10885     MESON_TAC[VECTOR_MUL_LID];
10886     FIRST_ASSUM(MP_TAC o MATCH_MP
10887       EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL) THEN
10888     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] SUBSET_TRANS) THEN
10889     REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `w:real^N` THEN
10890     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^N->real` THEN
10891     STRIP_TAC THEN ASM_SIMP_TAC[] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
10892     SUBGOAL_THEN `?y:real^N. y IN s /\ ~(y = x)` STRIP_ASSUME_TAC THENL
10893      [ASM SET_TAC[]; ALL_TAC] THEN
10894     SUBGOAL_THEN `sum {x,y} u <= sum s (u:real^N->real)` MP_TAC THENL
10895      [MATCH_MP_TAC SUM_SUBSET_SIMPLE THEN
10896       ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE; REAL_LT_IMP_LE; IN_DIFF] THEN
10897       ASM SET_TAC[];
10898       ASM_SIMP_TAC[SUM_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
10899       ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
10900       MATCH_MP_TAC(REAL_ARITH `&0 < y ==> x + y + &0 <= &1 ==> x < &1`) THEN
10901       ASM_SIMP_TAC[]]]);;
10902
10903 let RELATIVE_INTERIOR_CONVEX_HULL_EXPLICIT = prove
10904  (`!s. ~(affine_dependent s)
10905        ==> relative_interior(convex hull s) =
10906              {y:real^N | ?u. (!x. x IN s ==> &0 < u x) /\
10907                              sum s u = &1 /\
10908                              vsum s (\x. u x % x) = y}`,
10909   REPEAT STRIP_TAC THEN
10910   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
10911   MATCH_MP_TAC SUBSET_ANTISYM THEN
10912   ASM_SIMP_TAC[EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL_MINIMAL] THEN
10913   ASM_CASES_TAC `?a:real^N. s = {a}` THENL
10914    [FIRST_X_ASSUM(CHOOSE_THEN SUBST1_TAC) THEN
10915     ASM_REWRITE_TAC[SUM_SING; VSUM_SING; CONVEX_HULL_SING;
10916                     RELATIVE_INTERIOR_SING] THEN
10917     REWRITE_TAC[IN_ELIM_THM; SUBSET; IN_SING] THEN
10918     REPEAT STRIP_TAC THEN EXISTS_TAC `\x:real^N. &1` THEN
10919     ASM_REWRITE_TAC[VECTOR_MUL_LID; REAL_LT_01];
10920     ALL_TAC] THEN
10921   MATCH_MP_TAC(SET_RULE
10922    `relative_interior s SUBSET s /\
10923     (!x. x IN s /\ ~(x IN t) ==> ~(x IN relative_interior s))
10924     ==> relative_interior s SUBSET t`) THEN
10925   REWRITE_TAC[RELATIVE_INTERIOR_SUBSET] THEN
10926   X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_RELATIVE_INTERIOR] THEN
10927   REWRITE_TAC[AFFINE_HULL_CONVEX_HULL; IN_ELIM_THM; NOT_EXISTS_THM] THEN
10928   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
10929   DISCH_THEN(CONJUNCTS_THEN2
10930    (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC)
10931    (MP_TAC o SPEC `u:real^N->real`)) THEN
10932   ASM_REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; IN_RELATIVE_INTERIOR; DE_MORGAN_THM;
10933                   SUBSET; IN_ELIM_THM; IN_BALL; IN_INTER] THEN
10934   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN DISJ2_TAC THEN
10935   DISCH_THEN(X_CHOOSE_THEN `e:real`
10936    (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "*"))) THEN
10937   SUBGOAL_THEN `(u:real^N->real) a = &0` ASSUME_TAC THENL
10938    [ASM_SIMP_TAC[REAL_ARITH `&0 <= x /\ ~(&0 < x) ==> x = &0`]; ALL_TAC] THEN
10939   SUBGOAL_THEN `?b:real^N. b IN s /\ ~(b = a)` STRIP_ASSUME_TAC THENL
10940    [ASM SET_TAC[];ALL_TAC] THEN
10941   SUBGOAL_THEN `?d. &0 < d /\ norm(d % (a - b):real^N) < e`
10942   STRIP_ASSUME_TAC THENL
10943    [EXISTS_TAC `e / &2 / norm(a - b:real^N)` THEN
10944     ASM_SIMP_TAC[NORM_MUL; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; NORM_POS_LT;
10945                  REAL_ABS_DIV; REAL_ABS_NORM; REAL_ABS_NUM;
10946                  REAL_DIV_RMUL; REAL_LT_IMP_NZ; VECTOR_SUB_EQ] THEN
10947     ASM_REAL_ARITH_TAC;
10948     ALL_TAC] THEN
10949   REMOVE_THEN "*" (MP_TAC o SPEC `y - d % (a - b):real^N`) THEN
10950   ASM_REWRITE_TAC[NORM_ARITH `dist(a:real^N,a - b) = norm b`] THEN
10951   REWRITE_TAC[NOT_IMP] THEN CONJ_TAC THENL
10952    [MATCH_MP_TAC IN_AFFINE_SUB_MUL_DIFF THEN
10953     ASM_SIMP_TAC[HULL_INC; AFFINE_AFFINE_HULL] THEN
10954     REWRITE_TAC[AFFINE_HULL_FINITE; IN_ELIM_THM] THEN
10955     EXISTS_TAC `u:real^N->real` THEN ASM_REWRITE_TAC[];
10956     ALL_TAC] THEN
10957   DISCH_THEN(X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC) THEN
10958   UNDISCH_TAC `~(affine_dependent(s:real^N->bool))` THEN
10959   ASM_SIMP_TAC[AFFINE_DEPENDENT_EXPLICIT_FINITE] THEN
10960   EXISTS_TAC `\x:real^N. (v x - u x) -
10961                    (if x = a then --d else if x = b then d else &0)` THEN
10962   REWRITE_TAC[VECTOR_SUB_RDISTRIB; MESON[]
10963    `(if p then a else b) % x = (if p then a % x else b % x)`] THEN
10964   ASM_SIMP_TAC[SUM_SUB; VSUM_SUB] THEN
10965   ASM_SIMP_TAC[VSUM_CASES; SUM_CASES; FINITE_RESTRICT; IN_ELIM_THM] THEN
10966   ASM_SIMP_TAC[SET_RULE `a IN s ==> {x | x IN s /\ x = a} = {a}`;
10967    SET_RULE `b IN s /\ ~(b = a)
10968              ==> {x | (x IN s /\ ~(x = a)) /\ x = b} = {b}`] THEN
10969   ASM_SIMP_TAC[VECTOR_MUL_LZERO; SUM_0; VSUM_0; SUM_SING; VSUM_SING] THEN
10970   CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
10971   CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
10972   EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN
10973   FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N`) THEN ASM_REWRITE_TAC[] THEN
10974   ASM_REAL_ARITH_TAC);;
10975
10976 let EXPLICIT_SUBSET_INTERIOR_CONVEX_HULL = prove
10977  (`!s. FINITE s /\ affine hull s = (:real^N)
10978        ==> {y | ?u. (!x. x IN s ==> &0 < u x /\ u x < &1) /\
10979                     sum s u = &1 /\
10980                     vsum s (\x. u x % x) = y}
10981            SUBSET interior(convex hull s)`,
10982   REPEAT STRIP_TAC THEN
10983   FIRST_ASSUM(MP_TAC o
10984     MATCH_MP EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL) THEN
10985   ASM_SIMP_TAC[RELATIVE_INTERIOR_INTERIOR; AFFINE_HULL_CONVEX_HULL]);;
10986
10987 let EXPLICIT_SUBSET_INTERIOR_CONVEX_HULL_MINIMAL = prove
10988  (`!s. FINITE s /\ affine hull s = (:real^N)
10989        ==> {y | ?u. (!x. x IN s ==> &0 < u x) /\
10990                     sum s u = &1 /\
10991                     vsum s (\x. u x % x) = y}
10992            SUBSET interior(convex hull s)`,
10993   REPEAT STRIP_TAC THEN
10994   FIRST_ASSUM(MP_TAC o
10995     MATCH_MP EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL_MINIMAL) THEN
10996   ASM_SIMP_TAC[RELATIVE_INTERIOR_INTERIOR; AFFINE_HULL_CONVEX_HULL]);;
10997
10998 let INTERIOR_CONVEX_HULL_EXPLICIT_MINIMAL = prove
10999  (`!s:real^N->bool.
11000         ~(affine_dependent s)
11001         ==> interior(convex hull s) =
11002              if CARD(s) <= dimindex(:N) then {}
11003               else {y | ?u. (!x. x IN s ==> &0 < u x) /\
11004                             sum s u = &1 /\
11005                             vsum s (\x. u x % x) = y}`,
11006   REPEAT STRIP_TAC THEN
11007   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11008   COND_CASES_TAC THEN ASM_SIMP_TAC[EMPTY_INTERIOR_CONVEX_HULL] THEN
11009   MATCH_MP_TAC EQ_TRANS THEN
11010   EXISTS_TAC `relative_interior(convex hull s):real^N->bool` THEN
11011   CONJ_TAC THENL
11012    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
11013     REWRITE_TAC[AFFINE_HULL_CONVEX_HULL] THEN
11014     MATCH_MP_TAC AFFINE_INDEPENDENT_SPAN_GT THEN
11015     ASM_REWRITE_TAC[] THEN ASM_ARITH_TAC;
11016     ASM_SIMP_TAC[RELATIVE_INTERIOR_CONVEX_HULL_EXPLICIT]]);;
11017
11018 let INTERIOR_CONVEX_HULL_EXPLICIT = prove
11019  (`!s:real^N->bool.
11020         ~(affine_dependent s)
11021         ==> interior(convex hull s) =
11022              if CARD(s) <= dimindex(:N) then {}
11023               else {y | ?u. (!x. x IN s ==> &0 < u x /\ u x < &1) /\
11024                             sum s u = &1 /\
11025                             vsum s (\x. u x % x) = y}`,
11026   REPEAT STRIP_TAC THEN
11027   ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EXPLICIT_MINIMAL] THEN
11028   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
11029  REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN X_GEN_TAC `v:real^N` THEN
11030   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `u:real^N->real` THEN
11031   EQ_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[] THEN
11032   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
11033   MP_TAC(ISPEC `s:real^N->bool` CHOOSE_SUBSET) THEN
11034   ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE] THEN
11035   DISCH_THEN(MP_TAC o SPEC `2`) THEN ANTS_TAC THENL
11036    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (ARITH_RULE
11037      `~(c <= n) ==> 1 <= n ==> 2 <= c`)) THEN
11038     REWRITE_TAC[DIMINDEX_GE_1];
11039     ALL_TAC] THEN
11040   CONV_TAC(ONCE_DEPTH_CONV HAS_SIZE_CONV) THEN
11041   REWRITE_TAC[SUBSET] THEN
11042   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` (CONJUNCTS_THEN2 ASSUME_TAC
11043     MP_TAC)) THEN
11044   DISCH_THEN(X_CHOOSE_THEN `a:real^N` (X_CHOOSE_THEN `b:real^N`
11045         STRIP_ASSUME_TAC)) THEN
11046   SUBGOAL_THEN `?y:real^N. y IN s /\ ~(y = x)` STRIP_ASSUME_TAC THENL
11047    [ASM SET_TAC[]; ALL_TAC] THEN
11048   SUBGOAL_THEN `sum {x,y} u <= sum s (u:real^N->real)` MP_TAC THENL
11049    [MATCH_MP_TAC SUM_SUBSET_SIMPLE THEN
11050     ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE; REAL_LT_IMP_LE; IN_DIFF] THEN
11051     ASM SET_TAC[];
11052     ALL_TAC] THEN
11053   ASM_SIMP_TAC[SUM_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
11054   ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
11055   MATCH_MP_TAC(REAL_ARITH `&0 < y ==> x + y + &0 <= &1 ==> x < &1`) THEN
11056   ASM_SIMP_TAC[]);;
11057
11058 let INTERIOR_CONVEX_HULL_3_MINIMAL = prove
11059  (`!a b c:real^2.
11060         ~collinear{a,b,c}
11061         ==> interior(convex hull {a,b,c}) =
11062                 {v | ?x y z. &0 < x /\
11063                              &0 < y /\
11064                              &0 < z /\
11065                              x + y + z = &1 /\
11066                              x % a + y % b + z % c = v}`,
11067   REWRITE_TAC[COLLINEAR_3_EQ_AFFINE_DEPENDENT; DE_MORGAN_THM] THEN
11068   REPEAT STRIP_TAC THEN
11069   ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EXPLICIT_MINIMAL] THEN
11070   ASM_SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
11071   CONV_TAC(LAND_CONV(RATOR_CONV(LAND_CONV(ONCE_DEPTH_CONV(REWRITE_CONV
11072    [IN_INSERT; NOT_IN_EMPTY]))))) THEN
11073   ASM_REWRITE_TAC[DIMINDEX_2; ARITH] THEN
11074   SIMP_TAC[FINITE_INSERT; FINITE_UNION; FINITE_EMPTY; RIGHT_EXISTS_AND_THM;
11075            AFFINE_HULL_FINITE_STEP_GEN; REAL_LT_ADD; REAL_HALF] THEN
11076   REWRITE_TAC[REAL_ARITH `&1 - a - b - c = &0 <=> a + b + c = &1`;
11077          VECTOR_ARITH `y - a - b - c:real^N = vec 0 <=> a + b + c = y`]);;
11078
11079 let INTERIOR_CONVEX_HULL_3 = prove
11080  (`!a b c:real^2.
11081         ~collinear{a,b,c}
11082         ==> interior(convex hull {a,b,c}) =
11083                 {v | ?x y z. &0 < x /\ x < &1 /\
11084                              &0 < y /\ y < &1 /\
11085                              &0 < z /\ z < &1 /\
11086                              x + y + z = &1 /\
11087                              x % a + y % b + z % c = v}`,
11088   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_3_MINIMAL] THEN
11089   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN GEN_TAC THEN
11090   REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN EQ_TAC THEN STRIP_TAC THEN
11091   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
11092
11093 (* ------------------------------------------------------------------------- *)
11094 (* Similar results for closure and (relative or absolute) frontier.          *)
11095 (* ------------------------------------------------------------------------- *)
11096
11097 let CLOSURE_CONVEX_HULL = prove
11098  (`!s. compact s ==> closure(convex hull s) = convex hull s`,
11099   SIMP_TAC[CLOSURE_CLOSED; COMPACT_IMP_CLOSED; COMPACT_CONVEX_HULL]);;
11100
11101 let RELATIVE_FRONTIER_CONVEX_HULL_EXPLICIT = prove
11102  (`!s:real^N->bool.
11103         ~(affine_dependent s)
11104         ==> relative_frontier(convex hull s) =
11105                 {y | ?u. (!x. x IN s ==> &0 <= u x) /\
11106                          (?x. x IN s /\ u x = &0) /\
11107                          sum s u = &1 /\
11108                          vsum s (\x. u x % x) = y}`,
11109   REPEAT STRIP_TAC THEN REWRITE_TAC[relative_frontier; UNIONS_GSPEC] THEN
11110   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11111   ASM_SIMP_TAC[CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11112   ASM_SIMP_TAC[CONVEX_HULL_FINITE; RELATIVE_INTERIOR_CONVEX_HULL_EXPLICIT] THEN
11113   GEN_REWRITE_TAC I [EXTENSION] THEN X_GEN_TAC `y:real^N` THEN
11114   REWRITE_TAC[IN_DIFF; IN_ELIM_THM] THEN EQ_TAC THENL
11115    [DISCH_THEN(CONJUNCTS_THEN2
11116      (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC) ASSUME_TAC) THEN
11117     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
11118     DISCH_THEN(MP_TAC o SPEC `u:real^N->real`) THEN
11119     ASM_REWRITE_TAC[NOT_FORALL_THM; NOT_IMP] THEN
11120     DISCH_THEN(CHOOSE_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
11121     ASM_SIMP_TAC[REAL_ARITH `&0 <= x ==> (~(&0 < x) <=> x = &0)`] THEN
11122     DISCH_TAC THEN EXISTS_TAC `u:real^N->real` THEN
11123     ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[];
11124     DISCH_THEN(X_CHOOSE_THEN `u:real^N->real`
11125      (REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC)) THEN
11126     CONJ_TAC THENL
11127      [EXISTS_TAC `u:real^N->real` THEN ASM_SIMP_TAC[]; ALL_TAC] THEN
11128     DISCH_THEN(X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC) THEN
11129     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
11130      [AFFINE_DEPENDENT_EXPLICIT]) THEN
11131     REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
11132      [`s:real^N->bool`; `(\x. u x - v x):real^N->real`] THEN
11133     ASM_SIMP_TAC[SUBSET_REFL; VECTOR_SUB_RDISTRIB; SUM_SUB; VSUM_SUB] THEN
11134     REWRITE_TAC[REAL_SUB_0; VECTOR_SUB_EQ] THEN ASM_MESON_TAC[REAL_LT_REFL]]);;
11135
11136 let FRONTIER_CONVEX_HULL_EXPLICIT = prove
11137  (`!s:real^N->bool.
11138         ~(affine_dependent s)
11139         ==> frontier(convex hull s) =
11140                 {y | ?u. (!x. x IN s ==> &0 <= u x) /\
11141                          (dimindex(:N) < CARD s ==> ?x. x IN s /\ u x = &0) /\
11142                          sum s u = &1 /\
11143                          vsum s (\x. u x % x) = y}`,
11144   REPEAT STRIP_TAC THEN REWRITE_TAC[frontier] THEN
11145   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11146   DISJ_CASES_TAC
11147    (ARITH_RULE `CARD(s:real^N->bool) <= dimindex(:N) \/
11148                 dimindex(:N) < CARD(s:real^N->bool)`)
11149   THENL
11150    [ASM_SIMP_TAC[GSYM NOT_LE; INTERIOR_CONVEX_HULL_EXPLICIT] THEN
11151     ASM_SIMP_TAC[CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT; DIFF_EMPTY] THEN
11152     REWRITE_TAC[CONVEX_HULL_FINITE];
11153     ASM_SIMP_TAC[GSYM RELATIVE_FRONTIER_CONVEX_HULL_EXPLICIT] THEN
11154     REWRITE_TAC[relative_frontier] THEN AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN
11155     MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
11156     MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
11157     EXISTS_TAC `affine hull s:real^N->bool` THEN
11158     ASM_SIMP_TAC[AFFINE_INDEPENDENT_SPAN_GT; HULL_MONO; HULL_SUBSET]]);;
11159
11160 let RELATIVE_FRONTIER_CONVEX_HULL_CASES = prove
11161  (`!s:real^N->bool.
11162         ~(affine_dependent s)
11163         ==> relative_frontier(convex hull s) =
11164                 UNIONS { convex hull (s DELETE a) |a| a IN s }`,
11165   REPEAT STRIP_TAC THEN REWRITE_TAC[UNIONS_GSPEC] THEN
11166   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11167   ASM_SIMP_TAC[RELATIVE_FRONTIER_CONVEX_HULL_EXPLICIT] THEN
11168   REWRITE_TAC[EXTENSION; IN_ELIM_THM; CONVEX_HULL_FINITE] THEN
11169   X_GEN_TAC `y:real^N` THEN EQ_TAC THENL
11170    [DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` MP_TAC) THEN
11171     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
11172     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
11173     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
11174     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN EXISTS_TAC `u:real^N->real` THEN
11175     ASM_SIMP_TAC[IN_DELETE; SUM_DELETE; VSUM_DELETE; REAL_SUB_RZERO] THEN
11176     VECTOR_ARITH_TAC;
11177     REWRITE_TAC[IN_DELETE] THEN
11178     DISCH_THEN(X_CHOOSE_THEN `a:real^N` (CONJUNCTS_THEN2 ASSUME_TAC
11179      (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC))) THEN
11180     EXISTS_TAC `(\x. if x = a then &0 else u x):real^N->real` THEN
11181     ASM_SIMP_TAC[COND_RAND; COND_RATOR; REAL_LE_REFL; COND_ID] THEN
11182     CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
11183     ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; VECTOR_MUL_LZERO] THEN
11184     ASM_SIMP_TAC[GSYM DELETE; SUM_0; VSUM_0; REAL_ADD_LID; VECTOR_ADD_LID]]);;
11185
11186 let FRONTIER_CONVEX_HULL_CASES = prove
11187  (`!s:real^N->bool.
11188         ~(affine_dependent s)
11189         ==> frontier(convex hull s) =
11190                 if CARD(s) <= dimindex(:N) then convex hull s
11191                 else UNIONS { convex hull (s DELETE a) |a| a IN s }`,
11192   REPEAT STRIP_TAC THEN
11193   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11194   ASM_SIMP_TAC[frontier; CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11195   COND_CASES_TAC THENL
11196    [ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EXPLICIT; DIFF_EMPTY]; ALL_TAC] THEN
11197   ASM_SIMP_TAC[GSYM RELATIVE_FRONTIER_CONVEX_HULL_CASES] THEN
11198   ASM_SIMP_TAC[relative_frontier; frontier;
11199                CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11200   AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN
11201   RULE_ASSUM_TAC(REWRITE_RULE[NOT_LE]) THEN
11202   MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
11203   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
11204   EXISTS_TAC `affine hull s:real^N->bool` THEN
11205   ASM_SIMP_TAC[AFFINE_INDEPENDENT_SPAN_GT; HULL_MONO; HULL_SUBSET]);;
11206
11207 let IN_FRONTIER_CONVEX_HULL = prove
11208  (`!s x:real^N.
11209         FINITE s /\ CARD s <= dimindex(:N) + 1 /\ x IN s
11210         ==> x IN frontier(convex hull s)`,
11211   REPEAT STRIP_TAC THEN ASM_CASES_TAC `affine_dependent(s:real^N->bool)` THENL
11212    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [affine_dependent]) THEN
11213     DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
11214     ASM_SIMP_TAC[frontier; CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11215     ASM_SIMP_TAC[HULL_INC; IN_DIFF] THEN MATCH_MP_TAC(SET_RULE
11216      `!t. s SUBSET t /\ t = {} ==> ~(x IN s)`) THEN
11217     EXISTS_TAC `interior(affine hull s):real^N->bool` THEN
11218     SIMP_TAC[SUBSET_INTERIOR; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
11219     SUBGOAL_THEN `s = (a:real^N) INSERT (s DELETE a)` SUBST1_TAC THENL
11220      [ASM SET_TAC[]; ALL_TAC] THEN
11221     ASM_SIMP_TAC[HULL_REDUNDANT] THEN
11222     MATCH_MP_TAC EMPTY_INTERIOR_AFFINE_HULL THEN
11223     ASM_SIMP_TAC[FINITE_DELETE; CARD_DELETE] THEN ASM_ARITH_TAC;
11224     ASM_SIMP_TAC[FRONTIER_CONVEX_HULL_CASES] THEN
11225     COND_CASES_TAC THEN ASM_SIMP_TAC[HULL_INC] THEN
11226     REWRITE_TAC[UNIONS_GSPEC; IN_ELIM_THM] THEN
11227     SUBGOAL_THEN `?y:real^N. y IN s /\ ~(y = x)` MP_TAC THENL
11228      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
11229        `x IN s ==> ~(s = {x}) ==> ?y. y IN s /\ ~(y = x)`)) THEN DISCH_TAC THEN
11230       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_LE]) THEN
11231       ASM_SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
11232       REWRITE_TAC[NOT_LT; NOT_IN_EMPTY; ARITH_SUC; DIMINDEX_GE_1];
11233       MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN STRIP_TAC THEN
11234       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC HULL_INC THEN ASM SET_TAC[]]]);;
11235
11236 let NOT_IN_INTERIOR_CONVEX_HULL = prove
11237  (`!s x:real^N.
11238         FINITE s /\ CARD s <= dimindex(:N) + 1 /\ x IN s
11239         ==> ~(x IN interior(convex hull s))`,
11240   REPEAT GEN_TAC THEN
11241   DISCH_THEN(MP_TAC o MATCH_MP IN_FRONTIER_CONVEX_HULL) THEN
11242   SIMP_TAC[frontier; IN_DIFF]);;
11243
11244 let INTERIOR_CONVEX_HULL_EQ_EMPTY = prove
11245  (`!s:real^N->bool.
11246         s HAS_SIZE (dimindex(:N) + 1)
11247         ==> (interior(convex hull s) = {} <=> affine_dependent s)`,
11248   REPEAT GEN_TAC THEN REWRITE_TAC[HAS_SIZE] THEN STRIP_TAC THEN
11249   ASM_CASES_TAC `affine_dependent(s:real^N->bool)` THENL
11250    [ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I
11251       [affine_dependent]) THEN
11252     DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
11253     ASM_SIMP_TAC[frontier; CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11254     ASM_SIMP_TAC[HULL_INC; IN_DIFF] THEN MATCH_MP_TAC(SET_RULE
11255      `!t. s SUBSET t /\ t = {} ==> s = {}`) THEN
11256     EXISTS_TAC `interior(affine hull s):real^N->bool` THEN
11257     SIMP_TAC[SUBSET_INTERIOR; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
11258     SUBGOAL_THEN `s = (a:real^N) INSERT (s DELETE a)` SUBST1_TAC THENL
11259      [ASM SET_TAC[]; ALL_TAC] THEN
11260     ASM_SIMP_TAC[HULL_REDUNDANT] THEN
11261     MATCH_MP_TAC EMPTY_INTERIOR_AFFINE_HULL THEN
11262     ASM_SIMP_TAC[FINITE_DELETE; CARD_DELETE] THEN ASM_ARITH_TAC;
11263     ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EXPLICIT_MINIMAL] THEN
11264     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; ARITH_RULE `~(n + 1 <= n)`] THEN
11265     EXISTS_TAC `vsum s (\x:real^N. inv(&(dimindex(:N)) + &1) % x)` THEN
11266     REWRITE_TAC[IN_ELIM_THM] THEN
11267     EXISTS_TAC `\x:real^N. inv(&(dimindex(:N)) + &1)` THEN
11268     ASM_SIMP_TAC[REAL_LT_INV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
11269     ASM_SIMP_TAC[SUM_CONST; GSYM REAL_OF_NUM_ADD] THEN
11270     CONV_TAC REAL_FIELD]);;
11271
11272 (* ------------------------------------------------------------------------- *)
11273 (* Similar things in special case (could use above as lemmas here instead).  *)
11274 (* ------------------------------------------------------------------------- *)
11275
11276 let SIMPLEX_EXPLICIT = prove
11277  (`!s:real^N->bool.
11278         FINITE s /\ ~(vec 0 IN s)
11279         ==> convex hull (vec 0 INSERT s) =
11280             { y | ?u. (!x. x IN s ==> &0 <= u x) /\
11281                       sum s u <= &1 /\
11282                       vsum s (\x. u x % x) = y}`,
11283   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CONVEX_HULL_FINITE; FINITE_INSERT] THEN
11284   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN X_GEN_TAC `y:real^N` THEN
11285   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; IN_INSERT] THEN
11286   REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
11287   EQ_TAC THEN DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC) THENL
11288    [EXISTS_TAC `u:real^N->real` THEN ASM_SIMP_TAC[REAL_LE_REFL] THEN
11289     FIRST_X_ASSUM(MP_TAC o SPEC `vec 0:real^N`) THEN REWRITE_TAC[] THEN
11290     ASM_REAL_ARITH_TAC;
11291     EXISTS_TAC `\x:real^N. if x = vec 0 then &1 - sum (s:real^N->bool) u
11292                            else u(x)` THEN
11293     ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
11294      [X_GEN_TAC `x:real^N` THEN ASM_CASES_TAC `x:real^N = vec 0` THEN
11295       ASM_REWRITE_TAC[REAL_SUB_LE];
11296       MATCH_MP_TAC(REAL_ARITH `s = t ==> &1 - s + t = &1`) THEN
11297       MATCH_MP_TAC SUM_EQ THEN ASM_MESON_TAC[];
11298       FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
11299       MATCH_MP_TAC VSUM_EQ THEN ASM_MESON_TAC[]]]);;
11300
11301 let STD_SIMPLEX = prove
11302  (`convex hull (vec 0 INSERT { basis i | 1 <= i /\ i <= dimindex(:N)}) =
11303         {x:real^N | (!i. 1 <= i /\ i <= dimindex(:N) ==> &0 <= x$i) /\
11304                     sum (1..dimindex(:N)) (\i. x$i) <= &1 }`,
11305   W(MP_TAC o PART_MATCH (lhs o rand) SIMPLEX_EXPLICIT o lhs o snd) THEN ANTS_TAC THENL
11306    [REWRITE_TAC[SIMPLE_IMAGE; GSYM IN_NUMSEG] THEN
11307     SIMP_TAC[FINITE_IMAGE; FINITE_NUMSEG; IN_IMAGE] THEN
11308     REWRITE_TAC[IN_NUMSEG] THEN MESON_TAC[BASIS_NONZERO];
11309     ALL_TAC] THEN
11310   DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[EXTENSION] THEN
11311   ONCE_REWRITE_TAC[IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN
11312   REWRITE_TAC[SIMPLE_IMAGE; GSYM IN_NUMSEG] THEN
11313   SUBGOAL_THEN `!u. sum (IMAGE (basis:num->real^N) (1..dimindex(:N))) u =
11314                         sum (1..dimindex(:N)) (u o basis)`
11315    (fun th -> REWRITE_TAC[th])
11316   THENL
11317    [GEN_TAC THEN MATCH_MP_TAC SUM_IMAGE THEN REWRITE_TAC[IN_NUMSEG] THEN
11318     REWRITE_TAC[GSYM CONJ_ASSOC; BASIS_INJ];
11319     ALL_TAC] THEN
11320   SUBGOAL_THEN `!u. vsum (IMAGE (basis:num->real^N) (1..dimindex(:N))) u =
11321                         vsum (1..dimindex(:N)) ((u:real^N->real^N) o basis)`
11322    (fun th -> REWRITE_TAC[th])
11323   THENL
11324    [GEN_TAC THEN MATCH_MP_TAC VSUM_IMAGE THEN REWRITE_TAC[IN_NUMSEG] THEN
11325     REWRITE_TAC[GSYM CONJ_ASSOC; BASIS_INJ; FINITE_NUMSEG];
11326     ALL_TAC] THEN
11327   REWRITE_TAC[o_DEF; BASIS_EXPANSION_UNIQUE; FORALL_IN_IMAGE] THEN
11328   REWRITE_TAC[IN_NUMSEG] THEN EQ_TAC THENL
11329    [DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC) THEN
11330     CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
11331     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
11332      `x <= &1 ==> x = y ==> y <= &1`)) THEN
11333     MATCH_MP_TAC SUM_EQ THEN ASM_SIMP_TAC[IN_NUMSEG];
11334     STRIP_TAC THEN EXISTS_TAC `\y:real^N. y dot x` THEN
11335     ASM_SIMP_TAC[DOT_BASIS]]);;
11336
11337 let INTERIOR_STD_SIMPLEX = prove
11338  (`interior
11339     (convex hull (vec 0 INSERT { basis i | 1 <= i /\ i <= dimindex(:N)})) =
11340         {x:real^N | (!i. 1 <= i /\ i <= dimindex(:N) ==> &0 < x$i) /\
11341                     sum (1..dimindex(:N)) (\i. x$i) < &1 }`,
11342   REWRITE_TAC[EXTENSION; IN_INTERIOR; IN_ELIM_THM; STD_SIMPLEX] THEN
11343   REWRITE_TAC[SUBSET; IN_BALL; IN_ELIM_THM] THEN
11344   X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
11345    [DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
11346     FIRST_ASSUM(MP_TAC o SPEC `x:real^N`) THEN REWRITE_TAC[DIST_REFL] THEN
11347     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN ASM_SIMP_TAC[REAL_LT_LE] THEN
11348     CONJ_TAC THENL
11349      [X_GEN_TAC `k:num` THEN STRIP_TAC THEN
11350       FIRST_X_ASSUM(MP_TAC o SPEC `x - (e / &2) % basis k:real^N`) THEN
11351       REWRITE_TAC[NORM_ARITH `dist(x,x - e) = norm(e)`; NORM_MUL] THEN
11352       ASM_SIMP_TAC[NORM_BASIS; REAL_ARITH `&0 < e ==> abs(e / &2) * &1 < e`;
11353                    VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT] THEN
11354       DISCH_THEN(MP_TAC o SPEC `k:num` o CONJUNCT1) THEN ASM_REWRITE_TAC[] THEN
11355       ASM_SIMP_TAC[BASIS_COMPONENT] THEN UNDISCH_TAC `&0 < e` THEN
11356       REAL_ARITH_TAC;
11357       FIRST_X_ASSUM(MP_TAC o SPEC `x + (e / &2) % basis 1:real^N`) THEN
11358       REWRITE_TAC[NORM_ARITH `dist(x,x + e) = norm(e)`; NORM_MUL] THEN
11359       ASM_SIMP_TAC[NORM_BASIS; LE_REFL; DIMINDEX_GE_1] THEN
11360       ASM_SIMP_TAC[REAL_ARITH `&0 < e ==> abs(e / &2) * &1 < e`] THEN
11361       DISCH_THEN(MP_TAC o CONJUNCT2) THEN
11362       MATCH_MP_TAC(REAL_ARITH `x < y ==> y <= &1 ==> ~(x = &1)`) THEN
11363       MATCH_MP_TAC SUM_LT THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
11364       ONCE_REWRITE_TAC[TAUT `(a /\ b) /\ c <=> ~(a /\ b ==> ~c)`] THEN
11365       SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
11366                BASIS_COMPONENT] THEN
11367       CONJ_TAC THENL
11368        [GEN_TAC THEN COND_CASES_TAC;
11369         EXISTS_TAC `1` THEN REWRITE_TAC[LE_REFL; DIMINDEX_GE_1]] THEN
11370       ASM_REAL_ARITH_TAC];
11371     STRIP_TAC THEN
11372     EXISTS_TAC
11373      `min (inf(IMAGE (\i. (x:real^N)$i) (1..dimindex(:N))))
11374           ((&1 - sum (1..dimindex(:N)) (\i. x$i)) / &(dimindex(:N)))` THEN
11375     ASM_SIMP_TAC[REAL_LT_MIN] THEN
11376     SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; FINITE_NUMSEG;
11377              IMAGE_EQ_EMPTY; NUMSEG_EMPTY; GSYM NOT_LE; DIMINDEX_GE_1] THEN
11378     REWRITE_TAC[FORALL_IN_IMAGE] THEN
11379     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_OF_NUM_LT;
11380                  ARITH_RULE `0 < x <=> 1 <= x`; DIMINDEX_GE_1] THEN
11381     ASM_REWRITE_TAC[IN_NUMSEG; REAL_MUL_LZERO; REAL_SUB_LT] THEN
11382     REPEAT(POP_ASSUM(K ALL_TAC)) THEN X_GEN_TAC `y:real^N` THEN
11383     MATCH_MP_TAC MONO_AND THEN CONJ_TAC THENL
11384      [MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `k:num` THEN
11385       DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
11386       ASM_REWRITE_TAC[] THEN
11387       MATCH_MP_TAC(REAL_ARITH `abs(xk - yk) <= d ==> d < xk ==> &0 <= yk`);
11388       GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o RAND_CONV o RAND_CONV)
11389        [GSYM CARD_NUMSEG_1] THEN
11390       ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
11391       SIMP_TAC[GSYM SUM_CONST; FINITE_NUMSEG] THEN
11392       MATCH_MP_TAC(REAL_ARITH
11393        `s2 <= s0 + s1 ==> s0 < &1 - s1 ==> s2 <= &1`) THEN
11394       REWRITE_TAC[GSYM SUM_ADD_NUMSEG] THEN
11395       MATCH_MP_TAC SUM_LE_NUMSEG THEN REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
11396       MATCH_MP_TAC(REAL_ARITH `abs(y - x) <= z ==> x <= z + y`)] THEN
11397     ASM_SIMP_TAC[GSYM VECTOR_SUB_COMPONENT; dist] THEN
11398     MATCH_MP_TAC COMPONENT_LE_NORM THEN ASM_REWRITE_TAC[]]);;