Update from HH
[hl193./.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_VSUM_STRONG = prove
314  (`!s k u x:A->real^N.
315         affine s /\
316         sum k u = &1 /\
317         (!i. i IN k ==> u i = &0 \/ x i IN s)
318         ==> vsum k (\i. u i % x i) IN s`,
319   REPEAT STRIP_TAC THEN
320   SUBGOAL_THEN
321    `vsum k (\i. u i % (x:A->real^N) i) =
322     vsum {i | i IN k /\ ~(u i = &0)} (\i. u i % x i)`
323   SUBST1_TAC THENL
324    [MATCH_MP_TAC VSUM_SUPERSET THEN REWRITE_TAC[VECTOR_MUL_EQ_0] THEN
325     SET_TAC[];
326     MATCH_MP_TAC AFFINE_VSUM THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
327      [ASM_MESON_TAC[SUM_DEGENERATE; REAL_ARITH `~(&1 = &0)`];
328       FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
329       CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_SUPERSET THEN ASM SET_TAC[];
330       ASM SET_TAC[]]]);;
331
332 let AFFINE_INDEXED = prove
333  (`!s:real^N->bool.
334         affine s <=>
335             !k u x. (!i:num. 1 <= i /\ i <= k ==> x(i) IN s) /\
336                     (sum (1..k) u = &1)
337                     ==> vsum (1..k) (\i. u(i) % x(i)) IN s`,
338   REPEAT GEN_TAC THEN EQ_TAC THENL
339    [REPEAT STRIP_TAC THEN MATCH_MP_TAC AFFINE_VSUM THEN
340     ASM_REWRITE_TAC[IN_NUMSEG; FINITE_NUMSEG];
341     DISCH_TAC THEN REWRITE_TAC[affine] THEN
342     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
343     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `2`) THEN
344     DISCH_THEN(MP_TAC o SPEC `\n. if n = 1 then u else v:real`) THEN
345     DISCH_THEN(MP_TAC o SPEC `\n. if n = 1 then x else y:real^N`) THEN
346     REWRITE_TAC[num_CONV `2`; SUM_CLAUSES_NUMSEG; VSUM_CLAUSES_NUMSEG;
347       NUMSEG_SING; VSUM_SING; SUM_SING] THEN REWRITE_TAC[ARITH] THEN
348     ASM_MESON_TAC[]]);;
349
350 let AFFINE_HULL_INDEXED = prove
351  (`!s. affine hull s =
352         {y:real^N | ?k u x. (!i. 1 <= i /\ i <= k ==> x i IN s) /\
353                             (sum (1..k) u = &1) /\
354                             (vsum (1..k) (\i. u i % x i) = y)}`,
355   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN REPEAT CONJ_TAC THENL
356    [REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
357     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
358     MAP_EVERY EXISTS_TAC [`1`; `\i:num. &1`; `\i:num. x:real^N`] THEN
359     ASM_SIMP_TAC[FINITE_RULES; IN_SING; SUM_SING; VECTOR_MUL_LID; VSUM_SING;
360                  REAL_POS; NUMSEG_SING];
361     ALL_TAC;
362     REWRITE_TAC[AFFINE_INDEXED; SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
363     MESON_TAC[]] THEN
364   REWRITE_TAC[affine; IN_ELIM_THM] THEN
365   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
366   REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
367   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC
368    [`k1:num`; `u1:num->real`; `x1:num->real^N`;
369     `k2:num`; `u2:num->real`; `x2:num->real^N`] THEN
370   STRIP_TAC THEN EXISTS_TAC `k1 + k2:num` THEN
371   EXISTS_TAC `\i:num. if i <= k1 then u * u1(i) else v * u2(i - k1):real` THEN
372   EXISTS_TAC `\i:num. if i <= k1 then x1(i) else x2(i - k1):real^N` THEN
373   ASM_SIMP_TAC[NUMSEG_ADD_SPLIT; ARITH_RULE `1 <= x + 1 /\ x < x + 1`;
374    IN_NUMSEG; SUM_UNION; VSUM_UNION; FINITE_NUMSEG; DISJOINT_NUMSEG;
375    ARITH_RULE `k1 + 1 <= i ==> ~(i <= k1)`] THEN
376   REWRITE_TAC[ONCE_REWRITE_RULE[ADD_SYM] NUMSEG_OFFSET_IMAGE] THEN
377   ASM_SIMP_TAC[SUM_IMAGE; VSUM_IMAGE; EQ_ADD_LCANCEL; FINITE_NUMSEG] THEN
378   ASM_SIMP_TAC[o_DEF; ADD_SUB2; SUM_LMUL; VSUM_LMUL; GSYM VECTOR_MUL_ASSOC;
379                FINITE_NUMSEG; REAL_MUL_RID] THEN
380   ASM_MESON_TAC[REAL_LE_MUL; ARITH_RULE
381     `i <= k1 + k2 /\ ~(i <= k1) ==> 1 <= i - k1 /\ i - k1 <= k2`]);;
382
383 let AFFINE = prove
384  (`!V:real^N->bool.
385      affine V <=>
386          !(s:real^N->bool) (u:real^N->real).
387              FINITE s /\ ~(s = {}) /\ s SUBSET V /\ sum s u = &1
388              ==> vsum s (\x. u x % x) IN V`,
389   GEN_TAC THEN EQ_TAC THENL
390    [REPEAT STRIP_TAC THEN MATCH_MP_TAC AFFINE_VSUM THEN
391     ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
392     REWRITE_TAC[affine] THEN DISCH_TAC THEN
393     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
394     STRIP_TAC THEN ASM_CASES_TAC `x:real^N = y` THENL
395      [FIRST_X_ASSUM SUBST_ALL_TAC THEN
396       ASM_REWRITE_TAC[GSYM VECTOR_ADD_RDISTRIB;VECTOR_MUL_LID];ALL_TAC] THEN
397      FIRST_X_ASSUM(MP_TAC o SPEC `{x:real^N,y}`) THEN
398     DISCH_THEN(MP_TAC o SPEC `\w. if w = x:real^N then u else v:real`) THEN
399     ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FINITE_RULES; NUMSEG_SING;
400                  VSUM_SING; SUM_SING;SUBSET;IN_INSERT;NOT_IN_EMPTY] THEN
401     ASM SET_TAC[]]);;
402
403 let AFFINE_EXPLICIT = prove
404  (`!s:real^N->bool.
405         affine s <=>
406             !t u. FINITE t /\ t SUBSET s /\ sum t u = &1
407                   ==> vsum t (\x. u(x) % x) IN s`,
408   GEN_TAC THEN REWRITE_TAC[AFFINE] THEN
409   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
410   X_GEN_TAC `t:real^N->bool` THEN REWRITE_TAC[] THEN
411   AP_TERM_TAC THEN ABS_TAC THEN
412   ASM_CASES_TAC `t:real^N->bool = {}` THEN
413   ASM_REWRITE_TAC[SUM_CLAUSES] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
414
415 let AFFINE_HULL_EXPLICIT = prove
416  (`!(p:real^N -> bool).
417         affine hull p =
418          {y | ?s u. FINITE s /\ ~(s = {}) /\ s SUBSET p /\
419                     sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
420   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN REPEAT CONJ_TAC THENL
421    [REWRITE_TAC[SUBSET;IN_ELIM_THM] THEN
422     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
423     MAP_EVERY EXISTS_TAC [`{x:real^N}`;`\v:real^N. &1:real`] THEN
424     ASM_SIMP_TAC[FINITE_RULES;IN_SING;SUM_SING;VSUM_SING;VECTOR_MUL_LID] THEN
425     SET_TAC[];
426     REWRITE_TAC[affine;IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
427     EXISTS_TAC `(s UNION s'):real^N->bool` THEN
428     EXISTS_TAC
429       `\a:real^N. (\b:real^N.if (b IN s) then (u * (u' b)) else &0) a +
430                   (\b:real^N.if (b IN s') then v * (u'' b) else &0) a` THEN
431     REPEAT CONJ_TAC THENL
432      [ASM_REWRITE_TAC[FINITE_UNION];
433       ASM SET_TAC[];
434       ASM_REWRITE_TAC[UNION_SUBSET];
435       ASM_SIMP_TAC[REWRITE_RULE[REAL_ARITH `a + b = c + d <=> c = a + b - d`]
436                    SUM_INCL_EXCL; GSYM SUM_RESTRICT_SET;
437                    SET_RULE `{a | a IN (s:A->bool) /\ a IN s'} = s INTER s'`;
438                    SUM_ADD;SUM_LMUL;REAL_MUL_RID;
439                    FINITE_INTER;INTER_IDEMPOT] THEN
440     ASM_REWRITE_TAC[SET_RULE `(a INTER b) INTER a = a INTER b`;
441                     SET_RULE `(a INTER b) INTER b = a INTER b`;
442                     REAL_ARITH `(a + b) + (c + d) - (e + b) = (a + d) + c - e`;
443                     REAL_ARITH `a + b - c = a <=> b = c`] THEN
444     AP_TERM_TAC THEN REWRITE_TAC[INTER_COMM];
445     ASM_SIMP_TAC[REWRITE_RULE
446                   [VECTOR_ARITH `(a:real^N) + b = c + d <=> c = a + b - d`]
447                   VSUM_INCL_EXCL;GSYM VSUM_RESTRICT_SET;
448                  SET_RULE `{a | a IN (s:A->bool) /\ a IN s'} = s INTER s'`;
449                  VSUM_ADD;FINITE_INTER;INTER_IDEMPOT;VECTOR_ADD_RDISTRIB;
450                  GSYM VECTOR_MUL_ASSOC;VSUM_LMUL;
451                  MESON[] `(if P then a else b) % (x:real^N) =
452                           (if P then a % x else b % x)`;
453                  VECTOR_MUL_LZERO;GSYM VSUM_RESTRICT_SET] THEN
454     ASM_REWRITE_TAC[SET_RULE `(a INTER b) INTER a = a INTER b`;
455                     SET_RULE `(a INTER b) INTER b = a INTER b`;
456                     VECTOR_ARITH
457                      `((a:real^N) + b) + (c + d) - (e + b) = (a + d) + c - e`;
458                     VECTOR_ARITH `(a:real^N) + b - c = a <=> b = c`] THEN
459     AP_TERM_TAC THEN REWRITE_TAC[INTER_COMM]];
460     ASM_CASES_TAC `(p:real^N->bool) = {}` THENL
461       [FIRST_X_ASSUM SUBST_ALL_TAC THEN
462        REWRITE_TAC[SUBSET_EMPTY;EMPTY_SUBSET] THEN ASM SET_TAC[];
463        ALL_TAC] THEN
464     REWRITE_TAC[AFFINE; SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
465     ASM SET_TAC[]]);;
466
467 let AFFINE_HULL_EXPLICIT_ALT = prove
468  (`!(p:real^N -> bool).
469         affine hull p =
470          {y | ?s u. FINITE s /\ s SUBSET p /\
471                     sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
472   GEN_TAC THEN REWRITE_TAC[AFFINE_HULL_EXPLICIT] THEN
473   GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[IN_ELIM_THM] THEN
474   GEN_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
475   EQ_TAC THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
476   POP_ASSUM MP_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
477   SIMP_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH_EQ]);;
478
479 let AFFINE_HULL_FINITE = prove
480  (`!s:real^N->bool.
481         affine hull s = {y | ?u. sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
482   GEN_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
483   REWRITE_TAC[AFFINE_HULL_EXPLICIT; IN_ELIM_THM] THEN
484   X_GEN_TAC `x:real^N` THEN EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
485    [MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `f:real^N->real`] THEN
486     STRIP_TAC THEN
487     EXISTS_TAC `\x:real^N. if x IN t then f x else &0` THEN
488     REWRITE_TAC[COND_RAND; COND_RATOR; VECTOR_MUL_LZERO] THEN
489     REWRITE_TAC[GSYM SUM_RESTRICT_SET; GSYM VSUM_RESTRICT_SET] THEN
490     ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`];
491     X_GEN_TAC `f:real^N->real` THEN
492     ASM_CASES_TAC `s:real^N->bool = {}` THEN
493     ASM_REWRITE_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH] THEN STRIP_TAC THEN
494     EXISTS_TAC `support (+) (f:real^N->real) s` THEN
495     EXISTS_TAC `f:real^N->real` THEN
496     MP_TAC(ASSUME `sum s (f:real^N->real) = &1`) THEN
497     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [sum] THEN
498     REWRITE_TAC[iterate] THEN COND_CASES_TAC THEN
499     ASM_REWRITE_TAC[NEUTRAL_REAL_ADD; REAL_OF_NUM_EQ; ARITH] THEN
500     DISCH_THEN(K ALL_TAC) THEN
501     UNDISCH_TAC `sum s (f:real^N->real) = &1` THEN
502     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM SUM_SUPPORT] THEN
503     ASM_CASES_TAC `support (+) (f:real^N->real) s = {}` THEN
504     ASM_SIMP_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH] THEN
505     DISCH_TAC THEN REWRITE_TAC[SUPPORT_SUBSET] THEN
506     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN
507     CONV_TAC SYM_CONV THEN MATCH_MP_TAC VSUM_SUPERSET THEN
508     REWRITE_TAC[SUPPORT_SUBSET] THEN
509     REWRITE_TAC[support; IN_ELIM_THM; NEUTRAL_REAL_ADD] THEN
510     MESON_TAC[VECTOR_MUL_LZERO]]);;
511
512 (* ------------------------------------------------------------------------- *)
513 (* Stepping theorems and hence small special cases.                          *)
514 (* ------------------------------------------------------------------------- *)
515
516 let AFFINE_HULL_EMPTY = prove
517  (`affine hull {} = {}`,
518   MATCH_MP_TAC HULL_UNIQUE THEN
519   REWRITE_TAC[SUBSET_REFL; AFFINE_EMPTY; EMPTY_SUBSET]);;
520
521 let AFFINE_HULL_EQ_EMPTY = prove
522  (`!s. (affine hull s = {}) <=> (s = {})`,
523   GEN_TAC THEN EQ_TAC THEN
524   MESON_TAC[SUBSET_EMPTY; HULL_SUBSET; AFFINE_HULL_EMPTY]);;
525
526 let AFFINE_HULL_FINITE_STEP_GEN = prove
527  (`!P:real^N->real->bool.
528         ((?u. (!x. x IN {} ==> P x (u x)) /\
529               sum {} u = w /\ vsum {} (\x. u(x) % x) = y) <=>
530          w = &0 /\ y = vec 0) /\
531         (FINITE(s:real^N->bool) /\
532          (!y. a IN s /\ P a y ==> P a (y / &2)) /\
533          (!x y. a IN s /\ P a x /\ P a y ==> P a (x + y))
534          ==> ((?u. (!x. x IN (a INSERT s) ==> P x (u x)) /\
535                    sum (a INSERT s) u = w /\
536                    vsum (a INSERT s) (\x. u(x) % x) = y) <=>
537               ?v u. P a v /\ (!x. x IN s ==> P x (u x)) /\
538                     sum s u = w - v /\
539                     vsum s (\x. u(x) % x) = y - v % a))`,
540   GEN_TAC THEN SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; NOT_IN_EMPTY] THEN
541   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN DISCH_TAC THEN
542   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_REWRITE_TAC[] THENL
543    [ASM_SIMP_TAC[SET_RULE `a IN s ==> a INSERT s = s`] THEN EQ_TAC THEN
544     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
545      [X_GEN_TAC `u:real^N->real` THEN STRIP_TAC THEN
546       EXISTS_TAC `(u:real^N->real) a / &2` THEN
547       EXISTS_TAC `\x:real^N. if x = a then u x / &2 else u x`;
548       MAP_EVERY X_GEN_TAC [`v:real`; `u:real^N->real`] THEN
549       STRIP_TAC THEN
550       EXISTS_TAC `\x:real^N. if x = a then u x + v else u x`] THEN
551     ASM_SIMP_TAC[] THEN (CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC]) THEN
552     ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
553     ASM_SIMP_TAC[VSUM_CASES; SUM_CASES] THEN
554     ASM_SIMP_TAC[GSYM DELETE; SUM_DELETE; VSUM_DELETE] THEN
555     ASM_SIMP_TAC[SET_RULE `a IN s ==> {x | x IN s /\ x = a} = {a}`] THEN
556     REWRITE_TAC[SUM_SING; VSUM_SING] THEN
557     (CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]);
558     EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
559      [X_GEN_TAC `u:real^N->real` THEN STRIP_TAC THEN
560       EXISTS_TAC `(u:real^N->real) a` THEN
561       EXISTS_TAC `u:real^N->real` THEN ASM_SIMP_TAC[IN_INSERT] THEN
562       REPEAT(FIRST_X_ASSUM(SUBST1_TAC o SYM)) THEN
563       CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC];
564       MAP_EVERY X_GEN_TAC [`v:real`; `u:real^N->real`] THEN
565       STRIP_TAC THEN
566       EXISTS_TAC `\x:real^N. if x = a then v:real else u x` THEN
567       ASM_SIMP_TAC[IN_INSERT] THEN CONJ_TAC THENL
568        [ASM_MESON_TAC[]; ALL_TAC] THEN
569       ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
570       ASM_SIMP_TAC[VSUM_CASES; SUM_CASES] THEN
571       ASM_SIMP_TAC[GSYM DELETE; SUM_DELETE; VSUM_DELETE] THEN
572       ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> {x | x IN s /\ x = a} = {}`] THEN
573       ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> s DELETE a = s`] THEN
574       REWRITE_TAC[SUM_CLAUSES; VSUM_CLAUSES] THEN
575       CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]]]);;
576
577 let AFFINE_HULL_FINITE_STEP = prove
578  (`((?u. sum {} u = w /\ vsum {} (\x. u(x) % x) = y) <=>
579     w = &0 /\ y = vec 0) /\
580    (FINITE(s:real^N->bool)
581     ==> ((?u. sum (a INSERT s) u = w /\
582               vsum (a INSERT s) (\x. u(x) % x) = y) <=>
583          ?v u.  sum s u = w - v /\
584                 vsum s (\x. u(x) % x) = y - v % a))`,
585   MATCH_ACCEPT_TAC (REWRITE_RULE[]
586    (ISPEC `\x:real^N y:real. T` AFFINE_HULL_FINITE_STEP_GEN)));;
587
588 let AFFINE_HULL_2 = prove
589  (`!a b. affine hull {a,b} =
590          {u % a + v % b | u + v = &1}`,
591   SIMP_TAC[AFFINE_HULL_FINITE; FINITE_INSERT; FINITE_RULES] THEN
592   SIMP_TAC[AFFINE_HULL_FINITE_STEP; FINITE_INSERT; FINITE_RULES] THEN
593   REWRITE_TAC[REAL_ARITH `x - y = z:real <=> x = y + z`;
594               VECTOR_ARITH `x - y = z:real^N <=> x = y + z`] THEN
595   REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN SET_TAC[]);;
596
597 let AFFINE_HULL_2_ALT = prove
598  (`!a b. affine hull {a,b} = {a + u % (b - a) | u IN (:real)}`,
599   REPEAT GEN_TAC THEN REWRITE_TAC[AFFINE_HULL_2] THEN
600   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
601   REWRITE_TAC[IN_ELIM_THM; IN_UNIV; ARITH_RULE `u + v = &1 <=> v = &1 - u`;
602     FORALL_UNWIND_THM2; UNWIND_THM2] THEN
603   CONJ_TAC THEN X_GEN_TAC `u:real` THEN EXISTS_TAC `&1 - u` THEN
604   VECTOR_ARITH_TAC);;
605
606 let AFFINE_HULL_3 = prove
607  (`affine hull {a,b,c} =
608     { u % a + v % b + w % c | u + v + w = &1}`,
609   SIMP_TAC[AFFINE_HULL_FINITE; FINITE_INSERT; FINITE_RULES] THEN
610   SIMP_TAC[AFFINE_HULL_FINITE_STEP; FINITE_INSERT; FINITE_RULES] THEN
611   REWRITE_TAC[REAL_ARITH `x - y = z:real <=> x = y + z`;
612               VECTOR_ARITH `x - y = z:real^N <=> x = y + z`] THEN
613   REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN SET_TAC[]);;
614
615 (* ------------------------------------------------------------------------- *)
616 (* Some relations between affine hull and subspaces.                         *)
617 (* ------------------------------------------------------------------------- *)
618
619 let AFFINE_HULL_INSERT_SUBSET_SPAN = prove
620  (`!a:real^N s.
621      affine hull (a INSERT s) SUBSET {a + v | v | v IN span {x - a | x IN s}}`,
622   REPEAT GEN_TAC THEN GEN_REWRITE_TAC I [SUBSET] THEN
623   REWRITE_TAC[AFFINE_HULL_EXPLICIT; SPAN_EXPLICIT; IN_ELIM_THM] THEN
624   REWRITE_TAC[SIMPLE_IMAGE; CONJ_ASSOC; FINITE_SUBSET_IMAGE] THEN
625   REWRITE_TAC[MESON[]
626    `(?s u. (?t. P t /\ s = f t) /\ Q s u) <=>
627     (?t u. P t /\ Q (f t) u)`] THEN
628   REWRITE_TAC[MESON[]
629    `(?v. (?s u. P s /\ f s u = v) /\ (x = g a v)) <=>
630     (?s u. ~(P s ==> ~(g a (f s u) = x)))`] THEN
631   SIMP_TAC[VSUM_IMAGE; VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
632   REWRITE_TAC[o_DEF] THEN X_GEN_TAC `y:real^N` THEN
633   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
634   MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `u:real^N->real`] THEN
635   DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC (SUBST1_TAC o SYM)) THEN
636   MAP_EVERY EXISTS_TAC
637    [`t DELETE (a:real^N)`; `\x. (u:real^N->real)(x + a)`] THEN
638   ASM_SIMP_TAC[FINITE_DELETE; VECTOR_SUB_ADD; SET_RULE
639    `t SUBSET (a INSERT s) ==> t DELETE a SUBSET s`] THEN
640   MATCH_MP_TAC EQ_TRANS THEN
641   EXISTS_TAC `a + vsum t (\x. u x % (x - a)):real^N` THEN CONJ_TAC THENL
642    [AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC VSUM_SUPERSET THEN
643     REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN SET_TAC[];
644     ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; FINITE_DELETE; VSUM_SUB] THEN
645     ASM_REWRITE_TAC[VSUM_RMUL] THEN
646     REWRITE_TAC[VECTOR_ARITH `a + x - &1 % a:real^N = x`]]);;
647
648 let AFFINE_HULL_INSERT_SPAN = prove
649  (`!a:real^N s.
650         ~(a IN s)
651         ==> affine hull (a INSERT s) =
652             {a + v | v | v IN span {x - a | x IN s}}`,
653   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
654   REWRITE_TAC[AFFINE_HULL_INSERT_SUBSET_SPAN] THEN REWRITE_TAC[SUBSET] THEN
655   REWRITE_TAC[AFFINE_HULL_EXPLICIT; SPAN_EXPLICIT; IN_ELIM_THM] THEN
656   REWRITE_TAC[SIMPLE_IMAGE; CONJ_ASSOC; FINITE_SUBSET_IMAGE] THEN
657   REWRITE_TAC[MESON[]
658    `(?s u. (?t. P t /\ s = f t) /\ Q s u) <=>
659     (?t u. P t /\ Q (f t) u)`] THEN
660   REWRITE_TAC[MESON[]
661    `(?v. (?s u. P s /\ f s u = v) /\ (x = g a v)) <=>
662     (?s u. ~(P s ==> ~(g a (f s u) = x)))`] THEN
663   SIMP_TAC[VSUM_IMAGE; VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
664   REWRITE_TAC[o_DEF] THEN X_GEN_TAC `y:real^N` THEN
665   REWRITE_TAC[NOT_IMP; LEFT_IMP_EXISTS_THM] THEN
666   MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `u:real^N->real`] THEN
667   DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC (SUBST1_TAC o SYM)) THEN
668   MAP_EVERY EXISTS_TAC
669    [`(a:real^N) INSERT t`;
670     `\x. if x = a then &1 - sum t (\x. u(x - a))
671          else (u:real^N->real)(x - a)`] THEN
672   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES] THEN
673   ASM_CASES_TAC `(a:real^N) IN t` THENL [ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
674   ASM_SIMP_TAC[FINITE_INSERT; NOT_INSERT_EMPTY;
675                SET_RULE `s SUBSET t ==> (a INSERT s) SUBSET (a INSERT t)`] THEN
676   SUBGOAL_THEN `!x:real^N. x IN t ==> ~(x = a)` MP_TAC THENL
677    [ASM SET_TAC[]; SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC)] THEN
678   CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
679   ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; FINITE_DELETE; VSUM_SUB] THEN
680   ASM_REWRITE_TAC[VSUM_RMUL] THEN VECTOR_ARITH_TAC);;
681
682 let AFFINE_HULL_SPAN = prove
683  (`!a:real^N s.
684         a IN s
685         ==> (affine hull s =
686              {a + v | v | v IN span {x - a | x | x IN (s DELETE a)}})`,
687   REPEAT STRIP_TAC THEN
688   MP_TAC(ISPECL [`a:real^N`; `s DELETE (a:real^N)`]
689     AFFINE_HULL_INSERT_SPAN) THEN
690   ASM_REWRITE_TAC[IN_DELETE] THEN
691   DISCH_THEN(SUBST1_TAC o SYM) THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
692
693 let DIFFS_AFFINE_HULL_SPAN = prove
694  (`!a:real^N s.
695         a IN s ==> {x - a | x IN affine hull s} = span {x - a | x IN s}`,
696   REPEAT STRIP_TAC THEN
697   FIRST_ASSUM(SUBST1_TAC o MATCH_MP AFFINE_HULL_SPAN) THEN
698   REWRITE_TAC[SIMPLE_IMAGE; GSYM IMAGE_o; o_DEF; VECTOR_ADD_SUB; IMAGE_ID] THEN
699   SIMP_TAC[IMAGE_DELETE_INJ;
700            VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
701   REWRITE_TAC[VECTOR_SUB_REFL; SPAN_DELETE_0]);;
702
703 let AFFINE_HULL_SING = prove
704  (`!a. affine hull {a} = {a}`,
705   SIMP_TAC[AFFINE_HULL_INSERT_SPAN; NOT_IN_EMPTY] THEN
706   REWRITE_TAC[SET_RULE `{f x | x | F} = {}`; SPAN_EMPTY] THEN
707   REWRITE_TAC[SET_RULE `{f x | x IN {a}} = {f a}`; VECTOR_ADD_RID]);;
708
709 let AFFINE_HULL_EQ_SING = prove
710  (`!s a:real^N. affine hull s = {a} <=> s = {a}`,
711   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
712   ASM_REWRITE_TAC[AFFINE_HULL_EMPTY] THEN
713   EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[AFFINE_HULL_SING] THEN
714   MATCH_MP_TAC(SET_RULE `~(s = {}) /\ s SUBSET {a} ==> s = {a}`) THEN
715   ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
716   REWRITE_TAC[HULL_SUBSET]);;
717
718 (* ------------------------------------------------------------------------- *)
719 (* Convexity.                                                                *)
720 (* ------------------------------------------------------------------------- *)
721
722 let convex = new_definition
723   `convex s <=>
724         !x y u v. x IN s /\ y IN s /\ &0 <= u /\ &0 <= v /\ (u + v = &1)
725                   ==> (u % x + v % y) IN s`;;
726
727 let CONVEX_ALT = prove
728  (`convex s <=> !x y u. x IN s /\ y IN s /\ &0 <= u /\ u <= &1
729                         ==> ((&1 - u) % x + u % y) IN s`,
730   REWRITE_TAC[convex] THEN
731   MESON_TAC[REAL_ARITH `&0 <= u /\ &0 <= v /\ (u + v = &1)
732                         ==> v <= &1 /\ (u = &1 - v)`;
733             REAL_ARITH `u <= &1 ==> &0 <= &1 - u /\ ((&1 - u) + u = &1)`]);;
734
735 let IN_CONVEX_SET = prove
736  (`!s a b u.
737         convex s /\ a IN s /\ b IN s /\ &0 <= u /\ u <= &1
738         ==> ((&1 - u) % a + u % b) IN s`,
739   MESON_TAC[CONVEX_ALT]);;
740
741 let MIDPOINT_IN_CONVEX = prove
742  (`!s x y:real^N.
743         convex s /\ x IN s /\ y IN s ==> midpoint(x,y) IN s`,
744   REPEAT STRIP_TAC THEN
745   MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`; `y:real^N`; `&1 / &2`]
746         IN_CONVEX_SET) THEN
747   ASM_REWRITE_TAC[midpoint] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
748   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN
749   CONV_TAC VECTOR_ARITH);;
750
751 let CONVEX_CONTAINS_SEGMENT = prove
752  (`!s. convex s <=> !a b. a IN s /\ b IN s ==> segment[a,b] SUBSET s`,
753   REWRITE_TAC[CONVEX_ALT; segment; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
754
755 let CONVEX_CONTAINS_OPEN_SEGMENT = prove
756  (`!s. convex s <=> !a b. a IN s /\ b IN s ==> segment(a,b) SUBSET s`,
757   ONCE_REWRITE_TAC[segment] THEN REWRITE_TAC[CONVEX_CONTAINS_SEGMENT] THEN
758   SET_TAC[]);;
759
760 let CONVEX_CONTAINS_SEGMENT_EQ = prove
761  (`!s:real^N->bool.
762         convex s <=> !a b. segment[a,b] SUBSET s <=> a IN s /\ b IN s`,
763   REWRITE_TAC[CONVEX_CONTAINS_SEGMENT; SUBSET] THEN
764   MESON_TAC[ENDS_IN_SEGMENT]);;
765
766 let CONVEX_CONTAINS_SEGMENT_IMP = prove
767  (`!s a b. convex s ==> (segment[a,b] SUBSET s <=> a IN s /\ b IN s)`,
768   SIMP_TAC[CONVEX_CONTAINS_SEGMENT_EQ]);;
769
770 let CONVEX_EMPTY = prove
771  (`convex {}`,
772   REWRITE_TAC[convex; NOT_IN_EMPTY]);;
773
774 let CONVEX_SING = prove
775  (`!a. convex {a}`,
776   SIMP_TAC[convex; IN_SING; GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID]);;
777
778 let CONVEX_UNIV = prove
779  (`convex(UNIV:real^N->bool)`,
780   REWRITE_TAC[convex; IN_UNIV]);;
781
782 let CONVEX_INTERS = prove
783  (`(!s. s IN f ==> convex s) ==> convex(INTERS f)`,
784   REWRITE_TAC[convex; IN_INTERS] THEN MESON_TAC[]);;
785
786 let CONVEX_INTER = prove
787  (`!s t. convex s /\ convex t ==> convex(s INTER t)`,
788   REWRITE_TAC[convex; IN_INTER] THEN MESON_TAC[]);;
789
790 let CONVEX_HALFSPACE_LE = prove
791  (`!a b. convex {x | a dot x <= b}`,
792   REWRITE_TAC[convex; IN_ELIM_THM; DOT_RADD; DOT_RMUL] THEN
793   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN
794   EXISTS_TAC `(u + v) * b` THEN CONJ_TAC THENL
795    [ASM_MESON_TAC[REAL_ADD_RDISTRIB; REAL_LE_ADD2; REAL_LE_LMUL];
796     ASM_MESON_TAC[REAL_MUL_LID; REAL_LE_REFL]]);;
797
798 let CONVEX_HALFSPACE_COMPONENT_LE = prove
799  (`!a k. convex {x:real^N | x$k <= a}`,
800   REPEAT GEN_TAC THEN
801   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
802   CHOOSE_TAC THENL
803    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
804   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HALFSPACE_LE) THEN
805   ASM_SIMP_TAC[DOT_BASIS]);;
806
807 let CONVEX_HALFSPACE_GE = prove
808  (`!a b. convex {x:real^N | a dot x >= b}`,
809   REPEAT GEN_TAC THEN
810   SUBGOAL_THEN `{x:real^N | a dot x >= b} = {x | --a dot x <= --b}`
811    (fun th -> REWRITE_TAC[th; CONVEX_HALFSPACE_LE]) THEN
812   REWRITE_TAC[EXTENSION; IN_ELIM_THM; DOT_LNEG] THEN REAL_ARITH_TAC);;
813
814 let CONVEX_HALFSPACE_COMPONENT_GE = prove
815  (`!a k. convex {x:real^N | x$k >= a}`,
816   REPEAT GEN_TAC THEN
817   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
818   CHOOSE_TAC THENL
819    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
820   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HALFSPACE_GE) THEN
821   ASM_SIMP_TAC[DOT_BASIS]);;
822
823 let CONVEX_HYPERPLANE = prove
824  (`!a b. convex {x:real^N | a dot x = b}`,
825   REPEAT GEN_TAC THEN
826   SUBGOAL_THEN
827    `{x:real^N | a dot x = b} = {x | a dot x <= b} INTER {x | a dot x >= b}`
828    (fun th -> SIMP_TAC[th; CONVEX_INTER;
829                        CONVEX_HALFSPACE_LE; CONVEX_HALFSPACE_GE]) THEN
830   REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
831
832 let CONVEX_STANDARD_HYPERPLANE = prove
833  (`!k a. convex {x:real^N | x$k = a}`,
834   REPEAT GEN_TAC THEN
835   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
836   CHOOSE_TAC THENL
837    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
838   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HYPERPLANE) THEN
839   ASM_SIMP_TAC[DOT_BASIS]);;
840
841 let CONVEX_HALFSPACE_LT = prove
842  (`!a b. convex {x | a dot x < b}`,
843   REWRITE_TAC[convex; IN_ELIM_THM; DOT_RADD; DOT_RMUL] THEN
844   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_CONVEX_BOUND_LT THEN
845   ASM_REWRITE_TAC[]);;
846
847 let CONVEX_HALFSPACE_COMPONENT_LT = prove
848  (`!a k. convex {x:real^N | x$k < a}`,
849   REPEAT GEN_TAC THEN
850   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
851   CHOOSE_TAC THENL
852    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
853   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HALFSPACE_LT) THEN
854   ASM_SIMP_TAC[DOT_BASIS]);;
855
856 let CONVEX_HALFSPACE_GT = prove
857  (`!a b. convex {x | a dot x > b}`,
858   REWRITE_TAC[REAL_ARITH `ax > b <=> --ax < --b`] THEN
859   REWRITE_TAC[GSYM DOT_LNEG; CONVEX_HALFSPACE_LT]);;
860
861 let CONVEX_HALFSPACE_COMPONENT_GT = prove
862  (`!a k. convex {x:real^N | x$k > a}`,
863   REPEAT GEN_TAC THEN
864   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
865   CHOOSE_TAC THENL
866    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
867   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CONVEX_HALFSPACE_GT) THEN
868   ASM_SIMP_TAC[DOT_BASIS]);;
869
870 let CONVEX_POSITIVE_ORTHANT = prove
871  (`convex {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
872                           ==> &0 <= x$i}`,
873   SIMP_TAC[convex; IN_ELIM_THM; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
874            REAL_LE_MUL; REAL_LE_ADD]);;
875
876 let LIMPT_OF_CONVEX = prove
877  (`!s x:real^N.
878         convex s /\ x IN s ==> (x limit_point_of s <=> ~(s = {x}))`,
879   REPEAT STRIP_TAC THEN
880   ASM_CASES_TAC `s = {x:real^N}` THEN ASM_REWRITE_TAC[LIMPT_SING] THEN
881   SUBGOAL_THEN `?y:real^N. y IN s /\ ~(y = x)` STRIP_ASSUME_TAC THENL
882    [ASM SET_TAC[]; ALL_TAC] THEN
883   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
884   ABBREV_TAC `u = min (&1 / &2) (e / &2 / norm(y - x:real^N))` THEN
885   SUBGOAL_THEN `&0 < u /\ u < &1` STRIP_ASSUME_TAC THENL
886    [EXPAND_TAC "u" THEN REWRITE_TAC[REAL_LT_MIN; REAL_MIN_LT] THEN
887     CONV_TAC REAL_RAT_REDUCE_CONV THEN
888     ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ];
889     ALL_TAC] THEN
890   EXISTS_TAC `(&1 - u) % x + u % y:real^N` THEN REPEAT CONJ_TAC THENL
891    [FIRST_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
892     ASM_SIMP_TAC[REAL_LT_IMP_LE];
893     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ; VECTOR_ARITH
894      `(&1 - u) % x + u % y:real^N = x <=> u % (y - x) = vec 0`] THEN
895     ASM_REAL_ARITH_TAC;
896     REWRITE_TAC[dist; NORM_MUL; VECTOR_ARITH
897      `((&1 - u) % x + u % y) - x:real^N = u % (y - x)`] THEN
898     ASM_SIMP_TAC[REAL_ARITH `&0 < u ==> abs u = u`] THEN
899     MATCH_MP_TAC(REAL_ARITH `x <= e / &2 /\ &0 < e ==> x < e`) THEN
900     ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
901     ASM_REAL_ARITH_TAC]);;
902
903 let TRIVIAL_LIMIT_WITHIN_CONVEX = prove
904  (`!s x:real^N.
905         convex s /\ x IN s ==> (trivial_limit(at x within s) <=> s = {x})`,
906   SIMP_TAC[TRIVIAL_LIMIT_WITHIN; LIMPT_OF_CONVEX]);;
907
908 (* ------------------------------------------------------------------------- *)
909 (* Some invariance theorems for convex sets.                                 *)
910 (* ------------------------------------------------------------------------- *)
911
912 let CONVEX_TRANSLATION_EQ = prove
913  (`!a:real^N s. convex (IMAGE (\x. a + x) s) <=> convex s`,
914   REWRITE_TAC[CONVEX_ALT; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
915   REWRITE_TAC[IN_IMAGE; UNWIND_THM1; VECTOR_ARITH
916    `(&1 - u) % (a + x) + u % (a + y) = a + z <=> (&1 - u) % x + u % y = z`]);;
917
918 add_translation_invariants [CONVEX_TRANSLATION_EQ];;
919
920 let CONVEX_TRANSLATION = prove
921  (`!s a:real^N. convex s ==> convex (IMAGE (\x. a + x) s)`,
922   REWRITE_TAC[CONVEX_TRANSLATION_EQ]);;
923
924 let CONVEX_LINEAR_IMAGE = prove
925  (`!f s. convex s /\ linear f ==> convex(IMAGE f s)`,
926   REWRITE_TAC[convex; FORALL_IN_IMAGE; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
927   REWRITE_TAC[IN_IMAGE; linear] THEN MESON_TAC[]);;
928
929 let CONVEX_LINEAR_IMAGE_EQ = prove
930  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
931          ==> (convex (IMAGE f s) <=> convex s)`,
932   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE CONVEX_LINEAR_IMAGE));;
933
934 add_linear_invariants [CONVEX_LINEAR_IMAGE_EQ];;
935
936 (* ------------------------------------------------------------------------- *)
937 (* Explicit expressions for convexity in terms of arbitrary sums.            *)
938 (* ------------------------------------------------------------------------- *)
939
940 let CONVEX_VSUM = prove
941  (`!s k u x:A->real^N.
942         FINITE k /\ convex s /\ sum k u = &1 /\
943         (!i. i IN k ==> &0 <= u i /\ x i IN s)
944         ==> vsum k (\i. u i % x i) IN s`,
945   GEN_TAC THEN ASM_CASES_TAC `convex(s:real^N->bool)` THEN
946   ASM_REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
947   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
948   SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FORALL_IN_INSERT] THEN
949   CONV_TAC REAL_RAT_REDUCE_CONV THEN
950   MAP_EVERY X_GEN_TAC [`i:A`; `k:A->bool`] THEN
951   GEN_REWRITE_TAC (BINOP_CONV o DEPTH_CONV) [RIGHT_IMP_FORALL_THM] THEN
952   REWRITE_TAC[IMP_IMP] THEN STRIP_TAC THEN
953   MAP_EVERY X_GEN_TAC [`u:A->real`; `x:A->real^N`] THEN
954   ASM_CASES_TAC `(u:A->real) i = &1` THENL
955    [ASM_REWRITE_TAC[REAL_ARITH `&1 + a  = &1 <=> a = &0`] THEN
956     STRIP_TAC THEN
957     SUBGOAL_THEN `vsum k (\i:A. u i % x(i):real^N) = vec 0`
958      (fun th -> ASM_SIMP_TAC[th; VECTOR_ADD_RID; VECTOR_MUL_LID]) THEN
959     MATCH_MP_TAC VSUM_EQ_0 THEN REWRITE_TAC[VECTOR_MUL_EQ_0] THEN
960     REPEAT STRIP_TAC THEN DISJ1_TAC THEN
961     ASM_MESON_TAC[SUM_POS_EQ_0];
962     STRIP_TAC THEN
963     FIRST_X_ASSUM(MP_TAC o SPEC `\j:A. u(j) / (&1 - u(i))`) THEN
964     ASM_REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
965     ASM_SIMP_TAC[SUM_LMUL; VSUM_LMUL; GSYM VECTOR_MUL_ASSOC] THEN
966     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN
967     SUBGOAL_THEN `&0 < &1 - u(i:A)` ASSUME_TAC THENL
968      [ASM_MESON_TAC[SUM_POS_LE; REAL_ADD_SYM; REAL_ARITH
969        `&0 <= a /\ &0 <= b /\ b + a = &1 /\ ~(a = &1) ==> &0 < &1 - a`];
970       ALL_TAC] THEN
971     ASM_SIMP_TAC[REAL_LE_DIV; REAL_LT_IMP_LE] THEN
972     ASM_SIMP_TAC[REAL_EQ_LDIV_EQ; REAL_MUL_LID; REAL_EQ_SUB_LADD] THEN
973     DISCH_TAC THEN ONCE_REWRITE_TAC[VECTOR_ADD_SYM] THEN
974     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex]) THEN
975     DISCH_THEN(MP_TAC o SPECL
976      [`vsum k (\j. (u j / (&1 - u(i:A))) % x(j) :real^N)`;
977       `x(i:A):real^N`; `&1 - u(i:A)`; `u(i:A):real`]) THEN
978     REWRITE_TAC[real_div] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
979     ASM_SIMP_TAC[GSYM VECTOR_MUL_ASSOC; VSUM_LMUL] THEN
980     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; REAL_LT_IMP_NZ] THEN
981     REWRITE_TAC[VECTOR_MUL_LID] THEN DISCH_THEN MATCH_MP_TAC THEN
982     ASM_SIMP_TAC[REAL_LT_IMP_LE; VSUM_LMUL] THEN
983     CONJ_TAC THENL [FIRST_X_ASSUM MATCH_MP_TAC; REAL_ARITH_TAC] THEN
984     ASM_MESON_TAC[REAL_ADD_SYM]]);;
985
986 let CONVEX_VSUM_STRONG = prove
987  (`!s k u x:A->real^N.
988         convex s /\
989         sum k u = &1 /\
990         (!i. i IN k ==> &0 <= u i /\ (u i = &0 \/ x i IN s))
991         ==> vsum k (\i. u i % x i) IN s`,
992   REPEAT STRIP_TAC THEN
993   SUBGOAL_THEN
994    `vsum k (\i. u i % (x:A->real^N) i) =
995     vsum {i | i IN k /\ ~(u i = &0)} (\i. u i % x i)`
996   SUBST1_TAC THENL
997    [MATCH_MP_TAC VSUM_SUPERSET THEN REWRITE_TAC[VECTOR_MUL_EQ_0] THEN
998     SET_TAC[];
999     MATCH_MP_TAC CONVEX_VSUM THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
1000      [ASM_MESON_TAC[SUM_DEGENERATE; REAL_ARITH `~(&1 = &0)`];
1001       FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
1002       CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_SUPERSET THEN ASM SET_TAC[];
1003       ASM SET_TAC[]]]);;
1004
1005 let CONVEX_INDEXED = prove
1006  (`!s:real^N->bool.
1007         convex s <=>
1008             !k u x. (!i:num. 1 <= i /\ i <= k ==> &0 <= u(i) /\ x(i) IN s) /\
1009                     (sum (1..k) u = &1)
1010                     ==> vsum (1..k) (\i. u(i) % x(i)) IN s`,
1011   REPEAT GEN_TAC THEN EQ_TAC THENL
1012    [REPEAT STRIP_TAC THEN MATCH_MP_TAC CONVEX_VSUM THEN
1013     ASM_REWRITE_TAC[IN_NUMSEG; FINITE_NUMSEG];
1014     DISCH_TAC THEN REWRITE_TAC[convex] THEN
1015     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
1016     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `2`) THEN
1017     DISCH_THEN(MP_TAC o SPEC `\n. if n = 1 then u else v:real`) THEN
1018     DISCH_THEN(MP_TAC o SPEC `\n. if n = 1 then x else y:real^N`) THEN
1019     REWRITE_TAC[num_CONV `2`; SUM_CLAUSES_NUMSEG; VSUM_CLAUSES_NUMSEG;
1020       NUMSEG_SING; VSUM_SING; SUM_SING] THEN REWRITE_TAC[ARITH] THEN
1021     ASM_MESON_TAC[]]);;
1022
1023 let CONVEX_EXPLICIT = prove
1024  (`!s:real^N->bool.
1025         convex s <=>
1026         !t u. FINITE t /\ t SUBSET s /\ (!x. x IN t ==> &0 <= u x) /\
1027               sum t u = &1
1028               ==> vsum t (\x. u(x) % x) IN s`,
1029   REPEAT GEN_TAC THEN EQ_TAC THENL
1030    [REPEAT STRIP_TAC THEN MATCH_MP_TAC CONVEX_VSUM THEN
1031     ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
1032     DISCH_TAC THEN REWRITE_TAC[convex] THEN
1033     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
1034     ASM_CASES_TAC `x:real^N = y` THENL
1035      [ASM_SIMP_TAC[GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID]; ALL_TAC] THEN
1036     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `{x:real^N,y}`) THEN
1037     DISCH_THEN(MP_TAC o SPEC `\z:real^N. if z = x then u else v:real`) THEN
1038     ASM_SIMP_TAC[FINITE_INSERT; FINITE_RULES; SUM_CLAUSES; VSUM_CLAUSES;
1039                  NOT_IN_EMPTY] THEN
1040     ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; REAL_ADD_RID; SUBSET] THEN
1041     REWRITE_TAC[VECTOR_ADD_RID] THEN ASM_MESON_TAC[]]);;
1042
1043 let CONVEX = prove
1044  (`!V:real^N->bool.
1045      convex V <=>
1046          !(s:real^N->bool) (u:real^N->real).
1047              FINITE s /\ ~(s = {}) /\ s SUBSET V /\
1048              (!x. x IN s ==> &0 <= u x) /\ sum s u = &1
1049              ==> vsum s (\x. u x % x) IN V`,
1050   GEN_TAC THEN REWRITE_TAC[CONVEX_EXPLICIT] THEN
1051   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
1052   X_GEN_TAC `t:real^N->bool` THEN REWRITE_TAC[] THEN
1053   AP_TERM_TAC THEN ABS_TAC THEN
1054   ASM_CASES_TAC `t:real^N->bool = {}` THEN
1055   ASM_REWRITE_TAC[SUM_CLAUSES] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
1056
1057 let CONVEX_FINITE = prove
1058  (`!s:real^N->bool.
1059         FINITE s
1060         ==> (convex s <=>
1061                 !u. (!x. x IN s ==> &0 <= u x) /\
1062                     sum s u = &1
1063                     ==> vsum s (\x. u(x) % x) IN s)`,
1064   REPEAT STRIP_TAC THEN REWRITE_TAC[CONVEX_EXPLICIT] THEN
1065   EQ_TAC THENL [ASM_MESON_TAC[SUBSET_REFL]; ALL_TAC] THEN
1066   DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `u:real^N->real`] THEN
1067   STRIP_TAC THEN
1068   FIRST_X_ASSUM(MP_TAC o SPEC `\x:real^N. if x IN t then u x else &0`) THEN
1069   ASM_SIMP_TAC[GSYM SUM_RESTRICT_SET] THEN
1070   ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
1071   ASM_SIMP_TAC[VECTOR_MUL_LZERO; REAL_LE_REFL; GSYM VSUM_RESTRICT_SET] THEN
1072   ASM_SIMP_TAC[COND_ID; SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`]);;
1073
1074 let AFFINE_PCROSS = prove
1075  (`!s:real^M->bool t:real^N->bool.
1076         affine s /\ affine t ==> affine(s PCROSS t)`,
1077   REWRITE_TAC[affine; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1078   SIMP_TAC[FORALL_IN_PCROSS; GSYM PASTECART_CMUL; PASTECART_ADD] THEN
1079   SIMP_TAC[PASTECART_IN_PCROSS]);;
1080
1081 let AFFINE_PCROSS_EQ = prove
1082  (`!s:real^M->bool t:real^N->bool.
1083         affine(s PCROSS t) <=> s = {} \/ t = {} \/ affine s /\ affine t`,
1084   REPEAT GEN_TAC THEN
1085   ASM_CASES_TAC `s:real^M->bool = {}` THEN
1086   ASM_REWRITE_TAC[PCROSS_EMPTY; AFFINE_EMPTY] THEN
1087   ASM_CASES_TAC `t:real^N->bool = {}` THEN
1088   ASM_REWRITE_TAC[PCROSS_EMPTY; AFFINE_EMPTY] THEN
1089   EQ_TAC THEN REWRITE_TAC[AFFINE_PCROSS] THEN REPEAT STRIP_TAC THENL
1090    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
1091       `(s:real^M->bool) PCROSS (t:real^N->bool)`] AFFINE_LINEAR_IMAGE) THEN
1092     ASM_REWRITE_TAC[LINEAR_FSTCART];
1093     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
1094       `(s:real^M->bool) PCROSS (t:real^N->bool)`] AFFINE_LINEAR_IMAGE) THEN
1095     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
1096   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
1097   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
1098               FSTCART_PASTECART; SNDCART_PASTECART] THEN
1099   ASM SET_TAC[]);;
1100
1101 let CONVEX_PCROSS = prove
1102  (`!s:real^M->bool t:real^N->bool.
1103         convex s /\ convex t ==> convex(s PCROSS t)`,
1104   REWRITE_TAC[convex; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1105   SIMP_TAC[FORALL_IN_PCROSS; GSYM PASTECART_CMUL; PASTECART_ADD] THEN
1106   SIMP_TAC[PASTECART_IN_PCROSS]);;
1107
1108 let CONVEX_PCROSS_EQ = prove
1109  (`!s:real^M->bool t:real^N->bool.
1110         convex(s PCROSS t) <=> s = {} \/ t = {} \/ convex s /\ convex t`,
1111   REPEAT GEN_TAC THEN
1112   ASM_CASES_TAC `s:real^M->bool = {}` THEN
1113   ASM_REWRITE_TAC[PCROSS_EMPTY; CONVEX_EMPTY] THEN
1114   ASM_CASES_TAC `t:real^N->bool = {}` THEN
1115   ASM_REWRITE_TAC[PCROSS_EMPTY; CONVEX_EMPTY] THEN
1116   EQ_TAC THEN REWRITE_TAC[CONVEX_PCROSS] THEN REPEAT STRIP_TAC THENL
1117    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
1118       `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONVEX_LINEAR_IMAGE) THEN
1119     ASM_REWRITE_TAC[LINEAR_FSTCART];
1120     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
1121       `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONVEX_LINEAR_IMAGE) THEN
1122     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
1123   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
1124   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
1125               FSTCART_PASTECART; SNDCART_PASTECART] THEN
1126   ASM SET_TAC[]);;
1127
1128 (* ------------------------------------------------------------------------- *)
1129 (* Conic sets and conic hull.                                                *)
1130 (* ------------------------------------------------------------------------- *)
1131
1132 let conic = new_definition
1133   `conic s <=> !x c. x IN s /\ &0 <= c ==> (c % x) IN s`;;
1134
1135 let SUBSPACE_IMP_CONIC = prove
1136  (`!s. subspace s ==> conic s`,
1137   SIMP_TAC[subspace; conic]);;
1138
1139 let CONIC_EMPTY = prove
1140  (`conic {}`,
1141   REWRITE_TAC[conic; NOT_IN_EMPTY]);;
1142
1143 let CONIC_UNIV = prove
1144  (`conic (UNIV:real^N->bool)`,
1145   REWRITE_TAC[conic; IN_UNIV]);;
1146
1147 let CONIC_INTERS = prove
1148  (`(!s. s IN f ==> conic s) ==> conic(INTERS f)`,
1149   REWRITE_TAC[conic; IN_INTERS] THEN MESON_TAC[]);;
1150
1151 let CONIC_LINEAR_IMAGE = prove
1152  (`!f s. conic s /\ linear f ==> conic(IMAGE f s)`,
1153   REWRITE_TAC[conic; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
1154   REWRITE_TAC[IN_IMAGE] THEN MESON_TAC[LINEAR_CMUL]);;
1155
1156 let CONIC_LINEAR_IMAGE_EQ = prove
1157  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
1158          ==> (conic (IMAGE f s) <=> conic s)`,
1159   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE CONIC_LINEAR_IMAGE));;
1160
1161 add_linear_invariants [CONIC_LINEAR_IMAGE_EQ];;
1162
1163 let CONIC_CONIC_HULL = prove
1164  (`!s. conic(conic hull s)`,
1165   SIMP_TAC[P_HULL; CONIC_INTERS]);;
1166
1167 let CONIC_HULL_EQ = prove
1168  (`!s. (conic hull s = s) <=> conic s`,
1169   SIMP_TAC[HULL_EQ; CONIC_INTERS]);;
1170
1171 let CONIC_NEGATIONS = prove
1172  (`!s. conic s ==> conic (IMAGE (--) s)`,
1173   REWRITE_TAC[conic; RIGHT_FORALL_IMP_THM; IMP_CONJ; FORALL_IN_IMAGE] THEN
1174   REWRITE_TAC[IN_IMAGE; VECTOR_MUL_RNEG] THEN MESON_TAC[]);;
1175
1176 let CONIC_SPAN = prove
1177  (`!s. conic(span s)`,
1178   SIMP_TAC[SUBSPACE_IMP_CONIC; SUBSPACE_SPAN]);;
1179
1180 let CONIC_HULL_EXPLICIT = prove
1181  (`!s:real^N->bool. conic hull s = {c % x | &0 <= c /\ x IN s}`,
1182   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN
1183   REWRITE_TAC[conic; SUBSET; RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
1184   REWRITE_TAC[FORALL_IN_GSPEC] THEN
1185   REWRITE_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP; IN_ELIM_THM] THEN
1186   REPEAT CONJ_TAC THENL
1187    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1188     MAP_EVERY EXISTS_TAC [`&1`; `x:real^N`] THEN
1189     ASM_SIMP_TAC[REAL_POS; VECTOR_MUL_LID];
1190     REWRITE_TAC[VECTOR_MUL_ASSOC] THEN MESON_TAC[REAL_LE_MUL];
1191     MESON_TAC[]]);;
1192
1193 let CONIC_HULL_LINEAR_IMAGE = prove
1194  (`!f s. linear f ==> conic hull (IMAGE f s) = IMAGE f (conic hull s)`,
1195   REPEAT GEN_TAC THEN REWRITE_TAC[CONIC_HULL_EXPLICIT] THEN
1196   REWRITE_TAC[SET_RULE `IMAGE f {c % x | P c x} = {f(c % x) | P c x}`] THEN
1197   REWRITE_TAC[SET_RULE `{c % x | &0 <= c /\ x IN IMAGE f s} =
1198                         {c % f(x) | &0 <= c /\ x IN s}`] THEN
1199   DISCH_THEN(fun th -> REWRITE_TAC[MATCH_MP LINEAR_CMUL th]));;
1200
1201 add_linear_invariants [CONIC_HULL_LINEAR_IMAGE];;
1202
1203 let CONVEX_CONIC_HULL = prove
1204  (`!s:real^N->bool. convex s ==> convex (conic hull s)`,
1205   REWRITE_TAC[CONIC_HULL_EXPLICIT] THEN
1206   REWRITE_TAC[CONVEX_ALT; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1207   REWRITE_TAC[FORALL_IN_GSPEC] THEN REWRITE_TAC[IN_ELIM_THM; IMP_IMP] THEN
1208   X_GEN_TAC `s:real^N->bool` THEN DISCH_TAC THEN
1209   MAP_EVERY X_GEN_TAC [`c:real`; `x:real^N`] THEN STRIP_TAC THEN
1210   MAP_EVERY X_GEN_TAC [`d:real`; `y:real^N`] THEN STRIP_TAC THEN
1211   X_GEN_TAC `u:real` THEN STRIP_TAC THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN
1212   ASM_CASES_TAC `(&1 - u) * c = &0` THENL
1213    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN
1214     ASM_MESON_TAC[REAL_LE_MUL];
1215     ALL_TAC] THEN
1216   SUBGOAL_THEN `&0 < (&1 - u) * c + u * d` ASSUME_TAC THENL
1217    [MATCH_MP_TAC REAL_LTE_ADD THEN ASM_REWRITE_TAC[REAL_LT_LE] THEN
1218     CONJ_TAC THEN MATCH_MP_TAC REAL_LE_MUL THEN ASM_REAL_ARITH_TAC;
1219     ALL_TAC] THEN
1220   EXISTS_TAC `(&1 - u) * c + u * d:real` THEN
1221   EXISTS_TAC `((&1 - u) * c) / ((&1 - u) * c + u * d) % x +
1222               (u * d) / ((&1 - u) * c + u * d) % y:real^N` THEN
1223   REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC] THEN
1224   ASM_SIMP_TAC[REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
1225   ASM_SIMP_TAC[REAL_LE_ADD; REAL_LE_MUL; REAL_SUB_LE] THEN
1226   ASM_SIMP_TAC[REAL_FIELD
1227    `&0 < u + v ==> u / (u + v) = &1 - (v / (u + v))`] THEN
1228   RULE_ASSUM_TAC(REWRITE_RULE[RIGHT_IMP_FORALL_THM; IMP_IMP]) THEN
1229   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
1230   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ] THEN
1231   ASM_SIMP_TAC[REAL_MUL_LZERO; REAL_LE_MUL; REAL_MUL_LID; REAL_LE_ADDL;
1232                REAL_SUB_LE]);;
1233
1234 let CONIC_HALFSPACE_LE = prove
1235  (`!a. conic {x | a dot x <= &0}`,
1236   REWRITE_TAC[conic; IN_ELIM_THM; DOT_RMUL] THEN
1237   REWRITE_TAC[REAL_ARITH `a <= &0 <=> &0 <= --a`] THEN
1238   SIMP_TAC[GSYM REAL_MUL_RNEG; REAL_LE_MUL]);;
1239
1240 let CONIC_HALFSPACE_GE = prove
1241  (`!a. conic {x | a dot x >= &0}`,
1242   SIMP_TAC[conic; IN_ELIM_THM; DOT_RMUL; real_ge; REAL_LE_MUL]);;
1243
1244 let CONIC_HULL_EMPTY = prove
1245  (`conic hull {} = {}`,
1246   MATCH_MP_TAC HULL_UNIQUE THEN
1247   REWRITE_TAC[SUBSET_REFL; CONIC_EMPTY; EMPTY_SUBSET]);;
1248
1249 let CONIC_CONTAINS_0 = prove
1250  (`!s:real^N->bool. conic s ==> (vec 0 IN s <=> ~(s = {}))`,
1251   REPEAT STRIP_TAC THEN EQ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
1252   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
1253   DISCH_THEN(X_CHOOSE_TAC `x:real^N`) THEN
1254   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [conic]) THEN
1255   DISCH_THEN(MP_TAC o SPECL [`x:real^N`; `&0`]) THEN
1256   ASM_REWRITE_TAC[REAL_POS; VECTOR_MUL_LZERO]);;
1257
1258 let CONIC_HULL_EQ_EMPTY = prove
1259  (`!s. (conic hull s = {}) <=> (s = {})`,
1260   GEN_TAC THEN EQ_TAC THEN
1261   MESON_TAC[SUBSET_EMPTY; HULL_SUBSET; CONIC_HULL_EMPTY]);;
1262
1263 let CONIC_SUMS = prove
1264  (`!s t. conic s /\ conic t ==> conic {x + y:real^N | x IN s /\ y IN t}`,
1265   REWRITE_TAC[conic; IN_ELIM_THM] THEN
1266   MESON_TAC[VECTOR_ADD_LDISTRIB]);;
1267
1268 let CONIC_PCROSS = prove
1269  (`!s:real^M->bool t:real^N->bool.
1270         conic s /\ conic t ==> conic(s PCROSS t)`,
1271   REWRITE_TAC[conic; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1272   SIMP_TAC[FORALL_IN_PCROSS; GSYM PASTECART_CMUL; PASTECART_ADD] THEN
1273   SIMP_TAC[PASTECART_IN_PCROSS]);;
1274
1275 let CONIC_PCROSS_EQ = prove
1276  (`!s:real^M->bool t:real^N->bool.
1277         conic(s PCROSS t) <=> s = {} \/ t = {} \/ conic s /\ conic t`,
1278   REPEAT GEN_TAC THEN
1279   ASM_CASES_TAC `s:real^M->bool = {}` THEN
1280   ASM_REWRITE_TAC[PCROSS_EMPTY; CONIC_EMPTY] THEN
1281   ASM_CASES_TAC `t:real^N->bool = {}` THEN
1282   ASM_REWRITE_TAC[PCROSS_EMPTY; CONIC_EMPTY] THEN
1283   EQ_TAC THEN REWRITE_TAC[CONIC_PCROSS] THEN REPEAT STRIP_TAC THENL
1284    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
1285       `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONIC_LINEAR_IMAGE) THEN
1286     ASM_REWRITE_TAC[LINEAR_FSTCART];
1287     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
1288       `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONIC_LINEAR_IMAGE) THEN
1289     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
1290   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
1291   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
1292               FSTCART_PASTECART; SNDCART_PASTECART] THEN
1293   ASM SET_TAC[]);;
1294
1295 let CONIC_POSITIVE_ORTHANT = prove
1296  (`conic {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> &0 <= x$i}`,
1297   SIMP_TAC[conic; IN_ELIM_THM; REAL_LE_MUL; VECTOR_MUL_COMPONENT]);;
1298
1299 let SEPARATE_CLOSED_CONES = prove
1300  (`!c d:real^N->bool.
1301         conic c /\ closed c /\ conic d /\ closed d /\ c INTER d SUBSET {vec 0}
1302         ==> ?e. &0 < e /\
1303                 !x y. x IN c /\ y IN d
1304                       ==> dist(x,y) >= e * max (norm x) (norm y)`,
1305   SUBGOAL_THEN
1306    `!c d:real^N->bool.
1307         conic c /\ closed c /\ conic d /\ closed d /\ c INTER d SUBSET {vec 0}
1308         ==> ?e. &0 < e /\
1309                 !x y. x IN c /\ y IN d ==> dist(x,y)
1310                       >= e * norm x`
1311   ASSUME_TAC THENL
1312    [REPEAT STRIP_TAC THEN REWRITE_TAC[real_ge] THEN
1313     MP_TAC(ISPECL [`c INTER sphere(vec 0:real^N,&1)`; `d:real^N->bool`]
1314       SEPARATE_COMPACT_CLOSED) THEN
1315     ASM_SIMP_TAC[CLOSED_INTER_COMPACT; COMPACT_SPHERE] THEN ANTS_TAC THENL
1316      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
1317        `c INTER d SUBSET {a} ==> ~(a IN s) ==> (c INTER s) INTER d = {}`)) THEN
1318       REWRITE_TAC[IN_SPHERE_0; NORM_0] THEN REAL_ARITH_TAC;
1319       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN
1320       REWRITE_TAC[IN_INTER; IN_SPHERE_0] THEN STRIP_TAC THEN
1321       ASM_REWRITE_TAC[] THEN
1322       MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
1323       ASM_CASES_TAC `x:real^N = vec 0` THEN
1324       ASM_REWRITE_TAC[DIST_POS_LE; REAL_MUL_RZERO; NORM_0] THEN
1325       FIRST_X_ASSUM(MP_TAC o SPECL
1326        [`inv(norm x) % x:real^N`; `inv(norm(x:real^N)) % y:real^N`]) THEN
1327       REWRITE_TAC[dist; NORM_MUL; GSYM VECTOR_SUB_LDISTRIB] THEN
1328       REWRITE_TAC[REAL_ARITH `abs x * a = a * abs x`] THEN
1329       REWRITE_TAC[REAL_ABS_INV; GSYM real_div; REAL_ABS_NORM] THEN
1330       ASM_SIMP_TAC[REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
1331       DISCH_THEN MATCH_MP_TAC THEN
1332       ASM_SIMP_TAC[REAL_DIV_REFL; NORM_EQ_0] THEN
1333       RULE_ASSUM_TAC(REWRITE_RULE[conic]) THEN
1334       CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
1335       ASM_SIMP_TAC[REAL_LE_INV_EQ; NORM_POS_LE]];
1336     REPEAT STRIP_TAC THEN FIRST_X_ASSUM(fun th ->
1337       MP_TAC(SPECL [`c:real^N->bool`; `d:real^N->bool`] th) THEN
1338       MP_TAC(SPECL [`d:real^N->bool`; `c:real^N->bool`] th)) THEN
1339     ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[INTER_COMM] THEN
1340     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; real_ge] THEN
1341     X_GEN_TAC `d:real` THEN STRIP_TAC THEN
1342     X_GEN_TAC `e:real` THEN STRIP_TAC THEN
1343     EXISTS_TAC `min d e:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
1344     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
1345     REWRITE_TAC[real_max] THEN COND_CASES_TAC THEN
1346     MATCH_MP_TAC REAL_LE_TRANS THENL
1347      [EXISTS_TAC `d * norm(y:real^N)` THEN ONCE_REWRITE_TAC[DIST_SYM];
1348       EXISTS_TAC `e * norm(x:real^N)`] THEN
1349     ASM_SIMP_TAC[] THEN MATCH_MP_TAC REAL_LE_RMUL THEN NORM_ARITH_TAC]);;
1350
1351 let CONTINUOUS_ON_COMPACT_SURFACE_PROJECTION = prove
1352  (`!s:real^N->bool v d:real^N->real.
1353         compact s /\ s SUBSET (v DELETE (vec 0)) /\ conic v /\
1354         (!x k. x IN v DELETE (vec 0) ==> (&0 < k /\ (k % x) IN s <=> d x = k))
1355         ==> (\x. d x % x) continuous_on (v DELETE (vec 0))`,
1356   let lemma = prove
1357    (`!s:real^N->real^N p srf:real^N->bool pnc.
1358           compact srf /\ srf SUBSET pnc /\
1359           IMAGE s pnc SUBSET srf /\ (!x. x IN srf ==> s x = x) /\
1360           p continuous_on pnc /\
1361           (!x. x IN pnc ==> s(p x) = s x /\ p(s x) = p x)
1362           ==> s continuous_on pnc`,
1363     REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THEN
1364     EXISTS_TAC `(s:real^N->real^N) o (p:real^N->real^N)` THEN
1365     CONJ_TAC THENL [ASM_SIMP_TAC[o_DEF]; ALL_TAC] THEN
1366     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN
1367     SUBGOAL_THEN `IMAGE (p:real^N->real^N) pnc = IMAGE p srf` SUBST1_TAC THENL
1368      [ASM SET_TAC[];
1369       MATCH_MP_TAC CONTINUOUS_ON_INVERSE THEN ASM_REWRITE_TAC[] THEN
1370       CONJ_TAC THENL [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ASM SET_TAC[]]]) in
1371   REWRITE_TAC[conic; IN_DELETE; SUBSET] THEN
1372   REPEAT STRIP_TAC THEN MATCH_MP_TAC lemma THEN
1373   MAP_EVERY EXISTS_TAC [`\x:real^N. inv(norm x) % x`; `s:real^N->bool`] THEN
1374   ASM_REWRITE_TAC[] THEN
1375   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
1376   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
1377   ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN CONJ_TAC THENL
1378    [MATCH_MP_TAC CONTINUOUS_ON_MUL THEN SIMP_TAC[o_DEF; CONTINUOUS_ON_ID] THEN
1379     MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_INV) THEN
1380     SIMP_TAC[IN_DELETE; NORM_EQ_0; SIMP_RULE[o_DEF] CONTINUOUS_ON_LIFT_NORM];
1381     REWRITE_TAC[IN_UNIV; IN_DELETE]] THEN
1382   CONJ_TAC THENL
1383    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1384     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `&1`]) THEN
1385     ASM_REWRITE_TAC[VECTOR_MUL_LID; REAL_LT_01; IN_DELETE] THEN
1386     ASM_MESON_TAC[VECTOR_MUL_LID; SUBSET; IN_DELETE];
1387     ALL_TAC] THEN
1388   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN CONJ_TAC THENL
1389    [FIRST_ASSUM(MP_TAC o SPECL
1390      [`inv(norm x) % x:real^N`; `norm x * (d:real^N->real) x`]) THEN
1391     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `(d:real^N->real) x`]) THEN
1392     ASM_SIMP_TAC[VECTOR_MUL_EQ_0; REAL_INV_EQ_0; NORM_EQ_0] THEN STRIP_TAC THEN
1393     ASM_SIMP_TAC[REAL_LE_INV_EQ; NORM_POS_LE; REAL_LT_MUL; NORM_POS_LT] THEN
1394     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; NORM_EQ_0; REAL_FIELD
1395      `~(n = &0) ==> (n * d) * inv n = d`];
1396     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `(d:real^N->real) x`]) THEN
1397     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
1398     ASM_SIMP_TAC[NORM_MUL; VECTOR_MUL_ASSOC; REAL_INV_MUL] THEN
1399     ASM_SIMP_TAC[real_abs; REAL_LT_IMP_LE] THEN
1400     ASM_SIMP_TAC[REAL_FIELD `&0 < x ==> (inv(x) * y) * x = y`]]);;
1401
1402 (* ------------------------------------------------------------------------- *)
1403 (* Affine dependence and consequential theorems (from Lars Schewe).          *)
1404 (* ------------------------------------------------------------------------- *)
1405
1406 let affine_dependent = new_definition
1407  `affine_dependent (s:real^N -> bool) <=>
1408         ?x. x IN s /\ x IN (affine hull (s DELETE x))`;;
1409
1410 let AFFINE_DEPENDENT_EXPLICIT = prove
1411  (`!p. affine_dependent (p:real^N -> bool) <=>
1412             (?s u. FINITE s /\ s SUBSET p /\
1413                    sum s u = &0 /\
1414                    (?v. v IN s /\ ~(u v = &0)) /\
1415                    vsum s (\v. u v % v) = (vec 0):real^N)`,
1416   X_GEN_TAC `p:real^N->bool` THEN EQ_TAC THENL
1417    [REWRITE_TAC[affine_dependent;AFFINE_HULL_EXPLICIT;
1418                 IN_ELIM_THM] THEN
1419     REPEAT STRIP_TAC THEN
1420     EXISTS_TAC `(x:real^N) INSERT s` THEN
1421     EXISTS_TAC `\v:real^N.if v = x then -- &1 else u v` THEN
1422       ASM_SIMP_TAC[FINITE_INSERT;SUM_CLAUSES;VSUM_CLAUSES;INSERT_SUBSET] THEN
1423       REPEAT CONJ_TAC THENL
1424       [ASM SET_TAC[];
1425        COND_CASES_TAC THENL [ASM SET_TAC[];ALL_TAC] THEN
1426          ASM_SIMP_TAC[SUM_CASES; SUM_CLAUSES; SET_RULE
1427           `~((x:real^N) IN s) ==> {v | v IN s /\ v = x} = {} /\
1428                                   {v | v IN s /\ ~(v = x)} = s`] THEN
1429          REAL_ARITH_TAC;
1430        SET_TAC[REAL_ARITH `~(-- &1 = &0)`];
1431        MP_TAC (SET_RULE `s SUBSET p DELETE (x:real^N) ==> ~(x IN s)`) THEN
1432        ASM_REWRITE_TAC[] THEN
1433        DISCH_TAC THEN
1434        ASM_SIMP_TAC[VECTOR_ARITH
1435         `(-- &1 % (x:real^N)) + a = vec 0 <=> a = x`] THEN
1436        MATCH_MP_TAC EQ_TRANS THEN
1437        EXISTS_TAC `vsum s (\v:real^N. u v % v)` THEN
1438        CONJ_TAC THENL [
1439        MATCH_MP_TAC VSUM_EQ THEN
1440          ASM_SIMP_TAC[] THEN
1441          ASM SET_TAC[];
1442        ASM_REWRITE_TAC[]]];
1443        ALL_TAC] THEN
1444     REWRITE_TAC[affine_dependent;AFFINE_HULL_EXPLICIT;IN_ELIM_THM] THEN
1445     REPEAT STRIP_TAC THEN
1446     EXISTS_TAC `v:real^N` THEN
1447     CONJ_TAC THENL [ASM SET_TAC[];ALL_TAC] THEN
1448     EXISTS_TAC `s DELETE (v:real^N)` THEN
1449     EXISTS_TAC `\x:real^N. -- (&1 / (u v)) * u x` THEN
1450     ASM_SIMP_TAC[FINITE_DELETE;SUM_DELETE;VSUM_DELETE_CASES] THEN
1451     ASM_SIMP_TAC[SUM_LMUL;GSYM VECTOR_MUL_ASSOC;VSUM_LMUL;
1452             VECTOR_MUL_RZERO;VECTOR_ARITH `vec 0 - -- a % x = a % x:real^N`;
1453             REAL_MUL_RZERO;REAL_ARITH `&0 - -- a * b = a * b`] THEN
1454     ASM_SIMP_TAC[REAL_FIELD `~(x = &0) ==> &1 / x * x = &1`;
1455                  VECTOR_MUL_ASSOC;VECTOR_MUL_LID] THEN
1456     CONJ_TAC THENL [ALL_TAC;ASM SET_TAC[]] THEN
1457     ASM_SIMP_TAC[SET_RULE `v IN s ==> (s DELETE v = {} <=> s = {v})`] THEN
1458     ASM_CASES_TAC `s = {v:real^N}` THEN
1459     ASM_REWRITE_TAC[] THEN
1460     FIRST_X_ASSUM SUBST_ALL_TAC THEN
1461     FIND_ASSUM MP_TAC `sum {v:real^N} u = &0` THEN
1462     REWRITE_TAC[SUM_SING]
1463     THEN ASM_REWRITE_TAC[]);;
1464
1465 let AFFINE_DEPENDENT_EXPLICIT_FINITE = prove
1466  (`!s. FINITE(s:real^N -> bool)
1467        ==> (affine_dependent s <=>
1468             ?u. sum s u = &0 /\
1469                 (?v. v IN s /\ ~(u v = &0)) /\
1470                 vsum s (\v. u v % v) = vec 0)`,
1471   REPEAT STRIP_TAC THEN REWRITE_TAC[AFFINE_DEPENDENT_EXPLICIT] THEN
1472   EQ_TAC THENL [ALL_TAC; ASM_MESON_TAC[SUBSET_REFL]] THEN
1473   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool`
1474    (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC)) THEN
1475   EXISTS_TAC `\x:real^N. if x IN t then u(x) else &0` THEN
1476   REWRITE_TAC[COND_RAND; COND_RATOR; VECTOR_MUL_LZERO] THEN
1477   ASM_SIMP_TAC[GSYM SUM_RESTRICT_SET; GSYM VSUM_RESTRICT_SET] THEN
1478   ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
1479   ASM SET_TAC[]);;
1480
1481 let AFFINE_DEPENDENT_TRANSLATION_EQ = prove
1482  (`!a s. affine_dependent (IMAGE (\x. a + x) s) <=> affine_dependent s`,
1483   REWRITE_TAC[affine_dependent] THEN GEOM_TRANSLATE_TAC[]);;
1484
1485 add_translation_invariants [AFFINE_DEPENDENT_TRANSLATION_EQ];;
1486
1487 let AFFINE_DEPENDENT_TRANSLATION = prove
1488  (`!s a. affine_dependent s ==> affine_dependent (IMAGE (\x. a + x) s)`,
1489   REWRITE_TAC[AFFINE_DEPENDENT_TRANSLATION_EQ]);;
1490
1491 let AFFINE_DEPENDENT_LINEAR_IMAGE_EQ = prove
1492  (`!f:real^M->real^N s.
1493         linear f /\ (!x y. f x = f y ==> x = y)
1494         ==> (affine_dependent(IMAGE f s) <=> affine_dependent s)`,
1495   REWRITE_TAC[affine_dependent] THEN GEOM_TRANSFORM_TAC[]);;
1496
1497 add_linear_invariants [AFFINE_DEPENDENT_LINEAR_IMAGE_EQ];;
1498
1499 let AFFINE_DEPENDENT_LINEAR_IMAGE = prove
1500  (`!f:real^M->real^N s.
1501         linear f /\ (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) /\
1502         affine_dependent(s)
1503         ==> affine_dependent(IMAGE f s)`,
1504   REPEAT GEN_TAC THEN
1505   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
1506   REWRITE_TAC[affine_dependent; EXISTS_IN_IMAGE] THEN
1507   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^M` THEN
1508   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1509   SUBGOAL_THEN `IMAGE (f:real^M->real^N) s DELETE f a = IMAGE f (s DELETE a)`
1510    (fun t -> ASM_SIMP_TAC[FUN_IN_IMAGE; AFFINE_HULL_LINEAR_IMAGE; t]) THEN
1511   ASM SET_TAC[]);;
1512
1513 let AFFINE_DEPENDENT_MONO = prove
1514  (`!s t:real^N->bool. affine_dependent s /\ s SUBSET t ==> affine_dependent t`,
1515   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
1516   REWRITE_TAC[affine_dependent] THEN MATCH_MP_TAC MONO_EXISTS THEN
1517   X_GEN_TAC `x:real^N` THEN MATCH_MP_TAC MONO_AND THEN CONJ_TAC THEN
1518   FIRST_ASSUM(MP_TAC o MATCH_MP HULL_MONO o SPEC `x:real^N` o MATCH_MP
1519    (SET_RULE `!x. s SUBSET t ==> (s DELETE x) SUBSET (t DELETE x)`)) THEN
1520   ASM SET_TAC[]);;
1521
1522 let AFFINE_INDEPENDENT_EMPTY = prove
1523  (`~(affine_dependent {})`,
1524   REWRITE_TAC[affine_dependent; NOT_IN_EMPTY]);;
1525
1526 let AFFINE_INDEPENDENT_1 = prove
1527  (`!a:real^N. ~(affine_dependent {a})`,
1528   REWRITE_TAC[affine_dependent; EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN
1529   REWRITE_TAC[SET_RULE `{a} DELETE a = {}`; AFFINE_HULL_EMPTY; NOT_IN_EMPTY]);;
1530
1531 let AFFINE_INDEPENDENT_2 = prove
1532  (`!a b:real^N. ~(affine_dependent {a,b})`,
1533   REPEAT GEN_TAC THEN ASM_CASES_TAC `b:real^N = a` THENL
1534    [ASM_REWRITE_TAC[INSERT_AC; AFFINE_INDEPENDENT_1];
1535     REWRITE_TAC[affine_dependent; EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN
1536     ASM_SIMP_TAC[SET_RULE
1537      `~(a = b) ==> {a,b} DELETE a = {b} /\ {a,b} DELETE b = {a}`] THEN
1538     ASM_REWRITE_TAC[AFFINE_HULL_SING; IN_SING]]);;
1539
1540 let AFFINE_INDEPENDENT_SUBSET = prove
1541  (`!s t. ~affine_dependent t /\ s SUBSET t ==> ~affine_dependent s`,
1542   REWRITE_TAC[IMP_CONJ_ALT; CONTRAPOS_THM] THEN
1543   REWRITE_TAC[GSYM IMP_CONJ_ALT; AFFINE_DEPENDENT_MONO]);;
1544
1545 let AFFINE_INDEPENDENT_DELETE = prove
1546  (`!s a. ~affine_dependent s ==> ~affine_dependent(s DELETE a)`,
1547   REPEAT GEN_TAC THEN
1548   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_INDEPENDENT_SUBSET) THEN
1549   SET_TAC[]);;
1550
1551 (* ------------------------------------------------------------------------- *)
1552 (* Coplanarity, and collinearity in terms of affine hull.                    *)
1553 (* ------------------------------------------------------------------------- *)
1554
1555 let coplanar = new_definition
1556  `coplanar s <=> ?u v w. s SUBSET affine hull {u,v,w}`;;
1557
1558 let COLLINEAR_AFFINE_HULL = prove
1559  (`!s:real^N->bool. collinear s <=> ?u v. s SUBSET affine hull {u,v}`,
1560   GEN_TAC THEN REWRITE_TAC[collinear; AFFINE_HULL_2] THEN EQ_TAC THEN
1561   REWRITE_TAC[SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
1562   REWRITE_TAC[REAL_ARITH `u + v = &1 <=> &1 - u = v`; UNWIND_THM1] THENL
1563    [X_GEN_TAC `u:real^N` THEN DISCH_TAC THEN
1564     ASM_CASES_TAC `s:real^N->bool = {}` THEN
1565     ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
1566     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
1567     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN
1568     DISCH_TAC THEN EXISTS_TAC `x + u:real^N` THEN X_GEN_TAC `y:real^N` THEN
1569     DISCH_TAC THEN
1570     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `y:real^N`]) THEN
1571     ASM_REWRITE_TAC[VECTOR_ARITH `x - y:real^N = z <=> x = y + z`] THEN
1572     DISCH_THEN(X_CHOOSE_THEN `c:real` SUBST1_TAC) THEN
1573     EXISTS_TAC `&1 + c` THEN VECTOR_ARITH_TAC;
1574     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN DISCH_TAC THEN
1575     EXISTS_TAC `b - a:real^N` THEN
1576     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
1577     FIRST_X_ASSUM(fun th ->
1578       MP_TAC(SPEC `y:real^N` th) THEN MP_TAC(SPEC `x:real^N` th)) THEN
1579     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
1580     X_GEN_TAC `r:real` THEN DISCH_THEN SUBST1_TAC THEN
1581     X_GEN_TAC `s:real` THEN DISCH_THEN SUBST1_TAC THEN
1582     EXISTS_TAC `s - r:real` THEN VECTOR_ARITH_TAC]);;
1583
1584 let COLLINEAR_IMP_COPLANAR = prove
1585  (`!s. collinear s ==> coplanar s`,
1586   REWRITE_TAC[coplanar; COLLINEAR_AFFINE_HULL] THEN MESON_TAC[INSERT_AC]);;
1587
1588 let COPLANAR_SMALL = prove
1589  (`!s. FINITE s /\ CARD s <= 3 ==> coplanar s`,
1590   GEN_TAC THEN REWRITE_TAC[ARITH_RULE `s <= 3 <=> s <= 2 \/ s = 3`] THEN
1591   REWRITE_TAC[LEFT_OR_DISTRIB; GSYM HAS_SIZE] THEN
1592   DISCH_THEN(DISJ_CASES_THEN MP_TAC) THEN
1593   SIMP_TAC[COLLINEAR_IMP_COPLANAR; COLLINEAR_SMALL] THEN
1594   CONV_TAC(LAND_CONV HAS_SIZE_CONV) THEN REWRITE_TAC[coplanar] THEN
1595   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
1596   STRIP_TAC THEN ASM_REWRITE_TAC[HULL_INC; SUBSET]);;
1597
1598 let COPLANAR_EMPTY = prove
1599  (`coplanar {}`,
1600   SIMP_TAC[COLLINEAR_IMP_COPLANAR; COLLINEAR_EMPTY]);;
1601
1602 let COPLANAR_SING = prove
1603  (`!a. coplanar {a}`,
1604   SIMP_TAC[COLLINEAR_IMP_COPLANAR; COLLINEAR_SING]);;
1605
1606 let COPLANAR_2 = prove
1607  (`!a b. coplanar {a,b}`,
1608   SIMP_TAC[COLLINEAR_IMP_COPLANAR; COLLINEAR_2]);;
1609
1610 let COPLANAR_3 = prove
1611  (`!a b c. coplanar {a,b,c}`,
1612   REPEAT GEN_TAC THEN MATCH_MP_TAC COPLANAR_SMALL THEN
1613   SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_RULES] THEN ARITH_TAC);;
1614
1615 let COLLINEAR_AFFINE_HULL_COLLINEAR = prove
1616  (`!s. collinear(affine hull s) <=> collinear s`,
1617   REWRITE_TAC[COLLINEAR_AFFINE_HULL] THEN
1618   MESON_TAC[HULL_HULL; HULL_MONO; HULL_INC; SUBSET]);;
1619
1620 let COPLANAR_AFFINE_HULL_COPLANAR = prove
1621  (`!s. coplanar(affine hull s) <=> coplanar s`,
1622   REWRITE_TAC[coplanar] THEN
1623   MESON_TAC[HULL_HULL; HULL_MONO; HULL_INC; SUBSET]);;
1624
1625 let COPLANAR_TRANSLATION_EQ = prove
1626  (`!a:real^N s. coplanar(IMAGE (\x. a + x) s) <=> coplanar s`,
1627   REWRITE_TAC[coplanar] THEN GEOM_TRANSLATE_TAC[]);;
1628
1629 let COPLANAR_TRANSLATION = prove
1630  (`!a:real^N s. coplanar s ==> coplanar(IMAGE (\x. a + x) s)`,
1631   REWRITE_TAC[COPLANAR_TRANSLATION_EQ]);;
1632
1633 add_translation_invariants [COPLANAR_TRANSLATION_EQ];;
1634
1635 let COPLANAR_LINEAR_IMAGE = prove
1636  (`!f:real^M->real^N s. coplanar s /\ linear f ==> coplanar(IMAGE f s)`,
1637   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
1638   REWRITE_TAC[coplanar; LEFT_IMP_EXISTS_THM] THEN
1639   MAP_EVERY X_GEN_TAC [`a:real^M`; `b:real^M`; `c:real^M`] THEN STRIP_TAC THEN
1640   MAP_EVERY EXISTS_TAC
1641   [`(f:real^M->real^N) a`; `(f:real^M->real^N) b`; `(f:real^M->real^N) c`] THEN
1642   REWRITE_TAC[SET_RULE `{f a,f b,f c} = IMAGE f {a,b,c}`] THEN
1643   ASM_SIMP_TAC[AFFINE_HULL_LINEAR_IMAGE; IMAGE_SUBSET]);;
1644
1645 let COPLANAR_LINEAR_IMAGE_EQ = prove
1646  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
1647          ==> (coplanar (IMAGE f s) <=> coplanar s)`,
1648   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE COPLANAR_LINEAR_IMAGE));;
1649
1650 add_linear_invariants [COPLANAR_LINEAR_IMAGE_EQ];;
1651
1652 let COPLANAR_SUBSET = prove
1653  (`!s t. coplanar t /\ s SUBSET t ==> coplanar s`,
1654   REWRITE_TAC[coplanar] THEN SET_TAC[]);;
1655
1656 let AFFINE_HULL_3_IMP_COLLINEAR = prove
1657  (`!a b c. c IN affine hull {a,b} ==> collinear {a,b,c}`,
1658   ONCE_REWRITE_TAC[GSYM COLLINEAR_AFFINE_HULL_COLLINEAR] THEN
1659   SIMP_TAC[HULL_REDUNDANT_EQ; INSERT_AC] THEN
1660   REWRITE_TAC[COLLINEAR_AFFINE_HULL_COLLINEAR; COLLINEAR_2]);;
1661
1662 let COLLINEAR_3_AFFINE_HULL = prove
1663  (`!a b c:real^N.
1664         ~(a = b) ==> (collinear {a,b,c} <=> c IN affine hull {a,b})`,
1665   REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[AFFINE_HULL_3_IMP_COLLINEAR] THEN
1666   REWRITE_TAC[collinear] THEN
1667   DISCH_THEN(X_CHOOSE_THEN `u:real^N` STRIP_ASSUME_TAC) THEN
1668   FIRST_ASSUM(fun th -> MP_TAC(SPECL [`b:real^N`; `a:real^N`] th) THEN
1669                         MP_TAC(SPECL [`c:real^N`; `a:real^N`] th)) THEN
1670   REWRITE_TAC[IN_INSERT; AFFINE_HULL_2; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
1671   REWRITE_TAC[VECTOR_ARITH `a - b:real^N = c <=> a = b + c`] THEN
1672   X_GEN_TAC `x:real` THEN DISCH_TAC THEN X_GEN_TAC `y:real` THEN
1673   ASM_CASES_TAC `y = &0` THEN
1674   ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_RID] THEN DISCH_TAC THEN
1675   ASM_REWRITE_TAC[] THEN
1676   MAP_EVERY EXISTS_TAC [`&1 - x / y`; `x / y:real`] THEN
1677   CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
1678   REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC] THEN
1679   ASM_SIMP_TAC[REAL_DIV_RMUL] THEN VECTOR_ARITH_TAC);;
1680
1681 let COLLINEAR_3_EQ_AFFINE_DEPENDENT = prove
1682  (`!a b c:real^N.
1683         collinear{a,b,c} <=>
1684                 a = b \/ a = c \/ b = c \/ affine_dependent {a,b,c}`,
1685   REPEAT GEN_TAC THEN
1686   MAP_EVERY (fun t ->
1687     ASM_CASES_TAC t THENL [ASM_REWRITE_TAC[INSERT_AC; COLLINEAR_2]; ALL_TAC])
1688    [`a:real^N = b`; `a:real^N = c`; `b:real^N = c`] THEN
1689   ASM_REWRITE_TAC[affine_dependent] THEN EQ_TAC THENL
1690    [ASM_SIMP_TAC[COLLINEAR_3_AFFINE_HULL] THEN DISCH_TAC THEN
1691     EXISTS_TAC `c:real^N` THEN REWRITE_TAC[IN_INSERT];
1692     REWRITE_TAC[EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN STRIP_TAC THENL
1693      [ONCE_REWRITE_TAC[SET_RULE `{a,b,c} = {b,c,a}`];
1694       ONCE_REWRITE_TAC[SET_RULE `{a,b,c} = {c,a,b}`];
1695       ALL_TAC] THEN
1696     ASM_SIMP_TAC[COLLINEAR_3_AFFINE_HULL]] THEN
1697   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
1698    `x IN s ==> s SUBSET t ==> x IN t`)) THEN
1699   MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]);;
1700
1701 let AFFINE_DEPENDENT_IMP_COLLINEAR_3 = prove
1702  (`!a b c:real^N. affine_dependent {a,b,c} ==> collinear{a,b,c}`,
1703   REPEAT GEN_TAC THEN REWRITE_TAC[affine_dependent] THEN
1704   REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; RIGHT_OR_DISTRIB] THEN
1705   REWRITE_TAC[EXISTS_OR_THM; UNWIND_THM2; COLLINEAR_AFFINE_HULL] THEN
1706   STRIP_TAC THENL
1707    [MAP_EVERY EXISTS_TAC [`b:real^N`; `c:real^N`];
1708     MAP_EVERY EXISTS_TAC [`a:real^N`; `c:real^N`];
1709     MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real^N`]] THEN
1710   SIMP_TAC[INSERT_SUBSET; EMPTY_SUBSET; HULL_INC; IN_INSERT] THEN
1711   POP_ASSUM MP_TAC THEN
1712   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> a IN s ==> a IN t`) THEN
1713   MATCH_MP_TAC HULL_MONO THEN SET_TAC[]);;
1714
1715 let COLLINEAR_3_IN_AFFINE_HULL = prove
1716  (`!v0 v1 x:real^N.
1717         ~(v1 = v0)
1718         ==> (collinear {v0,v1,x} <=> x IN affine hull {v0,v1})`,
1719   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `v0:real^N` THEN
1720   REWRITE_TAC[COLLINEAR_LEMMA; AFFINE_HULL_2] THEN REPEAT STRIP_TAC THEN
1721   ASM_REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID; IN_ELIM_THM] THEN
1722   ASM_CASES_TAC `x:real^N = vec 0` THEN ASM_REWRITE_TAC[] THENL
1723    [MAP_EVERY EXISTS_TAC [`&1`; `&0`] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
1724     VECTOR_ARITH_TAC;
1725     MESON_TAC[REAL_ARITH `u + v = &1 <=> u = &1 - v`]]);;
1726
1727 (* ------------------------------------------------------------------------- *)
1728 (* A general lemma.                                                          *)
1729 (* ------------------------------------------------------------------------- *)
1730
1731 let CONVEX_CONNECTED = prove
1732  (`!s:real^N->bool. convex s ==> connected s`,
1733   REWRITE_TAC[CONVEX_ALT; connected; SUBSET; EXTENSION; IN_INTER;
1734               IN_UNION; NOT_IN_EMPTY; NOT_FORALL_THM; NOT_EXISTS_THM] THEN
1735   GEN_TAC THEN DISCH_TAC THEN REPEAT GEN_TAC THEN
1736   MAP_EVERY (K(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC))) (1--4) THEN
1737   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_THEN `x1:real^N` STRIP_ASSUME_TAC)
1738                          (X_CHOOSE_THEN `x2:real^N` STRIP_ASSUME_TAC)) THEN
1739   MP_TAC(ISPECL [`\u. (&1 - u) % x1 + u % (x2:real^N)`;
1740                  `&0`; `&1`; `e1:real^N->bool`; `e2:real^N->bool`]
1741          (REWRITE_RULE[GSYM open_def] CONNECTED_REAL_LEMMA)) THEN
1742   ASM_REWRITE_TAC[NOT_IMP; REAL_SUB_RZERO; VECTOR_MUL_LID; VECTOR_MUL_LZERO;
1743                   REAL_SUB_REFL; VECTOR_ADD_RID; VECTOR_ADD_LID; REAL_POS] THEN
1744   REPEAT(CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]]) THEN
1745   REPEAT STRIP_TAC THEN REWRITE_TAC[dist] THEN
1746   REWRITE_TAC[NORM_MUL; VECTOR_ARITH
1747    `((&1 - a) % x + a % y) - ((&1 - b) % x + b % y) = (a - b) % (y - x)`] THEN
1748   MP_TAC(ISPEC `(x2 - x1):real^N` NORM_POS_LE) THEN
1749   REWRITE_TAC[REAL_LE_LT] THEN STRIP_TAC THENL
1750    [ALL_TAC; ASM_MESON_TAC[REAL_MUL_RZERO; REAL_LT_01]] THEN
1751   EXISTS_TAC `e / norm((x2 - x1):real^N)` THEN
1752   ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LT_DIV]);;
1753
1754 (* ------------------------------------------------------------------------- *)
1755 (* Various topological facts are queued up here, just because they rely on   *)
1756 (* CONNECTED_UNIV, which is a trivial consequence of CONVEX_UNIV. It would   *)
1757 (* be fairly easy to prove it earlier and move these back to the topology.ml *)
1758 (* file, which is a bit tidier intellectually.                               *)
1759 (* ------------------------------------------------------------------------- *)
1760
1761 let CONNECTED_UNIV = prove
1762  (`connected (UNIV:real^N->bool)`,
1763   SIMP_TAC[CONVEX_CONNECTED; CONVEX_UNIV]);;
1764
1765 let CONNECTED_COMPONENT_UNIV = prove
1766  (`!x. connected_component(:real^N) x = (:real^N)`,
1767   MESON_TAC[CONNECTED_CONNECTED_COMPONENT_SET; CONNECTED_UNIV; IN_UNIV]);;
1768
1769 let CONNECTED_COMPONENT_EQ_UNIV = prove
1770  (`!s x. connected_component s x = (:real^N) <=> s = (:real^N)`,
1771   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CONNECTED_COMPONENT_UNIV] THEN
1772   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> s = UNIV ==> t = UNIV`) THEN
1773   REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]);;
1774
1775 let COMPONENTS_UNIV = prove
1776  (`components(:real^N) = {(:real^N)}`,
1777   REWRITE_TAC[COMPONENTS_EQ_SING; CONNECTED_UNIV; UNIV_NOT_EMPTY]);;
1778
1779 let CLOPEN = prove
1780  (`!s. closed s /\ open s <=> s = {} \/ s = (:real^N)`,
1781   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
1782   ASM_REWRITE_TAC[CLOSED_EMPTY; OPEN_EMPTY; CLOSED_UNIV; OPEN_UNIV] THEN
1783   MATCH_MP_TAC(REWRITE_RULE[CONNECTED_CLOPEN] CONNECTED_UNIV) THEN
1784   ASM_REWRITE_TAC[SUBTOPOLOGY_UNIV; GSYM OPEN_IN; GSYM CLOSED_IN]);;
1785
1786 let COMPACT_OPEN = prove
1787  (`!s:real^N->bool. compact s /\ open s <=> s = {}`,
1788   MESON_TAC[COMPACT_EMPTY; OPEN_EMPTY; COMPACT_IMP_CLOSED; CLOPEN;
1789             COMPACT_IMP_BOUNDED; NOT_BOUNDED_UNIV]);;
1790
1791 let FRONTIER_NOT_EMPTY = prove
1792  (`!s. ~(s = {}) /\ ~(s = (:real^N)) ==> ~(frontier s = {})`,
1793   REPEAT STRIP_TAC THEN
1794   MP_TAC(ISPECL [`(:real^N)`; `s:real^N->bool`] CONNECTED_INTER_FRONTIER) THEN
1795   REWRITE_TAC[CONNECTED_UNIV] THEN ASM SET_TAC[]);;
1796
1797 let FRONTIER_EQ_EMPTY = prove
1798  (`!s. frontier s = {} <=> s = {} \/ s = (:real^N)`,
1799   MESON_TAC[FRONTIER_NOT_EMPTY; FRONTIER_EMPTY; FRONTIER_UNIV]);;
1800
1801 let EQ_INTERVAL = prove
1802  (`(!a b c d:real^N.
1803         interval[a,b] = interval[c,d] <=>
1804         interval[a,b] = {} /\ interval[c,d] = {} \/ a = c /\ b = d) /\
1805    (!a b c d:real^N.
1806         interval[a,b] = interval(c,d) <=>
1807         interval[a,b] = {} /\ interval(c,d) = {}) /\
1808    (!a b c d:real^N.
1809         interval(a,b) = interval[c,d] <=>
1810         interval(a,b) = {} /\ interval[c,d] = {}) /\
1811    (!a b c d:real^N.
1812         interval(a,b) = interval(c,d) <=>
1813         interval(a,b) = {} /\ interval(c,d) = {} \/ a = c /\ b = d)`,
1814   REPEAT CONJ_TAC THEN REPEAT GEN_TAC THEN
1815   (EQ_TAC THENL [ALL_TAC; STRIP_TAC THEN ASM_REWRITE_TAC[]]) THEN
1816   MATCH_MP_TAC(MESON[]
1817    `(p = {} /\ q = {} ==> r) /\ (~(p = {}) /\ ~(q = {}) ==> p = q ==> r)
1818     ==> p = q ==> r`) THEN
1819   SIMP_TAC[] THENL
1820    [REWRITE_TAC[INTERVAL_NE_EMPTY; CART_EQ] THEN
1821     REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
1822     SIMP_TAC[SUBSET_INTERVAL; GSYM REAL_LE_ANTISYM];
1823     STRIP_TAC THEN MATCH_MP_TAC(MESON[CLOPEN]
1824      `closed s /\ open t /\ ~(s = {}) /\ ~(s = UNIV) ==> ~(s = t)`) THEN
1825     ASM_REWRITE_TAC[CLOSED_INTERVAL; OPEN_INTERVAL; NOT_INTERVAL_UNIV];
1826     STRIP_TAC THEN MATCH_MP_TAC(MESON[CLOPEN]
1827      `closed s /\ open t /\ ~(s = {}) /\ ~(s = UNIV) ==> ~(t = s)`) THEN
1828     ASM_REWRITE_TAC[CLOSED_INTERVAL; OPEN_INTERVAL; NOT_INTERVAL_UNIV];
1829     REWRITE_TAC[INTERVAL_NE_EMPTY; CART_EQ] THEN
1830     REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
1831     SIMP_TAC[SUBSET_INTERVAL; GSYM REAL_LE_ANTISYM]]);;
1832
1833 let CLOSED_INTERVAL_EQ = prove
1834  (`(!a b:real^N. closed(interval[a,b])) /\
1835    (!a b:real^N. closed(interval(a,b)) <=> interval(a,b) = {})`,
1836   REWRITE_TAC[CLOSED_INTERVAL] THEN
1837   REPEAT GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
1838   ASM_REWRITE_TAC[CLOSED_EMPTY] THEN
1839   MP_TAC(ISPEC `interval(a:real^N,b)` CLOPEN) THEN
1840   ASM_REWRITE_TAC[OPEN_INTERVAL] THEN
1841   MESON_TAC[BOUNDED_INTERVAL; NOT_BOUNDED_UNIV]);;
1842
1843 let OPEN_INTERVAL_EQ = prove
1844  (`(!a b:real^N. open(interval[a,b]) <=> interval[a,b] = {}) /\
1845    (!a b:real^N. open(interval(a,b)))`,
1846   REWRITE_TAC[OPEN_INTERVAL] THEN
1847   REPEAT GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
1848   ASM_REWRITE_TAC[CLOSED_EMPTY] THEN
1849   MP_TAC(ISPEC `interval[a:real^N,b]` CLOPEN) THEN
1850   ASM_REWRITE_TAC[CLOSED_INTERVAL] THEN
1851   MESON_TAC[BOUNDED_INTERVAL; NOT_BOUNDED_UNIV]);;
1852
1853 let COMPACT_INTERVAL_EQ = prove
1854  (`(!a b:real^N. compact(interval[a,b])) /\
1855    (!a b:real^N. compact(interval(a,b)) <=> interval(a,b) = {})`,
1856   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_INTERVAL] THEN
1857   REWRITE_TAC[CLOSED_INTERVAL_EQ]);;
1858
1859 let CONNECTED_CHAIN = prove
1860  (`!f:(real^N->bool)->bool.
1861         (!s. s IN f ==> compact s /\ connected s) /\
1862         (!s t. s IN f /\ t IN f ==> s SUBSET t \/ t SUBSET s)
1863         ==> connected(INTERS f)`,
1864   REPEAT STRIP_TAC THEN
1865   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
1866   ASM_REWRITE_TAC[INTERS_0; CONNECTED_UNIV] THEN
1867   ABBREV_TAC `c:real^N->bool = INTERS f` THEN
1868   SUBGOAL_THEN `compact(c:real^N->bool)` ASSUME_TAC THENL
1869    [EXPAND_TAC "c" THEN MATCH_MP_TAC COMPACT_INTERS THEN ASM SET_TAC[];
1870     ALL_TAC] THEN
1871   ASM_SIMP_TAC[CONNECTED_CLOSED_SET; COMPACT_IMP_CLOSED; NOT_EXISTS_THM] THEN
1872   MAP_EVERY X_GEN_TAC [`a:real^N->bool`; `b:real^N->bool`] THEN STRIP_TAC THEN
1873   MP_TAC(ISPECL [`a:real^N->bool`; `b:real^N->bool`] SEPARATION_NORMAL) THEN
1874   ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
1875   MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
1876   STRIP_TAC THEN
1877   SUBGOAL_THEN `?k:real^N->bool. k IN f` STRIP_ASSUME_TAC THENL
1878    [ASM SET_TAC[]; ALL_TAC] THEN
1879   SUBGOAL_THEN `?n:real^N->bool. open n /\ k SUBSET n` MP_TAC THENL
1880    [ASM_MESON_TAC[BOUNDED_SUBSET_BALL; COMPACT_IMP_BOUNDED; OPEN_BALL];
1881     REWRITE_TAC[UNIONS_SUBSET] THEN STRIP_TAC] THEN
1882   MP_TAC(ISPEC `k:real^N->bool` COMPACT_IMP_HEINE_BOREL) THEN
1883   ASM_SIMP_TAC[] THEN DISCH_THEN(MP_TAC o SPEC
1884    `(u UNION v:real^N->bool) INSERT {n DIFF s | s IN f}`) THEN
1885   REWRITE_TAC[SIMPLE_IMAGE; FORALL_IN_INSERT; FORALL_IN_IMAGE] THEN
1886   ASM_SIMP_TAC[OPEN_UNION; OPEN_DIFF; COMPACT_IMP_CLOSED; NOT_IMP] THEN
1887   CONJ_TAC THENL
1888    [REWRITE_TAC[UNIONS_INSERT] THEN REWRITE_TAC[SUBSET] THEN
1889     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN ONCE_REWRITE_TAC[IN_UNION] THEN
1890     ASM_CASES_TAC `(x:real^N) IN c` THENL [ASM SET_TAC[]; DISJ2_TAC] THEN
1891     REWRITE_TAC[UNIONS_IMAGE; IN_ELIM_THM] THEN
1892     UNDISCH_TAC `~((x:real^N) IN c)` THEN
1893     SUBST1_TAC(SYM(ASSUME `INTERS f:real^N->bool = c`)) THEN
1894     REWRITE_TAC[IN_INTERS; NOT_FORALL_THM] THEN
1895     MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[];
1896     ALL_TAC] THEN
1897   DISCH_THEN(X_CHOOSE_THEN `g:(real^N->bool)->bool` MP_TAC) THEN
1898   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
1899   REWRITE_TAC[SUBSET_INSERT_DELETE] THEN
1900   SUBGOAL_THEN `FINITE(g DELETE (u UNION v:real^N->bool))` MP_TAC THENL
1901    [ASM_REWRITE_TAC[FINITE_DELETE];
1902     REWRITE_TAC[TAUT `p ==> ~q <=> ~(p /\ q)`]] THEN
1903   REWRITE_TAC[FINITE_SUBSET_IMAGE] THEN
1904   DISCH_THEN(X_CHOOSE_THEN `f':(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
1905   SUBGOAL_THEN
1906    `?j:real^N->bool. j IN f /\
1907                      UNIONS(IMAGE (\s. n DIFF s) f') SUBSET (n DIFF j)`
1908   STRIP_ASSUME_TAC THENL
1909    [ASM_CASES_TAC `f':(real^N->bool)->bool = {}` THEN
1910     ASM_REWRITE_TAC[IMAGE_CLAUSES; UNIONS_0; EMPTY_SUBSET] THENL
1911      [ASM SET_TAC[]; ALL_TAC] THEN
1912     SUBGOAL_THEN
1913      `?j:real^N->bool. j IN f' /\
1914                        UNIONS(IMAGE (\s. n DIFF s) f') SUBSET (n DIFF j)`
1915     MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[SUBSET]] THEN
1916     SUBGOAL_THEN
1917      `!s t:real^N->bool. s IN f' /\ t IN f' ==> s SUBSET t \/ t SUBSET s`
1918     MP_TAC THENL [ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
1919     UNDISCH_TAC `~(f':(real^N->bool)->bool = {})` THEN
1920     UNDISCH_TAC `FINITE(f':(real^N->bool)->bool)` THEN
1921     SPEC_TAC(`f':(real^N->bool)->bool`,`f':(real^N->bool)->bool`) THEN
1922     MATCH_MP_TAC FINITE_INDUCT_STRONG THEN REWRITE_TAC[] THEN
1923     REWRITE_TAC[EXISTS_IN_INSERT; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1924     REWRITE_TAC[FORALL_IN_INSERT] THEN POP_ASSUM_LIST(K ALL_TAC) THEN
1925     MAP_EVERY X_GEN_TAC [`i:real^N->bool`; `f:(real^N->bool)->bool`] THEN
1926     ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
1927     ASM_REWRITE_TAC[IMAGE_CLAUSES; UNIONS_INSERT; NOT_IN_EMPTY;
1928                     UNIONS_0; UNION_EMPTY; SUBSET_REFL] THEN
1929     DISCH_THEN(fun th -> REPEAT DISCH_TAC THEN MP_TAC th) THEN
1930     ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
1931     DISCH_THEN(X_CHOOSE_THEN `j:real^N->bool` STRIP_ASSUME_TAC) THEN
1932     SUBGOAL_THEN `(n DIFF j) SUBSET (n DIFF i) \/
1933                   (n DIFF i:real^N->bool) SUBSET (n DIFF j)`
1934     STRIP_ASSUME_TAC THENL
1935      [FIRST_X_ASSUM(MP_TAC o SPEC `j:real^N->bool` o CONJUNCT2) THEN
1936       ASM SET_TAC[];
1937       DISJ1_TAC THEN ASM SET_TAC[];
1938       DISJ2_TAC THEN EXISTS_TAC `j:real^N->bool` THEN ASM SET_TAC[]];
1939     ALL_TAC] THEN
1940   SUBGOAL_THEN `(j INTER k:real^N->bool) SUBSET (u UNION v)` ASSUME_TAC THENL
1941    [MATCH_MP_TAC(SET_RULE
1942      `k SUBSET (u UNION v) UNION (n DIFF j)
1943       ==> (j INTER k) SUBSET (u UNION v)`) THEN
1944     MATCH_MP_TAC SUBSET_TRANS THEN
1945     EXISTS_TAC `UNIONS g :real^N->bool` THEN ASM_REWRITE_TAC[] THEN
1946     MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC
1947      `UNIONS((u UNION v:real^N->bool) INSERT (g DELETE (u UNION v)))` THEN
1948     CONJ_TAC THENL [MATCH_MP_TAC SUBSET_UNIONS THEN SET_TAC[]; ALL_TAC] THEN
1949     ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[UNIONS_INSERT] THEN
1950     ASM SET_TAC[];
1951     ALL_TAC] THEN
1952   SUBGOAL_THEN `connected(j INTER k:real^N->bool)` MP_TAC THENL
1953    [ASM_MESON_TAC[SET_RULE `s SUBSET t ==> s INTER t = s`; INTER_COMM];
1954     REWRITE_TAC[connected] THEN
1955     MAP_EVERY EXISTS_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
1956     ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;
1957
1958 let CONNECTED_CHAIN_GEN = prove
1959  (`!f:(real^N->bool)->bool.
1960        (!s. s IN f ==> closed s /\ connected s) /\
1961        (?s. s IN f /\ compact s) /\
1962        (!s t. s IN f /\ t IN f ==> s SUBSET t \/ t SUBSET s)
1963        ==> connected(INTERS f)`,
1964   GEN_TAC THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
1965   FIRST_X_ASSUM(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
1966   SUBGOAL_THEN
1967    `INTERS f = INTERS(IMAGE (\t:real^N->bool. s INTER t) f)`
1968   SUBST1_TAC THENL
1969    [REWRITE_TAC[EXTENSION; INTERS_IMAGE] THEN ASM SET_TAC[];
1970     MATCH_MP_TAC CONNECTED_CHAIN THEN
1971     REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
1972     ASM_SIMP_TAC[COMPACT_INTER_CLOSED] THEN
1973     CONJ_TAC THENL [X_GEN_TAC `t:real^N->bool`; ASM SET_TAC[]] THEN
1974     DISCH_TAC THEN
1975     SUBGOAL_THEN `s INTER t:real^N->bool = s \/ s INTER t = t`
1976      (DISJ_CASES_THEN SUBST1_TAC) THEN
1977     ASM SET_TAC[]]);;
1978
1979 let CONNECTED_NEST = prove
1980  (`!s. (!n. compact(s n) /\ connected(s n)) /\
1981        (!m n. m <= n ==> s n SUBSET s m)
1982        ==> connected(INTERS {s n | n IN (:num)})`,
1983   GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC CONNECTED_CHAIN THEN
1984   ASM_SIMP_TAC[FORALL_IN_GSPEC; IN_UNIV; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1985   MATCH_MP_TAC WLOG_LE THEN ASM_MESON_TAC[]);;
1986
1987 let CONNECTED_NEST_GEN = prove
1988  (`!s. (!n. closed(s n) /\ connected(s n)) /\ (?n. compact(s n)) /\
1989        (!m n. m <= n ==> s n SUBSET s m)
1990        ==> connected(INTERS {s n | n IN (:num)})`,
1991   GEN_TAC THEN
1992   DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC) THEN
1993   MATCH_MP_TAC CONNECTED_CHAIN_GEN THEN
1994   ASM_SIMP_TAC[FORALL_IN_GSPEC; IN_UNIV; IMP_CONJ; RIGHT_FORALL_IMP_THM;
1995                EXISTS_IN_GSPEC] THEN
1996   MATCH_MP_TAC WLOG_LE THEN ASM_MESON_TAC[]);;
1997
1998 let EQ_BALLS = prove
1999  (`(!a a':real^N r r'.
2000       ball(a,r) = ball(a',r') <=> a = a' /\ r = r' \/ r <= &0 /\ r' <= &0) /\
2001    (!a a':real^N r r'.
2002       ball(a,r) = cball(a',r') <=> r <= &0 /\ r' < &0) /\
2003    (!a a':real^N r r'.
2004       cball(a,r) = ball(a',r') <=> r < &0 /\ r' <= &0) /\
2005    (!a a':real^N r r'.
2006       cball(a,r) = cball(a',r') <=> a = a' /\ r = r' \/ r < &0 /\ r' < &0)`,
2007   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT STRIP_TAC THEN
2008   (EQ_TAC THENL
2009     [ALL_TAC; REWRITE_TAC[EXTENSION; IN_BALL; IN_CBALL] THEN NORM_ARITH_TAC])
2010   THENL
2011    [REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; SUBSET_BALLS] THEN NORM_ARITH_TAC;
2012     ONCE_REWRITE_TAC[EQ_SYM_EQ];
2013     ALL_TAC;
2014     REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; SUBSET_BALLS] THEN NORM_ARITH_TAC] THEN
2015   DISCH_THEN(MP_TAC o MATCH_MP (MESON[CLOPEN; BOUNDED_BALL; NOT_BOUNDED_UNIV]
2016     `s = t ==> closed s /\ open t /\ bounded t ==> s = {} /\ t = {}`)) THEN
2017   REWRITE_TAC[OPEN_BALL; CLOSED_CBALL; BOUNDED_BALL;
2018               BALL_EQ_EMPTY; CBALL_EQ_EMPTY] THEN
2019   REAL_ARITH_TAC);;
2020
2021 let FINITE_CBALL = prove
2022  (`!a:real^N r. FINITE(cball(a,r)) <=> r <= &0`,
2023   REPEAT STRIP_TAC THEN ASM_CASES_TAC `r < &0` THEN
2024   ASM_SIMP_TAC[CBALL_EMPTY; REAL_LT_IMP_LE; FINITE_EMPTY] THEN
2025   ASM_CASES_TAC `r = &0` THEN
2026   ASM_REWRITE_TAC[CBALL_TRIVIAL; FINITE_SING; REAL_LE_REFL] THEN
2027   EQ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
2028   DISCH_THEN(MP_TAC o MATCH_MP EMPTY_INTERIOR_FINITE) THEN
2029   REWRITE_TAC[INTERIOR_CBALL; BALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC);;
2030
2031 let FINITE_BALL = prove
2032  (`!a:real^N r. FINITE(ball(a,r)) <=> r <= &0`,
2033   REPEAT STRIP_TAC THEN ASM_CASES_TAC `r <= &0` THEN
2034   ASM_SIMP_TAC[BALL_EMPTY; REAL_LT_IMP_LE; FINITE_EMPTY] THEN
2035   DISCH_THEN(MP_TAC o MATCH_MP (ONCE_REWRITE_RULE[IMP_CONJ]
2036         FINITE_IMP_NOT_OPEN)) THEN
2037   REWRITE_TAC[OPEN_BALL; BALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC);;
2038
2039 (* ------------------------------------------------------------------------- *)
2040 (* Minimal continua.                                                         *)
2041 (* ------------------------------------------------------------------------- *)
2042
2043 let MINIMAL_CONTINUUM = prove
2044  (`!t s:real^N->bool.
2045         t SUBSET s /\ compact s /\ connected s
2046         ==> ?u. t SUBSET u /\ u SUBSET s /\ compact u /\ connected u /\
2047                 !v. v SUBSET u /\ t SUBSET v /\ compact v /\ connected v
2048                     ==> v = u`,
2049   REPEAT STRIP_TAC THEN
2050   ASM_CASES_TAC `t:real^N->bool = {}` THENL
2051    [EXISTS_TAC `{}:real^N->bool` THEN
2052     ASM_MESON_TAC[COMPACT_EMPTY; CONNECTED_EMPTY; SUBSET_EMPTY; EMPTY_SUBSET];
2053     ALL_TAC] THEN
2054   MP_TAC(ISPECL [`\u:real^N->bool. t SUBSET u /\ connected u`;
2055                  `s:real^N->bool`]
2056         BROUWER_REDUCTION_THEOREM) THEN
2057   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
2058    [CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN GEN_TAC THEN STRIP_TAC THEN
2059     CONJ_TAC THENL
2060      [REWRITE_TAC[SUBSET_INTERS] THEN ASM SET_TAC[];
2061       MATCH_MP_TAC CONNECTED_NEST THEN ASM_REWRITE_TAC[] THEN
2062       MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
2063       ASM_REWRITE_TAC[] THEN SET_TAC[]];
2064     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
2065     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2066     REWRITE_TAC[SET_RULE `(v SUBSET u /\ p ==> v = u) <=>
2067                           (v SUBSET u /\ p ==> ~(v PSUBSET u))`] THEN
2068     GEN_TAC THEN STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
2069     ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN ASM SET_TAC[]]);;
2070
2071 (* ------------------------------------------------------------------------- *)
2072 (* Convex functions into the reals.                                          *)
2073 (* ------------------------------------------------------------------------- *)
2074
2075 parse_as_infix ("convex_on",(12,"right"));;
2076
2077 let convex_on = new_definition
2078   `f convex_on s <=>
2079         !x y u v. x IN s /\ y IN s /\ &0 <= u /\ &0 <= v /\ (u + v = &1)
2080                   ==> f(u % x + v % y) <= u * f(x) + v * f(y)`;;
2081
2082 let CONVEX_ON_SUBSET = prove
2083  (`!f s t. f convex_on t /\ s SUBSET t ==> f convex_on s`,
2084   REWRITE_TAC[convex_on; SUBSET] THEN MESON_TAC[]);;
2085
2086 let CONVEX_ON_EQ = prove
2087  (`!f g s. convex s /\ (!x. x IN s ==> f x = g x) /\ f convex_on s
2088            ==> g convex_on s`,
2089   REWRITE_TAC[convex_on; convex] THEN MESON_TAC[]);;
2090
2091 let CONVEX_ADD = prove
2092  (`!s f g. f convex_on s /\ g convex_on s ==> (\x. f(x) + g(x)) convex_on s`,
2093   REWRITE_TAC[convex_on; AND_FORALL_THM] THEN
2094   REPEAT(MATCH_MP_TAC MONO_FORALL ORELSE GEN_TAC) THEN
2095   MATCH_MP_TAC(TAUT
2096     `(b /\ c ==> d) ==> (a ==> b) /\ (a ==> c) ==> a ==> d`) THEN
2097   REAL_ARITH_TAC);;
2098
2099 let CONVEX_CMUL = prove
2100  (`!s c f. &0 <= c /\ f convex_on s ==> (\x. c * f(x)) convex_on s`,
2101   SIMP_TAC[convex_on; REAL_LE_LMUL;
2102            REAL_ARITH `u * c * fx + v * c * fy = c * (u * fx + v * fy)`]);;
2103
2104 let CONVEX_MAX = prove
2105  (`!f g s. f convex_on s /\ g convex_on s
2106            ==> (\x. max (f x) (g x)) convex_on s`,
2107   REWRITE_TAC[convex_on; REAL_MAX_LE] THEN REPEAT STRIP_TAC THEN
2108   FIRST_X_ASSUM(fun th ->
2109     W(MP_TAC o PART_MATCH (lhand o rand) th o lhand o snd)) THEN
2110   ASM_REWRITE_TAC[] THEN
2111   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
2112   MATCH_MP_TAC REAL_LE_ADD2 THEN CONJ_TAC THEN
2113   MATCH_MP_TAC REAL_LE_LMUL THEN ASM_REAL_ARITH_TAC);;
2114
2115 let CONVEX_LOWER = prove
2116  (`!f s x y. f convex_on s /\
2117              x IN s /\ y IN s /\ &0 <= u /\ &0 <= v /\ (u + v = &1)
2118              ==> f(u % x + v % y) <= max (f(x)) (f(y))`,
2119   REWRITE_TAC[convex_on] THEN REPEAT STRIP_TAC THEN
2120   GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN
2121   FIRST_ASSUM(fun th -> GEN_REWRITE_TAC (RAND_CONV o LAND_CONV) [SYM th]) THEN
2122   REWRITE_TAC[REAL_ADD_RDISTRIB] THEN MATCH_MP_TAC REAL_LE_TRANS THEN
2123   ASM_MESON_TAC[REAL_LE_ADD2; REAL_LE_LMUL; REAL_MAX_MAX]);;
2124
2125 let CONVEX_LOWER_SEGMENT = prove
2126  (`!f s a b x:real^N.
2127         f convex_on s /\ a IN s /\ b IN s /\ x IN segment[a,b]
2128         ==> f(x) <= max (f a) (f b)`,
2129   REWRITE_TAC[IN_SEGMENT] THEN REPEAT STRIP_TAC THEN
2130   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONVEX_LOWER THEN
2131   EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
2132
2133 let CONVEX_LOCAL_GLOBAL_MINIMUM = prove
2134  (`!f s t x:real^N.
2135        f convex_on s /\ x IN t /\ open t /\ t SUBSET s /\
2136        (!y. y IN t ==> f(x) <= f(y))
2137        ==> !y. y IN s ==> f(x) <= f(y)`,
2138   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
2139   SUBGOAL_THEN `&0 < dist(x:real^N,y)` ASSUME_TAC THENL
2140    [ASM_MESON_TAC[DIST_POS_LT; REAL_LT_REFL]; ALL_TAC] THEN
2141   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
2142   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
2143   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
2144   MP_TAC(SPECL [`&1`; `e / dist(x:real^N,y)`] REAL_DOWN2) THEN
2145   ANTS_TAC THENL [ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_01]; ALL_TAC] THEN
2146   DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
2147   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex_on]) THEN
2148   DISCH_THEN(MP_TAC o
2149     SPECL [`x:real^N`; `y:real^N`; `&1 - u`; `u:real`]) THEN
2150   ANTS_TAC THENL
2151    [ASM_SIMP_TAC[REAL_SUB_ADD; REAL_SUB_LE; REAL_LT_IMP_LE] THEN
2152     ASM_MESON_TAC[CENTRE_IN_BALL; SUBSET];
2153     ALL_TAC] THEN
2154   REWRITE_TAC[REAL_NOT_LE] THEN MATCH_MP_TAC REAL_LTE_TRANS THEN
2155   EXISTS_TAC `(&1 - u) * f(x) + u * f(x:real^N):real` THEN
2156   ASM_SIMP_TAC[REAL_LT_LADD; REAL_LT_LMUL] THEN
2157   REWRITE_TAC[REAL_ARITH `(&1 - x) * a + x * a = a`] THEN
2158   FIRST_X_ASSUM MATCH_MP_TAC THEN
2159   FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
2160   REWRITE_TAC[IN_BALL; dist] THEN
2161   REWRITE_TAC[VECTOR_ARITH `x - ((&1 - u) % x + u % y):real^N =
2162                             u % (x - y)`] THEN
2163   REWRITE_TAC[NORM_MUL; GSYM dist] THEN
2164   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ;
2165                REAL_ARITH `&0 < x /\ x < b ==> abs x < b`]);;
2166
2167 let CONVEX_DISTANCE = prove
2168  (`!s a. (\x. dist(a,x)) convex_on s`,
2169   REWRITE_TAC[convex_on; dist] THEN REPEAT STRIP_TAC THEN
2170   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o LAND_CONV)
2171    [GSYM VECTOR_MUL_LID] THEN
2172   FIRST_ASSUM(SUBST1_TAC o SYM) THEN
2173   REWRITE_TAC[VECTOR_ARITH
2174    `(u + v) % z - (u % x + v % y) = u % (z - x) + v % (z - y)`] THEN
2175   ASM_MESON_TAC[NORM_TRIANGLE; NORM_MUL; REAL_ABS_REFL]);;
2176
2177 let CONVEX_NORM = prove
2178  (`!s:real^N->bool. norm convex_on s`,
2179   GEN_TAC THEN
2180   MP_TAC(ISPECL [`s:real^N->bool`; `vec 0:real^N`] CONVEX_DISTANCE) THEN
2181   REWRITE_TAC[DIST_0; ETA_AX]);;
2182
2183 let CONVEX_ON_COMPOSE_LINEAR = prove
2184  (`!f g:real^M->real^N s.
2185         f convex_on (IMAGE g s) /\ linear g ==> (f o g) convex_on s`,
2186   REWRITE_TAC[convex_on; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
2187   REWRITE_TAC[FORALL_IN_IMAGE; o_THM] THEN
2188   REWRITE_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP; GSYM CONJ_ASSOC] THEN
2189   REPEAT STRIP_TAC THEN
2190   FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP LINEAR_ADD th]) THEN
2191   FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP LINEAR_CMUL th]) THEN
2192   ASM_SIMP_TAC[]);;
2193
2194 let CONVEX_ON_TRANSLATION = prove
2195  (`!f a:real^N.
2196         f convex_on (IMAGE (\x. a + x) s) <=> (\x. f(a + x)) convex_on s`,
2197   REWRITE_TAC[convex_on; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
2198   REWRITE_TAC[FORALL_IN_IMAGE; o_THM] THEN
2199   REWRITE_TAC[VECTOR_ARITH
2200    `u % (a + x) + v % (a + y):real^N = (u + v) % a + u % x + v % y`] THEN
2201   SIMP_TAC[VECTOR_MUL_LID]);;
2202
2203 (* ------------------------------------------------------------------------- *)
2204 (* Open and closed balls are convex and hence connected.                     *)
2205 (* ------------------------------------------------------------------------- *)
2206
2207 let CONVEX_BALL = prove
2208  (`!x:real^N e. convex(ball(x,e))`,
2209   let lemma = REWRITE_RULE[convex_on; IN_UNIV]
2210    (ISPEC `(:real^N)` CONVEX_DISTANCE) in
2211   REWRITE_TAC[convex; IN_BALL] THEN REPEAT STRIP_TAC THEN
2212   W(MP_TAC o PART_MATCH (lhand o rand) lemma o lhand o snd) THEN
2213   ASM_MESON_TAC[REAL_LET_TRANS; REAL_CONVEX_BOUND_LT]);;
2214
2215 let CONNECTED_BALL = prove
2216  (`!x:real^N e. connected(ball(x,e))`,
2217   SIMP_TAC[CONVEX_CONNECTED; CONVEX_BALL]);;
2218
2219 let CONVEX_CBALL = prove
2220  (`!x:real^N e. convex(cball(x,e))`,
2221   REWRITE_TAC[convex; IN_CBALL; dist] THEN MAP_EVERY X_GEN_TAC
2222    [`x:real^N`; `e:real`; `y:real^N`; `z:real^N`; `u:real`; `v:real`] THEN
2223   STRIP_TAC THEN ONCE_REWRITE_TAC[VECTOR_ARITH `a - b = &1 % a - b`] THEN
2224   FIRST_ASSUM(SUBST1_TAC o SYM) THEN
2225   REWRITE_TAC[VECTOR_ARITH
2226    `(a + b) % x - (a % y + b % z) = a % (x - y) + b % (x - z)`] THEN
2227   MATCH_MP_TAC REAL_LE_TRANS THEN
2228   EXISTS_TAC `norm(u % (x - y)) + norm(v % (x - z):real^N)` THEN
2229   REWRITE_TAC[NORM_TRIANGLE; NORM_MUL] THEN
2230   MATCH_MP_TAC REAL_CONVEX_BOUND_LE THEN ASM_REWRITE_TAC[REAL_ABS_POS] THEN
2231   ASM_SIMP_TAC[REAL_ARITH
2232    `&0 <= u /\ &0 <= v /\ (u + v = &1) ==> (abs(u) + abs(v) = &1)`]);;
2233
2234 let CONNECTED_CBALL = prove
2235  (`!x:real^N e. connected(cball(x,e))`,
2236   SIMP_TAC[CONVEX_CONNECTED; CONVEX_CBALL]);;
2237
2238 let CONVEX_INTERMEDIATE_BALL = prove
2239  (`!a:real^N r t. ball(a,r) SUBSET t /\ t SUBSET cball(a,r) ==> convex t`,
2240   REPEAT STRIP_TAC THEN REWRITE_TAC[CONVEX_CONTAINS_OPEN_SEGMENT] THEN
2241   REPEAT STRIP_TAC THEN
2242   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
2243     SUBSET_TRANS)) THEN
2244   REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL] THEN GEN_TAC THEN DISCH_THEN
2245    (MP_TAC o SPEC `a:real^N` o MATCH_MP DIST_DECREASES_OPEN_SEGMENT) THEN
2246   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
2247   REWRITE_TAC[IN_CBALL] THEN ASM_MESON_TAC[REAL_LTE_TRANS]);;
2248
2249 let FRONTIER_OF_CONNECTED_COMPONENT_SUBSET = prove
2250  (`!s c x:real^N. frontier(connected_component s x) SUBSET frontier s`,
2251   REPEAT GEN_TAC THEN REWRITE_TAC[frontier; SUBSET; IN_DIFF] THEN
2252   X_GEN_TAC `y:real^N` THEN REPEAT STRIP_TAC THENL
2253    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
2254      `y IN s ==> s SUBSET t ==> y IN t`)) THEN
2255     MATCH_MP_TAC SUBSET_CLOSURE THEN REWRITE_TAC[CONNECTED_COMPONENT_SUBSET];
2256     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR]) THEN
2257     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
2258     SUBGOAL_THEN `ball(y:real^N,e) SUBSET connected_component s y`
2259     ASSUME_TAC THENL
2260      [MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
2261       ASM_REWRITE_TAC[CONNECTED_BALL; CENTRE_IN_BALL];
2262       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CLOSURE_APPROACHABLE]) THEN
2263       DISCH_THEN(MP_TAC o SPEC `e:real`) THEN
2264       ASM_REWRITE_TAC[ONCE_REWRITE_RULE[DIST_SYM] (GSYM IN_BALL)] THEN
2265       STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN
2266       REWRITE_TAC[IN_INTERIOR] THEN EXISTS_TAC `e:real` THEN
2267       MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`; `y:real^N`]
2268         CONNECTED_COMPONENT_OVERLAP) THEN
2269       MATCH_MP_TAC(TAUT `p /\ (q ==> r) ==> (p <=> q) ==> r`) THEN
2270       ASM_SIMP_TAC[] THEN ASM SET_TAC[]]]);;
2271
2272 let FRONTIER_OF_COMPONENTS_SUBSET = prove
2273  (`!s c:real^N->bool.
2274         c IN components s ==> frontier c SUBSET frontier s`,
2275   SIMP_TAC[components; FORALL_IN_GSPEC;
2276            FRONTIER_OF_CONNECTED_COMPONENT_SUBSET]);;
2277
2278 let FRONTIER_OF_COMPONENTS_CLOSED_COMPLEMENT = prove
2279  (`!s c. closed s /\ c IN components ((:real^N) DIFF s)
2280          ==> frontier c SUBSET s`,
2281   REPEAT STRIP_TAC THEN
2282   FIRST_ASSUM(MP_TAC o MATCH_MP FRONTIER_OF_COMPONENTS_SUBSET) THEN
2283   REWRITE_TAC[FRONTIER_COMPLEMENT] THEN
2284   ASM_MESON_TAC[FRONTIER_SUBSET_EQ; SUBSET_TRANS]);;
2285
2286 (* ------------------------------------------------------------------------- *)
2287 (* A couple of lemmas about components (see Newman IV, 3.3 and 3.4).         *)
2288 (* ------------------------------------------------------------------------- *)
2289
2290 let CONNECTED_UNION_CLOPEN_IN_COMPLEMENT = prove
2291  (`!s t u:real^N->bool.
2292         connected s /\ connected u /\ s SUBSET u /\
2293         open_in (subtopology euclidean (u DIFF s)) t /\
2294         closed_in (subtopology euclidean (u DIFF s)) t
2295         ==> connected (s UNION t)`,
2296   MAP_EVERY X_GEN_TAC
2297    [`c:real^N->bool`; `h:real^N->bool`; `s:real^N->bool`] THEN
2298   STRIP_TAC THEN
2299   REWRITE_TAC[CONNECTED_CLOSED_IN_EQ; NOT_EXISTS_THM] THEN
2300   MATCH_MP_TAC(MESON[]
2301    `!Q. (!x y. P x y <=> P y x) /\
2302         (!x y. P x y ==> Q x \/ Q y) /\
2303         (!x y. P x y /\ Q x ==> F)
2304         ==> (!x y. ~(P x y))`) THEN
2305   EXISTS_TAC `\x:real^N->bool. c SUBSET x` THEN
2306   CONJ_TAC THENL [MESON_TAC[INTER_COMM; UNION_COMM]; ALL_TAC] THEN
2307   REWRITE_TAC[] THEN CONJ_TAC THEN
2308   MAP_EVERY X_GEN_TAC [`h1:real^N->bool`; `h2:real^N->bool`] THENL
2309    [STRIP_TAC THEN UNDISCH_TAC `connected(c:real^N->bool)` THEN
2310     REWRITE_TAC[CONNECTED_CLOSED_IN; NOT_EXISTS_THM] THEN
2311     DISCH_THEN(MP_TAC o
2312       SPECL [`c INTER h1:real^N->bool`; `c INTER h2:real^N->bool`]) THEN
2313     MATCH_MP_TAC(TAUT
2314      `(p /\ q) /\ (~r ==> s) ==> ~(p /\ q /\ r) ==> s`) THEN
2315     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN CONJ_TAC THENL
2316      [UNDISCH_TAC
2317         `closed_in(subtopology euclidean (c UNION h)) (h1:real^N->bool)`;
2318       UNDISCH_TAC
2319         `closed_in(subtopology euclidean (c UNION h)) (h2:real^N->bool)`] THEN
2320     REWRITE_TAC[CLOSED_IN_CLOSED] THEN MATCH_MP_TAC MONO_EXISTS THEN
2321     ASM SET_TAC[];
2322     STRIP_TAC THEN
2323     FIRST_ASSUM(ASSUME_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN
2324     SUBGOAL_THEN `(h2:real^N->bool) SUBSET h` ASSUME_TAC THENL
2325      [ASM SET_TAC[]; ALL_TAC] THEN
2326     UNDISCH_TAC `connected(s:real^N->bool)` THEN
2327     REWRITE_TAC[CONNECTED_CLOPEN] THEN
2328     DISCH_THEN(MP_TAC o SPEC `h2:real^N->bool`) THEN REWRITE_TAC[NOT_IMP] THEN
2329     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
2330     SUBGOAL_THEN `s:real^N->bool = (s DIFF c) UNION (c UNION h)`
2331     SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN CONJ_TAC THENL
2332      [MATCH_MP_TAC OPEN_IN_SUBTOPOLOGY_UNION THEN
2333       MATCH_MP_TAC(TAUT `q /\ (q ==> p) ==> p /\ q`) THEN CONJ_TAC THENL
2334        [REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
2335         CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2336         SUBGOAL_THEN `(c UNION h) DIFF h2:real^N->bool = h1`
2337          (fun th -> ASM_REWRITE_TAC[th]) THEN ASM SET_TAC[];
2338         DISCH_TAC THEN MATCH_MP_TAC OPEN_IN_TRANS THEN
2339         EXISTS_TAC `h:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
2340         UNDISCH_TAC
2341          `open_in(subtopology euclidean (c UNION h)) (h2:real^N->bool)` THEN
2342         REWRITE_TAC[OPEN_IN_OPEN] THEN MATCH_MP_TAC MONO_EXISTS THEN
2343         ASM SET_TAC[]];
2344       MATCH_MP_TAC CLOSED_IN_SUBTOPOLOGY_UNION THEN ASM_REWRITE_TAC[] THEN
2345       MATCH_MP_TAC CLOSED_IN_TRANS THEN EXISTS_TAC `h:real^N->bool` THEN
2346       ASM_REWRITE_TAC[] THEN
2347       UNDISCH_TAC
2348        `closed_in(subtopology euclidean (c UNION h)) (h2:real^N->bool)` THEN
2349       REWRITE_TAC[CLOSED_IN_CLOSED] THEN MATCH_MP_TAC MONO_EXISTS THEN
2350       ASM SET_TAC[]]]);;
2351
2352 let COMPONENT_COMPLEMENT_CONNECTED = prove
2353  (`!s u c:real^N->bool.
2354         connected s /\ connected u /\ s SUBSET u /\ c IN components (u DIFF s)
2355         ==> connected(u DIFF c)`,
2356   MAP_EVERY X_GEN_TAC
2357    [`a:real^N->bool`; `s:real^N->bool`; `c:real^N->bool`] THEN
2358   STRIP_TAC THEN UNDISCH_TAC `connected(a:real^N->bool)` THEN
2359   REWRITE_TAC[CONNECTED_CLOSED_IN_EQ; NOT_EXISTS_THM] THEN
2360   DISCH_TAC THEN MAP_EVERY X_GEN_TAC
2361    [`h3:real^N->bool`; `h4:real^N->bool`] THEN STRIP_TAC THEN
2362   FIRST_X_ASSUM(MP_TAC o SPECL
2363    [`a INTER h3:real^N->bool`; `a INTER h4:real^N->bool`]) THEN
2364   FIRST_ASSUM(MP_TAC o MATCH_MP IN_COMPONENTS_NONEMPTY) THEN
2365   FIRST_ASSUM(MP_TAC o MATCH_MP IN_COMPONENTS_SUBSET) THEN
2366   EVERY_ASSUM(fun th -> try
2367         MP_TAC(CONJUNCT1(GEN_REWRITE_RULE I [closed_in] th))
2368         with Failure _ -> ALL_TAC) THEN
2369   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN REPEAT DISCH_TAC THEN
2370   REPEAT CONJ_TAC THENL
2371    [UNDISCH_TAC `closed_in (subtopology euclidean (s DIFF c))
2372                            (h3:real^N->bool)` THEN
2373     REWRITE_TAC[CLOSED_IN_CLOSED] THEN MATCH_MP_TAC MONO_EXISTS THEN
2374     ASM SET_TAC[];
2375     UNDISCH_TAC `closed_in (subtopology euclidean (s DIFF c))
2376                            (h4:real^N->bool)` THEN
2377     REWRITE_TAC[CLOSED_IN_CLOSED] THEN MATCH_MP_TAC MONO_EXISTS THEN
2378     ASM SET_TAC[];
2379     ASM SET_TAC[];
2380     ASM SET_TAC[];
2381     DISCH_TAC THEN
2382     MP_TAC(ISPECL [`s DIFF a:real^N->bool`; `c UNION h3:real^N->bool`;
2383                `c:real^N->bool`] COMPONENTS_MAXIMAL) THEN
2384     ASM_REWRITE_TAC[NOT_IMP; GSYM CONJ_ASSOC] THEN
2385     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
2386     MATCH_MP_TAC CONNECTED_UNION_CLOPEN_IN_COMPLEMENT THEN
2387     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
2388     REPEAT CONJ_TAC THENL
2389      [ASM_MESON_TAC[IN_COMPONENTS_CONNECTED];
2390       ASM SET_TAC[];
2391       REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
2392       CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2393       SUBGOAL_THEN `s DIFF c DIFF h3:real^N->bool = h4` SUBST1_TAC THEN
2394       ASM SET_TAC[]];
2395     DISCH_TAC THEN
2396     MP_TAC(ISPECL [`s DIFF a:real^N->bool`; `c UNION h4:real^N->bool`;
2397                `c:real^N->bool`] COMPONENTS_MAXIMAL) THEN
2398     ASM_REWRITE_TAC[NOT_IMP; GSYM CONJ_ASSOC] THEN
2399     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
2400     MATCH_MP_TAC CONNECTED_UNION_CLOPEN_IN_COMPLEMENT THEN
2401     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
2402     REPEAT CONJ_TAC THENL
2403      [ASM_MESON_TAC[IN_COMPONENTS_CONNECTED];
2404       ASM SET_TAC[];
2405       REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
2406       CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2407       SUBGOAL_THEN `s DIFF c DIFF h4:real^N->bool = h3` SUBST1_TAC THEN
2408       ASM SET_TAC[]]]);;
2409
2410 (* ------------------------------------------------------------------------- *)
2411 (* Condition for an open map's image to contain a ball.                      *)
2412 (* ------------------------------------------------------------------------- *)
2413
2414 let BALL_SUBSET_OPEN_MAP_IMAGE = prove
2415  (`!f:real^M->real^N s a r.
2416         bounded s /\ f continuous_on closure s /\ open(IMAGE f (interior s)) /\
2417         a IN s /\ &0 < r /\ (!z. z IN frontier s ==> r <= norm(f z - f a))
2418         ==> ball(f(a),r) SUBSET IMAGE f s`,
2419   REPEAT STRIP_TAC THEN
2420   MP_TAC(ISPECL [`ball((f:real^M->real^N) a,r)`;
2421                  `(:real^N) DIFF IMAGE (f:real^M->real^N) s`]
2422     CONNECTED_INTER_FRONTIER) THEN
2423   REWRITE_TAC[CONNECTED_BALL] THEN MATCH_MP_TAC(SET_RULE
2424    `~(b INTER s = {}) /\ b INTER f = {} ==>
2425     (~(b INTER (UNIV DIFF s) = {}) /\ ~(b DIFF (UNIV DIFF s) = {})
2426      ==> ~(b INTER f = {}))
2427     ==> b SUBSET s`) THEN
2428   REWRITE_TAC[FRONTIER_COMPLEMENT] THEN CONJ_TAC THENL
2429    [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN
2430     EXISTS_TAC `(f:real^M->real^N) a` THEN
2431     ASM_REWRITE_TAC[CENTRE_IN_BALL] THEN ASM SET_TAC[];
2432     REWRITE_TAC[SET_RULE `s INTER t = {} <=> !x. x IN t ==> ~(x IN s)`] THEN
2433     REWRITE_TAC[IN_BALL; REAL_NOT_LT]] THEN
2434   MP_TAC(ISPECL[`frontier(IMAGE (f:real^M->real^N) s)`; `(f:real^M->real^N) a`]
2435     DISTANCE_ATTAINS_INF) THEN
2436   REWRITE_TAC[FRONTIER_CLOSED; FRONTIER_EQ_EMPTY] THEN ANTS_TAC THENL
2437    [SIMP_TAC[DE_MORGAN_THM] THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2438     MATCH_MP_TAC(MESON[NOT_BOUNDED_UNIV] `bounded s ==> ~(s = UNIV)`) THEN
2439     MATCH_MP_TAC BOUNDED_SUBSET THEN
2440     EXISTS_TAC `IMAGE (f:real^M->real^N) (closure s)` THEN
2441     SIMP_TAC[IMAGE_SUBSET; CLOSURE_SUBSET] THEN
2442     MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
2443     MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
2444     ASM_REWRITE_TAC[COMPACT_CLOSURE];
2445     DISCH_THEN(X_CHOOSE_THEN `w:real^N` STRIP_ASSUME_TAC)] THEN
2446   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [frontier]) THEN
2447   REWRITE_TAC[IN_DIFF] THEN
2448   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
2449   REWRITE_TAC[CLOSURE_SEQUENTIAL] THEN
2450   DISCH_THEN(X_CHOOSE_THEN `y:num->real^N`
2451    (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC)) THEN
2452   REWRITE_TAC[IN_IMAGE; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
2453   X_GEN_TAC `z:num->real^M` THEN REWRITE_TAC[FORALL_AND_THM] THEN
2454   ONCE_REWRITE_TAC[GSYM FUN_EQ_THM] THEN
2455   DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
2456   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM COMPACT_CLOSURE]) THEN
2457   REWRITE_TAC[compact] THEN
2458   DISCH_THEN(MP_TAC o SPEC `z:num->real^M`) THEN
2459   ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET; LEFT_IMP_EXISTS_THM] THEN
2460   MAP_EVERY X_GEN_TAC [`y:real^M`; `r:num->num`] THEN STRIP_TAC THEN
2461   SUBGOAL_THEN
2462    `(((\n. (f:real^M->real^N)(z n)) o (r:num->num)) --> w) sequentially`
2463   MP_TAC THENL
2464    [MATCH_MP_TAC LIM_SUBSEQUENCE THEN ASM_REWRITE_TAC[];
2465     ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[GSYM o_ASSOC]] THEN
2466   DISCH_TAC THEN
2467   SUBGOAL_THEN `!n. ((z:num->real^M) o (r:num->num)) n IN s` MP_TAC THENL
2468    [ASM_REWRITE_TAC[o_THM];
2469     UNDISCH_THEN `((\n. (f:real^M->real^N) ((z:num->real^M) n)) --> w)
2470                   sequentially` (K ALL_TAC) THEN
2471     UNDISCH_THEN `!n. (z:num->real^M) n IN s` (K ALL_TAC)] THEN
2472   POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
2473   SPEC_TAC(`(z:num->real^M) o (r:num->num)`, `z:num->real^M`) THEN
2474   REPEAT STRIP_TAC THEN
2475   SUBGOAL_THEN `w = (f:real^M->real^N) y` SUBST_ALL_TAC THENL
2476    [MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
2477     EXISTS_TAC `(f:real^M->real^N) o (z:num->real^M)` THEN
2478     ASM_REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY] THEN
2479     ASM_MESON_TAC[CONTINUOUS_ON_CLOSURE_SEQUENTIALLY];
2480     ALL_TAC] THEN
2481   MATCH_MP_TAC REAL_LE_TRANS THEN
2482   EXISTS_TAC `norm(f y - (f:real^M->real^N) a)` THEN CONJ_TAC THENL
2483    [FIRST_X_ASSUM MATCH_MP_TAC; ASM_MESON_TAC[dist; NORM_SUB]] THEN
2484   ASM_REWRITE_TAC[frontier; IN_DIFF] THEN DISCH_TAC THEN
2485   FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN
2486   REWRITE_TAC[interior; IN_ELIM_THM] THEN
2487   EXISTS_TAC `IMAGE (f:real^M->real^N) (interior s)` THEN
2488   ASM_SIMP_TAC[IMAGE_SUBSET; INTERIOR_SUBSET] THEN ASM SET_TAC[]);;
2489
2490 (* ------------------------------------------------------------------------- *)
2491 (* Arithmetic operations on sets preserve convexity.                         *)
2492 (* ------------------------------------------------------------------------- *)
2493
2494 let CONVEX_SCALING = prove
2495  (`!s c. convex s ==> convex (IMAGE (\x. c % x) s)`,
2496   REWRITE_TAC[convex; IN_IMAGE] THEN REPEAT STRIP_TAC THEN
2497   ASM_REWRITE_TAC[VECTOR_ARITH
2498    `u % c % x + v % c % y = c % (u % x + v % y)`] THEN
2499   ASM_MESON_TAC[]);;
2500
2501 let CONVEX_SCALING_EQ = prove
2502  (`!s c. ~(c = &0) ==> (convex (IMAGE (\x. c % x) s) <=> convex s)`,
2503   REPEAT STRIP_TAC THEN EQ_TAC THEN REWRITE_TAC[CONVEX_SCALING] THEN
2504   DISCH_THEN(MP_TAC o SPEC `inv c` o MATCH_MP CONVEX_SCALING) THEN
2505   ASM_SIMP_TAC[GSYM IMAGE_o; o_DEF; VECTOR_MUL_ASSOC;
2506                REAL_MUL_LINV; VECTOR_MUL_LID; IMAGE_ID]);;
2507
2508 let CONVEX_NEGATIONS = prove
2509  (`!s. convex s ==> convex (IMAGE (--) s)`,
2510   REWRITE_TAC[convex; IN_IMAGE] THEN REPEAT STRIP_TAC THEN
2511   ASM_REWRITE_TAC[VECTOR_ARITH
2512    `u % --x + v % --y = --(u % x + v % y)`] THEN
2513   ASM_MESON_TAC[]);;
2514
2515 let CONVEX_SUMS = prove
2516  (`!s t. convex s /\ convex t ==> convex {x + y | x IN s /\ y IN t}`,
2517   REWRITE_TAC[convex; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
2518   ASM_REWRITE_TAC[VECTOR_ARITH
2519     `u % (a + b) + v % (c + d) = (u % a + v % c) + (u % b + v % d)`] THEN
2520   ASM_MESON_TAC[]);;
2521
2522 let CONVEX_DIFFERENCES = prove
2523  (`!s t. convex s /\ convex t ==> convex {x - y | x IN s /\ y IN t}`,
2524   REWRITE_TAC[convex; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
2525   ASM_REWRITE_TAC[VECTOR_ARITH
2526     `u % (a - b) + v % (c - d) = (u % a + v % c) - (u % b + v % d)`] THEN
2527   ASM_MESON_TAC[]);;
2528
2529 let CONVEX_AFFINITY = prove
2530  (`!s a:real^N c.
2531         convex s ==> convex (IMAGE (\x. a + c % x) s)`,
2532   REPEAT STRIP_TAC THEN
2533   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
2534   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
2535   ASM_SIMP_TAC[IMAGE_o; CONVEX_TRANSLATION; CONVEX_SCALING]);;
2536
2537 let CONVEX_LINEAR_PREIMAGE = prove
2538  (`!f:real^M->real^N.
2539      linear f /\ convex s ==> convex {x | f(x) IN s}`,
2540   REWRITE_TAC[CONVEX_ALT; IN_ELIM_THM] THEN
2541   SIMP_TAC[LINEAR_ADD; LINEAR_CMUL]);;
2542
2543 (* ------------------------------------------------------------------------- *)
2544 (* Some interesting "cancellation" properties for sum-sets.                  *)
2545 (* ------------------------------------------------------------------------- *)
2546
2547 let SUBSET_SUMS_LCANCEL = prove
2548  (`!s t u:real^N->bool.
2549         ~(s = {}) /\ bounded s /\ closed u /\ convex u /\
2550         {x + y | x IN s /\ y IN t} SUBSET {x + z | x IN s /\ z IN u}
2551         ==> t SUBSET u`,
2552   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN REWRITE_TAC[IN_ELIM_THM] THEN
2553   REPEAT GEN_TAC THEN STRIP_TAC THEN
2554   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
2555   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN X_GEN_TAC `b:real^N` THEN
2556   DISCH_TAC THEN
2557   SUBGOAL_THEN
2558    `!n. ?w z:real^N. w IN s /\ z IN u /\ (&n + &1) % (b - z) = w - a`
2559   MP_TAC THENL
2560    [INDUCT_TAC THENL
2561      [FIRST_X_ASSUM(MP_TAC o SPECL [`a:real^N`; `b:real^N`]) THEN
2562       ASM_REWRITE_TAC[REAL_ADD_LID; VECTOR_MUL_LID] THEN
2563       REWRITE_TAC[VECTOR_ARITH `b - z:real^N = w - a <=> a + b = w + z`] THEN
2564       MESON_TAC[];
2565       FIRST_X_ASSUM(X_CHOOSE_THEN `a':real^N` (X_CHOOSE_THEN `c':real^N`
2566         STRIP_ASSUME_TAC)) THEN
2567       FIRST_X_ASSUM(MP_TAC o SPECL [`a':real^N`; `b:real^N`]) THEN
2568       ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
2569       MAP_EVERY X_GEN_TAC [`a'':real^N`; `c'':real^N`] THEN STRIP_TAC THEN
2570       EXISTS_TAC `a'':real^N` THEN EXISTS_TAC
2571        `(&1 - &1 / (&n + &2)) % c' + &1 / (&n + &2) % c'':real^N` THEN
2572       ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
2573        [FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[CONVEX_ALT]) THEN
2574         ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ;
2575                      REAL_ARITH `&0 < &n + &2`] THEN
2576         REAL_ARITH_TAC;
2577         FIRST_X_ASSUM(SUBST1_TAC o GEN_REWRITE_RULE I
2578          [VECTOR_ARITH `a' + b:real^N = a'' + c <=> a'' = (a' + b) - c`]) THEN
2579         REWRITE_TAC[VECTOR_ARITH
2580          `(&n + &1) % (b - c):real^N = (a' + b) - c'' - a <=>
2581           &n % b - (&n + &1) % c = (a' - c'') - a`] THEN
2582         SIMP_TAC[GSYM REAL_OF_NUM_SUC; VECTOR_MUL_ASSOC; VECTOR_ADD_LDISTRIB;
2583                  REAL_ARITH `(n + &1) + &1 = n + &2`] THEN
2584         REWRITE_TAC[VECTOR_MUL_LID; REAL_FIELD
2585          `(&n + &2) * (&1 - (&1 / (&n + &2))) = &n + &1 /\
2586           (&n + &2) * &1 / (&n + &2) = &1`] THEN
2587         ASM_REWRITE_TAC[VECTOR_ARITH
2588          `n % b - (n % c + d):real^N = n % (b - c) - d`] THEN
2589         CONV_TAC VECTOR_ARITH]];
2590       FIRST_X_ASSUM(K ALL_TAC o check is_forall o concl) THEN
2591       MP_TAC(ISPECL [`s:real^N->bool`; `s:real^N->bool`] BOUNDED_DIFFS) THEN
2592       ASM_REWRITE_TAC[] THEN REWRITE_TAC[BOUNDED_POS; FORALL_IN_GSPEC] THEN
2593       DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
2594       DISCH_TAC THEN FIRST_X_ASSUM(fun th ->
2595         ONCE_REWRITE_TAC[GSYM(MATCH_MP CLOSED_APPROACHABLE th)]) THEN
2596       X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2597       MP_TAC(SPEC `e:real` REAL_ARCH) THEN ASM_REWRITE_TAC[] THEN
2598       DISCH_THEN(MP_TAC o SPEC `B:real`) THEN
2599       REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
2600       MATCH_MP_TAC num_INDUCTION THEN REWRITE_TAC[REAL_MUL_LZERO] THEN
2601       CONJ_TAC THENL [ASM_REAL_ARITH_TAC; X_GEN_TAC `n:num`] THEN
2602       DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[GSYM REAL_OF_NUM_SUC] THEN
2603       DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `n:num`) THEN
2604       ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
2605       X_GEN_TAC `c:real^N` THEN
2606       DISCH_THEN(X_CHOOSE_THEN `d:real^N` STRIP_ASSUME_TAC) THEN
2607       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LT_LCANCEL_IMP THEN
2608       EXISTS_TAC `abs(&n + &1)` THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
2609       CONJ_TAC THENL [REAL_ARITH_TAC; REWRITE_TAC[dist]] THEN
2610       ASM_REWRITE_TAC[GSYM NORM_MUL] THEN
2611       REWRITE_TAC[REAL_ARITH `abs(&n + &1) = &n + &1`] THEN
2612       ASM_MESON_TAC[REAL_LET_TRANS]]);;
2613
2614 let SUBSET_SUMS_RCANCEL = prove
2615  (`!s t u:real^N->bool.
2616         closed t /\ convex t /\ bounded u /\ ~(u = {}) /\
2617         {x + z | x IN s /\ z IN u} SUBSET {y + z | y IN t /\ z IN u}
2618         ==> s SUBSET t`,
2619   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_SUMS_LCANCEL THEN
2620   EXISTS_TAC `u:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
2621   ONCE_REWRITE_TAC[SUMS_SYM] THEN ASM_REWRITE_TAC[]);;
2622
2623 let EQ_SUMS_LCANCEL = prove
2624  (`!s t u.
2625         ~(s = {}) /\ bounded s /\
2626         closed t /\ convex t /\ closed u /\ convex u /\
2627         {x + y | x IN s /\ y IN t} = {x + z | x IN s /\ z IN u}
2628         ==> t = u`,
2629   REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; EMPTY_SUBSET] THEN
2630   REWRITE_TAC[SUBSET_EMPTY] THEN MESON_TAC[SUBSET_SUMS_LCANCEL]);;
2631
2632 let EQ_SUMS_RCANCEL = prove
2633  (`!s t u.
2634         closed s /\ convex s /\ closed t /\ convex t /\
2635         bounded u /\ ~(u = {}) /\
2636         {x + z | x IN s /\ z IN u} = {y + z | y IN t /\ z IN u}
2637         ==> s = t`,
2638   REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; EMPTY_SUBSET] THEN
2639   REWRITE_TAC[SUBSET_EMPTY] THEN MESON_TAC[SUBSET_SUMS_RCANCEL]);;
2640
2641 (* ------------------------------------------------------------------------- *)
2642 (* Convex hull.                                                              *)
2643 (* ------------------------------------------------------------------------- *)
2644
2645 let CONVEX_CONVEX_HULL = prove
2646  (`!s. convex(convex hull s)`,
2647   SIMP_TAC[P_HULL; CONVEX_INTERS]);;
2648
2649 let CONVEX_HULL_EQ = prove
2650  (`!s. (convex hull s = s) <=> convex s`,
2651   SIMP_TAC[HULL_EQ; CONVEX_INTERS]);;
2652
2653 let CONVEX_HULLS_EQ = prove
2654  (`!s t. s SUBSET convex hull t /\ t SUBSET convex hull s
2655          ==> convex hull s = convex hull t`,
2656   REPEAT STRIP_TAC THEN MATCH_MP_TAC HULLS_EQ THEN
2657   ASM_SIMP_TAC[CONVEX_INTERS]);;
2658
2659 let IS_CONVEX_HULL = prove
2660  (`!s. convex s <=> ?t. s = convex hull t`,
2661   GEN_TAC THEN MATCH_MP_TAC IS_HULL THEN SIMP_TAC[CONVEX_INTERS]);;
2662
2663 let MIDPOINTS_IN_CONVEX_HULL = prove 
2664  (`!x:real^N s. x IN convex hull s /\ y IN convex hull s
2665          ==> midpoint(x,y) IN convex hull s`,
2666   MESON_TAC[MIDPOINT_IN_CONVEX; CONVEX_CONVEX_HULL]);;
2667
2668 let CONVEX_HULL_UNIV = prove
2669  (`convex hull (:real^N) = (:real^N)`,
2670   REWRITE_TAC[CONVEX_HULL_EQ; CONVEX_UNIV]);;
2671
2672 let BOUNDED_CONVEX_HULL = prove
2673  (`!s:real^N->bool. bounded s ==> bounded(convex hull s)`,
2674   GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [bounded] THEN
2675   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
2676   MATCH_MP_TAC BOUNDED_SUBSET THEN EXISTS_TAC `cball(vec 0:real^N,B)` THEN
2677   SIMP_TAC[BOUNDED_CBALL; SUBSET_HULL; CONVEX_CBALL] THEN
2678   ASM_REWRITE_TAC[IN_CBALL; SUBSET; dist; VECTOR_SUB_LZERO; NORM_NEG]);;
2679
2680 let BOUNDED_CONVEX_HULL_EQ = prove
2681  (`!s. bounded(convex hull s) <=> bounded s`,
2682   MESON_TAC[BOUNDED_CONVEX_HULL; HULL_SUBSET; BOUNDED_SUBSET]);;
2683
2684 let FINITE_IMP_BOUNDED_CONVEX_HULL = prove
2685  (`!s. FINITE s ==> bounded(convex hull s)`,
2686   SIMP_TAC[BOUNDED_CONVEX_HULL; FINITE_IMP_BOUNDED]);;
2687
2688 (* ------------------------------------------------------------------------- *)
2689 (* Stepping theorems for convex hulls of finite sets.                        *)
2690 (* ------------------------------------------------------------------------- *)
2691
2692 let CONVEX_HULL_EMPTY = prove
2693  (`convex hull {} = {}`,
2694   MATCH_MP_TAC HULL_UNIQUE THEN
2695   REWRITE_TAC[SUBSET_REFL; CONVEX_EMPTY; EMPTY_SUBSET]);;
2696
2697 let CONVEX_HULL_EQ_EMPTY = prove
2698  (`!s. (convex hull s = {}) <=> (s = {})`,
2699   GEN_TAC THEN EQ_TAC THEN
2700   MESON_TAC[SUBSET_EMPTY; HULL_SUBSET; CONVEX_HULL_EMPTY]);;
2701
2702 let CONVEX_HULL_SING = prove
2703  (`!a. convex hull {a} = {a}`,
2704   REWRITE_TAC[CONVEX_HULL_EQ; CONVEX_SING]);;
2705
2706 let CONVEX_HULL_EQ_SING = prove
2707  (`!s a:real^N. convex hull s = {a} <=> s = {a}`,
2708   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
2709   ASM_REWRITE_TAC[CONVEX_HULL_EMPTY] THEN
2710   EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[CONVEX_HULL_SING] THEN
2711   MATCH_MP_TAC(SET_RULE `~(s = {}) /\ s SUBSET {a} ==> s = {a}`) THEN
2712   ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
2713   REWRITE_TAC[HULL_SUBSET]);;
2714
2715 let CONVEX_HULL_INSERT = prove
2716  (`!s a. ~(s = {})
2717          ==> (convex hull (a INSERT s) =
2718                 {x:real^N | ?u v b. &0 <= u /\ &0 <= v /\ (u + v = &1) /\
2719                                     b IN (convex hull s) /\
2720                                     (x = u % a + v % b)})`,
2721   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
2722    [MATCH_MP_TAC HULL_MINIMAL THEN CONJ_TAC THENL
2723      [REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_INSERT] THEN
2724       X_GEN_TAC `x:real^N` THEN STRIP_TAC THENL
2725        [MAP_EVERY EXISTS_TAC [`&1`; `&0`];
2726         MAP_EVERY EXISTS_TAC [`&0`; `&1`]] THEN
2727       ASM_REWRITE_TAC[VECTOR_MUL_LID; VECTOR_MUL_LZERO] THEN
2728       ASM_REWRITE_TAC[VECTOR_ADD_LID; VECTOR_ADD_RID] THEN
2729       CONV_TAC REAL_RAT_REDUCE_CONV THEN
2730       ASM_MESON_TAC[MEMBER_NOT_EMPTY; HULL_SUBSET; SUBSET];
2731       ALL_TAC];
2732     REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
2733     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2734     MATCH_MP_TAC(REWRITE_RULE[convex] CONVEX_CONVEX_HULL) THEN
2735     ASM_REWRITE_TAC[] THEN
2736     ASM_MESON_TAC[HULL_SUBSET; SUBSET; IN_INSERT; HULL_MONO]] THEN
2737   REWRITE_TAC[convex; IN_ELIM_THM] THEN
2738   REWRITE_TAC[LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
2739   REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
2740   MAP_EVERY X_GEN_TAC
2741    [`x:real^N`; `y:real^N`; `u:real`; `v:real`; `u1:real`; `v1:real`;
2742     `b1:real^N`; `u2:real`; `v2:real`; `b2:real^N`] THEN
2743   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2744   MAP_EVERY EXISTS_TAC [`u * u1 + v * u2`; `u * v1 + v * v2`] THEN
2745   REWRITE_TAC[VECTOR_ARITH
2746    `u % (u1 % a + v1 % b1) + v % (u2 % a + v2 % b2) =
2747     (u * u1 + v * u2) % a + (u * v1) % b1 + (v * v2) % b2`] THEN
2748   ASM_SIMP_TAC[REAL_LE_ADD; REAL_LE_MUL] THEN
2749   ASM_REWRITE_TAC[REAL_MUL_RID; REAL_ARITH
2750    `(u * u1 + v * u2) + (u * v1 + v * v2) =
2751     u * (u1 + v1) + v * (u2 + v2)`] THEN
2752   ASM_CASES_TAC `u * v1 + v * v2 = &0` THENL
2753    [FIRST_X_ASSUM(MP_TAC o MATCH_MP (REAL_ARITH
2754      `(a + b = &0) ==> &0 <= a /\ &0 <= b ==> (a = &0) /\ (b = &0)`)) THEN
2755     ASM_SIMP_TAC[REAL_LE_MUL; REAL_ADD_LID; VECTOR_MUL_LZERO;
2756                  VECTOR_ADD_RID] THEN
2757     ASM_MESON_TAC[];
2758     ALL_TAC] THEN
2759   EXISTS_TAC `(u * v1) / (u * v1 + v * v2) % b1 +
2760               (v * v2) / (u * v1 + v * v2) % b2 :real^N` THEN
2761   ASM_SIMP_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC; REAL_DIV_LMUL] THEN
2762   MATCH_MP_TAC(REWRITE_RULE[convex] CONVEX_CONVEX_HULL) THEN
2763   ASM_SIMP_TAC[REAL_LE_DIV; REAL_LE_MUL; REAL_LE_ADD] THEN
2764   ASM_SIMP_TAC[real_div; GSYM REAL_ADD_RDISTRIB; REAL_MUL_RINV]);;
2765
2766 let CONVEX_HULL_INSERT_ALT = prove
2767  (`!s a:real^N.
2768       convex hull (a INSERT s) =
2769       if s = {} then {a}
2770       else {(&1 - u) % a + u % x | &0 <= u /\ u <= &1 /\ x IN convex hull s}`,
2771   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
2772   ASM_REWRITE_TAC[CONVEX_HULL_SING] THEN
2773   ASM_SIMP_TAC[CONVEX_HULL_INSERT] THEN
2774   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c /\ d <=> b /\ c /\ a /\ d`] THEN
2775   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
2776   REWRITE_TAC[RIGHT_EXISTS_AND_THM; UNWIND_THM2; REAL_SUB_LE;
2777               REAL_ARITH `u + v = &1 <=> u = &1 - v`] THEN
2778   SET_TAC[]);;
2779
2780 (* ------------------------------------------------------------------------- *)
2781 (* Explicit expression for convex hull.                                      *)
2782 (* ------------------------------------------------------------------------- *)
2783
2784 let CONVEX_HULL_INDEXED = prove
2785  (`!s. convex hull s =
2786         {y:real^N | ?k u x. (!i. 1 <= i /\ i <= k ==> &0 <= u i /\ x i IN s) /\
2787                             (sum (1..k) u = &1) /\
2788                             (vsum (1..k) (\i. u i % x i) = y)}`,
2789   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN REPEAT CONJ_TAC THENL
2790    [REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
2791     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
2792     MAP_EVERY EXISTS_TAC [`1`; `\i:num. &1`; `\i:num. x:real^N`] THEN
2793     ASM_SIMP_TAC[FINITE_RULES; IN_SING; SUM_SING; VECTOR_MUL_LID; VSUM_SING;
2794                  REAL_POS; NUMSEG_SING];
2795     ALL_TAC;
2796     REWRITE_TAC[CONVEX_INDEXED; SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
2797     MESON_TAC[]] THEN
2798   REWRITE_TAC[convex; IN_ELIM_THM] THEN
2799   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
2800   REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
2801   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC
2802    [`k1:num`; `u1:num->real`; `x1:num->real^N`;
2803     `k2:num`; `u2:num->real`; `x2:num->real^N`] THEN
2804   STRIP_TAC THEN EXISTS_TAC `k1 + k2:num` THEN
2805   EXISTS_TAC `\i:num. if i <= k1 then u * u1(i) else v * u2(i - k1):real` THEN
2806   EXISTS_TAC `\i:num. if i <= k1 then x1(i) else x2(i - k1):real^N` THEN
2807   ASM_SIMP_TAC[NUMSEG_ADD_SPLIT; ARITH_RULE `1 <= x + 1 /\ x < x + 1`;
2808    IN_NUMSEG; SUM_UNION; VSUM_UNION; FINITE_NUMSEG; DISJOINT_NUMSEG;
2809    ARITH_RULE `k1 + 1 <= i ==> ~(i <= k1)`] THEN
2810   REWRITE_TAC[ONCE_REWRITE_RULE[ADD_SYM] NUMSEG_OFFSET_IMAGE] THEN
2811   ASM_SIMP_TAC[SUM_IMAGE; VSUM_IMAGE; EQ_ADD_LCANCEL; FINITE_NUMSEG] THEN
2812   ASM_SIMP_TAC[o_DEF; ADD_SUB2; SUM_LMUL; VSUM_LMUL; GSYM VECTOR_MUL_ASSOC;
2813                FINITE_NUMSEG; REAL_MUL_RID] THEN
2814   ASM_MESON_TAC[REAL_LE_MUL; ARITH_RULE
2815     `i <= k1 + k2 /\ ~(i <= k1) ==> 1 <= i - k1 /\ i - k1 <= k2`]);;
2816
2817 (* ------------------------------------------------------------------------- *)
2818 (* Another formulation from Lars Schewe.                                     *)
2819 (* ------------------------------------------------------------------------- *)
2820
2821 let CONVEX_HULL_EXPLICIT = prove
2822   (`!p. convex hull p =
2823         {y:real^N | ?s u. FINITE s /\ s SUBSET p /\
2824              (!x. x IN s ==> &0 <= u x) /\
2825              sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
2826    REWRITE_TAC[CONVEX_HULL_INDEXED;EXTENSION;IN_ELIM_THM] THEN
2827    REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL
2828    [MAP_EVERY  EXISTS_TAC [`IMAGE (x':num->real^N) (1..k)`;
2829                            `\v:real^N.sum {i | i IN (1..k) /\ x' i = v} u`]
2830     THEN ASM_SIMP_TAC[FINITE_IMAGE;FINITE_NUMSEG;IN_IMAGE] THEN
2831     REPEAT STRIP_TAC THENL
2832     [REWRITE_TAC[IMAGE;SUBSET;IN_ELIM_THM;IN_NUMSEG] THEN
2833        ASM_MESON_TAC[];
2834      MATCH_MP_TAC SUM_POS_LE THEN
2835        ASM_SIMP_TAC[FINITE_NUMSEG;FINITE_RESTRICT;IN_ELIM_THM;IN_NUMSEG];
2836      ASM_SIMP_TAC[GSYM SUM_IMAGE_GEN;FINITE_IMAGE;FINITE_NUMSEG];
2837      FIRST_X_ASSUM (fun th -> REWRITE_TAC[GSYM th]) THEN
2838      ASM_SIMP_TAC[GSYM VSUM_IMAGE_GEN;FINITE_IMAGE;
2839                   FINITE_NUMSEG;VSUM_VMUL;FINITE_RESTRICT] THEN
2840        MP_TAC (ISPECL [`x':num->real^N`;`\i:num.u i % (x' i):real^N`;`(1..k)`]
2841                       (GSYM VSUM_IMAGE_GEN)) THEN
2842        ASM_SIMP_TAC[FINITE_NUMSEG]];ALL_TAC] THEN
2843    STRIP_ASSUME_TAC (ASM_REWRITE_RULE [ASSUME `FINITE (s:real^N->bool)`]
2844     (ISPEC `s:real^N->bool` FINITE_INDEX_NUMSEG)) THEN
2845    MAP_EVERY EXISTS_TAC [`CARD (s:real^N->bool)`;
2846                          `(u:real^N->real) o (f:num->real^N)`;
2847                          `(f:num->real^N)`] THEN
2848    REPEAT STRIP_TAC THENL
2849    [REWRITE_TAC[o_DEF] THEN FIRST_ASSUM MATCH_MP_TAC THEN
2850       FIRST_ASSUM SUBST1_TAC THEN
2851       REWRITE_TAC[IN_IMAGE;IN_NUMSEG] THEN
2852       ASM_MESON_TAC[];
2853     MATCH_MP_TAC (REWRITE_RULE [SUBSET]
2854       (ASSUME `(s:real^N->bool) SUBSET p`)) THEN
2855       FIRST_ASSUM SUBST1_TAC THEN
2856       REWRITE_TAC[IN_IMAGE;IN_NUMSEG] THEN
2857       ASM_MESON_TAC[];
2858     MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `sum (s:real^N->bool) u` THEN
2859       CONJ_TAC THENL [ALL_TAC;ASM_REWRITE_TAC[]] THEN
2860       GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV)
2861        [ASSUME `(s:real^N->bool) = IMAGE f (1..CARD s)`] THEN
2862       MATCH_MP_TAC (GSYM SUM_IMAGE) THEN
2863       ASM_MESON_TAC[];
2864     REWRITE_TAC[MESON [o_THM;FUN_EQ_THM]
2865      `(\i:num. (u o f) i % f i) = (\v:real^N. u v % v) o f`] THEN
2866       MATCH_MP_TAC EQ_TRANS THEN
2867       EXISTS_TAC `vsum (s:real^N->bool) (\v. u v % v)` THEN
2868       CONJ_TAC THENL [ALL_TAC;ASM_REWRITE_TAC[]] THEN
2869       GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV)
2870        [ASSUME `(s:real^N->bool) = IMAGE f (1..CARD s)`] THEN
2871       MATCH_MP_TAC (GSYM VSUM_IMAGE) THEN
2872       ASM SET_TAC[FINITE_NUMSEG]]);;
2873
2874 let CONVEX_HULL_FINITE = prove
2875  (`!s:real^N->bool.
2876         convex hull s =
2877           {y | ?u. (!x. x IN s ==> &0 <= u x) /\
2878                    sum s u = &1 /\
2879                    vsum s (\x. u x % x) = y}`,
2880   GEN_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
2881   REWRITE_TAC[CONVEX_HULL_EXPLICIT; IN_ELIM_THM] THEN
2882   X_GEN_TAC `x:real^N` THEN EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THENL
2883    [MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `f:real^N->real`] THEN
2884     STRIP_TAC THEN
2885     EXISTS_TAC `\x:real^N. if x IN t then f x else &0` THEN
2886     REWRITE_TAC[COND_RAND; COND_RATOR; VECTOR_MUL_LZERO] THEN
2887     REWRITE_TAC[GSYM SUM_RESTRICT_SET; GSYM VSUM_RESTRICT_SET] THEN
2888     ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
2889     REWRITE_TAC[REAL_LE_REFL; COND_ID];
2890     X_GEN_TAC `f:real^N->real` THEN
2891     ASM_CASES_TAC `s:real^N->bool = {}` THEN
2892     ASM_REWRITE_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH] THEN STRIP_TAC THEN
2893     EXISTS_TAC `support (+) (f:real^N->real) s` THEN
2894     EXISTS_TAC `f:real^N->real` THEN
2895     MP_TAC(ASSUME `sum s (f:real^N->real) = &1`) THEN
2896     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [sum] THEN
2897     REWRITE_TAC[iterate] THEN COND_CASES_TAC THEN
2898     ASM_REWRITE_TAC[NEUTRAL_REAL_ADD; REAL_OF_NUM_EQ; ARITH] THEN
2899     DISCH_THEN(K ALL_TAC) THEN
2900     UNDISCH_TAC `sum s (f:real^N->real) = &1` THEN
2901     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM SUM_SUPPORT] THEN
2902     ASM_CASES_TAC `support (+) (f:real^N->real) s = {}` THEN
2903     ASM_SIMP_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH] THEN
2904     DISCH_TAC THEN REWRITE_TAC[SUPPORT_SUBSET] THEN CONJ_TAC THENL
2905      [ASM_SIMP_TAC[support; IN_ELIM_THM]; ALL_TAC] THEN
2906     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN
2907     CONV_TAC SYM_CONV THEN MATCH_MP_TAC VSUM_SUPERSET THEN
2908     REWRITE_TAC[SUPPORT_SUBSET] THEN
2909     REWRITE_TAC[support; IN_ELIM_THM; NEUTRAL_REAL_ADD] THEN
2910     MESON_TAC[VECTOR_MUL_LZERO]]);;
2911
2912 let CONVEX_HULL_UNION_EXPLICIT = prove
2913  (`!s t:real^N->bool.
2914         convex s /\ convex t
2915         ==> convex hull (s UNION t) =
2916              s UNION t UNION
2917              {(&1 - u) % x + u % y | x IN s /\ y IN t /\ &0 <= u /\ u <= &1}`,
2918   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
2919    [REWRITE_TAC[CONVEX_HULL_EXPLICIT] THEN GEN_REWRITE_TAC I [SUBSET] THEN
2920     REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
2921     MAP_EVERY X_GEN_TAC [`y:real^N`; `u:real^N->bool`; `f:real^N->real`] THEN
2922     REPLICATE_TAC 3 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
2923     SUBST1_TAC(SET_RULE `u:real^N->bool = (u INTER s) UNION (u DIFF s)`) THEN
2924     ASM_SIMP_TAC[SUM_UNION; VSUM_UNION; FINITE_INTER; FINITE_DIFF;
2925                  SET_RULE `DISJOINT (u INTER s) (u DIFF s)`] THEN
2926     ASM_CASES_TAC `sum (u INTER s) (f:real^N->real) = &0` THENL
2927      [SUBGOAL_THEN `!x. x IN (u INTER s) ==> (f:real^N->real) x = &0`
2928       ASSUME_TAC THENL
2929        [ASM_MESON_TAC[SUM_POS_EQ_0; FINITE_INTER; IN_INTER];
2930         ASM_SIMP_TAC[VECTOR_MUL_LZERO; VSUM_0] THEN
2931         REWRITE_TAC[VECTOR_ADD_LID; REAL_ADD_LID] THEN
2932         DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (SUBST1_TAC o SYM)) THEN
2933         REWRITE_TAC[IN_UNION] THEN DISJ2_TAC THEN DISJ1_TAC THEN
2934         FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
2935         ASM_SIMP_TAC[FINITE_DIFF; IN_DIFF] THEN ASM SET_TAC[]];
2936       ALL_TAC] THEN
2937     ASM_CASES_TAC `sum (u DIFF s) (f:real^N->real) = &0` THENL
2938      [SUBGOAL_THEN `!x. x IN (u DIFF s) ==> (f:real^N->real) x = &0`
2939       ASSUME_TAC THENL
2940        [ASM_MESON_TAC[SUM_POS_EQ_0; FINITE_DIFF; IN_DIFF];
2941         ASM_SIMP_TAC[VECTOR_MUL_LZERO; VSUM_0] THEN
2942         REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN
2943         DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (SUBST1_TAC o SYM)) THEN
2944         REWRITE_TAC[IN_UNION] THEN DISJ1_TAC THEN
2945         FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
2946         ASM_SIMP_TAC[FINITE_INTER; IN_INTER] THEN ASM SET_TAC[]];
2947       ALL_TAC] THEN
2948     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (SUBST1_TAC o SYM)) THEN
2949     REWRITE_TAC[IN_UNION; IN_ELIM_THM] THEN DISJ2_TAC THEN DISJ2_TAC THEN
2950     MAP_EVERY EXISTS_TAC
2951      [`vsum(u INTER s) (\v:real^N. (f v / sum(u INTER s) f) % v)`;
2952       `sum(u DIFF s) (f:real^N->real)`;
2953       `vsum(u DIFF s) (\v:real^N. (f v / sum(u DIFF s) f) % v)`] THEN
2954     REPEAT CONJ_TAC THENL
2955      [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
2956       ASM_SIMP_TAC[INTER_SUBSET; FINITE_INTER; SUM_POS_LE; REAL_LE_DIV;
2957                    IN_INTER; real_div; SUM_RMUL; REAL_MUL_RINV];
2958       FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
2959       ASM_SIMP_TAC[SUBSET_DIFF; FINITE_DIFF; SUM_POS_LE; REAL_LE_DIV;
2960                    IN_DIFF; real_div; SUM_RMUL; REAL_MUL_RINV] THEN
2961       ASM SET_TAC[];
2962       ASM_SIMP_TAC[SUM_POS_LE; IN_DIFF; FINITE_DIFF];
2963       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
2964        `a + b = &1 ==> &0 <= a ==> b <= &1`)) THEN
2965       ASM_SIMP_TAC[SUM_POS_LE; IN_INTER; FINITE_INTER];
2966       ASM_SIMP_TAC[GSYM VSUM_LMUL; FINITE_INTER; FINITE_DIFF] THEN
2967       SIMP_TAC[VECTOR_MUL_ASSOC; REAL_ARITH `a * b / c:real = a / c * b`] THEN
2968       FIRST_ASSUM(SUBST1_TAC o MATCH_MP (REAL_ARITH
2969        `a + b = &1 ==> &1 - b = a`)) THEN
2970       ASM_SIMP_TAC[REAL_DIV_REFL; REAL_MUL_LID]];
2971     REWRITE_TAC[GSYM UNION_ASSOC] THEN ONCE_REWRITE_TAC[UNION_SUBSET] THEN
2972     REWRITE_TAC[HULL_SUBSET] THEN REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
2973     MAP_EVERY X_GEN_TAC [`x:real^N`; `u:real`; `y:real^N`] THEN STRIP_TAC THEN
2974     MATCH_MP_TAC(REWRITE_RULE[CONVEX_ALT] CONVEX_CONVEX_HULL) THEN
2975     ASM_SIMP_TAC[HULL_INC; IN_UNION]]);;
2976
2977 let CONVEX_HULL_UNION_NONEMPTY_EXPLICIT = prove
2978  (`!s t:real^N->bool.
2979         convex s /\ ~(s = {}) /\ convex t /\ ~(t = {})
2980         ==> convex hull (s UNION t) =
2981              {(&1 - u) % x + u % y | x IN s /\ y IN t /\ &0 <= u /\ u <= &1}`,
2982   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CONVEX_HULL_UNION_EXPLICIT] THEN
2983   SIMP_TAC[SET_RULE `s UNION t UNION u = u <=> s SUBSET u /\ t SUBSET u`] THEN
2984   CONJ_TAC THEN REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `z:real^N` THEN
2985   DISCH_TAC THENL
2986    [MAP_EVERY EXISTS_TAC [`z:real^N`; `&0`] THEN
2987     REWRITE_TAC[REAL_SUB_RZERO; VECTOR_MUL_LID; REAL_POS; VECTOR_MUL_LZERO;
2988                 VECTOR_ADD_RID] THEN
2989     ASM SET_TAC[];
2990     SUBGOAL_THEN `?a:real^N. a IN s` MP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2991     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN DISCH_TAC THEN
2992     MAP_EVERY EXISTS_TAC [`&1`; `z:real^N`] THEN
2993     ASM_REWRITE_TAC[REAL_POS; REAL_LE_REFL] THEN VECTOR_ARITH_TAC]);;
2994
2995 let CONVEX_HULL_UNION_UNIONS = prove
2996  (`!f s:real^N->bool.
2997         convex(UNIONS f) /\ ~(f = {})
2998         ==> convex hull (s UNION UNIONS f) =
2999             UNIONS {convex hull (s UNION t) | t IN f}`,
3000   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3001    [ALL_TAC;
3002     REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC] THEN
3003     REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]] THEN
3004   ASM_CASES_TAC `s:real^N->bool = {}` THENL
3005    [ASM_SIMP_TAC[UNION_EMPTY; HULL_P; UNIONS_SUBSET] THEN
3006     X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
3007     MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `convex hull u:real^N->bool` THEN
3008     REWRITE_TAC[HULL_SUBSET] THEN ASM SET_TAC[];
3009     ALL_TAC] THEN
3010   ASM_CASES_TAC `UNIONS f :real^N->bool = {}` THENL
3011    [ASM_REWRITE_TAC[UNION_EMPTY] THEN
3012     SUBGOAL_THEN `?u:real^N->bool. u IN f` CHOOSE_TAC THENL
3013      [ASM_REWRITE_TAC[MEMBER_NOT_EMPTY]; ALL_TAC] THEN
3014     MATCH_MP_TAC SUBSET_TRANS THEN
3015     EXISTS_TAC `convex hull (s UNION u:real^N->bool)` THEN
3016     ASM_SIMP_TAC[HULL_MONO; SUBSET_UNION] THEN ASM SET_TAC[];
3017     ALL_TAC] THEN
3018   GEN_REWRITE_TAC LAND_CONV [HULL_UNION_LEFT] THEN
3019   ASM_SIMP_TAC[CONVEX_HULL_UNION_NONEMPTY_EXPLICIT; CONVEX_HULL_EQ_EMPTY;
3020                CONVEX_CONVEX_HULL] THEN
3021   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3022   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_UNIONS] THEN
3023   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
3024   MAP_EVERY X_GEN_TAC [`a:real`; `u:real^N->bool`] THEN DISCH_TAC THEN
3025   X_GEN_TAC `y:real^N` THEN REPEAT STRIP_TAC THEN
3026   REWRITE_TAC[IN_UNIONS; EXISTS_IN_GSPEC] THEN
3027   EXISTS_TAC `u:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
3028   MATCH_MP_TAC(REWRITE_RULE[CONVEX_ALT] CONVEX_CONVEX_HULL) THEN
3029   ASM_MESON_TAC[HULL_MONO; IN_UNION; SUBSET; HULL_INC]);;
3030
3031 (* ------------------------------------------------------------------------- *)
3032 (* A stepping theorem for that expansion.                                    *)
3033 (* ------------------------------------------------------------------------- *)
3034
3035 let CONVEX_HULL_FINITE_STEP = prove
3036  (`((?u. (!x. x IN {} ==> &0 <= u x) /\
3037          sum {} u = w /\
3038          vsum {} (\x. u(x) % x) = y) <=> w = &0 /\ y = vec 0) /\
3039    (FINITE(s:real^N->bool)
3040     ==> ((?u. (!x. x IN (a INSERT s) ==> &0 <= u x) /\
3041               sum (a INSERT s) u = w /\
3042               vsum (a INSERT s) (\x. u(x) % x) = y) <=>
3043          ?v. &0 <= v /\
3044              ?u. (!x. x IN s ==> &0 <= u x) /\
3045               sum s u = w - v /\
3046               vsum s (\x. u(x) % x) = y - v % a))`,
3047   MP_TAC(ISPEC `\x:real^N y:real. &0 <= y` AFFINE_HULL_FINITE_STEP_GEN) THEN
3048   SIMP_TAC[REAL_ARITH `&0 <= x / &2 <=> &0 <= x`; REAL_LE_ADD] THEN
3049   REWRITE_TAC[RIGHT_AND_EXISTS_THM]);;
3050
3051 (* ------------------------------------------------------------------------- *)
3052 (* Hence some special cases.                                                 *)
3053 (* ------------------------------------------------------------------------- *)
3054
3055 let CONVEX_HULL_2 = prove
3056  (`!a b. convex hull {a,b} =
3057          {u % a + v % b | &0 <= u /\ &0 <= v /\ u + v = &1}`,
3058   SIMP_TAC[CONVEX_HULL_FINITE; FINITE_INSERT; FINITE_RULES] THEN
3059   SIMP_TAC[CONVEX_HULL_FINITE_STEP; FINITE_INSERT; FINITE_RULES] THEN
3060   REWRITE_TAC[REAL_ARITH `x - y = z:real <=> x = y + z`;
3061               VECTOR_ARITH `x - y = z:real^N <=> x = y + z`] THEN
3062   REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN SET_TAC[]);;
3063
3064 let CONVEX_HULL_2_ALT = prove
3065  (`!a b. convex hull {a,b} = {a + u % (b - a) | &0 <= u /\ u <= &1}`,
3066   ONCE_REWRITE_TAC[SET_RULE `{a,b} = {b,a}`] THEN
3067   REWRITE_TAC[CONVEX_HULL_2; EXTENSION; IN_ELIM_THM] THEN
3068   REWRITE_TAC[REAL_ADD_ASSOC; CONJ_ASSOC] THEN
3069   REWRITE_TAC[TAUT `(a /\ x + y = &1) /\ b <=> x + y = &1 /\ a /\ b`] THEN
3070   REWRITE_TAC[REAL_ARITH `x + y = &1 <=> y = &1 - x`; UNWIND_THM2] THEN
3071   REPEAT GEN_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
3072   BINOP_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]);;
3073
3074 let CONVEX_HULL_3 = prove
3075  (`convex hull {a,b,c} =
3076     { u % a + v % b + w % c |
3077       &0 <= u /\ &0 <= v /\ &0 <= w /\ u + v + w = &1}`,
3078   SIMP_TAC[CONVEX_HULL_FINITE; FINITE_INSERT; FINITE_RULES] THEN
3079   SIMP_TAC[CONVEX_HULL_FINITE_STEP; FINITE_INSERT; FINITE_RULES] THEN
3080   REWRITE_TAC[REAL_ARITH `x - y = z:real <=> x = y + z`;
3081               VECTOR_ARITH `x - y = z:real^N <=> x = y + z`] THEN
3082   REWRITE_TAC[VECTOR_ADD_RID; REAL_ADD_RID] THEN SET_TAC[]);;
3083
3084 let CONVEX_HULL_3_ALT = prove
3085  (`!a b c. convex hull {a,b,c} =
3086                 {a + u % (b - a) + v % (c - a) |
3087                    &0 <= u /\ &0 <= v /\ u + v <= &1}`,
3088   ONCE_REWRITE_TAC[SET_RULE `{a,b,c} = {b,c,a}`] THEN
3089   REWRITE_TAC[CONVEX_HULL_3; EXTENSION; IN_ELIM_THM] THEN
3090   REWRITE_TAC[REAL_ADD_ASSOC; CONJ_ASSOC] THEN
3091   REWRITE_TAC[TAUT `(a /\ x + y = &1) /\ b <=> x + y = &1 /\ a /\ b`] THEN
3092   REWRITE_TAC[REAL_ARITH `x + y = &1 <=> y = &1 - x`; UNWIND_THM2] THEN
3093   REPEAT GEN_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
3094   BINOP_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]);;
3095
3096 let CONVEX_HULL_SUMS = prove
3097  (`!s t:real^N->bool.
3098         convex hull {x + y | x IN s /\ y IN t} =
3099         {x + y | x IN convex hull s /\ y IN convex hull t}`,
3100   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3101    [MATCH_MP_TAC HULL_MINIMAL THEN
3102     SIMP_TAC[CONVEX_SUMS; CONVEX_CONVEX_HULL] THEN
3103     REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3104     REWRITE_TAC[IN_ELIM_THM] THEN MESON_TAC[HULL_INC];
3105     REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3106     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
3107     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [CONVEX_HULL_INDEXED] THEN
3108     REWRITE_TAC[IN_ELIM_THM; LEFT_AND_EXISTS_THM] THEN
3109     REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
3110     MAP_EVERY X_GEN_TAC
3111      [`k1:num`; `u1:num->real`; `x1:num->real^N`;
3112       `k2:num`; `u2:num->real`; `x2:num->real^N`] THEN
3113     STRIP_TAC THEN
3114     SUBGOAL_THEN
3115      `x + y:real^N =
3116       vsum(1..k1) (\i. vsum(1..k2) (\j. u1 i % u2 j % (x1 i + x2 j)))`
3117     SUBST1_TAC THENL
3118      [REWRITE_TAC[VECTOR_ADD_LDISTRIB; VSUM_ADD_NUMSEG] THEN
3119       ASM_SIMP_TAC[VSUM_LMUL; VSUM_RMUL; VECTOR_MUL_LID];
3120       REWRITE_TAC[VSUM_LMUL] THEN MATCH_MP_TAC CONVEX_VSUM THEN
3121       ASM_SIMP_TAC[FINITE_NUMSEG; CONVEX_CONVEX_HULL; IN_NUMSEG] THEN
3122       REPEAT STRIP_TAC THEN MATCH_MP_TAC CONVEX_VSUM THEN
3123       ASM_SIMP_TAC[FINITE_NUMSEG; CONVEX_CONVEX_HULL; IN_NUMSEG] THEN
3124       REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_INC THEN ASM SET_TAC[]]]);;
3125
3126 let AFFINE_HULL_PCROSS,CONVEX_HULL_PCROSS = (CONJ_PAIR o prove)
3127  (`(!s:real^M->bool t:real^N->bool.
3128         affine hull (s PCROSS t) =
3129         (affine hull s) PCROSS (affine hull t)) /\
3130    (!s:real^M->bool t:real^N->bool.
3131         convex hull (s PCROSS t) =
3132         (convex hull s) PCROSS (convex hull t))`,
3133   let lemma1 = prove
3134    (`!u v x y:real^M z:real^N.
3135        u + v = &1
3136           ==> pastecart z (u % x + v % y) =
3137               u % pastecart z x + v % pastecart z y /\
3138               pastecart (u % x + v % y) z =
3139               u % pastecart x z + v % pastecart y z`,
3140     REWRITE_TAC[PASTECART_ADD; GSYM PASTECART_CMUL] THEN
3141     SIMP_TAC[GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID])
3142   and lemma2 = prove
3143    (`INTERS {{x | pastecart x y IN u} | y IN t} =
3144      {x | !y. y IN t ==> pastecart x y IN u}`,
3145     REWRITE_TAC[INTERS_GSPEC; EXTENSION; IN_ELIM_THM] THEN SET_TAC[]) in
3146   CONJ_TAC THENL
3147    [REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3148      [MATCH_MP_TAC HULL_MINIMAL THEN
3149       SIMP_TAC[AFFINE_PCROSS; AFFINE_AFFINE_HULL; HULL_SUBSET; PCROSS_MONO];
3150       REWRITE_TAC[SUBSET; FORALL_IN_PCROSS] THEN
3151       REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
3152       MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
3153        [X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
3154         MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
3155          [X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
3156           SUBGOAL_THEN `pastecart (x:real^M) (y:real^N) IN s PCROSS t` MP_TAC
3157           THENL [ASM_REWRITE_TAC[PASTECART_IN_PCROSS]; ALL_TAC] THEN
3158           REWRITE_TAC[HULL_INC];
3159           ALL_TAC];
3160         REWRITE_TAC[GSYM lemma2] THEN MATCH_MP_TAC AFFINE_INTERS THEN
3161         REWRITE_TAC[FORALL_IN_GSPEC]] THEN
3162       SIMP_TAC[affine; IN_ELIM_THM; lemma1;
3163                ONCE_REWRITE_RULE[affine] AFFINE_AFFINE_HULL]];
3164     REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3165      [MATCH_MP_TAC HULL_MINIMAL THEN
3166       SIMP_TAC[CONVEX_PCROSS; CONVEX_CONVEX_HULL; HULL_SUBSET; PCROSS_MONO];
3167       REWRITE_TAC[SUBSET; FORALL_IN_PCROSS] THEN
3168       REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
3169       MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
3170        [X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
3171         MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
3172          [X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
3173           SUBGOAL_THEN `pastecart (x:real^M) (y:real^N) IN s PCROSS t` MP_TAC
3174           THENL [ASM_REWRITE_TAC[PASTECART_IN_PCROSS]; ALL_TAC] THEN
3175           REWRITE_TAC[HULL_INC];
3176           ALL_TAC];
3177         REWRITE_TAC[GSYM lemma2] THEN MATCH_MP_TAC CONVEX_INTERS THEN
3178         REWRITE_TAC[FORALL_IN_GSPEC]] THEN
3179       SIMP_TAC[convex; IN_ELIM_THM; lemma1;
3180                ONCE_REWRITE_RULE[convex] CONVEX_CONVEX_HULL]]]);;
3181
3182 (* ------------------------------------------------------------------------- *)
3183 (* Relations among closure notions and corresponding hulls.                  *)
3184 (* ------------------------------------------------------------------------- *)
3185
3186 let SUBSPACE_IMP_AFFINE = prove
3187  (`!s. subspace s ==> affine s`,
3188   REWRITE_TAC[subspace; affine] THEN MESON_TAC[]);;
3189
3190 let AFFINE_IMP_CONVEX = prove
3191  (`!s. affine s ==> convex s`,
3192   REWRITE_TAC[affine; convex] THEN MESON_TAC[]);;
3193
3194 let SUBSPACE_IMP_CONVEX = prove
3195  (`!s. subspace s ==> convex s`,
3196   MESON_TAC[SUBSPACE_IMP_AFFINE; AFFINE_IMP_CONVEX]);;
3197
3198 let AFFINE_HULL_SUBSET_SPAN = prove
3199  (`!s. (affine hull s) SUBSET (span s)`,
3200   GEN_TAC THEN REWRITE_TAC[span] THEN MATCH_MP_TAC HULL_ANTIMONO THEN
3201   REWRITE_TAC[SUBSET; IN; SUBSPACE_IMP_AFFINE]);;
3202
3203 let CONVEX_HULL_SUBSET_SPAN = prove
3204  (`!s. (convex hull s) SUBSET (span s)`,
3205   GEN_TAC THEN REWRITE_TAC[span] THEN MATCH_MP_TAC HULL_ANTIMONO THEN
3206   REWRITE_TAC[SUBSET; IN; SUBSPACE_IMP_CONVEX]);;
3207
3208 let CONVEX_HULL_SUBSET_AFFINE_HULL = prove
3209  (`!s. (convex hull s) SUBSET (affine hull s)`,
3210   GEN_TAC THEN REWRITE_TAC[span] THEN MATCH_MP_TAC HULL_ANTIMONO THEN
3211   REWRITE_TAC[SUBSET; IN; AFFINE_IMP_CONVEX]);;
3212
3213 let COLLINEAR_CONVEX_HULL_COLLINEAR = prove
3214  (`!s:real^N->bool. collinear(convex hull s) <=> collinear s`,
3215   MESON_TAC[COLLINEAR_SUBSET; HULL_SUBSET; SUBSET_TRANS;
3216             COLLINEAR_AFFINE_HULL_COLLINEAR; CONVEX_HULL_SUBSET_AFFINE_HULL]);;
3217
3218 let AFFINE_SPAN = prove
3219  (`!s. affine(span s)`,
3220   SIMP_TAC[SUBSPACE_IMP_AFFINE; SUBSPACE_SPAN]);;
3221
3222 let CONVEX_SPAN = prove
3223  (`!s. convex(span s)`,
3224   SIMP_TAC[SUBSPACE_IMP_CONVEX; SUBSPACE_SPAN]);;
3225
3226 let AFFINE_EQ_SUBSPACE = prove
3227  (`!s:real^N->bool. vec 0 IN s ==> (affine s <=> subspace s)`,
3228   REPEAT STRIP_TAC THEN EQ_TAC THEN ASM_SIMP_TAC[subspace; affine] THEN
3229   DISCH_TAC THEN MATCH_MP_TAC(TAUT `b /\ (b ==> a) ==> a /\ b`) THEN
3230   CONJ_TAC THENL
3231    [MAP_EVERY X_GEN_TAC [`c:real`; `x:real^N`] THEN STRIP_TAC THEN
3232     SUBST1_TAC(VECTOR_ARITH `c % x:real^N = c % x + (&1 - c) % vec 0`) THEN
3233     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
3234     DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
3235     STRIP_TAC THEN SUBST1_TAC(VECTOR_ARITH
3236      `x + y:real^N = &2 % (&1 / &2 % x + &1 / &2 % y)`) THEN
3237     FIRST_X_ASSUM MATCH_MP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
3238     ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC]);;
3239
3240 let AFFINE_IMP_SUBSPACE = prove
3241  (`!s. affine s /\ vec 0 IN s ==> subspace s`,
3242   SIMP_TAC[GSYM AFFINE_EQ_SUBSPACE]);;
3243
3244 let AFFINE_HULL_EQ_SPAN = prove
3245  (`!s:real^N->bool. (vec 0) IN affine hull s ==> affine hull s = span s`,
3246   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
3247   REWRITE_TAC[AFFINE_HULL_SUBSET_SPAN] THEN
3248   REWRITE_TAC[SUBSET] THEN MATCH_MP_TAC SPAN_INDUCT THEN
3249   ASM_REWRITE_TAC[SUBSET; subspace; IN_ELIM_THM; HULL_INC] THEN
3250   REPEAT STRIP_TAC THENL
3251    [SUBST1_TAC(VECTOR_ARITH
3252      `x + y:real^N = &2 % (&1 / &2 % x + &1 / &2 % y) + --(&1) % vec 0`) THEN
3253     MATCH_MP_TAC(REWRITE_RULE[affine] AFFINE_AFFINE_HULL) THEN
3254     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN
3255     MATCH_MP_TAC(REWRITE_RULE[affine] AFFINE_AFFINE_HULL) THEN
3256     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[];
3257     SUBST1_TAC(VECTOR_ARITH
3258      `c % x:real^N = c % x + (&1 - c) % vec 0`) THEN
3259     MATCH_MP_TAC(REWRITE_RULE[affine] AFFINE_AFFINE_HULL) THEN
3260     ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC]);;
3261
3262 let CLOSED_AFFINE = prove
3263  (`!s:real^N->bool. affine s ==> closed s`,
3264   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
3265   ASM_REWRITE_TAC[CLOSED_EMPTY] THEN
3266   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3267   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
3268   SUBGOAL_THEN `affine (IMAGE (\x:real^N. --a + x) s)
3269                 ==> closed (IMAGE (\x:real^N. --a + x) s)`
3270   MP_TAC THENL
3271    [DISCH_THEN(fun th -> MATCH_MP_TAC CLOSED_SUBSPACE THEN MP_TAC th) THEN
3272     MATCH_MP_TAC EQ_IMP THEN MATCH_MP_TAC AFFINE_EQ_SUBSPACE THEN
3273     REWRITE_TAC[IN_IMAGE] THEN EXISTS_TAC `a:real^N` THEN
3274     ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC;
3275     REWRITE_TAC[AFFINE_TRANSLATION_EQ; CLOSED_TRANSLATION_EQ]]);;
3276
3277 let CLOSED_AFFINE_HULL = prove
3278  (`!s. closed(affine hull s)`,
3279   SIMP_TAC[CLOSED_AFFINE; AFFINE_AFFINE_HULL]);;
3280
3281 let CLOSURE_SUBSET_AFFINE_HULL = prove
3282  (`!s. closure s SUBSET affine hull s`,
3283   GEN_TAC THEN MATCH_MP_TAC CLOSURE_MINIMAL THEN
3284   REWRITE_TAC[CLOSED_AFFINE_HULL; HULL_SUBSET]);;
3285
3286 let AFFINE_HULL_CLOSURE = prove
3287  (`!s:real^N->bool. affine hull (closure s) = affine hull s`,
3288   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN
3289   REWRITE_TAC[CLOSURE_SUBSET_AFFINE_HULL; AFFINE_AFFINE_HULL] THEN
3290   X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
3291   MATCH_MP_TAC HULL_MINIMAL THEN ASM_REWRITE_TAC[] THEN
3292   ASM_MESON_TAC[CLOSURE_SUBSET; SUBSET]);;
3293
3294 let AFFINE_HULL_EQ_SPAN_EQ = prove
3295  (`!s:real^N->bool. (affine hull s = span s) <=> (vec 0) IN affine hull s`,
3296   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[SPAN_0; AFFINE_HULL_EQ_SPAN]);;
3297
3298 let AFFINE_DEPENDENT_IMP_DEPENDENT = prove
3299  (`!s. affine_dependent s ==> dependent s`,
3300   REWRITE_TAC[affine_dependent; dependent] THEN
3301   MESON_TAC[SUBSET; AFFINE_HULL_SUBSET_SPAN]);;
3302
3303 let DEPENDENT_AFFINE_DEPENDENT_CASES = prove
3304  (`!s:real^N->bool.
3305         dependent s <=> affine_dependent s \/ (vec 0) IN affine hull s`,
3306   REWRITE_TAC[DEPENDENT_EXPLICIT; AFFINE_DEPENDENT_EXPLICIT;
3307               AFFINE_HULL_EXPLICIT_ALT; IN_ELIM_THM] THEN
3308   GEN_TAC THEN ONCE_REWRITE_TAC[OR_EXISTS_THM] THEN
3309   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
3310   X_GEN_TAC `t:real^N->bool` THEN
3311   ASM_CASES_TAC `FINITE(t:real^N->bool)` THEN ASM_REWRITE_TAC[] THEN
3312   EQ_TAC THEN DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN
3313    (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC))
3314   THENL
3315    [ASM_CASES_TAC `sum t (u:real^N->real) = &0` THENL
3316      [ASM_MESON_TAC[]; ALL_TAC] THEN
3317     DISJ2_TAC THEN EXISTS_TAC `\v:real^N. inv(sum t u) * u v` THEN
3318     ASM_SIMP_TAC[SUM_LMUL; VSUM_LMUL; GSYM VECTOR_MUL_ASSOC] THEN
3319     ASM_SIMP_TAC[VECTOR_MUL_RZERO; REAL_MUL_LINV];
3320     EXISTS_TAC `u:real^N->real` THEN ASM_MESON_TAC[];
3321     EXISTS_TAC `u:real^N->real` THEN
3322     ASM_REWRITE_TAC[SET_RULE
3323      `(?v. v IN t /\ ~p v) <=> ~(!v. v IN t ==> p v)`] THEN
3324     DISCH_TAC THEN
3325     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
3326      `x = &1 ==> x = &0 ==> F`)) THEN
3327     ASM_MESON_TAC[SUM_EQ_0]]);;
3328
3329 let DEPENDENT_IMP_AFFINE_DEPENDENT = prove
3330  (`!a:real^N s. dependent {x - a | x IN s} /\ ~(a IN s)
3331                 ==> affine_dependent(a INSERT s)`,
3332   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
3333   REWRITE_TAC[DEPENDENT_EXPLICIT; AFFINE_DEPENDENT_EXPLICIT] THEN
3334   REWRITE_TAC[SIMPLE_IMAGE; CONJ_ASSOC; FINITE_SUBSET_IMAGE] THEN
3335   REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN REWRITE_TAC[GSYM CONJ_ASSOC] THEN
3336   GEN_REWRITE_TAC LAND_CONV [SWAP_EXISTS_THM] THEN
3337   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [SWAP_EXISTS_THM] THEN
3338   REWRITE_TAC[TAUT `a /\ x = IMAGE f s /\ b <=> x = IMAGE f s /\ a /\ b`] THEN
3339   REWRITE_TAC[UNWIND_THM2; EXISTS_IN_IMAGE] THEN
3340   DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` (X_CHOOSE_THEN `t:real^N->bool`
3341     STRIP_ASSUME_TAC)) THEN
3342   FIRST_X_ASSUM(MP_TAC o check (is_eq o concl)) THEN
3343   ASM_SIMP_TAC[VSUM_IMAGE; VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
3344   ASM_SIMP_TAC[o_DEF; VECTOR_SUB_LDISTRIB; VSUM_SUB; VSUM_RMUL] THEN
3345   STRIP_TAC THEN
3346   MAP_EVERY EXISTS_TAC
3347    [`(a:real^N) INSERT t`;
3348     `\x. if x = a then --sum t (\x. u (x - a))
3349          else (u:real^N->real) (x - a)`] THEN
3350   ASM_REWRITE_TAC[FINITE_INSERT; SUBSET_REFL] THEN
3351   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES] THEN
3352   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3353   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THENL [ASM SET_TAC[]; ALL_TAC] THEN
3354   REPEAT CONJ_TAC THENL
3355    [MATCH_MP_TAC(REAL_ARITH `x = y ==> --x + y = &0`) THEN
3356     MATCH_MP_TAC SUM_EQ THEN ASM_MESON_TAC[];
3357     EXISTS_TAC `x:real^N` THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3358     COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[];
3359     MATCH_MP_TAC(VECTOR_ARITH
3360      `!s. s - t % a = vec 0 /\ s = u ==> --t % a + u = vec 0`) THEN
3361     EXISTS_TAC `vsum t (\x:real^N. u(x - a) % x)` THEN
3362     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC VSUM_EQ THEN
3363     REPEAT STRIP_TAC THEN REWRITE_TAC[] THEN COND_CASES_TAC THEN
3364     ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]]);;
3365
3366 let AFFINE_DEPENDENT_BIGGERSET = prove
3367  (`!s:real^N->bool.
3368         (FINITE s ==> CARD s >= dimindex(:N) + 2) ==> affine_dependent s`,
3369   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
3370   ASM_SIMP_TAC[CARD_CLAUSES; ARITH_RULE `~(0 >= n + 2)`; FINITE_RULES] THEN
3371   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3372   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
3373   FIRST_ASSUM(SUBST1_TAC o MATCH_MP (SET_RULE
3374    `x IN s ==> s = x INSERT (s DELETE x)`)) THEN
3375   SIMP_TAC[FINITE_INSERT; CARD_CLAUSES; IN_DELETE] THEN
3376   REWRITE_TAC[ARITH_RULE `SUC x >= n + 2 <=> x > n`] THEN DISCH_TAC THEN
3377   MATCH_MP_TAC DEPENDENT_IMP_AFFINE_DEPENDENT THEN
3378   REWRITE_TAC[IN_DELETE] THEN MATCH_MP_TAC DEPENDENT_BIGGERSET THEN
3379   REWRITE_TAC[SET_RULE `{x - a:real^N | x | x IN s /\ ~(x = a)} =
3380                         IMAGE (\x. x - a) (s DELETE a)`] THEN
3381   ASM_SIMP_TAC[FINITE_IMAGE_INJ_EQ;
3382                VECTOR_ARITH `x - a = y - a <=> x:real^N = y`;
3383                CARD_IMAGE_INJ]);;
3384
3385 let AFFINE_DEPENDENT_BIGGERSET_GENERAL = prove
3386  (`!s:real^N->bool. (FINITE s ==> CARD s >= dim s + 2) ==> affine_dependent s`,
3387   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
3388   ASM_SIMP_TAC[CARD_CLAUSES; ARITH_RULE `~(0 >= n + 2)`; FINITE_RULES] THEN
3389   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3390   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
3391   FIRST_ASSUM(SUBST1_TAC o MATCH_MP (SET_RULE
3392    `x IN s ==> s = x INSERT (s DELETE x)`)) THEN
3393   SIMP_TAC[FINITE_INSERT; CARD_CLAUSES; IN_DELETE] THEN
3394   REWRITE_TAC[ARITH_RULE `SUC x >= n + 2 <=> x > n`] THEN DISCH_TAC THEN
3395   MATCH_MP_TAC DEPENDENT_IMP_AFFINE_DEPENDENT THEN
3396   REWRITE_TAC[IN_DELETE] THEN
3397   MATCH_MP_TAC DEPENDENT_BIGGERSET_GENERAL THEN
3398   REWRITE_TAC[SET_RULE `{x - a:real^N | x | x IN s /\ ~(x = a)} =
3399                         IMAGE (\x. x - a) (s DELETE a)`] THEN
3400   ASM_SIMP_TAC[FINITE_IMAGE_INJ_EQ; FINITE_DELETE;
3401                VECTOR_ARITH `x - a = y - a <=> x:real^N = y`;
3402                CARD_IMAGE_INJ] THEN
3403   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o check(is_imp o concl)) THEN
3404   ASM_REWRITE_TAC[FINITE_DELETE] THEN
3405   MATCH_MP_TAC(ARITH_RULE `c:num <= b ==> (a > b ==> a > c)`) THEN
3406   MATCH_MP_TAC SUBSET_LE_DIM THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
3407   SIMP_TAC[SPAN_SUB; SPAN_SUPERSET; IN_INSERT]);;
3408
3409 let AFFINE_INDEPENDENT_IMP_FINITE = prove
3410  (`!s:real^N->bool. ~(affine_dependent s) ==> FINITE s`,
3411   MESON_TAC[AFFINE_DEPENDENT_BIGGERSET]);;
3412
3413 let AFFINE_INDEPENDENT_CARD_LE = prove
3414  (`!s:real^N->bool. ~(affine_dependent s) ==> CARD s <= dimindex(:N) + 1`,
3415   REWRITE_TAC[ARITH_RULE `s <= n + 1 <=> ~(n + 2 <= s)`; CONTRAPOS_THM] THEN
3416   REPEAT STRIP_TAC THEN MATCH_MP_TAC AFFINE_DEPENDENT_BIGGERSET THEN
3417   ASM_REWRITE_TAC[GE]);;
3418
3419 let AFFINE_INDEPENDENT_CONVEX_AFFINE_HULL = prove
3420  (`!s t:real^N->bool.
3421         ~affine_dependent s /\ t SUBSET s
3422         ==> convex hull t = affine hull t INTER convex hull s`,
3423   REPEAT STRIP_TAC THEN
3424   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3425   SUBGOAL_THEN `FINITE(t:real^N->bool)` ASSUME_TAC THENL
3426    [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
3427   MATCH_MP_TAC(SET_RULE
3428    `ct SUBSET a /\ ct SUBSET cs /\ a INTER cs SUBSET ct
3429     ==> ct = a INTER cs`) THEN
3430   ASM_SIMP_TAC[HULL_MONO; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
3431   REWRITE_TAC[SUBSET; IN_INTER; CONVEX_HULL_FINITE; AFFINE_HULL_FINITE] THEN
3432   X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
3433   DISCH_THEN(CONJUNCTS_THEN2
3434    (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC)
3435    (X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC)) THEN
3436   EXISTS_TAC `u:real^N->real` THEN ASM_REWRITE_TAC[] THEN
3437   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
3438   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
3439     [AFFINE_DEPENDENT_EXPLICIT]) THEN
3440   REWRITE_TAC[NOT_EXISTS_THM] THEN
3441   DISCH_THEN(MP_TAC o SPECL [`s:real^N->bool`;
3442         `\x:real^N. if x IN t then v x - u x:real else v x`]) THEN
3443   ASM_REWRITE_TAC[SUBSET_REFL] THEN REWRITE_TAC[MESON[]
3444    `(if p then a else b) % x = if p then a % x else b % x`] THEN
3445   ASM_SIMP_TAC[VSUM_CASES; SUM_CASES; SET_RULE
3446    `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
3447   ASM_SIMP_TAC[GSYM DIFF; SUM_DIFF; VSUM_DIFF; VECTOR_SUB_RDISTRIB;
3448                SUM_SUB; VSUM_SUB] THEN
3449   REWRITE_TAC[REAL_ARITH `a - b + b - a = &0`; NOT_EXISTS_THM;
3450               VECTOR_ARITH `a - b + b - a:real^N = vec 0`] THEN
3451   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
3452   ASM_REWRITE_TAC[REAL_SUB_0] THEN ASM SET_TAC[]);;
3453
3454 let DISJOINT_AFFINE_HULL = prove
3455  (`!s t u:real^N->bool.
3456         ~affine_dependent s /\ t SUBSET s /\ u SUBSET s /\ DISJOINT t u
3457         ==> DISJOINT (affine hull t) (affine hull u)`,
3458   REPEAT STRIP_TAC THEN
3459   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3460   SUBGOAL_THEN `FINITE(t:real^N->bool) /\ FINITE (u:real^N->bool)` ASSUME_TAC
3461   THENL [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
3462   REWRITE_TAC[IN_DISJOINT; AFFINE_HULL_FINITE; IN_ELIM_THM] THEN
3463   DISCH_THEN(X_CHOOSE_THEN `y:real^N` MP_TAC) THEN
3464   DISCH_THEN(CONJUNCTS_THEN2
3465    (X_CHOOSE_THEN `a:real^N->real` STRIP_ASSUME_TAC)
3466    (X_CHOOSE_THEN `b:real^N->real` STRIP_ASSUME_TAC)) THEN
3467   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
3468     [AFFINE_DEPENDENT_EXPLICIT]) THEN
3469   REWRITE_TAC[NOT_EXISTS_THM] THEN
3470   MAP_EVERY EXISTS_TAC
3471    [`s:real^N->bool`;
3472     `\x:real^N. if x IN t then a x else if x IN u then --(b x) else &0`] THEN
3473   ASM_REWRITE_TAC[SUBSET_REFL] THEN REWRITE_TAC[MESON[]
3474    `(if p then a else b) % x = if p then a % x else b % x`] THEN
3475   ASM_SIMP_TAC[SUM_CASES; SUBSET_REFL; VSUM_CASES; GSYM DIFF; SUM_DIFF;
3476       VSUM_DIFF; SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
3477   ASM_SIMP_TAC[SUM_0; VSUM_0; VECTOR_MUL_LZERO; SUM_NEG; VSUM_NEG;
3478     VECTOR_MUL_LNEG; SET_RULE `DISJOINT t u ==> ~(x IN t /\ x IN u)`] THEN
3479   REWRITE_TAC[EMPTY_GSPEC; SUM_CLAUSES; VSUM_CLAUSES] THEN
3480   CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
3481   CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
3482   UNDISCH_TAC `sum t (a:real^N->real) = &1` THEN
3483   ASM_CASES_TAC `!x:real^N. x IN t ==> a x = &0` THEN
3484   ASM_SIMP_TAC[SUM_EQ_0; REAL_OF_NUM_EQ; ARITH_EQ] THEN DISCH_TAC THEN
3485   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_FORALL_THM]) THEN
3486   MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[]);;
3487
3488 let AFFINE_INDEPENDENT_SPAN_EQ = prove
3489  (`!s. ~(affine_dependent s) /\ CARD s = dimindex(:N) + 1
3490        ==> affine hull s = (:real^N)`,
3491   MATCH_MP_TAC SET_PROVE_CASES THEN
3492   REWRITE_TAC[CARD_CLAUSES; ARITH_RULE `~(0 = n + 1)`] THEN
3493   SIMP_TAC[IMP_CONJ; AFFINE_INDEPENDENT_IMP_FINITE; MESON[HAS_SIZE]
3494    `FINITE s ==> (CARD s = n <=> s HAS_SIZE n)`] THEN
3495   X_GEN_TAC `orig:real^N` THEN GEOM_ORIGIN_TAC `orig:real^N` THEN
3496   SIMP_TAC[AFFINE_HULL_EQ_SPAN; IN_INSERT; SPAN_INSERT_0; HULL_INC] THEN
3497   SIMP_TAC[HAS_SIZE; CARD_CLAUSES; FINITE_INSERT; IMP_CONJ] THEN
3498   REWRITE_TAC[ARITH_RULE `SUC n = m + 1 <=> n = m`; GSYM UNIV_SUBSET] THEN
3499   REPEAT STRIP_TAC THEN MATCH_MP_TAC CARD_GE_DIM_INDEPENDENT THEN
3500   ASM_REWRITE_TAC[DIM_UNIV; SUBSET_UNIV; LE_REFL; independent] THEN
3501   UNDISCH_TAC `~affine_dependent((vec 0:real^N) INSERT s)` THEN
3502   REWRITE_TAC[CONTRAPOS_THM] THEN DISCH_TAC THEN
3503   MATCH_MP_TAC DEPENDENT_IMP_AFFINE_DEPENDENT THEN
3504   ASM_REWRITE_TAC[VECTOR_SUB_RZERO; SET_RULE `{x | x IN s} = s`]);;
3505
3506 let AFFINE_INDEPENDENT_SPAN_GT = prove
3507  (`!s:real^N->bool.
3508         ~(affine_dependent s) /\ dimindex(:N) < CARD s
3509         ==> affine hull s = (:real^N)`,
3510   REPEAT STRIP_TAC THEN MATCH_MP_TAC AFFINE_INDEPENDENT_SPAN_EQ THEN
3511   ASM_REWRITE_TAC[] THEN
3512   MP_TAC(SPEC `s:real^N->bool` AFFINE_DEPENDENT_BIGGERSET) THEN
3513   ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE] THEN ASM_ARITH_TAC);;
3514
3515 let EMPTY_INTERIOR_AFFINE_HULL = prove
3516  (`!s:real^N->bool.
3517         FINITE s /\ CARD(s) <= dimindex(:N)
3518         ==> interior(affine hull s) = {}`,
3519   REWRITE_TAC[IMP_CONJ] THEN  MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
3520   REWRITE_TAC[AFFINE_HULL_EMPTY; INTERIOR_EMPTY] THEN
3521   SUBGOAL_THEN
3522    `!x s:real^N->bool n.
3523         ~(x IN s) /\ (x INSERT s) HAS_SIZE n /\ n <= dimindex(:N)
3524         ==> interior(affine hull(x INSERT s)) = {}`
3525    (fun th -> MESON_TAC[th; HAS_SIZE; FINITE_INSERT]) THEN
3526   X_GEN_TAC `orig:real^N` THEN GEOM_ORIGIN_TAC `orig:real^N` THEN
3527   SIMP_TAC[AFFINE_HULL_EQ_SPAN; IN_INSERT; SPAN_INSERT_0; HULL_INC] THEN
3528   REWRITE_TAC[HAS_SIZE; FINITE_INSERT; IMP_CONJ] THEN
3529   SIMP_TAC[CARD_CLAUSES] THEN
3530   REPEAT STRIP_TAC THEN MATCH_MP_TAC EMPTY_INTERIOR_LOWDIM THEN
3531   MATCH_MP_TAC LET_TRANS THEN EXISTS_TAC `CARD(s:real^N->bool)` THEN
3532   ASM_SIMP_TAC[DIM_LE_CARD; DIM_SPAN] THEN ASM_ARITH_TAC);;
3533
3534 let EMPTY_INTERIOR_CONVEX_HULL = prove
3535  (`!s:real^N->bool.
3536         FINITE s /\ CARD(s) <= dimindex(:N)
3537         ==> interior(convex hull s) = {}`,
3538   REPEAT STRIP_TAC THEN
3539   MATCH_MP_TAC(SET_RULE `!t. s SUBSET t /\ t = {} ==> s = {}`) THEN
3540   EXISTS_TAC `interior(affine hull s):real^N->bool` THEN
3541   SIMP_TAC[SUBSET_INTERIOR; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
3542   ASM_SIMP_TAC[EMPTY_INTERIOR_AFFINE_HULL]);;
3543
3544 let AFFINE_DEPENDENT_CHOOSE = prove
3545  (`!s a:real^N.
3546        ~(affine_dependent s)
3547        ==> (affine_dependent(a INSERT s) <=> ~(a IN s) /\ a IN affine hull s)`,
3548   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(a:real^N) IN s` THEN
3549   ASM_SIMP_TAC[SET_RULE `a IN s ==> a INSERT s = s`] THEN
3550   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3551   EQ_TAC THENL
3552    [UNDISCH_TAC `~(affine_dependent(s:real^N->bool))` THEN
3553     ASM_SIMP_TAC[AFFINE_DEPENDENT_EXPLICIT_FINITE; AFFINE_HULL_FINITE;
3554                  FINITE_INSERT; IN_ELIM_THM; SUM_CLAUSES; VSUM_CLAUSES] THEN
3555     DISCH_TAC THEN REWRITE_TAC[EXISTS_IN_INSERT] THEN
3556     DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` MP_TAC) THEN
3557     ASM_CASES_TAC `(u:real^N->real) a = &0` THEN ASM_REWRITE_TAC[] THENL
3558      [REWRITE_TAC[REAL_ADD_LID; VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN
3559       DISCH_TAC THEN
3560       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
3561       DISCH_THEN(MP_TAC o SPEC `u:real^N->real`) THEN ASM_REWRITE_TAC[];
3562       ONCE_REWRITE_TAC[REAL_ARITH `ua + sa = &0 <=> sa = --ua`;
3563                    VECTOR_ARITH `va + sa:real^N = vec 0 <=> sa = --va`] THEN
3564       STRIP_TAC THEN EXISTS_TAC `(\x. --(inv(u a)) * u x):real^N->real` THEN
3565       ASM_SIMP_TAC[SUM_LMUL; GSYM VECTOR_MUL_ASSOC; VSUM_LMUL] THEN
3566       ASM_REWRITE_TAC[VECTOR_MUL_ASSOC; GSYM VECTOR_MUL_LNEG] THEN
3567       REWRITE_TAC[REAL_ARITH `--a * --b:real = a * b`] THEN
3568       ASM_SIMP_TAC[REAL_MUL_LINV; VECTOR_MUL_LID]];
3569     DISCH_TAC THEN REWRITE_TAC[affine_dependent] THEN
3570     EXISTS_TAC `a:real^N` THEN
3571     ASM_SIMP_TAC[IN_INSERT; SET_RULE
3572      `~(a IN s) ==> (a INSERT s) DELETE a = s`]]);;
3573
3574 let AFFINE_INDEPENDENT_INSERT = prove
3575  (`!s a:real^N.
3576         ~(affine_dependent s) /\ ~(a IN affine hull s)
3577         ==> ~(affine_dependent(a INSERT s))`,
3578   SIMP_TAC[AFFINE_DEPENDENT_CHOOSE]);;
3579
3580 let AFFINE_HULL_EXPLICIT_UNIQUE = prove
3581  (`!s:real^N->bool u u'.
3582       ~(affine_dependent s) /\
3583       sum s u = &1 /\ sum s u' = &1 /\
3584       vsum s (\x. u x % x) = vsum s (\x. u' x % x)
3585       ==> !x. x IN s ==> u x = u' x`,
3586   REPEAT GEN_TAC THEN STRIP_TAC THEN
3587   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3588   FIRST_ASSUM(MP_TAC o MATCH_MP AFFINE_DEPENDENT_EXPLICIT_FINITE) THEN
3589   ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
3590   DISCH_THEN(MP_TAC o SPEC `(\x. u x - u' x):real^N->real`) THEN
3591   ASM_SIMP_TAC[VSUM_SUB; SUM_SUB; REAL_SUB_REFL; VECTOR_SUB_RDISTRIB;
3592                VECTOR_SUB_REFL; VECTOR_SUB_EQ; REAL_SUB_0] THEN
3593   MESON_TAC[]);;
3594
3595 let INDEPENDENT_IMP_AFFINE_DEPENDENT_0 = prove
3596  (`!s. independent s ==> ~(affine_dependent(vec 0 INSERT s))`,
3597   REWRITE_TAC[independent; DEPENDENT_AFFINE_DEPENDENT_CASES] THEN
3598   SIMP_TAC[DE_MORGAN_THM; AFFINE_INDEPENDENT_INSERT]);;
3599
3600 let AFFINE_INDEPENDENT_STDBASIS = prove
3601  (`~(affine_dependent
3602       ((vec 0:real^N) INSERT {basis i | 1 <= i /\ i <= dimindex (:N)}))`,
3603   SIMP_TAC[INDEPENDENT_IMP_AFFINE_DEPENDENT_0; INDEPENDENT_STDBASIS]);;
3604
3605 (* ------------------------------------------------------------------------- *)
3606 (* Nonempty affine sets are translates of (unique) subspaces.                *)
3607 (* ------------------------------------------------------------------------- *)
3608
3609 let AFFINE_TRANSLATION_SUBSPACE = prove
3610  (`!t:real^N->bool.
3611         affine t /\ ~(t = {}) <=> ?a s. subspace s /\ t = IMAGE (\x. a + x) s`,
3612   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
3613   ASM_SIMP_TAC[SUBSPACE_IMP_NONEMPTY; IMAGE_EQ_EMPTY;
3614                AFFINE_TRANSLATION; SUBSPACE_IMP_AFFINE] THEN
3615   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3616   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
3617   ONCE_REWRITE_TAC[TRANSLATION_GALOIS] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
3618   REWRITE_TAC[UNWIND_THM2] THEN MATCH_MP_TAC AFFINE_IMP_SUBSPACE THEN
3619   ASM_REWRITE_TAC[AFFINE_TRANSLATION_EQ; IN_IMAGE] THEN
3620   EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC);;
3621
3622 let AFFINE_TRANSLATION_UNIQUE_SUBSPACE = prove
3623  (`!t:real^N->bool.
3624         affine t /\ ~(t = {}) <=>
3625         ?!s. ?a. subspace s /\ t = IMAGE (\x. a + x) s`,
3626   GEN_TAC THEN REWRITE_TAC[AFFINE_TRANSLATION_SUBSPACE] THEN
3627   MATCH_MP_TAC(MESON[]
3628    `(!a a' s s'. P s a /\ P s' a' ==> s = s')
3629     ==> ((?a s. P s a) <=> (?!s. ?a. P s a))`) THEN
3630   REPEAT GEN_TAC THEN
3631   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC)) THEN
3632   DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
3633   ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[TRANSLATION_GALOIS] THEN
3634   DISCH_THEN SUBST1_TAC THEN CONV_TAC SYM_CONV THEN
3635   REWRITE_TAC[GSYM IMAGE_o; o_DEF; VECTOR_ADD_ASSOC] THEN
3636   MATCH_MP_TAC SUBSPACE_TRANSLATION_SELF THEN ASM_REWRITE_TAC[] THEN
3637   ONCE_REWRITE_TAC[VECTOR_ARITH `--a' + a:real^N = --(a' - a)`] THEN
3638   MATCH_MP_TAC SUBSPACE_NEG THEN ASM_REWRITE_TAC[] THEN
3639   UNDISCH_TAC `t = IMAGE (\x:real^N. a' + x) s'` THEN
3640   DISCH_THEN(MP_TAC o AP_TERM `\s. (a':real^N) IN s`) THEN
3641   REWRITE_TAC[IN_IMAGE; VECTOR_ARITH `a:real^N = a + x <=> x = vec 0`] THEN
3642   ASM_SIMP_TAC[UNWIND_THM2; SUBSPACE_0] THEN
3643   REWRITE_TAC[IN_IMAGE; VECTOR_ARITH `a':real^N = a + x <=> x = a' - a`] THEN
3644   REWRITE_TAC[UNWIND_THM2]);;
3645
3646 let AFFINE_TRANSLATION_SUBSPACE_EXPLICIT = prove
3647  (`!t:real^N->bool a.
3648         affine t /\ a IN t
3649         ==> subspace {x - a | x IN t} /\
3650             t = IMAGE (\x. a + x) {x - a | x IN t}`,
3651   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[AFFINE_DIFFS_SUBSPACE] THEN
3652   ASM_REWRITE_TAC[SIMPLE_IMAGE; GSYM IMAGE_o] THEN
3653   REWRITE_TAC[o_DEF; VECTOR_SUB_ADD2; IMAGE_ID]);;
3654
3655 (* ------------------------------------------------------------------------- *)
3656 (* If we take a slice out of a set, we can do it perpendicularly,            *)
3657 (* with the normal vector to the slice parallel to the affine hull.          *)
3658 (* ------------------------------------------------------------------------- *)
3659
3660 let AFFINE_PARALLEL_SLICE = prove
3661   (`!s a:real^N b.
3662        affine s
3663        ==> s INTER {x | a dot x <= b} = {} \/ s SUBSET {x | a dot x <= b} \/
3664            ?a' b'. ~(a' = vec 0) /\
3665
3666                    s INTER {x | a' dot x <= b'} = s INTER {x | a dot x <= b} /\
3667                    s INTER {x | a' dot x = b'} = s INTER {x | a dot x = b} /\
3668                    !w. w IN s ==> (w + a') IN s`,
3669    REPEAT STRIP_TAC THEN
3670    ASM_CASES_TAC `s INTER {x:real^N | a dot x = b} = {}` THENL
3671     [MATCH_MP_TAC(TAUT `~(~p /\ ~q) ==> p \/ q \/ r`) THEN
3672      REPEAT STRIP_TAC THEN SUBGOAL_THEN
3673       `?u v:real^N. u IN s /\ v IN s /\
3674                     a dot u <= b /\ ~(a dot v <= b)`
3675      STRIP_ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3676      SUBGOAL_THEN `(a:real^N) dot u < b` ASSUME_TAC THENL
3677       [ASM_REWRITE_TAC[REAL_LT_LE] THEN ASM SET_TAC[]; ALL_TAC] THEN
3678      RULE_ASSUM_TAC(REWRITE_RULE[REAL_NOT_LE]) THEN
3679      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
3680      REWRITE_TAC[NOT_IN_EMPTY; IN_INTER; NOT_FORALL_THM; IN_ELIM_THM] THEN
3681      EXISTS_TAC
3682       `u + (b - a dot u) / (a dot v - a dot u) % (v - u):real^N` THEN
3683      ASM_SIMP_TAC[IN_AFFINE_ADD_MUL_DIFF] THEN
3684      REWRITE_TAC[DOT_RADD; DOT_RMUL; DOT_RSUB] THEN
3685      REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD;
3686      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3687      DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
3688      REWRITE_TAC[IN_INTER; IN_ELIM_THM] THEN POP_ASSUM MP_TAC THEN
3689      GEN_GEOM_ORIGIN_TAC `z:real^N` ["a"; "a'"; "b'"; "w"] THEN
3690      REPEAT STRIP_TAC THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
3691      REWRITE_TAC[VECTOR_ADD_RID; FORALL_IN_IMAGE] THEN
3692      REWRITE_TAC[DOT_RADD; REAL_ARITH `a + x <= a <=> x <= &0`] THEN
3693      SUBGOAL_THEN `subspace(s:real^N->bool) /\ span s = s`
3694      STRIP_ASSUME_TAC THENL
3695       [ASM_MESON_TAC[AFFINE_IMP_SUBSPACE; SPAN_EQ_SELF]; ALL_TAC] THEN
3696      MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`]
3697            ORTHOGONAL_SUBSPACE_DECOMP_EXISTS) THEN
3698      ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; orthogonal] THEN
3699      MAP_EVERY X_GEN_TAC [`a':real^N`; `a'':real^N`] THEN
3700      ASM_CASES_TAC `a':real^N = vec 0` THENL
3701       [ASM_REWRITE_TAC[VECTOR_ADD_LID] THEN
3702        ASM_CASES_TAC `a'':real^N = a` THEN ASM_REWRITE_TAC[] THEN
3703        SIMP_TAC[SUBSET; IN_ELIM_THM; REAL_LE_REFL];
3704        ALL_TAC] THEN
3705      STRIP_TAC THEN REPEAT DISJ2_TAC THEN
3706      EXISTS_TAC `a':real^N` THEN ASM_REWRITE_TAC[] THEN
3707      EXISTS_TAC `(a':real^N) dot z` THEN
3708      REPEAT(CONJ_TAC THENL
3709       [MATCH_MP_TAC(SET_RULE
3710         `(!x. x IN s ==> (p x <=> q x))
3711          ==> s INTER {x | p x} = s INTER {x | q x}`) THEN
3712        ASM_SIMP_TAC[DOT_LADD] THEN REAL_ARITH_TAC;
3713        ALL_TAC]) THEN
3714      X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_IMAGE] THEN
3715      EXISTS_TAC `x + a':real^N` THEN
3716      ASM_SIMP_TAC[SUBSPACE_ADD; VECTOR_ADD_ASSOC]]);;
3717
3718 (* ------------------------------------------------------------------------- *)
3719 (* Affine dimension.                                                         *)
3720 (* ------------------------------------------------------------------------- *)
3721
3722 let MAXIMAL_AFFINE_INDEPENDENT_SUBSET = prove
3723  (`!s b:real^N->bool.
3724         b SUBSET s /\ ~(affine_dependent b) /\
3725         (!b'. b SUBSET b' /\ b' SUBSET s /\ ~(affine_dependent b') ==> b' = b)
3726         ==> s SUBSET (affine hull b)`,
3727   REPEAT STRIP_TAC THEN
3728   MATCH_MP_TAC(SET_RULE `(!a. a IN t /\ ~(a IN s) ==> F) ==> t SUBSET s`) THEN
3729   X_GEN_TAC `a:real^N` THEN STRIP_TAC THEN
3730   FIRST_X_ASSUM(MP_TAC o SPEC `(a:real^N) INSERT b`) THEN
3731   FIRST_ASSUM(MP_TAC o MATCH_MP
3732    (ONCE_REWRITE_RULE[GSYM CONTRAPOS_THM] HULL_INC)) THEN
3733   ASM_SIMP_TAC[AFFINE_INDEPENDENT_INSERT; INSERT_SUBSET] THEN
3734   ASM SET_TAC[]);;
3735
3736 let MAXIMAL_AFFINE_INDEPENDENT_SUBSET_AFFINE = prove
3737  (`!s b:real^N->bool.
3738         affine s /\ b SUBSET s /\ ~(affine_dependent b) /\
3739         (!b'. b SUBSET b' /\ b' SUBSET s /\ ~(affine_dependent b') ==> b' = b)
3740         ==> affine hull b = s`,
3741   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3742    [ASM_MESON_TAC[HULL_MONO; HULL_P];
3743     ASM_MESON_TAC[MAXIMAL_AFFINE_INDEPENDENT_SUBSET]]);;
3744
3745 let EXTEND_TO_AFFINE_BASIS = prove
3746  (`!s u:real^N->bool.
3747         ~(affine_dependent s) /\ s SUBSET u
3748         ==> ?t. ~(affine_dependent t) /\ s SUBSET t /\ t SUBSET u /\
3749                 affine hull t = affine hull u`,
3750   REPEAT STRIP_TAC THEN
3751   MP_TAC(SPEC `\n. ?t:real^N->bool. ~(affine_dependent t) /\ s SUBSET t /\
3752                                     t SUBSET u /\ CARD t = n`
3753    num_MAX) THEN
3754   DISCH_THEN(MP_TAC o fst o EQ_IMP_RULE) THEN REWRITE_TAC[] THEN ANTS_TAC THENL
3755    [ASM_MESON_TAC[SUBSET_REFL; AFFINE_INDEPENDENT_CARD_LE]; ALL_TAC] THEN
3756   DISCH_THEN(X_CHOOSE_THEN `n:num` (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC)) THEN
3757   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
3758   ASM_REWRITE_TAC[] THEN
3759   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3760    [ASM_MESON_TAC[HULL_MONO; HULL_P]; ALL_TAC] THEN
3761   MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[AFFINE_AFFINE_HULL] THEN
3762   MATCH_MP_TAC MAXIMAL_AFFINE_INDEPENDENT_SUBSET THEN ASM_REWRITE_TAC[] THEN
3763   X_GEN_TAC `c:real^N->bool` THEN STRIP_TAC THEN
3764   FIRST_X_ASSUM(MP_TAC o SPEC `CARD(c:real^N->bool)`) THEN
3765   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
3766   DISCH_THEN(MP_TAC o SPEC `c:real^N->bool`) THEN
3767   ANTS_TAC THENL [ASM SET_TAC[]; DISCH_TAC] THEN
3768   CONV_TAC SYM_CONV THEN MATCH_MP_TAC CARD_SUBSET_LE THEN
3769   ASM_MESON_TAC[AFFINE_INDEPENDENT_IMP_FINITE]);;
3770
3771 let AFFINE_BASIS_EXISTS = prove
3772  (`!s:real^N->bool.
3773       ?b. ~(affine_dependent b) /\ b SUBSET s /\
3774           affine hull b = affine hull s`,
3775   GEN_TAC THEN
3776   MP_TAC(ISPECL [`{}:real^N->bool`; `s:real^N->bool`]
3777     EXTEND_TO_AFFINE_BASIS) THEN
3778   REWRITE_TAC[AFFINE_INDEPENDENT_EMPTY; EMPTY_SUBSET]);;
3779
3780 let aff_dim = new_definition
3781   `aff_dim s =
3782         @d:int. ?b. affine hull b = affine hull s /\ ~(affine_dependent b) /\
3783                     &(CARD b) = d + &1`;;
3784
3785 let AFF_DIM = prove
3786  (`!s. ?b. affine hull b = affine hull s /\
3787            ~(affine_dependent b) /\
3788            aff_dim s = &(CARD b) - &1`,
3789   GEN_TAC THEN
3790   REWRITE_TAC[aff_dim; INT_ARITH `y:int = x + &1 <=> x = y - &1`] THEN
3791   CONV_TAC SELECT_CONV THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
3792   REWRITE_TAC[RIGHT_EXISTS_AND_THM; EXISTS_REFL] THEN
3793   MESON_TAC[AFFINE_BASIS_EXISTS]);;
3794
3795 let AFF_DIM_EMPTY = prove
3796  (`aff_dim {} = -- &1`,
3797   REWRITE_TAC[aff_dim; AFFINE_HULL_EMPTY; AFFINE_HULL_EQ_EMPTY] THEN
3798   REWRITE_TAC[UNWIND_THM2; AFFINE_INDEPENDENT_EMPTY; CARD_CLAUSES] THEN
3799   REWRITE_TAC[INT_ARITH `&0 = d + &1 <=> d:int = -- &1`; SELECT_REFL]);;
3800
3801 let AFF_DIM_AFFINE_HULL = prove
3802  (`!s. aff_dim(affine hull s) = aff_dim s`,
3803   REWRITE_TAC[aff_dim; HULL_HULL]);;
3804
3805 let AFF_DIM_TRANSLATION_EQ = prove
3806  (`!a:real^N s. aff_dim (IMAGE (\x. a + x) s) = aff_dim s`,
3807   REWRITE_TAC[aff_dim] THEN GEOM_TRANSLATE_TAC[] THEN
3808   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> ~(a /\ b ==> ~c)`] THEN
3809   SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE; CARD_IMAGE_INJ;
3810            VECTOR_ARITH `a + x:real^N = a + y <=> x = y`]);;
3811
3812 add_translation_invariants [AFF_DIM_TRANSLATION_EQ];;
3813
3814 let AFFINE_INDEPENDENT_CARD_DIM_DIFFS = prove
3815  (`!s a:real^N.
3816         ~affine_dependent s /\ a IN s
3817         ==> CARD s = dim {x - a | x IN s} + 1`,
3818   REPEAT STRIP_TAC THEN
3819   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
3820   MATCH_MP_TAC(ARITH_RULE `~(s = 0) /\ v = s - 1 ==> s = v + 1`) THEN
3821   ASM_SIMP_TAC[CARD_EQ_0] THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
3822   MATCH_MP_TAC DIM_UNIQUE THEN
3823   EXISTS_TAC `{b - a:real^N |b| b IN (s DELETE a)}` THEN REPEAT CONJ_TAC THENL
3824    [SET_TAC[];
3825     REWRITE_TAC[SIMPLE_IMAGE; SUBSET; FORALL_IN_IMAGE] THEN
3826     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN ASM_CASES_TAC `x:real^N = a` THENL
3827      [ASM_REWRITE_TAC[VECTOR_SUB_REFL; SPAN_0];
3828       MATCH_MP_TAC SPAN_SUPERSET THEN ASM SET_TAC[]];
3829     UNDISCH_TAC `~affine_dependent(s:real^N->bool)` THEN
3830     REWRITE_TAC[independent; CONTRAPOS_THM] THEN DISCH_TAC THEN
3831     SUBGOAL_THEN `s = (a:real^N) INSERT (s DELETE a)` SUBST1_TAC THENL
3832      [ASM SET_TAC[]; ALL_TAC] THEN
3833     MATCH_MP_TAC DEPENDENT_IMP_AFFINE_DEPENDENT THEN
3834     ASM_REWRITE_TAC[IN_DELETE];
3835     REWRITE_TAC[SIMPLE_IMAGE] THEN MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN
3836     SIMP_TAC[VECTOR_ARITH `x - a:real^N = y - a <=> x = y`] THEN
3837     ASM_SIMP_TAC[HAS_SIZE; FINITE_DELETE; CARD_DELETE]]);;
3838
3839 let AFF_DIM_DIM_AFFINE_DIFFS = prove
3840  (`!a:real^N s. affine s /\ a IN s ==> aff_dim s = &(dim {x - a | x IN s})`,
3841   REPEAT STRIP_TAC THEN
3842   MP_TAC(ISPEC `s:real^N->bool` AFF_DIM) THEN
3843   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` MP_TAC) THEN
3844   ASM_CASES_TAC `b:real^N->bool = {}` THENL
3845    [ASM_MESON_TAC[AFFINE_HULL_EQ_EMPTY; NOT_IN_EMPTY]; ALL_TAC] THEN
3846   STRIP_TAC THEN
3847   ASM_REWRITE_TAC[INT_EQ_SUB_RADD; INT_OF_NUM_ADD; INT_OF_NUM_EQ] THEN
3848   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3849   DISCH_THEN(X_CHOOSE_TAC `c:real^N`) THEN MATCH_MP_TAC EQ_TRANS THEN
3850   EXISTS_TAC `dim {x - c:real^N | x IN b} + 1` THEN CONJ_TAC THENL
3851    [MATCH_MP_TAC AFFINE_INDEPENDENT_CARD_DIM_DIFFS THEN ASM_REWRITE_TAC[];
3852     ALL_TAC] THEN
3853   MATCH_MP_TAC EQ_TRANS THEN
3854   EXISTS_TAC `dim {x - c:real^N | x IN affine hull b} + 1` THEN CONJ_TAC THENL
3855    [ASM_SIMP_TAC[DIFFS_AFFINE_HULL_SPAN; DIM_SPAN]; ALL_TAC] THEN
3856   ASM_REWRITE_TAC[] THEN AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
3857   SUBGOAL_THEN `affine hull s:real^N->bool = s` SUBST1_TAC THENL
3858    [ASM_MESON_TAC[AFFINE_HULL_EQ]; ALL_TAC] THEN
3859   SUBGOAL_THEN `(c:real^N) IN s` ASSUME_TAC THENL
3860    [ASM_MESON_TAC[AFFINE_HULL_EQ; HULL_INC]; ALL_TAC] THEN
3861   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
3862   REWRITE_TAC[IN_ELIM_THM] THEN
3863   SIMP_TAC[VECTOR_ARITH `x - c:real^N = y - a <=> y = x + &1 % (a - c)`] THEN
3864   ASM_MESON_TAC[IN_AFFINE_ADD_MUL_DIFF]);;
3865
3866 let AFF_DIM_DIM_0 = prove
3867  (`!s:real^N->bool. vec 0 IN affine hull s ==> aff_dim s = &(dim s)`,
3868   REPEAT STRIP_TAC THEN
3869   MP_TAC(ISPECL [`vec 0:real^N`; `affine hull s:real^N->bool`]
3870     AFF_DIM_DIM_AFFINE_DIFFS) THEN
3871   ASM_REWRITE_TAC[AFFINE_AFFINE_HULL; VECTOR_SUB_RZERO] THEN
3872   REWRITE_TAC[AFF_DIM_AFFINE_HULL; SET_RULE `{x | x IN s} = s`] THEN
3873   ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; DIM_SPAN]);;
3874
3875 let AFF_DIM_DIM_SUBSPACE = prove
3876  (`!s:real^N->bool. subspace s ==> aff_dim s = &(dim s)`,
3877   MESON_TAC[AFF_DIM_DIM_0; SUBSPACE_0; HULL_INC]);;
3878
3879 let AFF_DIM_LINEAR_IMAGE_LE = prove
3880  (`!f:real^M->real^N s. linear f ==> aff_dim(IMAGE f s) <= aff_dim s`,
3881   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
3882   ASM_SIMP_TAC[AFFINE_HULL_LINEAR_IMAGE] THEN
3883   MP_TAC(ISPEC `s:real^M->bool` AFFINE_AFFINE_HULL) THEN
3884   SPEC_TAC(`affine hull s:real^M->bool`,`s:real^M->bool`) THEN
3885   GEN_TAC THEN DISCH_TAC THEN ASM_CASES_TAC `s:real^M->bool = {}` THEN
3886   ASM_REWRITE_TAC[IMAGE_CLAUSES; AFF_DIM_EMPTY; INT_LE_REFL] THEN
3887   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3888   DISCH_THEN(X_CHOOSE_TAC `a:real^M`) THEN
3889   SUBGOAL_THEN `dim {x - f(a) |x| x IN IMAGE (f:real^M->real^N) s} <=
3890                 dim {x - a | x IN s}`
3891   MP_TAC THENL
3892    [REWRITE_TAC[SET_RULE `{f x | x IN IMAGE g s} = {f (g x) | x IN s}`] THEN
3893     ASM_SIMP_TAC[GSYM LINEAR_SUB] THEN REWRITE_TAC[SIMPLE_IMAGE] THEN
3894     ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[IMAGE_o] THEN
3895     MATCH_MP_TAC DIM_LINEAR_IMAGE_LE THEN ASM_REWRITE_TAC[];
3896     MATCH_MP_TAC EQ_IMP THEN REWRITE_TAC[GSYM INT_OF_NUM_LE] THEN
3897     BINOP_TAC THEN CONV_TAC SYM_CONV THEN
3898     MATCH_MP_TAC AFF_DIM_DIM_AFFINE_DIFFS THEN
3899     ASM_SIMP_TAC[AFFINE_LINEAR_IMAGE; FUN_IN_IMAGE]]);;
3900
3901 let AFF_DIM_INJECTIVE_LINEAR_IMAGE = prove
3902  (`!f:real^M->real^N s.
3903         linear f /\ (!x y. f x = f y ==> x = y)
3904         ==> aff_dim(IMAGE f s) = aff_dim s`,
3905   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM INT_LE_ANTISYM] THEN
3906   CONJ_TAC THENL [ASM_MESON_TAC[AFF_DIM_LINEAR_IMAGE_LE]; ALL_TAC] THEN
3907   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_LEFT_INVERSE) THEN
3908   ASM_REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN
3909   DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^M` STRIP_ASSUME_TAC) THEN
3910   MATCH_MP_TAC INT_LE_TRANS THEN EXISTS_TAC
3911    `aff_dim(IMAGE (g:real^N->real^M) (IMAGE (f:real^M->real^N) s))` THEN
3912   CONJ_TAC THENL
3913    [ASM_REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID; INT_LE_REFL];
3914     MATCH_MP_TAC AFF_DIM_LINEAR_IMAGE_LE THEN ASM_REWRITE_TAC[]]);;
3915
3916 add_linear_invariants [AFF_DIM_INJECTIVE_LINEAR_IMAGE];;
3917
3918 let AFF_DIM_AFFINE_INDEPENDENT = prove
3919  (`!b:real^N->bool.
3920         ~(affine_dependent b) ==> aff_dim b = &(CARD b) - &1`,
3921   GEN_TAC THEN ASM_CASES_TAC `b:real^N->bool = {}` THENL
3922    [ASM_REWRITE_TAC[CARD_CLAUSES; AFF_DIM_EMPTY] THEN INT_ARITH_TAC;
3923     ALL_TAC] THEN
3924   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
3925   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN DISCH_TAC THEN
3926   MP_TAC(ISPECL [`b:real^N->bool`; `a:real^N`]
3927    AFFINE_INDEPENDENT_CARD_DIM_DIFFS) THEN
3928   ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST1_TAC THEN
3929   REWRITE_TAC[GSYM INT_OF_NUM_ADD; INT_ARITH `(a + b) - b:int = a`] THEN
3930   MP_TAC(ISPECL [`a:real^N`; `affine hull b:real^N->bool`]
3931    AFF_DIM_DIM_AFFINE_DIFFS) THEN
3932   ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC; AFF_DIM_AFFINE_HULL] THEN
3933   DISCH_THEN(K ALL_TAC) THEN AP_TERM_TAC THEN
3934   ASM_MESON_TAC[DIFFS_AFFINE_HULL_SPAN; DIM_SPAN]);;
3935
3936 let AFF_DIM_UNIQUE = prove
3937  (`!s b:real^N->bool.
3938         affine hull b = affine hull s /\ ~(affine_dependent b)
3939         ==> aff_dim s = &(CARD b) - &1`,
3940   MESON_TAC[AFF_DIM_AFFINE_HULL; AFF_DIM_AFFINE_INDEPENDENT]);;
3941
3942 let AFF_DIM_SING = prove
3943  (`!a:real^N. aff_dim {a} = &0`,
3944   GEN_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
3945   EXISTS_TAC `&(CARD {a:real^N}) - &1:int` THEN CONJ_TAC THENL
3946    [MATCH_MP_TAC AFF_DIM_AFFINE_INDEPENDENT THEN
3947     REWRITE_TAC[AFFINE_INDEPENDENT_1];
3948     SIMP_TAC[CARD_CLAUSES; FINITE_RULES; ARITH; NOT_IN_EMPTY; INT_SUB_REFL]]);;
3949
3950 let AFF_DIM_LE_CARD = prove
3951  (`!s:real^N->bool. FINITE s ==> aff_dim s <= &(CARD s) - &1`,
3952   MATCH_MP_TAC SET_PROVE_CASES THEN
3953   SIMP_TAC[AFF_DIM_EMPTY; CARD_CLAUSES] THEN CONV_TAC INT_REDUCE_CONV THEN
3954   GEOM_ORIGIN_TAC `a:real^N` THEN
3955   SIMP_TAC[AFF_DIM_DIM_0; IN_INSERT; HULL_INC] THEN
3956   SIMP_TAC[CARD_IMAGE_INJ; VECTOR_ARITH `a + x:real^N = a + y <=> x = y`] THEN
3957   SIMP_TAC[DIM_INSERT_0; INT_LE_SUB_LADD; CARD_CLAUSES; FINITE_INSERT] THEN
3958   REWRITE_TAC[INT_OF_NUM_ADD; INT_OF_NUM_LE; ADD1; LE_ADD_RCANCEL] THEN
3959   SIMP_TAC[DIM_LE_CARD]);;
3960
3961 let AFF_DIM_GE = prove
3962  (`!s:real^N->bool. -- &1 <= aff_dim s`,
3963   GEN_TAC THEN MP_TAC(ISPEC `s:real^N->bool` AFF_DIM) THEN
3964   STRIP_TAC THEN ASM_REWRITE_TAC[INT_LE_SUB_LADD; INT_ADD_LINV; INT_POS]);;
3965
3966 let AFF_DIM_SUBSET = prove
3967  (`!s t:real^N->bool. s SUBSET t ==> aff_dim s <= aff_dim t`,
3968   MATCH_MP_TAC SET_PROVE_CASES THEN REWRITE_TAC[AFF_DIM_GE; AFF_DIM_EMPTY] THEN
3969   GEOM_ORIGIN_TAC `a:real^N` THEN REPEAT STRIP_TAC THEN
3970   SUBGOAL_THEN `(vec 0:real^N) IN t` ASSUME_TAC THENL
3971    [ASM SET_TAC[]; ALL_TAC] THEN
3972   ASM_SIMP_TAC[AFF_DIM_DIM_0; IN_INSERT; HULL_INC; INT_OF_NUM_LE; DIM_SUBSET]);;
3973
3974 let AFF_DIM_LE_DIM = prove
3975  (`!s:real^N->bool. aff_dim s <= &(dim s)`,
3976   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM DIM_SPAN] THEN
3977   ASM_SIMP_TAC[GSYM AFF_DIM_DIM_SUBSPACE; SUBSPACE_SPAN] THEN
3978   MATCH_MP_TAC AFF_DIM_SUBSET THEN REWRITE_TAC[SPAN_INC]);;
3979
3980 let AFF_DIM_CONVEX_HULL = prove
3981  (`!s:real^N->bool. aff_dim(convex hull s) = aff_dim s`,
3982   GEN_TAC THEN MATCH_MP_TAC(INT_ARITH
3983    `!c:int. c = a /\ a <= b /\ b <= c ==> b = a`) THEN
3984   EXISTS_TAC `aff_dim(affine hull s:real^N->bool)` THEN
3985   SIMP_TAC[AFF_DIM_AFFINE_HULL; AFF_DIM_SUBSET; HULL_SUBSET;
3986            CONVEX_HULL_SUBSET_AFFINE_HULL]);;
3987
3988 let AFF_DIM_CLOSURE = prove
3989  (`!s:real^N->bool. aff_dim(closure s) = aff_dim s`,
3990   GEN_TAC THEN MATCH_MP_TAC(INT_ARITH
3991    `!h. h = s /\ s <= c /\ c <= h ==> c:int = s`) THEN
3992   EXISTS_TAC `aff_dim(affine hull s:real^N->bool)` THEN
3993   REPEAT CONJ_TAC THENL
3994    [REWRITE_TAC[AFF_DIM_AFFINE_HULL];
3995     MATCH_MP_TAC AFF_DIM_SUBSET THEN REWRITE_TAC[CLOSURE_SUBSET];
3996     MATCH_MP_TAC AFF_DIM_SUBSET THEN
3997     MATCH_MP_TAC CLOSURE_MINIMAL THEN
3998     REWRITE_TAC[CLOSED_AFFINE_HULL; HULL_SUBSET]]);;
3999
4000 let AFF_DIM_2 = prove
4001  (`!a b:real^N. aff_dim {a,b} = if a = b then &0 else &1`,
4002   REPEAT GEN_TAC THEN COND_CASES_TAC THENL
4003    [ASM_REWRITE_TAC[INSERT_AC; AFF_DIM_SING]; ALL_TAC] THEN
4004   MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `&(CARD {a:real^N,b}) - &1:int` THEN
4005   ASM_SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; AFFINE_INDEPENDENT_2] THEN
4006   ASM_SIMP_TAC[CARD_CLAUSES; FINITE_RULES; IN_INSERT; NOT_IN_EMPTY] THEN
4007   CONV_TAC NUM_REDUCE_CONV THEN INT_ARITH_TAC);;
4008
4009 let AFF_DIM_EQ_MINUS1 = prove
4010  (`!s:real^N->bool. aff_dim s = -- &1 <=> s = {}`,
4011   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[AFF_DIM_EMPTY] THEN
4012   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4013   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN
4014   X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
4015   MATCH_MP_TAC(INT_ARITH `&0:int <= n ==> ~(n = -- &1)`) THEN
4016   MATCH_MP_TAC INT_LE_TRANS THEN EXISTS_TAC `aff_dim {a:real^N}` THEN
4017   ASM_SIMP_TAC[AFF_DIM_SUBSET; SING_SUBSET] THEN
4018   REWRITE_TAC[AFF_DIM_SING; INT_LE_REFL]);;
4019
4020 let AFF_DIM_POS_LE = prove
4021  (`!s:real^N->bool. &0 <= aff_dim s <=> ~(s = {})`,
4022   GEN_TAC THEN REWRITE_TAC[GSYM AFF_DIM_EQ_MINUS1] THEN
4023   MP_TAC(ISPEC `s:real^N->bool` AFF_DIM_GE) THEN INT_ARITH_TAC);;
4024
4025 let AFF_DIM_EQ_0 = prove
4026  (`!s:real^N->bool. aff_dim s = &0 <=> ?a. s = {a}`,
4027   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[AFF_DIM_SING; LEFT_IMP_EXISTS_THM] THEN
4028   ASM_CASES_TAC `s:real^N->bool = {}` THEN ASM_REWRITE_TAC[AFF_DIM_EMPTY] THEN
4029   CONV_TAC INT_REDUCE_CONV THEN DISCH_TAC THEN
4030   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
4031   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
4032   MATCH_MP_TAC(SET_RULE
4033    `(!b. ~(b = a) /\ {a,b} SUBSET s ==> F) ==> a IN s ==> s = {a}`) THEN
4034   X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
4035   FIRST_ASSUM(MP_TAC o MATCH_MP AFF_DIM_SUBSET) THEN
4036   MP_TAC(ISPECL [`a:real^N`; `b:real^N`] AFF_DIM_2) THEN
4037   ASM_SIMP_TAC[] THEN INT_ARITH_TAC);;
4038
4039 let CONNECTED_IMP_PERFECT_AFF_DIM = prove
4040  (`!s x:real^N.
4041         connected s /\ ~(aff_dim s = &0) /\ x IN s ==> x limit_point_of s`,
4042   REWRITE_TAC[AFF_DIM_EQ_0; CONNECTED_IMP_PERFECT]);;
4043
4044 let AFF_DIM_UNIV = prove
4045  (`aff_dim(:real^N) = &(dimindex(:N))`,
4046   SIMP_TAC[AFF_DIM_DIM_SUBSPACE; SUBSPACE_UNIV; DIM_UNIV]);;
4047
4048 let AFF_DIM_EQ_AFFINE_HULL = prove
4049  (`!s t:real^N->bool.
4050         s SUBSET t /\ aff_dim t <= aff_dim s
4051         ==> affine hull s = affine hull t`,
4052   MATCH_MP_TAC SET_PROVE_CASES THEN
4053   SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1; AFF_DIM_GE;
4054            INT_ARITH `a:int <= x ==> (x <= a <=> x = a)`] THEN
4055   X_GEN_TAC `a:real^N` THEN GEOM_ORIGIN_TAC `a:real^N` THEN
4056   SIMP_TAC[INSERT_SUBSET; IMP_CONJ; AFF_DIM_DIM_0; IN_INSERT; DIM_EQ_SPAN;
4057            HULL_INC; AFFINE_HULL_EQ_SPAN; INT_OF_NUM_LE]);;
4058
4059 let AFF_DIM_SUMS_INTER = prove
4060  (`!s t:real^N->bool.
4061         affine s /\ affine t /\ ~(s INTER t = {})
4062         ==> aff_dim {x + y | x IN s /\ y IN t} =
4063                 (aff_dim s + aff_dim t) - aff_dim(s INTER t)`,
4064   REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> c ==> a /\ b ==> d`] THEN
4065   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN
4066   GEN_REWRITE_TAC BINDER_CONV [SWAP_FORALL_THM] THEN
4067   GEN_REWRITE_TAC I [SWAP_FORALL_THM] THEN X_GEN_TAC `a:real^N` THEN
4068   GEOM_ORIGIN_TAC `a:real^N` THEN
4069   REWRITE_TAC[VECTOR_ARITH `(a + x) + (a + y):real^N = &2 % a + (x + y)`] THEN
4070   ONCE_REWRITE_TAC[SET_RULE `{a + x + y:real^N | x IN s /\ y IN t} =
4071                             IMAGE (\x. a + x) {x + y | x IN s /\ y IN t}`] THEN
4072   REWRITE_TAC[AFF_DIM_TRANSLATION_EQ; IN_INTER] THEN
4073   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `t:real^N->bool`] THEN STRIP_TAC THEN
4074   STRIP_TAC THEN
4075   SUBGOAL_THEN `(vec 0:real^N) IN {x + y | x IN s /\ y IN t}` ASSUME_TAC THENL
4076    [REWRITE_TAC[IN_ELIM_THM] THEN REPEAT(EXISTS_TAC `vec 0:real^N`) THEN
4077     ASM_REWRITE_TAC[VECTOR_ADD_LID];
4078     ALL_TAC] THEN
4079   ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; IN_INTER] THEN
4080   REWRITE_TAC[INT_EQ_SUB_LADD; INT_OF_NUM_ADD; INT_OF_NUM_EQ] THEN
4081   MATCH_MP_TAC DIM_SUMS_INTER THEN ASM_SIMP_TAC[AFFINE_IMP_SUBSPACE]);;
4082
4083 let AFF_DIM_PSUBSET = prove
4084  (`!s t. (affine hull s) PSUBSET (affine hull t) ==> aff_dim s < aff_dim t`,
4085   ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4086   SIMP_TAC[PSUBSET; AFF_DIM_SUBSET; INT_LT_LE] THEN
4087   MESON_TAC[INT_EQ_IMP_LE; AFF_DIM_EQ_AFFINE_HULL; HULL_HULL]);;
4088
4089 let AFF_DIM_EQ_FULL = prove
4090  (`!s. aff_dim s = &(dimindex(:N)) <=> affine hull s = (:real^N)`,
4091   GEN_TAC THEN EQ_TAC THENL
4092    [DISCH_TAC THEN ONCE_REWRITE_TAC[GSYM AFFINE_HULL_UNIV] THEN
4093     MATCH_MP_TAC AFF_DIM_EQ_AFFINE_HULL THEN
4094     ASM_REWRITE_TAC[SUBSET_UNIV; AFF_DIM_UNIV; INT_LE_REFL];
4095     ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4096     SIMP_TAC[AFF_DIM_UNIV]]);;
4097
4098 let AFF_DIM_LE_UNIV = prove
4099  (`!s:real^N->bool. aff_dim s <= &(dimindex(:N))`,
4100   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_UNIV] THEN
4101   MATCH_MP_TAC AFF_DIM_SUBSET THEN REWRITE_TAC[SUBSET_UNIV]);;
4102
4103 let AFFINE_INDEPENDENT_IFF_CARD = prove
4104  (`!s:real^N->bool.
4105         ~affine_dependent s <=> FINITE s /\ aff_dim s = &(CARD s) - &1`,
4106   GEN_TAC THEN EQ_TAC THEN
4107   SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; AFFINE_INDEPENDENT_IMP_FINITE] THEN
4108   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4109   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[] THEN DISCH_TAC THEN
4110   X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC
4111    (ISPEC `s:real^N->bool` AFFINE_BASIS_EXISTS) THEN
4112   MATCH_MP_TAC(ARITH_RULE `!b:int. a <= b - &1 /\ b < s ==> ~(a = s - &1)`) THEN
4113   EXISTS_TAC `&(CARD(b:real^N->bool)):int` THEN CONJ_TAC THENL
4114    [ASM_MESON_TAC[AFF_DIM_LE_CARD; FINITE_SUBSET; AFF_DIM_AFFINE_HULL];
4115     REWRITE_TAC[INT_OF_NUM_LT] THEN MATCH_MP_TAC CARD_PSUBSET THEN
4116     ASM_REWRITE_TAC[PSUBSET] THEN ASM_MESON_TAC[]]);;
4117
4118 let AFFINE_HULL_CONVEX_INTER_NONEMPTY_INTERIOR = prove
4119  (`!s t:real^N->bool.
4120         convex s /\ ~(s INTER interior t = {})
4121         ==> affine hull (s INTER t) = affine hull s`,
4122   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; RIGHT_AND_EXISTS_THM;
4123               LEFT_IMP_EXISTS_THM] THEN
4124   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `t:real^N->bool`; `a:real^N`] THEN
4125   GEOM_ORIGIN_TAC `a:real^N` THEN REWRITE_TAC[IN_INTER] THEN
4126   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
4127   SIMP_TAC[HULL_MONO; INTER_SUBSET] THEN
4128   SIMP_TAC[SUBSET_HULL; AFFINE_AFFINE_HULL] THEN
4129   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (SIMP_RULE[SUBSET] INTERIOR_SUBSET)) THEN
4130   ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC; IN_INTER] THEN
4131   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR_CBALL]) THEN
4132   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; SUBSET; IN_CBALL_0] THEN
4133   X_GEN_TAC `e:real` THEN STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_UNIV] THEN
4134   X_GEN_TAC `x:real^N` THEN ASM_CASES_TAC `x:real^N = vec 0` THEN
4135   ASM_SIMP_TAC[SPAN_SUPERSET; IN_INTER] THEN DISCH_TAC THEN
4136   ABBREV_TAC `k = min (&1 / &2) (e / norm(x:real^N))` THEN
4137   SUBGOAL_THEN `&0 < k /\ k < &1` STRIP_ASSUME_TAC THENL
4138    [EXPAND_TAC "k" THEN
4139     ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_DIV; NORM_POS_LT; REAL_MIN_LT] THEN
4140     CONV_TAC REAL_RAT_REDUCE_CONV;
4141     ALL_TAC] THEN
4142   SUBGOAL_THEN `x:real^N = inv k % k % x` SUBST1_TAC THENL
4143    [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID;
4144                  REAL_LT_IMP_NZ];
4145     ALL_TAC] THEN
4146   MATCH_MP_TAC SPAN_MUL THEN MATCH_MP_TAC SPAN_SUPERSET THEN
4147   REWRITE_TAC[IN_INTER] THEN CONJ_TAC THENL
4148    [ONCE_REWRITE_TAC[VECTOR_ARITH
4149      `k % x:real^N = (&1 - k) % vec 0 + k % x`] THEN
4150     MATCH_MP_TAC IN_CONVEX_SET THEN ASM_SIMP_TAC[REAL_LT_IMP_LE];
4151     FIRST_X_ASSUM MATCH_MP_TAC THEN EXPAND_TAC "k" THEN
4152     ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
4153     ASM_REAL_ARITH_TAC]);;
4154
4155 let AFFINE_HULL_CONVEX_INTER_OPEN = prove
4156  (`!s t:real^N->bool.
4157         convex s /\ open t /\ ~(s INTER t = {})
4158         ==> affine hull (s INTER t) = affine hull s`,
4159   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_INTER_NONEMPTY_INTERIOR; INTERIOR_OPEN]);;
4160
4161 let AFFINE_HULL_AFFINE_INTER_NONEMPTY_INTERIOR = prove
4162  (`!s t:real^N->bool.
4163         affine s /\ ~(s INTER interior t = {})
4164         ==> affine hull (s INTER t) = s`,
4165   SIMP_TAC[AFFINE_HULL_CONVEX_INTER_NONEMPTY_INTERIOR; AFFINE_IMP_CONVEX;
4166            HULL_P]);;
4167
4168 let AFFINE_HULL_AFFINE_INTER_OPEN = prove
4169  (`!s t:real^N->bool.
4170         affine s /\ open t /\ ~(s INTER t = {})
4171         ==> affine hull (s INTER t) = s`,
4172   SIMP_TAC[AFFINE_HULL_AFFINE_INTER_NONEMPTY_INTERIOR; INTERIOR_OPEN]);;
4173
4174 let CONVEX_AND_AFFINE_INTER_OPEN = prove
4175  (`!s t u:real^N->bool.
4176         convex s /\ affine t /\ open u /\
4177         s INTER u = t INTER u /\ ~(s INTER u = {})
4178         ==> affine hull s = t`,
4179   REPEAT STRIP_TAC THEN
4180   MATCH_MP_TAC(MESON[] `!u v. x = u /\ u = v /\ v = y ==> x = y`) THEN
4181   MAP_EVERY EXISTS_TAC
4182    [`affine hull (s INTER u:real^N->bool)`;
4183     `affine hull t:real^N->bool`] THEN
4184   REPEAT CONJ_TAC THENL
4185    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC AFFINE_HULL_CONVEX_INTER_OPEN THEN
4186     ASM_REWRITE_TAC[];
4187     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC AFFINE_HULL_CONVEX_INTER_OPEN THEN
4188     ASM_SIMP_TAC[AFFINE_IMP_CONVEX] THEN ASM SET_TAC[];
4189     ASM_REWRITE_TAC[AFFINE_HULL_EQ]]);;
4190
4191 let AFFINE_HULL_CONVEX_INTER_OPEN_IN = prove
4192  (`!s t:real^N->bool.
4193         convex s /\ open_in (subtopology euclidean (affine hull s)) t /\
4194         ~(s INTER t = {})
4195         ==> affine hull (s INTER t) = affine hull s`,
4196   REPEAT STRIP_TAC THEN
4197   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
4198   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
4199   ASM_SIMP_TAC[SET_RULE `s SUBSET t ==> s INTER t INTER u = s INTER u`;
4200                HULL_SUBSET] THEN
4201   MATCH_MP_TAC AFFINE_HULL_CONVEX_INTER_OPEN THEN ASM SET_TAC[]);;
4202
4203 let AFFINE_HULL_AFFINE_INTER_OPEN_IN = prove
4204  (`!s t:real^N->bool.
4205         affine s /\ open_in (subtopology euclidean s) t /\ ~(s INTER t = {})
4206         ==> affine hull (s INTER t) = s`,
4207   REPEAT STRIP_TAC THEN
4208   MP_TAC(ISPECL [`affine hull s:real^N->bool`; `t:real^N->bool`]
4209         AFFINE_HULL_CONVEX_INTER_OPEN_IN) THEN
4210   ASM_SIMP_TAC[HULL_HULL; AFFINE_IMP_CONVEX; AFFINE_AFFINE_HULL; HULL_P]);;
4211
4212 let AFFINE_HULL_OPEN_IN = prove
4213  (`!s t:real^N->bool.
4214         open_in (subtopology euclidean (affine hull t)) s /\ ~(s = {})
4215         ==> affine hull s = affine hull t`,
4216   REPEAT STRIP_TAC THEN
4217   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
4218   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
4219   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC AFFINE_HULL_AFFINE_INTER_OPEN THEN
4220   REWRITE_TAC[AFFINE_AFFINE_HULL] THEN ASM SET_TAC[]);;
4221
4222 let AFFINE_HULL_OPEN = prove
4223  (`!s. open s /\ ~(s = {}) ==> affine hull s = (:real^N)`,
4224   GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4225   SUBST1_TAC(SET_RULE `s = (:real^N) INTER s`) THEN
4226   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_INTER_OPEN; CONVEX_UNIV] THEN
4227   REWRITE_TAC[AFFINE_HULL_UNIV]);;
4228
4229 let AFFINE_HULL_NONEMPTY_INTERIOR = prove
4230  (`!s. ~(interior s = {}) ==> affine hull s = (:real^N)`,
4231   REPEAT STRIP_TAC THEN
4232   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
4233   EXISTS_TAC `affine hull (interior s:real^N->bool)` THEN
4234   SIMP_TAC[HULL_MONO; INTERIOR_SUBSET] THEN
4235   ASM_SIMP_TAC[AFFINE_HULL_OPEN; OPEN_INTERIOR]);;
4236
4237 let AFF_DIM_OPEN = prove
4238  (`!s:real^N->bool. open s /\ ~(s = {}) ==> aff_dim s = &(dimindex(:N))`,
4239   SIMP_TAC[AFF_DIM_EQ_FULL; AFFINE_HULL_OPEN]);;
4240
4241 let AFF_DIM_NONEMPTY_INTERIOR = prove
4242  (`!s:real^N->bool. ~(interior s = {}) ==> aff_dim s = &(dimindex(:N))`,
4243   SIMP_TAC[AFF_DIM_EQ_FULL; AFFINE_HULL_NONEMPTY_INTERIOR]);;
4244
4245 let SPAN_OPEN = prove
4246  (`!s. open s /\ ~(s = {}) ==> span s = (:real^N)`,
4247   REPEAT STRIP_TAC THEN
4248   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
4249   EXISTS_TAC `affine hull s:real^N->bool` THEN
4250   ASM_SIMP_TAC[AFFINE_HULL_OPEN; AFFINE_HULL_SUBSET_SPAN]);;
4251
4252 let DIM_OPEN = prove
4253  (`!s:real^N->bool. open s /\ ~(s = {}) ==> dim s = dimindex(:N)`,
4254   SIMP_TAC[DIM_EQ_FULL; SPAN_OPEN]);;
4255
4256 let AFF_DIM_INSERT = prove
4257  (`!a:real^N s.
4258         aff_dim (a INSERT s) =
4259         if a IN affine hull s then aff_dim s else aff_dim s + &1`,
4260   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN MATCH_MP_TAC SET_PROVE_CASES THEN
4261   SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_SING; AFFINE_HULL_EMPTY; NOT_IN_EMPTY] THEN
4262   CONV_TAC INT_REDUCE_CONV THEN REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN
4263   MAP_EVERY X_GEN_TAC [`b:real^N`; `s:real^N->bool`; `a:real^N`] THEN
4264   GEOM_ORIGIN_TAC `b:real^N` THEN
4265   SIMP_TAC[AFFINE_HULL_EQ_SPAN; AFF_DIM_DIM_0; HULL_INC; IN_INSERT] THEN
4266   MAP_EVERY X_GEN_TAC [`a:real^N`; `s:real^N->bool`] THEN
4267   DISCH_THEN(K ALL_TAC) THEN
4268   SPEC_TAC(`(vec 0:real^N) INSERT s`,`s:real^N->bool`) THEN
4269   SIMP_TAC[DIM_INSERT; INT_OF_NUM_ADD] THEN MESON_TAC[]);;
4270
4271 let AFFINE_BOUNDED_EQ_TRIVIAL = prove
4272  (`!s:real^N->bool.
4273         affine s ==> (bounded s <=> s = {} \/ ?a. s = {a})`,
4274   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
4275   ASM_REWRITE_TAC[BOUNDED_EMPTY] THEN
4276   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
4277   DISCH_THEN(X_CHOOSE_THEN `b:real^N` MP_TAC) THEN
4278   GEOM_ORIGIN_TAC `b:real^N` THEN SIMP_TAC[AFFINE_EQ_SUBSPACE] THEN
4279   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[SUBSPACE_BOUNDED_EQ_TRIVIAL] THEN
4280   FIRST_ASSUM(MP_TAC o MATCH_MP SUBSPACE_0) THEN SET_TAC[]);;
4281
4282 let AFFINE_BOUNDED_EQ_LOWDIM = prove
4283  (`!s:real^N->bool.
4284         affine s ==> (bounded s <=> aff_dim s <= &0)`,
4285   SIMP_TAC[AFF_DIM_GE; INT_ARITH
4286    `--(&1):int <= x ==> (x <= &0 <=> x = --(&1) \/ x = &0)`] THEN
4287   SIMP_TAC[AFF_DIM_EQ_0; AFF_DIM_EQ_MINUS1; AFFINE_BOUNDED_EQ_TRIVIAL]);;
4288
4289 let COLLINEAR_AFF_DIM = prove
4290  (`!s:real^N->bool. collinear s <=> aff_dim s <= &1`,
4291   GEN_TAC THEN EQ_TAC THENL
4292    [REWRITE_TAC[COLLINEAR_AFFINE_HULL; LEFT_IMP_EXISTS_THM] THEN
4293     MAP_EVERY X_GEN_TAC [`u:real^N`; `v:real^N`] THEN STRIP_TAC THEN
4294     MATCH_MP_TAC INT_LE_TRANS THEN EXISTS_TAC `aff_dim{u:real^N,v}` THEN
4295     CONJ_TAC THENL
4296      [ASM_MESON_TAC[AFF_DIM_SUBSET; AFF_DIM_AFFINE_HULL];
4297       MATCH_MP_TAC INT_LE_TRANS THEN
4298       EXISTS_TAC `&(CARD{u:real^N,v}) - &1:int` THEN
4299       SIMP_TAC[AFF_DIM_LE_CARD; FINITE_INSERT; FINITE_EMPTY] THEN
4300       REWRITE_TAC[INT_ARITH `x - &1:int <= &1 <=> x <= &2`; INT_OF_NUM_LE] THEN
4301       SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN ARITH_TAC];
4302     ONCE_REWRITE_TAC[GSYM COLLINEAR_AFFINE_HULL_COLLINEAR;
4303                      GSYM AFF_DIM_AFFINE_HULL] THEN
4304     MP_TAC(ISPEC `s:real^N->bool` AFFINE_BASIS_EXISTS) THEN
4305     DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` (STRIP_ASSUME_TAC o GSYM)) THEN
4306     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I
4307      [AFFINE_INDEPENDENT_IFF_CARD]) THEN
4308     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4309     ASM_REWRITE_TAC[COLLINEAR_AFFINE_HULL_COLLINEAR;
4310                     AFF_DIM_AFFINE_HULL] THEN
4311     REWRITE_TAC[INT_ARITH `x - &1:int <= &1 <=> x <= &2`; INT_OF_NUM_LE] THEN
4312     ASM_SIMP_TAC[COLLINEAR_SMALL]]);;
4313
4314 let HOMEOMORPHIC_AFFINE_SETS = prove
4315  (`!s:real^M->bool t:real^N->bool.
4316         affine s /\ affine t /\ aff_dim s = aff_dim t ==> s homeomorphic t`,
4317   REPEAT GEN_TAC THEN
4318   ASM_CASES_TAC `t:real^N->bool = {}` THEN
4319   ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1; HOMEOMORPHIC_EMPTY] THEN
4320   POP_ASSUM MP_TAC THEN
4321   GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o ONCE_DEPTH_CONV) [EQ_SYM_EQ] THEN
4322   ASM_CASES_TAC `s:real^M->bool = {}` THEN
4323   ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1; HOMEOMORPHIC_EMPTY] THEN
4324   POP_ASSUM MP_TAC THEN REWRITE_TAC
4325    [GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM; RIGHT_IMP_FORALL_THM] THEN
4326   MAP_EVERY X_GEN_TAC [`a:real^M`; `b:real^N`] THEN
4327   GEOM_ORIGIN_TAC `a:real^M` THEN GEOM_ORIGIN_TAC `b:real^N` THEN
4328   SIMP_TAC[AFFINE_EQ_SUBSPACE; AFF_DIM_DIM_0; HULL_INC; INT_OF_NUM_EQ] THEN
4329   MESON_TAC[HOMEOMORPHIC_SUBSPACES]);;
4330
4331 let AFF_DIM_OPEN_IN = prove
4332  (`!s t:real^N->bool.
4333         ~(s = {}) /\ open_in (subtopology euclidean t) s /\ affine t
4334         ==> aff_dim s = aff_dim t`,
4335   REPEAT GEN_TAC THEN
4336   REWRITE_TAC[IMP_CONJ; GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN
4337   X_GEN_TAC `a:real^N` THEN GEOM_ORIGIN_TAC `a:real^N` THEN
4338   REPEAT GEN_TAC THEN STRIP_TAC THEN DISCH_TAC THEN
4339   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
4340   SUBGOAL_THEN `(vec 0:real^N) IN t` ASSUME_TAC THENL
4341    [ASM SET_TAC[]; ALL_TAC] THEN
4342   ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; AFFINE_EQ_SUBSPACE] THEN
4343   DISCH_TAC THEN AP_TERM_TAC THEN
4344   ASM_SIMP_TAC[GSYM LE_ANTISYM; DIM_SUBSET] THEN
4345   SUBGOAL_THEN `?e. &0 < e /\ cball(vec 0:real^N,e) INTER t SUBSET s`
4346   MP_TAC THENL
4347    [FIRST_X_ASSUM(STRIP_ASSUME_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
4348     FIRST_X_ASSUM(MP_TAC o SPEC `vec 0:real^N` o
4349       GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
4350     ASM SET_TAC[];
4351     REWRITE_TAC[SUBSET; IN_INTER; IN_CBALL_0] THEN
4352     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC)] THEN
4353   FIRST_ASSUM(MP_TAC o MATCH_MP ORTHONORMAL_BASIS_SUBSPACE) THEN
4354   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC) THEN
4355   MP_TAC(ISPECL [`s:real^N->bool`; `IMAGE (\x:real^N. e % x) b`]
4356    INDEPENDENT_CARD_LE_DIM) THEN
4357   RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
4358   ASM_SIMP_TAC[CARD_IMAGE_INJ; VECTOR_MUL_LCANCEL; REAL_LT_IMP_NZ] THEN
4359   ANTS_TAC THENL [REWRITE_TAC[SUBSET]; MESON_TAC[]] THEN CONJ_TAC THENL
4360    [REWRITE_TAC[FORALL_IN_IMAGE] THEN REPEAT STRIP_TAC THEN
4361     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[NORM_MUL] THEN
4362     CONJ_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC SUBSPACE_MUL] THEN
4363     ASM SET_TAC[];
4364     MATCH_MP_TAC INDEPENDENT_INJECTIVE_IMAGE THEN
4365     ASM_SIMP_TAC[VECTOR_MUL_LCANCEL; REAL_LT_IMP_NZ; LINEAR_SCALING]]);;
4366
4367 let DIM_OPEN_IN = prove
4368  (`!s t:real^N->bool.
4369         ~(s = {}) /\ open_in (subtopology euclidean t) s /\ subspace t
4370         ==> dim s = dim t`,
4371   REPEAT STRIP_TAC THEN
4372   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
4373   ASM_SIMP_TAC[GSYM LE_ANTISYM; DIM_SUBSET] THEN
4374   REWRITE_TAC[GSYM INT_OF_NUM_LE] THEN
4375   MATCH_MP_TAC INT_LE_TRANS THEN EXISTS_TAC `aff_dim(s:real^N->bool)` THEN
4376   REWRITE_TAC[AFF_DIM_LE_DIM] THEN ASM_SIMP_TAC[GSYM AFF_DIM_DIM_SUBSPACE] THEN
4377   MATCH_MP_TAC INT_EQ_IMP_LE THEN CONV_TAC SYM_CONV THEN
4378   MATCH_MP_TAC AFF_DIM_OPEN_IN THEN ASM_SIMP_TAC[SUBSPACE_IMP_AFFINE]);;
4379
4380 let AFF_DIM_CONVEX_INTER_NONEMPTY_INTERIOR = prove
4381  (`!s t:real^N->bool.
4382         convex s /\ ~(s INTER interior t = {})
4383         ==> aff_dim(s INTER t) = aff_dim s`,
4384   ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4385   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_INTER_NONEMPTY_INTERIOR] THEN
4386   REWRITE_TAC[AFF_DIM_AFFINE_HULL]);;
4387
4388 let AFF_DIM_CONVEX_INTER_OPEN = prove
4389  (`!s t:real^N->bool.
4390         convex s /\ open t /\ ~(s INTER t = {})
4391         ==> aff_dim(s INTER t) = aff_dim s`,
4392   ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4393   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_INTER_OPEN] THEN
4394   REWRITE_TAC[AFF_DIM_AFFINE_HULL]);;
4395
4396 let AFFINE_HULL_HALFSPACE_LT = prove
4397  (`!a b. affine hull {x | a dot x < b} =
4398          if a = vec 0 /\ b <= &0 then {} else (:real^N)`,
4399   REPEAT GEN_TAC THEN COND_CASES_TAC THEN
4400   ASM_SIMP_TAC[AFFINE_HULL_EQ_EMPTY; HALFSPACE_EQ_EMPTY_LT;
4401                AFFINE_HULL_OPEN; OPEN_HALFSPACE_LT]);;
4402
4403 let AFFINE_HULL_HALFSPACE_LE = prove
4404  (`!a b. affine hull {x | a dot x <= b} =
4405          if a = vec 0 /\ b < &0 then {} else (:real^N)`,
4406   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THENL
4407    [ASM_SIMP_TAC[DOT_LZERO; SET_RULE `{x | p} = if p then UNIV else {}`] THEN
4408     COND_CASES_TAC THEN ASM_SIMP_TAC[AFFINE_HULL_EMPTY; AFFINE_HULL_UNIV] THEN
4409     COND_CASES_TAC THEN REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
4410     ASM_SIMP_TAC[GSYM CLOSURE_HALFSPACE_LT; AFFINE_HULL_CLOSURE] THEN
4411     ASM_REWRITE_TAC[AFFINE_HULL_HALFSPACE_LT]]);;
4412
4413 let AFFINE_HULL_HALFSPACE_GT = prove
4414  (`!a b. affine hull {x | a dot x > b} =
4415          if a = vec 0 /\ b >= &0 then {} else (:real^N)`,
4416   REPEAT GEN_TAC THEN COND_CASES_TAC THEN
4417   ASM_SIMP_TAC[AFFINE_HULL_EQ_EMPTY; HALFSPACE_EQ_EMPTY_GT;
4418                AFFINE_HULL_OPEN; OPEN_HALFSPACE_GT]);;
4419
4420 let AFFINE_HULL_HALFSPACE_GE = prove
4421  (`!a b. affine hull {x | a dot x >= b} =
4422          if a = vec 0 /\ b > &0 then {} else (:real^N)`,
4423   REPEAT GEN_TAC THEN
4424   MP_TAC(ISPECL [`--a:real^N`; `--b:real`] AFFINE_HULL_HALFSPACE_LE) THEN
4425   SIMP_TAC[real_ge; DOT_LNEG; REAL_LE_NEG2; VECTOR_NEG_EQ_0] THEN
4426   REWRITE_TAC[REAL_ARITH `--b < &0 <=> b > &0`]);;
4427
4428 let AFF_DIM_HALFSPACE_LT = prove
4429  (`!a:real^N b.
4430         aff_dim {x | a dot x < b} =
4431         if a = vec 0 /\ b <= &0 then --(&1) else &(dimindex(:N))`,
4432   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4433   SIMP_TAC[AFFINE_HULL_HALFSPACE_LT] THEN COND_CASES_TAC THEN
4434   ASM_REWRITE_TAC[AFF_DIM_EMPTY; AFF_DIM_UNIV]);;
4435
4436 let AFF_DIM_HALFSPACE_LE = prove
4437  (`!a:real^N b.
4438         aff_dim {x | a dot x <= b} =
4439         if a = vec 0 /\ b < &0 then --(&1) else &(dimindex(:N))`,
4440   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4441   SIMP_TAC[AFFINE_HULL_HALFSPACE_LE] THEN COND_CASES_TAC THEN
4442   ASM_REWRITE_TAC[AFF_DIM_EMPTY; AFF_DIM_UNIV]);;
4443
4444 let AFF_DIM_HALFSPACE_GT = prove
4445  (`!a:real^N b.
4446         aff_dim {x | a dot x > b} =
4447         if a = vec 0 /\ b >= &0 then --(&1) else &(dimindex(:N))`,
4448   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4449   SIMP_TAC[AFFINE_HULL_HALFSPACE_GT] THEN COND_CASES_TAC THEN
4450   ASM_REWRITE_TAC[AFF_DIM_EMPTY; AFF_DIM_UNIV]);;
4451
4452 let AFF_DIM_HALFSPACE_GE = prove
4453  (`!a:real^N b.
4454         aff_dim {x | a dot x >= b} =
4455         if a = vec 0 /\ b > &0 then --(&1) else &(dimindex(:N))`,
4456   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
4457   SIMP_TAC[AFFINE_HULL_HALFSPACE_GE] THEN COND_CASES_TAC THEN
4458   ASM_REWRITE_TAC[AFF_DIM_EMPTY; AFF_DIM_UNIV]);;
4459
4460 let CHOOSE_AFFINE_SUBSET = prove
4461  (`!s:real^N->bool d.
4462         affine s /\ --(&1) <= d /\ d <= aff_dim s
4463         ==> ?t. affine t /\ t SUBSET s /\ aff_dim t = d`,
4464   REPEAT GEN_TAC THEN ASM_CASES_TAC `d:int = --(&1)` THENL
4465    [STRIP_TAC THEN EXISTS_TAC `{}:real^N->bool` THEN
4466     ASM_REWRITE_TAC[EMPTY_SUBSET; AFFINE_EMPTY; AFF_DIM_EMPTY];
4467     ASM_SIMP_TAC[INT_ARITH
4468      `~(d:int = --(&1)) ==> (--(&1) <= d <=> &0 <= d)`] THEN
4469     POP_ASSUM(K ALL_TAC)] THEN
4470   ASM_CASES_TAC `s:real^N->bool = {}` THENL
4471    [ASM_REWRITE_TAC[AFF_DIM_EMPTY] THEN INT_ARITH_TAC;
4472     POP_ASSUM MP_TAC] THEN
4473   GEN_REWRITE_TAC LAND_CONV [GSYM MEMBER_NOT_EMPTY] THEN
4474   DISCH_THEN(X_CHOOSE_THEN `a:real^N` MP_TAC) THEN
4475   GEOM_ORIGIN_TAC `a:real^N` THEN
4476   SIMP_TAC[IMP_CONJ; AFF_DIM_DIM_SUBSPACE; AFFINE_EQ_SUBSPACE] THEN
4477   REPEAT GEN_TAC THEN DISCH_TAC THEN DISCH_TAC THEN
4478   REWRITE_TAC[GSYM INT_OF_NUM_EXISTS] THEN
4479   DISCH_THEN(X_CHOOSE_THEN `n:num` SUBST1_TAC) THEN
4480   REWRITE_TAC[INT_OF_NUM_LE] THEN DISCH_TAC THEN
4481   MP_TAC(ISPECL [`s:real^N->bool`; `n:num`]
4482         CHOOSE_SUBSPACE_OF_SUBSPACE) THEN
4483   ASM_SIMP_TAC[SPAN_OF_SUBSPACE] THEN
4484   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real^N->bool` THEN
4485   ASM_SIMP_TAC[AFF_DIM_DIM_SUBSPACE; SUBSPACE_IMP_AFFINE]);;
4486
4487 (* ------------------------------------------------------------------------- *)
4488 (* Existence of a rigid transform between congruent sets.                    *)
4489 (* ------------------------------------------------------------------------- *)
4490
4491 let RIGID_TRANSFORMATION_BETWEEN_CONGRUENT_SETS = prove
4492  (`!x:A->real^N y:A->real^N s.
4493         (!i j. i IN s /\ j IN s ==> dist(x i,x j) = dist(y i,y j))
4494         ==> ?a f. orthogonal_transformation f /\
4495                   !i. i IN s ==> y i = a + f(x i)`,
4496   let lemma = prove
4497    (`!x:(real^N)^M y:(real^N)^M.
4498           (!i j. 1 <= i /\ i <= dimindex(:M) /\
4499                  1 <= j /\ j <= dimindex(:M)
4500                  ==> dist(x$i,x$j) = dist(y$i,y$j))
4501           ==> ?a f. orthogonal_transformation f /\
4502                     !i. 1 <= i /\ i <= dimindex(:M)
4503                         ==> y$i = a + f(x$i)`,
4504     REPEAT STRIP_TAC THEN
4505     ABBREV_TAC `(X:real^M^N) = lambda i j. (x:real^N^M)$j$i - x$1$i` THEN
4506     ABBREV_TAC `(Y:real^M^N) = lambda i j. (y:real^N^M)$j$i - y$1$i` THEN
4507     SUBGOAL_THEN `transp(X:real^M^N) ** X = transp(Y:real^M^N) ** Y`
4508     ASSUME_TAC THENL
4509      [REWRITE_TAC[MATRIX_MUL_LTRANSP_DOT_COLUMN] THEN
4510       MAP_EVERY EXPAND_TAC ["X"; "Y"] THEN
4511       SIMP_TAC[CART_EQ; column; LAMBDA_BETA; dot] THEN
4512       REWRITE_TAC[GSYM VECTOR_SUB_COMPONENT; GSYM dot] THEN
4513       REWRITE_TAC[DOT_NORM_SUB; VECTOR_ARITH
4514        `(x - a) - (y - a):real^N = x - y`] THEN
4515       ASM_SIMP_TAC[GSYM dist; DIMINDEX_GE_1; LE_REFL];
4516       ALL_TAC] THEN
4517     SUBGOAL_THEN
4518      `?M:real^N^N. orthogonal_matrix M /\ (Y:real^M^N) = M ** (X:real^M^N)`
4519     (CHOOSE_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THENL
4520      [ALL_TAC;
4521       GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [CART_EQ] THEN
4522       MAP_EVERY EXPAND_TAC ["X"; "Y"] THEN
4523       SIMP_TAC[LAMBDA_BETA; matrix_mul] THEN
4524       REWRITE_TAC[REAL_ARITH `x - y:real = z <=> x = y + z`] THEN STRIP_TAC THEN
4525       EXISTS_TAC `(y:real^N^M)$1 - (M:real^N^N) ** (x:real^N^M)$1` THEN
4526       EXISTS_TAC `\x:real^N. (M:real^N^N) ** x` THEN
4527       ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_MATRIX;
4528                    MATRIX_OF_MATRIX_VECTOR_MUL; MATRIX_VECTOR_MUL_LINEAR] THEN
4529       SIMP_TAC[CART_EQ; matrix_vector_mul; LAMBDA_BETA;
4530                VECTOR_ADD_COMPONENT] THEN
4531       ASM_SIMP_TAC[REAL_SUB_LDISTRIB; SUM_SUB_NUMSEG] THEN
4532       REWRITE_TAC[VECTOR_SUB_COMPONENT; REAL_ARITH
4533        `a + y - b:real = a - z + y <=> z = b`] THEN
4534       SIMP_TAC[LAMBDA_BETA]] THEN
4535     MP_TAC(ISPEC `transp(X:real^M^N) ** X`
4536       SYMMETRIC_MATRIX_DIAGONALIZABLE_EXPLICIT) THEN
4537     REWRITE_TAC[MATRIX_TRANSP_MUL; TRANSP_TRANSP; LEFT_IMP_EXISTS_THM] THEN
4538     MAP_EVERY X_GEN_TAC [`P:real^M^M`; `d:num->real`] THEN
4539     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4540     DISCH_THEN(fun th -> MP_TAC th THEN ASM_REWRITE_TAC[] THEN MP_TAC th) THEN
4541     REWRITE_TAC[MATRIX_MUL_ASSOC; GSYM MATRIX_TRANSP_MUL] THEN
4542     REWRITE_TAC[GSYM MATRIX_MUL_ASSOC; LEFT_IMP_EXISTS_THM] THEN
4543     REWRITE_TAC[IMP_IMP] THEN
4544     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [CART_EQ] THEN
4545     SIMP_TAC[MATRIX_MUL_LTRANSP_DOT_COLUMN; LAMBDA_BETA] THEN STRIP_TAC THEN
4546     MP_TAC(ISPECL [`\i. column i ((X:real^M^N) ** (P:real^M^M))`;
4547                    `\i. column i ((Y:real^M^N) ** (P:real^M^M))`;
4548                    `1..dimindex(:M)`]
4549                   ORTHOGONAL_TRANSFORMATION_BETWEEN_ORTHOGONAL_SETS) THEN
4550     REWRITE_TAC[IN_NUMSEG] THEN ANTS_TAC THENL
4551      [ASM_SIMP_TAC[pairwise; IN_NUMSEG; NORM_EQ; orthogonal]; ALL_TAC] THEN
4552     DISCH_THEN(X_CHOOSE_THEN `f:real^N->real^N` (STRIP_ASSUME_TAC o GSYM)) THEN
4553     EXISTS_TAC `matrix(f:real^N->real^N)` THEN CONJ_TAC THENL
4554      [ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_MATRIX]; ALL_TAC] THEN
4555     SUBGOAL_THEN
4556      `!M:real^M^N. M = M ** (P:real^M^M) ** transp P`
4557      (fun th -> GEN_REWRITE_TAC BINOP_CONV [th])
4558     THENL
4559      [ASM_MESON_TAC[orthogonal_matrix; MATRIX_MUL_RID];
4560       REWRITE_TAC[MATRIX_MUL_ASSOC] THEN AP_THM_TAC THEN AP_TERM_TAC] THEN
4561     REWRITE_TAC[GSYM MATRIX_MUL_ASSOC] THEN
4562     ASM_SIMP_TAC[MATRIX_EQUAL_COLUMNS] THEN
4563     X_GEN_TAC `i:num` THEN STRIP_TAC THEN
4564     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [orthogonal_transformation]) THEN
4565     DISCH_THEN(ASSUME_TAC o GSYM o MATCH_MP MATRIX_WORKS o CONJUNCT1) THEN
4566     ASM_REWRITE_TAC[] THEN
4567     SIMP_TAC[CART_EQ; matrix_vector_mul; column; LAMBDA_BETA] THEN
4568     X_GEN_TAC `j:num` THEN STRIP_TAC THEN
4569     GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [matrix_mul] THEN
4570     ASM_SIMP_TAC[LAMBDA_BETA]) in
4571   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:A->bool = {}` THENL
4572    [REPEAT STRIP_TAC THEN
4573     MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `\x:real^N. x`] THEN
4574     ASM_REWRITE_TAC[NOT_IN_EMPTY; ORTHOGONAL_TRANSFORMATION_ID];
4575     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
4576     DISCH_THEN(X_CHOOSE_TAC `m:A`) THEN DISCH_TAC] THEN
4577   SUBGOAL_THEN
4578     `?r. IMAGE r (1..dimindex(:(N,1)finite_sum)) SUBSET s /\
4579          affine hull (IMAGE (y o r) (1..dimindex(:(N,1)finite_sum))) =
4580          affine hull (IMAGE (y:A->real^N) s)`
4581   MP_TAC THENL
4582    [REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
4583     SIMP_TAC[IMAGE_o; TAUT `p /\ q <=> ~(p ==> ~q)`;
4584              HULL_MONO; IMAGE_SUBSET] THEN REWRITE_TAC[NOT_IMP] THEN
4585     MP_TAC(ISPEC `IMAGE (y:A->real^N) s` AFFINE_BASIS_EXISTS) THEN
4586     DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC) THEN
4587     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [AFFINE_INDEPENDENT_IFF_CARD]) THEN
4588     STRIP_TAC THEN
4589     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [FINITE_INDEX_NUMSEG]) THEN
4590     DISCH_THEN(X_CHOOSE_THEN `f:num->real^N` STRIP_ASSUME_TAC) THEN
4591     SUBGOAL_THEN `CARD(b:real^N->bool) <= dimindex(:(N,1)finite_sum)`
4592     ASSUME_TAC THENL
4593      [REWRITE_TAC[GSYM INT_OF_NUM_LE] THEN
4594       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (INT_ARITH
4595        `a:int = c - &1 ==> a + &1 <= n ==> c <= n`)) THEN
4596       REWRITE_TAC[DIMINDEX_FINITE_SUM; DIMINDEX_1; GSYM INT_OF_NUM_ADD] THEN
4597       REWRITE_TAC[INT_LE_RADD; AFF_DIM_LE_UNIV];
4598       ALL_TAC] THEN
4599     UNDISCH_TAC `b SUBSET IMAGE (y:A->real^N) s` THEN
4600     ONCE_ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
4601     REWRITE_TAC[IN_IMAGE] THEN
4602     GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4603     REWRITE_TAC[SKOLEM_THM; IN_NUMSEG] THEN
4604     DISCH_THEN(X_CHOOSE_THEN `r:num->A` STRIP_ASSUME_TAC) THEN
4605     EXISTS_TAC `\i. if i <= CARD(b:real^N->bool) then r i else (m:A)` THEN
4606     CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
4607     UNDISCH_THEN `affine hull b:real^N->bool = affine hull IMAGE y (s:A->bool)`
4608      (SUBST1_TAC o SYM) THEN
4609     REWRITE_TAC[GSYM SUBSET] THEN MATCH_MP_TAC HULL_MONO THEN
4610     ONCE_ASM_REWRITE_TAC[] THEN
4611     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_NUMSEG] THEN
4612     X_GEN_TAC `i:num` THEN STRIP_TAC THEN REWRITE_TAC[GSYM IMAGE_o] THEN
4613     REWRITE_TAC[IN_IMAGE; IN_NUMSEG] THEN EXISTS_TAC `i:num` THEN
4614     ASM_REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[LE_TRANS];
4615     REWRITE_TAC[SUBSET; IN_NUMSEG; FORALL_IN_IMAGE] THEN
4616     STRIP_TAC THEN MP_TAC(ISPECL
4617      [`(lambda i. x(r i:A)):real^N^(N,1)finite_sum`;
4618       `(lambda i. y(r i:A)):real^N^(N,1)finite_sum`] lemma) THEN
4619     ASM_SIMP_TAC[LAMBDA_BETA] THEN
4620     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
4621     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^N->real^N` THEN
4622     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4623     X_GEN_TAC `k:A` THEN STRIP_TAC THEN
4624     SUBGOAL_THEN
4625      `!z. z IN
4626           affine hull IMAGE (y o (r:num->A)) (1..dimindex(:(N,1)finite_sum))
4627           ==> dist(z,y k) = dist(z,a + (f:real^N->real^N)(x k))`
4628     MP_TAC THENL
4629      [MATCH_MP_TAC SAME_DISTANCES_TO_AFFINE_HULL THEN
4630       REWRITE_TAC[FORALL_IN_IMAGE; o_THM; IN_NUMSEG] THEN
4631       X_GEN_TAC `j:num` THEN STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
4632       EXISTS_TAC `dist(x(r(j:num)),(x:A->real^N) k)` THEN CONJ_TAC THENL
4633        [CONV_TAC SYM_CONV THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[];
4634         REWRITE_TAC[dist] THEN ASM_SIMP_TAC[NORM_ARITH
4635          `(a + x) - (a + y):real^N = x - y`] THEN
4636         ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION; LINEAR_SUB]];
4637       ASM_SIMP_TAC[NORM_ARITH
4638        `a:real^N = b <=> dist(a:real^N,a) = dist(a,b)`] THEN
4639       DISCH_THEN MATCH_MP_TAC THEN  MATCH_MP_TAC HULL_INC THEN
4640       REWRITE_TAC[IN_IMAGE; IN_NUMSEG] THEN ASM_MESON_TAC[]]]);;
4641
4642 let RIGID_TRANSFORMATION_BETWEEN_CONGRUENT_SETS_STRONG = prove
4643  (`!x:A->real^N y:A->real^N s t.
4644         t SUBSET s /\ affine hull (IMAGE y t) = affine hull (IMAGE y s) /\
4645         (!i j. i IN s /\ j IN t ==> dist(x i,x j) = dist(y i,y j))
4646         ==> ?a f. orthogonal_transformation f /\
4647                   !i. i IN s ==> y i = a + f(x i)`,
4648   REPEAT STRIP_TAC THEN
4649   MP_TAC(ISPECL [`x:A->real^N`; `y:A->real^N`; `t:A->bool`]
4650         RIGID_TRANSFORMATION_BETWEEN_CONGRUENT_SETS) THEN
4651   ANTS_TAC THENL [ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
4652   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
4653   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^N->real^N` THEN
4654   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `i:A` THEN DISCH_TAC THEN
4655   SUBGOAL_THEN
4656    `!z. z IN affine hull (IMAGE (y:A->real^N) t)
4657         ==> dist(z,y i) = dist(z,a + (f:real^N->real^N)(x i))`
4658   MP_TAC THENL
4659    [MATCH_MP_TAC SAME_DISTANCES_TO_AFFINE_HULL THEN
4660     REWRITE_TAC[FORALL_IN_IMAGE; o_THM; IN_NUMSEG] THEN
4661     X_GEN_TAC `j:A` THEN STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
4662     EXISTS_TAC `dist(a + f(x(j:A):real^N):real^N,a + f(x i))` THEN
4663     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
4664     REWRITE_TAC[NORM_ARITH `dist(a + x:real^N,a + y) = dist(x,y)`] THEN
4665     ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_ISOMETRY; DIST_SYM];
4666     ASM_SIMP_TAC[NORM_ARITH
4667      `a:real^N = b <=> dist(a:real^N,a) = dist(a,b)`] THEN
4668     DISCH_THEN MATCH_MP_TAC THEN  MATCH_MP_TAC HULL_INC THEN
4669     REWRITE_TAC[IN_IMAGE] THEN ASM_MESON_TAC[]]);;
4670
4671 let RIGID_TRANSFORMATION_BETWEEN_3 = prove
4672  (`!a b c a' b' c':real^N.
4673         dist(a,b) = dist(a',b') /\
4674         dist(b,c) = dist(b',c') /\
4675         dist(c,a) = dist(c',a')
4676         ==> ?k f. orthogonal_transformation f /\
4677                   a' = k + f a /\ b' = k + f b /\ c' = k + f c`,
4678   REPEAT STRIP_TAC THEN
4679   MP_TAC(ISPECL
4680    [`FST:real^N#real^N->real^N`; `SND:real^N#real^N->real^N`;
4681     `{(a:real^N,a':real^N), (b,b'), (c,c')}`]
4682         RIGID_TRANSFORMATION_BETWEEN_CONGRUENT_SETS) THEN
4683   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_INSERT] THEN
4684   REWRITE_TAC[NOT_IN_EMPTY; IMP_IMP] THEN DISCH_THEN MATCH_MP_TAC THEN
4685   ASM_MESON_TAC[DIST_REFL; DIST_SYM]);;
4686
4687 let RIGID_TRANSFORMATION_BETWEEN_2 = prove
4688  (`!a b a' b':real^N.
4689         dist(a,b) = dist(a',b')
4690         ==> ?k f. orthogonal_transformation f /\
4691                   a' = k + f a /\ b' = k + f b`,
4692   REPEAT STRIP_TAC THEN
4693   MP_TAC(ISPECL [`a:real^N`; `b:real^N`; `a:real^N`;
4694                  `a':real^N`; `b':real^N`; `a':real^N`]
4695         RIGID_TRANSFORMATION_BETWEEN_3) THEN
4696   ASM_MESON_TAC[DIST_EQ_0; DIST_SYM]);;
4697
4698 (* ------------------------------------------------------------------------- *)
4699 (* Caratheodory's theorem.                                                   *)
4700 (* ------------------------------------------------------------------------- *)
4701
4702 let CONVEX_HULL_CARATHEODORY_AFF_DIM = prove
4703  (`!p. convex hull p =
4704         {y:real^N | ?s u. FINITE s /\ s SUBSET p /\
4705                           &(CARD s) <= aff_dim p + &1 /\
4706                           (!x. x IN s ==> &0 <= u x) /\
4707                           sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
4708   GEN_TAC THEN REWRITE_TAC[CONVEX_HULL_EXPLICIT] THEN
4709   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN X_GEN_TAC `y:real^N` THEN
4710   EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
4711   MATCH_MP_TAC(TAUT `!q. (p ==> q) /\ (q ==> r) ==> (p ==> r)`) THEN
4712   EXISTS_TAC `?n s u. CARD s = n /\
4713                       FINITE s /\ s SUBSET p /\
4714                       (!x. x IN s ==> &0 <= u x) /\
4715                       sum s u = &1 /\ vsum s (\v. u v % v) = (y:real^N)` THEN
4716   CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
4717   GEN_REWRITE_TAC LAND_CONV [num_WOP] THEN
4718   DISCH_THEN(X_CHOOSE_THEN `n:num` MP_TAC) THEN
4719   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
4720   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
4721   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4722   GEN_REWRITE_TAC I [GSYM INT_NOT_LT] THEN DISCH_TAC THEN
4723   FIRST_X_ASSUM(MP_TAC o SPEC `n - 1`) THEN REWRITE_TAC[NOT_IMP] THEN
4724   CONJ_TAC THENL
4725    [MATCH_MP_TAC(ARITH_RULE `~(n = 0) ==> n - 1 < n`) THEN
4726     DISCH_THEN SUBST_ALL_TAC THEN
4727     UNDISCH_TAC `aff_dim(p:real^N->bool) + &1 < &0` THEN
4728     REWRITE_TAC[INT_ARITH `p + &1:int < &0 <=> ~(-- &1 <= p)`] THEN
4729     REWRITE_TAC[AFF_DIM_GE];
4730     ALL_TAC] THEN
4731   MP_TAC(ISPEC `s:real^N->bool` AFF_DIM_AFFINE_INDEPENDENT) THEN
4732   ASM_REWRITE_TAC[] THEN
4733   SUBGOAL_THEN `~(aff_dim(s:real^N->bool) = &n - &1)` ASSUME_TAC THENL
4734    [FIRST_ASSUM(MP_TAC o MATCH_MP AFF_DIM_SUBSET) THEN
4735
4736     UNDISCH_TAC `aff_dim(p:real^N->bool) + &1 < &n` THEN
4737     INT_ARITH_TAC;
4738     ALL_TAC] THEN
4739   ASM_SIMP_TAC[AFFINE_DEPENDENT_EXPLICIT_FINITE] THEN
4740   DISCH_THEN(X_CHOOSE_THEN `w:real^N->real` STRIP_ASSUME_TAC) THEN
4741   SUBGOAL_THEN
4742    `?t. (!v:real^N. v IN s ==> u(v) + t * w(v) >= &0) /\
4743         ?a. a IN s /\ u(a) + t * w(a) = &0`
4744   STRIP_ASSUME_TAC THENL
4745    [ABBREV_TAC
4746      `i = IMAGE (\v. u(v) / --w(v)) {v:real^N | v IN s /\ w v < &0}` THEN
4747     EXISTS_TAC `inf i` THEN MP_TAC(SPEC `i:real->bool` INF_FINITE) THEN
4748     ANTS_TAC THENL
4749      [EXPAND_TAC "i" THEN
4750       ASM_SIMP_TAC[FINITE_IMAGE; FINITE_RESTRICT; IMAGE_EQ_EMPTY] THEN
4751       REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
4752       MP_TAC(ISPECL [`w:real^N->real`; `s:real^N->bool`] SUM_ZERO_EXISTS) THEN
4753       ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[];
4754       ALL_TAC] THEN
4755     ABBREV_TAC `t = inf i` THEN
4756     EXPAND_TAC "i" THEN REWRITE_TAC[FORALL_IN_IMAGE] THEN
4757     REWRITE_TAC[IN_IMAGE; IN_ELIM_THM] THEN
4758     DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_THEN `a:real^N`
4759       STRIP_ASSUME_TAC) MP_TAC) THEN
4760     SIMP_TAC[REAL_LE_RDIV_EQ; REAL_ARITH `x < &0 ==> &0 < --x`; real_ge] THEN
4761     REWRITE_TAC[REAL_ARITH `t * --w <= u <=> &0 <= u + t * w`] THEN
4762     STRIP_TAC THEN CONJ_TAC THENL
4763      [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4764       DISJ_CASES_TAC(REAL_ARITH `(w:real^N->real) x < &0 \/ &0 <= w x`) THEN
4765       ASM_SIMP_TAC[] THEN MATCH_MP_TAC REAL_LE_ADD THEN ASM_SIMP_TAC[] THEN
4766       MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[] THEN
4767       MATCH_MP_TAC REAL_LE_DIV THEN ASM_SIMP_TAC[] THEN
4768       MATCH_MP_TAC(REAL_ARITH `w < &0 ==> &0 <= --w`) THEN ASM_REWRITE_TAC[];
4769       EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN
4770       UNDISCH_TAC `w(a:real^N) < &0` THEN CONV_TAC REAL_FIELD];
4771     ALL_TAC] THEN
4772   MAP_EVERY EXISTS_TAC
4773    [`s DELETE (a:real^N)`; `(\v. u(v) + t * w(v)):real^N->real`] THEN
4774   ASM_SIMP_TAC[SUM_DELETE; VSUM_DELETE; CARD_DELETE; FINITE_DELETE] THEN
4775   ASM_SIMP_TAC[SUM_ADD; VECTOR_ADD_RDISTRIB; VSUM_ADD] THEN
4776   ASM_SIMP_TAC[GSYM VECTOR_MUL_ASSOC; SUM_LMUL; VSUM_LMUL] THEN
4777   REPEAT CONJ_TAC THENL
4778    [ASM SET_TAC[]; ASM SET_TAC[real_ge]; REAL_ARITH_TAC; VECTOR_ARITH_TAC]);;
4779
4780 let CARATHEODORY_AFF_DIM = prove
4781  (`!p. convex hull p =
4782         {x:real^N | ?s. FINITE s /\ s SUBSET p /\
4783                          &(CARD s) <= aff_dim p + &1 /\
4784                         x IN convex hull s}`,
4785   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REPEAT GEN_TAC THEN EQ_TAC THENL
4786    [GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
4787      [CONVEX_HULL_CARATHEODORY_AFF_DIM] THEN
4788     REWRITE_TAC[IN_ELIM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
4789     ASM_MESON_TAC[HULL_SUBSET; CONVEX_EXPLICIT; CONVEX_CONVEX_HULL];
4790     MESON_TAC[SUBSET; HULL_MONO]]);;
4791
4792 let CONVEX_HULL_CARATHEODORY = prove
4793  (`!p. convex hull p =
4794         {y:real^N | ?s u. FINITE s /\ s SUBSET p /\
4795                           CARD(s) <= dimindex(:N) + 1 /\
4796                           (!x. x IN s ==> &0 <= u x) /\
4797                           sum s u = &1 /\ vsum s (\v. u v % v) = y}`,
4798
4799   GEN_TAC THEN REWRITE_TAC[EXTENSION] THEN X_GEN_TAC `y:real^N` THEN
4800   EQ_TAC THENL
4801    [REWRITE_TAC[CONVEX_HULL_CARATHEODORY_AFF_DIM; IN_ELIM_THM] THEN
4802     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
4803     STRIP_TAC THEN
4804     ASM_REWRITE_TAC[GSYM INT_OF_NUM_LE; GSYM INT_OF_NUM_ADD] THEN
4805     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (INT_ARITH
4806      `a:int <= x + &1 ==> x <= y ==> a <= y + &1`)) THEN
4807     REWRITE_TAC[AFF_DIM_LE_UNIV];
4808     REWRITE_TAC[CONVEX_HULL_EXPLICIT; IN_ELIM_THM] THEN MESON_TAC[]]);;
4809
4810 let CARATHEODORY = prove
4811  (`!p. convex hull p =
4812         {x:real^N | ?s. FINITE s /\ s SUBSET p /\
4813                         CARD(s) <= dimindex(:N) + 1 /\
4814                         x IN convex hull s}`,
4815   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REPEAT GEN_TAC THEN EQ_TAC THENL
4816    [GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
4817      [CONVEX_HULL_CARATHEODORY] THEN
4818     REWRITE_TAC[IN_ELIM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
4819     ASM_MESON_TAC[HULL_SUBSET; CONVEX_EXPLICIT; CONVEX_CONVEX_HULL];
4820     MESON_TAC[SUBSET; HULL_MONO]]);;
4821
4822 (* ------------------------------------------------------------------------- *)
4823 (* Some results on decomposing convex hulls, e.g. simplicial subdivision.    *)
4824 (* ------------------------------------------------------------------------- *)
4825
4826 let AFFINE_HULL_INTER,CONVEX_HULL_INTER = (CONJ_PAIR o prove)
4827  (`(!s t:real^N->bool.
4828         ~(affine_dependent(s UNION t))
4829         ==> affine hull s INTER affine hull t = affine hull (s INTER t)) /\
4830    (!s t:real^N->bool.
4831         ~(affine_dependent (s UNION t))
4832         ==> convex hull s INTER convex hull t = convex hull (s INTER t))`,
4833   CONJ_TAC THEN
4834   (REPEAT STRIP_TAC THEN
4835    FIRST_ASSUM(MP_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
4836    REWRITE_TAC[FINITE_UNION] THEN STRIP_TAC THEN
4837    MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET_INTER] THEN
4838    SIMP_TAC[HULL_MONO; INTER_SUBSET] THEN
4839    REWRITE_TAC[SUBSET; AFFINE_HULL_FINITE; CONVEX_HULL_FINITE;
4840                IN_ELIM_THM; IN_INTER] THEN
4841    X_GEN_TAC `y:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2
4842     (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC)
4843     (X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC)) THEN
4844    FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
4845      [AFFINE_DEPENDENT_EXPLICIT]) THEN
4846    REWRITE_TAC[NOT_EXISTS_THM] THEN
4847    DISCH_THEN(MP_TAC o SPEC `(s UNION t):real^N->bool`) THEN
4848    ASM_REWRITE_TAC[SUBSET_REFL] THEN
4849    DISCH_THEN(MP_TAC o SPEC
4850     `\x:real^N. (if x IN s then u x else &0) -
4851                 (if x IN t then v x else &0)`) THEN
4852    ASM_SIMP_TAC[SUM_SUB; FINITE_UNION; VSUM_SUB; VECTOR_SUB_RDISTRIB] THEN
4853    REWRITE_TAC[MESON[]
4854     `(if p then a else b) % x = (if p then a % x else b % x)`] THEN
4855    ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; VECTOR_MUL_LZERO; FINITE_UNION] THEN
4856    ASM_REWRITE_TAC[SUM_0; VSUM_0;
4857      SET_RULE `{x | x IN (s UNION t) /\ x IN s} = s`;
4858      SET_RULE `{x | x IN (s UNION t) /\ x IN t} = t`] THEN
4859    MATCH_MP_TAC(TAUT `a /\ c /\ (~b ==> d) ==> ~(a /\ b /\ c) ==> d`) THEN
4860    REPEAT CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC; ALL_TAC] THEN
4861    DISCH_TAC THEN EXISTS_TAC `u:real^N->real` THEN ASM_SIMP_TAC[] THEN
4862    CONJ_TAC THEN MATCH_MP_TAC EQ_TRANS THENL
4863     [EXISTS_TAC `sum s (u:real^N->real)`;
4864      EXISTS_TAC `vsum s (\x. (u:real^N->real) x % x)`] THEN
4865    (CONJ_TAC THENL [ALL_TAC; FIRST_X_ASSUM ACCEPT_TAC]) THEN
4866    CONV_TAC SYM_CONV THENL
4867     [MATCH_MP_TAC SUM_EQ_SUPERSET; MATCH_MP_TAC VSUM_EQ_SUPERSET] THEN
4868    ASM_SIMP_TAC[FINITE_INTER; INTER_SUBSET; IN_INTER] THEN
4869    X_GEN_TAC `x:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4870    ASM_REWRITE_TAC[VECTOR_MUL_EQ_0] THEN DISCH_TAC THEN
4871    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
4872    DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
4873    ASM_REWRITE_TAC[REAL_SUB_RZERO] THEN ASM SET_TAC[]));;
4874
4875 let AFFINE_HULL_INTERS = prove
4876  (`!s:(real^N->bool)->bool.
4877         ~(affine_dependent(UNIONS s))
4878         ==> affine hull (INTERS s) = INTERS {affine hull t | t IN s}`,
4879   REPEAT STRIP_TAC THEN FIRST_X_ASSUM(fun th ->
4880    MP_TAC th THEN MP_TAC(MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE th)) THEN
4881   SPEC_TAC(`s:(real^N->bool)->bool`,`s:(real^N->bool)->bool`) THEN
4882   REWRITE_TAC[FINITE_UNIONS; IMP_CONJ] THEN
4883   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
4884   REWRITE_TAC[UNIONS_0; INTERS_0; UNIONS_INSERT; INTERS_INSERT;
4885               SET_RULE `{f x | x IN {}} = {}`; AFFINE_HULL_UNIV] THEN
4886   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `f:(real^N->bool)->bool`] THEN
4887   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
4888   REWRITE_TAC[FORALL_IN_INSERT] THEN
4889   DISCH_THEN(fun th -> STRIP_TAC THEN STRIP_TAC THEN MP_TAC th) THEN
4890   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
4891    [UNDISCH_TAC `~affine_dependent((s UNION UNIONS f):real^N->bool)` THEN
4892     REWRITE_TAC[CONTRAPOS_THM] THEN
4893     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO) THEN
4894     SET_TAC[];
4895     DISCH_TAC] THEN
4896   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
4897    [ASM_REWRITE_TAC[INTERS_0; INTER_UNIV; IN_SING] THEN
4898     REWRITE_TAC[SET_RULE `{f x | x = a} = {f a}`; INTERS_1];
4899     ALL_TAC] THEN
4900   W(MP_TAC o PART_MATCH (rhs o rand) AFFINE_HULL_INTER o lhand o snd) THEN
4901   ANTS_TAC THENL
4902    [UNDISCH_TAC `~affine_dependent((s UNION UNIONS f):real^N->bool)` THEN
4903     REWRITE_TAC[CONTRAPOS_THM] THEN
4904     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO) THEN
4905     UNDISCH_TAC `~(f:(real^N->bool)->bool = {})` THEN SET_TAC[];
4906     DISCH_THEN(SUBST1_TAC o SYM)] THEN
4907   REWRITE_TAC[SET_RULE
4908    `{f x | x IN (a INSERT s)} = (f a) INSERT {f x | x IN s}`] THEN
4909   ASM_REWRITE_TAC[INTERS_INSERT]);;
4910
4911 let CONVEX_HULL_INTERS = prove
4912  (`!s:(real^N->bool)->bool.
4913         ~(affine_dependent(UNIONS s))
4914         ==> convex hull (INTERS s) = INTERS {convex hull t | t IN s}`,
4915   REPEAT STRIP_TAC THEN FIRST_X_ASSUM(fun th ->
4916    MP_TAC th THEN MP_TAC(MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE th)) THEN
4917   SPEC_TAC(`s:(real^N->bool)->bool`,`s:(real^N->bool)->bool`) THEN
4918   REWRITE_TAC[FINITE_UNIONS; IMP_CONJ] THEN
4919   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
4920   REWRITE_TAC[UNIONS_0; INTERS_0; UNIONS_INSERT; INTERS_INSERT;
4921               SET_RULE `{f x | x IN {}} = {}`; CONVEX_HULL_UNIV] THEN
4922   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `f:(real^N->bool)->bool`] THEN
4923   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
4924   REWRITE_TAC[FORALL_IN_INSERT] THEN
4925   DISCH_THEN(fun th -> STRIP_TAC THEN STRIP_TAC THEN MP_TAC th) THEN
4926   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
4927    [UNDISCH_TAC `~affine_dependent((s UNION UNIONS f):real^N->bool)` THEN
4928     REWRITE_TAC[CONTRAPOS_THM] THEN
4929     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO) THEN
4930     SET_TAC[];
4931     DISCH_TAC] THEN
4932   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
4933    [ASM_REWRITE_TAC[INTERS_0; INTER_UNIV; IN_SING] THEN
4934     REWRITE_TAC[SET_RULE `{f x | x = a} = {f a}`; INTERS_1];
4935     ALL_TAC] THEN
4936   W(MP_TAC o PART_MATCH (rhs o rand) CONVEX_HULL_INTER o lhand o snd) THEN
4937   ANTS_TAC THENL
4938    [UNDISCH_TAC `~affine_dependent((s UNION UNIONS f):real^N->bool)` THEN
4939     REWRITE_TAC[CONTRAPOS_THM] THEN
4940     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO) THEN
4941     UNDISCH_TAC `~(f:(real^N->bool)->bool = {})` THEN SET_TAC[];
4942     DISCH_THEN(SUBST1_TAC o SYM)] THEN
4943   REWRITE_TAC[SET_RULE
4944    `{f x | x IN (a INSERT s)} = (f a) INSERT {f x | x IN s}`] THEN
4945   ASM_REWRITE_TAC[INTERS_INSERT]);;
4946
4947 let IN_CONVEX_HULL_EXCHANGE = prove
4948  (`!s a x:real^N.
4949         a IN convex hull s /\ x IN convex hull s
4950         ==> ?b. b IN s /\ x IN convex hull (a INSERT (s DELETE b))`,
4951   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(a:real^N) IN s` THENL
4952    [EXISTS_TAC `a:real^N` THEN ASM_SIMP_TAC[INSERT_DELETE]; ALL_TAC] THEN
4953   ASM_CASES_TAC `FINITE(s:real^N->bool) /\ CARD s <= dimindex(:N) + 1` THENL
4954    [ALL_TAC;
4955     UNDISCH_TAC `(x:real^N) IN convex hull s` THEN
4956     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [CARATHEODORY] THEN
4957     REWRITE_TAC[LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN
4958     X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
4959     ASM_CASES_TAC `t:real^N->bool = s` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
4960     SUBGOAL_THEN `?b:real^N. b IN s /\ ~(b IN t)` MP_TAC THENL
4961      [ASM SET_TAC[]; ALL_TAC] THEN
4962     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN
4963     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4964     UNDISCH_TAC `(x:real^N) IN convex hull t` THEN
4965     SPEC_TAC(`x:real^N`,`x:real^N`) THEN REWRITE_TAC[GSYM SUBSET] THEN
4966     MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]] THEN
4967   MP_TAC(ASSUME `(a:real^N) IN convex hull s`) THEN
4968   MP_TAC(ASSUME `(x:real^N) IN convex hull s`) THEN
4969   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
4970   X_GEN_TAC `v:real^N->real` THEN STRIP_TAC THEN
4971   X_GEN_TAC `u:real^N->real` THEN STRIP_TAC THEN
4972   ASM_CASES_TAC `?b. b IN s /\ (v:real^N->real) b = &0` THENL
4973    [FIRST_X_ASSUM(fun th -> MP_TAC th THEN MATCH_MP_TAC MONO_EXISTS) THEN
4974     X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4975     EXISTS_TAC `\x:real^N. if x = a then &0 else v x` THEN
4976     ASM_SIMP_TAC[FORALL_IN_INSERT; REAL_LE_REFL] THEN
4977     ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FINITE_DELETE] THEN
4978     ASM_REWRITE_TAC[IN_DELETE] THEN
4979     ASM_SIMP_TAC[SUM_DELETE; VSUM_DELETE; COND_ID] THEN
4980     ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
4981     ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; REAL_LE_REFL; COND_ID] THEN
4982     REWRITE_TAC[VECTOR_MUL_LZERO; SUM_0; VSUM_0] THEN
4983     ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> {x | x IN s /\ ~(x = a)} = s`] THEN
4984     CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC];
4985     ALL_TAC] THEN
4986   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
4987   REWRITE_TAC[TAUT `~(a /\ b) <=> a ==> ~b`] THEN DISCH_TAC THEN
4988   MP_TAC(ISPEC `IMAGE (\b. (u:real^N->real) b / v b) s` SUP_FINITE) THEN
4989   ASM_CASES_TAC `s:real^N->bool = {}` THENL
4990    [ASM_MESON_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY]; ALL_TAC] THEN
4991   ASM_SIMP_TAC[FINITE_IMAGE; IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
4992   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
4993   REWRITE_TAC[IN_IMAGE] THEN MATCH_MP_TAC MONO_EXISTS THEN
4994   X_GEN_TAC `b:real^N` THEN
4995   DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
4996   ASM_REWRITE_TAC[] THEN
4997   SUBGOAL_THEN `!b. b IN s ==> &0 < (v:real^N->real) b` ASSUME_TAC THENL
4998    [ASM_SIMP_TAC[REAL_LT_LE]; ALL_TAC] THEN
4999   SUBGOAL_THEN `&0 < (u:real^N->real) b /\ &0 < v b` STRIP_ASSUME_TAC THENL
5000    [ASM_SIMP_TAC[REAL_LT_LE] THEN
5001     UNDISCH_TAC `!x. x IN s ==> (u:real^N->real) x / v x <= u b / v b` THEN
5002     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[] THEN
5003     DISCH_THEN(SUBST1_TAC o SYM) THEN ASM_SIMP_TAC[REAL_LE_LDIV_EQ] THEN
5004     REWRITE_TAC[real_div; REAL_MUL_LZERO] THEN
5005     ASM_SIMP_TAC[REAL_ARITH `&0 <= x ==> (x <= &0 <=> x = &0)`] THEN
5006     DISCH_TAC THEN UNDISCH_TAC `sum s (u:real^N->real) = &1` THEN
5007     MATCH_MP_TAC(REAL_ARITH `x = &0 ==> x = &1 ==> F`) THEN
5008     ASM_SIMP_TAC[SUM_EQ_0];
5009     ALL_TAC] THEN
5010   EXISTS_TAC `(\x. if x = a then v b / u b else v x - (v b / u b) * u x):
5011               real^N->real` THEN
5012   ASM_SIMP_TAC[FORALL_IN_INSERT; REAL_LE_DIV; REAL_LT_IMP_LE] THEN
5013   ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
5014   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FINITE_DELETE] THEN
5015   ASM_SIMP_TAC[SUM_DELETE; VSUM_DELETE; IN_DELETE] THEN
5016   ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; FINITE_DELETE] THEN
5017   ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> {x | x IN s /\ ~(x = a)} = s`;
5018                SET_RULE `~(a IN s) ==> {x | x IN s /\ x = a} = {}`] THEN
5019   REWRITE_TAC[VSUM_CLAUSES; SUM_CLAUSES] THEN
5020   ASM_CASES_TAC `b:real^N = a` THENL [ASM_MESON_TAC[]; ASM_REWRITE_TAC[]] THEN
5021   ASM_SIMP_TAC[VECTOR_SUB_RDISTRIB; VSUM_SUB; SUM_SUB] THEN
5022   REWRITE_TAC[GSYM VECTOR_MUL_ASSOC; VECTOR_ADD_LID; REAL_ADD_LID] THEN
5023   ASM_SIMP_TAC[SUM_LMUL; VSUM_LMUL] THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN
5024   ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_LT_IMP_NZ] THEN REPEAT CONJ_TAC THENL
5025    [ALL_TAC; REAL_ARITH_TAC; VECTOR_ARITH_TAC] THEN
5026   X_GEN_TAC `c:real^N` THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
5027   STRIP_TAC THEN ASM_CASES_TAC `(u:real^N->real) c = &0` THENL
5028    [ASM_SIMP_TAC[REAL_MUL_RZERO; REAL_SUB_RZERO]; ALL_TAC] THEN
5029   REWRITE_TAC[REAL_SUB_LE] THEN
5030   ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; REAL_LT_LE] THEN
5031   ONCE_REWRITE_TAC[GSYM REAL_INV_DIV] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
5032   ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_LE]);;
5033
5034 let IN_CONVEX_HULL_EXCHANGE_UNIQUE = prove
5035  (`!s t t' a x:real^N.
5036         ~(affine_dependent s) /\
5037         a IN convex hull s /\
5038         t SUBSET s /\ t' SUBSET s /\
5039         x IN convex hull (a INSERT t) /\
5040         x IN convex hull (a INSERT t')
5041         ==> x IN convex hull (a INSERT (t INTER t'))`,
5042   REPEAT GEN_TAC THEN ASM_CASES_TAC `(a:real^N) IN s` THENL
5043    [REPEAT STRIP_TAC THEN REWRITE_TAC[SET_RULE
5044      `a INSERT (s INTER t) = (a INSERT s) INTER (a INSERT t)`] THEN
5045     W(MP_TAC o PART_MATCH (rand o rand)  CONVEX_HULL_INTER o rand o snd) THEN
5046     ANTS_TAC THENL
5047      [UNDISCH_TAC `~(affine_dependent(s:real^N->bool))` THEN
5048       REWRITE_TAC[CONTRAPOS_THM] THEN
5049       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] AFFINE_DEPENDENT_MONO);
5050       DISCH_THEN(SUBST1_TAC o SYM)] THEN
5051     ASM SET_TAC[];
5052     ALL_TAC] THEN
5053   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5054   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
5055   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
5056   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_THEN `b:real^N->real` STRIP_ASSUME_TAC)
5057     MP_TAC) THEN
5058   REPLICATE_TAC 2 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5059   SUBGOAL_THEN `~((a:real^N) IN t) /\ ~(a IN t')` STRIP_ASSUME_TAC THENL
5060    [ASM SET_TAC[]; ALL_TAC] THEN
5061   SUBGOAL_THEN `FINITE(t:real^N->bool) /\ FINITE(t':real^N->bool)`
5062   STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
5063   ASM_SIMP_TAC[AFFINE_HULL_FINITE_STEP_GEN; REAL_LE_ADD;
5064                REAL_ARITH `&0 <= a / &2 <=> &0 <= a`] THEN
5065   REWRITE_TAC[IMP_CONJ; LEFT_IMP_EXISTS_THM] THEN
5066   MAP_EVERY X_GEN_TAC [`u':real`; `u:real^N->real`] THEN REPEAT DISCH_TAC THEN
5067   MAP_EVERY X_GEN_TAC [`v':real`; `v:real^N->real`] THEN REPEAT DISCH_TAC THEN
5068   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
5069     [AFFINE_DEPENDENT_EXPLICIT]) THEN
5070   REWRITE_TAC[NOT_EXISTS_THM] THEN
5071   DISCH_THEN(MP_TAC o SPEC `s:real^N->bool`) THEN
5072   ASM_REWRITE_TAC[SUBSET_REFL] THEN
5073   DISCH_THEN(MP_TAC o SPEC
5074    `\x:real^N. (if x IN t then u x else &0) - (if x IN t' then v x else &0) +
5075                (u' - v') * b x`) THEN
5076   ASM_SIMP_TAC[SUM_ADD; VSUM_ADD; SUM_LMUL; VSUM_LMUL; VECTOR_ADD_RDISTRIB] THEN
5077   ASM_SIMP_TAC[SUM_SUB; VSUM_SUB; VECTOR_SUB_RDISTRIB] THEN
5078   REWRITE_TAC[MESON[]
5079    `(if p then a else b) % x = (if p then a % x else b % x)`] THEN
5080   ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; VECTOR_MUL_LZERO; SUM_0; VSUM_0] THEN
5081   ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> {x | x IN s /\ x IN t} = t`] THEN
5082   ASM_SIMP_TAC[SUM_ADD; SUM_LMUL; VSUM_ADD; VSUM_LMUL; VECTOR_ADD_RDISTRIB;
5083                GSYM VECTOR_MUL_ASSOC] THEN
5084   MATCH_MP_TAC(TAUT `a /\ c /\ (~b ==> d) ==> ~(a /\ b /\ c) ==> d`) THEN
5085   REPEAT CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC; ALL_TAC] THEN
5086   DISCH_TAC THEN
5087   SUBGOAL_THEN
5088    `(!x. x IN s ==> (if x IN t then u x else &0) <=
5089                     (if x IN t' then v x else &0)) \/
5090     (!x:real^N. x IN s ==> (if x IN t' then v x else &0) <=
5091                            (if x IN t then u x else &0))`
5092   (DISJ_CASES_THEN(LABEL_TAC "*")) THENL
5093    [MP_TAC(REAL_ARITH `&0 <= (u' - v') \/ &0 <= (v' - u')`) THEN
5094     MATCH_MP_TAC MONO_OR THEN CONJ_TAC THEN
5095     DISCH_TAC THEN X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
5096     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
5097     DISCH_THEN(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THENL
5098      [MATCH_MP_TAC(REAL_ARITH `&0 <= c ==> a - b + c = &0 ==> a <= b`);
5099       MATCH_MP_TAC(REAL_ARITH `&0 <= --c ==> a - b + c = &0 ==> b <= a`)] THEN
5100     ASM_SIMP_TAC[REAL_LE_MUL; GSYM REAL_MUL_LNEG; REAL_NEG_SUB];
5101     EXISTS_TAC `(\x. if x = a then u' else u x):real^N->real`;
5102     EXISTS_TAC `(\x. if x = a then v' else v x):real^N->real`] THEN
5103   ASM_SIMP_TAC[FORALL_IN_INSERT] THEN
5104   (CONJ_TAC THENL [ASM_MESON_TAC[IN_INTER]; ALL_TAC]) THEN
5105   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; FINITE_INTER] THEN
5106   ASM_REWRITE_TAC[IN_INTER] THEN
5107   REWRITE_TAC[REAL_ARITH `u' + u = &1 <=> u = &1 - u'`;
5108               VECTOR_ARITH `u' + u:real^N = y <=> u = y - u'`] THEN
5109   (CONJ_TAC THEN
5110    FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN
5111    CONV_TAC SYM_CONV THENL
5112     [MATCH_MP_TAC SUM_EQ_SUPERSET; MATCH_MP_TAC VSUM_EQ_SUPERSET]) THEN
5113   ASM_SIMP_TAC[FINITE_INTER; INTER_SUBSET; IN_INTER] THEN
5114   (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
5115   X_GEN_TAC `y:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5116   ASM_REWRITE_TAC[VECTOR_MUL_EQ_0] THEN DISCH_TAC THEN
5117   REMOVE_THEN "*" (MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THEN
5118   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN ASM SET_TAC[]);;
5119
5120 let CONVEX_HULL_EXCHANGE_UNION = prove
5121  (`!s a:real^N.
5122         a IN convex hull s
5123         ==> convex hull s =
5124             UNIONS {convex hull (a INSERT (s DELETE b)) |b| b IN s}`,
5125   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
5126    [ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN REWRITE_TAC[UNIONS_IMAGE] THEN
5127     REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
5128     ASM_MESON_TAC[IN_CONVEX_HULL_EXCHANGE];
5129     REWRITE_TAC[SUBSET; FORALL_IN_UNIONS; FORALL_IN_GSPEC;
5130                 IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
5131     GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[GSYM SUBSET] THEN
5132     ASM_SIMP_TAC[SUBSET_HULL; CONVEX_CONVEX_HULL] THEN
5133     ASM_REWRITE_TAC[INSERT_SUBSET] THEN
5134     MESON_TAC[HULL_INC; SUBSET; IN_DELETE]]);;
5135
5136 let CONVEX_HULL_EXCHANGE_INTER = prove
5137  (`!s a:real^N t t'.
5138          ~affine_dependent s /\
5139          a IN convex hull s /\
5140          t SUBSET s /\
5141          t' SUBSET s
5142          ==> (convex hull (a INSERT t)) INTER (convex hull (a INSERT t')) =
5143              convex hull (a INSERT (t INTER t'))`,
5144   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
5145    [REWRITE_TAC[SUBSET; IN_INTER] THEN REPEAT STRIP_TAC THEN
5146     MATCH_MP_TAC IN_CONVEX_HULL_EXCHANGE_UNIQUE THEN
5147     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[];
5148     REWRITE_TAC[SUBSET_INTER] THEN CONJ_TAC THEN
5149     MATCH_MP_TAC HULL_MONO THEN SET_TAC[]]);;
5150
5151 (* ------------------------------------------------------------------------- *)
5152 (* Representing affine hull as hyperplane or finite intersection of them.    *)
5153 (* ------------------------------------------------------------------------- *)
5154
5155 let AFF_DIM_EQ_HYPERPLANE = prove
5156  (`!s. aff_dim s = &(dimindex(:N)) - &1 <=>
5157        ?a b. ~(a = vec 0) /\ affine hull s = {x:real^N | a dot x = b}`,
5158   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
5159    [ASM_REWRITE_TAC[AFF_DIM_EMPTY; INT_ARITH `--a:int = b - a <=> b = &0`] THEN
5160     SIMP_TAC[INT_OF_NUM_EQ; LE_1; DIMINDEX_GE_1; AFFINE_HULL_EMPTY] THEN
5161     REWRITE_TAC[EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY; NOT_EXISTS_THM] THEN
5162     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN
5163     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5164     DISCH_THEN(MP_TAC o SPEC `(b / (a dot a)) % a:real^N`) THEN
5165     ASM_SIMP_TAC[DOT_RMUL; REAL_DIV_RMUL; DOT_EQ_0];
5166     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
5167     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `c:real^N` THEN
5168     GEN_GEOM_ORIGIN_TAC `c:real^N` ["a"] THEN
5169     SIMP_TAC[AFF_DIM_DIM_0; HULL_INC] THEN
5170     SIMP_TAC[INT_OF_NUM_SUB; DIMINDEX_GE_1; INT_OF_NUM_EQ] THEN
5171     SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC; DIM_EQ_HYPERPLANE] THEN
5172     REPEAT STRIP_TAC THEN AP_TERM_TAC THEN
5173     GEN_REWRITE_TAC I [FUN_EQ_THM] THEN X_GEN_TAC `a:real^N` THEN
5174     REWRITE_TAC[] THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
5175     ASM_REWRITE_TAC[DOT_RADD; REAL_ARITH `a + b:real = c <=> b = c - a`] THEN
5176     EQ_TAC THEN STRIP_TAC THENL
5177      [EXISTS_TAC `(a:real^N) dot c` THEN ASM_REWRITE_TAC[REAL_SUB_REFL];
5178       ASM_REWRITE_TAC[] THEN
5179       FIRST_X_ASSUM(MP_TAC o AP_TERM `\s. (vec 0:real^N) IN s`) THEN
5180       ASM_SIMP_TAC[SPAN_SUPERSET; IN_ELIM_THM; DOT_RZERO]]]);;
5181
5182 let AFF_DIM_HYPERPLANE = prove
5183  (`!a b. ~(a = vec 0)
5184          ==> aff_dim {x:real^N | a dot x = b} = &(dimindex(:N)) - &1`,
5185   REPEAT STRIP_TAC THEN REWRITE_TAC[AFF_DIM_EQ_HYPERPLANE] THEN
5186   MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real`] THEN
5187   ASM_REWRITE_TAC[AFFINE_HULL_EQ; AFFINE_HYPERPLANE]);;
5188
5189 let BOUNDED_HYPERPLANE_EQ_TRIVIAL = prove
5190  (`!a b. bounded {x:real^N | a dot x = b} <=>
5191          if a = vec 0 then ~(b = &0) else dimindex(:N) = 1`,
5192   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
5193   ASM_REWRITE_TAC[DOT_LZERO] THENL
5194    [ASM_CASES_TAC `b = &0` THEN
5195     ASM_REWRITE_TAC[EMPTY_GSPEC; BOUNDED_EMPTY] THEN
5196     REWRITE_TAC[NOT_BOUNDED_UNIV; SET_RULE `{x | T} = UNIV`];
5197     ASM_SIMP_TAC[AFFINE_BOUNDED_EQ_LOWDIM; AFF_DIM_HYPERPLANE;
5198                  AFFINE_HYPERPLANE] THEN
5199     REWRITE_TAC[INT_ARITH `a - &1:int <= &0 <=> a <= &1`; INT_OF_NUM_LE] THEN
5200     MATCH_MP_TAC(ARITH_RULE `1 <= n ==> (n <= 1 <=> n = 1)`) THEN
5201     REWRITE_TAC[DIMINDEX_GE_1]]);;
5202
5203 let AFFINE_HULL_FINITE_INTERSECTION_HYPERPLANES = prove
5204  (`!s:real^N->bool.
5205         ?f. FINITE f /\
5206             &(CARD f) + aff_dim s = &(dimindex(:N)) /\
5207             affine hull s = INTERS f /\
5208             (!h. h IN f ==> ?a b. ~(a = vec 0) /\ h = {x | a dot x = b})`,
5209   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
5210   MP_TAC(ISPEC `s:real^N->bool` AFFINE_BASIS_EXISTS) THEN
5211   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC) THEN
5212   FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
5213   MP_TAC(ISPECL [`b:real^N->bool`; `(:real^N)`] EXTEND_TO_AFFINE_BASIS) THEN
5214   ASM_REWRITE_TAC[SUBSET_UNIV; AFFINE_HULL_UNIV] THEN
5215   DISCH_THEN(X_CHOOSE_THEN `c:real^N->bool` STRIP_ASSUME_TAC) THEN
5216   SUBGOAL_THEN `FINITE(c:real^N->bool)` ASSUME_TAC THENL
5217    [ASM_MESON_TAC[AFFINE_INDEPENDENT_IMP_FINITE]; ALL_TAC] THEN
5218   REWRITE_TAC[GSYM AFF_DIM_UNIV] THEN FIRST_ASSUM(SUBST1_TAC o SYM) THEN
5219   REWRITE_TAC[AFF_DIM_AFFINE_HULL] THEN
5220   ASM_SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; CARD_DIFF] THEN
5221   REWRITE_TAC[INT_ARITH `f + b - &1:int = c - &1 <=> f = c - b`] THEN
5222   ASM_SIMP_TAC[INT_OF_NUM_SUB; CARD_SUBSET; GSYM CARD_DIFF; INT_OF_NUM_EQ] THEN
5223   ASM_CASES_TAC `c:real^N->bool = b` THENL
5224    [EXISTS_TAC `{}:(real^N->bool)->bool` THEN
5225     ASM_REWRITE_TAC[CARD_CLAUSES; FINITE_RULES; NOT_IN_EMPTY; INTERS_0;
5226                     DIFF_EQ_EMPTY] THEN
5227     ASM_MESON_TAC[];
5228     ALL_TAC] THEN
5229   EXISTS_TAC `{affine hull (c DELETE a) |a| (a:real^N) IN (c DIFF b)}` THEN
5230   REWRITE_TAC[FORALL_IN_GSPEC] THEN REWRITE_TAC[SIMPLE_IMAGE] THEN
5231   ASM_SIMP_TAC[FINITE_IMAGE; FINITE_DIFF] THEN REPEAT CONJ_TAC THENL
5232    [MATCH_MP_TAC CARD_IMAGE_INJ THEN ASM_SIMP_TAC[FINITE_DIFF] THEN
5233     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN REWRITE_TAC[IN_DIFF] THEN
5234     STRIP_TAC THEN ASM_CASES_TAC `x:real^N = y` THEN ASM_REWRITE_TAC[] THEN
5235     UNDISCH_TAC `~affine_dependent(c:real^N->bool)` THEN
5236     REWRITE_TAC[affine_dependent] THEN EXISTS_TAC `x:real^N` THEN
5237     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC HULL_INC THEN ASM SET_TAC[];
5238     ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[IMAGE_o] THEN
5239     ONCE_REWRITE_TAC[GSYM SIMPLE_IMAGE] THEN
5240     W(MP_TAC o PART_MATCH (rhs o rand) AFFINE_HULL_INTERS o rand o snd) THEN
5241     ANTS_TAC THENL
5242      [MATCH_MP_TAC AFFINE_INDEPENDENT_SUBSET THEN
5243       EXISTS_TAC `c:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
5244       REWRITE_TAC[SUBSET; FORALL_IN_UNIONS; FORALL_IN_IMAGE;
5245                   IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN SET_TAC[];
5246       DISCH_THEN(SUBST1_TAC o SYM) THEN AP_TERM_TAC THEN
5247       GEN_REWRITE_TAC I [EXTENSION] THEN
5248       REWRITE_TAC[IN_INTERS; FORALL_IN_IMAGE] THEN ASM SET_TAC[]];
5249     REWRITE_TAC[GSYM AFF_DIM_EQ_HYPERPLANE] THEN
5250     ASM_SIMP_TAC[IN_DIFF; AFFINE_INDEPENDENT_DELETE;
5251                  AFF_DIM_AFFINE_INDEPENDENT; CARD_DELETE] THEN
5252     REWRITE_TAC[GSYM AFF_DIM_UNIV] THEN FIRST_ASSUM(SUBST1_TAC o SYM) THEN
5253     REWRITE_TAC[AFF_DIM_AFFINE_HULL] THEN
5254     ASM_SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; CARD_DIFF] THEN
5255     REPEAT STRIP_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
5256     MATCH_MP_TAC(GSYM INT_OF_NUM_SUB) THEN
5257     MATCH_MP_TAC(ARITH_RULE `~(c = 0) ==> 1 <= c`) THEN
5258     ASM_SIMP_TAC[CARD_EQ_0] THEN ASM SET_TAC[]]);;
5259
5260 let AFFINE_HYPERPLANE_SUMS_EQ_UNIV = prove
5261  (`!a b s.
5262         affine s /\
5263         ~(s INTER {v | a dot v = b} = {}) /\
5264         ~(s DIFF {v | a dot v = b} = {})
5265         ==> {x + y | x IN s /\ y IN {v | a dot v = b}} = (:real^N)`,
5266   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THENL
5267    [ASM_REWRITE_TAC[DOT_LZERO] THEN SET_TAC[]; ALL_TAC] THEN
5268   REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> b ==> a /\ c ==> d`] THEN
5269   GEN_REWRITE_TAC LAND_CONV [GSYM MEMBER_NOT_EMPTY] THEN
5270   REWRITE_TAC[LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN X_GEN_TAC `c:real^N` THEN
5271   ONCE_REWRITE_TAC[SET_RULE
5272    `{x + y:real^N | x IN s /\ P y} =
5273         {z | ?x y. x IN s /\ P y /\ z = x + y}`] THEN
5274   GEOM_ORIGIN_TAC `c:real^N` THEN REPEAT GEN_TAC THEN
5275   REWRITE_TAC[DOT_RADD; REAL_ARITH `b dot c + a = d <=> a = d - b dot c`] THEN
5276   REWRITE_TAC[IN_INTER; IN_ELIM_THM; DOT_RZERO] THEN
5277   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (SUBST1_TAC o SYM)) THEN
5278   ASM_SIMP_TAC[AFFINE_EQ_SUBSPACE; HULL_INC] THEN STRIP_TAC THEN
5279   REWRITE_TAC[VECTOR_ARITH `c + z:real^N = (c + x) + (c + y) <=>
5280                             z = c + x + y`] THEN
5281   REWRITE_TAC[SET_RULE
5282    `{z | ?x y. x IN s /\ P y /\ z = c + x + y} =
5283     IMAGE (\x. c + x) {x + y:real^N | x IN s /\ y IN {v | P v}}`] THEN
5284   MATCH_MP_TAC(SET_RULE
5285    `!f. (!x. g(f x) = x) /\ s = UNIV ==> IMAGE g s = UNIV`) THEN
5286   EXISTS_TAC `\x:real^N. x - c` THEN
5287   REWRITE_TAC[VECTOR_ARITH `c + x - c:real^N = x`] THEN
5288   MATCH_MP_TAC(MESON[SPAN_EQ_SELF] `subspace s /\ span s = t ==> s = t`) THEN
5289   CONJ_TAC THENL
5290    [ASM_SIMP_TAC[SUBSPACE_SUMS; SUBSPACE_HYPERPLANE];
5291     ALL_TAC] THEN
5292   REWRITE_TAC[GSYM DIM_EQ_FULL] THEN
5293   REWRITE_TAC[GSYM LE_ANTISYM; DIM_SUBSET_UNIV] THEN
5294   MATCH_MP_TAC(ARITH_RULE `m - 1 < n ==> m <= n`) THEN
5295   MATCH_MP_TAC LET_TRANS THEN EXISTS_TAC `dim {x:real^N | a dot x = &0}` THEN
5296   CONJ_TAC THENL [ASM_SIMP_TAC[DIM_HYPERPLANE; LE_REFL]; ALL_TAC] THEN
5297   MATCH_MP_TAC DIM_PSUBSET THEN
5298   ASM_SIMP_TAC[snd(EQ_IMP_RULE(SPEC_ALL SPAN_EQ_SELF));
5299                SUBSPACE_SUMS; SUBSPACE_HYPERPLANE] THEN
5300   REWRITE_TAC[PSUBSET; SUBSET; FORALL_IN_GSPEC] THEN
5301   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN CONJ_TAC THENL
5302    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
5303     MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `x:real^N`] THEN
5304     ASM_SIMP_TAC[SUBSPACE_0; VECTOR_ADD_LID];
5305     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
5306     REWRITE_TAC[NOT_FORALL_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
5307     X_GEN_TAC `x:real^N` THEN SIMP_TAC[IN_DIFF; IN_ELIM_THM] THEN
5308     DISCH_TAC THEN MAP_EVERY EXISTS_TAC [`x:real^N`; `vec 0:real^N`] THEN
5309     ASM_REWRITE_TAC[DOT_RZERO; VECTOR_ADD_RID]]);;
5310
5311 let AFF_DIM_AFFINE_INTER_HYPERPLANE = prove
5312  (`!a b s:real^N->bool.
5313         affine s
5314         ==> aff_dim(s INTER {x | a dot x = b}) =
5315                 if s INTER {v | a dot v = b} = {} then -- &1
5316                 else if s SUBSET {v | a dot v = b} then aff_dim s
5317                 else aff_dim s - &1`,
5318   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THENL
5319    [ASM_REWRITE_TAC[DOT_LZERO] THEN ASM_CASES_TAC `b = &0` THEN
5320     ASM_REWRITE_TAC[EMPTY_GSPEC; INTER_EMPTY; AFF_DIM_EMPTY] THEN
5321     SIMP_TAC[SET_RULE `{x | T} = UNIV`; IN_UNIV; INTER_UNIV; SUBSET_UNIV] THEN
5322     COND_CASES_TAC THEN ASM_REWRITE_TAC[AFF_DIM_EMPTY];
5323     STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[AFF_DIM_EMPTY] THEN
5324     COND_CASES_TAC THENL [AP_TERM_TAC THEN ASM SET_TAC[]; ALL_TAC] THEN
5325     MP_TAC(ISPECL [`s:real^N->bool`; `{x:real^N | a dot x = b}`]
5326         AFF_DIM_SUMS_INTER) THEN
5327     ASM_SIMP_TAC[AFFINE_HYPERPLANE; AFF_DIM_HYPERPLANE] THEN
5328     ASM_SIMP_TAC[AFFINE_HYPERPLANE_SUMS_EQ_UNIV; AFF_DIM_UNIV;
5329                  SET_RULE `~(s SUBSET t) ==> ~(s DIFF t = {})`] THEN
5330     SPEC_TAC(`aff_dim (s INTER {x:real^N | a dot x = b})`,`i:int`) THEN
5331     INT_ARITH_TAC]);;
5332
5333 let AFF_DIM_LT_FULL = prove
5334  (`!s. aff_dim s < &(dimindex(:N)) <=> ~(affine hull s = (:real^N))`,
5335   GEN_TAC THEN REWRITE_TAC[GSYM AFF_DIM_EQ_FULL] THEN
5336   MP_TAC(ISPEC `s:real^N->bool` AFF_DIM_LE_UNIV) THEN ARITH_TAC);;
5337
5338 let AFF_LOWDIM_SUBSET_HYPERPLANE = prove
5339  (`!s:real^N->bool.
5340         aff_dim s < &(dimindex(:N))
5341         ==> ?a b. ~(a = vec 0) /\ s SUBSET {x | a dot x = b}`,
5342   MATCH_MP_TAC SET_PROVE_CASES THEN CONJ_TAC THENL
5343    [DISCH_TAC THEN EXISTS_TAC `basis 1:real^N` THEN
5344     SIMP_TAC[EMPTY_SUBSET; BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1];
5345     MAP_EVERY X_GEN_TAC [`c:real^N`; `s:real^N->bool`] THEN
5346     CONV_TAC(ONCE_DEPTH_CONV(GEN_ALPHA_CONV `a:real^N`)) THEN
5347     GEN_GEOM_ORIGIN_TAC `c:real^N` ["a"] THEN
5348     SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; IN_INSERT; INT_OF_NUM_LT] THEN
5349     REPEAT GEN_TAC THEN DISCH_TAC THEN
5350     DISCH_THEN(MP_TAC o MATCH_MP LOWDIM_SUBSET_HYPERPLANE) THEN
5351     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^N` THEN
5352     STRIP_TAC THEN EXISTS_TAC `(u:real^N) dot c` THEN
5353     ASM_REWRITE_TAC[DOT_RADD; REAL_EQ_ADD_LCANCEL_0] THEN
5354     ASM_MESON_TAC[SPAN_INC; SUBSET_TRANS]]);;
5355
5356 (* ------------------------------------------------------------------------- *)
5357 (* An additional lemma about hyperplanes.                                    *)
5358 (* ------------------------------------------------------------------------- *)
5359
5360 let SUBSET_HYPERPLANES = prove
5361  (`!a b a' b'.
5362         {x | a dot x = b} SUBSET {x | a' dot x = b'} <=>
5363         {x | a dot x = b} = {} \/ {x | a' dot x = b'} = (:real^N) \/
5364         {x | a dot x = b} = {x | a' dot x = b'}`,
5365   REPEAT GEN_TAC THEN
5366   ASM_CASES_TAC `{x:real^N | a dot x = b} = {}` THEN
5367   ASM_REWRITE_TAC[EMPTY_SUBSET] THEN
5368   ASM_CASES_TAC `{x | a' dot x = b'} = (:real^N)` THEN
5369   ASM_REWRITE_TAC[SUBSET_UNIV] THEN
5370   RULE_ASSUM_TAC(REWRITE_RULE
5371    [HYPERPLANE_EQ_EMPTY; HYPERPLANE_EQ_UNIV]) THEN
5372   REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
5373   ASM_CASES_TAC `{x:real^N | a dot x = b} SUBSET {x | a' dot x = b'}` THEN
5374   ASM_REWRITE_TAC[] THEN
5375   MP_TAC(ISPECL [`{x:real^N | a dot x = b}`; `{x:real^N | a' dot x = b'}`]
5376         AFF_DIM_PSUBSET) THEN
5377   ASM_SIMP_TAC[PSUBSET;
5378                REWRITE_RULE[GSYM AFFINE_HULL_EQ] AFFINE_HYPERPLANE] THEN
5379   ASM_CASES_TAC `{x:real^N | a dot x = b} = {x | a' dot x = b'}` THEN
5380   ASM_REWRITE_TAC[SUBSET_REFL] THEN ASM_CASES_TAC `a':real^N = vec 0` THENL
5381    [ASM_CASES_TAC `b' = &0` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
5382     ASM_REWRITE_TAC[DOT_LZERO] THEN SET_TAC[];
5383     ALL_TAC] THEN
5384   ASM_CASES_TAC `a:real^N = vec 0` THENL
5385    [ASM_CASES_TAC `b = &0` THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
5386     ASM_REWRITE_TAC[DOT_LZERO] THEN SET_TAC[];
5387     ALL_TAC] THEN
5388   ASM_SIMP_TAC[AFF_DIM_HYPERPLANE; INT_LT_REFL]);;
5389
5390 (* ------------------------------------------------------------------------- *)
5391 (* Openness and compactness are preserved by convex hull operation.          *)
5392 (* ------------------------------------------------------------------------- *)
5393
5394 let OPEN_CONVEX_HULL = prove
5395  (`!s:real^N->bool. open s ==> open(convex hull s)`,
5396   REPEAT GEN_TAC THEN
5397   REWRITE_TAC[CONVEX_HULL_EXPLICIT; OPEN_CONTAINS_CBALL] THEN
5398   REWRITE_TAC[IN_ELIM_THM; SUBSET; LEFT_IMP_EXISTS_THM] THEN DISCH_TAC THEN
5399   MAP_EVERY X_GEN_TAC [`a:real^N`; `t:real^N->bool`; `u:real^N->real`] THEN
5400   STRIP_TAC THEN
5401   SUBGOAL_THEN `?b. !x:real^N. x IN t ==> &0 < b(x) /\ cball(x,b(x)) SUBSET s`
5402   STRIP_ASSUME_TAC THENL
5403    [REWRITE_TAC[GSYM SKOLEM_THM] THEN ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
5404   ABBREV_TAC `i = IMAGE (b:real^N->real) t` THEN
5405   EXISTS_TAC `inf i` THEN MP_TAC(SPEC `i:real->bool` INF_FINITE) THEN
5406   EXPAND_TAC "i" THEN ASM_REWRITE_TAC[FORALL_IN_IMAGE; IN_IMAGE] THEN
5407   ANTS_TAC THENL
5408    [EXPAND_TAC "i" THEN CONJ_TAC THENL
5409      [ASM_SIMP_TAC[FINITE_IMAGE]; ALL_TAC] THEN
5410     REWRITE_TAC[IMAGE_EQ_EMPTY] THEN
5411     ASM_MESON_TAC[SUM_CLAUSES; REAL_ARITH `~(&1 = &0)`];
5412     ALL_TAC] THEN
5413   STRIP_TAC THEN CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
5414   X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_CBALL; dist] THEN
5415   DISCH_TAC THEN EXISTS_TAC `IMAGE (\v:real^N. v + (y - a)) t` THEN
5416   EXISTS_TAC `\v. (u:real^N->real)(v - (y - a))` THEN
5417   ASM_SIMP_TAC[FINITE_IMAGE; FORALL_IN_IMAGE; SUM_IMAGE; VSUM_IMAGE;
5418                VECTOR_ARITH `v + a:real^N = w + a <=> v = w`] THEN
5419   ASM_REWRITE_TAC[o_DEF; VECTOR_ARITH `(v + a) - a:real^N = v`] THEN
5420   ASM_REWRITE_TAC[VECTOR_ADD_LDISTRIB; ETA_AX] THEN
5421   ASM_SIMP_TAC[VSUM_ADD; VSUM_RMUL] THEN
5422   CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
5423   X_GEN_TAC `z:real^N` THEN STRIP_TAC THEN
5424   SUBGOAL_THEN `z + (y - a) IN cball(z:real^N,b z)`
5425    (fun th -> ASM_MESON_TAC[th; SUBSET]) THEN
5426   REWRITE_TAC[IN_CBALL; dist; NORM_ARITH
5427    `norm(z - (z + a - y)) = norm(y - a)`] THEN
5428   ASM_MESON_TAC[REAL_LE_TRANS]);;
5429
5430 let COMPACT_CONVEX_COMBINATIONS = prove
5431  (`!s t. compact s /\ compact t
5432          ==> compact { (&1 - u) % x + u % y :real^N |
5433                       &0 <= u /\ u <= &1 /\ x IN s /\ y IN t}`,
5434   REPEAT STRIP_TAC THEN SUBGOAL_THEN
5435    `{ (&1 - u) % x + u % y :real^N | &0 <= u /\ u <= &1 /\ x IN s /\ y IN t} =
5436     IMAGE (\z. (&1 - drop(fstcart z)) % fstcart(sndcart z) +
5437                drop(fstcart z) % sndcart(sndcart z))
5438           { pastecart u w | u IN interval[vec 0,vec 1] /\
5439                             w IN { pastecart x y | x IN s /\ y IN t} }`
5440   SUBST1_TAC THENL
5441    [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE] THEN
5442     X_GEN_TAC `x:real^N` THEN
5443     REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
5444     CONV_TAC(ONCE_DEPTH_CONV UNWIND_CONV) THEN
5445     REWRITE_TAC[FSTCART_PASTECART; SNDCART_PASTECART] THEN
5446     REWRITE_TAC[IN_INTERVAL_1; GSYM EXISTS_DROP; DROP_VEC] THEN MESON_TAC[];
5447     ALL_TAC] THEN
5448   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
5449   ASM_SIMP_TAC[COMPACT_PCROSS; GSYM PCROSS; COMPACT_INTERVAL] THEN
5450   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
5451   X_GEN_TAC `z:real^(1,(N,N)finite_sum)finite_sum` THEN
5452   DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[PCROSS] THEN
5453   MATCH_MP_TAC CONTINUOUS_ADD THEN CONJ_TAC THEN
5454   MATCH_MP_TAC CONTINUOUS_MUL THEN REWRITE_TAC[o_DEF; LIFT_SUB; LIFT_DROP] THEN
5455   CONJ_TAC THEN TRY(MATCH_MP_TAC CONTINUOUS_SUB) THEN
5456   REWRITE_TAC[CONTINUOUS_CONST] THEN
5457   MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
5458   REWRITE_TAC[LINEAR_FSTCART; LINEAR_SNDCART; ETA_AX] THEN
5459   GEN_REWRITE_TAC RAND_CONV [GSYM o_DEF] THEN
5460   MATCH_MP_TAC LINEAR_COMPOSE THEN
5461   REWRITE_TAC[LINEAR_FSTCART; LINEAR_SNDCART]);;
5462
5463 let COMPACT_CONVEX_HULL = prove
5464  (`!s:real^N->bool. compact s ==> compact(convex hull s)`,
5465   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[CARATHEODORY] THEN
5466   SPEC_TAC(`dimindex(:N) + 1`,`n:num`) THEN
5467   ASM_CASES_TAC `s:real^N->bool = {}` THENL
5468    [ASM_REWRITE_TAC[SUBSET_EMPTY] THEN
5469     CONV_TAC(ONCE_DEPTH_CONV UNWIND_CONV) THEN
5470     REWRITE_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY] THEN
5471     REWRITE_TAC[SET_RULE `{x | F} = {}`; COMPACT_EMPTY];
5472     ALL_TAC] THEN
5473   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
5474   DISCH_THEN(X_CHOOSE_TAC `w:real^N`) THEN INDUCT_TAC THENL
5475    [SUBGOAL_THEN
5476      `{x:real^N | ?t. FINITE t /\ t SUBSET s /\ CARD t <= 0 /\
5477                       x IN convex hull t} = {}`
5478      (fun th -> REWRITE_TAC[th; COMPACT_EMPTY]) THEN
5479     REWRITE_TAC[EXTENSION; NOT_IN_EMPTY; LE; IN_ELIM_THM] THEN
5480     MESON_TAC[CARD_EQ_0; CONVEX_HULL_EMPTY; NOT_IN_EMPTY];
5481     ALL_TAC] THEN
5482   ASM_CASES_TAC `n = 0` THENL
5483    [ASM_REWRITE_TAC[ARITH_RULE `s <= SUC 0 <=> s = 0 \/ s = 1`] THEN
5484     UNDISCH_TAC `compact(s:real^N->bool)` THEN
5485     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
5486     REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
5487     REWRITE_TAC[TAUT `a /\ b /\ (c \/ d) /\ e <=>
5488                       (a /\ c) /\ (b /\ e) \/ (a /\ d) /\ (b /\ e)`] THEN
5489     REWRITE_TAC[GSYM HAS_SIZE; num_CONV `1`; HAS_SIZE_CLAUSES] THEN
5490     REWRITE_TAC[EXISTS_OR_THM; LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
5491     CONV_TAC(TOP_DEPTH_CONV UNWIND_CONV) THEN
5492     REWRITE_TAC[NOT_IN_EMPTY; CONVEX_HULL_EMPTY] THEN
5493     REWRITE_TAC[CONVEX_HULL_SING] THEN SET_TAC[];
5494     ALL_TAC] THEN
5495   SUBGOAL_THEN
5496    `{x:real^N | ?t. FINITE t /\ t SUBSET s /\ CARD t <= SUC n /\
5497                     x IN convex hull t} =
5498     { (&1 - u) % x + u % y :real^N |
5499                       &0 <= u /\ u <= &1 /\ x IN s /\
5500                       y IN {x | ?t. FINITE t /\ t SUBSET s /\
5501                                     CARD t <= n /\ x IN convex hull t}}`
5502    (fun th -> ASM_SIMP_TAC[th; COMPACT_CONVEX_COMBINATIONS]) THEN
5503   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
5504   X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
5505    [ALL_TAC;
5506     REWRITE_TAC[LEFT_IMP_EXISTS_THM; RIGHT_AND_EXISTS_THM;
5507                 LEFT_AND_EXISTS_THM] THEN
5508     MAP_EVERY X_GEN_TAC [`u:real^N`; `c:real`; `v:real^N`;
5509                          `t:real^N->bool`] THEN
5510     STRIP_TAC THEN EXISTS_TAC `(u:real^N) INSERT t` THEN
5511     ASM_REWRITE_TAC[FINITE_INSERT; INSERT_SUBSET] THEN
5512     ASM_SIMP_TAC[CARD_CLAUSES] THEN CONJ_TAC THENL
5513      [ASM_ARITH_TAC; ALL_TAC] THEN
5514     MATCH_MP_TAC IN_CONVEX_SET THEN
5515     ASM_REWRITE_TAC[CONVEX_CONVEX_HULL] THEN CONJ_TAC THEN
5516     ASM_MESON_TAC[HULL_SUBSET; SUBSET; IN_INSERT; HULL_MONO]] THEN
5517   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
5518   ASM_CASES_TAC `CARD(t:real^N->bool) <= n` THENL
5519    [MAP_EVERY EXISTS_TAC [`w:real^N`; `&1`; `x:real^N`] THEN
5520     ASM_REWRITE_TAC[REAL_POS; REAL_LE_REFL] THEN
5521     CONJ_TAC THENL [ASM_MESON_TAC[]; VECTOR_ARITH_TAC];
5522     ALL_TAC] THEN
5523   SUBGOAL_THEN `(t:real^N->bool) HAS_SIZE (SUC n)` MP_TAC THENL
5524    [ASM_REWRITE_TAC[HAS_SIZE] THEN ASM_ARITH_TAC;
5525     ALL_TAC] THEN
5526   REWRITE_TAC[HAS_SIZE_CLAUSES] THEN
5527   DISCH_THEN(X_CHOOSE_THEN `a:real^N` (X_CHOOSE_THEN `u:real^N->bool`
5528     STRIP_ASSUME_TAC)) THEN
5529   FIRST_X_ASSUM SUBST_ALL_TAC THEN
5530   UNDISCH_TAC `(x:real^N) IN convex hull (a INSERT u)` THEN
5531   RULE_ASSUM_TAC(REWRITE_RULE[FINITE_INSERT]) THEN
5532   ASM_CASES_TAC `(u:real^N->bool) = {}` THENL
5533    [ASM_REWRITE_TAC[CONVEX_HULL_SING; IN_SING] THEN
5534     DISCH_THEN SUBST_ALL_TAC THEN
5535     MAP_EVERY EXISTS_TAC [`a:real^N`; `&1`; `a:real^N`] THEN
5536     ASM_REWRITE_TAC[REAL_POS; REAL_LE_REFL] THEN
5537     CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
5538     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5539     EXISTS_TAC `{a:real^N}` THEN SIMP_TAC[FINITE_RULES] THEN
5540     REWRITE_TAC[CONVEX_HULL_SING; IN_SING] THEN
5541     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5542     SIMP_TAC[CARD_CLAUSES; FINITE_RULES; NOT_IN_EMPTY] THEN
5543     UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC;
5544     ALL_TAC] THEN
5545   ASM_SIMP_TAC[CONVEX_HULL_INSERT; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
5546   MAP_EVERY X_GEN_TAC [`c:real`; `d:real`; `z:real^N`] THEN STRIP_TAC THEN
5547   MAP_EVERY EXISTS_TAC [`a:real^N`; `d:real`; `z:real^N`] THEN
5548   FIRST_X_ASSUM(SUBST_ALL_TAC o MATCH_MP (REAL_ARITH
5549    `c + d = &1 ==> c = (&1 - d)`)) THEN
5550   ASM_REWRITE_TAC[REAL_ARITH `d <= &1 <=> &0 <= &1 - d`] THEN
5551   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5552   EXISTS_TAC `u:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
5553   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5554   UNDISCH_TAC `CARD ((a:real^N) INSERT u) <= SUC n` THEN
5555   ASM_SIMP_TAC[CARD_CLAUSES; LE_SUC]);;
5556
5557 let FINITE_IMP_COMPACT_CONVEX_HULL = prove
5558  (`!s:real^N->bool. FINITE s ==> compact(convex hull s)`,
5559   SIMP_TAC[FINITE_IMP_COMPACT; COMPACT_CONVEX_HULL]);;
5560
5561 let CONVEX_HULL_INTERIOR_SUBSET = prove
5562  (`!s:real^N->bool. convex hull (interior s) SUBSET interior (convex hull s)`,
5563   GEN_TAC THEN MATCH_MP_TAC INTERIOR_MAXIMAL THEN
5564   SIMP_TAC[OPEN_CONVEX_HULL; OPEN_INTERIOR; HULL_MONO; INTERIOR_SUBSET]);;
5565
5566 (* ------------------------------------------------------------------------- *)
5567 (* Extremal points of a simplex are some vertices.                           *)
5568 (* ------------------------------------------------------------------------- *)
5569
5570 let DIST_INCREASES_ONLINE = prove
5571  (`!a b d. ~(d = vec 0)
5572            ==> dist(a,b + d) > dist(a,b) \/ dist(a,b - d) > dist(a,b)`,
5573   REWRITE_TAC[dist; vector_norm; real_gt; GSYM NORM_POS_LT] THEN
5574   SIMP_TAC[SQRT_MONO_LT_EQ; DOT_POS_LE; SQRT_LT_0] THEN
5575   REWRITE_TAC[DOT_RSUB; DOT_RADD; DOT_LSUB; DOT_LADD] THEN REAL_ARITH_TAC);;
5576
5577 let NORM_INCREASES_ONLINE = prove
5578  (`!a:real^N d. ~(d = vec 0)
5579                 ==> norm(a + d) > norm(a) \/ norm(a - d) > norm(a)`,
5580   MP_TAC(ISPEC `vec 0 :real^N` DIST_INCREASES_ONLINE) THEN
5581   REWRITE_TAC[dist; VECTOR_SUB_LZERO; NORM_NEG]);;
5582
5583 let SIMPLEX_FURTHEST_LT = prove
5584  (`!a:real^N s.
5585         FINITE s
5586         ==> !x. x IN (convex hull s) /\ ~(x IN s)
5587                 ==> ?y. y IN (convex hull s) /\ norm(x - a) < norm(y - a)`,
5588   GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5589   REWRITE_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY] THEN
5590   MAP_EVERY X_GEN_TAC [`x:real^N`; `s:real^N->bool`] THEN
5591   ASM_CASES_TAC `s:real^N->bool = {}` THENL
5592    [ASM_REWRITE_TAC[CONVEX_HULL_SING; IN_SING] THEN MESON_TAC[];
5593     ALL_TAC] THEN
5594   ASM_SIMP_TAC[CONVEX_HULL_INSERT] THEN
5595   STRIP_TAC THEN X_GEN_TAC `y:real^N` THEN
5596   REWRITE_TAC[IN_ELIM_THM; LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
5597   MAP_EVERY X_GEN_TAC [`u:real`; `v:real`; `b:real^N`] THEN
5598   ASM_CASES_TAC `y:real^N IN (convex hull s)` THENL
5599    [REWRITE_TAC[IN_INSERT; DE_MORGAN_THM] THEN STRIP_TAC THEN
5600     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN
5601     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN
5602     X_GEN_TAC `c:real^N` THEN STRIP_TAC THEN
5603     MAP_EVERY EXISTS_TAC [`&0`; `&1`; `c:real^N`] THEN
5604     ASM_REWRITE_TAC[REAL_ADD_LID; REAL_POS] THEN VECTOR_ARITH_TAC;
5605     ALL_TAC] THEN
5606   ASM_CASES_TAC `u = &0` THENL
5607    [ASM_SIMP_TAC[REAL_ADD_LID; VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN
5608     ASM_MESON_TAC[VECTOR_MUL_LID];
5609     ALL_TAC] THEN
5610   ASM_CASES_TAC `v = &0` THENL
5611    [ASM_SIMP_TAC[REAL_ADD_RID; VECTOR_MUL_LZERO; VECTOR_ADD_RID] THEN
5612     ASM_CASES_TAC `u = &1` THEN ASM_REWRITE_TAC[VECTOR_MUL_LID] THEN
5613     ASM_CASES_TAC `y = a:real^N` THEN ASM_REWRITE_TAC[IN_INSERT] THEN
5614     ASM_MESON_TAC[];
5615     ALL_TAC] THEN
5616   REWRITE_TAC[IN_INSERT; DE_MORGAN_THM] THEN STRIP_TAC THEN
5617   MP_TAC(SPECL [`u:real`; `v:real`] REAL_DOWN2) THEN ANTS_TAC THENL
5618    [ASM_REWRITE_TAC[REAL_LT_LE]; ALL_TAC] THEN
5619   DISCH_THEN(X_CHOOSE_THEN `w:real` STRIP_ASSUME_TAC) THEN
5620   MP_TAC(ISPECL [`a:real^N`; `y:real^N`; `w % (x - b):real^N`]
5621                 DIST_INCREASES_ONLINE) THEN
5622   ANTS_TAC THENL
5623    [ASM_SIMP_TAC[VECTOR_MUL_EQ_0; REAL_LT_IMP_NZ] THEN
5624     REWRITE_TAC[VECTOR_ARITH `(x - y = vec 0) <=> (x = y)`] THEN
5625     DISCH_THEN SUBST_ALL_TAC THEN
5626     UNDISCH_TAC `~(y:real^N IN convex hull s)` THEN
5627     ASM_REWRITE_TAC[GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID];
5628     ALL_TAC] THEN
5629   ASM_REWRITE_TAC[dist; real_gt] THEN
5630   REWRITE_TAC[VECTOR_ARITH
5631    `((u % x + v % b) + w % (x - b) = (u + w) % x + (v - w) % b) /\
5632     ((u % x + v % b) - w % (x - b) = (u - w) % x + (v + w) % b)`] THEN
5633   STRIP_TAC THENL
5634    [MAP_EVERY EXISTS_TAC
5635      [`(u + w) % x + (v - w) % b:real^N`; `u + w`; `v - w`; `b:real^N`];
5636     MAP_EVERY EXISTS_TAC
5637      [`(u - w) % x + (v + w) % b:real^N`; `u - w`; `v + w`; `b:real^N`]] THEN
5638   ONCE_REWRITE_TAC[NORM_SUB] THEN ASM_REWRITE_TAC[] THEN
5639   ASM_SIMP_TAC[REAL_LE_ADD; REAL_LT_IMP_LE; REAL_SUB_LE] THEN
5640   UNDISCH_TAC `u + v = &1` THEN REAL_ARITH_TAC);;
5641
5642 let SIMPLEX_FURTHEST_LE = prove
5643  (`!a:real^N s.
5644         FINITE s /\ ~(s = {})
5645         ==> ?y. y IN s /\
5646                 !x. x IN (convex hull s) ==> norm(x - a) <= norm(y - a)`,
5647   REPEAT GEN_TAC THEN DISCH_TAC THEN
5648   MP_TAC(ISPEC `convex hull (s:real^N->bool)` DISTANCE_ATTAINS_SUP) THEN
5649   DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN ANTS_TAC THENL
5650    [ASM_SIMP_TAC[FINITE_IMP_COMPACT_CONVEX_HULL] THEN
5651     ASM_MESON_TAC[SUBSET_EMPTY; HULL_SUBSET];
5652     ALL_TAC] THEN
5653   ONCE_REWRITE_TAC[DIST_SYM] THEN REWRITE_TAC[dist] THEN
5654   ASM_MESON_TAC[SIMPLEX_FURTHEST_LT; REAL_NOT_LE]);;
5655
5656 let SIMPLEX_FURTHEST_LE_EXISTS = prove
5657  (`!a:real^N s.
5658         FINITE s
5659         ==> !x. x IN (convex hull s)
5660                 ==> ?y. y IN s /\ norm(x - a) <= norm(y - a)`,
5661   MESON_TAC[NOT_IN_EMPTY; CONVEX_HULL_EMPTY; SIMPLEX_FURTHEST_LE]);;
5662
5663 let SIMPLEX_EXTREMAL_LE = prove
5664  (`!s:real^N->bool.
5665         FINITE s /\ ~(s = {})
5666          ==> ?u v. u IN s /\ v IN s /\
5667                    !x y. x IN convex hull s /\ y IN convex hull s
5668                          ==> norm(x - y) <= norm(u - v)`,
5669   REPEAT STRIP_TAC THEN
5670   MP_TAC(ISPEC `convex hull (s:real^N->bool)` COMPACT_SUP_MAXDISTANCE) THEN
5671   ANTS_TAC THENL
5672    [ASM_SIMP_TAC[FINITE_IMP_COMPACT_CONVEX_HULL] THEN
5673     ASM_MESON_TAC[SUBSET_EMPTY; HULL_SUBSET];
5674     ALL_TAC] THEN
5675   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
5676   SIMP_TAC[] THEN ASM_MESON_TAC[SIMPLEX_FURTHEST_LT; REAL_NOT_LE; NORM_SUB]);;
5677
5678 let SIMPLEX_EXTREMAL_LE_EXISTS = prove
5679  (`!s:real^N->bool x y. FINITE s /\ x IN convex hull s /\ y IN convex hull s
5680                         ==> ?u v. u IN s /\ v IN s /\
5681                                   norm(x - y) <= norm(u - v)`,
5682   MESON_TAC[NOT_IN_EMPTY; CONVEX_HULL_EMPTY; SIMPLEX_EXTREMAL_LE]);;
5683
5684 let DIAMETER_CONVEX_HULL = prove
5685  (`!s:real^N->bool. diameter(convex hull s) = diameter s`,
5686   let lemma = prove
5687    (`!a b s. (!x. x IN s ==> dist(a,x) <= b)
5688              ==> (!x. x IN convex hull s ==> dist(a,x) <= b)`,
5689     REPEAT GEN_TAC THEN DISCH_TAC THEN
5690     MATCH_MP_TAC HULL_INDUCT THEN ASM_REWRITE_TAC[GSYM cball; CONVEX_CBALL]) in
5691   GEN_TAC THEN REWRITE_TAC[diameter; CONVEX_HULL_EQ_EMPTY] THEN
5692   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUP_EQ THEN
5693   REWRITE_TAC[FORALL_IN_GSPEC] THEN X_GEN_TAC `b:real` THEN
5694   EQ_TAC THENL [MESON_TAC[SUBSET; HULL_SUBSET]; ALL_TAC] THEN
5695   MATCH_MP_TAC(TAUT `!b. (a ==> b) /\ (b ==> c) ==> a ==> c`) THEN
5696   EXISTS_TAC `!x:real^N y. x IN s /\ y IN convex hull s ==> norm(x - y) <= b`
5697   THEN CONJ_TAC THENL
5698    [MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `x:real^N` THEN
5699     ASM_CASES_TAC `(x:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
5700     REWRITE_TAC[GSYM dist; lemma];
5701     ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
5702     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `y:real^N` THEN
5703     ASM_CASES_TAC `(y:real^N) IN convex hull s` THEN ASM_REWRITE_TAC[] THEN
5704     REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[DIST_SYM] dist); lemma]]);;
5705
5706 let DIAMETER_SIMPLEX = prove
5707  (`!s:real^N->bool.
5708         ~(s = {})
5709         ==> diameter(convex hull s) = sup { dist(x,y) | x IN s /\ y IN s}`,
5710   REWRITE_TAC[DIAMETER_CONVEX_HULL] THEN SIMP_TAC[diameter; dist]);;
5711
5712 (* ------------------------------------------------------------------------- *)
5713 (* Closest point of a convex set is unique, with a continuous projection.    *)
5714 (* ------------------------------------------------------------------------- *)
5715
5716 let CLOSER_POINTS_LEMMA = prove
5717  (`!y:real^N z.
5718         y dot z > &0
5719         ==> ?u. &0 < u /\
5720                 !v. &0 < v /\ v <= u ==> norm(v % z - y) < norm y`,
5721   REWRITE_TAC[NORM_LT; DOT_LSUB; DOT_RSUB; DOT_LMUL; DOT_RMUL;
5722               REAL_SUB_LDISTRIB; real_gt] THEN REPEAT GEN_TAC THEN
5723   REWRITE_TAC[REAL_ARITH `(a - b) - (c - d) < d <=> a < b + c`] THEN
5724   STRIP_TAC THEN SUBST1_TAC(VECTOR_ARITH `(z:real^N) dot y = y dot z`) THEN
5725   SIMP_TAC[GSYM REAL_ADD_LDISTRIB; REAL_LT_LMUL_EQ] THEN
5726   EXISTS_TAC `(y dot (z:real^N)) / (z dot z)` THEN
5727   SUBGOAL_THEN `&0 < z dot (z:real^N)` ASSUME_TAC THENL
5728    [ASM_MESON_TAC[DOT_POS_LT; DOT_RZERO; REAL_LT_REFL]; ALL_TAC] THEN
5729   ASM_SIMP_TAC[REAL_LT_DIV; REAL_LE_RDIV_EQ] THEN
5730   ASM_SIMP_TAC[REAL_ARITH `&0 < y /\ x <= y ==> x < y + y`; REAL_LT_MUL]);;
5731
5732 let CLOSER_POINT_LEMMA = prove
5733  (`!x y z. (y - x) dot (z - x) > &0
5734            ==> ?u. &0 < u /\ u <= &1 /\ dist(x + u % (z - x),y) < dist(x,y)`,
5735   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP CLOSER_POINTS_LEMMA) THEN
5736   ONCE_REWRITE_TAC[DIST_SYM] THEN REWRITE_TAC[dist; NORM_LT] THEN
5737   REWRITE_TAC[VECTOR_ARITH
5738    `(y - (x + z)) dot (y - (x + z)) = (z - (y - x)) dot (z - (y - x))`] THEN
5739   DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
5740   EXISTS_TAC `min u (&1)` THEN
5741   ASM_SIMP_TAC[REAL_LT_MIN; REAL_MIN_LE; REAL_LT_01; REAL_LE_REFL]);;
5742
5743 let ANY_CLOSEST_POINT_DOT = prove
5744  (`!s a x y:real^N.
5745         convex s /\ closed s /\ x IN s /\ y IN s /\
5746         (!z. z IN s ==> dist(a,x) <= dist(a,z))
5747         ==> (a - x) dot (y - x) <= &0`,
5748   REPEAT STRIP_TAC THEN REWRITE_TAC[REAL_ARITH `x <= &0 <=> ~(x > &0)`] THEN
5749   DISCH_THEN(MP_TAC o MATCH_MP CLOSER_POINT_LEMMA) THEN
5750   DISCH_THEN(X_CHOOSE_THEN `u:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5751   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5752   REWRITE_TAC[REAL_NOT_LT] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
5753   FIRST_X_ASSUM MATCH_MP_TAC THEN
5754   REWRITE_TAC[VECTOR_ARITH `x + u % (y - x) = (&1 - u) % x + u % y`] THEN
5755   MATCH_MP_TAC IN_CONVEX_SET THEN ASM_SIMP_TAC[REAL_LT_IMP_LE]);;
5756
5757 let ANY_CLOSEST_POINT_UNIQUE = prove
5758  (`!s a x y:real^N.
5759         convex s /\ closed s /\ x IN s /\ y IN s /\
5760         (!z. z IN s ==> dist(a,x) <= dist(a,z)) /\
5761         (!z. z IN s ==> dist(a,y) <= dist(a,z))
5762         ==> x = y`,
5763   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
5764   REWRITE_TAC[GSYM NORM_LE_0; NORM_LE_SQUARE] THEN
5765   SUBGOAL_THEN `(a - x:real^N) dot (y - x) <= &0 /\ (a - y) dot (x - y) <= &0`
5766   MP_TAC THENL [ASM_MESON_TAC[ANY_CLOSEST_POINT_DOT]; ALL_TAC] THEN
5767   REWRITE_TAC[NORM_LT; DOT_LSUB; DOT_RSUB] THEN REAL_ARITH_TAC);;
5768
5769 let CLOSEST_POINT_UNIQUE = prove
5770  (`!s a x:real^N.
5771         convex s /\ closed s /\ x IN s /\
5772         (!z. z IN s ==> dist(a,x) <= dist(a,z))
5773         ==> x = closest_point s a`,
5774   REPEAT STRIP_TAC THEN MATCH_MP_TAC ANY_CLOSEST_POINT_UNIQUE THEN
5775   MAP_EVERY EXISTS_TAC [`s:real^N->bool`; `a:real^N`] THEN
5776   ASM_MESON_TAC[CLOSEST_POINT_EXISTS; MEMBER_NOT_EMPTY]);;
5777
5778 let CLOSEST_POINT_DOT = prove
5779  (`!s a x:real^N.
5780         convex s /\ closed s /\ x IN s
5781         ==> (a - closest_point s a) dot (x - closest_point s a) <= &0`,
5782   REPEAT STRIP_TAC THEN MATCH_MP_TAC ANY_CLOSEST_POINT_DOT THEN
5783   EXISTS_TAC `s:real^N->bool` THEN
5784   ASM_MESON_TAC[CLOSEST_POINT_EXISTS; MEMBER_NOT_EMPTY]);;
5785
5786 let CLOSEST_POINT_LT = prove
5787  (`!s a x. convex s /\ closed s /\ x IN s /\ ~(x = closest_point s a)
5788            ==> dist(a,closest_point s a) < dist(a,x)`,
5789   REPEAT GEN_TAC THEN
5790   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5791   REWRITE_TAC[GSYM REAL_NOT_LE; CONTRAPOS_THM] THEN
5792   DISCH_TAC THEN MATCH_MP_TAC CLOSEST_POINT_UNIQUE THEN
5793   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[CLOSEST_POINT_LE; REAL_LE_TRANS]);;
5794
5795 let CLOSEST_POINT_LIPSCHITZ = prove
5796  (`!s x y:real^N.
5797         convex s /\ closed s /\ ~(s = {})
5798         ==> dist(closest_point s x,closest_point s y) <= dist(x,y)`,
5799   REPEAT STRIP_TAC THEN REWRITE_TAC[dist; NORM_LE] THEN
5800   SUBGOAL_THEN
5801    `(x - closest_point s x :real^N) dot
5802     (closest_point s y - closest_point s x) <= &0 /\
5803     (y - closest_point s y) dot
5804     (closest_point s x - closest_point s y) <= &0`
5805   MP_TAC THENL
5806    [CONJ_TAC THEN MATCH_MP_TAC ANY_CLOSEST_POINT_DOT THEN
5807     EXISTS_TAC `s:real^N->bool` THEN ASM_MESON_TAC[CLOSEST_POINT_EXISTS];
5808     MP_TAC(ISPEC `(x - closest_point s x :real^N) - (y - closest_point s y)`
5809                  DOT_POS_LE) THEN
5810     REWRITE_TAC[NORM_LT; DOT_LSUB; DOT_RSUB; DOT_SYM] THEN REAL_ARITH_TAC]);;
5811
5812 let CONTINUOUS_AT_CLOSEST_POINT = prove
5813  (`!s x. convex s /\ closed s /\ ~(s = {})
5814          ==> (closest_point s) continuous (at x)`,
5815   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_at] THEN
5816   ASM_MESON_TAC[CLOSEST_POINT_LIPSCHITZ; REAL_LET_TRANS]);;
5817
5818 let CONTINUOUS_ON_CLOSEST_POINT = prove
5819  (`!s t. convex s /\ closed s /\ ~(s = {})
5820          ==> (closest_point s) continuous_on t`,
5821   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_CLOSEST_POINT]);;
5822
5823 (* ------------------------------------------------------------------------- *)
5824 (* Relating closest points and orthogonality.                                *)
5825 (* ------------------------------------------------------------------------- *)
5826
5827 let ANY_CLOSEST_POINT_AFFINE_ORTHOGONAL = prove
5828  (`!s a b:real^N.
5829         affine s /\ b IN s /\ (!x. x IN s ==> dist(a,b) <= dist(a,x))
5830         ==> (!x. x IN s ==> orthogonal (x - b) (a - b))`,
5831   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `b:real^N` THEN
5832   REWRITE_TAC[DIST_0; VECTOR_SUB_RZERO; orthogonal; dist; NORM_LE] THEN
5833   REWRITE_TAC[DOT_LSUB] THEN REWRITE_TAC[DOT_RSUB] THEN
5834   REWRITE_TAC[DOT_SYM; REAL_ARITH `a <= a - y - (y - x) <=> &2 * y <= x`] THEN
5835   REPEAT STRIP_TAC THEN ASM_CASES_TAC `x:real^N = vec 0` THEN
5836   ASM_REWRITE_TAC[DOT_RZERO] THEN FIRST_X_ASSUM(fun th ->
5837    MP_TAC(SPEC `vec 0 + --((a dot x) / (x dot x)) % (x - vec 0:real^N)` th) THEN
5838    MP_TAC(SPEC `vec 0 + (a dot x) / (x dot x) % (x - vec 0:real^N)` th)) THEN
5839   ASM_SIMP_TAC[IN_AFFINE_ADD_MUL_DIFF] THEN
5840   REWRITE_TAC[VECTOR_SUB_RZERO; VECTOR_ADD_LID; DOT_RMUL] THEN
5841   REWRITE_TAC[DOT_LMUL; IMP_IMP] THEN DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
5842    `&2 * x * a <= b * c * z /\ &2 * --x * a <= --b * --c * z
5843     ==> &2 * abs(x * a) <= b * c * z`)) THEN
5844   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
5845   ASM_SIMP_TAC[REAL_NOT_LE; REAL_DIV_RMUL; DOT_EQ_0] THEN
5846   MATCH_MP_TAC(REAL_ARITH `~(x = &0) ==> x < &2 * abs x`) THEN
5847   RULE_ASSUM_TAC(REWRITE_RULE[GSYM DOT_EQ_0]) THEN
5848   REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD);;
5849
5850 let ORTHOGONAL_ANY_CLOSEST_POINT = prove
5851  (`!s a b:real^N.
5852         b IN s /\ (!x. x IN s ==> orthogonal (x - b) (a - b))
5853         ==> (!x. x IN s ==> dist(a,b) <= dist(a,x))`,
5854   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `b:real^N` THEN
5855   REWRITE_TAC[dist; NORM_LE; orthogonal; VECTOR_SUB_RZERO] THEN
5856   SIMP_TAC[DOT_LSUB; DOT_RSUB; DOT_SYM] THEN
5857   REWRITE_TAC[DOT_POS_LE; REAL_ARITH `a <= a - &0 - (&0 - x) <=> &0 <= x`]);;
5858
5859 let CLOSEST_POINT_AFFINE_ORTHOGONAL = prove
5860  (`!s a:real^N x.
5861         affine s /\ ~(s = {}) /\ x IN s
5862         ==> orthogonal (x - closest_point s a) (a - closest_point s a)`,
5863   GEN_TAC THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
5864   DISCH_TAC THEN DISCH_TAC THEN GEN_TAC THEN
5865   MATCH_MP_TAC ANY_CLOSEST_POINT_AFFINE_ORTHOGONAL THEN
5866   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CLOSEST_POINT_EXISTS THEN
5867   ASM_SIMP_TAC[CLOSED_AFFINE]);;
5868
5869 let CLOSEST_POINT_AFFINE_ORTHOGONAL_EQ = prove
5870  (`!s a b:real^N.
5871         affine s /\ b IN s
5872         ==> (closest_point s a = b <=>
5873              !x. x IN s ==> orthogonal (x - b) (a - b))`,
5874   REPEAT STRIP_TAC THEN EQ_TAC THENL
5875    [ASM_MESON_TAC[CLOSEST_POINT_AFFINE_ORTHOGONAL; MEMBER_NOT_EMPTY];
5876     DISCH_TAC THEN CONV_TAC SYM_CONV THEN
5877     MATCH_MP_TAC CLOSEST_POINT_UNIQUE THEN
5878     ASM_SIMP_TAC[CLOSED_AFFINE; AFFINE_IMP_CONVEX] THEN
5879     MATCH_MP_TAC ORTHOGONAL_ANY_CLOSEST_POINT THEN ASM_REWRITE_TAC[]]);;
5880
5881 (* ------------------------------------------------------------------------- *)
5882 (* Various point-to-set separating/supporting hyperplane theorems.           *)
5883 (* ------------------------------------------------------------------------- *)
5884
5885 let SUPPORTING_HYPERPLANE_COMPACT_POINT_SUP = prove
5886  (`!a c s:real^N->bool.
5887         compact s /\ ~(s = {})
5888         ==> ?b y. y IN s /\ a dot (y - c) = b /\
5889                   (!x. x IN s ==> a dot (x - c) <= b)`,
5890   REPEAT STRIP_TAC THEN
5891   MP_TAC(ISPECL [`\x:real^N. a dot (x - c)`; `s:real^N->bool`]
5892         CONTINUOUS_ATTAINS_SUP) THEN
5893   ASM_REWRITE_TAC[] THEN
5894   ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
5895   SUBGOAL_THEN `(\x:real^N. a dot (x - c)) = (\x. a dot x) o (\x. x - c)`
5896   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
5897   REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
5898   SIMP_TAC[CONTINUOUS_ON_LIFT_DOT; CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST;
5899            CONTINUOUS_ON_ID]);;
5900
5901 let SUPPORTING_HYPERPLANE_COMPACT_POINT_INF = prove
5902  (`!a c s:real^N->bool.
5903         compact s /\ ~(s = {})
5904         ==> ?b y. y IN s /\ a dot (y - c) = b /\
5905                   (!x. x IN s ==> a dot (x - c) >= b)`,
5906   REPEAT STRIP_TAC THEN
5907   MP_TAC(ISPECL [`--a:real^N`; `c:real^N`; `s:real^N->bool`]
5908     SUPPORTING_HYPERPLANE_COMPACT_POINT_SUP) THEN
5909   ASM_REWRITE_TAC[] THEN
5910   DISCH_THEN(X_CHOOSE_THEN `b:real`
5911    (fun th -> EXISTS_TAC `--b:real` THEN MP_TAC th)) THEN
5912   REWRITE_TAC[DOT_LNEG; REAL_ARITH `x >= -- b <=> --x <= b`] THEN
5913   REWRITE_TAC[REAL_NEG_EQ]);;
5914
5915 let SUPPORTING_HYPERPLANE_CLOSED_POINT = prove
5916  (`!s z:real^N. convex s /\ closed s /\ ~(s = {}) /\ ~(z IN s)
5917                 ==> ?a b y. a dot z < b /\ y IN s /\ (a dot y = b) /\
5918                             (!x. x IN s ==> a dot x >= b)`,
5919   REPEAT STRIP_TAC THEN
5920   MP_TAC(ISPECL [`s:real^N->bool`; `z:real^N`] DISTANCE_ATTAINS_INF) THEN
5921   ASM_REWRITE_TAC[] THEN
5922   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
5923   EXISTS_TAC `y - z:real^N` THEN EXISTS_TAC `(y - z:real^N) dot y` THEN
5924   EXISTS_TAC `y:real^N` THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
5925   ASM_REWRITE_TAC[GSYM DOT_RSUB; DOT_POS_LT; VECTOR_SUB_EQ] THEN
5926   CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN X_GEN_TAC `x:real^N` THEN
5927   DISCH_TAC THEN SUBGOAL_THEN
5928    `!u. &0 <= u /\ u <= &1 ==> dist(z:real^N,y) <= dist(z,(&1 - u) % y + u % x)`
5929   MP_TAC THENL [ASM_MESON_TAC[CONVEX_ALT]; ALL_TAC] THEN
5930   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
5931   REWRITE_TAC[real_ge; REAL_NOT_LE; NOT_FORALL_THM; NOT_IMP] THEN
5932   GEN_REWRITE_TAC LAND_CONV [REAL_ARITH `x < y <=> y - x > &0`] THEN
5933   REWRITE_TAC[VECTOR_ARITH
5934    `(a - b) dot x - (a - b) dot y = (b - a) dot (y - x)`] THEN
5935   DISCH_THEN(MP_TAC o MATCH_MP CLOSER_POINT_LEMMA) THEN
5936   REWRITE_TAC[VECTOR_ARITH `y + u % (x - y) = (&1 - u) % y + u % x`] THEN
5937   MESON_TAC[REAL_LT_IMP_LE]);;
5938
5939 let SEPARATING_HYPERPLANE_CLOSED_POINT_INSET = prove
5940  (`!s z:real^N. convex s /\ closed s /\ ~(s = {}) /\ ~(z IN s)
5941                 ==> ?a b. a IN s /\
5942                           (a - z) dot z < b /\
5943                           (!x. x IN s ==> (a - z) dot x > b)`,
5944   REPEAT STRIP_TAC THEN
5945   MP_TAC(ISPECL [`s:real^N->bool`; `z:real^N`] DISTANCE_ATTAINS_INF) THEN
5946   ASM_REWRITE_TAC[] THEN
5947   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
5948   EXISTS_TAC `y:real^N` THEN ASM_REWRITE_TAC[] THEN
5949   EXISTS_TAC `(y - z:real^N) dot z + norm(y - z) pow 2 / &2` THEN
5950   SUBGOAL_THEN `&0 < norm(y - z:real^N)` ASSUME_TAC THENL
5951    [ASM_MESON_TAC[NORM_POS_LT; VECTOR_SUB_EQ]; ALL_TAC] THEN
5952   ASM_SIMP_TAC[REAL_LT_ADDR; REAL_LT_DIV; REAL_POW_LT;
5953                REAL_OF_NUM_LT; ARITH] THEN
5954   REWRITE_TAC[NORM_POW_2; REAL_ARITH `a > b + c <=> c < a - b`] THEN
5955   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
5956   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
5957   ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
5958   REWRITE_TAC[VECTOR_ARITH
5959    `((y - z) dot x - (y - z) dot z) * &2 - (y - z) dot (y - z) =
5960     &2 * ((y - z) dot (x - y)) + (y - z) dot (y - z)`] THEN
5961   MATCH_MP_TAC(REAL_ARITH `~(--x > &0) /\ &0 < y ==> &0 < &2 * x + y`) THEN
5962   ASM_SIMP_TAC[GSYM NORM_POW_2; REAL_POW_LT] THEN
5963   REWRITE_TAC[GSYM DOT_LNEG; VECTOR_NEG_SUB] THEN
5964   DISCH_THEN(MP_TAC o MATCH_MP CLOSER_POINT_LEMMA) THEN
5965   REWRITE_TAC[NOT_EXISTS_THM] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
5966   GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5967   REWRITE_TAC[REAL_NOT_LT] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
5968   REWRITE_TAC[VECTOR_ARITH `y + u % (x - y) = (&1 - u) % y + u % x`] THEN
5969   ASM_MESON_TAC[CONVEX_ALT; REAL_LT_IMP_LE]);;
5970
5971 let SEPARATING_HYPERPLANE_CLOSED_0_INSET = prove
5972  (`!s:real^N->bool.
5973         convex s /\ closed s /\ ~(s = {}) /\ ~(vec 0 IN s)
5974         ==> ?a b. a IN s /\ ~(a = vec 0) /\ &0 < b /\
5975                   (!x. x IN s ==> a dot x > b)`,
5976   REPEAT GEN_TAC THEN DISCH_TAC THEN
5977   FIRST_ASSUM(MP_TAC o MATCH_MP SEPARATING_HYPERPLANE_CLOSED_POINT_INSET) THEN
5978   REWRITE_TAC[DOT_RZERO; real_gt] THEN
5979   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
5980   SIMP_TAC[VECTOR_SUB_RZERO] THEN ASM_MESON_TAC[]);;
5981
5982 let SEPARATING_HYPERPLANE_CLOSED_POINT = prove
5983  (`!s z:real^N. convex s /\ closed s /\ ~(z IN s)
5984                 ==> ?a b. a dot z < b /\ (!x. x IN s ==> a dot x > b)`,
5985   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
5986    [MAP_EVERY EXISTS_TAC [`--z:real^N`; `&1`] THEN
5987     SIMP_TAC[DOT_LNEG; REAL_ARITH `&0 <= x ==> --x < &1`; DOT_POS_LE] THEN
5988     ASM_MESON_TAC[NOT_IN_EMPTY];
5989     ALL_TAC] THEN
5990   ASM_MESON_TAC[SEPARATING_HYPERPLANE_CLOSED_POINT_INSET]);;
5991
5992 let SEPARATING_HYPERPLANE_CLOSED_0 = prove
5993  (`!s:real^N->bool.
5994         convex s /\ closed s /\ ~(vec 0 IN s)
5995         ==> ?a b. ~(a = vec 0) /\ &0 < b /\ (!x. x IN s ==> a dot x > b)`,
5996   REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
5997    [EXISTS_TAC `basis 1:real^N` THEN EXISTS_TAC `&1` THEN
5998     ASM_REWRITE_TAC[NOT_IN_EMPTY; REAL_LT_01; GSYM NORM_POS_LT] THEN
5999     ASM_SIMP_TAC[NORM_BASIS; DIMINDEX_GE_1; LE_REFL; REAL_LT_01];
6000     FIRST_X_ASSUM(MP_TAC o MATCH_MP SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
6001     REWRITE_TAC[DOT_RZERO; real_gt] THEN
6002     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
6003     ASM_MESON_TAC[MEMBER_NOT_EMPTY; DOT_LZERO; REAL_LT_ANTISYM]]);;
6004
6005 (* ------------------------------------------------------------------------- *)
6006 (* Now set-to-set for closed/compact sets.                                   *)
6007 (* ------------------------------------------------------------------------- *)
6008
6009 let SEPARATING_HYPERPLANE_CLOSED_COMPACT = prove
6010  (`!s t. convex s /\ closed s /\
6011          convex t /\ compact t /\ ~(t = {}) /\ DISJOINT s t
6012          ==> ?a:real^N b. (!x. x IN s ==> a dot x < b) /\
6013                           (!x. x IN t ==> a dot x > b)`,
6014   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
6015    [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
6016     FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN
6017     REWRITE_TAC[BOUNDED_POS] THEN
6018     DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THEN
6019     SUBGOAL_THEN `?z:real^N. norm(z) = b + &1` CHOOSE_TAC THENL
6020      [ASM_SIMP_TAC[VECTOR_CHOOSE_SIZE; REAL_ARITH `&0 < b ==> &0 <= b + &1`];
6021       ALL_TAC] THEN
6022     MP_TAC(SPECL [`t:real^N->bool`; `z:real^N`]
6023        SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
6024     ANTS_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
6025     ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN
6026     ASM_MESON_TAC[REAL_ARITH `~(b + &1 <= b)`];
6027     ALL_TAC] THEN
6028   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN t}`; `vec 0 :real^N`]
6029                 SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
6030   ASM_SIMP_TAC[CLOSED_COMPACT_DIFFERENCES; CONVEX_DIFFERENCES] THEN
6031   ANTS_TAC THENL
6032    [REWRITE_TAC[IN_ELIM_THM] THEN ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN
6033     REWRITE_TAC[VECTOR_SUB_EQ] THEN
6034     ASM_MESON_TAC[DISJOINT; NOT_IN_EMPTY; IN_INTER; EXTENSION];
6035     ALL_TAC] THEN
6036   SIMP_TAC[DOT_RZERO; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
6037   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN
6038   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6039   GEN_REWRITE_TAC LAND_CONV [SWAP_FORALL_THM] THEN
6040   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [SWAP_FORALL_THM] THEN
6041   ONCE_REWRITE_TAC[IMP_CONJ] THEN REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN
6042   REWRITE_TAC[LEFT_FORALL_IMP_THM; EXISTS_REFL; DOT_RSUB] THEN
6043   REWRITE_TAC[real_gt; REAL_LT_SUB_LADD] THEN DISCH_TAC THEN
6044   EXISTS_TAC `--a:real^N` THEN
6045   MP_TAC(SPEC `IMAGE (\x:real^N. a dot x) t` SUP) THEN
6046   ABBREV_TAC `k = sup (IMAGE (\x:real^N. a dot x) t)` THEN
6047   ASM_REWRITE_TAC[FORALL_IN_IMAGE; IMAGE_EQ_EMPTY] THEN ANTS_TAC THENL
6048    [ASM_MESON_TAC[REAL_ARITH `b + x < y ==> x <= y - b`; MEMBER_NOT_EMPTY];
6049     ALL_TAC] THEN
6050   STRIP_TAC THEN EXISTS_TAC `--(k + b / &2)` THEN
6051   REWRITE_TAC[DOT_LNEG; REAL_LT_NEG2] THEN REPEAT STRIP_TAC THEN
6052   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH;
6053                REAL_ARITH `&0 < b /\ x <= k ==> x < k + b`] THEN
6054   FIRST_X_ASSUM(MP_TAC o SPEC `k - b / &2`) THEN
6055   ASM_SIMP_TAC[REAL_ARITH `k <= k - b2 <=> ~(&0 < b2)`; REAL_LT_DIV;
6056      REAL_OF_NUM_LT; ARITH; NOT_FORALL_THM; LEFT_IMP_EXISTS_THM; NOT_IMP] THEN
6057   X_GEN_TAC `y:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6058   MATCH_MP_TAC(REAL_ARITH
6059    `!b. (b2 + b2 = b) /\ b + ay < ax ==> ~(ay <= k - b2) ==> k + b2 < ax`) THEN
6060   ASM_MESON_TAC[REAL_HALF]);;
6061
6062 let SEPARATING_HYPERPLANE_COMPACT_CLOSED = prove
6063  (`!s t. convex s /\ compact s /\ ~(s = {}) /\
6064          convex t /\ closed t /\ DISJOINT s t
6065          ==> ?a:real^N b. (!x. x IN s ==> a dot x < b) /\
6066                           (!x. x IN t ==> a dot x > b)`,
6067   REPEAT STRIP_TAC THEN
6068   MP_TAC(ISPECL [`t:real^N->bool`; `s:real^N->bool`]
6069       SEPARATING_HYPERPLANE_CLOSED_COMPACT) THEN
6070   ANTS_TAC THENL [ASM_MESON_TAC[DISJOINT_SYM]; ALL_TAC] THEN
6071   REWRITE_TAC[real_gt] THEN
6072   DISCH_THEN(X_CHOOSE_THEN `a:real^N` (X_CHOOSE_THEN `b:real`
6073     STRIP_ASSUME_TAC)) THEN
6074   MAP_EVERY EXISTS_TAC [`--a:real^N`; `--b:real`] THEN
6075   ASM_REWRITE_TAC[REAL_LT_NEG2; DOT_LNEG]);;
6076
6077 let SEPARATING_HYPERPLANE_COMPACT_CLOSED_NONZERO = prove
6078  (`!s t:real^N->bool.
6079            convex s /\ compact s /\ ~(s = {}) /\
6080            convex t /\ closed t /\ DISJOINT s t
6081            ==> ?a b. ~(a = vec 0) /\
6082                      (!x. x IN s ==> a dot x < b) /\
6083                      (!x. x IN t ==> a dot x > b)`,
6084   REPEAT GEN_TAC THEN ASM_CASES_TAC `t:real^N->bool = {}` THENL
6085    [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN STRIP_TAC THEN
6086     EXISTS_TAC `basis 1:real^N` THEN
6087     SUBGOAL_THEN
6088      `bounded(IMAGE (\x:real^N. lift(basis 1 dot x)) s)`
6089     MP_TAC THENL
6090      [MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
6091       MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
6092       ASM_SIMP_TAC[REWRITE_RULE[o_DEF] CONTINUOUS_ON_LIFT_DOT];
6093       REWRITE_TAC[BOUNDED_POS_LT; FORALL_IN_IMAGE; NORM_LIFT] THEN
6094       SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL] THEN
6095       MESON_TAC[REAL_ARITH `abs x < b ==> x < b`]];
6096     STRIP_TAC THEN
6097     MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`]
6098         SEPARATING_HYPERPLANE_COMPACT_CLOSED) THEN
6099     ASM_REWRITE_TAC[] THEN
6100     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
6101     ASM_CASES_TAC `a:real^N = vec 0` THEN ASM_REWRITE_TAC[] THEN
6102     REWRITE_TAC[DOT_LZERO; real_gt] THEN
6103     ASM_MESON_TAC[REAL_LT_ANTISYM; MEMBER_NOT_EMPTY]]);;
6104
6105 let SEPARATING_HYPERPLANE_COMPACT_COMPACT = prove
6106  (`!s t:real^N->bool.
6107            convex s /\ compact s /\ convex t /\ compact t /\ DISJOINT s t
6108            ==> ?a b. ~(a = vec 0) /\
6109                      (!x. x IN s ==> a dot x < b) /\
6110                      (!x. x IN t ==> a dot x > b)`,
6111   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
6112    [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN STRIP_TAC THEN
6113     EXISTS_TAC `--basis 1:real^N` THEN
6114     SUBGOAL_THEN
6115      `bounded(IMAGE (\x:real^N. lift(basis 1 dot x)) t)`
6116     MP_TAC THENL
6117      [MATCH_MP_TAC COMPACT_IMP_BOUNDED THEN
6118       MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
6119       ASM_SIMP_TAC[REWRITE_RULE[o_DEF] CONTINUOUS_ON_LIFT_DOT];
6120       REWRITE_TAC[BOUNDED_POS_LT; FORALL_IN_IMAGE; NORM_LIFT] THEN
6121       SIMP_TAC[VECTOR_NEG_EQ_0; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL] THEN
6122       DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THEN
6123       EXISTS_TAC `--b:real` THEN REWRITE_TAC[DOT_LNEG] THEN
6124       REWRITE_TAC[REAL_ARITH `--x > --y <=> x < y`] THEN
6125       ASM_MESON_TAC[REAL_ARITH `abs x < b ==> x < b`]];
6126     STRIP_TAC THEN
6127     MATCH_MP_TAC SEPARATING_HYPERPLANE_COMPACT_CLOSED_NONZERO THEN
6128     ASM_SIMP_TAC[COMPACT_IMP_CLOSED]]);;
6129
6130 (* ------------------------------------------------------------------------- *)
6131 (* General case without assuming closure and getting non-strict separation.  *)
6132 (* ------------------------------------------------------------------------- *)
6133
6134 let SEPARATING_HYPERPLANE_SET_0_INSPAN = prove
6135  (`!s:real^N->bool.
6136         convex s /\ ~(s = {}) /\ ~(vec 0 IN s)
6137         ==> ?a b. a IN span s /\ ~(a = vec 0) /\
6138                   !x. x IN s ==> &0 <= a dot x`,
6139   REPEAT STRIP_TAC THEN
6140   ABBREV_TAC `k = \c:real^N. {x | &0 <= c dot x}` THEN
6141   SUBGOAL_THEN
6142    `~((span s INTER frontier(cball(vec 0:real^N,&1))) INTER
6143       (INTERS (IMAGE k (s:real^N->bool))) = {})`
6144   MP_TAC THENL
6145    [ALL_TAC;
6146     SIMP_TAC[EXTENSION; NOT_IN_EMPTY; IN_INTER; IN_INTERS; NOT_FORALL_THM;
6147              FORALL_IN_IMAGE; FRONTIER_CBALL; REAL_LT_01] THEN
6148     EXPAND_TAC "k" THEN REWRITE_TAC[IN_SPHERE_0; IN_ELIM_THM; NORM_NEG] THEN
6149     MESON_TAC[NORM_EQ_0; REAL_ARITH `~(&1 = &0)`; DOT_SYM]] THEN
6150   MATCH_MP_TAC COMPACT_IMP_FIP THEN
6151   SIMP_TAC[COMPACT_CBALL; COMPACT_FRONTIER; FORALL_IN_IMAGE;
6152            CLOSED_INTER_COMPACT; CLOSED_SPAN] THEN
6153   CONJ_TAC THENL
6154    [EXPAND_TAC "k" THEN REWRITE_TAC[GSYM real_ge; CLOSED_HALFSPACE_GE];
6155     ALL_TAC] THEN
6156   REWRITE_TAC[FINITE_SUBSET_IMAGE] THEN GEN_TAC THEN
6157   DISCH_THEN(X_CHOOSE_THEN `c:real^N->bool` MP_TAC) THEN
6158   ASM_CASES_TAC `c:real^N->bool = {}` THENL
6159    [ASM_SIMP_TAC[INTERS_0; INTER_UNIV; IMAGE_CLAUSES] THEN
6160     DISCH_THEN(K ALL_TAC) THEN
6161     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
6162     DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
6163     SUBGOAL_THEN `~(a:real^N = vec 0)` ASSUME_TAC THENL
6164      [ASM_MESON_TAC[]; ALL_TAC] THEN
6165     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
6166     EXISTS_TAC `inv(norm a) % a:real^N` THEN
6167     ASM_SIMP_TAC[IN_INTER; FRONTIER_CBALL; SPAN_CLAUSES; IN_SPHERE_0] THEN
6168     REWRITE_TAC[DIST_0; NORM_MUL; REAL_ABS_INV; REAL_ABS_NORM] THEN
6169     ASM_SIMP_TAC[REAL_MUL_LINV; NORM_EQ_0];
6170     ALL_TAC] THEN
6171   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
6172   MP_TAC(ISPEC `convex hull (c:real^N->bool)`
6173       SEPARATING_HYPERPLANE_CLOSED_0_INSET) THEN
6174   ANTS_TAC THENL
6175    [ASM_REWRITE_TAC[CONVEX_HULL_EQ_EMPTY] THEN
6176     ASM_MESON_TAC[CONVEX_CONVEX_HULL; SUBSET; SUBSET_HULL; HULL_SUBSET;
6177                   FINITE_IMP_COMPACT_CONVEX_HULL; COMPACT_IMP_CLOSED];
6178     ALL_TAC] THEN
6179   REWRITE_TAC[DOT_RZERO; real_gt] THEN
6180   DISCH_THEN(X_CHOOSE_THEN `a:real^N` (X_CHOOSE_THEN `b:real`
6181     STRIP_ASSUME_TAC)) THEN
6182   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER; IN_INTERS; FORALL_IN_IMAGE] THEN
6183   EXPAND_TAC "k" THEN SIMP_TAC[IN_ELIM_THM; FRONTIER_CBALL; REAL_LT_01] THEN
6184   REWRITE_TAC[dist; VECTOR_SUB_LZERO; NORM_NEG] THEN
6185   EXISTS_TAC `inv(norm(a)) % a:real^N` THEN REWRITE_TAC[DOT_RMUL] THEN
6186   SUBGOAL_THEN `(a:real^N) IN s` ASSUME_TAC THENL
6187    [ASM_MESON_TAC[SUBSET; HULL_MINIMAL]; ASM_SIMP_TAC[SPAN_CLAUSES]] THEN
6188   REWRITE_TAC[IN_SPHERE_0; VECTOR_SUB_LZERO; NORM_NEG; NORM_MUL] THEN
6189   REWRITE_TAC[REAL_ABS_INV; REAL_ABS_NORM] THEN
6190   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN
6191   ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_EQ_LDIV_EQ; NORM_POS_LT] THEN
6192   REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID] THEN
6193   ASM_MESON_TAC[REAL_LT_IMP_LE; REAL_LE_TRANS; HULL_SUBSET; SUBSET; DOT_SYM]);;
6194
6195 let SEPARATING_HYPERPLANE_SET_POINT_INAFF = prove
6196  (`!s z:real^N.
6197         convex s /\ ~(s = {}) /\ ~(z IN s)
6198         ==> ?a b. (z + a) IN affine hull (z INSERT s) /\ ~(a = vec 0) /\
6199                   a dot z <= b /\ (!x. x IN s ==> a dot x >= b)`,
6200   REPEAT STRIP_TAC THEN
6201   MP_TAC(ISPEC `IMAGE (\x:real^N. --z + x) s`
6202      SEPARATING_HYPERPLANE_SET_0_INSPAN) THEN
6203   ASM_SIMP_TAC[FORALL_IN_IMAGE; CONVEX_TRANSLATION; IMAGE_EQ_EMPTY] THEN
6204   REWRITE_TAC[IN_IMAGE; VECTOR_ARITH `vec 0:real^N = --z + x <=> x = z`] THEN
6205   ASM_SIMP_TAC[UNWIND_THM2; AFFINE_HULL_INSERT_SPAN; IN_ELIM_THM] THEN
6206   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
6207   REWRITE_TAC[GSYM SIMPLE_IMAGE; VECTOR_ARITH `--x + y:real^N = y - x`] THEN
6208   STRIP_TAC THEN ASM_REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN
6209   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
6210   EXISTS_TAC `(a:real^N) dot z` THEN REWRITE_TAC[REAL_LE_REFL] THEN
6211   ASM_REWRITE_TAC[REAL_ARITH `x >= y <=> &0 <= x - y`; GSYM DOT_RSUB]);;
6212
6213 let SEPARATING_HYPERPLANE_SET_0 = prove
6214  (`!s:real^N->bool.
6215         convex s /\ ~(vec 0 IN s)
6216         ==> ?a b. ~(a = vec 0) /\ !x. x IN s ==> &0 <= a dot x`,
6217   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
6218    [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
6219     MESON_TAC[BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1];
6220     ASM_MESON_TAC[SEPARATING_HYPERPLANE_SET_0_INSPAN]]);;
6221
6222 let SEPARATING_HYPERPLANE_SETS = prove
6223  (`!s t. convex s /\ convex t /\ ~(s = {}) /\ ~(t = {}) /\ DISJOINT s t
6224          ==> ?a:real^N b. ~(a = vec 0) /\
6225                           (!x. x IN s ==> a dot x <= b) /\
6226                           (!x. x IN t ==> a dot x >= b)`,
6227   REPEAT STRIP_TAC THEN
6228   MP_TAC(ISPEC `{y - x:real^N | y IN t /\ x IN s}`
6229                 SEPARATING_HYPERPLANE_SET_0) THEN
6230   ASM_SIMP_TAC[CONVEX_DIFFERENCES] THEN ANTS_TAC THENL
6231    [REWRITE_TAC[IN_ELIM_THM] THEN ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN
6232     REWRITE_TAC[VECTOR_SUB_EQ] THEN
6233     ASM_MESON_TAC[DISJOINT; NOT_IN_EMPTY; IN_INTER; EXTENSION];
6234     ALL_TAC] THEN
6235   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
6236   SIMP_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
6237   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6238   GEN_REWRITE_TAC LAND_CONV [SWAP_FORALL_THM] THEN
6239   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [SWAP_FORALL_THM] THEN
6240   ONCE_REWRITE_TAC[IMP_CONJ] THEN REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN
6241   REWRITE_TAC[LEFT_FORALL_IMP_THM; EXISTS_REFL; DOT_RSUB; REAL_SUB_LE] THEN
6242   DISCH_TAC THEN
6243   MP_TAC(SPEC `IMAGE (\x:real^N. a dot x) s` SUP) THEN
6244   ABBREV_TAC `k = sup (IMAGE (\x:real^N. a dot x) s)` THEN
6245   ASM_REWRITE_TAC[FORALL_IN_IMAGE; IMAGE_EQ_EMPTY; real_ge] THEN ANTS_TAC THENL
6246    [ASM_MESON_TAC[MEMBER_NOT_EMPTY]; ASM_MESON_TAC[]]);;
6247
6248 (* ------------------------------------------------------------------------- *)
6249 (* More convexity generalities.                                              *)
6250 (* ------------------------------------------------------------------------- *)
6251
6252 let CONVEX_CLOSURE = prove
6253  (`!s:real^N->bool. convex s ==> convex(closure s)`,
6254   REWRITE_TAC[convex; CLOSURE_SEQUENTIAL] THEN
6255   GEN_TAC THEN DISCH_TAC THEN
6256   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
6257   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `a:num->real^N`) MP_TAC) THEN
6258   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `b:num->real^N`) MP_TAC) THEN
6259   STRIP_TAC THEN EXISTS_TAC `\n:num. u % a(n) + v % b(n) :real^N` THEN
6260   ASM_SIMP_TAC[LIM_ADD; LIM_CMUL]);;
6261
6262 let CONVEX_INTERIOR = prove
6263  (`!s:real^N->bool. convex s ==> convex(interior s)`,
6264   REWRITE_TAC[CONVEX_ALT; IN_INTERIOR; SUBSET; IN_BALL; dist] THEN
6265   REPEAT GEN_TAC THEN STRIP_TAC THEN REPEAT GEN_TAC THEN
6266   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `d:real`) MP_TAC) THEN
6267   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `e:real`) STRIP_ASSUME_TAC) THEN
6268   EXISTS_TAC `min d e` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
6269   X_GEN_TAC `z:real^N` THEN STRIP_TAC THEN
6270   SUBST1_TAC(VECTOR_ARITH `z:real^N =
6271    (&1 - u) % (z - u % (y - x)) + u % (z + (&1 - u) % (y - x))`) THEN
6272   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
6273   ASM_MESON_TAC[VECTOR_ARITH `x - (z - u % (y - x)) =
6274                                 ((&1 - u) % x + u % y) - z:real^N`;
6275                 VECTOR_ARITH `y - (z + (&1 - u) % (y - x)) =
6276                                 ((&1 - u) % x + u % y) - z:real^N`]);;
6277
6278 let CONVEX_ON_SETDIST = prove
6279  (`!s t:real^N->bool. convex t ==> (\x. setdist ({x},t)) convex_on s`,
6280   SUBGOAL_THEN
6281    `!s t:real^N->bool. convex t /\ closed t
6282                        ==> (\x. setdist ({x},t)) convex_on s`
6283   MP_TAC THENL
6284    [ALL_TAC;
6285     REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o
6286       SPECL [`s:real^N->bool`; `closure t:real^N->bool`]) THEN
6287     ASM_SIMP_TAC[CLOSED_CLOSURE; SETDIST_CLOSURE; CONVEX_CLOSURE]] THEN
6288   REPEAT STRIP_TAC THEN REWRITE_TAC[convex_on] THEN
6289   ASM_CASES_TAC `t:real^N->bool = {}` THEN
6290   ASM_SIMP_TAC[SETDIST_EMPTY; REAL_MUL_RZERO; REAL_ADD_RID; REAL_LE_REFL] THEN
6291   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `u:real`; `v:real`] THEN
6292   STRIP_TAC THEN
6293   MP_TAC(ISPECL [`{x:real^N}`; `t:real^N->bool`] SETDIST_COMPACT_CLOSED) THEN
6294   MP_TAC(ISPECL [`{y:real^N}`; `t:real^N->bool`] SETDIST_COMPACT_CLOSED) THEN
6295   ASM_REWRITE_TAC[NOT_INSERT_EMPTY; COMPACT_SING; UNWIND_THM2; SETDIST_CLOSURE;
6296                   CLOSURE_EQ_EMPTY; RIGHT_EXISTS_AND_THM; IN_SING] THEN
6297   DISCH_THEN(X_CHOOSE_THEN `y':real^N` (STRIP_ASSUME_TAC o GSYM)) THEN
6298   DISCH_THEN(X_CHOOSE_THEN `x':real^N` (STRIP_ASSUME_TAC o GSYM)) THEN
6299   MATCH_MP_TAC REAL_LE_TRANS THEN
6300   EXISTS_TAC `dist(u % x + v % y:real^N,u % x' + v % y')` THEN CONJ_TAC THENL
6301    [MATCH_MP_TAC SETDIST_LE_DIST THEN REWRITE_TAC[IN_SING] THEN
6302     ASM_MESON_TAC[convex];
6303     REWRITE_TAC[dist] THEN MATCH_MP_TAC(NORM_ARITH
6304      `norm(a - a':real^N) + norm(b - b') <= r
6305       ==> norm((a + b) - (a' + b')) <= r`) THEN
6306     ASM_REWRITE_TAC[GSYM VECTOR_SUB_LDISTRIB; NORM_MUL; dist] THEN
6307     ASM_REWRITE_TAC[real_abs; REAL_LE_REFL]]);;
6308
6309 (* ------------------------------------------------------------------------- *)
6310 (* Moving and scaling convex hulls.                                          *)
6311 (* ------------------------------------------------------------------------- *)
6312
6313 let CONVEX_HULL_TRANSLATION = prove
6314  (`!a:real^N s.
6315        convex hull (IMAGE (\x. a + x) s) = IMAGE (\x. a + x) (convex hull s)`,
6316   REPEAT GEN_TAC THEN MATCH_MP_TAC HULL_IMAGE THEN
6317   REWRITE_TAC[CONVEX_TRANSLATION_EQ; CONVEX_CONVEX_HULL] THEN
6318   REWRITE_TAC[VECTOR_ARITH `a + x:real^N = y <=> x = y - a`; EXISTS_REFL] THEN
6319   VECTOR_ARITH_TAC);;
6320
6321 add_translation_invariants [CONVEX_HULL_TRANSLATION];;
6322
6323 let CONVEX_HULL_SCALING = prove
6324  (`!s:real^N->bool c.
6325        convex hull (IMAGE (\x. c % x) s) = IMAGE (\x. c % x) (convex hull s)`,
6326   REPEAT GEN_TAC THEN ASM_CASES_TAC `c = &0` THENL
6327    [ASM_SIMP_TAC[IMAGE_CONST; VECTOR_MUL_LZERO; CONVEX_HULL_EQ_EMPTY] THEN
6328     COND_CASES_TAC THEN REWRITE_TAC[CONVEX_HULL_EMPTY; CONVEX_HULL_SING];
6329     ALL_TAC] THEN
6330   MATCH_MP_TAC HULL_IMAGE THEN
6331   ASM_SIMP_TAC[CONVEX_SCALING_EQ; CONVEX_CONVEX_HULL] THEN
6332   REWRITE_TAC[VECTOR_ARITH `c % x = c % y <=> c % (x - y) = vec 0`] THEN
6333   ASM_SIMP_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
6334   X_GEN_TAC `x:real^N` THEN EXISTS_TAC `inv c % x:real^N` THEN
6335   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; VECTOR_MUL_LID]);;
6336
6337 let CONVEX_HULL_AFFINITY = prove
6338  (`!s a:real^N c.
6339         convex hull (IMAGE (\x. a + c % x) s) =
6340         IMAGE (\x. a + c % x) (convex hull s)`,
6341   REPEAT GEN_TAC THEN
6342   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
6343   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
6344   ASM_SIMP_TAC[IMAGE_o; CONVEX_HULL_TRANSLATION; CONVEX_HULL_SCALING]);;
6345
6346 (* ------------------------------------------------------------------------- *)
6347 (* Convex set as intersection of halfspaces.                                 *)
6348 (* ------------------------------------------------------------------------- *)
6349
6350 let CONVEX_HALFSPACE_INTERSECTION = prove
6351  (`!s. closed(s:real^N->bool) /\ convex s
6352        ==> s = INTERS {h | s SUBSET h /\ ?a b. h = {x | a dot x <= b}}`,
6353   REPEAT STRIP_TAC THEN
6354   GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[IN_INTERS] THEN
6355   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
6356   REWRITE_TAC[MESON[] `(!t. (P t /\ ?a b. t = x a b) ==> Q t) <=>
6357                        (!a b. P(x a b) ==> Q(x a b))`] THEN
6358   EQ_TAC THENL [SET_TAC[]; ALL_TAC] THEN STRIP_TAC THEN
6359   MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
6360   MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`]
6361     SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
6362   ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
6363   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN STRIP_TAC THEN
6364   FIRST_X_ASSUM(MP_TAC o SPECL [`--a:real^N`; `--b:real`]) THEN
6365   ASM_SIMP_TAC[SUBSET; IN_ELIM_THM; DOT_LNEG; NOT_IMP] THEN
6366   ASM_SIMP_TAC[REAL_LE_NEG2; REAL_LT_NEG2; REAL_NOT_LE;
6367                REAL_ARITH `a > b ==> b <= a`]);;
6368
6369 (* ------------------------------------------------------------------------- *)
6370 (* Radon's theorem (from Lars Schewe).                                       *)
6371 (* ------------------------------------------------------------------------- *)
6372
6373 let RADON_EX_LEMMA = prove
6374  (`!(c:real^N->bool).
6375         FINITE c /\ affine_dependent c
6376         ==> (?u. sum c u = &0 /\ (?v. v IN c /\ ~(u v = &0)) /\
6377                                       vsum c (\v. u v % v) = (vec 0):real^N)`,
6378   REWRITE_TAC[AFFINE_DEPENDENT_EXPLICIT] THEN
6379   REPEAT STRIP_TAC THEN
6380   EXISTS_TAC `\v:real^N. if v IN s then u v else &0` THEN
6381   ASM_SIMP_TAC[GSYM SUM_RESTRICT_SET] THEN
6382   ASM_SIMP_TAC[COND_RAND;COND_RATOR;
6383                VECTOR_MUL_LZERO;GSYM VSUM_RESTRICT_SET] THEN
6384   ASM_SIMP_TAC[SET_RULE `s SUBSET c ==> {x | x IN c /\ x IN s} = s`] THEN
6385   EXISTS_TAC `v:real^N` THEN
6386   ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;
6387
6388 let RADON_S_LEMMA = prove
6389  (`!(s:A->bool) f.
6390         FINITE s /\ sum s f = &0
6391         ==> sum {x | x IN s /\ &0 < f x} f =
6392             -- sum {x | x IN s /\ f x < &0} f`,
6393   REWRITE_TAC[REAL_ARITH `a = --b <=> a + b = &0`] THEN
6394   REPEAT STRIP_TAC THEN
6395   ASM_SIMP_TAC[FINITE_RESTRICT;GSYM SUM_UNION;
6396     REWRITE_RULE [REAL_ARITH `&0 < f x ==> ~(f x < &0)`]
6397      (SET_RULE `(!x:A. &0 < f x ==> ~(f x < &0))
6398                 ==>  DISJOINT {x | x IN s /\ &0 < f x}
6399                               {x | x IN s /\ f x < &0}`)] THEN
6400   MATCH_MP_TAC (REAL_ARITH `!a b.a = &0 /\ a + b = &0 ==> b = &0`) THEN
6401   EXISTS_TAC `sum {x:A | x IN s /\ f x = &0} f` THEN
6402   CONJ_TAC THENL
6403   [ASM_SIMP_TAC[SUM_RESTRICT_SET] THEN REWRITE_TAC[COND_ID;SUM_0];
6404    ALL_TAC] THEN
6405   SUBGOAL_THEN `DISJOINT {x:A | x IN s /\ f x = &0}
6406                          ({x | x IN s /\ &0 < f x} UNION
6407                           {x | x IN s /\ f x < &0})` ASSUME_TAC THENL
6408   [REWRITE_TAC[DISJOINT;UNION;INTER;IN_ELIM_THM;EXTENSION;NOT_IN_EMPTY] THEN
6409    REAL_ARITH_TAC;
6410    ALL_TAC] THEN
6411    ASM_SIMP_TAC[FINITE_UNION;FINITE_RESTRICT;GSYM SUM_UNION] THEN
6412   FIRST_X_ASSUM (SUBST1_TAC o GSYM) THEN
6413   MATCH_MP_TAC (MESON[] `a = b ==> sum a f = sum b f`) THEN
6414   REWRITE_TAC[EXTENSION;IN_ELIM_THM;UNION] THEN
6415   MESON_TAC[REAL_LT_TOTAL]);;
6416
6417 let RADON_V_LEMMA = prove
6418  (`!(s:A->bool) f g.
6419         FINITE s /\ vsum s f = vec 0 /\ (!x. g x = &0 ==> f x = vec 0)
6420         ==> (vsum {x | x IN s /\ &0 < g x} f) :real^N =
6421              -- vsum {x | x IN s /\ g x < &0} f`,
6422   REWRITE_TAC[VECTOR_ARITH `a:real^N = --b <=> a + b = vec 0`] THEN
6423   REPEAT STRIP_TAC THEN
6424   ASM_SIMP_TAC[FINITE_RESTRICT;GSYM VSUM_UNION;
6425                REWRITE_RULE [REAL_ARITH `&0 < f x ==> ~(f x < &0)`]
6426                  (SET_RULE `(!x:A. &0 < f x ==> ~(f x < &0))
6427                             ==>  DISJOINT {x | x IN s /\ &0 < f x}
6428                                           {x | x IN s /\ f x < &0}`)] THEN
6429   MATCH_MP_TAC (VECTOR_ARITH
6430     `!a b. (a:real^N) = vec 0 /\ a + b = vec 0 ==> b = vec 0`) THEN
6431   EXISTS_TAC `(vsum {x:A | x IN s /\ g x = &0} f):real^N` THEN
6432   CONJ_TAC THENL
6433    [ASM_SIMP_TAC[VSUM_RESTRICT_SET;COND_ID;VSUM_0];ALL_TAC] THEN
6434     SUBGOAL_THEN `DISJOINT {x:A | x IN s /\ g x = &0}
6435                            ({x | x IN s /\ &0 < g x} UNION
6436                             {x | x IN s /\ g x < &0})` ASSUME_TAC THENL
6437      [REWRITE_TAC[DISJOINT;UNION;INTER;IN_ELIM_THM;EXTENSION;NOT_IN_EMPTY] THEN
6438       REAL_ARITH_TAC;
6439       ALL_TAC] THEN
6440   ASM_SIMP_TAC[FINITE_UNION;FINITE_RESTRICT;GSYM VSUM_UNION] THEN
6441   FIRST_X_ASSUM (SUBST1_TAC o GSYM) THEN
6442   MATCH_MP_TAC (MESON[] `a = b ==> vsum a f = vsum b f`) THEN
6443   REWRITE_TAC[EXTENSION;IN_ELIM_THM;UNION] THEN
6444   MESON_TAC[REAL_LT_TOTAL]);;
6445
6446 let RADON_PARTITION = prove
6447  (`!(c:real^N->bool).
6448         FINITE c /\ affine_dependent c
6449         ==> ?(m:real^N->bool) (p:real^N->bool).
6450                 (DISJOINT m p) /\
6451                 (m UNION p = c) /\
6452                 ~(DISJOINT (convex hull m) (convex hull p))`,
6453   REPEAT STRIP_TAC THEN
6454   MP_TAC (ISPEC `c:real^N->bool` RADON_EX_LEMMA) THEN
6455   ASM_REWRITE_TAC[] THEN
6456   REPEAT STRIP_TAC THEN
6457   MAP_EVERY EXISTS_TAC [`{v:real^N | v IN c /\ u v <= &0}`;
6458                         `{v:real^N | v IN c /\ u v > &0}`] THEN
6459   REPEAT CONJ_TAC THENL
6460    [REWRITE_TAC[DISJOINT;INTER;
6461                IN_ELIM_THM;REAL_ARITH `x <= &0 <=> ~(x > &0)`] THEN
6462     SET_TAC[];
6463     REWRITE_TAC[UNION;IN_ELIM_THM;REAL_ARITH `x <= &0 <=> ~(x > &0)`] THEN
6464     SET_TAC[];
6465     ALL_TAC] THEN
6466   SUBGOAL_THEN `~(sum {x:real^N | x IN c /\ u x > &0} u = &0)` ASSUME_TAC THENL
6467    [MATCH_MP_TAC (REAL_ARITH `a > &0 ==> ~(a = &0)`) THEN
6468     REWRITE_TAC[REAL_ARITH `a > &0 <=> &0 < a`]        THEN
6469     MATCH_MP_TAC (REWRITE_RULE[SUM_0] (ISPEC `\x. &0` SUM_LT_ALL)) THEN
6470     ASM_SIMP_TAC[FINITE_RESTRICT;IN_ELIM_THM;EXTENSION;NOT_IN_EMPTY] THEN
6471     REWRITE_TAC[MESON[]`~(!x. ~(P x /\ Q x)) = ?x. P x /\ Q x`] THEN
6472        ASM_CASES_TAC `&0 < u (v:real^N)` THENL
6473     [ASM SET_TAC[];ALL_TAC] THEN
6474     POP_ASSUM MP_TAC THEN POP_ASSUM (K ALL_TAC) THEN POP_ASSUM MP_TAC THEN
6475     REWRITE_TAC[IMP_IMP;REAL_ARITH `~(a = &0) /\ ~(&0 < a) <=> a < &0`] THEN
6476     DISCH_TAC THEN
6477     REWRITE_TAC[MESON[REAL_NOT_LT]
6478      `(?x:real^N. P x /\ &0 < u x) <=> (!x. P x ==> u x <= &0) ==> F`]  THEN
6479     DISCH_TAC THEN
6480        MP_TAC (ISPECL [`u:real^N->real`;`\x:real^N. &0`;`c:real^N->bool`]
6481                       SUM_LT) THEN
6482     ASM_REWRITE_TAC[SUM_0;REAL_ARITH `~(&0 < &0)`] THEN
6483     ASM_MESON_TAC[];ALL_TAC] THEN
6484   REWRITE_TAC[SET_RULE `~DISJOINT a b <=> ?y. y IN a /\ y IN b`] THEN
6485   EXISTS_TAC `&1 / (sum {x:real^N | x IN c /\ u x > &0} u) %
6486               vsum {x:real^N | x IN c /\ u x > &0} (\x. u x % x)` THEN
6487   REWRITE_TAC[CONVEX_HULL_EXPLICIT;IN_ELIM_THM] THEN
6488   CONJ_TAC THENL
6489   [MAP_EVERY EXISTS_TAC [`{v:real^N | v IN c /\ u v < &0}`;
6490                          `\y:real^N.
6491                          &1 / (sum {x:real^N | x IN c /\ u x > &0} u) *
6492                            (--(u y))`] THEN
6493    ASM_SIMP_TAC[FINITE_RESTRICT;SUBSET;IN_ELIM_THM] THEN
6494    REPEAT CONJ_TAC THENL
6495     [REAL_ARITH_TAC;
6496      REPEAT STRIP_TAC THEN
6497      MATCH_MP_TAC REAL_LE_MUL THEN
6498      CONJ_TAC THENL [ALL_TAC;
6499                      ASM_REWRITE_TAC[REAL_NEG_GE0;REAL_LE_LT]] THEN
6500      MATCH_MP_TAC REAL_LE_DIV THEN
6501      REWRITE_TAC[REAL_LE_01] THEN
6502      MATCH_MP_TAC SUM_POS_LE THEN
6503      ASM_SIMP_TAC[FINITE_RESTRICT;IN_ELIM_THM] THEN
6504      REAL_ARITH_TAC;
6505      ASM_SIMP_TAC[FINITE_RESTRICT;SUM_LMUL] THEN
6506      MATCH_MP_TAC (REAL_FIELD `!a. ~(a = &0) /\ a * b = a * c ==> b = c`) THEN
6507      EXISTS_TAC `sum {x:real^N | x IN c /\ u x > &0} u` THEN
6508      REWRITE_TAC[SUM_LMUL] THEN
6509      ASM_SIMP_TAC[REAL_FIELD `~(a = &0) ==> a * &1 / a * b = b`]  THEN
6510      REWRITE_TAC[SUM_NEG;REAL_MUL_RID] THEN
6511      REWRITE_TAC[REAL_ARITH `a > &0 <=> &0 < a`] THEN
6512      MATCH_MP_TAC (GSYM RADON_S_LEMMA) THEN
6513      ASM_REWRITE_TAC[];
6514      ALL_TAC] THEN
6515     REWRITE_TAC[GSYM VECTOR_MUL_ASSOC;VSUM_LMUL;VECTOR_MUL_LCANCEL] THEN
6516     REWRITE_TAC[VECTOR_MUL_LNEG;VSUM_NEG] THEN
6517     DISJ2_TAC THEN
6518     MATCH_MP_TAC (REWRITE_RULE[REAL_ARITH `&0 < a <=>  a > &0`]
6519      (GSYM RADON_V_LEMMA)) THEN
6520     ASM_REWRITE_TAC[] THEN
6521     MESON_TAC[VECTOR_MUL_LZERO];ALL_TAC] THEN
6522   MAP_EVERY EXISTS_TAC [`{v:real^N | v IN c /\ u v > &0}`;
6523                         `\y:real^N.
6524                            &1 / (sum {x:real^N | x IN c /\ u x > &0} u) *
6525                            (u y)`] THEN
6526   ASM_SIMP_TAC[FINITE_RESTRICT;SUBSET;IN_ELIM_THM] THEN
6527   REPEAT CONJ_TAC THENL
6528    [REPEAT STRIP_TAC THEN
6529     MATCH_MP_TAC REAL_LE_MUL THEN
6530     CONJ_TAC THENL [ALL_TAC;
6531                     ASM_SIMP_TAC[REAL_ARITH `a > &0 ==> &0 <= a`]] THEN
6532     MATCH_MP_TAC REAL_LE_DIV THEN
6533     REWRITE_TAC[REAL_LE_01] THEN
6534     MATCH_MP_TAC SUM_POS_LE THEN
6535     ASM_SIMP_TAC[FINITE_RESTRICT;IN_ELIM_THM] THEN
6536     REAL_ARITH_TAC;
6537     ASM_SIMP_TAC[FINITE_RESTRICT;SUM_LMUL] THEN
6538     MATCH_MP_TAC (REAL_FIELD `!a. ~(a = &0) /\ a * b = a * c ==> b = c`) THEN
6539     EXISTS_TAC `sum {x:real^N | x IN c /\ u x > &0} u` THEN
6540     REWRITE_TAC[SUM_LMUL] THEN
6541     ASM_SIMP_TAC[REAL_FIELD `~(a = &0) ==> a * &1 / a * b = b`]  THEN
6542     REWRITE_TAC[SUM_NEG;REAL_MUL_RID] THEN
6543     REWRITE_TAC[REAL_ARITH `a > &0 <=> &0 < a`] THEN
6544     MATCH_MP_TAC (GSYM RADON_S_LEMMA) THEN
6545     ASM_REWRITE_TAC[];
6546     ALL_TAC] THEN
6547   REWRITE_TAC[GSYM VECTOR_MUL_ASSOC;VSUM_LMUL;VECTOR_MUL_LCANCEL] THEN
6548   REWRITE_TAC[VECTOR_MUL_LNEG;VSUM_NEG] THEN
6549   DISJ2_TAC THEN
6550   MATCH_MP_TAC (REWRITE_RULE[REAL_ARITH `&0 < a <=>  a > &0`]
6551     (GSYM RADON_V_LEMMA)) THEN
6552   ASM_REWRITE_TAC[] THEN
6553   MESON_TAC[VECTOR_MUL_LZERO]);;
6554
6555 let RADON = prove
6556  (`!(c:real^N->bool).
6557         affine_dependent c
6558         ==> ?(m:real^N->bool) (p:real^N->bool).
6559                 m SUBSET c /\
6560                 p SUBSET c /\
6561                 DISJOINT m p /\
6562                 ~(DISJOINT (convex hull m) (convex hull p))`,
6563   REPEAT STRIP_TAC THEN MP_TAC
6564     (ISPEC `c:real^N->bool` AFFINE_DEPENDENT_EXPLICIT) THEN
6565   ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN MP_TAC
6566   (ISPEC `s:real^N->bool` RADON_PARTITION) THEN
6567   ANTS_TAC THENL
6568   [ASM_SIMP_TAC[AFFINE_DEPENDENT_EXPLICIT] THEN
6569      MAP_EVERY EXISTS_TAC [`s:real^N->bool`;`u:real^N->real`] THEN
6570      ASM SET_TAC[];ALL_TAC] THEN
6571   DISCH_THEN STRIP_ASSUME_TAC THEN
6572   MAP_EVERY EXISTS_TAC [`m:real^N->bool`;`p:real^N->bool`] THEN
6573   ASM SET_TAC[]);;
6574
6575 (* ------------------------------------------------------------------------- *)
6576 (* Helly's theorem.                                                          *)
6577 (* ------------------------------------------------------------------------- *)
6578
6579 let HELLY_INDUCT = prove
6580  (`!n f. f HAS_SIZE n /\ n >= dimindex(:N) + 1 /\
6581          (!s:real^N->bool. s IN f ==> convex s) /\
6582          (!t. t SUBSET f /\ CARD(t) = dimindex(:N) + 1
6583               ==> ~(INTERS t = {}))
6584          ==> ~(INTERS f = {})`,
6585   INDUCT_TAC THEN REWRITE_TAC[ARITH_RULE `~(0 >= n + 1)`] THEN GEN_TAC THEN
6586   POP_ASSUM(LABEL_TAC "*") THEN STRIP_TAC THEN
6587   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [HAS_SIZE_SUC]) THEN
6588   STRIP_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
6589   FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP (ARITH_RULE
6590     `SUC n >= m + 1 ==> m = n \/ n >= m + 1`))
6591   THENL
6592    [FIRST_X_ASSUM MATCH_MP_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
6593     ASM_SIMP_TAC[CARD_CLAUSES; SUBSET_REFL] THEN ARITH_TAC;
6594     ALL_TAC] THEN
6595   SUBGOAL_THEN
6596    `?X. !s:real^N->bool. s IN f ==> X(s) IN INTERS (f DELETE s)`
6597   STRIP_ASSUME_TAC THENL
6598    [REWRITE_TAC[GSYM SKOLEM_THM; MEMBER_NOT_EMPTY; RIGHT_EXISTS_IMP_THM] THEN
6599     GEN_TAC THEN STRIP_TAC THEN REMOVE_THEN "*" MATCH_MP_TAC THEN
6600     ASM_SIMP_TAC[FINITE_DELETE; CARD_DELETE] THEN ASM SET_TAC[];
6601     ALL_TAC] THEN
6602   ASM_CASES_TAC
6603    `?s t:real^N->bool. s IN f /\ t IN f /\ ~(s = t) /\ X s:real^N = X t`
6604   THENL
6605    [FIRST_X_ASSUM(CHOOSE_THEN STRIP_ASSUME_TAC) THEN
6606     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
6607     EXISTS_TAC `(X:(real^N->bool)->real^N) t` THEN
6608     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC ONCE_DEPTH_CONV
6609      [MATCH_MP
6610        (SET_RULE`~(s = t)
6611                ==> INTERS f = INTERS(f DELETE s) INTER INTERS(f DELETE t)`)
6612        th]) THEN
6613     REWRITE_TAC[IN_INTER] THEN ASM_MESON_TAC[];
6614     ALL_TAC] THEN
6615   MP_TAC(ISPEC `IMAGE (X:(real^N->bool)->real^N) f` RADON_PARTITION) THEN
6616   ANTS_TAC THENL
6617    [ASM_SIMP_TAC[FINITE_IMAGE] THEN
6618     MATCH_MP_TAC AFFINE_DEPENDENT_BIGGERSET THEN
6619     ASM_SIMP_TAC[FINITE_IMAGE] THEN
6620     MATCH_MP_TAC(ARITH_RULE
6621      `!f n. n >= d + 1 /\ f = SUC n /\ c = f ==> c >= d + 2`) THEN
6622     MAP_EVERY EXISTS_TAC [`CARD(f:(real^N->bool)->bool)`; `n:num`] THEN
6623     REPEAT(CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC]) THEN
6624     MATCH_MP_TAC CARD_IMAGE_INJ THEN ASM_MESON_TAC[];
6625     ALL_TAC] THEN
6626   ONCE_REWRITE_TAC[SET_RULE
6627    `P /\ m UNION p = s /\ Q <=>
6628     m SUBSET s /\ p SUBSET s /\ m UNION p = s /\ P /\ Q`] THEN
6629   REWRITE_TAC[SUBSET_IMAGE; DISJOINT] THEN
6630   REWRITE_TAC[MESON[]
6631    `(?m p. (?u. P u /\ m = t u) /\ (?u. P u /\ p = t u) /\ Q m p) ==> r <=>
6632     (!u v. P u /\ P v /\ Q (t u) (t v) ==> r)`] THEN
6633   MAP_EVERY X_GEN_TAC [`g:(real^N->bool)->bool`; `h:(real^N->bool)->bool`] THEN
6634   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6635   SUBGOAL_THEN `(f:(real^N->bool)->bool) = h UNION g` SUBST1_TAC THENL
6636    [MATCH_MP_TAC SUBSET_ANTISYM THEN ASM_REWRITE_TAC[UNION_SUBSET] THEN
6637     REWRITE_TAC[SUBSET; IN_UNION] THEN X_GEN_TAC `s:real^N->bool` THEN
6638     DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
6639     DISCH_THEN(MP_TAC o ISPEC `X:(real^N->bool)->real^N` o
6640       MATCH_MP FUN_IN_IMAGE) THEN
6641     FIRST_X_ASSUM(fun th ->
6642       GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM th]) THEN
6643     ONCE_REWRITE_TAC[DISJ_SYM] THEN REWRITE_TAC[IN_UNION; IN_IMAGE] THEN
6644     MATCH_MP_TAC MONO_OR THEN ASM_MESON_TAC[SUBSET];
6645     ALL_TAC] THEN
6646   MATCH_MP_TAC(SET_RULE
6647    `g SUBSET INTERS g' /\ h SUBSET INTERS h'
6648     ==> ~(g INTER h = {}) ==> ~(INTERS(g' UNION h') = {})`) THEN
6649   FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP (SET_RULE
6650    `IMAGE X s INTER IMAGE X t = {} ==> s INTER t = {}`)) THEN
6651   CONJ_TAC THEN MATCH_MP_TAC HULL_MINIMAL THEN
6652   (CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[SUBSET; CONVEX_INTERS]]) THEN
6653   REWRITE_TAC[SUBSET; IN_INTERS; FORALL_IN_IMAGE] THEN ASM SET_TAC[]);;
6654
6655 let HELLY = prove
6656  (`!f:(real^N->bool)->bool.
6657         FINITE f /\ CARD(f) >= dimindex(:N) + 1 /\
6658         (!s. s IN f ==> convex s) /\
6659         (!t. t SUBSET f /\ CARD(t) = dimindex(:N) + 1 ==> ~(INTERS t = {}))
6660         ==> ~(INTERS f = {})`,
6661   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC HELLY_INDUCT THEN
6662   ASM_REWRITE_TAC[HAS_SIZE] THEN ASM_MESON_TAC[]);;
6663
6664 let HELLY_ALT = prove
6665  (`!f:(real^N->bool)->bool.
6666         FINITE f /\
6667         (!s. s IN f ==> convex s) /\
6668         (!t. t SUBSET f /\ CARD(t) <= dimindex(:N) + 1 ==> ~(INTERS t = {}))
6669         ==> ~(INTERS f = {})`,
6670   GEN_TAC THEN STRIP_TAC THEN
6671   ASM_CASES_TAC `CARD(f:(real^N->bool)->bool) < dimindex(:N) + 1` THEN
6672   ASM_SIMP_TAC[SUBSET_REFL; LT_IMP_LE] THEN MATCH_MP_TAC HELLY THEN
6673   ASM_SIMP_TAC[GE; GSYM NOT_LT] THEN ASM_MESON_TAC[LE_REFL]);;
6674
6675 let HELLY_CLOSED_ALT = prove
6676  (`!f:(real^N->bool)->bool.
6677         (!s. s IN f ==> convex s /\ closed s) /\ (?s. s IN f /\ bounded s) /\
6678         (!t. t SUBSET f /\ FINITE t /\ CARD(t) <= dimindex(:N) + 1
6679              ==> ~(INTERS t = {}))
6680         ==> ~(INTERS f = {})`,
6681   GEN_TAC THEN
6682   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
6683   MATCH_MP_TAC CLOSED_FIP THEN ASM_SIMP_TAC[] THEN
6684   X_GEN_TAC `g:(real^N->bool)->bool` THEN STRIP_TAC THEN
6685   MATCH_MP_TAC HELLY_ALT THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
6686    [ASM SET_TAC[];
6687     ASM_MESON_TAC[SUBSET_TRANS; FINITE_SUBSET]]);;
6688
6689 let HELLY_COMPACT_ALT = prove
6690  (`!f:(real^N->bool)->bool.
6691         (!s. s IN f ==> convex s /\ compact s) /\
6692         (!t. t SUBSET f /\ FINITE t /\ CARD(t) <= dimindex(:N) + 1
6693              ==> ~(INTERS t = {}))
6694         ==> ~(INTERS f = {})`,
6695   GEN_TAC THEN STRIP_TAC THEN
6696   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
6697   ASM_REWRITE_TAC[INTERS_0; UNIV_NOT_EMPTY] THEN
6698   MATCH_MP_TAC HELLY_CLOSED_ALT THEN
6699   ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN
6700   ASM_MESON_TAC[MEMBER_NOT_EMPTY; COMPACT_IMP_BOUNDED]);;
6701
6702 let HELLY_CLOSED = prove
6703  (`!f:(real^N->bool)->bool.
6704         (FINITE f ==> CARD f >= dimindex (:N) + 1) /\
6705         (!s. s IN f ==> convex s /\ closed s) /\ (?s. s IN f /\ bounded s) /\
6706         (!t. t SUBSET f /\ FINITE t /\ CARD(t) = dimindex(:N) + 1
6707              ==> ~(INTERS t = {}))
6708         ==> ~(INTERS f = {})`,
6709   GEN_TAC THEN REWRITE_TAC[GE] THEN
6710   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
6711   MATCH_MP_TAC HELLY_CLOSED_ALT THEN ASM_REWRITE_TAC[] THEN
6712   X_GEN_TAC `g:(real^N->bool)->bool` THEN STRIP_TAC THEN
6713   MP_TAC(ISPECL [`dimindex(:N) + 1`; `g:(real^N->bool)->bool`;
6714                  `f:(real^N->bool)->bool`] CHOOSE_SUBSET_BETWEEN) THEN
6715   ASM_REWRITE_TAC[] THEN
6716   DISCH_THEN(X_CHOOSE_THEN `h:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
6717   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ ~(s = {}) ==> ~(t = {})`) THEN
6718   EXISTS_TAC `INTERS h: real^N->bool` THEN
6719   CONJ_TAC THENL [ASM SET_TAC[]; FIRST_X_ASSUM MATCH_MP_TAC] THEN
6720   ASM_MESON_TAC[HAS_SIZE]);;
6721
6722 let HELLY_COMPACT = prove
6723  (`!f:(real^N->bool)->bool.
6724         (FINITE f ==> CARD f >= dimindex (:N) + 1) /\
6725         (!s. s IN f ==> convex s /\ compact s) /\
6726         (!t. t SUBSET f /\ FINITE t /\ CARD(t) = dimindex(:N) + 1
6727              ==> ~(INTERS t = {}))
6728         ==> ~(INTERS f = {})`,
6729   GEN_TAC THEN STRIP_TAC THEN
6730   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
6731   ASM_REWRITE_TAC[INTERS_0; UNIV_NOT_EMPTY] THEN
6732   MATCH_MP_TAC HELLY_CLOSED THEN
6733   ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN
6734   ASM_MESON_TAC[MEMBER_NOT_EMPTY; COMPACT_IMP_BOUNDED]);;
6735
6736 (* ------------------------------------------------------------------------- *)
6737 (* Kirchberger's theorem                                                     *)
6738 (* ------------------------------------------------------------------------- *)
6739
6740 let KIRCHBERGER = prove
6741  (`!s t:real^N->bool.
6742         compact s /\ compact t /\
6743         (!s' t'. s' SUBSET s /\ t' SUBSET t /\ FINITE s' /\ FINITE t' /\
6744                  CARD(s') + CARD(t') <= dimindex(:N) + 2
6745                  ==> ?a b. (!x. x IN s' ==> a dot x < b) /\
6746                            (!x. x IN t' ==> a dot x > b))
6747         ==> ?a b. ~(a = vec 0) /\
6748                   (!x. x IN s ==> a dot x < b) /\
6749                   (!x. x IN t ==> a dot x > b)`,
6750   let lemma = prove
6751    (`(!x. x IN convex hull s ==> a dot x < b) /\
6752      (!x. x IN convex hull t ==> a dot x > b) <=>
6753      (!x. x IN s ==> a dot x < b) /\ (!x. x IN t ==> a dot x > b)`,
6754     REWRITE_TAC[SET_RULE `(!x. x IN s ==> P x) <=> s SUBSET {x | P x}`] THEN
6755     SIMP_TAC[SUBSET_HULL; CONVEX_HALFSPACE_LT; CONVEX_HALFSPACE_GT])
6756   and KIRCH_LEMMA = prove
6757    (`!s t:real^N->bool.
6758           FINITE s /\ FINITE t /\
6759           (!s' t'. s' SUBSET s /\ t' SUBSET t /\
6760                    CARD(s') + CARD(t') <= dimindex(:N) + 2
6761                    ==> ?a b. (!x. x IN s' ==> a dot x < b) /\
6762                              (!x. x IN t' ==> a dot x > b))
6763           ==> ?a b. (!x. x IN s ==> a dot x < b) /\
6764                     (!x. x IN t ==> a dot x > b)`,
6765     REPEAT STRIP_TAC THEN MP_TAC(ISPECL
6766      [`IMAGE (\r. {z:real^(N,1)finite_sum |
6767                           fstcart z dot r < drop(sndcart z)}) s UNION
6768        IMAGE (\r. {z:real^(N,1)finite_sum |
6769                           fstcart z dot r > drop(sndcart z)}) t`]
6770      HELLY_ALT) THEN
6771     REWRITE_TAC[FORALL_SUBSET_UNION; IN_UNION; IMP_CONJ] THEN
6772     REWRITE_TAC[RIGHT_FORALL_IMP_THM; FORALL_SUBSET_IMAGE] THEN
6773     ASM_SIMP_TAC[FINITE_UNION; FINITE_IMAGE; INTERS_UNION] THEN
6774     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; INTERS_IMAGE; IN_INTER;
6775                 EXISTS_PASTECART; IN_ELIM_PASTECART_THM;
6776                 FSTCART_PASTECART; SNDCART_PASTECART] THEN
6777     REWRITE_TAC[TAUT `p \/ q ==> r <=> (p ==> r) /\ (q ==> r)`] THEN
6778     REWRITE_TAC[FORALL_AND_THM; FORALL_IN_IMAGE; RIGHT_IMP_FORALL_THM] THEN
6779     REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC; GSYM EXISTS_DROP] THEN
6780     DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL
6781      [REWRITE_TAC[REAL_ARITH `a > b <=> --a < --b`; GSYM DOT_RNEG] THEN
6782       REWRITE_TAC[convex; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_GSPEC] THEN
6783       SIMP_TAC[PASTECART_ADD; GSYM PASTECART_CMUL; IN_ELIM_PASTECART_THM] THEN
6784       SIMP_TAC[DOT_LADD; DOT_LMUL; DROP_ADD; DROP_CMUL; GSYM FORALL_DROP] THEN
6785       REWRITE_TAC[REAL_ARITH `--(a * x + b * y):real = a * --x + b * --y`] THEN
6786       REPEAT STRIP_TAC THEN
6787       FIRST_ASSUM(MP_TAC o MATCH_MP (REAL_ARITH
6788        `u + v = &1
6789         ==> &0 <= u /\ &0 <= v
6790            ==> u = &0 /\ v = &1 \/ u = &1 /\ v = &0 \/ &0 < u /\ &0 < v`)) THEN
6791       ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
6792       ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID;
6793                       REAL_ADD_LID; REAL_ADD_RID] THEN
6794       MATCH_MP_TAC REAL_LT_ADD2 THEN ASM_SIMP_TAC[REAL_LT_LMUL_EQ];
6795       REWRITE_TAC[DIMINDEX_FINITE_SUM; DIMINDEX_1;
6796                   ARITH_RULE `(n + 1) + 1 = n + 2`] THEN
6797       MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
6798       DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
6799       SUBGOAL_THEN `FINITE(u:real^N->bool) /\ FINITE(v:real^N->bool)`
6800       STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
6801       W(MP_TAC o PART_MATCH (lhs o rand) CARD_UNION o lhand o lhand o snd) THEN
6802       ASM_SIMP_TAC[FINITE_IMAGE] THEN ANTS_TAC THENL
6803        [REWRITE_TAC[SET_RULE `IMAGE f s INTER IMAGE g t = {} <=>
6804                               !x y. x IN s /\ y IN t ==> ~(f x = g y)`] THEN
6805         MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
6806         REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
6807         DISCH_THEN(MP_TAC o SPEC `vec 0:real^N`) THEN
6808         REWRITE_TAC[GSYM FORALL_DROP; DOT_LZERO] THEN
6809         DISCH_THEN(MP_TAC o SPEC `&1`) THEN REAL_ARITH_TAC;
6810         DISCH_THEN SUBST1_TAC] THEN
6811       DISCH_THEN(fun th -> FIRST_X_ASSUM MATCH_MP_TAC THEN MP_TAC th) THEN
6812       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(ARITH_RULE
6813        `a = a' /\ b = b' ==> a + b <= n + 2 ==> a' + b' <= n + 2`) THEN
6814       CONJ_TAC THEN MATCH_MP_TAC CARD_IMAGE_INJ THEN
6815       ASM_REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
6816       SIMP_TAC[GSYM FORALL_DROP; real_gt; VECTOR_EQ_LDOT;
6817         MESON[REAL_LT_TOTAL; REAL_LT_REFL]
6818          `((!y:real. a < y <=> b < y) <=> a = b) /\
6819           ((!y:real. y < a <=> y < b) <=> a = b)`]]) in
6820   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM lemma] THEN
6821   MATCH_MP_TAC SEPARATING_HYPERPLANE_COMPACT_COMPACT THEN
6822   ASM_SIMP_TAC[CONVEX_CONVEX_HULL; COMPACT_CONVEX_HULL;
6823                CONVEX_HULL_EQ_EMPTY] THEN
6824   SUBGOAL_THEN
6825    `!s' t'. (s':real^N->bool) SUBSET s /\ t' SUBSET t /\
6826             FINITE s' /\ CARD(s') <= dimindex(:N) + 1 /\
6827             FINITE t' /\ CARD(t') <= dimindex(:N) + 1
6828             ==> DISJOINT (convex hull s') (convex hull t')`
6829   MP_TAC THENL
6830    [REPEAT STRIP_TAC THEN
6831     MP_TAC(ISPECL [`s':real^N->bool`; `t':real^N->bool`] KIRCH_LEMMA) THEN
6832     ANTS_TAC THENL
6833      [ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
6834       FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_MESON_TAC[SUBSET; FINITE_SUBSET];
6835       ONCE_REWRITE_TAC[GSYM lemma] THEN SET_TAC[REAL_LT_ANTISYM; real_gt]];
6836     POP_ASSUM_LIST(K ALL_TAC) THEN STRIP_TAC THEN
6837     REWRITE_TAC[SET_RULE `DISJOINT s t <=> !x. x IN s /\ x IN t ==> F`] THEN
6838     X_GEN_TAC `x:real^N` THEN ONCE_REWRITE_TAC[CARATHEODORY] THEN
6839     REWRITE_TAC[IN_ELIM_THM] THEN
6840     DISCH_THEN(CONJUNCTS_THEN2
6841       (X_CHOOSE_THEN `s':real^N->bool` STRIP_ASSUME_TAC)
6842       (X_CHOOSE_THEN `t':real^N->bool` STRIP_ASSUME_TAC)) THEN
6843     FIRST_X_ASSUM(MP_TAC o SPECL [`s':real^N->bool`; `t':real^N->bool`]) THEN
6844     ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;
6845
6846 (* ------------------------------------------------------------------------- *)
6847 (* Convex hull is "preserved" by a linear function.                          *)
6848 (* ------------------------------------------------------------------------- *)
6849
6850 let CONVEX_HULL_LINEAR_IMAGE = prove
6851  (`!f s. linear f ==> convex hull (IMAGE f s) = IMAGE f (convex hull s)`,
6852   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
6853   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
6854   CONJ_TAC THEN MATCH_MP_TAC HULL_INDUCT THEN
6855   REWRITE_TAC[FORALL_IN_IMAGE] THEN SIMP_TAC[FUN_IN_IMAGE; HULL_INC] THEN
6856   REWRITE_TAC[convex; IN_ELIM_THM] THEN
6857   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THENL
6858    [FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_CMUL th)]) THEN
6859     FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_ADD th)]) THEN
6860     REWRITE_TAC[IN_IMAGE] THEN
6861     MESON_TAC[REWRITE_RULE[convex] CONVEX_CONVEX_HULL];
6862     ASM_SIMP_TAC[LINEAR_ADD; LINEAR_CMUL] THEN
6863     MESON_TAC[REWRITE_RULE[convex] CONVEX_CONVEX_HULL]]);;
6864
6865 add_linear_invariants [CONVEX_HULL_LINEAR_IMAGE];;
6866
6867 let IN_CONVEX_HULL_LINEAR_IMAGE = prove
6868  (`!f:real^M->real^N s x.
6869         linear f /\ x IN convex hull s ==> (f x) IN convex hull (IMAGE f s)`,
6870   SIMP_TAC[CONVEX_HULL_LINEAR_IMAGE] THEN SET_TAC[]);;
6871
6872 (* ------------------------------------------------------------------------- *)
6873 (* Convexity of general and special intervals.                               *)
6874 (* ------------------------------------------------------------------------- *)
6875
6876 let IS_INTERVAL_CONVEX = prove
6877  (`!s:real^N->bool. is_interval s ==> convex s`,
6878   REWRITE_TAC[is_interval; convex] THEN
6879   REPEAT STRIP_TAC THEN FIRST_ASSUM MATCH_MP_TAC THEN
6880   MAP_EVERY EXISTS_TAC [`x:real^N`; `y:real^N`] THEN
6881   ASM_SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN
6882   GEN_TAC THEN STRIP_TAC THEN
6883   DISJ_CASES_TAC(SPECL [`(x:real^N)$i`; `(y:real^N)$i`] REAL_LE_TOTAL) THENL
6884    [DISJ1_TAC; DISJ2_TAC] THEN
6885   MATCH_MP_TAC(REAL_ARITH
6886    `&1 * a <= b /\ b <= &1 * c ==> a <= b /\ b <= c`) THEN
6887   FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
6888   ASM_SIMP_TAC[GSYM VECTOR_MUL_COMPONENT;
6889                VECTOR_ADD_RDISTRIB; VECTOR_ADD_COMPONENT] THEN
6890   ASM_SIMP_TAC[VECTOR_MUL_COMPONENT; REAL_LE_LMUL;
6891                REAL_LE_LADD; REAL_LE_RADD]);;
6892
6893 let IS_INTERVAL_CONNECTED = prove
6894  (`!s:real^N->bool. is_interval s ==> connected s`,
6895   MESON_TAC[IS_INTERVAL_CONVEX; CONVEX_CONNECTED]);;
6896
6897 let IS_INTERVAL_CONNECTED_1 = prove
6898  (`!s:real^1->bool. is_interval s <=> connected s`,
6899   GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[IS_INTERVAL_CONNECTED] THEN
6900   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
6901   REWRITE_TAC[IS_INTERVAL_1; connected; NOT_FORALL_THM; LEFT_IMP_EXISTS_THM;
6902               NOT_IMP; FORALL_LIFT; LIFT_DROP] THEN
6903   MAP_EVERY X_GEN_TAC [`a:real`; `b:real`; `x:real`] THEN STRIP_TAC THEN
6904   MAP_EVERY EXISTS_TAC
6905    [`{z:real^1 | basis 1 dot z < x}`; `{z:real^1 | basis 1 dot z > x}`] THEN
6906   REWRITE_TAC[OPEN_HALFSPACE_LT; OPEN_HALFSPACE_GT] THEN
6907   SIMP_TAC[SUBSET; EXTENSION; IN_UNION; IN_INTER; GSYM drop; NOT_FORALL_THM;
6908    real_gt; NOT_IN_EMPTY; IN_ELIM_THM; DOT_BASIS; DIMINDEX_1; ARITH] THEN
6909   REPEAT CONJ_TAC THENL
6910    [ASM_MESON_TAC[REAL_LT_TOTAL; LIFT_DROP];
6911     REAL_ARITH_TAC;
6912     EXISTS_TAC `lift a`;
6913     EXISTS_TAC `lift b`] THEN
6914   ASM_REWRITE_TAC[REAL_LT_LE; LIFT_DROP] THEN ASM_MESON_TAC[]);;
6915
6916 let CONVEX_INTERVAL = prove
6917  (`!a b:real^N. convex(interval [a,b]) /\ convex(interval (a,b))`,
6918   SIMP_TAC[IS_INTERVAL_CONVEX; IS_INTERVAL_INTERVAL]);;
6919
6920 let CONNECTED_INTERVAL = prove
6921  (`(!a b:real^N. connected(interval[a,b])) /\
6922    (!a b:real^N. connected(interval(a,b)))`,
6923   SIMP_TAC[CONVEX_CONNECTED; CONVEX_INTERVAL]);;
6924
6925 let CONVEX_CONNECTED_COLLINEAR = prove
6926  (`!s:real^N->bool. collinear s ==> (convex s <=> connected s)`,
6927   REPEAT STRIP_TAC THEN EQ_TAC THEN REWRITE_TAC[CONVEX_CONNECTED] THEN
6928   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COLLINEAR_AFFINE_HULL]) THEN
6929   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
6930   MAP_EVERY X_GEN_TAC [`u:real^N`; `v:real^N`] THEN
6931   GEOM_ORIGIN_TAC `u:real^N` THEN
6932   SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC; IN_INSERT; SPAN_INSERT_0] THEN
6933   GEOM_BASIS_MULTIPLE_TAC 1 `v:real^N` THEN
6934   GEN_TAC THEN DISCH_TAC THEN GEN_TAC THEN
6935   REWRITE_TAC[SPAN_SPECIAL_SCALE] THEN COND_CASES_TAC THENL
6936    [REWRITE_TAC[SPAN_EMPTY; SET_RULE `s SUBSET {a} <=> s = {} \/ s = {a}`] THEN
6937     STRIP_TAC THEN ASM_REWRITE_TAC[CONVEX_EMPTY; CONVEX_SING];
6938     DISCH_TAC THEN
6939     REWRITE_TAC[CONVEX_CONTAINS_SEGMENT; connected; NOT_EXISTS_THM] THEN
6940     DISCH_TAC THEN
6941     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN
6942     ASM_CASES_TAC `a:real^N = b` THEN
6943     ASM_REWRITE_TAC[SEGMENT_REFL; SING_SUBSET] THEN
6944     REWRITE_TAC[SUBSET; IN_SEGMENT; LEFT_IMP_EXISTS_THM] THEN
6945     MAP_EVERY X_GEN_TAC [`x:real^N`; `u:real`] THEN
6946     MAP_EVERY ASM_CASES_TAC [`u = &0`; `u = &1`] THEN
6947     ASM_SIMP_TAC[VECTOR_MUL_LZERO; VECTOR_MUL_LID; REAL_SUB_REFL;
6948                     REAL_SUB_RZERO; VECTOR_ADD_LID; VECTOR_ADD_RID] THEN
6949     ASM_REWRITE_TAC[REAL_LE_LT] THEN STRIP_TAC THEN
6950     FIRST_X_ASSUM(MP_TAC o SPECL
6951      [`{y:real^N | basis 1 dot y < basis 1 dot (x:real^N)}`;
6952       `{y:real^N | basis 1 dot y > basis 1 dot (x:real^N)}`]) THEN
6953     REWRITE_TAC[OPEN_HALFSPACE_LT; OPEN_HALFSPACE_GT] THEN
6954     MATCH_MP_TAC(TAUT `q /\ r /\ (~p ==> s) ==> ~(p /\ q /\ r) ==> s`) THEN
6955     CONJ_TAC THENL
6956      [REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM; NOT_IN_EMPTY] THEN
6957       REWRITE_TAC[CONJ_ASSOC; REAL_ARITH `~(x:real < a /\ x > a)`];
6958       ALL_TAC] THEN
6959     REWRITE_TAC[real_gt] THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
6960     REWRITE_TAC[GSYM DOT_RSUB; SET_RULE
6961      `~(s SUBSET {x | P x} UNION {x | Q x}) <=>
6962       ?x. x IN s /\ ~(P x \/ Q x)`] THEN
6963     SUBGOAL_THEN
6964      `!p q:real^N. p IN span {basis 1} /\ q IN span {basis 1} /\
6965                    basis 1 dot p = basis 1 dot q
6966                    ==> p = q`
6967     ASSUME_TAC THENL
6968      [SIMP_TAC[SPAN_SING; IMP_CONJ; LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN
6969       SIMP_TAC[DOT_RMUL; BASIS_NONZERO; DOT_BASIS_BASIS; DIMINDEX_GE_1;
6970                LE_REFL; REAL_MUL_RID];
6971       ALL_TAC] THEN
6972     SUBGOAL_THEN `(x:real^N) IN span {basis 1}` ASSUME_TAC THENL
6973      [ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SPAN_ADD THEN CONJ_TAC THEN
6974       MATCH_MP_TAC SPAN_MUL THEN ASM SET_TAC[];
6975       ALL_TAC] THEN
6976     CONJ_TAC THENL
6977      [CONJ_TAC THEN MATCH_MP_TAC(SET_RULE
6978        `(a:real^N) IN s \/ b IN s ==> ~(s = {})`) THEN
6979       ASM_REWRITE_TAC[IN_INTER; IN_ELIM_THM; DOT_RADD; DOT_RMUL;
6980         VECTOR_ARITH `((&1 - u) % a + u % b) - b:real^N = (u - &1) % (b - a)`;
6981         VECTOR_ARITH `((&1 - u) % a + u % b) - a:real^N = u % (b - a)`;
6982         VECTOR_ARITH `b - ((&1 - u) % a + u % b):real^N = (u - &1) % (a - b)`;
6983         VECTOR_ARITH `a - ((&1 - u) % a + u % b):real^N = u % (a - b)`] THEN
6984       MATCH_MP_TAC(REAL_ARITH
6985        `(&0 < x ==> &0 < u * x) /\ (&0 < --x ==> &0 < (&1 - u) * --x) /\
6986         ~(x = &0)
6987         ==>  &0 < u * x \/ &0 < (u - &1) * x`) THEN
6988       ASM_SIMP_TAC[REAL_LT_MUL; REAL_SUB_LT] THEN
6989       REWRITE_TAC[DOT_RSUB; REAL_SUB_0];
6990       REWRITE_TAC[DOT_RSUB; REAL_ARITH
6991        `~(&0 < x - y \/ &0 < y - x) <=> y = x`]] THEN
6992     ASM SET_TAC[]]);;
6993
6994 let CONVEX_EQ_CONVEX_LINE_INTERSECTION = prove
6995  (`!s:real^N->bool. convex s <=> !a b. convex(s INTER affine hull {a,b})`,
6996   GEN_TAC THEN EQ_TAC THEN
6997   SIMP_TAC[CONVEX_INTER; AFFINE_IMP_CONVEX; AFFINE_AFFINE_HULL] THEN
6998   REWRITE_TAC[CONVEX_CONTAINS_SEGMENT] THEN DISCH_TAC THEN
6999   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN
7000   FIRST_X_ASSUM(MP_TAC o SPECL
7001    [`a:real^N`; `b:real^N`; `a:real^N`; `b:real^N`]) THEN
7002   ASM_SIMP_TAC[IN_INTER; HULL_INC; IN_INSERT] THEN SET_TAC[]);;
7003
7004 let CONVEX_EQ_CONNECTED_LINE_INTERSECTION = prove
7005  (`!s:real^N->bool. convex s <=> !a b. connected(s INTER affine hull {a,b})`,
7006   GEN_TAC THEN
7007   GEN_REWRITE_TAC LAND_CONV [CONVEX_EQ_CONVEX_LINE_INTERSECTION] THEN
7008   REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
7009   MATCH_MP_TAC CONVEX_CONNECTED_COLLINEAR THEN
7010   MATCH_MP_TAC COLLINEAR_SUBSET THEN
7011   EXISTS_TAC `affine hull {a:real^N,b}` THEN
7012   REWRITE_TAC[COLLINEAR_AFFINE_HULL_COLLINEAR; COLLINEAR_2] THEN
7013   SET_TAC[]);;
7014
7015 (* ------------------------------------------------------------------------- *)
7016 (* On real^1, is_interval, convex and connected are all equivalent.          *)
7017 (* ------------------------------------------------------------------------- *)
7018
7019 let IS_INTERVAL_CONVEX_1 = prove
7020  (`!s:real^1->bool. is_interval s <=> convex s`,
7021   MESON_TAC[IS_INTERVAL_CONVEX; CONVEX_CONNECTED; IS_INTERVAL_CONNECTED_1]);;
7022
7023 let CONVEX_CONNECTED_1 = prove
7024  (`!s:real^1->bool. convex s <=> connected s`,
7025   REWRITE_TAC[GSYM IS_INTERVAL_CONVEX_1; GSYM IS_INTERVAL_CONNECTED_1]);;
7026
7027 let CONNECTED_CONVEX_1 = prove
7028  (`!s:real^1->bool. connected s <=> convex s`,
7029   REWRITE_TAC[GSYM IS_INTERVAL_CONVEX_1; GSYM IS_INTERVAL_CONNECTED_1]);;
7030
7031 let CONNECTED_COMPACT_INTERVAL_1 = prove
7032  (`!s:real^1->bool. connected s /\ compact s <=> ?a b. s = interval[a,b]`,
7033   REWRITE_TAC[GSYM IS_INTERVAL_CONNECTED_1; IS_INTERVAL_COMPACT]);;
7034
7035 let CONVEX_CONNECTED_1_GEN = prove
7036  (`!s:real^N->bool.
7037         dimindex(:N) = 1 ==> (convex s <=> connected s)`,
7038   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN
7039   REWRITE_TAC[GSYM DIMINDEX_1] THEN
7040   DISCH_THEN(ACCEPT_TAC o C GEOM_EQUAL_DIMENSION_RULE CONVEX_CONNECTED_1));;
7041
7042 let CONNECTED_CONVEX_1_GEN = prove
7043  (`!s:real^N->bool.
7044         dimindex(:N) = 1 ==> (convex s <=> connected s)`,
7045   SIMP_TAC[CONVEX_CONNECTED_1_GEN]);;
7046
7047 (* ------------------------------------------------------------------------- *)
7048 (* Jung's theorem.                                                           *)
7049 (* Proof taken from http://cstheory.wordpress.com/2010/08/07/jungs-theorem/  *)
7050 (* ------------------------------------------------------------------------- *)
7051
7052 let JUNG = prove
7053  (`!s:real^N->bool r.
7054         bounded s /\
7055         sqrt(&(dimindex(:N)) / &(2 * dimindex(:N) + 2)) * diameter s <= r
7056         ==> ?a. s SUBSET cball(a,r)`,
7057   let lemma = prove
7058    (`&0 < x /\ x <= y ==> (x - &1) / x <= (y - &1) / y`,
7059     SIMP_TAC[REAL_LE_LDIV_EQ] THEN REPEAT STRIP_TAC THEN
7060     ONCE_REWRITE_TAC[REAL_ARITH `x / y * z:real = (x * z) / y`] THEN
7061     SUBGOAL_THEN `&0 < y` ASSUME_TAC THENL
7062      [ASM_REAL_ARITH_TAC; ASM_SIMP_TAC[REAL_LE_RDIV_EQ]] THEN
7063     ASM_REAL_ARITH_TAC) in
7064   REPEAT STRIP_TAC THEN
7065   SUBGOAL_THEN `&0 <= r` ASSUME_TAC THENL
7066    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
7067         REAL_LE_TRANS)) THEN
7068     MATCH_MP_TAC REAL_LE_MUL THEN ASM_SIMP_TAC[DIAMETER_POS_LE] THEN
7069     SIMP_TAC[SQRT_POS_LE; REAL_LE_DIV; REAL_POS];
7070     ALL_TAC] THEN
7071   MP_TAC(ISPEC `IMAGE (\x:real^N. cball(x,r)) s` HELLY_COMPACT_ALT) THEN
7072   REWRITE_TAC[FORALL_IN_IMAGE; COMPACT_CBALL; CONVEX_CBALL] THEN
7073   REWRITE_TAC[TAUT `p /\ q /\ r ==> s <=> q /\ p ==> r ==> s`] THEN
7074   REWRITE_TAC[FORALL_FINITE_SUBSET_IMAGE] THEN
7075   REWRITE_TAC[INTERS_IMAGE; GSYM MEMBER_NOT_EMPTY] THEN
7076   REWRITE_TAC[SUBSET; IN_CBALL; IN_ELIM_THM] THEN
7077   ANTS_TAC THENL [ALL_TAC; MESON_TAC[DIST_SYM]] THEN
7078   X_GEN_TAC `t:real^N->bool` THEN REWRITE_TAC[GSYM SUBSET] THEN
7079   STRIP_TAC THEN
7080   ASM_SIMP_TAC[CARD_IMAGE_INJ; EQ_BALLS; GSYM REAL_NOT_LE] THEN
7081   UNDISCH_TAC `FINITE(t:real^N->bool)` THEN
7082   SUBGOAL_THEN `bounded(t:real^N->bool)` MP_TAC THENL
7083    [ASM_MESON_TAC[BOUNDED_SUBSET]; ALL_TAC] THEN
7084   UNDISCH_TAC `&0 <= r` THEN
7085   SUBGOAL_THEN
7086    `sqrt(&(dimindex(:N)) / &(2 * dimindex(:N) + 2)) *
7087     diameter(t:real^N->bool) <= r`
7088   MP_TAC THENL
7089    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
7090         REAL_LE_TRANS)) THEN
7091     MATCH_MP_TAC REAL_LE_LMUL THEN
7092     ASM_SIMP_TAC[DIAMETER_SUBSET; SQRT_POS_LE; REAL_POS; REAL_LE_DIV];
7093     POP_ASSUM_LIST(K ALL_TAC) THEN
7094     SPEC_TAC(`t:real^N->bool`,`s:real^N->bool`) THEN
7095     REPEAT STRIP_TAC] THEN
7096   ASM_CASES_TAC `s:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
7097   MP_TAC(ISPEC `{d | &0 <= d /\ ?a:real^N. s SUBSET cball(a,d)}` INF) THEN
7098   ABBREV_TAC `d = inf {d | &0 <= d /\ ?a:real^N. s SUBSET cball(a,d)}` THEN
7099   REWRITE_TAC[IN_ELIM_THM] THEN ANTS_TAC THENL
7100    [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
7101     ASM_MESON_TAC[BOUNDED_SUBSET_CBALL; REAL_LT_IMP_LE];
7102     DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "P") (LABEL_TAC "M"))] THEN
7103   SUBGOAL_THEN `&0 <= d` ASSUME_TAC THENL
7104    [ASM_MESON_TAC[REAL_LE_REFL]; ALL_TAC] THEN
7105   SUBGOAL_THEN `?a:real^N. s SUBSET cball(a,d)` MP_TAC THENL
7106    [SUBGOAL_THEN
7107      `!n. ?a:real^N. s SUBSET cball(a,d + inv(&n + &1))`
7108     MP_TAC THENL
7109      [X_GEN_TAC `n:num` THEN
7110       REMOVE_THEN "M" (MP_TAC o SPEC `d + inv(&n + &1)`) THEN
7111       REWRITE_TAC[REAL_ARITH `d + i <= d <=> ~(&0 < i)`] THEN
7112       REWRITE_TAC[REAL_LT_INV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
7113       REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; REAL_NOT_LE] THEN
7114       MESON_TAC[SUBSET_CBALL; REAL_LT_IMP_LE; SUBSET_TRANS];
7115       ALL_TAC] THEN
7116     REWRITE_TAC[LEFT_IMP_EXISTS_THM; SKOLEM_THM] THEN
7117     X_GEN_TAC `aa:num->real^N` THEN DISCH_TAC THEN
7118     SUBGOAL_THEN `?t. compact t /\ !n. (aa:num->real^N) n IN t` MP_TAC THENL
7119      [FIRST_X_ASSUM(MP_TAC o SPEC `vec 0:real^N` o
7120         MATCH_MP BOUNDED_SUBSET_CBALL) THEN
7121       REWRITE_TAC[LEFT_IMP_EXISTS_THM; SUBSET; IN_CBALL_0] THEN
7122       X_GEN_TAC `B:real` THEN STRIP_TAC THEN
7123       EXISTS_TAC `cball(vec 0:real^N,B + d + &1)` THEN
7124       REWRITE_TAC[COMPACT_CBALL; IN_CBALL_0] THEN X_GEN_TAC `n:num` THEN
7125       RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; IN_CBALL]) THEN
7126       MATCH_MP_TAC(NORM_ARITH
7127        `(?x:real^N. norm(x) <= B /\ dist(a,x) <= d) ==> norm(a) <= B + d`) THEN
7128       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
7129       MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM_SIMP_TAC[] THEN
7130       MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `d + inv(&n + &1)` THEN
7131       ASM_SIMP_TAC[REAL_LE_LADD] THEN
7132       MATCH_MP_TAC REAL_INV_LE_1 THEN REAL_ARITH_TAC;
7133       ALL_TAC] THEN
7134     REWRITE_TAC[compact; LEFT_IMP_EXISTS_THM] THEN
7135     X_GEN_TAC `t:real^N->bool` THEN
7136     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
7137     DISCH_THEN(MP_TAC o SPEC `aa:num->real^N`) THEN ASM_REWRITE_TAC[] THEN
7138     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
7139     DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN
7140     REWRITE_TAC[SUBSET; IN_CBALL] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7141     REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
7142     MP_TAC(SPEC `(dist(a:real^N,x) - d) / &2` REAL_ARCH_INV) THEN
7143     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
7144     DISCH_THEN(MP_TAC o SPEC `(dist(a:real^N,x) - d) / &2`) THEN
7145     ASM_SIMP_TAC[REAL_SUB_LT; REAL_HALF; o_THM] THEN
7146     DISCH_THEN(X_CHOOSE_THEN `N1:num` STRIP_ASSUME_TAC) THEN
7147     DISCH_THEN(X_CHOOSE_THEN `N2:num` STRIP_ASSUME_TAC) THEN
7148     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE BINDER_CONV [SUBSET]) THEN
7149     DISCH_THEN(MP_TAC o SPECL [`(r:num->num)(N1 + N2)`; `x:real^N`]) THEN
7150     ASM_REWRITE_TAC[IN_CBALL; REAL_NOT_LE] THEN
7151     FIRST_X_ASSUM(MP_TAC o SPEC `N1 + N2:num`) THEN
7152     ASM_REWRITE_TAC[LE_ADD] THEN
7153     SUBGOAL_THEN `inv(&(r (N1 + N2:num)) + &1) < (dist(a:real^N,x) - d) / &2`
7154     MP_TAC THENL [ALL_TAC; NORM_ARITH_TAC] THEN
7155     MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&N2)` THEN
7156     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
7157     CONJ_TAC THENL [ASM_MESON_TAC[REAL_LT_INV_EQ]; ALL_TAC] THEN
7158     REWRITE_TAC[REAL_OF_NUM_LE; REAL_OF_NUM_ADD] THEN
7159     MATCH_MP_TAC(ARITH_RULE
7160       `N1 + N2 <= r(N1 + N2) ==> N2 <= r(N1 + N2) + 1`) THEN
7161     ASM_MESON_TAC[MONOTONE_BIGGER];
7162     ALL_TAC] THEN
7163   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
7164   ONCE_REWRITE_TAC[DIST_SYM] THEN
7165   REWRITE_TAC[GSYM IN_CBALL; GSYM SUBSET] THEN
7166   DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
7167   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] SUBSET_TRANS) THEN
7168   MATCH_MP_TAC SUBSET_CBALL THEN
7169   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
7170    `a * s <= r ==> d <= a * s ==> d <= r`)) THEN
7171   UNDISCH_THEN `&0 <= r` (K ALL_TAC) THEN REMOVE_THEN "M" (K ALL_TAC) THEN
7172   FIRST_X_ASSUM(K ALL_TAC o SYM) THEN REMOVE_THEN "P" MP_TAC THEN
7173   REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
7174   ABBREV_TAC `n = CARD(s:real^N->bool)` THEN
7175   SUBGOAL_THEN `(s:real^N->bool) HAS_SIZE n` MP_TAC THENL
7176    [ASM_REWRITE_TAC[HAS_SIZE]; ALL_TAC] THEN
7177   UNDISCH_THEN `CARD(s:real^N->bool) = n` (K ALL_TAC) THEN
7178   POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
7179   SPEC_TAC(`d:real`,`r:real`) THEN GEN_TAC THEN
7180   GEOM_ORIGIN_TAC `a:real^N` THEN SIMP_TAC[HAS_SIZE] THEN
7181   REPEAT STRIP_TAC THEN FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN
7182   ABBREV_TAC `t = {x:real^N | x IN s /\ norm(x) = r}` THEN
7183   SUBGOAL_THEN `FINITE(t:real^N->bool)` ASSUME_TAC THENL
7184    [EXPAND_TAC "t" THEN ASM_SIMP_TAC[FINITE_RESTRICT]; ALL_TAC] THEN
7185   SUBGOAL_THEN `(vec 0:real^N) IN convex hull t` MP_TAC THENL
7186    [MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
7187     MP_TAC(ISPEC `convex hull t:real^N->bool`
7188       SEPARATING_HYPERPLANE_CLOSED_0) THEN
7189     ASM_SIMP_TAC[CONVEX_CONVEX_HULL; NOT_IMP; COMPACT_CONVEX_HULL;
7190                  FINITE_IMP_COMPACT; COMPACT_IMP_CLOSED] THEN
7191     REWRITE_TAC[NOT_EXISTS_THM; TAUT `~(p /\ q) <=> p ==> ~q`] THEN
7192     X_GEN_TAC `v:real^N` THEN
7193     ABBREV_TAC `k = CARD(s:real^N->bool)` THEN
7194     SUBGOAL_THEN `(s:real^N->bool) HAS_SIZE k` MP_TAC THENL
7195      [ASM_REWRITE_TAC[HAS_SIZE]; ALL_TAC] THEN
7196     UNDISCH_THEN `CARD(s:real^N->bool) = k` (K ALL_TAC) THEN
7197     POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
7198     GEOM_BASIS_MULTIPLE_TAC 1 `v:real^N` THEN X_GEN_TAC `m:real` THEN
7199     GEN_REWRITE_TAC LAND_CONV [REAL_ARITH `&0 <= x <=> x = &0 \/ &0 < x`] THEN
7200     STRIP_TAC THEN ASM_REWRITE_TAC[VECTOR_MUL_EQ_0] THEN
7201     ASM_SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL; REAL_LT_IMP_NZ] THEN
7202     REPEAT GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[HAS_SIZE] THEN
7203     DISCH_THEN(SUBST_ALL_TAC o SYM) THEN X_GEN_TAC `b:real` THEN DISCH_TAC THEN
7204     ASM_SIMP_TAC[DOT_LMUL; DOT_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
7205     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
7206     ASM_SIMP_TAC[real_gt; GSYM REAL_LT_LDIV_EQ] THEN
7207     SUBGOAL_THEN `&0 < b / m` MP_TAC THENL
7208      [ASM_SIMP_TAC[REAL_LT_DIV];
7209       UNDISCH_THEN `&0 < b` (K ALL_TAC) THEN
7210       SPEC_TAC(`b / m:real`,`b:real`)] THEN
7211     X_GEN_TAC `b:real` THEN DISCH_TAC THEN DISCH_TAC THEN
7212     SUBGOAL_THEN
7213      `!x:real^N e. &0 < e /\ e < b /\ x IN t ==> norm(x - e % basis 1) < r`
7214     ASSUME_TAC THENL
7215      [MAP_EVERY X_GEN_TAC [`x:real^N`; `e:real`] THEN STRIP_TAC THEN
7216       SUBGOAL_THEN `r = norm(x:real^N)` SUBST1_TAC THENL
7217        [ASM SET_TAC[]; REWRITE_TAC[NORM_LT; dot]] THEN
7218       SIMP_TAC[SUM_CLAUSES_LEFT; DIMINDEX_GE_1] THEN
7219       SIMP_TAC[VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT;
7220                BASIS_COMPONENT; DIMINDEX_GE_1; LE_REFL;
7221                ARITH_RULE `2 <= n ==> 1 <= n /\ ~(n = 1)`; ARITH] THEN
7222       REWRITE_TAC[REAL_MUL_RZERO; REAL_SUB_RZERO; REAL_LT_RADD] THEN
7223       REWRITE_TAC[GSYM REAL_POW_2; GSYM REAL_LT_SQUARE_ABS] THEN
7224       MATCH_MP_TAC(REAL_ARITH
7225        `!b. &0 < e /\ e < b /\ b < x ==> abs(x - e * &1) < abs x`) THEN
7226       EXISTS_TAC `b:real` THEN ASM_REWRITE_TAC[] THEN
7227       ASM_MESON_TAC[HULL_INC];
7228       ALL_TAC] THEN
7229     SUBGOAL_THEN
7230      `?d. &0 < d /\
7231           !x:real^N a. x IN (s DIFF t) /\ norm(a) < d ==> norm(x - a) < r`
7232     STRIP_ASSUME_TAC THENL
7233      [ASM_CASES_TAC `s DIFF t:real^N->bool = {}` THENL
7234        [ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN MESON_TAC[REAL_LT_01]; ALL_TAC] THEN
7235       EXISTS_TAC `inf (IMAGE (\x:real^N. r - norm x) (s DIFF t))` THEN
7236       SUBGOAL_THEN `FINITE(s DIFF t:real^N->bool)` ASSUME_TAC THENL
7237        [ASM_MESON_TAC[FINITE_DIFF]; ALL_TAC] THEN
7238       ASM_SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
7239       REWRITE_TAC[FORALL_IN_IMAGE] THEN SIMP_TAC
7240        [NORM_ARITH `norm a < r - norm x ==> norm(x - a:real^N) < r`] THEN
7241       EXPAND_TAC "t" THEN REWRITE_TAC[IN_DIFF; IN_ELIM_THM; REAL_SUB_LT] THEN
7242       RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; IN_CBALL_0]) THEN
7243       ASM_MESON_TAC[REAL_LT_LE];
7244       ALL_TAC] THEN
7245     SUBGOAL_THEN
7246      `?a. !x. x IN s ==> norm(x - a:real^N) < r`
7247     STRIP_ASSUME_TAC THENL
7248      [EXISTS_TAC `min (b / &2) (d / &2) % basis 1:real^N` THEN
7249       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7250       ASM_CASES_TAC `(x:real^N) IN t` THENL
7251        [MATCH_MP_TAC(ASSUME
7252          `!x:real^N e. &0 < e /\ e < b /\ x IN t
7253                        ==> norm (x - e % basis 1) < r`) THEN
7254         ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
7255         MATCH_MP_TAC(ASSUME
7256          `!x:real^N a. x IN s DIFF t /\ norm a < d ==> norm (x - a) < r`) THEN
7257         ASM_SIMP_TAC[IN_DIFF; NORM_MUL; LE_REFL; NORM_BASIS;
7258                      DIMINDEX_GE_1] THEN
7259         ASM_REAL_ARITH_TAC];
7260       SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL
7261        [ASM_MESON_TAC[MEMBER_NOT_EMPTY; NORM_ARITH
7262          `norm(x:real^N) < r ==> &0 < r`];
7263         ALL_TAC] THEN
7264       UNDISCH_THEN
7265         `!x a:real^N. &0 <= x /\ s SUBSET cball (a,x) ==> r <= x` (MP_TAC o
7266         SPECL [`max (&0) (r - inf (IMAGE (\x:real^N. r - norm(x - a)) s))`;
7267                `a:real^N`]) THEN
7268       ASM_SIMP_TAC[REAL_ARITH `&0 < r ==> (r <= max (&0) a <=> r <= a)`] THEN
7269       REWRITE_TAC[SUBSET; IN_CBALL; REAL_ARITH `a <= max a b`] THEN
7270       REWRITE_TAC[NOT_IMP; REAL_ARITH `~(r <= r - x) <=> &0 < x`] THEN
7271       ASM_SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
7272       ASM_REWRITE_TAC[FORALL_IN_IMAGE; REAL_SUB_LT] THEN
7273       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7274       MATCH_MP_TAC(REAL_ARITH `d <= b ==> d <= max a b`) THEN
7275       ONCE_REWRITE_TAC[REAL_ARITH `a <= b - c <=> c <= b - a`] THEN
7276       ASM_SIMP_TAC[REAL_INF_LE_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
7277       REWRITE_TAC[EXISTS_IN_IMAGE; ONCE_REWRITE_RULE[NORM_SUB] dist] THEN
7278       ASM_MESON_TAC[REAL_LE_REFL]];
7279     ALL_TAC] THEN
7280   ASM_CASES_TAC `t:real^N->bool = {}` THEN
7281   ASM_REWRITE_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY] THEN
7282   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
7283   DISCH_THEN(X_CHOOSE_THEN `l:real^N->real` STRIP_ASSUME_TAC) THEN
7284   MATCH_MP_TAC REAL_LE_TRANS THEN
7285   EXISTS_TAC `sqrt((&(dimindex (:N)) / &(2 * dimindex (:N) + 2)) *
7286                    diameter(s:real^N->bool) pow 2)` THEN
7287   CONJ_TAC THENL
7288    [MATCH_MP_TAC REAL_LE_RSQRT;
7289     ASM_SIMP_TAC[SQRT_MUL; DIAMETER_POS_LE; REAL_POW_LE; REAL_LE_DIV;
7290                  REAL_POS; POW_2_SQRT; REAL_LE_REFL]] THEN
7291
7292   SUBGOAL_THEN
7293    `sum t (\y:real^N. &2 * r pow 2) <=
7294     sum t (\y. (&1 - l y) * diameter(s:real^N->bool) pow 2)`
7295   MP_TAC THENL
7296    [MATCH_MP_TAC SUM_LE THEN ASM_REWRITE_TAC[] THEN
7297     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7298     MATCH_MP_TAC REAL_LE_TRANS THEN
7299     EXISTS_TAC `sum (t DELETE x) (\x:real^N. l(x)) *
7300                 diameter(s:real^N->bool) pow 2` THEN CONJ_TAC THENL
7301      [ALL_TAC; ASM_SIMP_TAC[SUM_DELETE; ETA_AX; REAL_LE_REFL]] THEN
7302     REWRITE_TAC[GSYM SUM_RMUL] THEN MATCH_MP_TAC REAL_LE_TRANS THEN
7303     EXISTS_TAC `sum (t DELETE x) (\y:real^N. l y * norm(y - x) pow 2)` THEN
7304     CONJ_TAC THENL
7305      [ALL_TAC;
7306       MATCH_MP_TAC SUM_LE THEN ASM_REWRITE_TAC[FINITE_DELETE; IN_DELETE] THEN
7307       X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN MATCH_MP_TAC REAL_LE_LMUL THEN
7308       ASM_SIMP_TAC[] THEN MATCH_MP_TAC REAL_POW_LE2 THEN
7309       REWRITE_TAC[NORM_POS_LE] THEN
7310       MATCH_MP_TAC DIAMETER_BOUNDED_BOUND THEN ASM SET_TAC[]] THEN
7311     MATCH_MP_TAC REAL_LE_TRANS THEN
7312     EXISTS_TAC `sum t (\y:real^N. l y * norm (y - x) pow 2)` THEN
7313     CONJ_TAC THENL
7314      [ALL_TAC;
7315       MATCH_MP_TAC REAL_EQ_IMP_LE THEN MATCH_MP_TAC SUM_EQ_SUPERSET THEN
7316       ASM_REWRITE_TAC[FINITE_DELETE] THEN
7317       CONJ_TAC THENL [SET_TAC[]; REWRITE_TAC[IN_DELETE]] THEN
7318       SIMP_TAC[TAUT `p /\ ~(p /\ ~q) <=> p /\ q`] THEN
7319       REWRITE_TAC[VECTOR_SUB_REFL; NORM_0] THEN REAL_ARITH_TAC] THEN
7320     REWRITE_TAC[NORM_POW_2; VECTOR_ARITH
7321      `(y - x:real^N) dot (y - x) = (x dot x + y dot y) - &2 * x dot y`] THEN
7322     MATCH_MP_TAC REAL_LE_TRANS THEN
7323     EXISTS_TAC `sum t (\y:real^N. l y * (&2 * r pow 2 - &2 * (x dot y)))` THEN
7324     CONJ_TAC THENL
7325      [ALL_TAC;
7326       MATCH_MP_TAC REAL_EQ_IMP_LE THEN MATCH_MP_TAC SUM_EQ THEN
7327       UNDISCH_TAC `(x:real^N) IN t` THEN EXPAND_TAC "t" THEN
7328       REWRITE_TAC[IN_DELETE; IN_ELIM_THM] THEN
7329       SIMP_TAC[NORM_EQ_SQUARE; NORM_POW_2] THEN REAL_ARITH_TAC] THEN
7330     REWRITE_TAC[REAL_ARITH `x * (&2 * y - &2 * z) = &2 * (x * y - x * z)`] THEN
7331     REWRITE_TAC[SUM_LMUL] THEN MATCH_MP_TAC REAL_LE_LMUL THEN
7332     REWRITE_TAC[REAL_POS] THEN
7333     ASM_SIMP_TAC[SUM_SUB; FINITE_DELETE; SUM_RMUL] THEN
7334     REWRITE_TAC[GSYM DOT_RMUL] THEN
7335     ASM_SIMP_TAC[GSYM DOT_RSUM; DOT_RZERO] THEN REAL_ARITH_TAC;
7336     ASM_SIMP_TAC[SUM_CONST; SUM_RMUL; SUM_SUB] THEN
7337     REWRITE_TAC[REAL_OF_NUM_MUL; MULT_CLAUSES] THEN
7338     GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [REAL_MUL_SYM] THEN
7339     SUBGOAL_THEN `&0 < &(CARD(t:real^N->bool) * 2)` ASSUME_TAC THENL
7340      [REWRITE_TAC[REAL_OF_NUM_LT; ARITH_RULE `0 < n * 2 <=> ~(n = 0)`] THEN
7341       ASM_SIMP_TAC[CARD_EQ_0];
7342       ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ] THEN
7343       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
7344       REWRITE_TAC[REAL_ARITH `(a * b) / c:real = a / c * b`] THEN
7345       MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_LE_POW_2] THEN
7346       REWRITE_TAC[ARITH_RULE `2 * n + 2 = (n + 1) * 2`; GSYM REAL_OF_NUM_MUL;
7347                   real_div; REAL_INV_MUL; REAL_MUL_ASSOC] THEN
7348       MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[GSYM real_div] THEN
7349       CONV_TAC REAL_RAT_REDUCE_CONV THEN
7350       SUBGOAL_THEN `&(dimindex(:N)) = &(dimindex(:N) + 1) - &1`
7351       SUBST1_TAC THENL
7352        [REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN REAL_ARITH_TAC;
7353         MATCH_MP_TAC lemma THEN
7354         ASM_SIMP_TAC[REAL_OF_NUM_LE; REAL_OF_NUM_LT; CARD_EQ_0;
7355                      ARITH_RULE `0 < n <=> ~(n = 0)`] THEN
7356         MATCH_MP_TAC LE_TRANS THEN EXISTS_TAC `CARD(s:real^N->bool)` THEN
7357         ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CARD_SUBSET THEN
7358         ASM SET_TAC[]]]]);;
7359
7360 (* ------------------------------------------------------------------------- *)
7361 (* The Dugundji extension theorem, and Tietze variants as corollaries.       *)
7362 (* ------------------------------------------------------------------------- *)
7363
7364 let DUGUNDJI = prove
7365  (`!f:real^M->real^N c u s.
7366         convex c /\ ~(c = {}) /\
7367         closed_in (subtopology euclidean u) s /\
7368         f continuous_on s /\ IMAGE f s SUBSET c
7369         ==> ?g. g continuous_on u /\ IMAGE g u SUBSET c /\
7370                 !x. x IN s ==> g x = f x`,
7371   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^M->bool = {}` THENL
7372    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
7373     DISCH_THEN(X_CHOOSE_TAC `y:real^N`) THEN
7374     EXISTS_TAC `(\x. y):real^M->real^N` THEN
7375     REWRITE_TAC[CONTINUOUS_ON_CONST] THEN ASM SET_TAC[];
7376     ALL_TAC] THEN
7377   MP_TAC(ISPECL [`u DIFF s:real^M->bool`;
7378                  `{ ball(x:real^M,setdist({x},s) / &2) |x| x IN u DIFF s}`]
7379         PARACOMPACT) THEN
7380   REWRITE_TAC[FORALL_IN_GSPEC; EXISTS_IN_GSPEC; OPEN_BALL] THEN ANTS_TAC THENL
7381    [REWRITE_TAC[SUBSET; IN_DIFF; IN_ELIM_THM; UNIONS_GSPEC] THEN
7382     X_GEN_TAC `x:real^M` THEN STRIP_TAC THEN EXISTS_TAC `x:real^M` THEN
7383     ASM_REWRITE_TAC[CENTRE_IN_BALL] THEN
7384     MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ ~(x = &0) ==> &0 < x / &2`) THEN
7385     ASM_MESON_TAC[SETDIST_POS_LE; SETDIST_EQ_0_CLOSED_IN];
7386     DISCH_THEN(X_CHOOSE_THEN `c:(real^M->bool)->bool` STRIP_ASSUME_TAC)] THEN
7387   SUBGOAL_THEN
7388    `!t. t IN c
7389         ==> ?v a:real^M. v IN u /\ ~(v IN s) /\ a IN s /\
7390                          t SUBSET ball(v,setdist({v},s) / &2) /\
7391                          dist(v,a) <= &2 * setdist({v},s)`
7392   MP_TAC THENL
7393    [X_GEN_TAC `t:real^M->bool` THEN DISCH_TAC THEN
7394     FIRST_X_ASSUM(MP_TAC o SPEC `t:real^M->bool`) THEN
7395     ASM_REWRITE_TAC[] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
7396     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v:real^M` THEN
7397     REWRITE_TAC[IN_DIFF] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
7398     MP_TAC(ISPECL[`{v:real^M}`; `s:real^M->bool`; `&2 * setdist({v:real^M},s)`]
7399         REAL_SETDIST_LT_EXISTS) THEN
7400     ASM_SIMP_TAC[NOT_INSERT_EMPTY; SETDIST_POS_LE; REAL_ARITH
7401       `&0 <= x ==> (x < &2 * x <=> ~(x = &0))`] THEN
7402     ASM_MESON_TAC[REAL_LT_IMP_LE; IN_SING; SETDIST_EQ_0_CLOSED_IN];
7403     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
7404     REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC
7405      [`vv:(real^M->bool)->real^M`; `aa:(real^M->bool)->real^M`] THEN
7406     STRIP_TAC] THEN
7407   SUBGOAL_THEN
7408    `!t v:real^M. t IN c /\ v IN t ==> setdist({vv t},s) <= &2 * setdist({v},s)`
7409   ASSUME_TAC THENL
7410    [REPEAT STRIP_TAC THEN
7411     FIRST_X_ASSUM(MP_TAC o SPEC `t:real^M->bool`) THEN
7412     ASM_REWRITE_TAC[SUBSET] THEN DISCH_THEN(MP_TAC o el 3 o CONJUNCTS) THEN
7413     DISCH_THEN(MP_TAC o SPEC `v:real^M`) THEN ASM_REWRITE_TAC[IN_BALL] THEN
7414     MP_TAC(ISPECL [`s:real^M->bool`; `(vv:(real^M->bool)->real^M) t`;
7415                    `v:real^M`] SETDIST_SING_TRIANGLE) THEN
7416     REAL_ARITH_TAC;
7417     ALL_TAC] THEN
7418   SUBGOAL_THEN
7419    `!t v a:real^M. t IN c /\ v IN t /\ a IN s
7420                    ==> dist(a,aa t) <= &6 * dist(a,v)`
7421   ASSUME_TAC THENL
7422    [REPEAT STRIP_TAC THEN
7423     FIRST_X_ASSUM(MP_TAC o SPECL [`t:real^M->bool`; `v:real^M`]) THEN
7424     ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MP_TAC o SPEC `t:real^M->bool`) THEN
7425     ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o funpow 3 CONJUNCT2) THEN
7426     REWRITE_TAC[IMP_CONJ; SUBSET; IN_BALL] THEN
7427     DISCH_THEN(MP_TAC o SPEC `v:real^M`) THEN ASM_REWRITE_TAC[] THEN
7428     MP_TAC(ISPECL [`{v:real^M}`; `s:real^M->bool`; `v:real^M`; `a:real^M`]
7429         SETDIST_LE_DIST) THEN
7430     ASM_REWRITE_TAC[IN_SING] THEN CONV_TAC NORM_ARITH;
7431     ALL_TAC] THEN
7432   MP_TAC(ISPECL [`c:(real^M->bool)->bool`; `u DIFF s:real^M->bool`]
7433         SUBORDINATE_PARTITION_OF_UNITY) THEN
7434   ASM_SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN
7435   X_GEN_TAC `h:(real^M->bool)->real^M->real` THEN STRIP_TAC THEN
7436   EXISTS_TAC
7437    `\x. if x IN s then (f:real^M->real^N) x
7438         else vsum c (\t:real^M->bool. h t x % f(aa t))` THEN
7439   SIMP_TAC[] THEN CONJ_TAC THENL
7440    [ALL_TAC;
7441     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
7442     X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
7443     COND_CASES_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7444     MATCH_MP_TAC CONVEX_VSUM_STRONG THEN ASM SET_TAC[]] THEN
7445   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
7446   X_GEN_TAC `a:real^M` THEN DISCH_TAC THEN
7447   ASM_CASES_TAC `(a:real^M) IN s` THENL
7448    [ALL_TAC;
7449     MATCH_MP_TAC CONTINUOUS_TRANSFORM_WITHIN_OPEN_IN THEN
7450     MAP_EVERY EXISTS_TAC
7451      [`\x:real^M.
7452         vsum c (\t:real^M->bool. h t x % (f:real^M->real^N) (aa t))`;
7453       `u DIFF s:real^M->bool`] THEN
7454     ASM_SIMP_TAC[OPEN_IN_DIFF; OPEN_IN_REFL; IN_DIFF] THEN
7455     FIRST_X_ASSUM(MP_TAC o SPEC `a:real^M`) THEN
7456     ASM_REWRITE_TAC[IN_DIFF] THEN
7457     DISCH_THEN(X_CHOOSE_THEN `n:real^M->bool` STRIP_ASSUME_TAC) THEN
7458     MATCH_MP_TAC CONTINUOUS_TRANSFORM_WITHIN_OPEN_IN THEN MAP_EVERY EXISTS_TAC
7459      [`\x. vsum {u | u IN c /\ ~(!x:real^M. x IN n ==> h u x = &0)}
7460                 (\t:real^M->bool. h t x % (f:real^M->real^N) (aa t))`;
7461       `(u DIFF s) INTER n:real^M->bool`] THEN
7462     ASM_SIMP_TAC[OPEN_IN_DIFF; OPEN_IN_REFL; OPEN_IN_INTER_OPEN;
7463                  IN_INTER; IN_DIFF] THEN
7464     CONJ_TAC THENL
7465      [REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN
7466       MATCH_MP_TAC VSUM_SUPERSET THEN
7467       REWRITE_TAC[VECTOR_MUL_EQ_0] THEN ASM SET_TAC[];
7468       MATCH_MP_TAC CONTINUOUS_VSUM THEN ASM_REWRITE_TAC[IN_ELIM_THM] THEN
7469       REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_VMUL THEN
7470       FIRST_X_ASSUM(MP_TAC o SPEC `t:real^M->bool`) THEN
7471       ASM_REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
7472       DISCH_THEN(MP_TAC o SPEC `a:real^M` o CONJUNCT1) THEN
7473       ASM_REWRITE_TAC[IN_DIFF; ETA_AX] THEN
7474       REWRITE_TAC[CONTINUOUS_WITHIN] THEN MATCH_MP_TAC EQ_IMP THEN
7475       MATCH_MP_TAC LIM_TRANSFORM_WITHIN_SET THEN
7476       SUBGOAL_THEN `open_in (subtopology euclidean u) (u DIFF s:real^M->bool)`
7477       MP_TAC THENL [ASM_SIMP_TAC[OPEN_IN_DIFF; OPEN_IN_REFL]; ALL_TAC] THEN
7478       REWRITE_TAC[EVENTUALLY_AT; OPEN_IN_CONTAINS_BALL] THEN
7479       DISCH_THEN(MP_TAC o SPEC `a:real^M` o CONJUNCT2) THEN
7480       ASM_REWRITE_TAC[IN_DIFF] THEN MATCH_MP_TAC MONO_EXISTS THEN
7481       REWRITE_TAC[SUBSET; IN_BALL; IN_INTER; IN_DIFF] THEN
7482       MESON_TAC[DIST_SYM]]] THEN
7483   ASM_REWRITE_TAC[CONTINUOUS_WITHIN_OPEN] THEN
7484   X_GEN_TAC `w:real^N->bool` THEN STRIP_TAC THEN
7485   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
7486   DISCH_THEN(MP_TAC o SPEC `(f:real^M->real^N) a`) THEN ASM_REWRITE_TAC[] THEN
7487   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
7488   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I
7489    [CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN]) THEN
7490   DISCH_THEN(MP_TAC o SPEC `a:real^M`) THEN ASM_REWRITE_TAC[] THEN
7491   REWRITE_TAC[continuous_within] THEN
7492   DISCH_THEN(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
7493   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
7494   EXISTS_TAC `ball(a:real^M,d / &6)` THEN
7495   ASM_REWRITE_TAC[CENTRE_IN_BALL; OPEN_BALL] THEN
7496   ASM_REWRITE_TAC[REAL_ARITH `&0 < e / &6 <=> &0 < e`] THEN
7497   X_GEN_TAC `x:real^M` THEN REWRITE_TAC[IN_BALL] THEN STRIP_TAC THEN
7498   FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
7499   COND_CASES_TAC THENL
7500    [REWRITE_TAC[IN_BALL] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
7501     FIRST_X_ASSUM MATCH_MP_TAC THEN
7502     ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN ASM_REAL_ARITH_TAC;
7503     ALL_TAC] THEN
7504   MATCH_MP_TAC CONVEX_VSUM_STRONG THEN
7505   ASM_SIMP_TAC[CONVEX_BALL; IN_DIFF] THEN
7506   X_GEN_TAC `t:real^M->bool` THEN DISCH_TAC THEN
7507   ASM_CASES_TAC `(x:real^M) IN t` THENL [DISJ2_TAC; ASM SET_TAC[]] THEN
7508   REWRITE_TAC[IN_BALL] THEN
7509   ONCE_REWRITE_TAC[DIST_SYM] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
7510   ASM_SIMP_TAC[] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (NORM_ARITH
7511    `dist(a:real^M,v) < d / &6
7512     ==> dist(a,a') <= &6 * dist(a,v) ==> dist(a',a) < d`)) THEN
7513   ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;
7514
7515 let TIETZE = prove
7516  (`!f:real^M->real^N u s B.
7517         &0 <= B /\
7518         closed_in (subtopology euclidean u) s /\
7519         f continuous_on s /\
7520         (!x. x IN s ==> norm(f x) <= B)
7521         ==> ?g. g continuous_on u /\
7522                 (!x. x IN s ==> g x = f x) /\
7523                 (!x. x IN u ==> norm(g x) <= B)`,
7524   REPEAT STRIP_TAC THEN
7525   MP_TAC(ISPECL [`f:real^M->real^N`; `cball(vec 0:real^N,B)`; `u:real^M->bool`;
7526                  `s:real^M->bool`] DUGUNDJI) THEN
7527   ASM_REWRITE_TAC[CONVEX_CBALL; CBALL_EQ_EMPTY; REAL_NOT_LT] THEN
7528   ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_CBALL_0] THEN
7529   MESON_TAC[]);;
7530
7531 let TIETZE_CLOSED_INTERVAL = prove
7532  (`!f:real^M->real^N u s a b.
7533         ~(interval[a,b] = {}) /\
7534         closed_in (subtopology euclidean u) s /\
7535         f continuous_on s /\
7536         (!x. x IN s ==> f x IN interval[a,b])
7537         ==> ?g. g continuous_on u /\
7538                 (!x. x IN s ==> g x = f x) /\
7539                 (!x. x IN u ==> g(x) IN interval[a,b])`,
7540   REPEAT STRIP_TAC THEN
7541   MP_TAC(ISPECL [`f:real^M->real^N`; `interval[a:real^N,b]`; `u:real^M->bool`;
7542                  `s:real^M->bool`] DUGUNDJI) THEN
7543   ASM_REWRITE_TAC[CONVEX_INTERVAL; SUBSET; FORALL_IN_IMAGE] THEN
7544   MESON_TAC[]);;
7545
7546 let TIETZE_CLOSED_INTERVAL_1 = prove
7547  (`!f:real^N->real^1 u s a b.
7548         drop a <= drop b /\
7549         closed_in (subtopology euclidean u) s /\
7550         f continuous_on s /\
7551         (!x. x IN s ==> f x IN interval[a,b])
7552         ==> ?g. g continuous_on u /\
7553                 (!x. x IN s ==> g x = f x) /\
7554                 (!x. x IN u ==> g(x) IN interval[a,b])`,
7555   REPEAT STRIP_TAC THEN MATCH_MP_TAC TIETZE_CLOSED_INTERVAL THEN
7556   ASM_REWRITE_TAC[INTERVAL_NE_EMPTY_1]);;
7557
7558 let TIETZE_OPEN_INTERVAL = prove
7559  (`!f:real^M->real^N u s a b.
7560         ~(interval(a,b) = {}) /\
7561         closed_in (subtopology euclidean u) s /\
7562         f continuous_on s /\
7563         (!x. x IN s ==> f x IN interval(a,b))
7564         ==> ?g. g continuous_on u /\
7565                 (!x. x IN s ==> g x = f x) /\
7566                 (!x. x IN u ==> g(x) IN interval(a,b))`,
7567   REPEAT STRIP_TAC THEN
7568   MP_TAC(ISPECL [`f:real^M->real^N`; `interval(a:real^N,b)`; `u:real^M->bool`;
7569                  `s:real^M->bool`] DUGUNDJI) THEN
7570   ASM_REWRITE_TAC[CONVEX_INTERVAL; SUBSET; FORALL_IN_IMAGE] THEN
7571   MESON_TAC[]);;
7572
7573 let TIETZE_OPEN_INTERVAL_1 = prove
7574  (`!f:real^N->real^1 u s a b.
7575         drop a < drop b /\
7576         closed_in (subtopology euclidean u) s /\
7577         f continuous_on s /\
7578         (!x. x IN s ==> f x IN interval(a,b))
7579         ==> ?g. g continuous_on u /\
7580                 (!x. x IN s ==> g x = f x) /\
7581                 (!x. x IN u ==> g(x) IN interval(a,b))`,
7582   REPEAT STRIP_TAC THEN MATCH_MP_TAC TIETZE_OPEN_INTERVAL THEN
7583   ASM_REWRITE_TAC[INTERVAL_NE_EMPTY_1]);;
7584
7585 let TIETZE_UNBOUNDED = prove
7586  (`!f:real^M->real^N u s.
7587         closed_in (subtopology euclidean u) s /\ f continuous_on s
7588         ==> ?g. g continuous_on u /\
7589                 (!x. x IN s ==> g x = f x)`,
7590   REPEAT STRIP_TAC THEN
7591   MP_TAC(ISPECL [`f:real^M->real^N`; `(:real^N)`; `u:real^M->bool`;
7592                  `s:real^M->bool`] DUGUNDJI) THEN
7593   ASM_REWRITE_TAC[CONVEX_UNIV; UNIV_NOT_EMPTY; SUBSET_UNIV]);;
7594
7595 (* ------------------------------------------------------------------------- *)
7596 (* Convex cones and corresponding hulls.                                     *)
7597 (* ------------------------------------------------------------------------- *)
7598
7599 let convex_cone = new_definition
7600  `convex_cone s <=> ~(s = {}) /\ convex s /\ conic s`;;
7601
7602 let CONVEX_CONE = prove
7603  (`!s:real^N->bool.
7604      convex_cone s <=>
7605         vec 0 IN s /\
7606         (!x y. x IN s /\ y IN s ==> (x + y) IN s) /\
7607         (!x c. x IN s /\ &0 <= c ==> (c % x) IN s)`,
7608   GEN_TAC THEN REWRITE_TAC[convex_cone; GSYM conic] THEN
7609   ASM_CASES_TAC `conic(s:real^N->bool)` THEN
7610   ASM_SIMP_TAC[CONIC_CONTAINS_0] THEN AP_TERM_TAC THEN
7611   RULE_ASSUM_TAC(REWRITE_RULE[conic]) THEN
7612   REWRITE_TAC[convex] THEN EQ_TAC THEN
7613   ASM_SIMP_TAC[REAL_SUB_LE] THEN DISCH_TAC THEN
7614   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
7615   FIRST_X_ASSUM(MP_TAC o SPECL
7616    [`&2 % (x:real^N)`; `&2 % (y:real^N)`; `&1 / &2`; `&1 / &2`]) THEN
7617   REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
7618   ASM_SIMP_TAC[VECTOR_MUL_LID; REAL_POS]);;
7619
7620 let CONVEX_CONE_ADD = prove
7621  (`!s x y. convex_cone s /\ x IN s /\ y IN s ==> (x + y) IN s`,
7622   MESON_TAC[CONVEX_CONE]);;
7623
7624 let CONVEX_CONE_MUL = prove
7625  (`!s c x. convex_cone s /\ &0 <= c /\ x IN s ==> (c % x) IN s`,
7626   MESON_TAC[CONVEX_CONE]);;
7627
7628 let CONVEX_CONE_NONEMPTY = prove
7629  (`!s. convex_cone s ==> ~(s = {})`,
7630   MESON_TAC[CONVEX_CONE; MEMBER_NOT_EMPTY]);;
7631
7632 let CONVEX_CONE_LINEAR_IMAGE = prove
7633  (`!f:real^M->real^N s.
7634         convex_cone s /\ linear f ==> convex_cone(IMAGE f s)`,
7635   SIMP_TAC[convex_cone; CONVEX_LINEAR_IMAGE; IMAGE_EQ_EMPTY;
7636            CONIC_LINEAR_IMAGE]);;
7637
7638 let CONVEX_CONE_LINEAR_IMAGE_EQ = prove
7639  (`!f:real^M->real^N s.
7640         linear f /\ (!x y. f x = f y ==> x = y)
7641         ==> (convex_cone(IMAGE f s) <=> convex_cone s)`,
7642   REWRITE_TAC[convex_cone] THEN
7643   MESON_TAC[IMAGE_EQ_EMPTY; CONVEX_LINEAR_IMAGE_EQ; CONIC_LINEAR_IMAGE_EQ]);;
7644
7645 add_linear_invariants [CONVEX_CONE_LINEAR_IMAGE_EQ];;
7646
7647 let CONVEX_CONE_HALFSPACE_GE = prove
7648  (`!a. convex_cone {x | a dot x >= &0}`,
7649   SIMP_TAC[CONVEX_CONE; real_ge; IN_ELIM_THM; DOT_RZERO; DOT_RADD; DOT_RMUL;
7650            REAL_LE_ADD; REAL_LE_MUL; REAL_LE_REFL]);;
7651
7652 let CONVEX_CONE_HALFSPACE_LE = prove
7653  (`!a. convex_cone {x | a dot x <= &0}`,
7654   REWRITE_TAC[REAL_ARITH `x <= &0 <=> &0 <= --x`; GSYM DOT_LNEG] THEN
7655   REWRITE_TAC[GSYM real_ge; CONVEX_CONE_HALFSPACE_GE]);;
7656
7657 let CONVEX_CONE_CONTAINS_0 = prove
7658  (`!s:real^N->bool. convex_cone s ==> vec 0 IN s`,
7659   SIMP_TAC[CONVEX_CONE]);;
7660
7661 let CONVEX_CONE_INTERS = prove
7662  (`!f. (!s:real^N->bool. s IN f ==> convex_cone s) ==> convex_cone(INTERS f)`,
7663   SIMP_TAC[convex_cone; CONIC_INTERS; CONVEX_INTERS] THEN
7664   REWRITE_TAC[GSYM convex_cone] THEN GEN_TAC THEN DISCH_TAC THEN
7665   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `vec 0:real^N` THEN
7666   ASM_SIMP_TAC[IN_INTERS; CONVEX_CONE_CONTAINS_0]);;
7667
7668 let CONVEX_CONE_CONVEX_CONE_HULL = prove
7669  (`!s. convex_cone(convex_cone hull s)`,
7670   SIMP_TAC[P_HULL; CONVEX_CONE_INTERS]);;
7671
7672 let CONVEX_CONVEX_CONE_HULL = prove
7673  (`!s. convex(convex_cone hull s)`,
7674   MESON_TAC[CONVEX_CONE_CONVEX_CONE_HULL; convex_cone]);;
7675
7676 let CONIC_CONVEX_CONE_HULL = prove
7677  (`!s. conic(convex_cone hull s)`,
7678   MESON_TAC[CONVEX_CONE_CONVEX_CONE_HULL; convex_cone]);;
7679
7680 let CONVEX_CONE_HULL_NONEMPTY = prove
7681  (`!s. ~(convex_cone hull s = {})`,
7682   MESON_TAC[CONVEX_CONE_CONVEX_CONE_HULL; convex_cone]);;
7683
7684 let CONVEX_CONE_HULL_CONTAINS_0 = prove
7685  (`!s. vec 0 IN convex_cone hull s`,
7686   MESON_TAC[CONVEX_CONE_CONVEX_CONE_HULL; CONVEX_CONE]);;
7687
7688 let CONVEX_CONE_HULL_ADD = prove
7689  (`!s x y:real^N.
7690         x IN convex_cone hull s /\ y IN convex_cone hull s
7691         ==> x + y IN convex_cone hull s`,
7692   MESON_TAC[CONVEX_CONE; CONVEX_CONE_CONVEX_CONE_HULL]);;
7693
7694 let CONVEX_CONE_HULL_MUL = prove
7695  (`!s c x:real^N.
7696         &0 <= c /\ x IN convex_cone hull s
7697         ==> (c % x) IN convex_cone hull s`,
7698   MESON_TAC[CONVEX_CONE; CONVEX_CONE_CONVEX_CONE_HULL]);;
7699
7700 let CONVEX_CONE_SUMS = prove
7701  (`!s t. convex_cone s /\ convex_cone t
7702          ==> convex_cone {x + y:real^N | x IN s /\ y IN t}`,
7703   SIMP_TAC[convex_cone; CONIC_SUMS; CONVEX_SUMS] THEN SET_TAC[]);;
7704
7705 let CONVEX_CONE_PCROSS = prove
7706  (`!s:real^M->bool t:real^N->bool.
7707         convex_cone s /\ convex_cone t ==> convex_cone(s PCROSS t)`,
7708   SIMP_TAC[convex_cone; CONVEX_PCROSS; CONIC_PCROSS; PCROSS_EQ_EMPTY]);;
7709
7710 let CONVEX_CONE_PCROSS_EQ = prove
7711  (`!s:real^M->bool t:real^N->bool.
7712         convex_cone(s PCROSS t) <=> convex_cone s /\ convex_cone t`,
7713   REPEAT GEN_TAC THEN
7714   ASM_CASES_TAC `s:real^M->bool = {}` THENL
7715    [ASM_REWRITE_TAC[PCROSS_EMPTY; convex_cone]; ALL_TAC] THEN
7716   ASM_CASES_TAC `t:real^N->bool = {}` THENL
7717    [ASM_REWRITE_TAC[PCROSS_EMPTY; convex_cone]; ALL_TAC] THEN
7718   EQ_TAC THEN REWRITE_TAC[CONVEX_CONE_PCROSS] THEN REPEAT STRIP_TAC THENL
7719    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
7720      `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONVEX_CONE_LINEAR_IMAGE) THEN
7721     ASM_REWRITE_TAC[LINEAR_FSTCART];
7722     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
7723      `(s:real^M->bool) PCROSS (t:real^N->bool)`] CONVEX_CONE_LINEAR_IMAGE) THEN
7724     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
7725   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
7726   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
7727               FSTCART_PASTECART; SNDCART_PASTECART] THEN
7728   ASM SET_TAC[]);;
7729
7730 let CONVEX_CONE_HULL_UNION = prove
7731  (`!s t. convex_cone hull(s UNION t) =
7732          {x + y:real^N | x IN convex_cone hull s /\ y IN convex_cone hull t}`,
7733   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
7734    [MATCH_MP_TAC HULL_MINIMAL THEN
7735     SIMP_TAC[CONVEX_CONE_SUMS; CONVEX_CONE_CONVEX_CONE_HULL] THEN
7736     REWRITE_TAC[SUBSET; IN_UNION; IN_ELIM_THM] THEN
7737     X_GEN_TAC `x:real^N` THEN STRIP_TAC THENL
7738      [MAP_EVERY EXISTS_TAC [`x:real^N`; `vec 0:real^N`] THEN
7739       ASM_SIMP_TAC[HULL_INC; CONVEX_CONE_HULL_CONTAINS_0; VECTOR_ADD_RID];
7740       MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `x:real^N`] THEN
7741       ASM_SIMP_TAC[HULL_INC; CONVEX_CONE_HULL_CONTAINS_0; VECTOR_ADD_LID]];
7742     REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
7743     REPEAT STRIP_TAC THEN MATCH_MP_TAC CONVEX_CONE_HULL_ADD THEN
7744     ASM_MESON_TAC[HULL_MONO; SUBSET_UNION; SUBSET]]);;
7745
7746 let CONVEX_CONE_SING = prove
7747  (`convex_cone {vec 0}`,
7748   SIMP_TAC[CONVEX_CONE; IN_SING; VECTOR_ADD_LID; VECTOR_MUL_RZERO]);;
7749
7750 let CONVEX_HULL_SUBSET_CONVEX_CONE_HULL = prove
7751  (`!s. convex hull s SUBSET convex_cone hull s`,
7752   GEN_TAC THEN MATCH_MP_TAC HULL_ANTIMONO THEN
7753   SIMP_TAC[convex_cone; SUBSET; IN]);;
7754
7755 let CONIC_HULL_SUBSET_CONVEX_CONE_HULL = prove
7756  (`!s. conic hull s SUBSET convex_cone hull s`,
7757   GEN_TAC THEN MATCH_MP_TAC HULL_ANTIMONO THEN
7758   SIMP_TAC[convex_cone; SUBSET; IN]);;
7759
7760 let CONVEX_CONE_HULL_SEPARATE_NONEMPTY = prove
7761  (`!s:real^N->bool.
7762     ~(s = {})
7763     ==> convex_cone hull s = conic hull (convex hull s)`,
7764   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THEN
7765   MATCH_MP_TAC HULL_MINIMAL THEN
7766   REWRITE_TAC[CONIC_CONVEX_CONE_HULL; CONVEX_HULL_SUBSET_CONVEX_CONE_HULL] THEN
7767   ASM_SIMP_TAC[CONVEX_CONIC_HULL; CONVEX_CONVEX_HULL; CONIC_CONIC_HULL;
7768                convex_cone; CONIC_HULL_EQ_EMPTY; CONVEX_HULL_EQ_EMPTY] THEN
7769   ASM_MESON_TAC[HULL_SUBSET; SUBSET_REFL; SUBSET_TRANS]);;
7770
7771 let CONVEX_CONE_HULL_EMPTY = prove
7772  (`convex_cone hull {} = {vec 0}`,
7773   MATCH_MP_TAC HULL_UNIQUE THEN
7774   REWRITE_TAC[CONVEX_CONE_CONTAINS_0; EMPTY_SUBSET; CONVEX_CONE_SING;
7775               SET_RULE `{a} SUBSET s <=> a IN s`; CONVEX_CONE_CONTAINS_0]);;
7776
7777 let CONVEX_CONE_HULL_SEPARATE = prove
7778  (`!s:real^N->bool.
7779     convex_cone hull s = vec 0 INSERT conic hull (convex hull s)`,
7780   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
7781   ASM_SIMP_TAC[CONVEX_CONE_HULL_EMPTY; CONVEX_HULL_EMPTY; CONIC_HULL_EMPTY] THEN
7782   ASM_SIMP_TAC[CONVEX_CONE_HULL_SEPARATE_NONEMPTY] THEN
7783   MATCH_MP_TAC(SET_RULE `a IN s ==> s = a INSERT s`) THEN
7784   ASM_SIMP_TAC[CONIC_CONTAINS_0; CONIC_CONIC_HULL] THEN
7785   ASM_REWRITE_TAC[CONIC_HULL_EQ_EMPTY; CONVEX_HULL_EQ_EMPTY]);;
7786
7787 let CONVEX_CONE_HULL_CONVEX_HULL_NONEMPTY = prove
7788  (`!s:real^N->bool.
7789         ~(s = {})
7790         ==> convex_cone hull s = {c % x | &0 <= c /\ x IN convex hull s}`,
7791   SIMP_TAC[CONVEX_CONE_HULL_SEPARATE_NONEMPTY; CONIC_HULL_EXPLICIT]);;
7792
7793 let CONVEX_CONE_HULL_CONVEX_HULL = prove
7794  (`!s:real^N->bool.
7795         convex_cone hull s =
7796         vec 0 INSERT {c % x | &0 <= c /\ x IN convex hull s}`,
7797   REWRITE_TAC[CONVEX_CONE_HULL_SEPARATE; CONIC_HULL_EXPLICIT]);;
7798
7799 let CONVEX_CONE_HULL_LINEAR_IMAGE = prove
7800  (`!f:real^M->real^N s.
7801         linear f
7802         ==> convex_cone hull (IMAGE f s) = IMAGE f (convex_cone hull s)`,
7803   REPEAT STRIP_TAC THEN
7804   ASM_CASES_TAC `s:real^M-> bool = {}` THEN
7805   ASM_SIMP_TAC[CONVEX_CONE_HULL_SEPARATE_NONEMPTY; IMAGE_EQ_EMPTY;
7806                CONVEX_HULL_LINEAR_IMAGE; CONIC_HULL_LINEAR_IMAGE] THEN
7807   REWRITE_TAC[IMAGE_CLAUSES; CONVEX_CONE_HULL_EMPTY] THEN
7808   MATCH_MP_TAC(SET_RULE `f x = y ==> {y} = {f x}`) THEN
7809   ASM_MESON_TAC[LINEAR_0]);;
7810
7811 add_linear_invariants [CONVEX_CONE_HULL_LINEAR_IMAGE];;
7812
7813 let SUBSPACE_IMP_CONVEX_CONE = prove
7814  (`!s. subspace s ==> convex_cone s`,
7815   SIMP_TAC[subspace; CONVEX_CONE]);;
7816
7817 let CONVEX_CONE_SPAN = prove
7818  (`!s. convex_cone(span s)`,
7819   SIMP_TAC[convex_cone; CONVEX_SPAN; CONIC_SPAN; GSYM MEMBER_NOT_EMPTY] THEN
7820   MESON_TAC[SPAN_0]);;
7821
7822 let CONVEX_CONE_NEGATIONS = prove
7823  (`!s. convex_cone s ==> convex_cone (IMAGE (--) s)`,
7824   SIMP_TAC[convex_cone; IMAGE_EQ_EMPTY; CONIC_NEGATIONS; CONVEX_NEGATIONS]);;
7825
7826 let SUBSPACE_CONVEX_CONE_SYMMETRIC = prove
7827  (`!s:real^N->bool.
7828         subspace s <=> convex_cone s /\ (!x. x IN s ==> --x IN s)`,
7829   GEN_TAC THEN REWRITE_TAC[subspace; CONVEX_CONE] THEN
7830   EQ_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[] THENL
7831    [ASM_MESON_TAC[VECTOR_ARITH `--x:real^N = -- &1 % x`];
7832     MAP_EVERY X_GEN_TAC [`c:real`; `x:real^N`] THEN DISCH_TAC THEN
7833     DISJ_CASES_TAC(SPEC `c:real` REAL_LE_NEGTOTAL) THEN ASM_SIMP_TAC[] THEN
7834     ASM_MESON_TAC[VECTOR_ARITH `c % x:real^N = --(--c % x)`]]);;
7835
7836 let SPAN_CONVEX_CONE_ALLSIGNS = prove
7837  (`!s:real^N->bool. span s = convex_cone hull (s UNION IMAGE (--) s)`,
7838   GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
7839    [MATCH_MP_TAC SPAN_SUBSET_SUBSPACE THEN CONJ_TAC THENL
7840      [MESON_TAC[HULL_SUBSET; SUBSET_UNION; SUBSET_TRANS]; ALL_TAC] THEN
7841     REWRITE_TAC[SUBSPACE_CONVEX_CONE_SYMMETRIC;
7842                 CONVEX_CONE_CONVEX_CONE_HULL] THEN
7843     MATCH_MP_TAC HULL_INDUCT THEN CONJ_TAC THENL
7844      [X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_UNION; IN_IMAGE] THEN
7845       DISCH_TAC THEN MATCH_MP_TAC HULL_INC THEN
7846       REWRITE_TAC[IN_UNION; IN_IMAGE] THEN ASM_MESON_TAC[VECTOR_NEG_NEG];
7847       SUBGOAL_THEN `!s. {x:real^N | (--x) IN s} = IMAGE (--) s`
7848        (fun th -> SIMP_TAC[th; CONVEX_CONE_NEGATIONS;
7849                            CONVEX_CONE_CONVEX_CONE_HULL]) THEN
7850       GEN_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
7851       REWRITE_TAC[IN_ELIM_THM] THEN MESON_TAC[VECTOR_NEG_NEG]];
7852     MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_CONE_SPAN] THEN
7853     REWRITE_TAC[UNION_SUBSET; SPAN_INC] THEN
7854     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
7855     MESON_TAC[SPAN_SUPERSET; SPAN_NEG]]);;
7856
7857 (* ------------------------------------------------------------------------- *)
7858 (* Epigraphs of convex functions.                                            *)
7859 (* ------------------------------------------------------------------------- *)
7860
7861 let epigraph = new_definition
7862   `epigraph s (f:real^N->real) =
7863        {xy:real^((N,1)finite_sum) |
7864              fstcart xy IN s /\ f(fstcart xy) <= drop(sndcart xy)}`;;
7865
7866 let IN_EPIGRAPH = prove
7867  (`!x y. (pastecart x (lift y)) IN epigraph s f <=> x IN s /\ f(x) <= y`,
7868   REWRITE_TAC[epigraph; IN_ELIM_THM; FSTCART_PASTECART; SNDCART_PASTECART;
7869               LIFT_DROP]);;
7870
7871 let CONVEX_EPIGRAPH = prove
7872  (`!f s. f convex_on s /\ convex s <=> convex(epigraph s f)`,
7873   REWRITE_TAC[convex; convex_on; IN_ELIM_THM; SNDCART_ADD; SNDCART_CMUL;
7874    epigraph; FSTCART_ADD; FSTCART_CMUL; FORALL_PASTECART; FSTCART_PASTECART;
7875    SNDCART_PASTECART] THEN
7876   REWRITE_TAC[GSYM FORALL_DROP; DROP_ADD; DROP_CMUL] THEN
7877   MESON_TAC[REAL_LE_REFL; REAL_LE_ADD2; REAL_LE_LMUL; REAL_LE_TRANS]);;
7878
7879 let CONVEX_EPIGRAPH_CONVEX = prove
7880  (`!f s. convex s ==> (f convex_on s <=> convex(epigraph s f))`,
7881   REWRITE_TAC[GSYM CONVEX_EPIGRAPH] THEN CONV_TAC TAUT);;
7882
7883 let CONVEX_ON_EPIGRAPH_SLICE_LE = prove
7884  (`!f:real^N->real s a.
7885         f convex_on s /\ convex s ==> convex {x | x IN s /\ f(x) <= a}`,
7886   SIMP_TAC[convex_on; convex; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
7887   FIRST_X_ASSUM(fun th ->
7888     W(MP_TAC o PART_MATCH (lhand o rand) th o lhand o snd)) THEN
7889   ASM_REWRITE_TAC[] THEN
7890   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
7891   MATCH_MP_TAC REAL_CONVEX_BOUND_LE THEN ASM_REWRITE_TAC[]);;
7892
7893 let CONVEX_ON_EPIGRAPH_SLICE_LT = prove
7894  (`!f:real^N->real s a.
7895         f convex_on s /\ convex s ==> convex {x | x IN s /\ f(x) < a}`,
7896   SIMP_TAC[convex_on; convex; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
7897   FIRST_X_ASSUM(fun th ->
7898     W(MP_TAC o PART_MATCH (lhand o rand) th o lhand o snd)) THEN
7899   ASM_REWRITE_TAC[] THEN
7900   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LET_TRANS) THEN
7901   MATCH_MP_TAC REAL_CONVEX_BOUND_LT THEN ASM_REWRITE_TAC[]);;
7902
7903 (* ------------------------------------------------------------------------- *)
7904 (* Use this to derive general bound property of convex function.             *)
7905 (* ------------------------------------------------------------------------- *)
7906
7907 let FORALL_OF_PASTECART = prove
7908  (`(!p. P (fstcart o p) (sndcart o p)) <=> (!x:A->B^M y:A->B^N. P x y)`,
7909   EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN REPEAT STRIP_TAC THEN
7910   FIRST_ASSUM(MP_TAC o SPEC `\a:A. pastecart (x a :B^M) (y a :B^N)`) THEN
7911   REWRITE_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART; ETA_AX]);;
7912
7913 let FORALL_OF_DROP = prove
7914  (`(!v. P (drop o v)) <=> (!x:A->real. P x)`,
7915   EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN REPEAT STRIP_TAC THEN
7916   FIRST_ASSUM(MP_TAC o SPEC `\a:A. lift(x a)`) THEN
7917   REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX]);;
7918
7919 let CONVEX_ON_JENSEN = prove
7920  (`!f:real^N->real s.
7921         convex s
7922         ==> (f convex_on s <=>
7923                 !k u x.
7924                    (!i:num. 1 <= i /\ i <= k ==> &0 <= u(i) /\ x(i) IN s) /\
7925                    (sum (1..k) u = &1)
7926                    ==> f(vsum (1..k) (\i. u(i) % x(i)))
7927                            <= sum (1..k) (\i. u(i) * f(x(i))))`,
7928   let lemma = prove
7929    (`(!x. P x ==> (Q x = R x)) ==> (!x. P x) ==> ((!x. Q x) <=> (!x. R x))`,
7930     MESON_TAC[]) in
7931   REPEAT STRIP_TAC THEN FIRST_ASSUM
7932    (fun th -> REWRITE_TAC[MATCH_MP CONVEX_EPIGRAPH_CONVEX th]) THEN
7933   REWRITE_TAC[CONVEX_INDEXED; epigraph] THEN
7934   SIMP_TAC[IN_ELIM_THM; SNDCART_ADD; SNDCART_CMUL; FINITE_NUMSEG;
7935            FSTCART_ADD; FSTCART_CMUL; FORALL_PASTECART; DROP_CMUL;
7936            FSTCART_PASTECART; SNDCART_PASTECART;
7937            FSTCART_VSUM; SNDCART_VSUM; DROP_VSUM; o_DEF] THEN
7938   REWRITE_TAC[GSYM(ISPEC `fstcart` o_THM); GSYM(ISPEC `sndcart` o_THM)] THEN
7939   REWRITE_TAC[GSYM(ISPEC `drop` o_THM)] THEN
7940   REWRITE_TAC[FORALL_OF_PASTECART; FORALL_OF_DROP] THEN
7941   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONVEX_INDEXED]) THEN
7942   REPEAT(MATCH_MP_TAC lemma THEN GEN_TAC) THEN SIMP_TAC[] THEN
7943   REWRITE_TAC[TAUT `a ==> b /\ c <=> (a ==> b) /\ (a ==> c)`] THEN
7944   REWRITE_TAC[FORALL_AND_THM] THEN DISCH_THEN(K ALL_TAC) THEN
7945   EQ_TAC THEN SIMP_TAC[REAL_LE_REFL] THEN
7946   DISCH_THEN(fun th -> REPEAT STRIP_TAC THEN MP_TAC th) THEN
7947   ASM_REWRITE_TAC[] THEN
7948   MATCH_MP_TAC(REAL_ARITH `a <= b ==> x <= a ==> x <= b`) THEN
7949   ASM_SIMP_TAC[SUM_LE_NUMSEG; REAL_LE_LMUL]);;
7950
7951 let CONVEX_ON_IMP_JENSEN = prove
7952  (`!f:real^N->real s k:A->bool u x.
7953         f convex_on s /\ convex s /\ FINITE k /\
7954         (!i. i IN k ==> &0 <= u i /\ x i IN s) /\ sum k u = &1
7955         ==> f(vsum k (\i. u i % x i)) <= sum k (\i. u i * f(x i))`,
7956   REPEAT GEN_TAC THEN
7957   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
7958   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [FINITE_INDEX_NUMSEG]) THEN
7959   ABBREV_TAC `n = CARD(k:A->bool)` THEN
7960   REWRITE_TAC[INJECTIVE_ON_ALT] THEN
7961   DISCH_THEN(X_CHOOSE_THEN `g:num->A`
7962    (CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC)) THEN
7963   ASM_SIMP_TAC[VSUM_IMAGE; SUM_IMAGE; FINITE_NUMSEG; IMP_CONJ; o_DEF] THEN
7964   DISCH_TAC THEN MP_TAC(ISPECL [`f:real^N->real`; `s:real^N->bool`]
7965         CONVEX_ON_JENSEN) THEN
7966   ASM_REWRITE_TAC[] THEN DISCH_THEN MATCH_MP_TAC THEN
7967   ASM_REWRITE_TAC[GSYM IN_NUMSEG] THEN ASM SET_TAC[]);;
7968
7969 (* ------------------------------------------------------------------------- *)
7970 (* Another intermediate value theorem formulation.                           *)
7971 (* ------------------------------------------------------------------------- *)
7972
7973 let IVT_INCREASING_COMPONENT_ON_1 = prove
7974  (`!f:real^1->real^N a b y k.
7975         drop a <= drop b /\ 1 <= k /\ k <= dimindex(:N) /\
7976         f continuous_on interval[a,b] /\
7977         f(a)$k <= y /\ y <= f(b)$k
7978         ==> ?x. x IN interval[a,b] /\ f(x)$k = y`,
7979   REPEAT STRIP_TAC THEN
7980   MP_TAC(ISPECL [`IMAGE (f:real^1->real^N) (interval[a,b])`]
7981         CONNECTED_IVT_COMPONENT) THEN
7982   REWRITE_TAC[EXISTS_IN_IMAGE] THEN DISCH_THEN MATCH_MP_TAC THEN
7983   REWRITE_TAC[RIGHT_EXISTS_AND_THM; EXISTS_IN_IMAGE] THEN
7984   ASM_SIMP_TAC[CONNECTED_CONTINUOUS_IMAGE; CONVEX_CONNECTED;
7985                CONVEX_INTERVAL] THEN
7986   EXISTS_TAC `a:real^1` THEN ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL] THEN
7987   EXISTS_TAC `b:real^1` THEN ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL]);;
7988
7989 let IVT_INCREASING_COMPONENT_1 = prove
7990  (`!f:real^1->real^N a b y k.
7991         drop a <= drop b /\ 1 <= k /\ k <= dimindex(:N) /\
7992         (!x. x IN interval[a,b] ==> f continuous at x) /\
7993         f(a)$k <= y /\ y <= f(b)$k
7994         ==> ?x. x IN interval[a,b] /\ f(x)$k = y`,
7995   REPEAT STRIP_TAC THEN MATCH_MP_TAC IVT_INCREASING_COMPONENT_ON_1 THEN
7996   ASM_SIMP_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
7997
7998 let IVT_DECREASING_COMPONENT_ON_1 = prove
7999  (`!f:real^1->real^N a b y k.
8000         drop a <= drop b /\ 1 <= k /\ k <= dimindex(:N) /\
8001         f continuous_on interval[a,b] /\
8002         f(b)$k <= y /\ y <= f(a)$k
8003         ==> ?x. x IN interval[a,b] /\ f(x)$k = y`,
8004   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_EQ_NEG2] THEN
8005   ASM_SIMP_TAC[GSYM VECTOR_NEG_COMPONENT] THEN
8006   MATCH_MP_TAC IVT_INCREASING_COMPONENT_ON_1 THEN
8007   ASM_SIMP_TAC[VECTOR_NEG_COMPONENT; CONTINUOUS_ON_NEG; REAL_LE_NEG2]);;
8008
8009 let IVT_DECREASING_COMPONENT_1 = prove
8010  (`!f:real^1->real^N a b y k.
8011         drop a <= drop b /\ 1 <= k /\ k <= dimindex(:N) /\
8012         (!x. x IN interval[a,b] ==> f continuous at x) /\
8013         f(b)$k <= y /\ y <= f(a)$k
8014         ==> ?x. x IN interval[a,b] /\ f(x)$k = y`,
8015   REPEAT STRIP_TAC THEN MATCH_MP_TAC IVT_DECREASING_COMPONENT_ON_1 THEN
8016   ASM_SIMP_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
8017
8018 (* ------------------------------------------------------------------------- *)
8019 (* A bound within a convex hull, and so an interval.                         *)
8020 (* ------------------------------------------------------------------------- *)
8021
8022 let CONVEX_ON_CONVEX_HULL_BOUND = prove
8023  (`!f s b. f convex_on (convex hull s) /\
8024            (!x:real^N. x IN s ==> f(x) <= b)
8025            ==> !x. x IN convex hull s ==> f(x) <= b`,
8026   REPEAT GEN_TAC THEN SIMP_TAC[CONVEX_ON_JENSEN; CONVEX_CONVEX_HULL] THEN
8027   STRIP_TAC THEN GEN_TAC THEN REWRITE_TAC[CONVEX_HULL_INDEXED] THEN
8028   REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
8029   MAP_EVERY X_GEN_TAC [`k:num`; `u:num->real`; `v:num->real^N`] THEN
8030   DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN ASM_REWRITE_TAC[] THEN
8031   MATCH_MP_TAC REAL_LE_TRANS THEN
8032   EXISTS_TAC `sum(1..k) (\i. u i * f(v i :real^N))` THEN CONJ_TAC THENL
8033    [FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_MESON_TAC[SUBSET; HULL_SUBSET];
8034     ALL_TAC] THEN
8035   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `sum(1..k) (\i. u i * b)` THEN
8036   CONJ_TAC THENL
8037    [MATCH_MP_TAC SUM_LE_NUMSEG THEN ASM_SIMP_TAC[REAL_LE_LMUL];
8038     ALL_TAC] THEN
8039   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[SUM_LMUL] THEN
8040   ASM_MESON_TAC[REAL_LE_REFL; REAL_MUL_RID]);;
8041
8042 let UNIT_INTERVAL_CONVEX_HULL = prove
8043  (`interval [vec 0,vec 1:real^N] =
8044      convex hull
8045        {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
8046                            ==> ((x$i = &0) \/ (x$i = &1))}`,
8047   let lemma = prove
8048    (`FINITE {i | 1 <= i /\ i <= n /\ P(i)} /\
8049      CARD {i | 1 <= i /\ i <= n /\ P(i)} <= n`,
8050     CONJ_TAC THENL
8051      [MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `1..n`;
8052       GEN_REWRITE_TAC RAND_CONV [ARITH_RULE `x = (x + 1) - 1`] THEN
8053       REWRITE_TAC[GSYM CARD_NUMSEG] THEN MATCH_MP_TAC CARD_SUBSET] THEN
8054     SIMP_TAC[FINITE_NUMSEG; IN_NUMSEG; SUBSET; IN_ELIM_THM]) in
8055   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
8056    [ALL_TAC;
8057     MATCH_MP_TAC HULL_MINIMAL THEN
8058     REWRITE_TAC[CONVEX_INTERVAL; SUBSET; IN_INTERVAL; IN_ELIM_THM] THEN
8059     SIMP_TAC[VEC_COMPONENT] THEN MESON_TAC[REAL_LE_REFL; REAL_POS]] THEN
8060   SUBGOAL_THEN
8061    `!n x:real^N.
8062         x IN interval[vec 0,vec 1] /\
8063         n <= dimindex(:N) /\
8064         CARD {i | 1 <= i /\ i <= dimindex(:N) /\ ~(x$i = &0)} <= n
8065         ==> x IN convex hull
8066                   {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
8067                                   ==> ((x$i = &0) \/ (x$i = &1))}`
8068   MP_TAC THENL
8069    [ALL_TAC;
8070     REWRITE_TAC[SUBSET] THEN REPEAT STRIP_TAC THEN
8071     FIRST_X_ASSUM MATCH_MP_TAC THEN EXISTS_TAC `dimindex(:N)` THEN
8072     ASM_REWRITE_TAC[LE_REFL; lemma]] THEN
8073   INDUCT_TAC THEN X_GEN_TAC `x:real^N` THENL
8074    [SIMP_TAC[LE; lemma; CARD_EQ_0] THEN
8075     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
8076      [EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY; BETA_THM] THEN
8077     REWRITE_TAC[TAUT `~(a /\ b /\ c) <=> a /\ b ==> ~c`] THEN STRIP_TAC THEN
8078     SUBGOAL_THEN `x = vec 0:real^N` SUBST1_TAC THENL
8079      [ASM_SIMP_TAC[CART_EQ; VEC_COMPONENT]; ALL_TAC] THEN
8080     MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
8081     SIMP_TAC[IN_ELIM_THM; VEC_COMPONENT];
8082     ALL_TAC] THEN
8083   ASM_CASES_TAC
8084    `{i | 1 <= i /\ i <= dimindex(:N) /\ ~((x:real^N)$i = &0)} = {}`
8085   THENL
8086    [DISCH_THEN(K ALL_TAC) THEN
8087     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
8088     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
8089      [EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY; BETA_THM] THEN
8090     REWRITE_TAC[TAUT `~(a /\ b /\ c) <=> a /\ b ==> ~c`] THEN STRIP_TAC THEN
8091     SUBGOAL_THEN `x = vec 0:real^N` SUBST1_TAC THENL
8092      [ASM_SIMP_TAC[CART_EQ; VEC_COMPONENT]; ALL_TAC] THEN
8093     MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
8094     SIMP_TAC[IN_ELIM_THM; VEC_COMPONENT];
8095     ALL_TAC] THEN
8096   MP_TAC(ISPEC
8097    `IMAGE (\i. x$i)
8098       {i | 1 <= i /\ i <= dimindex(:N) /\ ~((x:real^N)$i = &0)}`
8099    INF_FINITE) THEN
8100   ABBREV_TAC `xi = inf
8101    (IMAGE (\i. x$i)
8102      {i | 1 <= i /\ i <= dimindex(:N) /\ ~((x:real^N)$i = &0)})` THEN
8103   ASM_SIMP_TAC[FINITE_IMAGE; IMAGE_EQ_EMPTY; lemma] THEN
8104   REWRITE_TAC[FORALL_IN_IMAGE] THEN
8105   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [IN_IMAGE; IN_ELIM_THM] THEN
8106   REWRITE_TAC[] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
8107   FIRST_X_ASSUM(X_CHOOSE_THEN `i:num` STRIP_ASSUME_TAC) THEN
8108   FIRST_X_ASSUM SUBST_ALL_TAC THEN REPEAT STRIP_TAC THEN
8109   SUBGOAL_THEN `&0 <= (x:real^N)$i /\ x$i <= &1` STRIP_ASSUME_TAC THENL
8110    [UNDISCH_TAC `x:real^N IN interval [vec 0,vec 1]` THEN
8111     ASM_SIMP_TAC[IN_INTERVAL; VEC_COMPONENT];
8112     ALL_TAC] THEN
8113   FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
8114    `x <= &1 ==> (x = &1) \/ x < &1`))
8115   THENL
8116    [SUBGOAL_THEN
8117      `x = lambda i. if (x:real^N)$i = &0 then &0 else &1`
8118     SUBST1_TAC THENL
8119      [UNDISCH_TAC `x:real^N IN interval [vec 0,vec 1]` THEN
8120       ASM_SIMP_TAC[CART_EQ; IN_INTERVAL; VEC_COMPONENT; LAMBDA_BETA] THEN
8121       ASM_MESON_TAC[REAL_LE_ANTISYM];
8122       ALL_TAC] THEN
8123     MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
8124     SIMP_TAC[IN_ELIM_THM; LAMBDA_BETA] THEN MESON_TAC[];
8125     ALL_TAC] THEN
8126   SUBGOAL_THEN
8127    `x:real^N =
8128         x$i % (lambda j. if x$j = &0 then &0 else &1) +
8129         (&1 - x$i) %
8130         (lambda j. if x$j = &0 then &0 else (x$j - x$i) / (&1 - x$i))`
8131   SUBST1_TAC THENL
8132    [SIMP_TAC[CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
8133              LAMBDA_BETA; VEC_COMPONENT] THEN
8134     REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
8135     ASM_REWRITE_TAC[REAL_MUL_RZERO; REAL_ADD_LID] THEN
8136     ASM_SIMP_TAC[REAL_DIV_LMUL; ARITH_RULE `x < &1 ==> ~(&1 - x = &0)`] THEN
8137     REPEAT STRIP_TAC THEN REAL_ARITH_TAC;
8138     ALL_TAC] THEN
8139   MATCH_MP_TAC(REWRITE_RULE[convex] CONVEX_CONVEX_HULL) THEN
8140   ASM_SIMP_TAC[REAL_ARITH `x < &1 ==> &0 <= &1 - x`;
8141                REAL_ARITH `x + &1 - x = &1`] THEN
8142   CONJ_TAC THENL
8143    [MATCH_MP_TAC(REWRITE_RULE[SUBSET] HULL_SUBSET) THEN
8144     SIMP_TAC[LAMBDA_BETA; IN_ELIM_THM] THEN MESON_TAC[];
8145     ALL_TAC] THEN
8146   FIRST_X_ASSUM MATCH_MP_TAC THEN
8147   ASM_SIMP_TAC[ARITH_RULE `SUC k <= n ==> k <= n`] THEN CONJ_TAC THENL
8148    [SIMP_TAC[IN_INTERVAL; LAMBDA_BETA; VEC_COMPONENT] THEN
8149     GEN_TAC THEN STRIP_TAC THEN
8150     COND_CASES_TAC THEN REWRITE_TAC[REAL_LE_REFL; REAL_POS] THEN
8151     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ;
8152                  REAL_ARITH `x < &1 ==> &0 < &1 - x`] THEN
8153     ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_SUB_LE; REAL_MUL_LID] THEN
8154     ASM_SIMP_TAC[REAL_ARITH `a - b <= &1 - b <=> a <= &1`] THEN
8155     UNDISCH_TAC `x:real^N IN interval [vec 0,vec 1]` THEN
8156     ASM_SIMP_TAC[CART_EQ; IN_INTERVAL; VEC_COMPONENT; LAMBDA_BETA];
8157     ALL_TAC] THEN
8158   MATCH_MP_TAC LE_TRANS THEN
8159   EXISTS_TAC
8160    `CARD({i | 1 <= i /\ i <= dimindex(:N) /\ ~((x:real^N)$i = &0)}
8161          DELETE i)` THEN
8162   CONJ_TAC THENL
8163    [MATCH_MP_TAC CARD_SUBSET THEN REWRITE_TAC[lemma; FINITE_DELETE] THEN
8164     REWRITE_TAC[SUBSET; IN_DELETE; IN_ELIM_THM] THEN
8165     GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
8166     ASM_SIMP_TAC[LAMBDA_BETA] THEN
8167     COND_CASES_TAC THEN ASM_REWRITE_TAC[CONTRAPOS_THM] THEN
8168     SIMP_TAC[real_div; REAL_SUB_REFL; REAL_MUL_LZERO];
8169     SIMP_TAC[lemma; CARD_DELETE] THEN COND_CASES_TAC THEN
8170     ASM_SIMP_TAC[ARITH_RULE `x <= SUC n ==> x - 1 <= n`] THEN
8171     RULE_ASSUM_TAC(REWRITE_RULE[IN_ELIM_THM]) THEN
8172     ASM_MESON_TAC[]]);;
8173
8174 (* ------------------------------------------------------------------------- *)
8175 (* Some convexity-related properties of Hausdorff distance                   *)
8176 (* ------------------------------------------------------------------------- *)
8177
8178 let HAUSDIST_CONVEX_HULLS = prove
8179  (`!s t:real^N->bool.
8180         bounded s /\ bounded t
8181         ==> hausdist(convex hull s,convex hull t) <= hausdist(s,t)`,
8182   REPEAT STRIP_TAC THEN
8183   ASM_CASES_TAC `s:real^N->bool = {}` THENL
8184    [ASM_MESON_TAC[HAUSDIST_EMPTY; CONVEX_HULL_EMPTY; REAL_LE_REFL];
8185     ALL_TAC] THEN
8186   ASM_CASES_TAC `t:real^N->bool = {}` THENL
8187    [ASM_MESON_TAC[HAUSDIST_EMPTY; CONVEX_HULL_EMPTY; REAL_LE_REFL];
8188     ALL_TAC] THEN
8189   MATCH_MP_TAC REAL_HAUSDIST_LE THEN ASM_REWRITE_TAC[CONVEX_HULL_EQ_EMPTY] THEN
8190   CONJ_TAC THEN MATCH_MP_TAC CONVEX_ON_CONVEX_HULL_BOUND THEN
8191   CONJ_TAC THEN SIMP_TAC[CONVEX_ON_SETDIST; CONVEX_CONVEX_HULL] THEN
8192   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_HAUSDIST THEN
8193   ASM_REWRITE_TAC[LEFT_EXISTS_AND_THM; RIGHT_EXISTS_AND_THM; CONJ_ASSOC] THEN
8194   (CONJ_TAC THENL
8195     [CONJ_TAC; ASM_MESON_TAC[SETDIST_SUBSET_RIGHT; HULL_SUBSET]]) THEN
8196   MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`] BOUNDED_DIFFS) THEN
8197   ASM_REWRITE_TAC[bounded; FORALL_IN_GSPEC; GSYM dist] THEN
8198   MATCH_MP_TAC MONO_EXISTS THEN
8199   ASM_MESON_TAC[SETDIST_LE_DIST; dist; DIST_SYM; REAL_LE_TRANS;
8200                 MEMBER_NOT_EMPTY; IN_SING]);;
8201
8202 let HAUSDIST_SUMS = prove
8203  (`!s t:real^N->bool u.
8204         bounded s /\ bounded t /\ convex s /\ convex t /\ bounded u /\
8205         ~(s = {}) /\ ~(t = {}) /\ ~(u = {})
8206         ==> hausdist({x + e | x IN s /\ e IN u},
8207                      {y + e | y IN t /\ e IN u}) =
8208             hausdist(s,t)`,
8209   REPEAT GEN_TAC THEN
8210   ONCE_REWRITE_TAC[MESON[HAUSDIST_CLOSURE]
8211    `hausdist(s:real^N->bool,t) = hausdist(closure s,closure t)`] THEN
8212   SIMP_TAC[CLOSURE_SUMS] THEN
8213   SIMP_TAC[CLOSURE_CLOSED; CLOSED_CBALL; GSYM COMPACT_CLOSURE] THEN
8214   ONCE_REWRITE_TAC[GSYM CLOSURE_EQ_EMPTY] THEN
8215   ASM_CASES_TAC
8216    `convex(closure s:real^N->bool) /\ convex(closure t:real^N->bool)`
8217   THENL [POP_ASSUM MP_TAC; ASM_MESON_TAC[CONVEX_CLOSURE]] THEN
8218   ASM_CASES_TAC `convex(s:real^N->bool)` THEN ASM_REWRITE_TAC[] THEN
8219   ASM_CASES_TAC `convex(t:real^N->bool)` THEN ASM_REWRITE_TAC[] THEN
8220   POP_ASSUM_LIST(K ALL_TAC) THEN
8221   SPEC_TAC(`closure u:real^N->bool`,`u:real^N->bool`) THEN
8222   SPEC_TAC(`closure t:real^N->bool`,`t:real^N->bool`) THEN
8223   SPEC_TAC(`closure s:real^N->bool`,`s:real^N->bool`) THEN
8224   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN REPEAT STRIP_TAC THEN
8225   MATCH_MP_TAC REAL_HAUSDIST_LE_SUMS THEN
8226   MAP_EVERY ABBREV_TAC
8227    [`a = hausdist(s:real^N->bool,t)`;
8228     `b = hausdist({x + e:real^N | x IN s /\ e IN u},
8229                   {y + e | y IN t /\ e IN u})`] THEN
8230    ASM_REWRITE_TAC[CBALL_EQ_EMPTY; REAL_NOT_LT; SET_RULE
8231     `{f x y | x IN s /\ y IN t} = {} <=> s = {} \/ t = {}`]
8232   THENL
8233    [REWRITE_TAC[SUMS_ASSOC] THEN
8234     GEN_REWRITE_TAC (BINOP_CONV o RAND_CONV o RAND_CONV o ONCE_DEPTH_CONV)
8235       [SUMS_SYM] THEN
8236     REWRITE_TAC[GSYM SUMS_ASSOC] THEN CONJ_TAC THEN
8237     MATCH_MP_TAC(SET_RULE
8238      `s SUBSET s'
8239       ==> {f x y | x IN s /\ y IN t} SUBSET {f x y | x IN s' /\ y IN t}`) THEN
8240     EXPAND_TAC "a" THENL
8241      [ALL_TAC; ONCE_REWRITE_TAC[HAUSDIST_SYM]] THEN
8242     MATCH_MP_TAC HAUSDIST_COMPACT_SUMS THEN ASM_SIMP_TAC[COMPACT_IMP_BOUNDED];
8243     CONJ_TAC THEN MATCH_MP_TAC SUBSET_SUMS_RCANCEL THEN
8244     EXISTS_TAC `u:real^N->bool` THEN
8245     ASM_SIMP_TAC[CLOSED_COMPACT_SUMS; COMPACT_CBALL; COMPACT_IMP_CLOSED;
8246       CONVEX_CBALL; COMPACT_IMP_BOUNDED; CONVEX_SUMS; REAL_NOT_LT] THEN
8247     REWRITE_TAC[SUMS_ASSOC] THEN
8248     GEN_REWRITE_TAC (RAND_CONV o RAND_CONV o ONCE_DEPTH_CONV) [SUMS_SYM] THEN
8249     REWRITE_TAC[GSYM SUMS_ASSOC] THEN
8250     EXPAND_TAC "b" THENL
8251      [ALL_TAC; ONCE_REWRITE_TAC[HAUSDIST_SYM]] THEN
8252     MATCH_MP_TAC HAUSDIST_COMPACT_SUMS THEN
8253     ASM_SIMP_TAC[BOUNDED_SUMS; COMPACT_SUMS; COMPACT_CBALL;
8254      COMPACT_IMP_BOUNDED; CBALL_EQ_EMPTY; REAL_NOT_LT; SET_RULE
8255      `{f x y | x IN s /\ y IN t} = {} <=> s = {} \/ t = {}`]]);;
8256
8257 (* ------------------------------------------------------------------------- *)
8258 (* Representation of any interval as a finite convex hull.                   *)
8259 (* ------------------------------------------------------------------------- *)
8260
8261 let CLOSED_INTERVAL_AS_CONVEX_HULL = prove
8262  (`!a b:real^N. ?s. FINITE s /\ interval[a,b] = convex hull s`,
8263   REPEAT GEN_TAC THEN ASM_CASES_TAC `interval[a:real^N,b] = {}` THENL
8264    [ASM_MESON_TAC[CONVEX_HULL_EMPTY; FINITE_EMPTY]; ALL_TAC] THEN
8265   ASM_SIMP_TAC[CLOSED_INTERVAL_IMAGE_UNIT_INTERVAL] THEN
8266   SUBGOAL_THEN
8267    `?s:real^N->bool. FINITE s /\ interval[vec 0,vec 1] = convex hull s`
8268   STRIP_ASSUME_TAC THENL
8269    [EXISTS_TAC
8270      `{x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
8271                       ==> ((x$i = &0) \/ (x$i = &1))}` THEN
8272     REWRITE_TAC[UNIT_INTERVAL_CONVEX_HULL] THEN
8273     MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC
8274      `IMAGE (\s. (lambda i. if i IN s then &1 else &0):real^N)
8275             {t | t SUBSET (1..dimindex(:N))}` THEN
8276     ASM_SIMP_TAC[FINITE_POWERSET; FINITE_IMAGE; FINITE_NUMSEG] THEN
8277     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_IMAGE] THEN
8278     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN EXISTS_TAC
8279      `{i | 1 <= i /\ i <= dimindex(:N) /\ ((x:real^N)$i = &1)}` THEN
8280     SIMP_TAC[CART_EQ; IN_ELIM_THM; IN_NUMSEG; LAMBDA_BETA] THEN
8281     ASM_MESON_TAC[];
8282     EXISTS_TAC `IMAGE (\x:real^N. a + x)
8283                       (IMAGE (\x. (lambda i. ((b:real^N)$i - a$i) * x$i))
8284                              (s:real^N->bool))` THEN
8285     ASM_SIMP_TAC[FINITE_IMAGE; CONVEX_HULL_TRANSLATION] THEN
8286     AP_TERM_TAC THEN MATCH_MP_TAC(GSYM CONVEX_HULL_LINEAR_IMAGE) THEN
8287     SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
8288              VECTOR_MUL_COMPONENT] THEN
8289     REPEAT STRIP_TAC THEN REAL_ARITH_TAC]);;
8290
8291 (* ------------------------------------------------------------------------- *)
8292 (* Bounded convex function on open set is continuous.                        *)
8293 (* ------------------------------------------------------------------------- *)
8294
8295 let CONVEX_ON_BOUNDED_CONTINUOUS = prove
8296  (`!f:real^N->real s b.
8297         open s /\ f convex_on s /\ (!x. x IN s ==> abs(f x) <= b)
8298         ==> (lift o f) continuous_on s`,
8299   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
8300   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
8301   REWRITE_TAC[CONTINUOUS_AT_LIFT_RANGE] THEN
8302   ABBREV_TAC `B = abs(b) + &1` THEN
8303   SUBGOAL_THEN `&0 < B /\ !x:real^N. x IN s ==> abs(f x) <= B`
8304   STRIP_ASSUME_TAC THENL
8305    [EXPAND_TAC "B" THEN CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
8306     ASM_MESON_TAC[REAL_ARITH `x <= b ==> x <= abs b + &1`];
8307     ALL_TAC] THEN
8308   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8309   REWRITE_TAC[REAL_ARITH `abs(x - y) < e <=> x - y < e /\ y - x < e`] THEN
8310   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
8311   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN REWRITE_TAC[SUBSET; IN_CBALL] THEN
8312   ASM_REWRITE_TAC[] THEN
8313   DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
8314   EXISTS_TAC `min (k / &2) (e / (&2 * B) * k)` THEN
8315   ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_DIV; REAL_LT_MUL;
8316                REAL_OF_NUM_LT; ARITH] THEN
8317   X_GEN_TAC `y:real^N` THEN
8318   ASM_CASES_TAC `y:real^N = x` THEN ASM_REWRITE_TAC[REAL_SUB_REFL] THEN
8319   STRIP_TAC THEN
8320   ABBREV_TAC `t = k / norm(y - x:real^N)` THEN
8321   SUBGOAL_THEN `&2 < t` ASSUME_TAC THENL
8322    [EXPAND_TAC "t" THEN
8323     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
8324     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8325     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH];
8326     ALL_TAC] THEN
8327   FIRST_ASSUM(STRIP_ASSUME_TAC o MATCH_MP (REAL_ARITH
8328    `&2 < t ==> &0 < t /\ ~(t = &0) /\ &0 < t - &1 /\
8329                &0 < &1 + t /\ ~(&1 + t = &0)`)) THEN
8330   SUBGOAL_THEN `y:real^N IN s` ASSUME_TAC THENL
8331    [FIRST_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[dist] THEN
8332     ONCE_REWRITE_TAC[NORM_SUB] THEN
8333     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
8334      `x < k / &2 ==> k / &2 <= k ==> x <= k`)) THEN
8335     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
8336     UNDISCH_TAC `&0 < k` THEN REAL_ARITH_TAC;
8337     ALL_TAC] THEN
8338   CONJ_TAC THENL
8339    [ABBREV_TAC `w:real^N = x + t % (y - x)` THEN
8340     SUBGOAL_THEN `w:real^N IN s` STRIP_ASSUME_TAC THENL
8341      [FIRST_ASSUM MATCH_MP_TAC THEN EXPAND_TAC "w" THEN
8342       REWRITE_TAC[dist; VECTOR_ARITH `x - (x + t) = --t:real^N`] THEN
8343       EXPAND_TAC "t" THEN REWRITE_TAC[NORM_NEG; NORM_MUL; REAL_ABS_DIV] THEN
8344       REWRITE_TAC[REAL_ABS_NORM; real_div; GSYM REAL_MUL_ASSOC] THEN
8345       ASM_SIMP_TAC[REAL_MUL_LINV; REAL_LT_IMP_NZ; NORM_POS_LT; VECTOR_SUB_EQ;
8346         REAL_MUL_RID; REAL_ARITH `&0 < x ==> abs(x) <= x`];
8347       ALL_TAC] THEN
8348     SUBGOAL_THEN `(&1 / t) % w + (t - &1) / t % x = y:real^N` ASSUME_TAC THENL
8349      [EXPAND_TAC "w" THEN
8350       REWRITE_TAC[VECTOR_ARITH
8351        `b % (x + c % (y - x)) + a % x =
8352         (a + b - b * c) % x + (b * c) % y`] THEN
8353       ASM_SIMP_TAC[REAL_DIV_RMUL; VECTOR_MUL_LID] THEN
8354       ASM_SIMP_TAC[real_div; REAL_MUL_RINV; REAL_SUB_REFL;
8355                    VECTOR_MUL_LZERO; VECTOR_ADD_LID;
8356                    REAL_ARITH `(a - &1) * b + &1 * b - &1 = a * b - &1`];
8357       ALL_TAC] THEN
8358     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex_on]) THEN
8359     DISCH_THEN(MP_TAC o SPECL
8360      [`w:real^N`; `x:real^N`; `&1 / t`; `(t - &1) / t`]) THEN
8361     ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LT_DIV; REAL_LT_01] THEN
8362     REWRITE_TAC[real_div; GSYM REAL_ADD_RDISTRIB] THEN
8363     ASM_SIMP_TAC[REAL_SUB_ADD2; REAL_MUL_RINV] THEN
8364     MATCH_MP_TAC(REAL_ARITH
8365      `a * fw + (b - &1) * fx < e
8366       ==> fy <= a * fw + b * fx ==> fy - fx < e`) THEN
8367     ASM_SIMP_TAC[real_div; REAL_SUB_RDISTRIB; REAL_MUL_RINV; REAL_MUL_LID;
8368                  REAL_ARITH `a * x + y - a * y - y = a * (x - y)`] THEN
8369     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8370     ASM_SIMP_TAC[GSYM real_div; REAL_LT_LDIV_EQ] THEN
8371     MATCH_MP_TAC(REAL_ARITH
8372      `!b. abs(x) <= b /\ abs(y) <= b /\ &2 * b < z ==> x - y < z`) THEN
8373     EXISTS_TAC `B:real` THEN ASM_SIMP_TAC[] THEN EXPAND_TAC "t" THEN
8374     REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN
8375     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
8376     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8377     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_LT_MUL; REAL_OF_NUM_LT; ARITH] THEN
8378     REWRITE_TAC[real_div; REAL_ARITH `(a * b) * inv c = (b * inv c) * a`] THEN
8379     ASM_REWRITE_TAC[GSYM real_div];
8380
8381     ABBREV_TAC `w:real^N = x - t % (y - x)` THEN
8382     SUBGOAL_THEN `w:real^N IN s` STRIP_ASSUME_TAC THENL
8383      [FIRST_ASSUM MATCH_MP_TAC THEN EXPAND_TAC "w" THEN
8384       REWRITE_TAC[dist; VECTOR_ARITH `x - (x - t) = t:real^N`] THEN
8385       EXPAND_TAC "t" THEN REWRITE_TAC[NORM_MUL; REAL_ABS_DIV] THEN
8386       REWRITE_TAC[REAL_ABS_NORM; real_div; GSYM REAL_MUL_ASSOC] THEN
8387       ASM_SIMP_TAC[REAL_MUL_LINV; REAL_LT_IMP_NZ; NORM_POS_LT; VECTOR_SUB_EQ;
8388         REAL_MUL_RID; REAL_ARITH `&0 < x ==> abs(x) <= x`];
8389       ALL_TAC] THEN
8390     SUBGOAL_THEN `(&1 / (&1 + t)) % w + t / (&1 + t) % y = x:real^N`
8391     ASSUME_TAC THENL
8392      [EXPAND_TAC "w" THEN
8393       REWRITE_TAC[VECTOR_ARITH
8394        `b % (x - c % (y - x)) + a % y =
8395         (b * (&1 + c)) % x + (a - b * c) % y`] THEN
8396       ASM_SIMP_TAC[REAL_DIV_RMUL; VECTOR_MUL_LID] THEN
8397       REWRITE_TAC[real_div; REAL_MUL_AC; REAL_MUL_LID; REAL_MUL_RID] THEN
8398       REWRITE_TAC[REAL_SUB_REFL; VECTOR_MUL_LZERO; VECTOR_ADD_RID];
8399       ALL_TAC] THEN
8400     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex_on]) THEN
8401     DISCH_THEN(MP_TAC o SPECL
8402      [`w:real^N`; `y:real^N`; `&1 / (&1 + t)`; `t / (&1 + t)`]) THEN
8403     ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LT_DIV; REAL_LT_01] THEN
8404     REWRITE_TAC[real_div; GSYM REAL_ADD_RDISTRIB] THEN
8405     ASM_SIMP_TAC[REAL_SUB_ADD2; REAL_MUL_RINV] THEN
8406     MATCH_MP_TAC(REAL_ARITH
8407      `a * fw + (b - &1) * fx < e
8408       ==> fy <= a * fw + b * fx ==> fy - fx < e`) THEN
8409     SUBGOAL_THEN `t * inv(&1 + t) - &1 = --(inv(&1 + t))` SUBST1_TAC THENL
8410      [REWRITE_TAC[REAL_ARITH `(a * b - &1 = --b) <=> ((&1 + a) * b = &1)`] THEN
8411       ASM_SIMP_TAC[REAL_MUL_RINV];
8412       ALL_TAC] THEN
8413     REWRITE_TAC[REAL_ARITH `(&1 * a) * x + --a * y = a * (x - y)`] THEN
8414     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8415     ASM_SIMP_TAC[GSYM real_div; REAL_LT_LDIV_EQ] THEN
8416     MATCH_MP_TAC(REAL_ARITH
8417      `!b. abs(x) <= b /\ abs(y) <= b /\ &2 * b < z ==> x - y < z`) THEN
8418     EXISTS_TAC `B:real` THEN ASM_SIMP_TAC[] THEN
8419     MATCH_MP_TAC(REAL_ARITH `&0 < e /\ x < e * k ==> x < e * (&1 + k)`) THEN
8420     EXPAND_TAC "t" THEN REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN
8421     REWRITE_TAC[GSYM real_div] THEN
8422     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
8423     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8424     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_LT_MUL; REAL_OF_NUM_LT; ARITH] THEN
8425     REWRITE_TAC[real_div; REAL_ARITH `(a * b) * inv c = (b * inv c) * a`] THEN
8426     ASM_REWRITE_TAC[GSYM real_div]]);;
8427
8428 (* ------------------------------------------------------------------------- *)
8429 (* Upper bound on a ball implies upper and lower bounds.                     *)
8430 (* ------------------------------------------------------------------------- *)
8431
8432 let CONVEX_BOUNDS_LEMMA = prove
8433  (`!f x:real^N e.
8434         f convex_on cball(x,e) /\
8435         (!y. y IN cball(x,e) ==> f(y) <= b)
8436         ==> !y. y IN cball(x,e) ==> abs(f(y)) <= b + &2 * abs(f(x))`,
8437   REPEAT GEN_TAC THEN ASM_CASES_TAC `&0 <= e` THENL
8438    [ALL_TAC;
8439     REWRITE_TAC[IN_CBALL] THEN ASM_MESON_TAC[DIST_POS_LE; REAL_LE_TRANS]] THEN
8440   REPEAT STRIP_TAC THEN
8441   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [convex_on]) THEN
8442   DISCH_THEN(MP_TAC o SPECL
8443    [`y:real^N`; `&2 % x - y:real^N`; `&1 / &2`; `&1 / &2`]) THEN
8444   REWRITE_TAC[GSYM VECTOR_ADD_LDISTRIB; GSYM REAL_ADD_LDISTRIB] THEN
8445   REWRITE_TAC[VECTOR_ARITH `y + x - y = x:real^N`] THEN
8446   REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
8447   ABBREV_TAC `z = &2 % x - y:real^N` THEN
8448   SUBGOAL_THEN `z:real^N IN cball(x,e)` ASSUME_TAC THENL
8449    [UNDISCH_TAC `y:real^N IN cball(x,e)`  THEN
8450     EXPAND_TAC "z" THEN REWRITE_TAC[dist; IN_CBALL] THEN
8451     REWRITE_TAC[VECTOR_ARITH `x - (&2 % x - y) = y - x`] THEN
8452     REWRITE_TAC[NORM_SUB];
8453     ALL_TAC] THEN
8454   ASM_REWRITE_TAC[VECTOR_MUL_LID] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8455   REWRITE_TAC[real_div; REAL_MUL_LID] THEN REWRITE_TAC[GSYM real_div] THEN
8456   ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
8457   FIRST_X_ASSUM(fun th ->
8458     MAP_EVERY (MP_TAC o C SPEC th) [`y:real^N`; `z:real^N`]) THEN
8459   ASM_REWRITE_TAC[CENTRE_IN_CBALL] THEN REAL_ARITH_TAC);;
8460
8461 (* ------------------------------------------------------------------------- *)
8462 (* Hence a convex function on an open set is continuous.                     *)
8463 (* ------------------------------------------------------------------------- *)
8464
8465 let CONVEX_ON_CONTINUOUS = prove
8466  (`!f s:real^N->bool. open s /\ f convex_on s ==> lift o f continuous_on s`,
8467   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT] THEN
8468   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
8469   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
8470   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
8471   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
8472   ABBREV_TAC `d = e / &(dimindex(:N))` THEN
8473   SUBGOAL_THEN `&0 < d` ASSUME_TAC THENL
8474    [EXPAND_TAC "d" THEN MATCH_MP_TAC REAL_LT_DIV THEN
8475     ASM_REWRITE_TAC[REAL_OF_NUM_LT; DIMINDEX_GE_1;
8476                     ARITH_RULE `0 < d <=> 1 <= d`];
8477     ALL_TAC] THEN
8478   SUBGOAL_THEN
8479    `?b. !y:real^N. y IN interval[(x - lambda i. d),(x + lambda i. d)]
8480                    ==> f(y) <= b`
8481   STRIP_ASSUME_TAC THENL
8482    [MP_TAC(ISPECL [`x - (lambda i. d):real^N`; `x + (lambda i. d):real^N`]
8483         CLOSED_INTERVAL_AS_CONVEX_HULL) THEN
8484     DISCH_THEN(X_CHOOSE_THEN `c:real^N->bool` STRIP_ASSUME_TAC) THEN
8485     ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `c = {}:real^N->bool` THEN
8486     ASM_REWRITE_TAC[CONVEX_HULL_EMPTY; NOT_IN_EMPTY] THEN
8487     MP_TAC(ISPEC `IMAGE (f:real^N->real) c` SUP_FINITE) THEN
8488     ASM_SIMP_TAC[FINITE_IMAGE; IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
8489     ABBREV_TAC `k = sup(IMAGE (f:real^N->real) c)` THEN
8490     STRIP_TAC THEN EXISTS_TAC `k:real` THEN
8491     MATCH_MP_TAC CONVEX_ON_CONVEX_HULL_BOUND THEN
8492     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONVEX_ON_SUBSET THEN
8493     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
8494     MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `cball (x:real^N,e)` THEN
8495     ASM_REWRITE_TAC[] THEN
8496     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [SYM th]) THEN
8497     REWRITE_TAC[SUBSET; IN_INTERVAL; IN_CBALL] THEN
8498     SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_SUB_COMPONENT; LAMBDA_BETA] THEN
8499     X_GEN_TAC `z:real^N` THEN
8500     REWRITE_TAC[REAL_ARITH `x - d <= z /\ z <= x + d <=> abs(x - z) <= d`] THEN
8501     DISCH_TAC THEN REWRITE_TAC[dist] THEN
8502     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
8503      `sum(1..dimindex(:N)) (\i. abs((x - z:real^N)$i))` THEN
8504     REWRITE_TAC[NORM_LE_L1] THEN
8505     MATCH_MP_TAC SUM_BOUND_GEN THEN
8506     REWRITE_TAC[FINITE_NUMSEG; NUMSEG_EMPTY; CARD_NUMSEG] THEN
8507     ASM_SIMP_TAC[IN_NUMSEG; NOT_LT; DIMINDEX_GE_1; ADD_SUB;
8508                  VECTOR_SUB_COMPONENT];
8509     ALL_TAC] THEN
8510   SUBGOAL_THEN `cball(x:real^N,d) SUBSET cball(x,e)` ASSUME_TAC THENL
8511    [REWRITE_TAC[SUBSET; IN_CBALL] THEN GEN_TAC THEN
8512     MATCH_MP_TAC(REAL_ARITH `d <= e ==> x <= d ==> x <= e`) THEN
8513     EXPAND_TAC "d" THEN
8514     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; DIMINDEX_GE_1;
8515                  ARITH_RULE `0 < x <=> 1 <= x`] THEN
8516     GEN_REWRITE_TAC LAND_CONV [GSYM REAL_MUL_RID] THEN
8517     ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_OF_NUM_LE; DIMINDEX_GE_1];
8518     ALL_TAC] THEN
8519   SUBGOAL_THEN
8520    `!y:real^N. y IN cball(x,d) ==> abs(f(y)) <= b + &2 * abs(f(x))`
8521   ASSUME_TAC THENL
8522    [MATCH_MP_TAC CONVEX_BOUNDS_LEMMA THEN CONJ_TAC THENL
8523      [ASM_MESON_TAC[CONVEX_ON_SUBSET; SUBSET_TRANS]; ALL_TAC] THEN
8524     REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
8525     UNDISCH_TAC `y:real^N IN cball(x,d)` THEN REWRITE_TAC[IN_CBALL] THEN
8526     REWRITE_TAC[IN_INTERVAL; IN_CBALL; dist] THEN DISCH_TAC THEN
8527     SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_SUB_COMPONENT; LAMBDA_BETA] THEN
8528     REWRITE_TAC[REAL_ARITH `x - d <= z /\ z <= x + d <=> abs(x - z) <= d`] THEN
8529     SIMP_TAC[GSYM VECTOR_SUB_COMPONENT] THEN REPEAT STRIP_TAC THEN
8530     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `norm(x - y:real^N)` THEN
8531     ASM_SIMP_TAC[COMPONENT_LE_NORM];
8532     ALL_TAC] THEN
8533   SUBGOAL_THEN `(lift o f) continuous_on (ball(x:real^N,d))` MP_TAC THENL
8534    [MATCH_MP_TAC CONVEX_ON_BOUNDED_CONTINUOUS THEN REWRITE_TAC[OPEN_BALL] THEN
8535     EXISTS_TAC `b + &2 * abs(f(x:real^N))` THEN
8536     ASM_MESON_TAC[SUBSET; CONVEX_ON_SUBSET; SUBSET_TRANS; BALL_SUBSET_CBALL];
8537     ALL_TAC] THEN
8538   ASM_SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT; OPEN_BALL; CENTRE_IN_BALL]);;
8539
8540 (* ------------------------------------------------------------------------- *)
8541 (* Characterizations of convex functions in terms of sequents.               *)
8542 (* ------------------------------------------------------------------------- *)
8543
8544 let CONVEX_ON_LEFT_SECANT_MUL,CONVEX_ON_RIGHT_SECANT_MUL = (CONJ_PAIR o prove)
8545  (`(!f s:real^N->bool.
8546         f convex_on s <=>
8547           !a b x. a IN s /\ b IN s /\ x IN segment[a,b]
8548                   ==> (f x - f a) * norm(b - a) <= (f b - f a) * norm(x - a)) /\
8549    (!f s:real^N->bool.
8550         f convex_on s <=>
8551           !a b x. a IN s /\ b IN s /\ x IN segment[a,b]
8552                   ==> (f b - f a) * norm(b - x) <= (f b - f x) * norm(b - a))`,
8553   CONJ_TAC THEN
8554   REPEAT GEN_TAC THEN REWRITE_TAC[convex_on] THEN
8555   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8556   X_GEN_TAC `a:real^N` THEN REWRITE_TAC[] THEN
8557   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8558   X_GEN_TAC `b:real^N` THEN REWRITE_TAC[] THEN
8559   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
8560   ASM_CASES_TAC `(b:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
8561   REWRITE_TAC[IN_SEGMENT; LEFT_IMP_EXISTS_THM] THEN
8562   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
8563   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8564   X_GEN_TAC `u:real` THEN REWRITE_TAC[] THEN
8565   REWRITE_TAC[TAUT `a /\ x = y <=> x = y /\ a`;
8566               TAUT `a /\ x = y /\ b <=> x = y /\ a /\ b`] THEN
8567   REWRITE_TAC[REAL_ARITH `v + u = &1 <=> v = &1 - u`] THEN
8568   REWRITE_TAC[FORALL_UNWIND_THM2; IMP_CONJ] THEN
8569   REWRITE_TAC[REAL_SUB_LE] THEN
8570   ASM_CASES_TAC `&0 <= u` THEN ASM_REWRITE_TAC[] THEN
8571   ASM_CASES_TAC `u <= &1` THEN ASM_REWRITE_TAC[] THEN
8572   REWRITE_TAC[VECTOR_ARITH `((&1 - u) % a + u % b) - a:real^N = u % (b - a)`;
8573    VECTOR_ARITH `b - ((&1 - u) % a + u % b):real^N = (&1 - u) % (b - a)`] THEN
8574   REWRITE_TAC[NORM_MUL; REAL_MUL_ASSOC] THEN
8575   (ASM_CASES_TAC `b:real^N = a` THENL
8576    [ASM_REWRITE_TAC[VECTOR_SUB_REFL; REAL_SUB_REFL;
8577                     VECTOR_ARITH `(&1 - u) % a + u % a:real^N = a`] THEN
8578     REAL_ARITH_TAC;
8579     ASM_SIMP_TAC[REAL_LE_RMUL_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
8580     ASM_SIMP_TAC[REAL_ARITH
8581      `&0 <= u /\ u <= &1 ==> abs u = u /\ abs(&1 - u) = &1 - u`] THEN
8582     REAL_ARITH_TAC]));;
8583
8584 let CONVEX_ON_LEFT_SECANT,CONVEX_ON_RIGHT_SECANT = (CONJ_PAIR o prove)
8585  (`(!f s:real^N->bool.
8586       f convex_on s <=>
8587         !a b x. a IN s /\ b IN s /\ x IN segment(a,b)
8588                 ==> (f x - f a) / norm(x - a) <= (f b - f a) / norm(b - a)) /\
8589    (!f s:real^N->bool.
8590       f convex_on s <=>
8591         !a b x. a IN s /\ b IN s /\ x IN segment(a,b)
8592                 ==> (f b - f a) / norm(b - a) <= (f b - f x) / norm(b - x))`,
8593   CONJ_TAC THEN REPEAT GEN_TAC THENL
8594    [REWRITE_TAC[CONVEX_ON_LEFT_SECANT_MUL];
8595     REWRITE_TAC[CONVEX_ON_RIGHT_SECANT_MUL]] THEN
8596   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8597   X_GEN_TAC `a:real^N` THEN REWRITE_TAC[] THEN
8598   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8599   X_GEN_TAC `b:real^N` THEN REWRITE_TAC[] THEN
8600   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
8601   ASM_CASES_TAC `(b:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
8602   ASM_CASES_TAC `a:real^N = b` THEN
8603   ASM_REWRITE_TAC[SEGMENT_REFL; NOT_IN_EMPTY; REAL_SUB_REFL; VECTOR_SUB_REFL;
8604                   NORM_0; REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_LE_REFL] THEN
8605   AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
8606   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[] THEN
8607   REWRITE_TAC[open_segment; IN_DIFF; IN_INSERT; NOT_IN_EMPTY] THEN
8608   MAP_EVERY ASM_CASES_TAC [`x:real^N = a`; `x:real^N = b`] THEN
8609   ASM_REWRITE_TAC[REAL_LE_REFL; REAL_SUB_REFL; VECTOR_SUB_REFL; NORM_0;
8610                   REAL_MUL_LZERO; REAL_MUL_RZERO] THEN
8611   ASM_SIMP_TAC[REAL_LE_RDIV_EQ; GSYM REAL_LE_LDIV_EQ; NORM_POS_LT;
8612                VECTOR_SUB_EQ] THEN
8613   AP_TERM_TAC THEN REAL_ARITH_TAC);;
8614
8615 (* ------------------------------------------------------------------------- *)
8616 (* Starlike sets and more stuff about line segments.                         *)
8617 (* ------------------------------------------------------------------------- *)
8618
8619 let starlike = new_definition
8620  `starlike s <=> ?a. a IN s /\ !x. x IN s ==> segment[a,x] SUBSET s`;;
8621
8622 let CONVEX_IMP_STARLIKE = prove
8623  (`!s. convex s /\ ~(s = {}) ==> starlike s`,
8624   REWRITE_TAC[CONVEX_CONTAINS_SEGMENT; starlike; GSYM MEMBER_NOT_EMPTY] THEN
8625   MESON_TAC[]);;
8626
8627 let SEGMENT_CONVEX_HULL = prove
8628  (`!a b. segment[a,b] = convex hull {a,b}`,
8629   REPEAT GEN_TAC THEN
8630   SIMP_TAC[CONVEX_HULL_INSERT; CONVEX_HULL_SING; NOT_INSERT_EMPTY] THEN
8631   REWRITE_TAC[IN_SING; RIGHT_EXISTS_AND_THM; UNWIND_THM2] THEN
8632   REWRITE_TAC[segment; EXTENSION; IN_ELIM_THM] THEN
8633   REWRITE_TAC[REAL_ARITH `u + v = &1 <=> u = &1 - v`] THEN
8634   REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
8635   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c /\ d <=> c /\ a /\ b /\ d`] THEN
8636   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[UNWIND_THM2] THEN
8637   REWRITE_TAC[REAL_LE_SUB_LADD; REAL_ADD_LID] THEN MESON_TAC[]);;
8638
8639 let SEGMENT_FURTHEST_LE = prove
8640  (`!a b x y:real^N.
8641         x IN segment[a,b] ==> norm(y - x) <= norm(y - a) \/
8642                               norm(y - x) <= norm(y - b)`,
8643   REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN REPEAT STRIP_TAC THEN
8644   MP_TAC(ISPECL [`y:real^N`; `{a:real^N,b}`] SIMPLEX_FURTHEST_LE) THEN
8645   ASM_REWRITE_TAC[FINITE_INSERT; FINITE_RULES; NOT_INSERT_EMPTY] THEN
8646   REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN STRIP_TAC THEN
8647   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
8648   ASM_MESON_TAC[NORM_SUB]);;
8649
8650 let SEGMENT_BOUND = prove
8651  (`!a b x:real^N.
8652         x IN segment[a,b] ==> norm(x - a) <= norm(b - a) /\
8653                               norm(x - b) <= norm(b - a)`,
8654   REPEAT STRIP_TAC THEN
8655   MP_TAC(SPECL [`a:real^N`; `b:real^N`; `x:real^N`] SEGMENT_FURTHEST_LE) THENL
8656    [DISCH_THEN(MP_TAC o SPEC `a:real^N`);
8657     DISCH_THEN(MP_TAC o SPEC `b:real^N`)] THEN
8658   REWRITE_TAC[VECTOR_SUB_REFL; NORM_0] THEN
8659   ASM_MESON_TAC[NORM_POS_LE; REAL_LE_TRANS; NORM_SUB]);;
8660
8661 let BETWEEN_IN_CONVEX_HULL = prove
8662  (`!x a b:real^N. between x (a,b) <=> x IN convex hull {a,b}`,
8663   REWRITE_TAC[BETWEEN_IN_SEGMENT; SEGMENT_CONVEX_HULL]);;
8664
8665 let STARLIKE_LINEAR_IMAGE = prove
8666  (`!f s. starlike s /\ linear f ==> starlike(IMAGE f s)`,
8667   REWRITE_TAC[starlike; FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
8668   SIMP_TAC[CLOSED_SEGMENT_LINEAR_IMAGE] THEN SET_TAC[]);;
8669
8670 let STARLIKE_LINEAR_IMAGE_EQ = prove
8671  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
8672          ==> (starlike (IMAGE f s) <=> starlike s)`,
8673   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE STARLIKE_LINEAR_IMAGE));;
8674
8675 add_linear_invariants [STARLIKE_LINEAR_IMAGE_EQ];;
8676
8677 let STARLIKE_TRANSLATION_EQ = prove
8678  (`!a s. starlike (IMAGE (\x. a + x) s) <=> starlike s`,
8679   REWRITE_TAC[starlike] THEN GEOM_TRANSLATE_TAC[]);;
8680
8681 add_translation_invariants [STARLIKE_TRANSLATION_EQ];;
8682
8683 let BETWEEN_LINEAR_IMAGE_EQ = prove
8684  (`!f x y z. linear f /\ (!x y. f x = f y ==> x = y)
8685              ==> (between (f x) (f y,f z) <=> between x (y,z))`,
8686   SIMP_TAC[BETWEEN_IN_SEGMENT; CLOSED_SEGMENT_LINEAR_IMAGE] THEN SET_TAC[]);;
8687
8688 add_linear_invariants [BETWEEN_LINEAR_IMAGE_EQ];;
8689
8690 let BETWEEN_TRANSLATION = prove
8691  (`!a x y. between (a + x) (a + y,a + z) <=> between x (y,z)`,
8692   REWRITE_TAC[between] THEN NORM_ARITH_TAC);;
8693
8694 add_translation_invariants [STARLIKE_TRANSLATION_EQ];;
8695
8696 let STARLIKE_CLOSURE = prove
8697  (`!s:real^N->bool. starlike s ==> starlike(closure s)`,
8698   GEN_TAC THEN REWRITE_TAC[starlike; SUBSET; segment; FORALL_IN_GSPEC] THEN
8699   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
8700   STRIP_TAC THEN ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN
8701   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE] THEN
8702   DISCH_TAC THEN X_GEN_TAC `u:real` THEN STRIP_TAC THEN X_GEN_TAC `e:real` THEN
8703   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN
8704   ASM_REWRITE_TAC[] THEN
8705   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
8706   EXISTS_TAC `(&1 - u) % a + u % y:real^N` THEN
8707   ASM_SIMP_TAC[dist; NORM_MUL; VECTOR_ARITH
8708    `(v % a + u % y) - (v % a + u % z):real^N = u % (y - z)`] THEN
8709   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
8710         REAL_LET_TRANS)) THEN
8711   REWRITE_TAC[dist; REAL_ARITH `u * n <= n <=> &0 <= n * (&1 - u)`] THEN
8712   MATCH_MP_TAC REAL_LE_MUL THEN REWRITE_TAC[NORM_POS_LE] THEN
8713   ASM_REAL_ARITH_TAC);;
8714
8715 let STARLIKE_UNIV = prove
8716  (`starlike(:real^N)`,
8717   MESON_TAC[CONVEX_IMP_STARLIKE; CONVEX_UNIV;
8718             BOUNDED_EMPTY; NOT_BOUNDED_UNIV]);;
8719
8720 let STARLIKE_PCROSS = prove
8721  (`!s:real^M->bool t:real^N->bool.
8722         starlike s /\ starlike t ==> starlike(s PCROSS t)`,
8723   SIMP_TAC[starlike; EXISTS_IN_PCROSS; SUBSET; IN_SEGMENT] THEN
8724   REPEAT GEN_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
8725   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
8726   REWRITE_TAC[FORALL_IN_PCROSS; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
8727   REWRITE_TAC[FORALL_UNWIND_THM2; IMP_IMP] THEN
8728   REWRITE_TAC[GSYM PASTECART_CMUL; PASTECART_ADD] THEN
8729   REWRITE_TAC[PASTECART_IN_PCROSS] THEN MESON_TAC[]);;
8730
8731 let STARLIKE_PCROSS_EQ = prove
8732  (`!s:real^M->bool t:real^N->bool.
8733         starlike(s PCROSS t) <=> starlike s /\ starlike t`,
8734   REPEAT GEN_TAC THEN
8735   ASM_CASES_TAC `s:real^M->bool = {}` THENL
8736    [ASM_REWRITE_TAC[PCROSS_EMPTY] THEN MESON_TAC[starlike; NOT_IN_EMPTY];
8737     ALL_TAC] THEN
8738   ASM_CASES_TAC `t:real^N->bool = {}` THENL
8739    [ASM_REWRITE_TAC[PCROSS_EMPTY] THEN MESON_TAC[starlike; NOT_IN_EMPTY];
8740     ALL_TAC] THEN
8741   EQ_TAC THEN REWRITE_TAC[STARLIKE_PCROSS] THEN REPEAT STRIP_TAC THENL
8742    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
8743      `(s:real^M->bool) PCROSS (t:real^N->bool)`] STARLIKE_LINEAR_IMAGE) THEN
8744     ASM_REWRITE_TAC[LINEAR_FSTCART];
8745     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
8746      `(s:real^M->bool) PCROSS (t:real^N->bool)`] STARLIKE_LINEAR_IMAGE) THEN
8747     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
8748   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
8749   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
8750               FSTCART_PASTECART; SNDCART_PASTECART] THEN
8751   ASM SET_TAC[]);;
8752
8753 let BETWEEN_DIST_LT = prove
8754  (`!r a b c:real^N.
8755         dist(c,a) < r /\ dist(c,b) < r /\ between x (a,b) ==> dist(c,x) < r`,
8756   REPEAT STRIP_TAC THEN
8757   SUBGOAL_THEN `convex hull {a,b} SUBSET ball(c:real^N,r)` MP_TAC THENL
8758    [MATCH_MP_TAC HULL_MINIMAL THEN
8759     ASM_REWRITE_TAC[CONVEX_BALL; INSERT_SUBSET; EMPTY_SUBSET; IN_BALL];
8760     ASM_SIMP_TAC[SUBSET; GSYM BETWEEN_IN_CONVEX_HULL; IN_BALL]]);;
8761
8762 let BETWEEN_DIST_LE = prove
8763  (`!r a b c:real^N.
8764       dist(c,a) <= r /\ dist(c,b) <= r /\ between x (a,b) ==> dist(c,x) <= r`,
8765
8766   REPEAT STRIP_TAC THEN
8767   SUBGOAL_THEN `convex hull {a,b} SUBSET cball(c:real^N,r)` MP_TAC THENL
8768    [MATCH_MP_TAC HULL_MINIMAL THEN
8769     ASM_REWRITE_TAC[CONVEX_CBALL; INSERT_SUBSET; EMPTY_SUBSET; IN_CBALL];
8770     ASM_SIMP_TAC[SUBSET; GSYM BETWEEN_IN_CONVEX_HULL; IN_CBALL]]);;
8771
8772 let BETWEEN_NORM_LT = prove
8773  (`!r a b x:real^N.
8774         norm a < r /\ norm b < r /\ between x (a,b) ==> norm x < r`,
8775   REWRITE_TAC[GSYM(CONJUNCT2(SPEC_ALL DIST_0)); BETWEEN_DIST_LT]);;
8776
8777 let BETWEEN_NORM_LE = prove
8778  (`!r a b x:real^N.
8779         norm a <= r /\ norm b <= r /\ between x (a,b) ==> norm x <= r`,
8780   REWRITE_TAC[GSYM(CONJUNCT2(SPEC_ALL DIST_0)); BETWEEN_DIST_LE]);;
8781
8782 let UNION_SEGMENT = prove
8783  (`!a b c:real^N.
8784         b IN segment[a,c]
8785         ==> segment[a,b] UNION segment[b,c] = segment[a,c]`,
8786   REPEAT GEN_TAC THEN ASM_CASES_TAC `c:real^N = a` THENL
8787    [ASM_SIMP_TAC[SEGMENT_REFL; IN_SING; UNION_IDEMPOT];
8788     ONCE_REWRITE_TAC[UNION_COMM] THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
8789     DISCH_THEN(SUBST1_TAC o MATCH_MP CONVEX_HULL_EXCHANGE_UNION) THEN
8790     ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
8791     REWRITE_TAC[IMAGE_CLAUSES; UNIONS_2] THEN
8792     BINOP_TAC THEN AP_TERM_TAC THEN ASM SET_TAC[]]);;
8793
8794 (* ------------------------------------------------------------------------- *)
8795 (* Shrinking towards the interior of a convex set.                           *)
8796 (* ------------------------------------------------------------------------- *)
8797
8798 let IN_INTERIOR_CONVEX_SHRINK = prove
8799  (`!s e x c:real^N.
8800      convex s /\ c IN interior s /\
8801      x IN s /\ &0 < e /\ e <= &1
8802      ==> x - e % (x - c) IN interior s`,
8803   REPEAT STRIP_TAC THEN
8804   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR]) THEN
8805   REWRITE_TAC[IN_INTERIOR; SUBSET; IN_BALL; dist] THEN
8806   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
8807   EXISTS_TAC `e * d:real` THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
8808   X_GEN_TAC `y':real^N` THEN DISCH_TAC THEN
8809   FIRST_X_ASSUM(MP_TAC o SPEC `(&1 / e) % y' - ((&1 - e) / e) % x:real^N`) THEN
8810   ANTS_TAC THENL
8811    [UNDISCH_TAC `norm (x - e % (x - c) - y':real^N) < e * d` THEN
8812     SUBGOAL_THEN `x - e % (x - c) - y':real^N =
8813                   e % (c - (&1 / e % y' - (&1 - e) / e % x))`
8814     SUBST1_TAC THENL
8815      [ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; VECTOR_MUL_ASSOC;
8816                    REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN VECTOR_ARITH_TAC;
8817       ASM_SIMP_TAC[NORM_MUL; REAL_LT_LMUL_EQ; real_abs; REAL_LT_IMP_LE]];
8818     DISCH_TAC THEN
8819     SUBGOAL_THEN `y' = (&1 - (&1 - e)) % (&1 / e % y' - (&1 - e) / e % x) +
8820                        (&1 - e) % x:real^N`
8821     SUBST1_TAC THENL
8822      [ASM_SIMP_TAC[REAL_ARITH `&1 - (&1 - e) = e`; VECTOR_SUB_LDISTRIB;
8823                    VECTOR_MUL_ASSOC; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
8824       VECTOR_ARITH_TAC;
8825       FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
8826       ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC]]);;
8827
8828 let IN_INTERIOR_CLOSURE_CONVEX_SHRINK = prove
8829  (`!s e x c:real^N.
8830      convex s /\ c IN interior s /\
8831      x IN closure s /\ &0 < e /\ e <= &1
8832      ==> x - e % (x - c) IN interior s`,
8833   REPEAT STRIP_TAC THEN
8834   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR]) THEN
8835   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
8836   SUBGOAL_THEN `?y:real^N. y IN s /\ norm(y - x) * (&1 - e) < e * d`
8837   STRIP_ASSUME_TAC THENL
8838    [ASM_CASES_TAC `(x:real^N) IN s` THENL
8839      [EXISTS_TAC `x:real^N` THEN
8840       ASM_SIMP_TAC[REAL_LT_MUL; VECTOR_SUB_REFL; NORM_0; REAL_MUL_LZERO];
8841       ALL_TAC] THEN
8842     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [closure]) THEN
8843     ASM_REWRITE_TAC[IN_UNION; IN_ELIM_THM; LIMPT_APPROACHABLE; dist] THEN
8844     FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
8845      `e <= &1 ==> e = &1 \/ e < &1`)) THEN
8846     ASM_SIMP_TAC[REAL_SUB_REFL; GSYM REAL_LT_RDIV_EQ; REAL_SUB_LT] THENL
8847      [DISCH_THEN(MP_TAC o SPEC `&1`) THEN
8848       REWRITE_TAC[REAL_MUL_RZERO; REAL_LT_01];
8849       DISCH_THEN(MP_TAC o SPEC `(e * d) / (&1 - e)`)] THEN
8850     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_SUB_LT; REAL_MUL_LZERO; REAL_LT_MUL;
8851                  REAL_MUL_LID] THEN
8852     MATCH_MP_TAC MONO_EXISTS THEN MESON_TAC[];
8853     ALL_TAC] THEN
8854   ABBREV_TAC `z:real^N = c + ((&1 - e) / e) % (x - y)` THEN
8855   SUBGOAL_THEN `x - e % (x - c):real^N = y - e % (y - z)` SUBST1_TAC THENL
8856    [EXPAND_TAC "z" THEN
8857     REWRITE_TAC[VECTOR_SUB_LDISTRIB; VECTOR_ADD_LDISTRIB] THEN
8858     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
8859     VECTOR_ARITH_TAC;
8860     ALL_TAC] THEN
8861   MATCH_MP_TAC IN_INTERIOR_CONVEX_SHRINK THEN ASM_REWRITE_TAC[] THEN
8862   FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET] o
8863      MATCH_MP SUBSET_INTERIOR) THEN
8864   SIMP_TAC[INTERIOR_OPEN; OPEN_BALL] THEN
8865   REWRITE_TAC[IN_BALL; dist] THEN EXPAND_TAC "z" THEN
8866   REWRITE_TAC[NORM_ARITH `norm(c - (c + x)) = norm(x)`] THEN
8867   REWRITE_TAC[NORM_MUL; REAL_ABS_DIV] THEN
8868   ASM_SIMP_TAC[real_abs; REAL_LT_IMP_LE; REAL_SUB_LE] THEN
8869   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8870   REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN
8871   ASM_SIMP_TAC[GSYM real_div; REAL_LT_LDIV_EQ] THEN
8872   ASM_MESON_TAC[REAL_MUL_SYM; NORM_SUB]);;
8873
8874 let IN_INTERIOR_CLOSURE_CONVEX_SEGMENT = prove
8875  (`!s a b:real^N.
8876         convex s /\ a IN interior s /\ b IN closure s
8877         ==> segment(a,b) SUBSET interior s`,
8878   REWRITE_TAC[SUBSET; IN_SEGMENT] THEN REPEAT STRIP_TAC THEN
8879   ASM_REWRITE_TAC[VECTOR_ARITH
8880    `(&1 - u) % a + u % b:real^N = b - (&1 - u) % (b - a)`] THEN
8881   MATCH_MP_TAC IN_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
8882   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
8883
8884 (* ------------------------------------------------------------------------- *)
8885 (* Relative interior of a set.                                               *)
8886 (* ------------------------------------------------------------------------- *)
8887
8888 let relative_interior = new_definition
8889  `relative_interior s =
8890    {x | ?t. open_in (subtopology euclidean (affine hull s)) t /\
8891             x IN t /\ t SUBSET s}`;;
8892
8893 let relative_frontier = new_definition
8894  `relative_frontier s = closure s DIFF relative_interior s`;;
8895
8896 let RELATIVE_INTERIOR = prove
8897  (`!s. relative_interior s =
8898           {x | x IN s /\
8899                ?t. open t /\ x IN t /\ t INTER (affine hull s) SUBSET s}`,
8900   REWRITE_TAC[EXTENSION; relative_interior; IN_ELIM_THM] THEN
8901   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN; LEFT_AND_EXISTS_THM] THEN
8902   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
8903   ONCE_REWRITE_TAC[TAUT `(a /\ b) /\ c /\ d <=> b /\ a /\ c /\ d`] THEN
8904   REWRITE_TAC[UNWIND_THM2; SUBSET; IN_INTER; RIGHT_AND_EXISTS_THM] THEN
8905   AP_TERM_TAC THEN ABS_TAC THEN MESON_TAC[HULL_INC]);;
8906
8907 let RELATIVE_INTERIOR_EQ = prove
8908  (`!s. relative_interior s = s <=>
8909        open_in(subtopology euclidean (affine hull s)) s`,
8910   GEN_TAC THEN REWRITE_TAC[EXTENSION; relative_interior; IN_ELIM_THM] THEN
8911   GEN_REWRITE_TAC RAND_CONV [OPEN_IN_SUBOPEN] THEN MESON_TAC[SUBSET]);;
8912
8913 let RELATIVE_INTERIOR_OPEN_IN = prove
8914  (`!s. open_in(subtopology euclidean (affine hull s)) s
8915        ==> relative_interior s = s`,
8916   REWRITE_TAC[RELATIVE_INTERIOR_EQ]);;
8917
8918 let RELATIVE_INTERIOR_EMPTY = prove
8919  (`relative_interior {} = {}`,
8920   SIMP_TAC[RELATIVE_INTERIOR_OPEN_IN; OPEN_IN_EMPTY]);;
8921
8922 let RELATIVE_FRONTIER_EMPTY = prove
8923  (`relative_frontier {} = {}`,
8924   REWRITE_TAC[relative_frontier; CLOSURE_EMPTY; EMPTY_DIFF]);;
8925
8926 let RELATIVE_INTERIOR_AFFINE = prove
8927  (`!s:real^N->bool. affine s ==> relative_interior s = s`,
8928   SIMP_TAC[RELATIVE_INTERIOR_EQ; OPEN_IN_SUBTOPOLOGY_REFL; HULL_P] THEN
8929   REWRITE_TAC[TOPSPACE_EUCLIDEAN; SUBSET_UNIV]);;
8930
8931 let RELATIVE_INTERIOR_UNIV = prove
8932  (`!s. relative_interior(affine hull s) = affine hull s`,
8933   REPEAT STRIP_TAC THEN MATCH_MP_TAC RELATIVE_INTERIOR_OPEN_IN THEN
8934   REWRITE_TAC[HULL_HULL; OPEN_IN_SUBTOPOLOGY_REFL] THEN
8935   REWRITE_TAC[TOPSPACE_EUCLIDEAN; SUBSET_UNIV]);;
8936
8937 let OPEN_IN_RELATIVE_INTERIOR = prove
8938  (`!s. open_in (subtopology euclidean (affine hull s))
8939                (relative_interior s)`,
8940   GEN_TAC THEN REWRITE_TAC[relative_interior] THEN
8941   GEN_REWRITE_TAC I [OPEN_IN_SUBOPEN] THEN
8942   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
8943
8944 let RELATIVE_INTERIOR_SUBSET = prove
8945  (`!s. (relative_interior s) SUBSET s`,
8946   REWRITE_TAC[SUBSET; relative_interior; IN_ELIM_THM] THEN MESON_TAC[]);;
8947
8948 let OPEN_IN_SET_RELATIVE_INTERIOR = prove
8949  (`!s:real^N->bool. open_in (subtopology euclidean s) (relative_interior s)`,
8950   GEN_TAC THEN MATCH_MP_TAC OPEN_IN_SUBSET_TRANS THEN
8951   EXISTS_TAC `affine hull s:real^N->bool` THEN
8952   REWRITE_TAC[OPEN_IN_RELATIVE_INTERIOR; RELATIVE_INTERIOR_SUBSET;
8953               HULL_SUBSET]);;
8954
8955 let SUBSET_RELATIVE_INTERIOR = prove
8956  (`!s t. s SUBSET t /\ affine hull s = affine hull t
8957          ==> (relative_interior s) SUBSET (relative_interior t)`,
8958   REWRITE_TAC[relative_interior; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
8959
8960 let RELATIVE_INTERIOR_MAXIMAL = prove
8961  (`!s t. t SUBSET s /\
8962          open_in(subtopology euclidean (affine hull s)) t
8963          ==> t SUBSET (relative_interior s)`,
8964   REWRITE_TAC[relative_interior; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
8965
8966 let RELATIVE_INTERIOR_UNIQUE = prove
8967  (`!s t. t SUBSET s /\
8968          open_in(subtopology euclidean (affine hull s)) t /\
8969          (!t'. t' SUBSET s /\
8970                open_in(subtopology euclidean (affine hull s)) t'
8971                ==> t' SUBSET t)
8972          ==> (relative_interior s = t)`,
8973   MESON_TAC[SUBSET_ANTISYM; RELATIVE_INTERIOR_MAXIMAL; RELATIVE_INTERIOR_SUBSET;
8974             OPEN_IN_RELATIVE_INTERIOR]);;
8975
8976 let IN_RELATIVE_INTERIOR = prove
8977  (`!x:real^N s.
8978         x IN relative_interior s <=>
8979         x IN s /\ ?e. &0 < e /\ (ball(x,e) INTER (affine hull s)) SUBSET s`,
8980   REPEAT GEN_TAC THEN REWRITE_TAC[relative_interior; IN_ELIM_THM] THEN
8981   REWRITE_TAC[OPEN_IN_OPEN; LEFT_AND_EXISTS_THM] THEN
8982   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
8983   ONCE_REWRITE_TAC[TAUT `(a /\ b) /\ c /\ d <=> b /\ a /\ c /\ d`] THEN
8984   REWRITE_TAC[UNWIND_THM2; SUBSET; IN_INTER] THEN EQ_TAC THENL
8985    [ASM_MESON_TAC[SUBSET; OPEN_CONTAINS_BALL];
8986     STRIP_TAC THEN EXISTS_TAC `ball(x:real^N,e)` THEN
8987     ASM_SIMP_TAC[OPEN_BALL; CENTRE_IN_BALL; HULL_INC]]);;
8988
8989 let IN_RELATIVE_INTERIOR_CBALL = prove
8990  (`!x:real^N s.
8991         x IN relative_interior s <=>
8992         x IN s /\ ?e. &0 < e /\ (cball(x,e) INTER affine hull s) SUBSET s`,
8993   REPEAT GEN_TAC THEN REWRITE_TAC[IN_RELATIVE_INTERIOR] THEN
8994   AP_TERM_TAC THEN EQ_TAC THEN
8995   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THENL
8996    [EXISTS_TAC `e / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
8997     MATCH_MP_TAC SUBSET_TRANS THEN
8998     EXISTS_TAC `ball(x:real^N,e) INTER affine hull s` THEN
8999     ASM_REWRITE_TAC[] THEN
9000     REWRITE_TAC[SUBSET; IN_INTER; IN_BALL; IN_CBALL] THEN
9001     ASM_SIMP_TAC[REAL_ARITH `&0 < e /\ x <= e / &2 ==> x < e`];
9002     EXISTS_TAC `e:real` THEN ASM_REWRITE_TAC[] THEN
9003     MATCH_MP_TAC SUBSET_TRANS THEN
9004     EXISTS_TAC `cball(x:real^N,e) INTER affine hull s` THEN
9005     ASM_REWRITE_TAC[] THEN
9006     SIMP_TAC[SUBSET; IN_INTER; IN_BALL; IN_CBALL; REAL_LT_IMP_LE]]);;
9007
9008 let OPEN_IN_SUBSET_RELATIVE_INTERIOR = prove
9009  (`!s t. open_in(subtopology euclidean (affine hull t)) s
9010          ==> (s SUBSET relative_interior t <=> s SUBSET t)`,
9011   MESON_TAC[RELATIVE_INTERIOR_MAXIMAL; RELATIVE_INTERIOR_SUBSET;
9012             SUBSET_TRANS]);;
9013
9014 let RELATIVE_INTERIOR_TRANSLATION = prove
9015  (`!a:real^N s.
9016         relative_interior (IMAGE (\x. a + x) s) =
9017         IMAGE (\x. a + x) (relative_interior s)`,
9018   REWRITE_TAC[relative_interior; OPEN_IN_OPEN] THEN GEOM_TRANSLATE_TAC[]);;
9019
9020 add_translation_invariants [RELATIVE_INTERIOR_TRANSLATION];;
9021
9022 let RELATIVE_FRONTIER_TRANSLATION = prove
9023  (`!a:real^N s.
9024         relative_frontier (IMAGE (\x. a + x) s) =
9025         IMAGE (\x. a + x) (relative_frontier s)`,
9026   REWRITE_TAC[relative_frontier] THEN GEOM_TRANSLATE_TAC[]);;
9027
9028 add_translation_invariants [RELATIVE_FRONTIER_TRANSLATION];;
9029
9030 let RELATIVE_INTERIOR_INJECTIVE_LINEAR_IMAGE = prove
9031  (`!f:real^M->real^N s.
9032         linear f /\ (!x y. f x = f y ==> x = y)
9033         ==> relative_interior(IMAGE f s) = IMAGE f (relative_interior s)`,
9034   REPEAT GEN_TAC THEN DISCH_TAC THEN
9035   ASM_SIMP_TAC[relative_interior; AFFINE_HULL_LINEAR_IMAGE] THEN
9036   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> c /\ a /\ b`] THEN
9037   REWRITE_TAC[EXISTS_SUBSET_IMAGE] THEN
9038   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_INJECTIVE_LINEAR_IMAGE) THEN
9039   ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;
9040
9041 add_linear_invariants [RELATIVE_INTERIOR_INJECTIVE_LINEAR_IMAGE];;
9042
9043 let RELATIVE_FRONTIER_INJECTIVE_LINEAR_IMAGE = prove
9044  (`!f:real^M->real^N s.
9045         linear f /\ (!x y. f x = f y ==> x = y)
9046         ==> relative_frontier(IMAGE f s) = IMAGE f (relative_frontier s)`,
9047   REWRITE_TAC[relative_frontier] THEN GEOM_TRANSFORM_TAC[]);;
9048
9049 add_linear_invariants [RELATIVE_FRONTIER_INJECTIVE_LINEAR_IMAGE];;
9050
9051 let RELATIVE_INTERIOR_EQ_EMPTY = prove
9052  (`!s:real^N->bool.
9053         convex s ==> (relative_interior s = {} <=> s = {})`,
9054   SUBGOAL_THEN
9055    `!s:real^N->bool.
9056         vec 0 IN s /\ convex s ==> ~(relative_interior s = {})`
9057   ASSUME_TAC THENL
9058    [ALL_TAC;
9059     GEN_TAC THEN DISCH_TAC THEN
9060     ASM_CASES_TAC `s:real^N->bool = {}` THEN
9061     ASM_REWRITE_TAC[RELATIVE_INTERIOR_EMPTY] THEN
9062     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9063     DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
9064     FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (\x:real^N. --a + x) s`) THEN
9065     REWRITE_TAC[CONVEX_TRANSLATION_EQ; RELATIVE_INTERIOR_TRANSLATION] THEN
9066     ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; IN_IMAGE] THEN
9067     DISCH_THEN MATCH_MP_TAC THEN EXISTS_TAC `a:real^N` THEN
9068     ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC] THEN
9069   GEN_TAC THEN STRIP_TAC THEN
9070   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_RELATIVE_INTERIOR] THEN
9071   ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC] THEN
9072   X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC
9073    (ISPEC `s:real^N->bool` BASIS_EXISTS) THEN
9074   SUBGOAL_THEN `span(s:real^N->bool) = span b` SUBST_ALL_TAC THENL
9075    [ASM_SIMP_TAC[SPAN_EQ] THEN ASM_MESON_TAC[SPAN_INC; SUBSET_TRANS];
9076     ALL_TAC] THEN
9077   RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
9078   ABBREV_TAC `n = dim(s:real^N->bool)` THEN
9079   SUBGOAL_THEN
9080    `!c. (!v. v IN b ==> &0 <= c(v)) /\ sum b c <= &1
9081         ==> vsum b (\v:real^N. c(v) % v) IN s`
9082   ASSUME_TAC THENL
9083    [REPEAT STRIP_TAC THEN SUBGOAL_THEN
9084      `vsum (vec 0 INSERT b :real^N->bool)
9085            (\v. (if v = vec 0 then &1 - sum b c else c v) % v) IN s`
9086     MP_TAC THENL
9087      [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_EXPLICIT]) THEN
9088       ASM_SIMP_TAC[INSERT_SUBSET; FINITE_INSERT; SUM_CLAUSES;
9089                    INDEPENDENT_NONZERO; IN_INSERT] THEN
9090       CONJ_TAC THENL [ASM_MESON_TAC[REAL_SUB_LE]; ALL_TAC] THEN
9091       REWRITE_TAC[REAL_ARITH `&1 - x + y = &1 <=> x = y`] THEN
9092       MATCH_MP_TAC SUM_EQ THEN ASM_MESON_TAC[INDEPENDENT_NONZERO];
9093       MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN
9094       ASM_SIMP_TAC[VSUM_CLAUSES; INDEPENDENT_NONZERO] THEN
9095       REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
9096       MATCH_MP_TAC VSUM_EQ THEN ASM_MESON_TAC[INDEPENDENT_NONZERO]];
9097     ALL_TAC] THEN
9098   ABBREV_TAC `a:real^N = vsum b (\v. inv(&2 * &n + &1) % v)` THEN
9099   EXISTS_TAC `a:real^N` THEN CONJ_TAC THENL
9100    [EXPAND_TAC "a" THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
9101     ASM_SIMP_TAC[SUM_CONST; REAL_LE_INV_EQ; REAL_ARITH `&0 < &2 * &n + &1`;
9102                  GSYM real_div; REAL_LT_IMP_LE; REAL_LE_LDIV_EQ] THEN
9103     REAL_ARITH_TAC;
9104     ALL_TAC] THEN
9105   MP_TAC(ISPECL [`b:real^N->bool`; `inv(&2 * &n + &1)`]
9106         BASIS_COORDINATES_CONTINUOUS) THEN
9107   ASM_REWRITE_TAC[REAL_LT_INV_EQ] THEN
9108   ANTS_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
9109   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN STRIP_TAC THEN
9110   ASM_SIMP_TAC[SUBSET; IN_INTER; IMP_CONJ_ALT] THEN
9111   ASM_SIMP_TAC[SPAN_FINITE; LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN
9112   GEN_TAC THEN X_GEN_TAC `u:real^N->real` THEN
9113   DISCH_THEN(SUBST1_TAC o SYM) THEN REWRITE_TAC[IN_BALL; dist] THEN
9114   EXPAND_TAC "a" THEN ASM_SIMP_TAC[GSYM VSUM_SUB] THEN
9115   DISCH_THEN(fun th -> FIRST_X_ASSUM MATCH_MP_TAC THEN MP_TAC th) THEN
9116   REWRITE_TAC[GSYM VECTOR_SUB_RDISTRIB] THEN
9117   DISCH_THEN(fun th -> FIRST_X_ASSUM(MP_TAC o C MATCH_MP th)) THEN
9118   REWRITE_TAC[REAL_ARITH `abs(x - y) < x <=> &0 < y /\ abs(y) < &2 * x`] THEN
9119   SIMP_TAC[REAL_LT_IMP_LE] THEN DISCH_TAC THEN
9120   MATCH_MP_TAC REAL_LE_TRANS THEN
9121   EXISTS_TAC `&(CARD(b:real^N->bool)) * &2 * inv(&2 * &n + &1)` THEN
9122   CONJ_TAC THENL
9123    [MATCH_MP_TAC SUM_BOUND THEN
9124     ASM_SIMP_TAC[REAL_ARITH `abs x < a ==> x <= a`];
9125     ASM_REWRITE_TAC[REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM real_div] THEN
9126     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_ARITH `&0 < &2 * &n + &1`] THEN
9127     REAL_ARITH_TAC]);;
9128
9129 let RELATIVE_INTERIOR_INTERIOR = prove
9130  (`!s. affine hull s = (:real^N)
9131        ==> relative_interior s = interior s`,
9132   SIMP_TAC[relative_interior; interior; SUBTOPOLOGY_UNIV; OPEN_IN]);;
9133
9134 let RELATIVE_INTERIOR_OPEN = prove
9135  (`!s:real^N->bool. open s ==> relative_interior s = s`,
9136   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9137   ASM_REWRITE_TAC[RELATIVE_INTERIOR_EMPTY] THEN
9138   ASM_SIMP_TAC[RELATIVE_INTERIOR_INTERIOR; AFFINE_HULL_OPEN; INTERIOR_EQ]);;
9139
9140 let RELATIVE_INTERIOR_NONEMPTY_INTERIOR = prove
9141  (`!s. ~(interior s = {}) ==> relative_interior s = interior s`,
9142   MESON_TAC[RELATIVE_INTERIOR_INTERIOR; AFFINE_HULL_NONEMPTY_INTERIOR]);;
9143
9144 let RELATIVE_FRONTIER_NONEMPTY_INTERIOR = prove
9145  (`!s. ~(interior s = {}) ==> relative_frontier s = frontier s`,
9146   SIMP_TAC[relative_frontier; frontier; RELATIVE_INTERIOR_NONEMPTY_INTERIOR]);;
9147
9148 let RELATIVE_FRONTIER_FRONTIER = prove
9149  (`!s. affine hull s = (:real^N) ==> relative_frontier s = frontier s`,
9150   SIMP_TAC[relative_frontier; frontier; RELATIVE_INTERIOR_INTERIOR]);;
9151
9152 let AFFINE_HULL_CONVEX_HULL = prove
9153  (`!s. affine hull (convex hull s) = affine hull s`,
9154   GEN_TAC THEN MATCH_MP_TAC HULL_UNIQUE THEN
9155   REWRITE_TAC[AFFINE_AFFINE_HULL; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
9156   REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_MINIMAL THEN
9157   ASM_MESON_TAC[SUBSET_TRANS; HULL_SUBSET]);;
9158
9159 let INTERIOR_SIMPLEX_NONEMPTY = prove
9160  (`!s:real^N->bool.
9161         independent s /\ s HAS_SIZE (dimindex(:N))
9162         ==> ?a. a IN interior(convex hull (vec 0 INSERT s))`,
9163   REPEAT STRIP_TAC THEN
9164   MP_TAC(ISPEC `convex hull (vec 0 INSERT s):real^N->bool`
9165     RELATIVE_INTERIOR_EQ_EMPTY) THEN
9166   ASM_SIMP_TAC[AFFINE_HULL_CONVEX_HULL] THEN
9167   REWRITE_TAC[CONVEX_HULL_EQ_EMPTY; CONVEX_CONVEX_HULL; NOT_INSERT_EMPTY] THEN
9168   REWRITE_TAC[MEMBER_NOT_EMPTY] THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
9169   AP_THM_TAC THEN AP_TERM_TAC THEN MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
9170   SIMP_TAC[AFFINE_HULL_EQ_SPAN; IN_INSERT; HULL_INC] THEN
9171   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
9172   EXISTS_TAC `span s:real^N->bool` THEN CONJ_TAC THENL
9173    [MATCH_MP_TAC SPAN_MONO THEN MATCH_MP_TAC(SET_RULE
9174      `(a INSERT s) SUBSET P hull (a INSERT s)
9175       ==> s SUBSET P hull (a INSERT s)`) THEN REWRITE_TAC[HULL_SUBSET];
9176     MATCH_MP_TAC(SET_RULE `UNIV SUBSET s ==> s = UNIV`) THEN
9177     MATCH_MP_TAC CARD_GE_DIM_INDEPENDENT THEN
9178     ASM_REWRITE_TAC[DIM_UNIV; SUBSET_UNIV] THEN
9179     ASM_MESON_TAC[LE_REFL;HAS_SIZE]]);;
9180
9181 let INTERIOR_SUBSET_RELATIVE_INTERIOR = prove
9182  (`!s. interior s SUBSET relative_interior s`,
9183   REWRITE_TAC[SUBSET; IN_INTERIOR; IN_RELATIVE_INTERIOR; IN_INTER] THEN
9184   MESON_TAC[CENTRE_IN_BALL]);;
9185
9186 let CONVEX_RELATIVE_INTERIOR = prove
9187  (`!s:real^N->bool. convex s ==> convex(relative_interior s)`,
9188   REWRITE_TAC[CONVEX_ALT; IN_RELATIVE_INTERIOR; IN_INTER;
9189               SUBSET; IN_BALL; dist] THEN
9190   GEN_TAC THEN DISCH_TAC THEN REPEAT GEN_TAC THEN
9191   REWRITE_TAC[TAUT `(a /\ b) /\ (c /\ d) /\ e ==> f <=>
9192                     a /\ c /\ e ==> b /\ d ==> f`] THEN
9193   STRIP_TAC THEN ASM_SIMP_TAC[] THEN
9194   MATCH_MP_TAC(MESON[] `(!d e. P d /\ Q e ==> R(min d e))
9195                         ==> (?e. P e) /\ (?e. Q e) ==> (?e. R e)`) THEN
9196   REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
9197   X_GEN_TAC `z:real^N` THEN STRIP_TAC THEN
9198   SUBST1_TAC(VECTOR_ARITH `z:real^N =
9199    (&1 - u) % (z - u % (y - x)) + u % (z + (&1 - u) % (y - x))`) THEN
9200   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
9201   FIRST_X_ASSUM(CONJUNCTS_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
9202   REWRITE_TAC[GSYM IMP_CONJ_ALT] THEN MATCH_MP_TAC MONO_AND THEN
9203   CONJ_TAC THEN DISCH_THEN MATCH_MP_TAC THEN
9204   (CONJ_TAC THENL
9205     [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
9206       `norm x < e ==> norm x = y ==> y < e`)) THEN
9207      AP_TERM_TAC THEN VECTOR_ARITH_TAC;
9208      REWRITE_TAC[VECTOR_ARITH `a - b % c:real^N = a + --b % c`] THEN
9209      MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
9210      ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC]]));;
9211
9212 let IN_RELATIVE_INTERIOR_CONVEX_SHRINK = prove
9213  (`!s e x c:real^N.
9214      convex s /\ c IN relative_interior s /\
9215      x IN s /\ &0 < e /\ e <= &1
9216      ==> x - e % (x - c) IN relative_interior s`,
9217   REPEAT STRIP_TAC THEN
9218   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR]) THEN
9219   REWRITE_TAC[IN_RELATIVE_INTERIOR; SUBSET; IN_INTER; IN_BALL; dist] THEN
9220   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9221   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN CONJ_TAC THENL
9222    [REWRITE_TAC[VECTOR_ARITH
9223      `x - e % (x - c):real^N = (&1 - e) % x + e % c`] THEN
9224     FIRST_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [convex]) THEN
9225     ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
9226     ALL_TAC] THEN
9227   EXISTS_TAC `e * d:real` THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
9228   X_GEN_TAC `y':real^N` THEN STRIP_TAC THEN
9229   FIRST_X_ASSUM(MP_TAC o SPEC `(&1 / e) % y' - ((&1 - e) / e) % x:real^N`) THEN
9230   ANTS_TAC THENL
9231    [CONJ_TAC THENL
9232      [UNDISCH_TAC `norm (x - e % (x - c) - y':real^N) < e * d` THEN
9233       SUBGOAL_THEN `x - e % (x - c) - y':real^N =
9234                     e % (c - (&1 / e % y' - (&1 - e) / e % x))`
9235       SUBST1_TAC THENL
9236        [ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; VECTOR_MUL_ASSOC;
9237                      REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN VECTOR_ARITH_TAC;
9238         ASM_SIMP_TAC[NORM_MUL; REAL_LT_LMUL_EQ; real_abs; REAL_LT_IMP_LE]];
9239       REWRITE_TAC[real_div; REAL_SUB_RDISTRIB] THEN
9240       ASM_SIMP_TAC[REAL_MUL_RINV; REAL_LT_IMP_NZ] THEN
9241       REWRITE_TAC[VECTOR_ARITH `a % y - (b - c) % x:real^N =
9242                                 (c - b) % x + a % y`] THEN
9243       MATCH_MP_TAC(REWRITE_RULE[AFFINE_ALT] AFFINE_AFFINE_HULL) THEN
9244       ASM_SIMP_TAC[HULL_INC]];
9245     DISCH_TAC THEN
9246     SUBGOAL_THEN `y' = (&1 - (&1 - e)) % (&1 / e % y' - (&1 - e) / e % x) +
9247                        (&1 - e) % x:real^N`
9248     SUBST1_TAC THENL
9249      [ASM_SIMP_TAC[REAL_ARITH `&1 - (&1 - e) = e`; VECTOR_SUB_LDISTRIB;
9250                    VECTOR_MUL_ASSOC; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
9251       VECTOR_ARITH_TAC;
9252       FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
9253       ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC]]);;
9254
9255 let IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK = prove
9256  (`!s e x c:real^N.
9257      convex s /\ c IN relative_interior s /\
9258      x IN closure s /\ &0 < e /\ e <= &1
9259      ==> x - e % (x - c) IN relative_interior s`,
9260   REPEAT STRIP_TAC THEN
9261   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR]) THEN
9262   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9263   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
9264   SUBGOAL_THEN `?y:real^N. y IN s /\ norm(y - x) * (&1 - e) < e * d`
9265   STRIP_ASSUME_TAC THENL
9266    [ASM_CASES_TAC `(x:real^N) IN s` THENL
9267      [EXISTS_TAC `x:real^N` THEN
9268       ASM_SIMP_TAC[REAL_LT_MUL; VECTOR_SUB_REFL; NORM_0; REAL_MUL_LZERO];
9269       ALL_TAC] THEN
9270     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [closure]) THEN
9271     ASM_REWRITE_TAC[IN_UNION; IN_ELIM_THM; LIMPT_APPROACHABLE; dist] THEN
9272     FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
9273      `e <= &1 ==> e = &1 \/ e < &1`)) THEN
9274     ASM_SIMP_TAC[REAL_SUB_REFL; GSYM REAL_LT_RDIV_EQ; REAL_SUB_LT] THENL
9275      [DISCH_THEN(MP_TAC o SPEC `&1`) THEN
9276       REWRITE_TAC[REAL_MUL_RZERO; REAL_LT_01];
9277       DISCH_THEN(MP_TAC o SPEC `(e * d) / (&1 - e)`)] THEN
9278     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_SUB_LT; REAL_MUL_LZERO; REAL_LT_MUL;
9279                  REAL_MUL_LID] THEN
9280     MATCH_MP_TAC MONO_EXISTS THEN MESON_TAC[];
9281     ALL_TAC] THEN
9282   ABBREV_TAC `z:real^N = c + ((&1 - e) / e) % (x - y)` THEN
9283   SUBGOAL_THEN `x - e % (x - c):real^N = y - e % (y - z)` SUBST1_TAC THENL
9284    [EXPAND_TAC "z" THEN
9285     REWRITE_TAC[VECTOR_SUB_LDISTRIB; VECTOR_ADD_LDISTRIB] THEN
9286     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
9287     VECTOR_ARITH_TAC;
9288     ALL_TAC] THEN
9289   MATCH_MP_TAC IN_RELATIVE_INTERIOR_CONVEX_SHRINK THEN ASM_REWRITE_TAC[] THEN
9290   SUBGOAL_THEN `dist(c:real^N,z) < d` ASSUME_TAC THENL
9291    [EXPAND_TAC "z" THEN
9292     REWRITE_TAC[NORM_ARITH `dist(c:real^N,c + x) = norm x`] THEN
9293     REWRITE_TAC[NORM_MUL; REAL_ABS_DIV] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN
9294     REWRITE_TAC[REAL_ARITH `a / b * c:real = (c * a) / b`] THEN
9295     ASM_SIMP_TAC[real_abs; REAL_SUB_LE; REAL_LT_IMP_LE; REAL_LT_LDIV_EQ] THEN
9296     ASM_REAL_ARITH_TAC;
9297     ALL_TAC] THEN
9298   SUBGOAL_THEN `(z:real^N) IN affine hull s` ASSUME_TAC THENL
9299    [EXPAND_TAC "z" THEN MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
9300     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC] THEN
9301     MATCH_MP_TAC(SET_RULE `!t. x IN t /\ t = s ==> x IN s`) THEN
9302     EXISTS_TAC `closure(affine hull s):real^N->bool` THEN
9303     SIMP_TAC[CLOSURE_EQ; CLOSED_AFFINE_HULL] THEN
9304     ASM_MESON_TAC[SUBSET_CLOSURE; HULL_INC; SUBSET];
9305     ALL_TAC] THEN
9306   ASM_REWRITE_TAC[IN_RELATIVE_INTERIOR] THEN CONJ_TAC THENL
9307    [ASM_MESON_TAC[IN_BALL; IN_INTER; SUBSET]; ALL_TAC] THEN
9308   EXISTS_TAC `d - dist(c:real^N,z)` THEN ASM_REWRITE_TAC[REAL_SUB_LT] THEN
9309   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
9310    (REWRITE_RULE[IMP_CONJ_ALT] SUBSET_TRANS)) THEN
9311   REWRITE_TAC[SUBSET; IN_INTER] THEN GEN_TAC THEN
9312   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
9313   UNDISCH_TAC `dist(c:real^N,z) < d` THEN REWRITE_TAC[IN_BALL] THEN
9314   NORM_ARITH_TAC);;
9315
9316 let IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT = prove
9317  (`!s a b:real^N.
9318         convex s /\ a IN relative_interior s /\ b IN closure s
9319         ==> segment(a,b) SUBSET relative_interior s`,
9320   REWRITE_TAC[SUBSET; IN_SEGMENT] THEN REPEAT STRIP_TAC THEN
9321   ASM_REWRITE_TAC[VECTOR_ARITH
9322    `(&1 - u) % a + u % b:real^N = b - (&1 - u) % (b - a)`] THEN
9323   MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
9324   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
9325
9326 let CONVEX_OPEN_SEGMENT_CASES = prove
9327  (`!s a b:real^N.
9328         convex s /\ a IN closure s /\ b IN closure s
9329         ==> segment(a,b) SUBSET relative_frontier s \/
9330             segment(a,b) SUBSET relative_interior s`,
9331   REPEAT STRIP_TAC THEN REWRITE_TAC[relative_frontier] THEN
9332   MATCH_MP_TAC(SET_RULE
9333    `s SUBSET c /\ (!a. a IN i /\ a IN s ==> s SUBSET i)
9334     ==> s SUBSET c DIFF i \/ s SUBSET i`) THEN
9335   CONJ_TAC THENL
9336    [ASM_MESON_TAC[CONVEX_CONTAINS_OPEN_SEGMENT; CONVEX_CLOSURE];
9337     X_GEN_TAC `c:real^N` THEN ONCE_REWRITE_TAC[segment]] THEN
9338   REWRITE_TAC[IN_DIFF; IN_INSERT; DE_MORGAN_THM; NOT_IN_EMPTY] THEN
9339   STRIP_TAC THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP UNION_SEGMENT) THEN
9340   MP_TAC(ISPECL [`s:real^N->bool`; `c:real^N`]
9341         IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT) THEN
9342   DISCH_THEN(fun th ->
9343     MP_TAC(SPEC `b:real^N` th) THEN MP_TAC(SPEC `a:real^N` th)) THEN
9344   ASM_REWRITE_TAC[SEGMENT_SYM; CONJUNCT2 segment] THEN ASM SET_TAC[]);;
9345
9346 let RELATIVE_INTERIOR_SING = prove
9347  (`!a. relative_interior {a} = {a}`,
9348   GEN_TAC THEN MATCH_MP_TAC(SET_RULE
9349    `s SUBSET {a} /\ ~(s = {}) ==> s = {a}`) THEN
9350   SIMP_TAC[RELATIVE_INTERIOR_SUBSET; RELATIVE_INTERIOR_EQ_EMPTY;
9351            CONVEX_SING] THEN
9352   SET_TAC[]);;
9353
9354 let RELATIVE_FRONTIER_SING = prove
9355  (`!a:real^N. relative_frontier {a} = {}`,
9356   REWRITE_TAC[relative_frontier; RELATIVE_INTERIOR_SING; CLOSURE_SING] THEN
9357   SET_TAC[]);;
9358
9359 let RELATIVE_INTERIOR_CBALL = prove
9360  (`!a r. relative_interior(cball(a,r)) = if r = &0 then {a} else ball(a,r)`,
9361   REPEAT GEN_TAC THEN ASM_CASES_TAC `r < &0` THEN
9362   ASM_SIMP_TAC[REAL_LT_IMP_NE; CBALL_EMPTY; BALL_EMPTY;
9363                RELATIVE_INTERIOR_EMPTY; REAL_LT_IMP_LE] THEN
9364   COND_CASES_TAC THEN ASM_SIMP_TAC[CBALL_SING; RELATIVE_INTERIOR_SING] THEN
9365   REWRITE_TAC[GSYM INTERIOR_CBALL] THEN
9366   MATCH_MP_TAC RELATIVE_INTERIOR_NONEMPTY_INTERIOR THEN
9367   ASM_REWRITE_TAC[INTERIOR_CBALL; BALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC);;
9368
9369 let RELATIVE_INTERIOR_BALL = prove
9370  (`!a r. relative_interior(ball(a,r)) = ball(a,r)`,
9371   SIMP_TAC[RELATIVE_INTERIOR_OPEN; OPEN_BALL]);;
9372
9373 let RELATIVE_FRONTIER_CBALL = prove
9374  (`!a:real^N r. relative_frontier(cball(a,r)) =
9375                 if r = &0 then {} else sphere(a,r)`,
9376   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
9377   ASM_SIMP_TAC[CBALL_SING; RELATIVE_FRONTIER_SING] THEN
9378   ASM_CASES_TAC `r < &0` THEN
9379   ASM_SIMP_TAC[CBALL_EMPTY; SPHERE_EMPTY; RELATIVE_FRONTIER_EMPTY] THEN
9380   SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
9381   ASM_SIMP_TAC[RELATIVE_FRONTIER_NONEMPTY_INTERIOR; INTERIOR_CBALL;
9382                BALL_EQ_EMPTY; GSYM REAL_NOT_LT; FRONTIER_CBALL]);;
9383
9384 let RELATIVE_FRONTIER_BALL = prove
9385  (`!a:real^N r. relative_frontier(ball(a,r)) =
9386                 if r = &0 then {} else sphere(a,r)`,
9387   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
9388   ASM_SIMP_TAC[BALL_EMPTY; REAL_LE_REFL; RELATIVE_FRONTIER_EMPTY] THEN
9389   ASM_CASES_TAC `r < &0` THEN
9390   ASM_SIMP_TAC[BALL_EMPTY; REAL_LT_IMP_LE; SPHERE_EMPTY;
9391                RELATIVE_FRONTIER_EMPTY] THEN
9392   SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
9393   ASM_SIMP_TAC[RELATIVE_FRONTIER_NONEMPTY_INTERIOR; INTERIOR_OPEN; OPEN_BALL;
9394                BALL_EQ_EMPTY; GSYM REAL_NOT_LT; FRONTIER_BALL]);;
9395
9396 let STARLIKE_CONVEX_TWEAK_BOUNDARY_POINTS = prove
9397  (`!s t:real^N->bool.
9398         convex s /\ ~(s = {}) /\
9399         relative_interior s SUBSET t /\ t SUBSET closure s
9400         ==> starlike t`,
9401   REPEAT STRIP_TAC THEN
9402   SUBGOAL_THEN `~(relative_interior s:real^N->bool = {})` MP_TAC THENL
9403    [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY]; REWRITE_TAC[starlike]] THEN
9404   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN MATCH_MP_TAC MONO_EXISTS THEN
9405   X_GEN_TAC `a:real^N` THEN
9406   REPEAT STRIP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
9407   MATCH_MP_TAC(SET_RULE
9408    `a IN s /\ b IN s /\ segment[a,b] DIFF {a,b} SUBSET s
9409     ==> segment[a:real^N,b] SUBSET s`) THEN
9410   ASM_REWRITE_TAC[GSYM open_segment] THEN
9411   ASM_MESON_TAC[IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT; SUBSET]);;
9412
9413 let RELATIVE_INTERIOR_PROLONG = prove
9414  (`!s x y:real^N.
9415         x IN relative_interior s /\ y IN s
9416         ==> ?t. &1 < t /\ (y + t % (x - y)) IN s`,
9417   REPEAT GEN_TAC THEN
9418   REWRITE_TAC[IN_RELATIVE_INTERIOR_CBALL; IN_ELIM_THM] THEN
9419   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
9420   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `e:real`
9421   STRIP_ASSUME_TAC)) THEN
9422   ASM_CASES_TAC `y:real^N = x` THENL
9423    [ASM_REWRITE_TAC[VECTOR_ARITH `y + t % (x - x):real^N = y`] THEN
9424     EXISTS_TAC `&2` THEN CONV_TAC REAL_RAT_REDUCE_CONV;
9425     EXISTS_TAC `&1 + e / norm(x - y:real^N)` THEN
9426     ASM_SIMP_TAC[REAL_LT_ADDR; REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ] THEN
9427     REWRITE_TAC[VECTOR_ARITH
9428      `y + (&1 + e) % (x - y):real^N = x + e % (x - y)`] THEN
9429     FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET]) THEN
9430     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; IN_INTER; IN_AFFINE_ADD_MUL_DIFF;
9431                  HULL_INC; IN_CBALL] THEN
9432     REWRITE_TAC[NORM_ARITH `dist(x:real^N,x + y) = norm y`] THEN
9433     REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
9434     ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ] THEN
9435     ASM_REAL_ARITH_TAC]);;
9436
9437 let RELATIVE_INTERIOR_CONVEX_PROLONG = prove
9438  (`!s. convex s
9439        ==> relative_interior s =
9440            {x:real^N | x IN s /\
9441                        !y. y IN s ==> ?t. &1 < t /\ (y + t % (x - y)) IN s}`,
9442   REPEAT STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
9443   X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
9444    [SIMP_TAC[RELATIVE_INTERIOR_PROLONG] THEN
9445     MESON_TAC[SUBSET; RELATIVE_INTERIOR_SUBSET];
9446     STRIP_TAC THEN
9447     SUBGOAL_THEN `?y:real^N. y IN relative_interior s` STRIP_ASSUME_TAC THENL
9448      [ASM_SIMP_TAC[MEMBER_NOT_EMPTY; RELATIVE_INTERIOR_EQ_EMPTY] THEN
9449       ASM SET_TAC[];
9450       ALL_TAC] THEN
9451     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ANTS_TAC THENL
9452      [ASM_MESON_TAC[RELATIVE_INTERIOR_SUBSET; SUBSET]; ALL_TAC] THEN
9453     ASM_CASES_TAC `y:real^N = x` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
9454     DISCH_THEN(X_CHOOSE_THEN `t:real` STRIP_ASSUME_TAC) THEN
9455     MP_TAC(ISPECL [`s:real^N->bool`; `y:real^N`; `y + t % (x - y):real^N`]
9456         IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT) THEN
9457     ANTS_TAC THENL [ASM_MESON_TAC[SUBSET; CLOSURE_SUBSET]; ALL_TAC] THEN
9458     REWRITE_TAC[SUBSET] THEN DISCH_THEN MATCH_MP_TAC THEN
9459     REWRITE_TAC[IN_SEGMENT; IN_ELIM_THM] THEN
9460     ASM_REWRITE_TAC[VECTOR_ARITH `y:real^N = y + x <=> x = vec 0`;
9461       VECTOR_ARITH `(&1 - u) % y + u % (y + t % (x - y)):real^N =
9462                     y + t % u % (x - y)`] THEN
9463     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
9464     CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
9465     EXISTS_TAC `inv t:real` THEN
9466     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; REAL_LT_INV_EQ;
9467       REAL_INV_LT_1; REAL_LT_IMP_NZ; REAL_ARITH `&1 < x ==> &0 < x`] THEN
9468     VECTOR_ARITH_TAC]);;
9469
9470 let RELATIVE_INTERIOR_EQ_CLOSURE = prove
9471  (`!s:real^N->bool.
9472         relative_interior s = closure s <=> affine s`,
9473   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9474   ASM_REWRITE_TAC[RELATIVE_INTERIOR_EMPTY; CLOSURE_EMPTY; AFFINE_EMPTY] THEN
9475   EQ_TAC THEN
9476   SIMP_TAC[RELATIVE_INTERIOR_AFFINE; CLOSURE_CLOSED; CLOSED_AFFINE] THEN
9477   DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
9478    `relative_interior s = closure s
9479     ==> relative_interior s SUBSET s /\ s SUBSET closure s
9480         ==> relative_interior s = s /\ closure s = s`)) THEN
9481   REWRITE_TAC[RELATIVE_INTERIOR_SUBSET; CLOSURE_SUBSET] THEN
9482   REWRITE_TAC[RELATIVE_INTERIOR_EQ; CLOSURE_EQ; GSYM AFFINE_HULL_EQ] THEN
9483   STRIP_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
9484    `~(s = {}) ==> s = {} \/ s = a ==> a = s`)) THEN
9485   MP_TAC(ISPEC `affine hull s:real^N->bool` CONNECTED_CLOPEN) THEN
9486   SIMP_TAC[AFFINE_IMP_CONVEX; CONVEX_CONNECTED; AFFINE_AFFINE_HULL] THEN
9487   DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
9488   MATCH_MP_TAC CLOSED_SUBSET THEN ASM_REWRITE_TAC[HULL_SUBSET]);;
9489
9490 let RAY_TO_RELATIVE_FRONTIER = prove
9491  (`!s a l:real^N.
9492         bounded s /\ a IN relative_interior s /\
9493         (a + l) IN affine hull s /\ ~(l = vec 0)
9494         ==> ?d. &0 < d /\
9495                 (a + d % l) IN relative_frontier s /\
9496                 !e. &0 <= e /\ e < d ==> (a + e % l) IN relative_interior s`,
9497   REPEAT STRIP_TAC THEN REWRITE_TAC[relative_frontier] THEN
9498   MP_TAC(ISPEC
9499    `{d | &0 < d /\ ~((a + d % l:real^N) IN relative_interior(s))}` INF) THEN
9500   ABBREV_TAC
9501    `d = inf {d | &0 < d /\ ~((a + d % l:real^N) IN relative_interior(s))}` THEN
9502   SUBGOAL_THEN
9503    `?e. &0 < e /\ !d. &0 <= d /\ d < e
9504                       ==> (a + d % l:real^N) IN relative_interior s`
9505    (X_CHOOSE_THEN `k:real` (LABEL_TAC "0"))
9506   THENL
9507    [MP_TAC(ISPEC `s:real^N->bool` OPEN_IN_RELATIVE_INTERIOR) THEN
9508     REWRITE_TAC[open_in; GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
9509     DISCH_THEN(MP_TAC o SPEC `a:real^N` o CONJUNCT2) THEN
9510     ASM_REWRITE_TAC[] THEN
9511     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
9512     EXISTS_TAC `e / norm(l:real^N)` THEN
9513     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT] THEN X_GEN_TAC `x:real` THEN
9514     STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
9515      [MATCH_MP_TAC IN_AFFINE_ADD_MUL THEN
9516       ASM_REWRITE_TAC[AFFINE_AFFINE_HULL] THEN
9517       ASM_MESON_TAC[SUBSET; HULL_SUBSET; RELATIVE_INTERIOR_SUBSET];
9518       REWRITE_TAC[NORM_ARITH `dist(a + x:real^N,a) = norm x`] THEN
9519       ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LT_RDIV_EQ; NORM_POS_LT] THEN
9520       ASM_REAL_ARITH_TAC];
9521     ALL_TAC] THEN
9522   ANTS_TAC THENL
9523    [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
9524     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[REAL_NOT_LT; REAL_LT_IMP_LE]] THEN
9525     FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N` o
9526        MATCH_MP BOUNDED_SUBSET_BALL) THEN
9527     REWRITE_TAC[SUBSET; IN_BALL] THEN
9528     DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
9529     EXISTS_TAC `B / norm(l:real^N)` THEN
9530     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT] THEN
9531     DISCH_THEN(MP_TAC o MATCH_MP
9532      (REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET)) THEN
9533     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE BINDER_CONV
9534      [GSYM CONTRAPOS_THM]) THEN
9535     REWRITE_TAC[REAL_NOT_LT] THEN DISCH_THEN MATCH_MP_TAC THEN
9536     REWRITE_TAC[NORM_ARITH `dist(a:real^N,a + x) = norm x`] THEN
9537     ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM;
9538                  REAL_DIV_RMUL; NORM_EQ_0] THEN
9539     ASM_REAL_ARITH_TAC;
9540     REWRITE_TAC[IN_ELIM_THM] THEN
9541     DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "1") (LABEL_TAC "2")) THEN
9542     EXISTS_TAC `d:real` THEN
9543     MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
9544      [MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `k:real` THEN
9545       ASM_MESON_TAC[REAL_NOT_LT; REAL_LT_IMP_LE];
9546       DISCH_TAC] THEN
9547     MATCH_MP_TAC(TAUT `b /\ (b ==> a) ==> a /\ b`) THEN CONJ_TAC THENL
9548      [REWRITE_TAC[REAL_LE_LT] THEN
9549       ASM_MESON_TAC[VECTOR_ARITH `a + &0 % l:real^N = a`;
9550                     REAL_NOT_LT; REAL_LT_IMP_LE];
9551       DISCH_TAC] THEN
9552     REWRITE_TAC[IN_DIFF] THEN CONJ_TAC THENL
9553      [REWRITE_TAC[CLOSURE_APPROACHABLE] THEN
9554       X_GEN_TAC `x:real` THEN DISCH_TAC THEN
9555       EXISTS_TAC `a + (d - min d (x / &2 / norm(l:real^N))) % l` THEN
9556       CONJ_TAC THENL
9557        [MATCH_MP_TAC(REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET) THEN
9558         FIRST_X_ASSUM MATCH_MP_TAC THEN
9559         CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
9560         MATCH_MP_TAC(REAL_ARITH `&0 < x /\ &0 < d ==> d - min d x < d`) THEN
9561         ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT];
9562         REWRITE_TAC[NORM_ARITH `dist(a + x:real^N,a + y) = norm(x - y)`] THEN
9563         REWRITE_TAC[GSYM VECTOR_SUB_RDISTRIB; NORM_MUL] THEN
9564         ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT] THEN
9565         MATCH_MP_TAC(REAL_ARITH
9566          `&0 < x /\ x < y /\ &0 < d ==> abs((d - min d x) - d) < y`) THEN
9567         REWRITE_TAC[REAL_ARITH `x / &2 / y < x / y <=> &0 < x / y`] THEN
9568         ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT]];
9569       DISCH_TAC THEN
9570       MP_TAC(ISPEC `s:real^N->bool` OPEN_IN_RELATIVE_INTERIOR) THEN
9571       REWRITE_TAC[open_in; GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
9572       DISCH_THEN(MP_TAC o SPEC `a + d % l:real^N` o CONJUNCT2) THEN
9573       ASM_REWRITE_TAC[] THEN
9574       DISCH_THEN(X_CHOOSE_THEN `e:real`
9575        (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "3"))) THEN
9576       REMOVE_THEN "2" (MP_TAC o SPEC `d + e / norm(l:real^N)`) THEN
9577       ASM_SIMP_TAC[NOT_IMP; REAL_ARITH `~(d + l <= d) <=> &0 < l`;
9578                    REAL_LT_DIV; NORM_POS_LT] THEN
9579       X_GEN_TAC `x:real` THEN
9580       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9581       ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
9582       REWRITE_TAC[REAL_NOT_LE] THEN DISCH_TAC THEN
9583       ASM_CASES_TAC `x < d` THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN
9584       REMOVE_THEN "3" MATCH_MP_TAC THEN CONJ_TAC THENL
9585        [MATCH_MP_TAC IN_AFFINE_ADD_MUL THEN
9586         ASM_REWRITE_TAC[AFFINE_AFFINE_HULL] THEN
9587         ASM_MESON_TAC[SUBSET; HULL_SUBSET; RELATIVE_INTERIOR_SUBSET];
9588         REWRITE_TAC[NORM_ARITH `dist(a + x:real^N,a + y) = norm(x - y)`] THEN
9589         REWRITE_TAC[GSYM VECTOR_SUB_RDISTRIB; NORM_MUL] THEN
9590         ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT] THEN
9591         ASM_REAL_ARITH_TAC]]]);;
9592
9593 let RAY_TO_FRONTIER = prove
9594  (`!s a l:real^N.
9595         bounded s /\ a IN interior s /\ ~(l = vec 0)
9596         ==> ?d. &0 < d /\ (a + d % l) IN frontier s /\
9597                 !e. &0 <= e /\ e < d ==> (a + e % l) IN interior s`,
9598   REPEAT STRIP_TAC THEN REWRITE_TAC[frontier] THEN
9599   SUBGOAL_THEN `interior s:real^N->bool = relative_interior s` SUBST1_TAC THENL
9600    [ALL_TAC;
9601     REWRITE_TAC[GSYM relative_frontier] THEN
9602     MATCH_MP_TAC RAY_TO_RELATIVE_FRONTIER THEN ASM_REWRITE_TAC[]] THEN
9603   ASM_MESON_TAC[NOT_IN_EMPTY; RELATIVE_INTERIOR_NONEMPTY_INTERIOR; IN_UNIV;
9604                 AFFINE_HULL_NONEMPTY_INTERIOR]);;
9605
9606 let RELATIVE_FRONTIER_NOT_SING = prove
9607  (`!s a:real^N. bounded s ==> ~(relative_frontier s = {a})`,
9608   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9609   ASM_REWRITE_TAC[RELATIVE_FRONTIER_EMPTY; NOT_INSERT_EMPTY] THEN
9610   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9611   DISCH_THEN(X_CHOOSE_TAC `z:real^N`) THEN
9612   ASM_CASES_TAC `s = {z:real^N}` THEN
9613   ASM_REWRITE_TAC[RELATIVE_FRONTIER_SING; NOT_INSERT_EMPTY] THEN
9614   SUBGOAL_THEN `?w:real^N. w IN s /\ ~(w = z)` STRIP_ASSUME_TAC THENL
9615    [ASM SET_TAC[]; REPEAT STRIP_TAC] THEN
9616   SUBGOAL_THEN
9617     `~((w:real^N) IN relative_frontier s /\ z IN relative_frontier s)`
9618   MP_TAC THENL [ASM SET_TAC[]; DISCH_TAC] THEN
9619   MAP_EVERY UNDISCH_TAC
9620    [`relative_frontier s = {a:real^N}`; `bounded(s:real^N->bool)`;
9621     `~(w:real^N = z)`; `(z:real^N) IN s`; `(w:real^N) IN s`;
9622     `~((w:real^N) IN relative_frontier s /\ z IN relative_frontier s)`] THEN
9623   POP_ASSUM_LIST(K ALL_TAC) THEN REWRITE_TAC[DE_MORGAN_THM] THEN
9624   MAP_EVERY (fun t -> SPEC_TAC(t,t)) [`z:real^N`; `w:real^N`] THEN
9625   MATCH_MP_TAC(MESON[]
9626    `(!w z. Q w z <=> Q z w) /\ (!w z. P z ==> Q w z)
9627     ==> !w z. P w \/ P z ==> Q w z`) THEN
9628   CONJ_TAC THENL [MESON_TAC[]; REPEAT GEN_TAC] THEN
9629   DISCH_THEN(fun th -> REPEAT STRIP_TAC THEN MP_TAC th) THEN
9630   REWRITE_TAC[relative_frontier; IN_DIFF] THEN
9631   CONJ_TAC THENL [ASM_MESON_TAC[SUBSET; CLOSURE_SUBSET]; DISCH_TAC] THEN
9632   MP_TAC(GEN `d:real`
9633    (ISPECL [`s:real^N->bool`; `z:real^N`; `d % (w - z):real^N`]
9634    RAY_TO_RELATIVE_FRONTIER)) THEN
9635   ASM_SIMP_TAC[VECTOR_SUB_EQ; IN_AFFINE_ADD_MUL_DIFF; AFFINE_AFFINE_HULL;
9636                HULL_INC; VECTOR_MUL_EQ_0] THEN
9637   DISCH_THEN(fun th -> MP_TAC(SPEC `&1` th) THEN MP_TAC(SPEC `--(&1)` th)) THEN
9638   CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[IN_SING] THEN
9639   DISCH_THEN(X_CHOOSE_THEN `e:real` (STRIP_ASSUME_TAC o GSYM)) THEN
9640   ASM_REWRITE_TAC[VECTOR_MUL_RCANCEL; VECTOR_MUL_ASSOC; VECTOR_SUB_EQ;
9641                   VECTOR_ARITH `a + x:real^N = a + y <=> x = y`] THEN
9642   ASM_REAL_ARITH_TAC);;
9643
9644 let RELATIVE_INTERIOR_PCROSS = prove
9645  (`!s:real^M->bool t:real^N->bool.
9646         relative_interior(s PCROSS t) =
9647         relative_interior s PCROSS relative_interior t`,
9648   REPEAT STRIP_TAC THEN MAP_EVERY ASM_CASES_TAC
9649    [`s:real^M->bool = {}`; `t:real^N->bool = {}`] THEN
9650   ASM_REWRITE_TAC[PCROSS_EMPTY; RELATIVE_INTERIOR_EMPTY] THEN
9651   REWRITE_TAC[relative_interior; AFFINE_HULL_PCROSS] THEN
9652   REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_THM;
9653               PASTECART_IN_PCROSS] THEN
9654   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^N`] THEN EQ_TAC THENL
9655    [ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> r /\ q /\ p`] THEN
9656     DISCH_THEN(X_CHOOSE_THEN `u:real^(M,N)finite_sum->bool`
9657      (CONJUNCTS_THEN ASSUME_TAC)) THEN
9658     FIRST_ASSUM(MP_TAC o MATCH_MP PASTECART_IN_INTERIOR_SUBTOPOLOGY) THEN
9659     REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN
9660     REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
9661     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
9662     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
9663     W(MP_TAC o PART_MATCH (funpow 3 rand) SUBSET_PCROSS o snd) THEN
9664     ASM SET_TAC[];
9665     DISCH_THEN(CONJUNCTS_THEN2
9666      (X_CHOOSE_THEN `v:real^M->bool` STRIP_ASSUME_TAC)
9667      (X_CHOOSE_THEN `w:real^N->bool` STRIP_ASSUME_TAC)) THEN
9668     EXISTS_TAC `(v:real^M->bool) PCROSS (w:real^N->bool)` THEN
9669     ASM_SIMP_TAC[PASTECART_IN_PCROSS; SUBSET_PCROSS; OPEN_IN_PCROSS]]);;
9670
9671 let RELATIVE_FRONTIER_EQ_EMPTY = prove
9672  (`!s:real^N->bool. relative_frontier s = {} <=> affine s`,
9673   GEN_TAC THEN REWRITE_TAC[relative_frontier] THEN
9674   REWRITE_TAC[GSYM RELATIVE_INTERIOR_EQ_CLOSURE] THEN
9675   MP_TAC(ISPEC `s:real^N->bool` RELATIVE_INTERIOR_SUBSET) THEN
9676   MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[]);;
9677
9678 let DIAMETER_BOUNDED_BOUND_LT = prove
9679  (`!s x y:real^N.
9680         bounded s /\ x IN relative_interior s /\ y IN closure s /\
9681         ~(diameter s = &0)
9682         ==> norm(x - y) < diameter s`,
9683   let lemma = prove
9684    (`!s x y:real^N.
9685           bounded s /\ x IN relative_interior s /\ y IN s /\
9686           ~(diameter s = &0)
9687           ==> norm(x - y) < diameter s`,
9688     REPEAT STRIP_TAC THEN FIRST_X_ASSUM
9689      (MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR_CBALL]) THEN
9690     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `e:real`
9691      STRIP_ASSUME_TAC)) THEN
9692     ASM_SIMP_TAC[REAL_LT_LE; DIAMETER_BOUNDED_BOUND] THEN
9693     ASM_CASES_TAC `y:real^N = x` THEN
9694     ASM_SIMP_TAC[VECTOR_SUB_REFL; NORM_0] THEN
9695     DISCH_TAC THEN
9696     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
9697     DISCH_THEN(MP_TAC o SPEC `x + e / norm(x - y) % (x - y):real^N`) THEN
9698     REWRITE_TAC[NOT_IMP; IN_INTER] THEN REPEAT CONJ_TAC THENL
9699      [REWRITE_TAC[IN_CBALL; NORM_ARITH `dist(x:real^M,x + y) = norm y`] THEN
9700       ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL;
9701                    NORM_EQ_0; VECTOR_SUB_EQ] THEN ASM_REAL_ARITH_TAC;
9702       MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
9703       ASM_SIMP_TAC[HULL_INC; AFFINE_AFFINE_HULL];
9704       DISCH_TAC THEN MP_TAC(ISPECL
9705        [`s:real^N->bool`; `x + e / norm(x - y) % (x - y):real^N`; `y:real^N`]
9706           DIAMETER_BOUNDED_BOUND) THEN
9707       ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
9708       REWRITE_TAC[VECTOR_ARITH
9709        `(x + e % (x - y)) - y:real^N = (&1 + e) % (x - y)`] THEN
9710       SIMP_TAC[NORM_MUL; REAL_ARITH `~(a * n <= n) <=> &0 < n * (a - &1)`] THEN
9711       MATCH_MP_TAC REAL_LT_MUL THEN
9712       ASM_REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
9713       MATCH_MP_TAC(REAL_ARITH `&0 < e ==> &0 < abs(&1 + e) - &1`) THEN
9714       MATCH_MP_TAC REAL_LT_DIV THEN
9715       ASM_REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ]]) in
9716   REPEAT STRIP_TAC THEN
9717   MP_TAC(ISPECL [`closure s:real^N->bool`; `x:real^N`; `y:real^N`]
9718         lemma) THEN
9719   ASM_SIMP_TAC[DIAMETER_CLOSURE; BOUNDED_CLOSURE] THEN
9720   DISCH_THEN MATCH_MP_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
9721    (SET_RULE `x IN s ==> s SUBSET t ==> x IN t`)) THEN
9722   MATCH_MP_TAC SUBSET_RELATIVE_INTERIOR THEN
9723   REWRITE_TAC[CLOSURE_SUBSET; AFFINE_HULL_CLOSURE]);;
9724
9725 let DIAMETER_ATTAINED_RELATIVE_FRONTIER = prove
9726  (`!s:real^N->bool.
9727         bounded s /\ ~(diameter s = &0)
9728         ==> ?x y. x IN relative_frontier s /\
9729                   y IN relative_frontier s /\
9730                   norm(x - y) = diameter s`,
9731   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9732   ASM_REWRITE_TAC[DIAMETER_EMPTY; relative_frontier] THEN REPEAT STRIP_TAC THEN
9733   MP_TAC(ISPEC `closure s:real^N->bool` DIAMETER_COMPACT_ATTAINED) THEN
9734   ASM_SIMP_TAC[COMPACT_CLOSURE; CLOSURE_EQ_EMPTY; DIAMETER_CLOSURE] THEN
9735   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
9736   STRIP_TAC THEN ASM_REWRITE_TAC[IN_DIFF] THEN REPEAT STRIP_TAC THEN
9737   MP_TAC(ISPEC `s:real^N->bool` DIAMETER_BOUNDED_BOUND_LT) THENL
9738    [DISCH_THEN(MP_TAC o SPECL [`x:real^N`; `y:real^N`]);
9739     DISCH_THEN(MP_TAC o SPECL [`y:real^N`; `x:real^N`])] THEN
9740   ASM_MESON_TAC[REAL_LT_REFL; NORM_SUB]);;
9741
9742 let DIAMETER_RELATIVE_FRONTIER = prove
9743  (`!s:real^N->bool.
9744         bounded s /\ ~(?a. s = {a})
9745         ==> diameter(relative_frontier s) = diameter s`,
9746   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9747   ASM_REWRITE_TAC[RELATIVE_FRONTIER_EMPTY] THEN
9748   REWRITE_TAC[relative_frontier] THEN
9749   ASM_SIMP_TAC[GSYM DIAMETER_CLOSURE; GSYM REAL_LE_ANTISYM] THEN
9750   ASM_SIMP_TAC[SUBSET_DIFF; DIAMETER_SUBSET; BOUNDED_CLOSURE] THEN
9751   ASM_SIMP_TAC[DIAMETER_CLOSURE] THEN
9752   MP_TAC(ISPEC `s:real^N->bool` DIAMETER_ATTAINED_RELATIVE_FRONTIER) THEN
9753   ASM_SIMP_TAC[DIAMETER_EQ_0; relative_frontier] THEN STRIP_TAC THEN
9754   FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN MATCH_MP_TAC DIAMETER_BOUNDED_BOUND THEN
9755   ASM_SIMP_TAC[BOUNDED_CLOSURE; BOUNDED_DIFF]);;
9756
9757 let DIAMETER_ATTAINED_FRONTIER = prove
9758  (`!s:real^N->bool.
9759         bounded s /\ ~(diameter s = &0)
9760         ==> ?x y. x IN frontier s /\ y IN frontier s /\
9761                   norm(x - y) = diameter s`,
9762   REPEAT GEN_TAC THEN
9763   DISCH_THEN(MP_TAC o MATCH_MP DIAMETER_ATTAINED_RELATIVE_FRONTIER) THEN
9764   REWRITE_TAC[frontier; relative_frontier; IN_DIFF] THEN
9765   MESON_TAC[REWRITE_RULE[SUBSET] INTERIOR_SUBSET_RELATIVE_INTERIOR]);;
9766
9767 let DIAMETER_FRONTIER = prove
9768  (`!s:real^N->bool. bounded s ==> diameter(frontier s) = diameter s`,
9769   REPEAT STRIP_TAC THEN ASM_CASES_TAC `?a:real^N. s = {a}` THENL
9770    [ASM_MESON_TAC[FRONTIER_SING]; ALL_TAC] THEN
9771   MATCH_MP_TAC(REAL_ARITH
9772    `!r. r <= f /\ f <= s /\ r = s ==> f = s`) THEN
9773   EXISTS_TAC `diameter(closure s DIFF relative_interior s:real^N->bool)` THEN
9774   REPEAT CONJ_TAC THENL
9775    [ASM_SIMP_TAC[GSYM DIAMETER_CLOSURE] THEN MATCH_MP_TAC DIAMETER_SUBSET THEN
9776     ASM_SIMP_TAC[BOUNDED_FRONTIER] THEN REWRITE_TAC[frontier] THEN
9777     MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET_RELATIVE_INTERIOR) THEN
9778     SET_TAC[];
9779     ASM_SIMP_TAC[GSYM DIAMETER_CLOSURE] THEN MATCH_MP_TAC DIAMETER_SUBSET THEN
9780     ASM_SIMP_TAC[BOUNDED_CLOSURE; frontier; SUBSET_DIFF];
9781     ASM_SIMP_TAC[DIAMETER_RELATIVE_FRONTIER; GSYM relative_frontier]]);;
9782
9783 let DIAMETER_SPHERE = prove
9784  (`!a:real^N r. diameter(sphere(a,r)) = if r < &0 then &0 else &2 * r`,
9785   REWRITE_TAC[GSYM FRONTIER_CBALL] THEN
9786   ASM_SIMP_TAC[DIAMETER_FRONTIER; BOUNDED_CBALL; DIAMETER_CBALL]);;
9787
9788 let CLOSEST_POINT_IN_RELATIVE_INTERIOR = prove
9789  (`!s x:real^N.
9790         closed s /\ ~(s = {}) /\ x IN affine hull s
9791         ==> ((closest_point s x) IN relative_interior s <=>
9792              x IN relative_interior s)`,
9793   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THEN
9794   ASM_SIMP_TAC[CLOSEST_POINT_SELF] THEN
9795   MATCH_MP_TAC(TAUT `~q /\ ~p ==> (p <=> q)`) THEN CONJ_TAC THENL
9796    [ASM_MESON_TAC[RELATIVE_INTERIOR_SUBSET; SUBSET]; STRIP_TAC] THEN
9797   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR_CBALL]) THEN
9798   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9799   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
9800   SUBGOAL_THEN `~(closest_point s (x:real^N) = x)` ASSUME_TAC THENL
9801    [ASM_MESON_TAC[]; ALL_TAC] THEN
9802   MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`;
9803    `closest_point s x -
9804     (min (&1) (e / norm(closest_point s x - x))) %
9805     (closest_point s x - x):real^N`]
9806     CLOSEST_POINT_LE) THEN
9807   ASM_REWRITE_TAC[dist; NOT_IMP; VECTOR_ARITH
9808    `x - (y - e % (y - x)):real^N = (&1 - e) % (x - y)`] THEN
9809   CONJ_TAC THENL
9810    [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
9811     REWRITE_TAC[IN_CBALL; IN_INTER] THEN CONJ_TAC THENL
9812      [REWRITE_TAC[NORM_ARITH `dist(a:real^N,a - x) = norm x`] THEN
9813       REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
9814       ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
9815       MATCH_MP_TAC(REAL_ARITH `&0 <= a ==> abs(min (&1) a) <= a`) THEN
9816       ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LE_DIV; NORM_POS_LE];
9817       MATCH_MP_TAC IN_AFFINE_SUB_MUL_DIFF THEN
9818       ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC]];
9819     REWRITE_TAC[NORM_MUL; REAL_ARITH
9820      `~(n <= a * n) <=> &0 < (&1 - a) * n`] THEN
9821     MATCH_MP_TAC REAL_LT_MUL THEN
9822     ASM_SIMP_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
9823     MATCH_MP_TAC(REAL_ARITH
9824      `&0 < e /\ e <= &1 ==> &0 < &1 - abs(&1 - e)`) THEN
9825     REWRITE_TAC[REAL_MIN_LE; REAL_LT_MIN; REAL_LT_01; REAL_LE_REFL] THEN
9826     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ]]);;
9827
9828 let CLOSEST_POINT_IN_RELATIVE_FRONTIER = prove
9829  (`!s x:real^N.
9830         closed s /\ ~(s = {}) /\ x IN affine hull s DIFF relative_interior s
9831         ==> closest_point s x IN relative_frontier s`,
9832   SIMP_TAC[relative_frontier; IN_DIFF; CLOSEST_POINT_IN_RELATIVE_INTERIOR] THEN
9833   MESON_TAC[CLOSURE_SUBSET; CLOSEST_POINT_IN_SET; SUBSET]);;
9834
9835 (* ------------------------------------------------------------------------- *)
9836 (* Interior, relative interior and closure interrelations.                   *)
9837 (* ------------------------------------------------------------------------- *)
9838
9839 let CONVEX_CLOSURE_INTERIOR = prove
9840  (`!s:real^N->bool.
9841         convex s /\ ~(interior s = {})
9842         ==> closure(interior s) = closure s`,
9843   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9844   SIMP_TAC[SUBSET_CLOSURE; INTERIOR_SUBSET] THEN
9845   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9846   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN REWRITE_TAC[SUBSET] THEN
9847   X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN ASM_CASES_TAC `b:real^N = a` THENL
9848    [ASM_MESON_TAC[CLOSURE_SUBSET; SUBSET]; ALL_TAC] THEN
9849   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM] THEN DISJ2_TAC THEN
9850   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
9851   EXISTS_TAC `b - min (e / &2 / norm(b - a)) (&1) % (b - a):real^N` THEN
9852   REPEAT CONJ_TAC THENL
9853    [MATCH_MP_TAC IN_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
9854     ASM_REWRITE_TAC[REAL_MIN_LE; REAL_LT_MIN; REAL_LE_REFL; REAL_LT_01];
9855     REWRITE_TAC[VECTOR_ARITH `b - x:real^N = b <=> x = vec 0`] THEN
9856     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
9857     MATCH_MP_TAC(REAL_ARITH `&0 < x ==> ~(min x (&1) = &0)`);
9858     REWRITE_TAC[NORM_ARITH `dist(b - x:real^N,b) = norm x`] THEN
9859     REWRITE_TAC[NORM_MUL] THEN MATCH_MP_TAC REAL_LET_TRANS THEN
9860     EXISTS_TAC `e / &2 / norm(b - a:real^N) * norm(b - a)` THEN CONJ_TAC THENL
9861      [MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[NORM_POS_LE] THEN
9862       MATCH_MP_TAC(REAL_ARITH `&0 < x ==> abs(min x (&1)) <= x`);
9863       ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_POS_LT; REAL_LT_IMP_NZ;
9864                    VECTOR_SUB_EQ] THEN
9865       ASM_REAL_ARITH_TAC]] THEN
9866   ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; REAL_OF_NUM_LT;
9867                  VECTOR_SUB_EQ; ARITH]);;
9868
9869 let EMPTY_INTERIOR_SUBSET_HYPERPLANE = prove
9870  (`!s. convex s /\ interior s = {}
9871        ==> ?a:real^N b. ~(a = vec 0) /\ s SUBSET {x | a dot x = b}`,
9872   let lemma = prove
9873    (`!s. convex s /\ (vec 0) IN s /\ interior s = {}
9874          ==> ?a:real^N b. ~(a = vec 0) /\ s SUBSET {x | a dot x = b}`,
9875     GEN_TAC THEN
9876     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
9877     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
9878     SUBGOAL_THEN `~(relative_interior(s:real^N->bool) = {})` MP_TAC THENL
9879      [ASM_MESON_TAC[RELATIVE_INTERIOR_EQ_EMPTY; MEMBER_NOT_EMPTY]; ALL_TAC] THEN
9880     ASM_REWRITE_TAC[CONTRAPOS_THM] THEN MATCH_MP_TAC EQ_IMP THEN
9881     AP_THM_TAC THEN AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN
9882     MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
9883     ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC] THEN
9884     ONCE_REWRITE_TAC[GSYM SPAN_UNIV] THEN MATCH_MP_TAC DIM_EQ_SPAN THEN
9885     REWRITE_TAC[SUBSET_UNIV; DIM_UNIV; GSYM NOT_LT] THEN
9886     DISCH_THEN(MP_TAC o MATCH_MP LOWDIM_SUBSET_HYPERPLANE) THEN
9887     DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
9888     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
9889     DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN
9890     ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN EXISTS_TAC `&0` THEN
9891     ASM_MESON_TAC[SUBSET_TRANS; SPAN_INC]) in
9892   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
9893    [ASM_MESON_TAC[EMPTY_SUBSET; BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1];
9894     ALL_TAC] THEN
9895   STRIP_TAC THEN
9896   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9897   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
9898   MP_TAC(ISPEC `IMAGE (\x:real^N. --a + x) s` lemma) THEN
9899   ASM_REWRITE_TAC[CONVEX_TRANSLATION_EQ; INTERIOR_TRANSLATION;
9900                   IMAGE_EQ_EMPTY; IN_IMAGE; UNWIND_THM2;
9901                   VECTOR_ARITH `vec 0:real^N = --a + x <=> x = a`] THEN
9902   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `c:real^N` THEN
9903   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM; DOT_RADD] THEN
9904   MESON_TAC[REAL_ARITH `a + x:real = b <=> x = b - a`]);;
9905
9906 let CONVEX_INTERIOR_CLOSURE = prove
9907  (`!s:real^N->bool. convex s ==> interior(closure s) = interior s`,
9908   REPEAT STRIP_TAC THEN
9909   ASM_CASES_TAC `interior(s:real^N->bool) = {}` THENL
9910    [MP_TAC(ISPEC `s:real^N->bool` EMPTY_INTERIOR_SUBSET_HYPERPLANE) THEN
9911     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
9912     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN STRIP_TAC THEN
9913     MATCH_MP_TAC(SET_RULE `!t. s SUBSET t /\ t = {} ==> s = {}`) THEN
9914     EXISTS_TAC `interior {x:real^N | a dot x = b}` THEN CONJ_TAC THENL
9915      [ALL_TAC;  ASM_SIMP_TAC[INTERIOR_HYPERPLANE]] THEN
9916     MATCH_MP_TAC SUBSET_INTERIOR THEN MATCH_MP_TAC CLOSURE_MINIMAL THEN
9917     ASM_REWRITE_TAC[CLOSED_HYPERPLANE];
9918     ALL_TAC] THEN
9919   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9920   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
9921   MATCH_MP_TAC SUBSET_ANTISYM THEN
9922   SIMP_TAC[SUBSET_INTERIOR; CLOSURE_SUBSET] THEN
9923   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN
9924   MP_TAC(ASSUME `(b:real^N) IN interior(closure s)`) THEN
9925   GEN_REWRITE_TAC LAND_CONV [IN_INTERIOR_CBALL] THEN
9926   REWRITE_TAC[SUBSET; IN_CBALL; LEFT_IMP_EXISTS_THM] THEN
9927   X_GEN_TAC `e:real` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9928   ASM_CASES_TAC `b:real^N = a` THEN ASM_REWRITE_TAC[] THEN
9929   DISCH_THEN(MP_TAC o SPEC `b + e / norm(b - a) % (b - a):real^N`) THEN
9930   ASM_SIMP_TAC[NORM_ARITH `dist(b:real^N,b + e) = norm e`; NORM_MUL;
9931     REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ;
9932     REAL_ARITH `&0 < e ==> abs e <= e`] THEN
9933   DISCH_TAC THEN
9934   SUBGOAL_THEN
9935    `b = (b + e / norm(b - a) % (b - a)) -
9936         e / norm(b - a) / (&1 + e / norm(b - a)) %
9937         ((b + e / norm(b - a) % (b - a)) - a):real^N`
9938   SUBST1_TAC THENL
9939    [REWRITE_TAC[VECTOR_ARITH
9940      `b = (b + e % (b - a)) - d % ((b + e % (b - a)) - a) <=>
9941       (e - d * (&1 + e)) % (b - a) = vec 0`] THEN
9942     ASM_REWRITE_TAC[VECTOR_SUB_EQ; VECTOR_MUL_EQ_0];
9943     MATCH_MP_TAC IN_INTERIOR_CLOSURE_CONVEX_SHRINK] THEN
9944   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LT_DIV; NORM_POS_LT;
9945                VECTOR_SUB_EQ; REAL_ARITH `&0 < x ==> &0 < &1 + x`;
9946                REAL_ARITH `&0 < x ==> ~(&1 + x = &0)`;
9947                REAL_MUL_LID; REAL_ADD_RDISTRIB; REAL_DIV_RMUL;
9948                REAL_LT_IMP_NZ; REAL_LE_ADDL; NORM_POS_LE; REAL_SUB_REFL]);;
9949
9950 let FRONTIER_CLOSURE_CONVEX = prove
9951  (`!s:real^N->bool. convex s ==> frontier(closure s) = frontier s`,
9952   SIMP_TAC[frontier; CLOSURE_CLOSURE; CONVEX_INTERIOR_CLOSURE]);;
9953
9954 let CONVEX_CLOSURE_RELATIVE_INTERIOR = prove
9955  (`!s:real^N->bool.
9956         convex s ==> closure(relative_interior s) = closure s`,
9957   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9958   SIMP_TAC[SUBSET_CLOSURE; RELATIVE_INTERIOR_SUBSET] THEN
9959   ASM_CASES_TAC `relative_interior(s:real^N->bool) = {}` THENL
9960    [ASM_MESON_TAC[RELATIVE_INTERIOR_EQ_EMPTY; SUBSET_REFL]; ALL_TAC] THEN
9961   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9962   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN REWRITE_TAC[SUBSET] THEN
9963   X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN ASM_CASES_TAC `b:real^N = a` THENL
9964    [ASM_MESON_TAC[CLOSURE_SUBSET; SUBSET]; ALL_TAC] THEN
9965   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM] THEN DISJ2_TAC THEN
9966   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
9967   EXISTS_TAC `b - min (e / &2 / norm(b - a)) (&1) % (b - a):real^N` THEN
9968   REPEAT CONJ_TAC THENL
9969    [MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
9970     ASM_REWRITE_TAC[REAL_MIN_LE; REAL_LT_MIN; REAL_LE_REFL; REAL_LT_01];
9971     REWRITE_TAC[VECTOR_ARITH `b - x:real^N = b <=> x = vec 0`] THEN
9972     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
9973     MATCH_MP_TAC(REAL_ARITH `&0 < x ==> ~(min x (&1) = &0)`);
9974     REWRITE_TAC[NORM_ARITH `dist(b - x:real^N,b) = norm x`] THEN
9975     REWRITE_TAC[NORM_MUL] THEN MATCH_MP_TAC REAL_LET_TRANS THEN
9976     EXISTS_TAC `e / &2 / norm(b - a:real^N) * norm(b - a)` THEN CONJ_TAC THENL
9977      [MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[NORM_POS_LE] THEN
9978       MATCH_MP_TAC(REAL_ARITH `&0 < x ==> abs(min x (&1)) <= x`);
9979       ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_POS_LT; REAL_LT_IMP_NZ;
9980                    VECTOR_SUB_EQ] THEN
9981       ASM_REAL_ARITH_TAC]] THEN
9982   ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; REAL_OF_NUM_LT;
9983                  VECTOR_SUB_EQ; ARITH]);;
9984
9985 let AFFINE_HULL_RELATIVE_INTERIOR = prove
9986  (`!s. convex s
9987        ==> affine hull (relative_interior s) = affine hull s`,
9988   MESON_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR; AFFINE_HULL_CLOSURE]);;
9989
9990 let CONVEX_RELATIVE_INTERIOR_CLOSURE = prove
9991  (`!s:real^N->bool.
9992         convex s ==> relative_interior(closure s) = relative_interior s`,
9993   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9994   ASM_REWRITE_TAC[CLOSURE_EMPTY; RELATIVE_INTERIOR_EMPTY] THEN
9995   SUBGOAL_THEN `?a:real^N. a IN relative_interior s` STRIP_ASSUME_TAC THENL
9996    [ASM_SIMP_TAC[MEMBER_NOT_EMPTY; RELATIVE_INTERIOR_EQ_EMPTY];
9997     ALL_TAC] THEN
9998   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET] THEN CONJ_TAC THENL
9999    [ALL_TAC;
10000     REWRITE_TAC[IN_RELATIVE_INTERIOR; AFFINE_HULL_CLOSURE; SUBSET] THEN
10001     MESON_TAC[CLOSURE_SUBSET; SUBSET]] THEN
10002   X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN
10003   MP_TAC(ASSUME `(b:real^N) IN relative_interior(closure s)`) THEN
10004   GEN_REWRITE_TAC LAND_CONV [IN_RELATIVE_INTERIOR_CBALL] THEN
10005   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
10006   REWRITE_TAC[SUBSET; IN_CBALL; IN_INTER; LEFT_IMP_EXISTS_THM;
10007               AFFINE_HULL_CLOSURE] THEN
10008   X_GEN_TAC `e:real` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
10009   ASM_CASES_TAC `b:real^N = a` THEN ASM_REWRITE_TAC[] THEN
10010   DISCH_THEN(MP_TAC o SPEC `b + e / norm(b - a) % (b - a):real^N`) THEN
10011   ASM_SIMP_TAC[NORM_ARITH `dist(b:real^N,b + e) = norm e`; NORM_MUL;
10012     REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ;
10013     REAL_ARITH `&0 < e ==> abs e <= e`] THEN
10014   ANTS_TAC THENL
10015    [MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
10016     ASM_MESON_TAC[SUBSET; AFFINE_AFFINE_HULL; RELATIVE_INTERIOR_SUBSET;
10017                   CLOSURE_SUBSET_AFFINE_HULL; HULL_INC];
10018     ALL_TAC] THEN
10019   DISCH_TAC THEN
10020   SUBGOAL_THEN
10021    `b = (b + e / norm(b - a) % (b - a)) -
10022         e / norm(b - a) / (&1 + e / norm(b - a)) %
10023         ((b + e / norm(b - a) % (b - a)) - a):real^N`
10024   SUBST1_TAC THENL
10025    [REWRITE_TAC[VECTOR_ARITH
10026      `b = (b + e % (b - a)) - d % ((b + e % (b - a)) - a) <=>
10027       (e - d * (&1 + e)) % (b - a) = vec 0`] THEN
10028     ASM_REWRITE_TAC[VECTOR_SUB_EQ; VECTOR_MUL_EQ_0];
10029     MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK] THEN
10030   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LT_DIV; NORM_POS_LT;
10031                VECTOR_SUB_EQ; REAL_ARITH `&0 < x ==> &0 < &1 + x`;
10032                REAL_ARITH `&0 < x ==> ~(&1 + x = &0)`;
10033                REAL_MUL_LID; REAL_ADD_RDISTRIB; REAL_DIV_RMUL;
10034                REAL_LT_IMP_NZ; REAL_LE_ADDL; NORM_POS_LE; REAL_SUB_REFL]);;
10035
10036 let RELATIVE_FRONTIER_CLOSURE = prove
10037  (`!s. convex s ==> relative_frontier(closure s) = relative_frontier s`,
10038   SIMP_TAC[relative_frontier; CLOSURE_CLOSURE;
10039            CONVEX_RELATIVE_INTERIOR_CLOSURE]);;
10040
10041 let RELATIVE_FRONTIER_RELATIVE_INTERIOR = prove
10042  (`!s:real^N->bool.
10043         convex s
10044         ==> relative_frontier(relative_interior s) = relative_frontier s`,
10045   ASM_MESON_TAC[RELATIVE_FRONTIER_CLOSURE; CONVEX_CLOSURE_RELATIVE_INTERIOR;
10046                 CONVEX_RELATIVE_INTERIOR]);;
10047
10048 let CONNECTED_INTER_RELATIVE_FRONTIER = prove
10049  (`!s t:real^N->bool.
10050         connected s /\ s SUBSET affine hull t /\
10051         ~(s INTER t = {}) /\ ~(s DIFF t = {})
10052         ==> ~(s INTER relative_frontier t = {})`,
10053   REWRITE_TAC[relative_frontier] THEN REPEAT STRIP_TAC THEN
10054   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONNECTED_OPEN_IN]) THEN
10055   REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
10056    [`s INTER relative_interior t:real^N->bool`;
10057     `s DIFF closure t:real^N->bool`] THEN
10058   REPEAT CONJ_TAC THENL
10059    [MATCH_MP_TAC OPEN_IN_SUBTOPOLOGY_INTER_SUBSET THEN
10060     EXISTS_TAC `affine hull t:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
10061     MATCH_MP_TAC OPEN_IN_INTER THEN
10062     REWRITE_TAC[OPEN_IN_RELATIVE_INTERIOR; OPEN_IN_SUBTOPOLOGY_REFL] THEN
10063     REWRITE_TAC[TOPSPACE_EUCLIDEAN; SUBSET_UNIV];
10064     ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
10065     MATCH_MP_TAC OPEN_IN_OPEN_INTER THEN
10066     REWRITE_TAC[GSYM closed; CLOSED_CLOSURE];
10067     ASM SET_TAC[];
10068     MATCH_MP_TAC(SET_RULE
10069      `i SUBSET t /\ t SUBSET c ==> (s INTER i) INTER (s DIFF c) = {}`) THEN
10070     REWRITE_TAC[RELATIVE_INTERIOR_SUBSET; CLOSURE_SUBSET];
10071     MP_TAC(ISPEC `t:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
10072     MP_TAC(ISPEC `t:real^N->bool` RELATIVE_INTERIOR_SUBSET) THEN
10073     ASM SET_TAC[]]);;
10074
10075 let CLOSED_RELATIVE_FRONTIER = prove
10076  (`!s:real^N->bool. closed(relative_frontier s)`,
10077   REPEAT GEN_TAC THEN REWRITE_TAC[relative_frontier] THEN
10078   MATCH_MP_TAC CLOSED_IN_CLOSED_TRANS THEN
10079   EXISTS_TAC `affine hull s:real^N->bool` THEN
10080   REWRITE_TAC[CLOSED_AFFINE_HULL] THEN MATCH_MP_TAC CLOSED_IN_DIFF THEN
10081   REWRITE_TAC[OPEN_IN_RELATIVE_INTERIOR] THEN
10082   MATCH_MP_TAC CLOSED_SUBSET THEN REWRITE_TAC[CLOSED_CLOSURE] THEN
10083   MATCH_MP_TAC(SET_RULE
10084    `s SUBSET closure t /\ closure t = t ==> s SUBSET t`) THEN
10085   SIMP_TAC[SUBSET_CLOSURE; HULL_SUBSET; CLOSURE_EQ; CLOSED_AFFINE_HULL]);;
10086
10087 let CLOSED_RELATIVE_BOUNDARY = prove
10088  (`!s. closed s ==> closed(s DIFF relative_interior s)`,
10089   MESON_TAC[CLOSED_RELATIVE_FRONTIER; relative_frontier; CLOSURE_CLOSED]);;
10090
10091 let COMPACT_RELATIVE_BOUNDARY = prove
10092  (`!s. compact s ==> compact(s DIFF relative_interior s)`,
10093   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_RELATIVE_BOUNDARY;
10094            BOUNDED_DIFF]);;
10095
10096 let BOUNDED_RELATIVE_FRONTIER = prove
10097  (`!s:real^N->bool. bounded s ==> bounded(relative_frontier s)`,
10098   REWRITE_TAC[relative_frontier] THEN
10099   MESON_TAC[BOUNDED_CLOSURE; BOUNDED_SUBSET; SUBSET_DIFF]);;
10100
10101 let COMPACT_RELATIVE_FRONTIER_BOUNDED = prove
10102  (`!s:real^N->bool. bounded s ==> compact(relative_frontier s)`,
10103   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_RELATIVE_FRONTIER;
10104            BOUNDED_RELATIVE_FRONTIER]);;
10105
10106 let COMPACT_RELATIVE_FRONTIER = prove
10107  (`!s:real^N->bool. compact s ==> compact(relative_frontier s)`,
10108   SIMP_TAC[COMPACT_RELATIVE_FRONTIER_BOUNDED; COMPACT_IMP_BOUNDED]);;
10109
10110 let CONVEX_SAME_RELATIVE_INTERIOR_CLOSURE = prove
10111  (`!s t. convex s /\ convex t
10112          ==> (relative_interior s = relative_interior t <=>
10113               closure s = closure t)`,
10114   MESON_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR;
10115             CONVEX_RELATIVE_INTERIOR_CLOSURE]);;
10116
10117 let CONVEX_SAME_RELATIVE_INTERIOR_CLOSURE_STRADDLE = prove
10118  (`!s t. convex s /\ convex t
10119          ==> (relative_interior s = relative_interior t <=>
10120               relative_interior s SUBSET t /\ t SUBSET closure s)`,
10121   MESON_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR;
10122             CONVEX_RELATIVE_INTERIOR_CLOSURE; SUBSET_CLOSURE;
10123                 SUBSET_ANTISYM; RELATIVE_INTERIOR_SUBSET;
10124                 CLOSURE_SUBSET; CLOSURE_CLOSURE]);;
10125
10126 let RELATIVE_INTERIOR_LINEAR_IMAGE_CONVEX = prove
10127  (`!f:real^M->real^N s.
10128         linear f /\ convex s
10129         ==> relative_interior(IMAGE f s) = IMAGE f (relative_interior s)`,
10130   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
10131    [SUBGOAL_THEN
10132      `relative_interior (IMAGE f (relative_interior s)) =
10133       relative_interior (IMAGE (f:real^M->real^N) s)`
10134      (fun th -> REWRITE_TAC[SYM th; RELATIVE_INTERIOR_SUBSET]) THEN
10135     ASM_SIMP_TAC[CONVEX_SAME_RELATIVE_INTERIOR_CLOSURE_STRADDLE;
10136                  CONVEX_RELATIVE_INTERIOR; CONVEX_LINEAR_IMAGE] THEN
10137     CONJ_TAC THENL
10138      [MATCH_MP_TAC SUBSET_TRANS THEN
10139       EXISTS_TAC `IMAGE (f:real^M->real^N) (relative_interior s)` THEN
10140       SIMP_TAC[RELATIVE_INTERIOR_SUBSET; IMAGE_SUBSET];
10141       MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC
10142         `IMAGE (f:real^M->real^N) (closure(relative_interior s))` THEN
10143       ASM_SIMP_TAC[CLOSURE_LINEAR_IMAGE_SUBSET] THEN
10144       ASM_SIMP_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR] THEN
10145       MATCH_MP_TAC IMAGE_SUBSET THEN REWRITE_TAC[CLOSURE_SUBSET]];
10146     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN X_GEN_TAC `z:real^M` THEN
10147     DISCH_TAC THEN
10148     ASM_SIMP_TAC[RELATIVE_INTERIOR_CONVEX_PROLONG; CONVEX_LINEAR_IMAGE] THEN
10149     REWRITE_TAC[IN_ELIM_THM; FORALL_IN_IMAGE] THEN CONJ_TAC THENL
10150      [MATCH_MP_TAC FUN_IN_IMAGE THEN
10151       ASM_MESON_TAC[SUBSET; RELATIVE_INTERIOR_SUBSET];
10152       ALL_TAC] THEN
10153     X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
10154     MP_TAC(ISPECL [`s:real^M->bool`; `z:real^M`; `x:real^M`]
10155         RELATIVE_INTERIOR_PROLONG) THEN ASM_REWRITE_TAC[] THEN
10156     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real` THEN
10157     MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
10158     DISCH_THEN(MP_TAC o ISPEC `f:real^M->real^N` o MATCH_MP FUN_IN_IMAGE) THEN
10159     ASM_MESON_TAC[LINEAR_ADD; LINEAR_SUB; LINEAR_CMUL]]);;
10160
10161 let CLOSURE_INTERS_CONVEX = prove
10162  (`!f:(real^N->bool)->bool.
10163         (!s. s IN f ==> convex s) /\
10164         ~(INTERS(IMAGE relative_interior f) = {})
10165         ==> closure(INTERS f) = INTERS(IMAGE closure f)`,
10166   REPEAT STRIP_TAC THEN
10167   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[CLOSURE_INTERS_SUBSET] THEN
10168   REWRITE_TAC[SUBSET; IN_INTERS; FORALL_IN_IMAGE] THEN
10169   X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
10170   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
10171   REWRITE_TAC[INTERS_IMAGE; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
10172   X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
10173   REWRITE_TAC[CLOSURE_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
10174   ASM_CASES_TAC `b:real^N = a` THENL
10175    [EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[DIST_REFL; IN_INTERS] THEN
10176     ASM_MESON_TAC[SUBSET; RELATIVE_INTERIOR_SUBSET];
10177     ALL_TAC] THEN
10178   EXISTS_TAC `b - min (&1 / &2) (e / &2 / norm(b - a)) % (b - a):real^N` THEN
10179   CONJ_TAC THENL
10180    [ALL_TAC;
10181     REWRITE_TAC[NORM_ARITH `dist(b - a:real^N,b) = norm a`; NORM_MUL] THEN
10182     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
10183     MATCH_MP_TAC(REAL_ARITH
10184      `&0 < a /\ &0 < x /\ x < y ==> abs(min a x) < y`) THEN
10185     ASM_SIMP_TAC[REAL_LT_DIV2_EQ; REAL_HALF; REAL_LT_DIV; NORM_POS_LT;
10186                  VECTOR_SUB_EQ] THEN
10187     ASM_REAL_ARITH_TAC] THEN
10188   REWRITE_TAC[IN_INTERS] THEN X_GEN_TAC `s:real^N->bool` THEN DISCH_TAC THEN
10189   MATCH_MP_TAC
10190    (MESON[RELATIVE_INTERIOR_SUBSET; SUBSET]
10191          `!x. x IN relative_interior s ==> x IN s`) THEN
10192   MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
10193   ASM_SIMP_TAC[REAL_LT_MIN; REAL_HALF; REAL_LT_DIV; NORM_POS_LT;
10194                VECTOR_SUB_EQ] THEN
10195   REAL_ARITH_TAC);;
10196
10197 let CLOSURE_INTERS_CONVEX_OPEN = prove
10198  (`!f:(real^N->bool)->bool.
10199         (!s. s IN f ==> convex s /\ open s)
10200         ==> closure(INTERS f) =
10201                 if INTERS f = {} then {}
10202                 else INTERS(IMAGE closure f)`,
10203   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[CLOSURE_EMPTY] THEN
10204   MATCH_MP_TAC CLOSURE_INTERS_CONVEX THEN ASM_SIMP_TAC[] THEN
10205   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
10206    `~(s = {}) ==> s = t ==> ~(t = {})`)) THEN
10207   AP_TERM_TAC THEN MATCH_MP_TAC(SET_RULE
10208    `(!x. x IN s ==> f x = x) ==> s = IMAGE f s`) THEN
10209   ASM_SIMP_TAC[RELATIVE_INTERIOR_OPEN; INTERIOR_EQ]);;
10210
10211 let CLOSURE_INTER_CONVEX = prove
10212  (`!s t:real^N->bool.
10213         convex s /\ convex t /\
10214         ~(relative_interior s INTER relative_interior t = {})
10215         ==> closure(s INTER t) = closure(s) INTER closure(t)`,
10216   REPEAT STRIP_TAC THEN
10217   MP_TAC(ISPEC `{s:real^N->bool,t}` CLOSURE_INTERS_CONVEX) THEN
10218   ASM_SIMP_TAC[IMAGE_CLAUSES; INTERS_2] THEN
10219   ASM_REWRITE_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY]);;
10220
10221 let CLOSURE_INTER_CONVEX_OPEN = prove
10222  (`!s t. convex s /\ open s /\ convex t /\ open t
10223          ==> closure(s INTER t) =
10224                 if s INTER t = {} then {} else closure(s) INTER closure(t)`,
10225   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[CLOSURE_EMPTY] THEN
10226   MATCH_MP_TAC CLOSURE_INTER_CONVEX THEN
10227   ASM_SIMP_TAC[RELATIVE_INTERIOR_OPEN]);;
10228
10229 let CLOSURE_CONVEX_INTER_SUPERSET = prove
10230  (`!s t:real^N->bool.
10231         convex s /\ ~(interior s = {}) /\ interior s SUBSET closure t
10232         ==> closure(s INTER t) = closure s`,
10233   REPEAT GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
10234   SIMP_TAC[SUBSET_CLOSURE; INTER_SUBSET; SUBSET_INTER] THEN
10235   MATCH_MP_TAC SUBSET_TRANS THEN
10236   EXISTS_TAC `closure(interior s):real^N->bool` THEN CONJ_TAC THENL
10237    [ASM_SIMP_TAC[CONVEX_CLOSURE_INTERIOR; SUBSET_REFL];
10238     ASM_SIMP_TAC[GSYM CLOSURE_OPEN_INTER_SUPERSET; OPEN_INTERIOR] THEN
10239     MATCH_MP_TAC SUBSET_CLOSURE THEN
10240     MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET) THEN SET_TAC[]]);;
10241
10242 let CLOSURE_DYADIC_RATIONALS_IN_CONVEX_SET = prove
10243  (`!s:real^N->bool.
10244         convex s /\ ~(interior s = {})
10245         ==> closure(s INTER
10246                     { inv(&2 pow n) % x | n,x |
10247                       !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }) =
10248             closure s`,
10249   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_CONVEX_INTER_SUPERSET THEN
10250   ASM_REWRITE_TAC[CLOSURE_DYADIC_RATIONALS; SUBSET_UNIV]);;
10251
10252 let CLOSURE_RATIONALS_IN_CONVEX_SET = prove
10253  (`!s:real^N->bool.
10254       convex s /\ ~(interior s = {})
10255       ==> closure(s INTER
10256                   { x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) }) =
10257           closure s`,
10258   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_CONVEX_INTER_SUPERSET THEN
10259   ASM_REWRITE_TAC[CLOSURE_RATIONAL_COORDINATES; SUBSET_UNIV]);;
10260
10261 let RELATIVE_INTERIOR_CONVEX_INTER_AFFINE = prove
10262  (`!s t:real^N->bool.
10263         convex s /\ affine t /\ ~(interior s INTER t = {})
10264         ==> relative_interior(s INTER t) = interior s INTER t`,
10265   REPEAT GEN_TAC THEN
10266   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; RIGHT_AND_EXISTS_THM] THEN
10267   DISCH_THEN(X_CHOOSE_THEN `a:real^N` MP_TAC) THEN
10268   GEOM_ORIGIN_TAC `a:real^N` THEN REWRITE_TAC[IN_INTER] THEN
10269   REPEAT GEN_TAC THEN ASM_CASES_TAC `(vec 0:real^N) IN t` THEN
10270   ASM_SIMP_TAC[AFFINE_EQ_SUBSPACE] THEN STRIP_TAC THEN
10271   GEN_REWRITE_TAC I [EXTENSION] THEN X_GEN_TAC `x:real^N` THEN
10272   MP_TAC(ISPECL [`t:real^N->bool`; `s:real^N->bool`]
10273         (ONCE_REWRITE_RULE[INTER_COMM]
10274            AFFINE_HULL_AFFINE_INTER_NONEMPTY_INTERIOR)) THEN
10275   ASM_SIMP_TAC[SUBSPACE_IMP_AFFINE; IN_RELATIVE_INTERIOR_CBALL] THEN
10276   ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[IN_INTER; IN_INTERIOR_CBALL]] THEN
10277   DISCH_THEN SUBST1_TAC THEN
10278   ASM_CASES_TAC `(x:real^N) IN t` THEN ASM_REWRITE_TAC[] THEN
10279   SIMP_TAC[SUBSET; IN_INTER] THEN
10280   ASM_CASES_TAC `(x:real^N) IN s` THENL
10281    [ASM_REWRITE_TAC[]; ASM_MESON_TAC[CENTRE_IN_CBALL; REAL_LT_IMP_LE]] THEN
10282   EQ_TAC THENL [REWRITE_TAC[IN_CBALL]; MESON_TAC[]] THEN
10283   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
10284   ASM_CASES_TAC `x:real^N = vec 0` THENL
10285    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR_CBALL]) THEN
10286     ASM_REWRITE_TAC[SUBSET; IN_CBALL];
10287     ALL_TAC] THEN
10288   MP_TAC(ISPECL
10289    [`s:real^N->bool`; `vec 0:real^N`; `(&1 + e / norm x) % x:real^N`]
10290    IN_INTERIOR_CLOSURE_CONVEX_SEGMENT) THEN
10291   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
10292    [MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN
10293     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_SIMP_TAC[SUBSPACE_MUL] THEN
10294     REWRITE_TAC[VECTOR_ADD_RDISTRIB; VECTOR_MUL_LID;
10295                 NORM_ARITH `dist(a:real^N,a + x) = norm x`] THEN
10296     ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM;
10297                  REAL_DIV_RMUL; NORM_EQ_0] THEN
10298     ASM_REAL_ARITH_TAC;
10299     REWRITE_TAC[SUBSET; IN_INTERIOR_CBALL; IN_CBALL] THEN
10300     DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[IN_SEGMENT] THEN
10301     CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN
10302     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
10303     REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
10304     EXISTS_TAC `inv(&1 + e / norm(x:real^N))` THEN
10305     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_LT_DIV; NORM_POS_LT; VECTOR_MUL_LID;
10306                  REAL_LT_INV_EQ; REAL_MUL_LINV; REAL_INV_LT_1; REAL_ARITH
10307                  `&0 < x ==> &1 < &1 + x /\ &0 < &1 + x /\ ~(&1 + x = &0)`]]);;
10308
10309 (* ------------------------------------------------------------------------- *)
10310 (* Homeomorphism of all convex compact sets with same affine dimension, and  *)
10311 (* in particular all those with nonempty interior.                           *)
10312 (* ------------------------------------------------------------------------- *)
10313
10314 let COMPACT_FRONTIER_LINE_LEMMA = prove
10315  (`!s x. compact s /\ (vec 0 IN s) /\ ~(x = vec 0 :real^N)
10316          ==> ?u. &0 <= u /\ (u % x) IN frontier s /\
10317                  !v. u < v ==> ~((v % x) IN s)`,
10318   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN
10319   REWRITE_TAC[BOUNDED_POS] THEN
10320   DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THEN
10321   MP_TAC(ISPECL
10322     [`{y:real^N | ?u. &0 <= u /\ u <= b / norm(x) /\ (y = u % x)} INTER s`;
10323      `vec 0:real^N`]
10324    DISTANCE_ATTAINS_SUP) THEN
10325   ANTS_TAC THENL
10326    [CONJ_TAC THENL
10327      [ALL_TAC;
10328       REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `vec 0:real^N` THEN
10329       ASM_REWRITE_TAC[IN_INTER; IN_ELIM_THM] THEN
10330       EXISTS_TAC `&0` THEN
10331       ASM_SIMP_TAC[VECTOR_MUL_LZERO; REAL_LE_REFL; REAL_LT_IMP_LE;
10332                    REAL_LT_DIV; NORM_POS_LT]] THEN
10333     MATCH_MP_TAC COMPACT_INTER THEN ASM_REWRITE_TAC[] THEN
10334     SUBGOAL_THEN
10335      `{y:real^N | ?u. &0 <= u /\ u <= b / norm(x) /\ (y = u % x)} =
10336       IMAGE (\u. drop u % x) (interval [vec 0,lambda i. b / norm(x:real^N)])`
10337     SUBST1_TAC THENL
10338      [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; IN_INTERVAL] THEN
10339       SIMP_TAC[LAMBDA_BETA] THEN
10340       SIMP_TAC[DIMINDEX_1; ARITH_RULE `1 <= i /\ i <= 1 <=> (i = 1)`] THEN
10341       REWRITE_TAC[GSYM drop; LEFT_FORALL_IMP_THM; EXISTS_REFL; DROP_VEC] THEN
10342       REWRITE_TAC[EXISTS_LIFT; LIFT_DROP] THEN MESON_TAC[];
10343       ALL_TAC] THEN
10344     MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
10345     REWRITE_TAC[COMPACT_INTERVAL] THEN
10346     MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN REPEAT STRIP_TAC THEN
10347     MATCH_MP_TAC CONTINUOUS_VMUL THEN
10348     REWRITE_TAC[o_DEF; LIFT_DROP; CONTINUOUS_AT_ID];
10349     ALL_TAC] THEN
10350   REWRITE_TAC[IN_INTER; IN_ELIM_THM; LEFT_AND_EXISTS_THM] THEN
10351   ONCE_REWRITE_TAC[TAUT `(a /\ b /\ c) /\ d <=> c /\ a /\ b /\ d`] THEN
10352   SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
10353   GEN_REWRITE_TAC (BINDER_CONV o ONCE_DEPTH_CONV) [SWAP_FORALL_THM] THEN
10354   SIMP_TAC[IMP_CONJ] THEN
10355   REWRITE_TAC[LEFT_FORALL_IMP_THM; EXISTS_REFL] THEN
10356   REWRITE_TAC[IMP_IMP] THEN REWRITE_TAC[LEFT_FORALL_IMP_THM] THEN
10357   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real` THEN
10358   REWRITE_TAC[dist; VECTOR_SUB_LZERO; NORM_NEG; NORM_MUL] THEN
10359   ASM_SIMP_TAC[REAL_LE_RMUL_EQ; NORM_POS_LT] THEN
10360   DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
10361   ASM_SIMP_TAC[real_abs] THEN REPEAT STRIP_TAC THENL
10362    [REWRITE_TAC[FRONTIER_STRADDLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
10363     CONJ_TAC THENL
10364      [EXISTS_TAC `u % x :real^N` THEN ASM_REWRITE_TAC[DIST_REFL];
10365       ALL_TAC] THEN
10366     EXISTS_TAC `(u + (e / &2) / norm(x)) % x :real^N` THEN
10367     REWRITE_TAC[dist; VECTOR_ARITH `u % x - (u + a) % x = --(a % x)`] THEN
10368     ASM_SIMP_TAC[NORM_NEG; NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; NORM_EQ_0;
10369                  REAL_DIV_RMUL; REAL_ABS_NUM; REAL_LT_LDIV_EQ; REAL_OF_NUM_LT;
10370                  ARITH; REAL_ARITH `abs e < e * &2 <=> &0 < e`] THEN
10371     DISCH_TAC THEN
10372     FIRST_X_ASSUM(MP_TAC o SPEC `u + (e / &2) / norm(x:real^N)`) THEN
10373     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(REAL_ARITH
10374      `&0 < e /\ &0 <= u /\ u + e <= b
10375       ==> ~(&0 <= u + e /\ u + e <= b ==> u + e <= u)`) THEN
10376     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; NORM_POS_LT] THEN
10377     FIRST_X_ASSUM(MP_TAC o SPEC `(u + (e / &2) / norm(x:real^N)) % x`) THEN
10378     ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
10379     REAL_ARITH_TAC;
10380     ALL_TAC] THEN
10381   FIRST_X_ASSUM(MP_TAC o SPEC `v:real`) THEN
10382   ASM_REWRITE_TAC[GSYM REAL_NOT_LT] THEN ASM_REWRITE_TAC[REAL_NOT_LT] THEN
10383   CONJ_TAC THENL [ASM_MESON_TAC[REAL_LET_TRANS; REAL_LT_IMP_LE]; ALL_TAC] THEN
10384   FIRST_X_ASSUM(MP_TAC o SPEC `v % x:real^N`) THEN
10385   ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
10386   REAL_ARITH_TAC);;
10387
10388 let STARLIKE_COMPACT_PROJECTIVE = prove
10389  (`!s:real^N->bool a.
10390         compact s /\ a IN relative_interior s /\
10391         (!x. x IN s ==> segment(a,x) SUBSET relative_interior s)
10392         ==> s DIFF relative_interior s homeomorphic
10393             sphere(a,&1) INTER affine hull s /\
10394             s homeomorphic cball(a,&1) INTER affine hull s`,
10395   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN
10396   REWRITE_TAC[SUBSET; IMP_IMP; RIGHT_IMP_FORALL_THM] THEN
10397   GEN_TAC THEN STRIP_TAC THEN
10398   SUBGOAL_THEN
10399    `!x:real^N u. x IN s /\ &0 <= u /\ u < &1
10400                  ==> (u % x) IN relative_interior s`
10401   ASSUME_TAC THENL
10402    [REWRITE_TAC[REAL_ARITH `&0 <= u <=> u = &0 \/ &0 < u`] THEN
10403     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[VECTOR_MUL_LZERO] THEN
10404     ASM_CASES_TAC `x:real^N = vec 0` THEN
10405     ASM_REWRITE_TAC[VECTOR_MUL_RZERO] THEN
10406     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[IN_SEGMENT] THEN
10407     REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN ASM_MESON_TAC[];
10408     FIRST_X_ASSUM(K ALL_TAC o SPECL [`x:real^N`; `x:real^N`])] THEN
10409   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REWRITE_RULE[SUBSET]
10410     RELATIVE_INTERIOR_SUBSET)) THEN
10411   ABBREV_TAC `proj = \x:real^N. inv(norm(x)) % x` THEN
10412   SUBGOAL_THEN
10413    `!x:real^N y. (proj(x) = proj(y):real^N) /\ (norm x = norm y) <=> (x = y)`
10414   ASSUME_TAC THENL
10415    [REPEAT GEN_TAC THEN EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
10416     ASM_CASES_TAC `y:real^N = vec 0` THEN
10417     ASM_SIMP_TAC[NORM_EQ_0; NORM_0] THEN
10418     ASM_CASES_TAC `x:real^N = vec 0` THENL
10419      [ASM_MESON_TAC[NORM_EQ_0]; ALL_TAC] THEN
10420     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
10421     EXPAND_TAC "proj" THEN REWRITE_TAC[] THEN
10422     ASM_REWRITE_TAC[VECTOR_ARITH
10423      `a % x = a % y <=> a % (x - y):real^N = vec 0`] THEN
10424     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; REAL_INV_EQ_0; NORM_EQ_0; VECTOR_SUB_EQ];
10425     ALL_TAC] THEN
10426   SUBGOAL_THEN
10427    `(!x. x IN affine hull s ==> proj x IN affine hull s) /\
10428     (!x. ~(x = vec 0) ==> norm(proj x) = &1) /\
10429     (!x:real^N. proj x = vec 0 <=> x = vec 0)`
10430   STRIP_ASSUME_TAC THENL
10431    [EXPAND_TAC "proj" THEN REWRITE_TAC[NORM_MUL; VECTOR_MUL_EQ_0] THEN
10432     REWRITE_TAC[REAL_INV_EQ_0; NORM_EQ_0; REAL_ABS_INV; REAL_ABS_NORM] THEN
10433     SIMP_TAC[REAL_MUL_LINV; NORM_EQ_0] THEN REPEAT STRIP_TAC THEN
10434     GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_ADD_LID] THEN
10435     MATCH_MP_TAC IN_AFFINE_ADD_MUL THEN
10436     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; VECTOR_ADD_LID; HULL_INC];
10437     ALL_TAC] THEN
10438   SUBGOAL_THEN `(proj:real^N->real^N) continuous_on (UNIV DELETE vec 0)`
10439   ASSUME_TAC THENL
10440    [MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
10441     REWRITE_TAC[IN_DELETE; IN_UNIV] THEN EXPAND_TAC "proj" THEN
10442     REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
10443     ASM_SIMP_TAC[CONTINUOUS_AT_ID] THEN
10444     REWRITE_TAC[GSYM(ISPEC `lift` o_DEF);
10445                 GSYM(ISPEC `inv:real->real` o_DEF)] THEN
10446     MATCH_MP_TAC CONTINUOUS_AT_INV THEN
10447     ASM_REWRITE_TAC[NORM_EQ_0; VECTOR_SUB_EQ; CONTINUOUS_AT_LIFT_NORM];
10448     ALL_TAC] THEN
10449   ABBREV_TAC `usph = {x:real^N | x IN affine hull s /\ norm x = &1}` THEN
10450   SUBGOAL_THEN ` sphere(vec 0:real^N,&1) INTER affine hull s = usph`
10451   SUBST1_TAC THENL
10452    [EXPAND_TAC "usph" THEN REWRITE_TAC[EXTENSION; IN_INTER; IN_SPHERE_0] THEN
10453     SET_TAC[];
10454     ALL_TAC] THEN
10455   SUBGOAL_THEN
10456    `!x. x IN affine hull s /\ ~(x = vec 0)
10457         ==> (proj:real^N->real^N) x IN usph`
10458   ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10459   SUBGOAL_THEN `?surf. homeomorphism (s DIFF relative_interior s,usph)
10460                                      (proj:real^N->real^N,surf)`
10461   MP_TAC THENL
10462    [MATCH_MP_TAC HOMEOMORPHISM_COMPACT THEN
10463     ASM_SIMP_TAC[COMPACT_RELATIVE_BOUNDARY] THEN REPEAT CONJ_TAC THENL
10464      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10465           CONTINUOUS_ON_SUBSET)) THEN
10466       ASM SET_TAC[];
10467       MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
10468        [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_DIFF] THEN
10469         EXPAND_TAC "usph" THEN REWRITE_TAC[IN_ELIM_THM] THEN
10470         ASM_MESON_TAC[HULL_INC];
10471         MAP_EVERY EXPAND_TAC ["proj"; "usph"] THEN
10472         REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN
10473         ASM_CASES_TAC `x:real^N = vec 0` THEN
10474         ASM_REWRITE_TAC[NORM_0; REAL_OF_NUM_EQ; ARITH_EQ] THEN STRIP_TAC THEN
10475         MP_TAC(ISPECL [`s:real^N->bool`; `vec 0:real^N`; `x:real^N`]
10476             RAY_TO_RELATIVE_FRONTIER) THEN
10477         REWRITE_TAC[relative_frontier] THEN
10478         ASM_SIMP_TAC[COMPACT_IMP_BOUNDED; CLOSURE_CLOSED; COMPACT_IMP_CLOSED;
10479                      VECTOR_ADD_LID] THEN
10480         DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
10481         EXPAND_TAC "proj" THEN REWRITE_TAC[IN_IMAGE] THEN
10482         EXISTS_TAC `d % x:real^N` THEN ASM_REWRITE_TAC[NORM_MUL] THEN
10483         ASM_SIMP_TAC[REAL_MUL_RID; real_abs; REAL_LT_IMP_LE] THEN
10484         ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_LT_IMP_NZ;
10485                      VECTOR_MUL_LID]];
10486       MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
10487       REWRITE_TAC[IN_DIFF] THEN STRIP_TAC THEN
10488       ASM_CASES_TAC `x:real^N = vec 0` THENL [ASM SET_TAC[]; ALL_TAC] THEN
10489       ASM_CASES_TAC `y:real^N = vec 0` THENL [ASM SET_TAC[]; ALL_TAC] THEN
10490       UNDISCH_TAC `(proj:real^N->real^N) x = proj y` THEN
10491       EXPAND_TAC "proj" THEN
10492       REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC (REAL_ARITH
10493        `norm(x:real^N) = norm(y:real^N) \/
10494         norm x < norm y \/ norm y < norm x`)
10495       THENL
10496        [ASM_REWRITE_TAC[VECTOR_MUL_LCANCEL; REAL_INV_EQ_0; NORM_EQ_0];
10497         DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL
10498          [`y:real^N`; `norm(x:real^N) / norm(y:real^N)`]);
10499         DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL
10500          [`x:real^N`; `norm(y:real^N) / norm(x:real^N)`])] THEN
10501       ASM_SIMP_TAC[REAL_LE_DIV; NORM_POS_LE; REAL_LT_LDIV_EQ; NORM_POS_LT;
10502                    REAL_MUL_LID] THEN
10503       ASM_REWRITE_TAC[real_div; GSYM VECTOR_MUL_ASSOC] THENL
10504        [FIRST_X_ASSUM(SUBST1_TAC o SYM); ALL_TAC] THEN
10505       ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; NORM_EQ_0] THEN
10506       ASM_REWRITE_TAC[VECTOR_MUL_LID]];
10507     DISCH_THEN(fun th ->
10508       CONJ_TAC THENL
10509        [MESON_TAC[homeomorphic; th];
10510         ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
10511         MATCH_MP_TAC HOMEOMORPHIC_COMPACT THEN
10512         SIMP_TAC[COMPACT_INTER_CLOSED; CLOSED_AFFINE_HULL; COMPACT_CBALL] THEN
10513         MP_TAC th]) THEN
10514     REWRITE_TAC[HOMEOMORPHISM; LEFT_IMP_EXISTS_THM] THEN
10515     X_GEN_TAC `surf:real^N->real^N` THEN STRIP_TAC THEN
10516     EXISTS_TAC `\x:real^N. norm(x) % (surf:real^N->real^N)(proj(x))` THEN
10517     REWRITE_TAC[]] THEN
10518   UNDISCH_THEN
10519    `(proj:real^N->real^N) continuous_on s DIFF relative_interior s`
10520    (K ALL_TAC) THEN
10521   REWRITE_TAC[] THEN CONJ_TAC THENL
10522    [REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; IN_INTER] THEN
10523     X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
10524     ASM_CASES_TAC `x = vec 0:real^N` THENL
10525      [ASM_REWRITE_TAC[CONTINUOUS_WITHIN; VECTOR_MUL_LZERO; NORM_0] THEN
10526       MATCH_MP_TAC LIM_NULL_VMUL_BOUNDED THEN
10527       FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN
10528       REWRITE_TAC[BOUNDED_POS] THEN MATCH_MP_TAC MONO_EXISTS THEN
10529       REPEAT STRIP_TAC THENL
10530        [REWRITE_TAC[LIM_WITHIN; o_THM; DIST_0; NORM_LIFT; REAL_ABS_NORM] THEN
10531         MESON_TAC[];
10532         REWRITE_TAC[EVENTUALLY_WITHIN] THEN EXISTS_TAC `&1` THEN
10533         REWRITE_TAC[REAL_LT_01; IN_INTER; DIST_0; NORM_POS_LT] THEN
10534         ASM SET_TAC[]];
10535       MATCH_MP_TAC CONTINUOUS_WITHIN_SUBSET THEN
10536       EXISTS_TAC `affine hull s:real^N->bool` THEN
10537       REWRITE_TAC[INTER_SUBSET] THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
10538       SIMP_TAC[CONTINUOUS_LIFT_NORM_COMPOSE; CONTINUOUS_WITHIN_ID; o_DEF] THEN
10539       SUBGOAL_THEN
10540        `((surf:real^N->real^N) o (proj:real^N->real^N)) continuous_on
10541         (affine hull s DELETE vec 0)`
10542       MP_TAC THENL
10543        [MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
10544         ASM_REWRITE_TAC[] THEN CONJ_TAC THEN
10545         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10546             CONTINUOUS_ON_SUBSET)) THEN
10547         SIMP_TAC[SUBSET; IN_DELETE; IN_UNIV; FORALL_IN_IMAGE] THEN
10548         EXPAND_TAC "usph" THEN ASM_SIMP_TAC[IN_ELIM_THM];
10549         SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
10550         DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_SIMP_TAC[IN_DELETE] THEN
10551         REWRITE_TAC[CONTINUOUS_WITHIN; o_DEF] THEN MATCH_MP_TAC EQ_IMP THEN
10552         MATCH_MP_TAC LIM_TRANSFORM_WITHIN_SET THEN
10553         REWRITE_TAC[EVENTUALLY_AT] THEN EXISTS_TAC `norm(x:real^N)` THEN
10554         ASM_REWRITE_TAC[IN_DELETE; IN_INTER; IN_CBALL; NORM_POS_LT] THEN
10555         X_GEN_TAC `y:real^N` THEN
10556         ASM_CASES_TAC `(y:real^N) IN affine hull s` THEN ASM_REWRITE_TAC[] THEN
10557         CONV_TAC NORM_ARITH]];
10558     ALL_TAC] THEN
10559   SUBGOAL_THEN
10560    `!a x. &0 < a ==> (proj:real^N->real^N)(a % x) = proj x`
10561   ASSUME_TAC THENL
10562    [REPEAT GEN_TAC THEN EXPAND_TAC "proj" THEN
10563     REWRITE_TAC[NORM_MUL; REAL_INV_MUL; VECTOR_MUL_ASSOC] THEN
10564     SIMP_TAC[REAL_FIELD `&0 < a ==> (inv(a) * x) * a = x`; real_abs;
10565              REAL_LT_IMP_LE];
10566     ALL_TAC] THEN
10567   CONJ_TAC THENL
10568    [ALL_TAC;
10569     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
10570     ASM_CASES_TAC `y:real^N = vec 0` THENL
10571      [ASM_SIMP_TAC[VECTOR_MUL_LZERO; VECTOR_MUL_EQ_0; NORM_0; NORM_EQ_0] THEN
10572       ASM SET_TAC[];
10573       ALL_TAC] THEN
10574     ASM_CASES_TAC `x:real^N = vec 0` THENL
10575      [CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN
10576       ASM_SIMP_TAC[VECTOR_MUL_LZERO; VECTOR_MUL_EQ_0; NORM_0; NORM_EQ_0] THEN
10577       ASM SET_TAC[];
10578       ALL_TAC] THEN
10579     REWRITE_TAC[IN_INTER; IN_CBALL_0] THEN
10580     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC)) THEN
10581     DISCH_THEN(fun th -> MP_TAC th THEN
10582              MP_TAC(AP_TERM `proj:real^N->real^N` th)) THEN
10583     ASM_SIMP_TAC[NORM_POS_LT; VECTOR_MUL_RCANCEL] THEN ASM SET_TAC[]] THEN
10584   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
10585    [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_CBALL_0] THEN
10586     X_GEN_TAC `x:real^N` THEN ASM_CASES_TAC `x:real^N = vec 0` THEN
10587     ASM_REWRITE_TAC[NORM_0; VECTOR_MUL_LZERO; IN_INTER] THEN
10588     REWRITE_TAC[IN_CBALL_0; REAL_LE_LT] THEN STRIP_TAC  THENL
10589      [MATCH_MP_TAC(REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET) THEN
10590       FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[NORM_POS_LE] THEN
10591       ASM SET_TAC[];
10592       ASM_REWRITE_TAC[VECTOR_MUL_LID] THEN ASM SET_TAC[]];
10593     ALL_TAC] THEN
10594   REWRITE_TAC[SUBSET; IN_IMAGE; IN_CBALL_0; IN_INTER] THEN
10595   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
10596   ASM_CASES_TAC `x:real^N = vec 0` THENL
10597    [EXISTS_TAC `vec 0:real^N` THEN
10598     ASM_SIMP_TAC[NORM_0; VECTOR_MUL_LZERO; HULL_INC; REAL_POS];
10599     ALL_TAC] THEN
10600   SUBGOAL_THEN
10601    `!x. x IN usph ==> ~((surf:real^N->real^N) x = vec 0)`
10602   ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10603   EXISTS_TAC `inv(norm(surf(proj x:real^N):real^N)) % x:real^N` THEN
10604   FIRST_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [GSYM th]) THEN
10605   REWRITE_TAC[GSYM CONJ_ASSOC] THEN
10606   ASM (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 5)
10607    [NORM_POS_LT; REAL_LT_INV_EQ; HULL_INC; REAL_LT_MUL; NORM_MUL;
10608     REAL_ABS_INV; REAL_ABS_NORM] THEN
10609   REPEAT CONJ_TAC THENL
10610    [MATCH_MP_TAC(REAL_FIELD `~(y = &0) ==> x = (inv y * x) * y`) THEN
10611     ASM_SIMP_TAC[NORM_EQ_0; HULL_INC];
10612     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
10613     ASM (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 5)
10614      [GSYM real_div; REAL_LE_LDIV_EQ; NORM_POS_LT; HULL_INC; REAL_MUL_LID] THEN
10615     FIRST_X_ASSUM(MP_TAC o SPECL
10616      [`x:real^N`; `norm(surf(proj x:real^N):real^N) / norm(x:real^N)`]) THEN
10617     ASM_SIMP_TAC[REAL_LE_DIV; NORM_POS_LE; REAL_LT_LDIV_EQ; NORM_POS_LT] THEN
10618     GEN_REWRITE_TAC LAND_CONV [GSYM CONTRAPOS_THM] THEN
10619     REWRITE_TAC[REAL_NOT_LT; REAL_MUL_LID] THEN DISCH_THEN MATCH_MP_TAC THEN
10620     SUBGOAL_THEN
10621      `norm(surf(proj x)) / norm x % x:real^N = surf(proj x:real^N)`
10622     SUBST1_TAC THENL
10623      [FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC I [GSYM th]) THEN
10624       ASM (CONV_TAC o GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV (basic_ss []) 5)
10625        [NORM_POS_LT; REAL_LT_INV_EQ; HULL_INC; REAL_LT_MUL; NORM_MUL;
10626         REAL_ABS_INV; REAL_ABS_NORM; REAL_ABS_DIV; REAL_LT_DIV;
10627         REAL_DIV_RMUL; NORM_EQ_0];
10628       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
10629        `IMAGE f s SUBSET t DIFF u ==> x IN s ==> ~(f x IN u)`)) THEN
10630       ASM_SIMP_TAC[HULL_INC]];
10631     GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_ADD_LID] THEN
10632     MATCH_MP_TAC IN_AFFINE_ADD_MUL THEN
10633     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; VECTOR_ADD_LID; HULL_INC]]);;
10634
10635 let HOMEOMORPHIC_CONVEX_COMPACT_SETS,
10636     HOMEOMORPHIC_RELATIVE_FRONTIERS_CONVEX_BOUNDED_SETS = (CONJ_PAIR o prove)
10637  (`(!s:real^M->bool t:real^N->bool.
10638         convex s /\ compact s /\ convex t /\ compact t /\ aff_dim s = aff_dim t
10639         ==> s homeomorphic t) /\
10640    (!s:real^M->bool t:real^N->bool.
10641         convex s /\ bounded s /\ convex t /\ bounded t /\ aff_dim s = aff_dim t
10642         ==> relative_frontier s homeomorphic relative_frontier t)`,
10643   let lemma = prove
10644    (`!s:real^M->bool t:real^N->bool.
10645           convex s /\ compact s /\ convex t /\ compact t /\
10646           aff_dim s = aff_dim t
10647           ==> (s DIFF relative_interior s) homeomorphic
10648               (t DIFF relative_interior t) /\
10649               s homeomorphic t`,
10650     REPEAT GEN_TAC THEN
10651     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
10652     ASM_CASES_TAC `relative_interior t:real^N->bool = {}` THENL
10653      [UNDISCH_TAC `relative_interior t:real^N->bool = {}` THEN
10654       ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1;
10655                    EMPTY_DIFF; HOMEOMORPHIC_EMPTY; RELATIVE_INTERIOR_EQ_EMPTY];
10656        FIRST_X_ASSUM(X_CHOOSE_THEN `b:real^N` MP_TAC o
10657           GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY])] THEN
10658     CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN
10659     ASM_CASES_TAC `relative_interior s:real^M->bool = {}` THENL
10660      [UNDISCH_TAC `relative_interior s:real^M->bool = {}` THEN
10661       ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_EQ_MINUS1;
10662                    EMPTY_DIFF; HOMEOMORPHIC_EMPTY; RELATIVE_INTERIOR_EQ_EMPTY];
10663       FIRST_X_ASSUM(X_CHOOSE_THEN `a:real^M` MP_TAC o
10664           GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY])] THEN
10665     REPEAT(POP_ASSUM MP_TAC) THEN
10666     GEOM_ORIGIN_TAC `b:real^N` THEN REPEAT GEN_TAC THEN
10667     GEOM_ORIGIN_TAC `a:real^M` THEN REPEAT GEN_TAC THEN
10668     REPEAT DISCH_TAC THEN
10669     MP_TAC(ISPECL [`s:real^M->bool`; `vec 0:real^M`]
10670           STARLIKE_COMPACT_PROJECTIVE) THEN
10671     MP_TAC(ISPECL [`t:real^N->bool`; `vec 0:real^N`]
10672           STARLIKE_COMPACT_PROJECTIVE) THEN
10673     ASM_SIMP_TAC[IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT;
10674                  REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN
10675     DISCH_THEN(fun th -> MATCH_MP_TAC MONO_AND THEN MP_TAC th) THEN
10676     MATCH_MP_TAC MONO_AND THEN CONJ_TAC THEN
10677     DISCH_THEN(fun th ->
10678      MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ_ALT] HOMEOMORPHIC_TRANS) THEN
10679      MP_TAC(ONCE_REWRITE_RULE[HOMEOMORPHIC_SYM] th)) THEN
10680     MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ] HOMEOMORPHIC_TRANS) THEN
10681     REPEAT(FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP (REWRITE_RULE[SUBSET]
10682           RELATIVE_INTERIOR_SUBSET))) THEN
10683     FIRST_X_ASSUM(MP_TAC o SYM) THEN
10684     ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC; AFF_DIM_DIM_0] THEN
10685     REWRITE_TAC[INT_OF_NUM_EQ] THEN DISCH_TAC THEN
10686     MP_TAC(ISPECL [`span s:real^M->bool`; `span t:real^N->bool`]
10687             ISOMETRIES_SUBSPACES) THEN
10688     ASM_REWRITE_TAC[SUBSPACE_SPAN; DIM_SPAN; homeomorphic; HOMEOMORPHISM] THEN
10689     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^M->real^N` THEN
10690     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^M` THEN
10691     SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_CBALL_0; IN_SPHERE_0] THEN
10692     SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN ASM SET_TAC[]) in
10693   SIMP_TAC[lemma; relative_frontier] THEN REPEAT STRIP_TAC THEN
10694   MP_TAC(SPECL [`closure s:real^M->bool`; `closure t:real^N->bool`] lemma) THEN
10695   ASM_SIMP_TAC[CONVEX_CLOSURE; COMPACT_CLOSURE; AFF_DIM_CLOSURE] THEN
10696   ASM_SIMP_TAC[CONVEX_RELATIVE_INTERIOR_CLOSURE]);;
10697
10698 let HOMEOMORPHIC_CONVEX_COMPACT = prove
10699  (`!s:real^N->bool t:real^N->bool.
10700         convex s /\ compact s /\ ~(interior s = {}) /\
10701         convex t /\ compact t /\ ~(interior t = {})
10702         ==> s homeomorphic t`,
10703   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHIC_CONVEX_COMPACT_SETS THEN
10704   ASM_SIMP_TAC[AFF_DIM_NONEMPTY_INTERIOR]);;
10705
10706 let HOMEOMORPHIC_CONVEX_COMPACT_CBALL = prove
10707  (`!s:real^N->bool b:real^N e.
10708         convex s /\ compact s /\ ~(interior s = {}) /\ &0 < e
10709         ==> s homeomorphic cball(b,e)`,
10710   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHIC_CONVEX_COMPACT THEN
10711   ASM_REWRITE_TAC[COMPACT_CBALL; INTERIOR_CBALL; CONVEX_CBALL] THEN
10712   ASM_REWRITE_TAC[BALL_EQ_EMPTY; REAL_NOT_LE]);;
10713
10714 let HOMEOMORPHIC_CLOSED_INTERVALS = prove
10715  (`!a b:real^N c d:real^N.
10716         ~(interval(a,b) = {}) /\ ~(interval(c,d) = {})
10717         ==> interval[a,b] homeomorphic interval[c,d]`,
10718   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHIC_CONVEX_COMPACT THEN
10719   REWRITE_TAC[CONVEX_INTERVAL; COMPACT_INTERVAL] THEN
10720   ASM_REWRITE_TAC[INTERIOR_CLOSED_INTERVAL]);;
10721
10722 (* ------------------------------------------------------------------------- *)
10723 (* More about affine dimension of special sets.                              *)
10724 (* ------------------------------------------------------------------------- *)
10725
10726 let AFF_DIM_NONEMPTY_INTERIOR_EQ = prove
10727  (`!s:real^N->bool.
10728         convex s ==> (aff_dim s = &(dimindex (:N)) <=> ~(interior s = {}))`,
10729   REPEAT STRIP_TAC THEN EQ_TAC THEN
10730   ASM_SIMP_TAC[AFF_DIM_NONEMPTY_INTERIOR] THEN
10731   REPEAT STRIP_TAC THEN
10732   MP_TAC(ISPEC `s:real^N->bool` EMPTY_INTERIOR_SUBSET_HYPERPLANE) THEN
10733   ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
10734   FIRST_ASSUM(MP_TAC o MATCH_MP AFF_DIM_SUBSET) THEN
10735   ASM_SIMP_TAC[AFF_DIM_HYPERPLANE] THEN INT_ARITH_TAC);;
10736
10737 let AFF_DIM_BALL = prove
10738  (`!a:real^N r.
10739         aff_dim(ball(a,r)) = if &0 < r then &(dimindex(:N)) else --(&1)`,
10740   REPEAT GEN_TAC THEN COND_CASES_TAC THENL
10741    [MATCH_MP_TAC AFF_DIM_OPEN THEN
10742     ASM_REWRITE_TAC[OPEN_BALL; BALL_EQ_EMPTY; REAL_NOT_LE];
10743     RULE_ASSUM_TAC(REWRITE_RULE[REAL_NOT_LT; GSYM BALL_EQ_EMPTY]) THEN
10744     ASM_REWRITE_TAC[AFF_DIM_EMPTY]]);;
10745
10746 let AFF_DIM_CBALL = prove
10747  (`!a:real^N r.
10748         aff_dim(cball(a,r)) =
10749             if &0 < r then &(dimindex(:N))
10750             else if r = &0 then &0 else --(&1)`,
10751   REPEAT GEN_TAC THEN REPEAT COND_CASES_TAC THENL
10752    [MATCH_MP_TAC AFF_DIM_NONEMPTY_INTERIOR THEN
10753     ASM_REWRITE_TAC[INTERIOR_CBALL; BALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC;
10754     ASM_SIMP_TAC[CBALL_SING; AFF_DIM_SING];
10755     MATCH_MP_TAC(MESON[AFF_DIM_EMPTY] `s = {} ==> aff_dim s = --(&1)`) THEN
10756     REWRITE_TAC[CBALL_EQ_EMPTY] THEN ASM_REAL_ARITH_TAC]);;
10757
10758 let AFF_DIM_INTERVAL = prove
10759  (`(!a b:real^N.
10760         aff_dim(interval[a,b]) =
10761                 if interval[a,b] = {} then --(&1)
10762                 else &(CARD {i | 1 <= i /\ i <= dimindex(:N) /\ a$i < b$i})) /\
10763    (!a b:real^N.
10764          aff_dim(interval(a,b)) =
10765                 if interval(a,b) = {} then --(&1)
10766                 else &(dimindex(:N)))`,
10767   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
10768   ASM_SIMP_TAC[AFF_DIM_EMPTY; AFF_DIM_OPEN; OPEN_INTERVAL] THEN
10769   POP_ASSUM MP_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN
10770   REPEAT STRIP_TAC THEN
10771   REWRITE_TAC[VECTOR_ADD_COMPONENT; VEC_COMPONENT; REAL_LT_LADD] THEN
10772   ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; ENDS_IN_INTERVAL] THEN AP_TERM_TAC THEN
10773   ONCE_REWRITE_TAC[GSYM DIM_SPAN] THEN MATCH_MP_TAC DIM_UNIQUE THEN EXISTS_TAC
10774    `{basis i:real^N | 1 <= i /\ i <= dimindex(:N) /\ &0 < (b:real^N)$i}` THEN
10775   RULE_ASSUM_TAC(REWRITE_RULE[INTERVAL_NE_EMPTY; VEC_COMPONENT]) THEN
10776   REPEAT CONJ_TAC THENL
10777    [REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
10778     X_GEN_TAC `i:num` THEN STRIP_TAC THEN
10779     SUBGOAL_THEN `basis i:real^N = inv(b$i) % (b:real^N)$i % basis i`
10780     SUBST1_TAC THENL
10781      [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_LT_IMP_NZ] THEN
10782       REWRITE_TAC[VECTOR_MUL_LID];
10783       MATCH_MP_TAC SPAN_MUL THEN MATCH_MP_TAC SPAN_SUPERSET THEN
10784       SIMP_TAC[IN_INTERVAL; VECTOR_MUL_COMPONENT; BASIS_COMPONENT] THEN
10785       X_GEN_TAC `j:num` THEN REWRITE_TAC[VEC_COMPONENT] THEN
10786       COND_CASES_TAC THEN
10787       ASM_SIMP_TAC[REAL_MUL_RZERO; REAL_MUL_RID; REAL_LE_REFL]];
10788     MATCH_MP_TAC SPAN_SUBSET_SUBSPACE THEN
10789     REWRITE_TAC[SUBSPACE_SPAN; SUBSET; IN_INTERVAL; VEC_COMPONENT] THEN
10790     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
10791     GEN_REWRITE_TAC LAND_CONV [GSYM BASIS_EXPANSION] THEN
10792     MATCH_MP_TAC SPAN_VSUM THEN REWRITE_TAC[FINITE_NUMSEG] THEN
10793     X_GEN_TAC `i:num` THEN REWRITE_TAC[IN_NUMSEG] THEN STRIP_TAC THEN
10794     ASM_CASES_TAC `&0 < (b:real^N)$i` THENL
10795      [MATCH_MP_TAC SPAN_MUL THEN MATCH_MP_TAC SPAN_SUPERSET THEN ASM SET_TAC[];
10796       SUBGOAL_THEN `(x:real^N)$i = &0`
10797         (fun th -> REWRITE_TAC[th; VECTOR_MUL_LZERO; SPAN_0]) THEN
10798       REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `i:num`)) THEN
10799       ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC];
10800     MATCH_MP_TAC PAIRWISE_ORTHOGONAL_INDEPENDENT THEN
10801     REWRITE_TAC[SET_RULE `~(a IN {f x | P x}) <=> !x. P x ==> ~(f x = a)`] THEN
10802     SIMP_TAC[BASIS_NONZERO; pairwise; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
10803     SIMP_TAC[FORALL_IN_GSPEC; BASIS_INJ_EQ; ORTHOGONAL_BASIS_BASIS];
10804     GEN_REWRITE_TAC LAND_CONV [SIMPLE_IMAGE_GEN] THEN
10805     MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN
10806     SIMP_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_GSPEC; BASIS_INJ_EQ;
10807              HAS_SIZE] THEN
10808     SIMP_TAC[CONJ_ASSOC; GSYM IN_NUMSEG; FINITE_RESTRICT; FINITE_NUMSEG]]);;
10809
10810 (* ------------------------------------------------------------------------- *)
10811 (* Deducing convexity from midpoint convexity in common cases.               *)
10812 (* ------------------------------------------------------------------------- *)
10813
10814 let MIDPOINT_CONVEX_DYADIC_RATIONALS = prove
10815  (`!f:real^N->real s.
10816         (!x y. x IN s /\ y IN s
10817                ==> midpoint(x,y) IN s /\
10818                    f(midpoint(x,y)) <= (f(x) + f(y)) / &2)
10819         ==> !n m p x y.
10820                 x IN s /\ y IN s /\ m + p = 2 EXP n
10821                 ==> (&m / &2 pow n % x + &p / &2 pow n % y) IN s /\
10822                     f(&m / &2 pow n % x + &p / &2 pow n % y)
10823                     <= &m / &2 pow n * f x + &p / &2 pow n * f y`,
10824   REPEAT GEN_TAC THEN DISCH_TAC THEN INDUCT_TAC THENL
10825    [REWRITE_TAC[ARITH_RULE
10826      `m + p = 2 EXP 0 <=> m = 0 /\ p = 1 \/ m = 1 /\ p = 0`] THEN
10827     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
10828     CONV_TAC REAL_RAT_REDUCE_CONV THEN
10829     ASM_REWRITE_TAC[VECTOR_MUL_LID; VECTOR_MUL_LZERO;
10830                   VECTOR_ADD_LID; VECTOR_ADD_RID] THEN
10831     REAL_ARITH_TAC;
10832     MATCH_MP_TAC WLOG_LE THEN CONJ_TAC THENL
10833      [REWRITE_TAC[VECTOR_ADD_SYM; REAL_ADD_SYM; ADD_SYM] THEN MESON_TAC[];
10834       ALL_TAC] THEN
10835     MAP_EVERY X_GEN_TAC [`m:num`; `p:num`] THEN DISCH_TAC THEN
10836     REPEAT GEN_TAC THEN REWRITE_TAC[EXP; real_pow] THEN STRIP_TAC THEN
10837     REWRITE_TAC[real_div; REAL_INV_MUL] THEN
10838     ONCE_REWRITE_TAC[REAL_ARITH `x * inv(&2) * y = inv(&2) * x * y`] THEN
10839     ONCE_REWRITE_TAC[GSYM REAL_MUL_ASSOC; GSYM VECTOR_MUL_ASSOC] THEN
10840     REWRITE_TAC[GSYM REAL_ADD_LDISTRIB; GSYM VECTOR_ADD_LDISTRIB] THEN
10841     SUBGOAL_THEN `2 EXP n <= p` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
10842     SUBGOAL_THEN `&p * inv(&2 pow n) = &(p - 2 EXP n) * inv(&2 pow n) + &1`
10843     SUBST1_TAC THENL
10844      [ASM_SIMP_TAC[GSYM REAL_OF_NUM_SUB; GSYM REAL_OF_NUM_POW] THEN
10845       ASM_SIMP_TAC[REAL_SUB_RDISTRIB; REAL_MUL_RINV; REAL_LT_IMP_NZ;
10846                    REAL_LT_POW2] THEN REAL_ARITH_TAC;
10847       REWRITE_TAC[VECTOR_ADD_RDISTRIB; REAL_ADD_RDISTRIB] THEN
10848       REWRITE_TAC[VECTOR_MUL_LID; REAL_MUL_LID] THEN
10849       REWRITE_TAC[VECTOR_ADD_ASSOC; REAL_ADD_ASSOC] THEN
10850       REWRITE_TAC[GSYM midpoint; GSYM real_div] THEN FIRST_X_ASSUM(fun th ->
10851         W(MP_TAC o PART_MATCH (lhand o rand) th o lhand o snd)) THEN
10852       FIRST_X_ASSUM(fun th ->
10853         W(MP_TAC o PART_MATCH (lhand o rand) th o funpow 3 lhand o  snd)) THEN
10854       ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
10855        [ASM_ARITH_TAC; SIMP_TAC[] THEN REAL_ARITH_TAC]]]);;
10856
10857 let CONTINUOUS_MIDPOINT_CONVEX = prove
10858  (`!f:real^N->real s.
10859         (lift o f) continuous_on s /\ convex s /\
10860         (!x y. x IN s /\ y IN s ==> f(midpoint(x,y)) <= (f(x) + f(y)) / &2)
10861          ==> f convex_on s`,
10862   REWRITE_TAC[midpoint] THEN REPEAT STRIP_TAC THEN REWRITE_TAC[convex_on] THEN
10863   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
10864   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[GSYM IMP_CONJ_ALT] THEN
10865   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
10866   REWRITE_TAC[REAL_ARITH `u + v = &1 <=> v = &1 - u`; IMP_CONJ] THEN
10867   REWRITE_TAC[FORALL_UNWIND_THM2; REAL_SUB_LE] THEN
10868   REWRITE_TAC[FORALL_DROP; GSYM DROP_VEC; IMP_IMP; GSYM IN_INTERVAL_1] THEN
10869   MP_TAC(ISPEC `interval[vec 0:real^1,vec 1]`
10870         CLOSURE_DYADIC_RATIONALS_IN_CONVEX_SET) THEN
10871   SIMP_TAC[CONVEX_INTERVAL; INTERIOR_CLOSED_INTERVAL;
10872            CLOSURE_CLOSED; CLOSED_INTERVAL; UNIT_INTERVAL_NONEMPTY] THEN
10873   REWRITE_TAC[DIMINDEX_1; FORALL_1; GSYM drop] THEN
10874   DISCH_THEN(fun th -> SUBST1_TAC(SYM th) THEN ASSUME_TAC th) THEN
10875   ONCE_REWRITE_TAC[REAL_ARITH `a <= b <=> a - b <= &0`] THEN
10876   MATCH_MP_TAC CONTINUOUS_LE_ON_CLOSURE THEN
10877   REWRITE_TAC[IN_INTER; IMP_CONJ_ALT; FORALL_IN_GSPEC] THEN
10878   FIRST_X_ASSUM SUBST1_TAC THEN
10879   REWRITE_TAC[IN_INTERVAL_1; DROP_CMUL; GSYM FORALL_DROP; DROP_VEC] THEN
10880   CONJ_TAC THENL
10881    [REWRITE_TAC[o_DEF; LIFT_SUB; LIFT_ADD; LIFT_CMUL] THEN
10882     MATCH_MP_TAC CONTINUOUS_ON_SUB THEN CONJ_TAC THENL
10883      [REPLICATE_TAC 2 (ONCE_REWRITE_TAC[GSYM o_DEF]) THEN
10884       REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
10885       CONJ_TAC THENL
10886        [ALL_TAC;
10887         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10888           CONTINUOUS_ON_SUBSET)) THEN
10889         REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1; GSYM FORALL_DROP;
10890                     DROP_VEC] THEN REPEAT STRIP_TAC THEN
10891         FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [convex]) THEN
10892         ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC];
10893       ALL_TAC] THEN
10894     MATCH_MP_TAC CONTINUOUS_ON_ADD THEN CONJ_TAC THEN
10895     MATCH_MP_TAC CONTINUOUS_ON_MUL THEN
10896     SIMP_TAC[o_DEF; LIFT_DROP; CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST;
10897              LIFT_SUB; CONTINUOUS_ON_SUB];
10898     MAP_EVERY X_GEN_TAC [`n:num`; `i:real`] THEN
10899     ASM_SIMP_TAC[REAL_LE_MUL_EQ; REAL_LT_INV_EQ; REAL_LT_POW2] THEN
10900     ASM_CASES_TAC `&0 <= i` THEN ASM_SIMP_TAC[INTEGER_POS] THEN
10901     DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST_ALL_TAC) THEN
10902     REWRITE_TAC[ONCE_REWRITE_RULE[REAL_MUL_SYM] (GSYM real_div)] THEN
10903     SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LT_POW2; REAL_MUL_LID] THEN
10904     GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV)
10905      [REAL_OF_NUM_POW; REAL_OF_NUM_LE] THEN DISCH_TAC THEN
10906     MP_TAC(ISPECL [`f:real^N->real`; `s:real^N->bool`]
10907         MIDPOINT_CONVEX_DYADIC_RATIONALS) THEN
10908     ANTS_TAC THENL
10909      [ASM_SIMP_TAC[midpoint] THEN REWRITE_TAC[VECTOR_ADD_LDISTRIB] THEN
10910       REPEAT STRIP_TAC THEN
10911       FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [convex]) THEN
10912       ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
10913       DISCH_THEN(MP_TAC o SPECL
10914        [`n:num`; `m:num`; `2 EXP n - m`; `x:real^N`; `y:real^N`]) THEN
10915       ASM_REWRITE_TAC[] THEN
10916       ANTS_TAC THENL [ASM_ARITH_TAC; DISCH_THEN(MP_TAC o CONJUNCT2)] THEN
10917       ASM_SIMP_TAC[GSYM REAL_OF_NUM_SUB; GSYM REAL_OF_NUM_POW] THEN
10918       ASM_SIMP_TAC[REAL_LT_POW2; REAL_FIELD
10919        `&0 < y ==> (y - x) / y = &1 - x / y`] THEN
10920       REAL_ARITH_TAC]]);;
10921
10922 (* ------------------------------------------------------------------------- *)
10923 (* Slightly shaper separating/supporting hyperplane results.                 *)
10924 (* ------------------------------------------------------------------------- *)
10925
10926 let SEPARATING_HYPERPLANE_RELATIVE_INTERIORS = prove
10927  (`!s t. convex s /\ convex t /\
10928          ~(s = {} /\ t = (:real^N) \/ s = (:real^N) /\ t = {}) /\
10929          DISJOINT (relative_interior s) (relative_interior t)
10930          ==> ?a b. ~(a = vec 0) /\
10931                    (!x. x IN s ==> a dot x <= b) /\
10932                    (!x. x IN t ==> a dot x >= b)`,
10933   REPEAT GEN_TAC THEN MAP_EVERY ASM_CASES_TAC
10934    [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
10935   ASM_REWRITE_TAC[NOT_IN_EMPTY; UNIV_NOT_EMPTY; CONVEX_EMPTY;
10936                   RELATIVE_INTERIOR_EMPTY] THEN
10937   STRIP_TAC THENL
10938    [EXISTS_TAC `basis 1:real^N` THEN
10939     SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL];
10940     FIRST_X_ASSUM(X_CHOOSE_TAC `x:real^N` o MATCH_MP (SET_RULE
10941      `~(s = UNIV) ==> ?a. ~(a IN s)`)) THEN
10942     MP_TAC(ISPECL [`t:real^N->bool`; `x:real^N`]
10943         SEPARATING_HYPERPLANE_SET_POINT_INAFF) THEN
10944     ASM_MESON_TAC[];
10945     FIRST_X_ASSUM(X_CHOOSE_TAC `x:real^N` o MATCH_MP (SET_RULE
10946      `~(s = UNIV) ==> ?a. ~(a IN s)`)) THEN
10947     MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`]
10948         SEPARATING_HYPERPLANE_SET_POINT_INAFF) THEN
10949     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; real_ge] THEN
10950     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN STRIP_TAC THEN
10951     MAP_EVERY EXISTS_TAC [`--a:real^N`; `--b:real`] THEN
10952     ASM_REWRITE_TAC[VECTOR_NEG_EQ_0; DOT_LNEG; REAL_LE_NEG2];
10953     MP_TAC(ISPECL [`relative_interior s:real^N->bool`;
10954                    `relative_interior t:real^N->bool`]
10955           SEPARATING_HYPERPLANE_SETS) THEN
10956     ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY; CONVEX_RELATIVE_INTERIOR] THEN
10957     SIMP_TAC[real_ge] THEN MATCH_MP_TAC MONO_EXISTS THEN
10958     X_GEN_TAC `a:real^N` THEN MATCH_MP_TAC MONO_EXISTS THEN
10959     X_GEN_TAC `b:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
10960     CONJ_TAC THEN MATCH_MP_TAC
10961     (MESON[CONVEX_CLOSURE_RELATIVE_INTERIOR; CLOSURE_SUBSET; SUBSET]
10962       `convex s /\ (!x. x IN closure(relative_interior s) ==> P x)
10963        ==> !x. x IN s ==> P x`) THEN
10964     ASM_REWRITE_TAC[] THENL
10965      [MATCH_MP_TAC CONTINUOUS_LE_ON_CLOSURE;
10966       MATCH_MP_TAC CONTINUOUS_GE_ON_CLOSURE] THEN
10967     ASM_REWRITE_TAC[CONTINUOUS_ON_LIFT_DOT]]);;
10968
10969 let SUPPORTING_HYPERPLANE_RELATIVE_BOUNDARY = prove
10970  (`!s x:real^N.
10971         convex s /\ x IN s /\ ~(x IN relative_interior s)
10972         ==> ?a. ~(a = vec 0) /\
10973                 (!y. y IN s ==> a dot x <= a dot y) /\
10974                 (!y. y IN relative_interior s ==> a dot x < a dot y)`,
10975   REPEAT STRIP_TAC THEN
10976   MP_TAC(ISPECL [`relative_interior s:real^N->bool`; `x:real^N`]
10977         SEPARATING_HYPERPLANE_SET_POINT_INAFF) THEN
10978   ASM_SIMP_TAC[CONVEX_SING; CONVEX_RELATIVE_INTERIOR;
10979                RELATIVE_INTERIOR_EQ_EMPTY; real_ge] THEN
10980   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10981   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
10982   REWRITE_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY] THEN
10983   DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THEN ASM_SIMP_TAC[] THEN
10984   MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
10985    [X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
10986     MP_TAC(ISPECL [`lift o (\x:real^N. a dot x)`;
10987                    `relative_interior s:real^N->bool`;
10988                    `y:real^N`; `(a:real^N) dot x`; `1`]
10989       CONTINUOUS_ON_CLOSURE_COMPONENT_GE) THEN
10990     REWRITE_TAC[CONTINUOUS_ON_LIFT_DOT; GSYM drop; o_THM; LIFT_DROP] THEN
10991     ASM_SIMP_TAC[CONVEX_CLOSURE_RELATIVE_INTERIOR] THEN
10992     ASM_MESON_TAC[CLOSURE_SUBSET; REAL_LE_TRANS; SUBSET];
10993     DISCH_TAC] THEN
10994   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
10995   REWRITE_TAC[REAL_LT_LE] THEN CONJ_TAC THENL
10996    [ASM_MESON_TAC[REAL_LE_TRANS]; ALL_TAC] THEN
10997   DISCH_TAC THEN UNDISCH_TAC `(y:real^N) IN relative_interior s` THEN
10998   REWRITE_TAC[IN_RELATIVE_INTERIOR_CBALL] THEN
10999   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
11000   REWRITE_TAC[LEFT_IMP_EXISTS_THM; SUBSET; IN_INTER; IN_CBALL] THEN
11001   X_GEN_TAC `e:real` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
11002   DISCH_THEN(MP_TAC o SPEC `y + --(e / norm(a)) % ((x + a) - x):real^N`) THEN
11003   REWRITE_TAC[NOT_IMP] THEN REPEAT CONJ_TAC THENL
11004    [SIMP_TAC[NORM_ARITH `dist(y:real^N,y + e) = norm e`; VECTOR_ADD_SUB] THEN
11005     REWRITE_TAC[NORM_MUL; REAL_ABS_NEG; REAL_ABS_DIV; REAL_ABS_NORM] THEN
11006     ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN ASM_REAL_ARITH_TAC;
11007     MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN
11008     ASM_SIMP_TAC[AFFINE_AFFINE_HULL; HULL_INC] THEN
11009     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
11010      `x IN s ==> s SUBSET t ==> x IN t`)) THEN
11011     MATCH_MP_TAC HULL_MONO THEN
11012     ASM_REWRITE_TAC[INSERT_SUBSET; RELATIVE_INTERIOR_SUBSET];
11013     REWRITE_TAC[VECTOR_ADD_SUB] THEN DISCH_TAC THEN
11014     UNDISCH_TAC `!y:real^N. y IN s ==> a dot x <= a dot y` THEN
11015     DISCH_THEN(MP_TAC o SPEC `y + --(e / norm(a)) % a:real^N`) THEN
11016     ASM_REWRITE_TAC[DOT_RMUL; DOT_RNEG; DOT_RADD] THEN
11017     MATCH_MP_TAC(REAL_ARITH `&0 < x * y ==> ~(a <= a + --x * y)`) THEN
11018     ASM_SIMP_TAC[REAL_LT_MUL; REAL_LT_DIV; NORM_POS_LT; DOT_POS_LT]]);;
11019
11020 let SUPPORTING_HYPERPLANE_RELATIVE_FRONTIER = prove
11021  (`!s x:real^N.
11022         convex s /\ x IN closure s /\ ~(x IN relative_interior s)
11023         ==> ?a. ~(a = vec 0) /\
11024                 (!y. y IN closure s ==> a dot x <= a dot y) /\
11025                 (!y. y IN relative_interior s ==> a dot x < a dot y)`,
11026   REPEAT STRIP_TAC THEN
11027   MP_TAC(ISPECL [`closure s:real^N->bool`; `x:real^N`]
11028     SUPPORTING_HYPERPLANE_RELATIVE_BOUNDARY) THEN
11029   ASM_SIMP_TAC[CONVEX_CLOSURE; CONVEX_RELATIVE_INTERIOR_CLOSURE]);;
11030
11031 (* ------------------------------------------------------------------------- *)
11032 (* Containment of rays in unbounded convex sets.                             *)
11033 (* ------------------------------------------------------------------------- *)
11034
11035 let UNBOUNDED_CONVEX_CLOSED_CONTAINS_RAY = prove
11036  (`!s a:real^N.
11037         convex s /\ ~bounded s /\ closed s /\ a IN s
11038         ==> ?l. ~(l = vec 0) /\ !t. &0 <= t ==> (a + t % l) IN s`,
11039   GEN_GEOM_ORIGIN_TAC `a:real^N` ["l"] THEN
11040   REWRITE_TAC[VECTOR_ADD_LID] THEN REPEAT STRIP_TAC THEN
11041   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [BOUNDED_POS]) THEN
11042   REWRITE_TAC[NOT_EXISTS_THM; TAUT `~(p /\ q) <=> p ==> ~q`] THEN
11043   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC `&n + &1:real`) THEN
11044   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; REAL_ARITH `&0 < &n + &1`] THEN
11045   REWRITE_TAC[REAL_NOT_LE; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
11046   X_GEN_TAC `x:num->real^N` THEN REWRITE_TAC[FORALL_AND_THM] THEN
11047   STRIP_TAC THEN
11048   SUBGOAL_THEN `!n. ~((x:num->real^N) n = vec 0)` ASSUME_TAC THENL
11049    [ASM_MESON_TAC[NORM_ARITH `~(&n + &1 < norm(vec 0:real^N))`]; ALL_TAC] THEN
11050   MP_TAC(ISPEC `sphere(vec 0:real^N,&1)` compact) THEN
11051   REWRITE_TAC[COMPACT_SPHERE] THEN
11052   DISCH_THEN(MP_TAC o SPEC `\n. inv(norm(x n)) % (x:num->real^N) n`) THEN
11053   ASM_SIMP_TAC[IN_SPHERE_0; NORM_MUL; REAL_ABS_INV; REAL_ABS_NORM;
11054                REAL_MUL_LINV; NORM_EQ_0; o_DEF] THEN
11055   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real^N` THEN
11056   DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN CONJ_TAC THENL
11057    [ASM_MESON_TAC[NORM_ARITH `~(norm(vec 0:real^N) = &1)`]; ALL_TAC] THEN
11058   X_GEN_TAC `t:real` THEN DISCH_TAC THEN
11059   MATCH_MP_TAC CLOSED_CONTAINS_SEQUENTIAL_LIMIT THEN
11060   SUBGOAL_THEN
11061    `?N:num. !n. N <= n ==> t / norm(x n:real^N) <= &1`
11062   STRIP_ASSUME_TAC THENL
11063    [ASM_SIMP_TAC[REAL_LE_LDIV_EQ; NORM_POS_LT] THEN
11064     MP_TAC(SPEC `t:real` REAL_ARCH_SIMPLE) THEN
11065     MATCH_MP_TAC MONO_EXISTS THEN
11066     REWRITE_TAC[GSYM REAL_OF_NUM_LE; REAL_MUL_LID] THEN
11067     ASM_MESON_TAC[REAL_ARITH `t <= m /\ m <= n /\ n + &1 < x ==> t <= x`];
11068     EXISTS_TAC `\n:num. t / norm((x:num->real^N)(r(N + n))) % x(r(N + n))` THEN
11069     ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
11070      [X_GEN_TAC `n:num` THEN
11071       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
11072       DISCH_THEN(MP_TAC o SPEC `vec 0:real^N`) THEN
11073       ASM_REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
11074       DISCH_THEN MATCH_MP_TAC THEN ASM_SIMP_TAC[REAL_LE_DIV; NORM_POS_LE] THEN
11075       FIRST_X_ASSUM MATCH_MP_TAC THEN
11076       FIRST_ASSUM(MP_TAC o SPEC `N + n:num` o MATCH_MP MONOTONE_BIGGER) THEN
11077       ARITH_TAC;
11078       REWRITE_TAC[real_div; GSYM VECTOR_MUL_ASSOC] THEN
11079       MATCH_MP_TAC LIM_CMUL THEN ONCE_REWRITE_TAC[ADD_SYM] THEN
11080       FIRST_ASSUM(MP_TAC o SPEC `N:num` o MATCH_MP SEQ_OFFSET) THEN
11081       ASM_REWRITE_TAC[]]]);;
11082
11083 let CONVEX_CLOSED_CONTAINS_SAME_RAY = prove
11084  (`!s a b l:real^N.
11085         convex s /\ closed s /\ b IN s /\ (!t. &0 <= t ==> (a + t % l) IN s)
11086         ==> !t. &0 <= t ==> (b + t % l) IN s`,
11087   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `&0`) THEN
11088   REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_RID] THEN DISCH_TAC THEN
11089   MATCH_MP_TAC(ISPEC `sequentially` LIM_IN_CLOSED_SET) THEN
11090   EXISTS_TAC `\n. (&1 - t / (&n + &1)) % b +
11091                   t / (&n + &1) % (a + (&n + &1) % l):real^N` THEN
11092   ASM_REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY] THEN CONJ_TAC THENL
11093    [REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
11094     MP_TAC(SPEC `t:real` REAL_ARCH_SIMPLE) THEN
11095     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
11096     DISCH_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
11097     FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
11098     ASM_SIMP_TAC[REAL_LE_DIV; REAL_ARITH `&0 <= &n + &1`] THEN
11099     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
11100     RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC;
11101     REWRITE_TAC[VECTOR_ARITH
11102      `(&1 - u) % b + u % c:real^N = b + u % (c - b)`] THEN
11103     MATCH_MP_TAC LIM_ADD THEN REWRITE_TAC[LIM_CONST] THEN
11104     REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_SUB_LDISTRIB] THEN
11105     SIMP_TAC[VECTOR_MUL_ASSOC; REAL_FIELD `t / (&n + &1) * (&n + &1) = t`] THEN
11106     SIMP_TAC[VECTOR_ARITH `(v % a + b) - v % c:real^N = b + v % (a - c)`] THEN
11107     GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_ADD_RID] THEN
11108     MATCH_MP_TAC LIM_ADD THEN REWRITE_TAC[LIM_CONST] THEN
11109     REWRITE_TAC[real_div; VECTOR_ARITH `(x * y) % a:real^N = y % x % a`] THEN
11110     MATCH_MP_TAC LIM_NULL_VMUL_BOUNDED THEN
11111     EXISTS_TAC `norm(t % (a - b):real^N)` THEN
11112     REWRITE_TAC[REAL_LE_REFL; EVENTUALLY_TRUE; o_DEF] THEN
11113     MP_TAC(MATCH_MP SEQ_OFFSET SEQ_HARMONIC) THEN
11114     SIMP_TAC[REAL_OF_NUM_ADD]]);;
11115
11116 let UNBOUNDED_CONVEX_CLOSED_CONTAINS_RAYS = prove
11117  (`!s:real^N->bool.
11118         convex s /\ ~bounded s /\ closed s
11119         ==> ?l. ~(l = vec 0) /\ !a t. a IN s /\ &0 <= t ==> (a + t % l) IN s`,
11120   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
11121   ASM_REWRITE_TAC[BOUNDED_EMPTY] THEN
11122   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
11123   ASM_MESON_TAC[UNBOUNDED_CONVEX_CLOSED_CONTAINS_RAY;
11124                 CONVEX_CLOSED_CONTAINS_SAME_RAY]);;
11125
11126 let RELATIVE_INTERIOR_UNBOUNDED_CONVEX_CONTAINS_RAY = prove
11127  (`!s a:real^N.
11128         convex s /\ ~bounded s /\ a IN relative_interior s
11129         ==> ?l. ~(l = vec 0) /\
11130                 !t. &0 <= t ==> (a + t % l) IN relative_interior s`,
11131   REPEAT STRIP_TAC THEN
11132   MP_TAC(ISPECL [`closure s:real^N->bool`; `a:real^N`]
11133         UNBOUNDED_CONVEX_CLOSED_CONTAINS_RAY) THEN
11134   ASM_SIMP_TAC[CONVEX_CLOSURE; CLOSED_CLOSURE] THEN ANTS_TAC THENL
11135    [ASM_MESON_TAC[BOUNDED_SUBSET; SUBSET; CLOSURE_SUBSET;
11136                   RELATIVE_INTERIOR_SUBSET];
11137     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real^N` THEN STRIP_TAC THEN
11138     ASM_REWRITE_TAC[] THEN
11139     ONCE_REWRITE_TAC[VECTOR_ARITH
11140       `a + t % l:real^N =
11141        (a + (&2 * t) % l) - inv(&2) % ((a + (&2 * t) % l) - a)`] THEN
11142     REPEAT STRIP_TAC THEN
11143     MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
11144     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN
11145     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC]);;
11146
11147 let RELATIVE_INTERIOR_CONVEX_CONTAINS_SAME_RAY = prove
11148  (`!s a b l:real^N.
11149         convex s /\ b IN relative_interior s /\
11150         (!t. &0 <= t ==> (a + t % l) IN relative_interior s)
11151         ==> !t. &0 <= t ==> (b + t % l) IN relative_interior s`,
11152   REPEAT STRIP_TAC THEN
11153   MP_TAC(ISPECL [`closure s:real^N->bool`; `a:real^N`; `b:real^N`; `l:real^N`]
11154         CONVEX_CLOSED_CONTAINS_SAME_RAY) THEN
11155   ASM_SIMP_TAC[CONVEX_CLOSURE; CLOSED_CLOSURE] THEN ANTS_TAC THENL
11156    [ASM_MESON_TAC[BOUNDED_SUBSET; SUBSET; CLOSURE_SUBSET;
11157                   RELATIVE_INTERIOR_SUBSET];
11158     DISCH_TAC THEN
11159     ONCE_REWRITE_TAC[VECTOR_ARITH
11160       `a + t % l:real^N =
11161        (a + (&2 * t) % l) - inv(&2) % ((a + (&2 * t) % l) - a)`] THEN
11162     REPEAT STRIP_TAC THEN
11163     MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SHRINK THEN
11164     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[] THEN
11165     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC]);;
11166
11167 let RELATIVE_INTERIOR_UNBOUNDED_CONVEX_CONTAINS_RAYS = prove
11168  (`!s:real^N->bool.
11169         convex s /\ ~bounded s
11170         ==> ?l. ~(l = vec 0) /\
11171                 !a t. a IN relative_interior s /\ &0 <= t
11172                       ==> (a + t % l) IN relative_interior s`,
11173   REPEAT GEN_TAC THEN
11174   ASM_CASES_TAC `relative_interior s:real^N->bool = {}` THENL
11175    [ASM_MESON_TAC[RELATIVE_INTERIOR_EQ_EMPTY; BOUNDED_EMPTY]; ALL_TAC] THEN
11176   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
11177   ASM_MESON_TAC[RELATIVE_INTERIOR_UNBOUNDED_CONVEX_CONTAINS_RAY;
11178                 RELATIVE_INTERIOR_CONVEX_CONTAINS_SAME_RAY]);;
11179
11180 (* ------------------------------------------------------------------------- *)
11181 (* Explicit formulas for interior and relative interior of convex hull.      *)
11182 (* ------------------------------------------------------------------------- *)
11183
11184 let EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL = prove
11185  (`!s. FINITE s
11186        ==> {y:real^N | ?u. (!x. x IN s ==> &0 < u x /\ u x < &1) /\
11187                            sum s u = &1 /\
11188                            vsum s (\x. u x % x) = y}
11189        SUBSET relative_interior(convex hull s)`,
11190   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
11191   ASM_REWRITE_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH_EQ] THEN
11192   REWRITE_TAC[EMPTY_GSPEC; EMPTY_SUBSET] THEN
11193   REPEAT STRIP_TAC THEN MATCH_MP_TAC RELATIVE_INTERIOR_MAXIMAL THEN
11194   REWRITE_TAC[AFFINE_HULL_CONVEX_HULL] THEN CONJ_TAC THENL
11195    [REWRITE_TAC[CONVEX_HULL_FINITE; SUBSET; IN_ELIM_THM] THEN
11196     GEN_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[REAL_LT_IMP_LE];
11197     ALL_TAC] THEN
11198   REWRITE_TAC[open_in; IN_ELIM_THM] THEN CONJ_TAC THENL
11199    [REWRITE_TAC[AFFINE_HULL_FINITE; SUBSET; IN_ELIM_THM] THEN
11200     GEN_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[REAL_LT_IMP_LE];
11201     ALL_TAC] THEN
11202   X_GEN_TAC `y:real^N` THEN
11203   DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC) THEN
11204   ABBREV_TAC `e = inf (IMAGE (\x:real^N. min (&1 - u x) (u x)) s)` THEN
11205   SUBGOAL_THEN `&0 < e` ASSUME_TAC THENL
11206    [EXPAND_TAC "e" THEN
11207     ASM_SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
11208     ASM_SIMP_TAC[REAL_LT_MIN; REAL_SUB_LT; FORALL_IN_IMAGE];
11209     ALL_TAC] THEN
11210   MP_TAC(ISPEC `IMAGE (\z:real^N. z - y) (affine hull s)` BASIS_EXISTS) THEN
11211   REWRITE_TAC[SUBSET_IMAGE] THEN
11212   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool`
11213    (CONJUNCTS_THEN2 (X_CHOOSE_THEN `c:real^N->bool` (STRIP_ASSUME_TAC o GSYM))
11214                     MP_TAC)) THEN
11215   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; HAS_SIZE] THEN
11216   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
11217   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
11218   ASM_SIMP_TAC[SPAN_FINITE; IN_ELIM_THM] THEN
11219   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
11220   REWRITE_TAC[SKOLEM_THM] THEN
11221   DISCH_THEN(X_CHOOSE_TAC `compo:real^N->real^N->real`) THEN
11222   FIRST_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o
11223     MATCH_MP BASIS_COORDINATES_LIPSCHITZ) THEN
11224   SUBGOAL_THEN
11225    `!i. i IN b ==> ?u. sum s u = &0 /\ vsum s (\x:real^N. u x % x) = i`
11226   MP_TAC THENL
11227    [EXPAND_TAC "b" THEN REWRITE_TAC[FORALL_IN_IMAGE] THEN
11228     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
11229     SUBGOAL_THEN `(x:real^N) IN affine hull s` MP_TAC THENL
11230      [ASM SET_TAC[]; REWRITE_TAC[AFFINE_HULL_FINITE; IN_ELIM_THM]] THEN
11231     DISCH_THEN(X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC) THEN
11232     EXISTS_TAC `(\x. v x - u x):real^N->real` THEN
11233     ASM_SIMP_TAC[SUM_SUB; VSUM_SUB; VECTOR_SUB_RDISTRIB] THEN
11234     REWRITE_TAC[REAL_SUB_REFL; VECTOR_SUB_RZERO];
11235     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
11236      [RIGHT_IMP_EXISTS_THM; SKOLEM_THM; FORALL_AND_THM;
11237                 TAUT `(a ==> b /\ c) <=> (a ==> b) /\ (a ==> c)`] THEN
11238     DISCH_THEN(X_CHOOSE_THEN `w:real^N->real^N->real` STRIP_ASSUME_TAC)] THEN
11239   EXISTS_TAC `e / B /
11240               (&1 + sum (b:real^N->bool)
11241                    (\i. abs(sup(IMAGE (abs o w i) (s:real^N->bool)))))` THEN
11242   ASM_SIMP_TAC[REAL_LT_DIV; REAL_ARITH `&0 <= x ==> &0 < &1 + x`;
11243                SUM_POS_LE; REAL_ABS_POS] THEN
11244   X_GEN_TAC `z:real^N` THEN STRIP_TAC THEN
11245   EXISTS_TAC
11246    `\x:real^N. u x + sum (b:real^N->bool)
11247                          (\i. compo (z:real^N) i * w i x)` THEN
11248   REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
11249    [ALL_TAC;
11250     ASM_SIMP_TAC[SUM_ADD; REAL_ARITH `&1 + x = &1 <=> x = &0`] THEN
11251     W(MP_TAC o PART_MATCH (lhs o rand) SUM_SWAP o lhand o snd) THEN
11252     ASM_REWRITE_TAC[FINITE_NUMSEG] THEN DISCH_THEN SUBST1_TAC THEN
11253     MATCH_MP_TAC SUM_EQ_0 THEN
11254     ASM_SIMP_TAC[SUM_LMUL; ETA_AX; REAL_MUL_RZERO; SUM_0];
11255     ASM_SIMP_TAC[VSUM_ADD; VECTOR_ADD_RDISTRIB] THEN
11256     ONCE_REWRITE_TAC[VECTOR_ARITH `y + w:real^N = z <=> w = z - y`] THEN
11257     ASM_SIMP_TAC[GSYM VSUM_LMUL; GSYM VSUM_RMUL; GSYM VECTOR_MUL_ASSOC] THEN
11258     W(MP_TAC o PART_MATCH (lhs o rand) VSUM_SWAP o lhand o snd) THEN
11259     ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST1_TAC THEN
11260     ASM_SIMP_TAC[VSUM_LMUL] THEN MATCH_MP_TAC EQ_TRANS THEN
11261     EXISTS_TAC `vsum b (\v:real^N. compo (z:real^N) v % v)` THEN
11262     CONJ_TAC THENL [ALL_TAC; ASM_SIMP_TAC[]] THEN
11263     MATCH_MP_TAC VSUM_EQ THEN ASM_SIMP_TAC[]] THEN
11264   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[] THEN
11265   MATCH_MP_TAC(REAL_ARITH
11266    `abs(x) < min u (&1 - u) ==> &0 < u + x /\ u + x < &1`) THEN
11267   MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC
11268     `B * norm(z - y:real^N) * sum (b:real^N->bool)
11269                    (\i. abs(sup(IMAGE (abs o w i) (s:real^N->bool))))` THEN
11270   CONJ_TAC THENL
11271    [REWRITE_TAC[GSYM SUM_LMUL] THEN MATCH_MP_TAC SUM_ABS_LE THEN
11272     ASM_REWRITE_TAC[REAL_ABS_MUL; REAL_MUL_ASSOC] THEN
11273     X_GEN_TAC `i:real^N` THEN STRIP_TAC THEN MATCH_MP_TAC REAL_LE_MUL2 THEN
11274     REWRITE_TAC[REAL_ABS_POS] THEN CONJ_TAC THENL
11275      [FIRST_X_ASSUM(MP_TAC o SPECL [`(compo:real^N->real^N->real) z`;
11276                                   `i:real^N`]) THEN
11277       ASM_SIMP_TAC[];
11278       MATCH_MP_TAC(REAL_ARITH `x <= a ==> x <= abs a`) THEN
11279       ASM_SIMP_TAC[REAL_LE_SUP_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
11280       REWRITE_TAC[EXISTS_IN_IMAGE; o_THM] THEN ASM_MESON_TAC[REAL_LE_REFL]];
11281     ALL_TAC] THEN
11282   GEN_REWRITE_TAC LAND_CONV [REAL_MUL_SYM] THEN
11283   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ] THEN
11284   MATCH_MP_TAC(REAL_ARITH
11285    `&0 <= x /\ x * (&1 + e) < d ==> x * e < d`) THEN
11286   REWRITE_TAC[NORM_POS_LE] THEN
11287   ASM_SIMP_TAC[NORM_POS_LE; GSYM REAL_LT_RDIV_EQ;
11288                REAL_ARITH `&0 <= x ==> &0 < &1 + x`;
11289                SUM_POS_LE; REAL_ABS_POS] THEN
11290   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (NORM_ARITH
11291    `dist(z:real^N,y) < k ==> k <= d ==> norm(z - y) < d`)) THEN
11292   ASM_SIMP_TAC[REAL_LE_DIV2_EQ; REAL_ARITH `&0 <= x ==> &0 < &1 + x`;
11293                SUM_POS_LE; REAL_ABS_POS] THEN
11294   EXPAND_TAC "e" THEN
11295   ASM_SIMP_TAC[REAL_INF_LE_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
11296   REWRITE_TAC[EXISTS_IN_IMAGE] THEN EXISTS_TAC `x:real^N` THEN
11297   ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
11298
11299 let EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL_MINIMAL = prove
11300  (`!s. FINITE s
11301        ==> {y:real^N | ?u. (!x. x IN s ==> &0 < u x) /\
11302                            sum s u = &1 /\
11303                            vsum s (\x. u x % x) = y}
11304        SUBSET relative_interior(convex hull s)`,
11305   REPEAT STRIP_TAC THEN
11306   ASM_CASES_TAC `s:real^N->bool = {}` THEN
11307   ASM_REWRITE_TAC[SUM_CLAUSES; REAL_OF_NUM_EQ; ARITH_EQ] THEN
11308   REWRITE_TAC[EMPTY_GSPEC; EMPTY_SUBSET] THEN
11309   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
11310   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
11311   ASM_CASES_TAC `s = {a:real^N}` THENL
11312    [ASM_REWRITE_TAC[SUM_SING; VSUM_SING; FORALL_IN_INSERT; NOT_IN_EMPTY] THEN
11313     REWRITE_TAC[RELATIVE_INTERIOR_SING; CONVEX_HULL_SING] THEN
11314     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_SING] THEN
11315     MESON_TAC[VECTOR_MUL_LID];
11316     FIRST_ASSUM(MP_TAC o MATCH_MP
11317       EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL) THEN
11318     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] SUBSET_TRANS) THEN
11319     REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `w:real^N` THEN
11320     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^N->real` THEN
11321     STRIP_TAC THEN ASM_SIMP_TAC[] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
11322     SUBGOAL_THEN `?y:real^N. y IN s /\ ~(y = x)` STRIP_ASSUME_TAC THENL
11323      [ASM SET_TAC[]; ALL_TAC] THEN
11324     SUBGOAL_THEN `sum {x,y} u <= sum s (u:real^N->real)` MP_TAC THENL
11325      [MATCH_MP_TAC SUM_SUBSET_SIMPLE THEN
11326       ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE; REAL_LT_IMP_LE; IN_DIFF] THEN
11327       ASM SET_TAC[];
11328       ASM_SIMP_TAC[SUM_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
11329       ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
11330       MATCH_MP_TAC(REAL_ARITH `&0 < y ==> x + y + &0 <= &1 ==> x < &1`) THEN
11331       ASM_SIMP_TAC[]]]);;
11332
11333 let RELATIVE_INTERIOR_CONVEX_HULL_EXPLICIT = prove
11334  (`!s. ~(affine_dependent s)
11335        ==> relative_interior(convex hull s) =
11336              {y:real^N | ?u. (!x. x IN s ==> &0 < u x) /\
11337                              sum s u = &1 /\
11338                              vsum s (\x. u x % x) = y}`,
11339   REPEAT STRIP_TAC THEN
11340   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11341   MATCH_MP_TAC SUBSET_ANTISYM THEN
11342   ASM_SIMP_TAC[EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL_MINIMAL] THEN
11343   ASM_CASES_TAC `?a:real^N. s = {a}` THENL
11344    [FIRST_X_ASSUM(CHOOSE_THEN SUBST1_TAC) THEN
11345     ASM_REWRITE_TAC[SUM_SING; VSUM_SING; CONVEX_HULL_SING;
11346                     RELATIVE_INTERIOR_SING] THEN
11347     REWRITE_TAC[IN_ELIM_THM; SUBSET; IN_SING] THEN
11348     REPEAT STRIP_TAC THEN EXISTS_TAC `\x:real^N. &1` THEN
11349     ASM_REWRITE_TAC[VECTOR_MUL_LID; REAL_LT_01];
11350     ALL_TAC] THEN
11351   MATCH_MP_TAC(SET_RULE
11352    `relative_interior s SUBSET s /\
11353     (!x. x IN s /\ ~(x IN t) ==> ~(x IN relative_interior s))
11354     ==> relative_interior s SUBSET t`) THEN
11355   REWRITE_TAC[RELATIVE_INTERIOR_SUBSET] THEN
11356   X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_RELATIVE_INTERIOR] THEN
11357   REWRITE_TAC[AFFINE_HULL_CONVEX_HULL; IN_ELIM_THM; NOT_EXISTS_THM] THEN
11358   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
11359   DISCH_THEN(CONJUNCTS_THEN2
11360    (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC)
11361    (MP_TAC o SPEC `u:real^N->real`)) THEN
11362   ASM_REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; IN_RELATIVE_INTERIOR; DE_MORGAN_THM;
11363                   SUBSET; IN_ELIM_THM; IN_BALL; IN_INTER] THEN
11364   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN DISJ2_TAC THEN
11365   DISCH_THEN(X_CHOOSE_THEN `e:real`
11366    (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "*"))) THEN
11367   SUBGOAL_THEN `(u:real^N->real) a = &0` ASSUME_TAC THENL
11368    [ASM_SIMP_TAC[REAL_ARITH `&0 <= x /\ ~(&0 < x) ==> x = &0`]; ALL_TAC] THEN
11369   SUBGOAL_THEN `?b:real^N. b IN s /\ ~(b = a)` STRIP_ASSUME_TAC THENL
11370    [ASM SET_TAC[];ALL_TAC] THEN
11371   SUBGOAL_THEN `?d. &0 < d /\ norm(d % (a - b):real^N) < e`
11372   STRIP_ASSUME_TAC THENL
11373    [EXISTS_TAC `e / &2 / norm(a - b:real^N)` THEN
11374     ASM_SIMP_TAC[NORM_MUL; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH; NORM_POS_LT;
11375                  REAL_ABS_DIV; REAL_ABS_NORM; REAL_ABS_NUM;
11376                  REAL_DIV_RMUL; REAL_LT_IMP_NZ; VECTOR_SUB_EQ] THEN
11377     ASM_REAL_ARITH_TAC;
11378     ALL_TAC] THEN
11379   REMOVE_THEN "*" (MP_TAC o SPEC `y - d % (a - b):real^N`) THEN
11380   ASM_REWRITE_TAC[NORM_ARITH `dist(a:real^N,a - b) = norm b`] THEN
11381   REWRITE_TAC[NOT_IMP] THEN CONJ_TAC THENL
11382    [MATCH_MP_TAC IN_AFFINE_SUB_MUL_DIFF THEN
11383     ASM_SIMP_TAC[HULL_INC; AFFINE_AFFINE_HULL] THEN
11384     REWRITE_TAC[AFFINE_HULL_FINITE; IN_ELIM_THM] THEN
11385     EXISTS_TAC `u:real^N->real` THEN ASM_REWRITE_TAC[];
11386     ALL_TAC] THEN
11387   DISCH_THEN(X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC) THEN
11388   UNDISCH_TAC `~(affine_dependent(s:real^N->bool))` THEN
11389   ASM_SIMP_TAC[AFFINE_DEPENDENT_EXPLICIT_FINITE] THEN
11390   EXISTS_TAC `\x:real^N. (v x - u x) -
11391                    (if x = a then --d else if x = b then d else &0)` THEN
11392   REWRITE_TAC[VECTOR_SUB_RDISTRIB; MESON[]
11393    `(if p then a else b) % x = (if p then a % x else b % x)`] THEN
11394   ASM_SIMP_TAC[SUM_SUB; VSUM_SUB] THEN
11395   ASM_SIMP_TAC[VSUM_CASES; SUM_CASES; FINITE_RESTRICT; IN_ELIM_THM] THEN
11396   ASM_SIMP_TAC[SET_RULE `a IN s ==> {x | x IN s /\ x = a} = {a}`;
11397    SET_RULE `b IN s /\ ~(b = a)
11398              ==> {x | (x IN s /\ ~(x = a)) /\ x = b} = {b}`] THEN
11399   ASM_SIMP_TAC[VECTOR_MUL_LZERO; SUM_0; VSUM_0; SUM_SING; VSUM_SING] THEN
11400   CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
11401   CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
11402   EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN
11403   FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N`) THEN ASM_REWRITE_TAC[] THEN
11404   ASM_REAL_ARITH_TAC);;
11405
11406 let EXPLICIT_SUBSET_INTERIOR_CONVEX_HULL = prove
11407  (`!s. FINITE s /\ affine hull s = (:real^N)
11408        ==> {y | ?u. (!x. x IN s ==> &0 < u x /\ u x < &1) /\
11409                     sum s u = &1 /\
11410                     vsum s (\x. u x % x) = y}
11411            SUBSET interior(convex hull s)`,
11412   REPEAT STRIP_TAC THEN
11413   FIRST_ASSUM(MP_TAC o
11414     MATCH_MP EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL) THEN
11415   ASM_SIMP_TAC[RELATIVE_INTERIOR_INTERIOR; AFFINE_HULL_CONVEX_HULL]);;
11416
11417 let EXPLICIT_SUBSET_INTERIOR_CONVEX_HULL_MINIMAL = prove
11418  (`!s. FINITE s /\ affine hull s = (:real^N)
11419        ==> {y | ?u. (!x. x IN s ==> &0 < u x) /\
11420                     sum s u = &1 /\
11421                     vsum s (\x. u x % x) = y}
11422            SUBSET interior(convex hull s)`,
11423   REPEAT STRIP_TAC THEN
11424   FIRST_ASSUM(MP_TAC o
11425     MATCH_MP EXPLICIT_SUBSET_RELATIVE_INTERIOR_CONVEX_HULL_MINIMAL) THEN
11426   ASM_SIMP_TAC[RELATIVE_INTERIOR_INTERIOR; AFFINE_HULL_CONVEX_HULL]);;
11427
11428 let INTERIOR_CONVEX_HULL_EXPLICIT_MINIMAL = prove
11429  (`!s:real^N->bool.
11430         ~(affine_dependent s)
11431         ==> interior(convex hull s) =
11432              if CARD(s) <= dimindex(:N) then {}
11433               else {y | ?u. (!x. x IN s ==> &0 < u x) /\
11434                             sum s u = &1 /\
11435                             vsum s (\x. u x % x) = y}`,
11436   REPEAT STRIP_TAC THEN
11437   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11438   COND_CASES_TAC THEN ASM_SIMP_TAC[EMPTY_INTERIOR_CONVEX_HULL] THEN
11439   MATCH_MP_TAC EQ_TRANS THEN
11440   EXISTS_TAC `relative_interior(convex hull s):real^N->bool` THEN
11441   CONJ_TAC THENL
11442    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
11443     REWRITE_TAC[AFFINE_HULL_CONVEX_HULL] THEN
11444     MATCH_MP_TAC AFFINE_INDEPENDENT_SPAN_GT THEN
11445     ASM_REWRITE_TAC[] THEN ASM_ARITH_TAC;
11446     ASM_SIMP_TAC[RELATIVE_INTERIOR_CONVEX_HULL_EXPLICIT]]);;
11447
11448 let INTERIOR_CONVEX_HULL_EXPLICIT = prove
11449  (`!s:real^N->bool.
11450         ~(affine_dependent s)
11451         ==> interior(convex hull s) =
11452              if CARD(s) <= dimindex(:N) then {}
11453               else {y | ?u. (!x. x IN s ==> &0 < u x /\ u x < &1) /\
11454                             sum s u = &1 /\
11455                             vsum s (\x. u x % x) = y}`,
11456   REPEAT STRIP_TAC THEN
11457   ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EXPLICIT_MINIMAL] THEN
11458   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
11459  REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN X_GEN_TAC `v:real^N` THEN
11460   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `u:real^N->real` THEN
11461   EQ_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[] THEN
11462   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
11463   MP_TAC(ISPEC `s:real^N->bool` CHOOSE_SUBSET) THEN
11464   ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE] THEN
11465   DISCH_THEN(MP_TAC o SPEC `2`) THEN ANTS_TAC THENL
11466    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (ARITH_RULE
11467      `~(c <= n) ==> 1 <= n ==> 2 <= c`)) THEN
11468     REWRITE_TAC[DIMINDEX_GE_1];
11469     ALL_TAC] THEN
11470   CONV_TAC(ONCE_DEPTH_CONV HAS_SIZE_CONV) THEN
11471   REWRITE_TAC[SUBSET] THEN
11472   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` (CONJUNCTS_THEN2 ASSUME_TAC
11473     MP_TAC)) THEN
11474   DISCH_THEN(X_CHOOSE_THEN `a:real^N` (X_CHOOSE_THEN `b:real^N`
11475         STRIP_ASSUME_TAC)) THEN
11476   SUBGOAL_THEN `?y:real^N. y IN s /\ ~(y = x)` STRIP_ASSUME_TAC THENL
11477    [ASM SET_TAC[]; ALL_TAC] THEN
11478   SUBGOAL_THEN `sum {x,y} u <= sum s (u:real^N->real)` MP_TAC THENL
11479    [MATCH_MP_TAC SUM_SUBSET_SIMPLE THEN
11480     ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE; REAL_LT_IMP_LE; IN_DIFF] THEN
11481     ASM SET_TAC[];
11482     ALL_TAC] THEN
11483   ASM_SIMP_TAC[SUM_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
11484   ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
11485   MATCH_MP_TAC(REAL_ARITH `&0 < y ==> x + y + &0 <= &1 ==> x < &1`) THEN
11486   ASM_SIMP_TAC[]);;
11487
11488 let INTERIOR_CONVEX_HULL_3_MINIMAL = prove
11489  (`!a b c:real^2.
11490         ~collinear{a,b,c}
11491         ==> interior(convex hull {a,b,c}) =
11492                 {v | ?x y z. &0 < x /\
11493                              &0 < y /\
11494                              &0 < z /\
11495                              x + y + z = &1 /\
11496                              x % a + y % b + z % c = v}`,
11497   REWRITE_TAC[COLLINEAR_3_EQ_AFFINE_DEPENDENT; DE_MORGAN_THM] THEN
11498   REPEAT STRIP_TAC THEN
11499   ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EXPLICIT_MINIMAL] THEN
11500   ASM_SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
11501   CONV_TAC(LAND_CONV(RATOR_CONV(LAND_CONV(ONCE_DEPTH_CONV(REWRITE_CONV
11502    [IN_INSERT; NOT_IN_EMPTY]))))) THEN
11503   ASM_REWRITE_TAC[DIMINDEX_2; ARITH] THEN
11504   SIMP_TAC[FINITE_INSERT; FINITE_UNION; FINITE_EMPTY; RIGHT_EXISTS_AND_THM;
11505            AFFINE_HULL_FINITE_STEP_GEN; REAL_LT_ADD; REAL_HALF] THEN
11506   REWRITE_TAC[REAL_ARITH `&1 - a - b - c = &0 <=> a + b + c = &1`;
11507          VECTOR_ARITH `y - a - b - c:real^N = vec 0 <=> a + b + c = y`]);;
11508
11509 let INTERIOR_CONVEX_HULL_3 = prove
11510  (`!a b c:real^2.
11511         ~collinear{a,b,c}
11512         ==> interior(convex hull {a,b,c}) =
11513                 {v | ?x y z. &0 < x /\ x < &1 /\
11514                              &0 < y /\ y < &1 /\
11515                              &0 < z /\ z < &1 /\
11516                              x + y + z = &1 /\
11517                              x % a + y % b + z % c = v}`,
11518   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_3_MINIMAL] THEN
11519   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN GEN_TAC THEN
11520   REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN EQ_TAC THEN STRIP_TAC THEN
11521   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC);;
11522
11523 (* ------------------------------------------------------------------------- *)
11524 (* Similar results for closure and (relative or absolute) frontier.          *)
11525 (* ------------------------------------------------------------------------- *)
11526
11527 let CLOSURE_CONVEX_HULL = prove
11528  (`!s. compact s ==> closure(convex hull s) = convex hull s`,
11529   SIMP_TAC[CLOSURE_CLOSED; COMPACT_IMP_CLOSED; COMPACT_CONVEX_HULL]);;
11530
11531 let RELATIVE_FRONTIER_CONVEX_HULL_EXPLICIT = prove
11532  (`!s:real^N->bool.
11533         ~(affine_dependent s)
11534         ==> relative_frontier(convex hull s) =
11535                 {y | ?u. (!x. x IN s ==> &0 <= u x) /\
11536                          (?x. x IN s /\ u x = &0) /\
11537                          sum s u = &1 /\
11538                          vsum s (\x. u x % x) = y}`,
11539   REPEAT STRIP_TAC THEN REWRITE_TAC[relative_frontier; UNIONS_GSPEC] THEN
11540   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11541   ASM_SIMP_TAC[CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11542   ASM_SIMP_TAC[CONVEX_HULL_FINITE; RELATIVE_INTERIOR_CONVEX_HULL_EXPLICIT] THEN
11543   GEN_REWRITE_TAC I [EXTENSION] THEN X_GEN_TAC `y:real^N` THEN
11544   REWRITE_TAC[IN_DIFF; IN_ELIM_THM] THEN EQ_TAC THENL
11545    [DISCH_THEN(CONJUNCTS_THEN2
11546      (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC) ASSUME_TAC) THEN
11547     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
11548     DISCH_THEN(MP_TAC o SPEC `u:real^N->real`) THEN
11549     ASM_REWRITE_TAC[NOT_FORALL_THM; NOT_IMP] THEN
11550     DISCH_THEN(CHOOSE_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
11551     ASM_SIMP_TAC[REAL_ARITH `&0 <= x ==> (~(&0 < x) <=> x = &0)`] THEN
11552     DISCH_TAC THEN EXISTS_TAC `u:real^N->real` THEN
11553     ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[];
11554     DISCH_THEN(X_CHOOSE_THEN `u:real^N->real`
11555      (REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC)) THEN
11556     CONJ_TAC THENL
11557      [EXISTS_TAC `u:real^N->real` THEN ASM_SIMP_TAC[]; ALL_TAC] THEN
11558     DISCH_THEN(X_CHOOSE_THEN `v:real^N->real` STRIP_ASSUME_TAC) THEN
11559     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
11560      [AFFINE_DEPENDENT_EXPLICIT]) THEN
11561     REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
11562      [`s:real^N->bool`; `(\x. u x - v x):real^N->real`] THEN
11563     ASM_SIMP_TAC[SUBSET_REFL; VECTOR_SUB_RDISTRIB; SUM_SUB; VSUM_SUB] THEN
11564     REWRITE_TAC[REAL_SUB_0; VECTOR_SUB_EQ] THEN ASM_MESON_TAC[REAL_LT_REFL]]);;
11565
11566 let FRONTIER_CONVEX_HULL_EXPLICIT = prove
11567  (`!s:real^N->bool.
11568         ~(affine_dependent s)
11569         ==> frontier(convex hull s) =
11570                 {y | ?u. (!x. x IN s ==> &0 <= u x) /\
11571                          (dimindex(:N) < CARD s ==> ?x. x IN s /\ u x = &0) /\
11572                          sum s u = &1 /\
11573                          vsum s (\x. u x % x) = y}`,
11574   REPEAT STRIP_TAC THEN REWRITE_TAC[frontier] THEN
11575   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11576   DISJ_CASES_TAC
11577    (ARITH_RULE `CARD(s:real^N->bool) <= dimindex(:N) \/
11578                 dimindex(:N) < CARD(s:real^N->bool)`)
11579   THENL
11580    [ASM_SIMP_TAC[GSYM NOT_LE; INTERIOR_CONVEX_HULL_EXPLICIT] THEN
11581     ASM_SIMP_TAC[CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT; DIFF_EMPTY] THEN
11582     REWRITE_TAC[CONVEX_HULL_FINITE];
11583     ASM_SIMP_TAC[GSYM RELATIVE_FRONTIER_CONVEX_HULL_EXPLICIT] THEN
11584     REWRITE_TAC[relative_frontier] THEN AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN
11585     MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
11586     MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
11587     EXISTS_TAC `affine hull s:real^N->bool` THEN
11588     ASM_SIMP_TAC[AFFINE_INDEPENDENT_SPAN_GT; HULL_MONO; HULL_SUBSET]]);;
11589
11590 let RELATIVE_FRONTIER_CONVEX_HULL_CASES = prove
11591  (`!s:real^N->bool.
11592         ~(affine_dependent s)
11593         ==> relative_frontier(convex hull s) =
11594                 UNIONS { convex hull (s DELETE a) |a| a IN s }`,
11595   REPEAT STRIP_TAC THEN REWRITE_TAC[UNIONS_GSPEC] THEN
11596   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11597   ASM_SIMP_TAC[RELATIVE_FRONTIER_CONVEX_HULL_EXPLICIT] THEN
11598   REWRITE_TAC[EXTENSION; IN_ELIM_THM; CONVEX_HULL_FINITE] THEN
11599   X_GEN_TAC `y:real^N` THEN EQ_TAC THENL
11600    [DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` MP_TAC) THEN
11601     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
11602     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
11603     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
11604     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN EXISTS_TAC `u:real^N->real` THEN
11605     ASM_SIMP_TAC[IN_DELETE; SUM_DELETE; VSUM_DELETE; REAL_SUB_RZERO] THEN
11606     VECTOR_ARITH_TAC;
11607     REWRITE_TAC[IN_DELETE] THEN
11608     DISCH_THEN(X_CHOOSE_THEN `a:real^N` (CONJUNCTS_THEN2 ASSUME_TAC
11609      (X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC))) THEN
11610     EXISTS_TAC `(\x. if x = a then &0 else u x):real^N->real` THEN
11611     ASM_SIMP_TAC[COND_RAND; COND_RATOR; REAL_LE_REFL; COND_ID] THEN
11612     CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
11613     ASM_SIMP_TAC[SUM_CASES; VSUM_CASES; VECTOR_MUL_LZERO] THEN
11614     ASM_SIMP_TAC[GSYM DELETE; SUM_0; VSUM_0; REAL_ADD_LID; VECTOR_ADD_LID]]);;
11615
11616 let FRONTIER_CONVEX_HULL_CASES = prove
11617  (`!s:real^N->bool.
11618         ~(affine_dependent s)
11619         ==> frontier(convex hull s) =
11620                 if CARD(s) <= dimindex(:N) then convex hull s
11621                 else UNIONS { convex hull (s DELETE a) |a| a IN s }`,
11622   REPEAT STRIP_TAC THEN
11623   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
11624   ASM_SIMP_TAC[frontier; CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11625   COND_CASES_TAC THENL
11626    [ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EXPLICIT; DIFF_EMPTY]; ALL_TAC] THEN
11627   ASM_SIMP_TAC[GSYM RELATIVE_FRONTIER_CONVEX_HULL_CASES] THEN
11628   ASM_SIMP_TAC[relative_frontier; frontier;
11629                CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11630   AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN
11631   RULE_ASSUM_TAC(REWRITE_RULE[NOT_LE]) THEN
11632   MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
11633   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
11634   EXISTS_TAC `affine hull s:real^N->bool` THEN
11635   ASM_SIMP_TAC[AFFINE_INDEPENDENT_SPAN_GT; HULL_MONO; HULL_SUBSET]);;
11636
11637 let IN_FRONTIER_CONVEX_HULL = prove
11638  (`!s x:real^N.
11639         FINITE s /\ CARD s <= dimindex(:N) + 1 /\ x IN s
11640         ==> x IN frontier(convex hull s)`,
11641   REPEAT STRIP_TAC THEN ASM_CASES_TAC `affine_dependent(s:real^N->bool)` THENL
11642    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [affine_dependent]) THEN
11643     DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
11644     ASM_SIMP_TAC[frontier; CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11645     ASM_SIMP_TAC[HULL_INC; IN_DIFF] THEN MATCH_MP_TAC(SET_RULE
11646      `!t. s SUBSET t /\ t = {} ==> ~(x IN s)`) THEN
11647     EXISTS_TAC `interior(affine hull s):real^N->bool` THEN
11648     SIMP_TAC[SUBSET_INTERIOR; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
11649     SUBGOAL_THEN `s = (a:real^N) INSERT (s DELETE a)` SUBST1_TAC THENL
11650      [ASM SET_TAC[]; ALL_TAC] THEN
11651     ASM_SIMP_TAC[HULL_REDUNDANT] THEN
11652     MATCH_MP_TAC EMPTY_INTERIOR_AFFINE_HULL THEN
11653     ASM_SIMP_TAC[FINITE_DELETE; CARD_DELETE] THEN ASM_ARITH_TAC;
11654     ASM_SIMP_TAC[FRONTIER_CONVEX_HULL_CASES] THEN
11655     COND_CASES_TAC THEN ASM_SIMP_TAC[HULL_INC] THEN
11656     REWRITE_TAC[UNIONS_GSPEC; IN_ELIM_THM] THEN
11657     SUBGOAL_THEN `?y:real^N. y IN s /\ ~(y = x)` MP_TAC THENL
11658      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
11659        `x IN s ==> ~(s = {x}) ==> ?y. y IN s /\ ~(y = x)`)) THEN DISCH_TAC THEN
11660       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_LE]) THEN
11661       ASM_SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
11662       REWRITE_TAC[NOT_LT; NOT_IN_EMPTY; ARITH_SUC; DIMINDEX_GE_1];
11663       MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN STRIP_TAC THEN
11664       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC HULL_INC THEN ASM SET_TAC[]]]);;
11665
11666 let NOT_IN_INTERIOR_CONVEX_HULL = prove
11667  (`!s x:real^N.
11668         FINITE s /\ CARD s <= dimindex(:N) + 1 /\ x IN s
11669         ==> ~(x IN interior(convex hull s))`,
11670   REPEAT GEN_TAC THEN
11671   DISCH_THEN(MP_TAC o MATCH_MP IN_FRONTIER_CONVEX_HULL) THEN
11672   SIMP_TAC[frontier; IN_DIFF]);;
11673
11674 let INTERIOR_CONVEX_HULL_EQ_EMPTY = prove
11675  (`!s:real^N->bool.
11676         s HAS_SIZE (dimindex(:N) + 1)
11677         ==> (interior(convex hull s) = {} <=> affine_dependent s)`,
11678   REPEAT GEN_TAC THEN REWRITE_TAC[HAS_SIZE] THEN STRIP_TAC THEN
11679   ASM_CASES_TAC `affine_dependent(s:real^N->bool)` THENL
11680    [ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I
11681       [affine_dependent]) THEN
11682     DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
11683     ASM_SIMP_TAC[frontier; CLOSURE_CONVEX_HULL; FINITE_IMP_COMPACT] THEN
11684     ASM_SIMP_TAC[HULL_INC; IN_DIFF] THEN MATCH_MP_TAC(SET_RULE
11685      `!t. s SUBSET t /\ t = {} ==> s = {}`) THEN
11686     EXISTS_TAC `interior(affine hull s):real^N->bool` THEN
11687     SIMP_TAC[SUBSET_INTERIOR; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
11688     SUBGOAL_THEN `s = (a:real^N) INSERT (s DELETE a)` SUBST1_TAC THENL
11689      [ASM SET_TAC[]; ALL_TAC] THEN
11690     ASM_SIMP_TAC[HULL_REDUNDANT] THEN
11691     MATCH_MP_TAC EMPTY_INTERIOR_AFFINE_HULL THEN
11692     ASM_SIMP_TAC[FINITE_DELETE; CARD_DELETE] THEN ASM_ARITH_TAC;
11693     ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EXPLICIT_MINIMAL] THEN
11694     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; ARITH_RULE `~(n + 1 <= n)`] THEN
11695     EXISTS_TAC `vsum s (\x:real^N. inv(&(dimindex(:N)) + &1) % x)` THEN
11696     REWRITE_TAC[IN_ELIM_THM] THEN
11697     EXISTS_TAC `\x:real^N. inv(&(dimindex(:N)) + &1)` THEN
11698     ASM_SIMP_TAC[REAL_LT_INV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
11699     ASM_SIMP_TAC[SUM_CONST; GSYM REAL_OF_NUM_ADD] THEN
11700     CONV_TAC REAL_FIELD]);;
11701
11702 (* ------------------------------------------------------------------------- *)
11703 (* Similar things in special case (could use above as lemmas here instead).  *)
11704 (* ------------------------------------------------------------------------- *)
11705
11706 let SIMPLEX_EXPLICIT = prove
11707  (`!s:real^N->bool.
11708         FINITE s /\ ~(vec 0 IN s)
11709         ==> convex hull (vec 0 INSERT s) =
11710             { y | ?u. (!x. x IN s ==> &0 <= u x) /\
11711                       sum s u <= &1 /\
11712                       vsum s (\x. u x % x) = y}`,
11713   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CONVEX_HULL_FINITE; FINITE_INSERT] THEN
11714   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN X_GEN_TAC `y:real^N` THEN
11715   ASM_SIMP_TAC[SUM_CLAUSES; VSUM_CLAUSES; IN_INSERT] THEN
11716   REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
11717   EQ_TAC THEN DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC) THENL
11718    [EXISTS_TAC `u:real^N->real` THEN ASM_SIMP_TAC[REAL_LE_REFL] THEN
11719     FIRST_X_ASSUM(MP_TAC o SPEC `vec 0:real^N`) THEN REWRITE_TAC[] THEN
11720     ASM_REAL_ARITH_TAC;
11721     EXISTS_TAC `\x:real^N. if x = vec 0 then &1 - sum (s:real^N->bool) u
11722                            else u(x)` THEN
11723     ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
11724      [X_GEN_TAC `x:real^N` THEN ASM_CASES_TAC `x:real^N = vec 0` THEN
11725       ASM_REWRITE_TAC[REAL_SUB_LE];
11726       MATCH_MP_TAC(REAL_ARITH `s = t ==> &1 - s + t = &1`) THEN
11727       MATCH_MP_TAC SUM_EQ THEN ASM_MESON_TAC[];
11728       FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
11729       MATCH_MP_TAC VSUM_EQ THEN ASM_MESON_TAC[]]]);;
11730
11731 let STD_SIMPLEX = prove
11732  (`convex hull (vec 0 INSERT { basis i | 1 <= i /\ i <= dimindex(:N)}) =
11733         {x:real^N | (!i. 1 <= i /\ i <= dimindex(:N) ==> &0 <= x$i) /\
11734                     sum (1..dimindex(:N)) (\i. x$i) <= &1 }`,
11735   W(MP_TAC o PART_MATCH (lhs o rand) SIMPLEX_EXPLICIT o lhs o snd) THEN ANTS_TAC THENL
11736    [REWRITE_TAC[SIMPLE_IMAGE; GSYM IN_NUMSEG] THEN
11737     SIMP_TAC[FINITE_IMAGE; FINITE_NUMSEG; IN_IMAGE] THEN
11738     REWRITE_TAC[IN_NUMSEG] THEN MESON_TAC[BASIS_NONZERO];
11739     ALL_TAC] THEN
11740   DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[EXTENSION] THEN
11741   ONCE_REWRITE_TAC[IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN
11742   REWRITE_TAC[SIMPLE_IMAGE; GSYM IN_NUMSEG] THEN
11743   SUBGOAL_THEN `!u. sum (IMAGE (basis:num->real^N) (1..dimindex(:N))) u =
11744                         sum (1..dimindex(:N)) (u o basis)`
11745    (fun th -> REWRITE_TAC[th])
11746   THENL
11747    [GEN_TAC THEN MATCH_MP_TAC SUM_IMAGE THEN REWRITE_TAC[IN_NUMSEG] THEN
11748     REWRITE_TAC[GSYM CONJ_ASSOC; BASIS_INJ];
11749     ALL_TAC] THEN
11750   SUBGOAL_THEN `!u. vsum (IMAGE (basis:num->real^N) (1..dimindex(:N))) u =
11751                         vsum (1..dimindex(:N)) ((u:real^N->real^N) o basis)`
11752    (fun th -> REWRITE_TAC[th])
11753   THENL
11754    [GEN_TAC THEN MATCH_MP_TAC VSUM_IMAGE THEN REWRITE_TAC[IN_NUMSEG] THEN
11755     REWRITE_TAC[GSYM CONJ_ASSOC; BASIS_INJ; FINITE_NUMSEG];
11756     ALL_TAC] THEN
11757   REWRITE_TAC[o_DEF; BASIS_EXPANSION_UNIQUE; FORALL_IN_IMAGE] THEN
11758   REWRITE_TAC[IN_NUMSEG] THEN EQ_TAC THENL
11759    [DISCH_THEN(X_CHOOSE_THEN `u:real^N->real` STRIP_ASSUME_TAC) THEN
11760     CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
11761     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
11762      `x <= &1 ==> x = y ==> y <= &1`)) THEN
11763     MATCH_MP_TAC SUM_EQ THEN ASM_SIMP_TAC[IN_NUMSEG];
11764     STRIP_TAC THEN EXISTS_TAC `\y:real^N. y dot x` THEN
11765     ASM_SIMP_TAC[DOT_BASIS]]);;
11766
11767 let INTERIOR_STD_SIMPLEX = prove
11768  (`interior
11769     (convex hull (vec 0 INSERT { basis i | 1 <= i /\ i <= dimindex(:N)})) =
11770         {x:real^N | (!i. 1 <= i /\ i <= dimindex(:N) ==> &0 < x$i) /\
11771                     sum (1..dimindex(:N)) (\i. x$i) < &1 }`,
11772   REWRITE_TAC[EXTENSION; IN_INTERIOR; IN_ELIM_THM; STD_SIMPLEX] THEN
11773   REWRITE_TAC[SUBSET; IN_BALL; IN_ELIM_THM] THEN
11774   X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
11775    [DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
11776     FIRST_ASSUM(MP_TAC o SPEC `x:real^N`) THEN REWRITE_TAC[DIST_REFL] THEN
11777     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN ASM_SIMP_TAC[REAL_LT_LE] THEN
11778     CONJ_TAC THENL
11779      [X_GEN_TAC `k:num` THEN STRIP_TAC THEN
11780       FIRST_X_ASSUM(MP_TAC o SPEC `x - (e / &2) % basis k:real^N`) THEN
11781       REWRITE_TAC[NORM_ARITH `dist(x,x - e) = norm(e)`; NORM_MUL] THEN
11782       ASM_SIMP_TAC[NORM_BASIS; REAL_ARITH `&0 < e ==> abs(e / &2) * &1 < e`;
11783                    VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT] THEN
11784       DISCH_THEN(MP_TAC o SPEC `k:num` o CONJUNCT1) THEN ASM_REWRITE_TAC[] THEN
11785       ASM_SIMP_TAC[BASIS_COMPONENT] THEN UNDISCH_TAC `&0 < e` THEN
11786       REAL_ARITH_TAC;
11787       FIRST_X_ASSUM(MP_TAC o SPEC `x + (e / &2) % basis 1:real^N`) THEN
11788       REWRITE_TAC[NORM_ARITH `dist(x,x + e) = norm(e)`; NORM_MUL] THEN
11789       ASM_SIMP_TAC[NORM_BASIS; LE_REFL; DIMINDEX_GE_1] THEN
11790       ASM_SIMP_TAC[REAL_ARITH `&0 < e ==> abs(e / &2) * &1 < e`] THEN
11791       DISCH_THEN(MP_TAC o CONJUNCT2) THEN
11792       MATCH_MP_TAC(REAL_ARITH `x < y ==> y <= &1 ==> ~(x = &1)`) THEN
11793       MATCH_MP_TAC SUM_LT THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
11794       ONCE_REWRITE_TAC[TAUT `(a /\ b) /\ c <=> ~(a /\ b ==> ~c)`] THEN
11795       SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
11796                BASIS_COMPONENT] THEN
11797       CONJ_TAC THENL
11798        [GEN_TAC THEN COND_CASES_TAC;
11799         EXISTS_TAC `1` THEN REWRITE_TAC[LE_REFL; DIMINDEX_GE_1]] THEN
11800       ASM_REAL_ARITH_TAC];
11801     STRIP_TAC THEN
11802     EXISTS_TAC
11803      `min (inf(IMAGE (\i. (x:real^N)$i) (1..dimindex(:N))))
11804           ((&1 - sum (1..dimindex(:N)) (\i. x$i)) / &(dimindex(:N)))` THEN
11805     ASM_SIMP_TAC[REAL_LT_MIN] THEN
11806     SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; FINITE_NUMSEG;
11807              IMAGE_EQ_EMPTY; NUMSEG_EMPTY; GSYM NOT_LE; DIMINDEX_GE_1] THEN
11808     REWRITE_TAC[FORALL_IN_IMAGE] THEN
11809     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_OF_NUM_LT;
11810                  ARITH_RULE `0 < x <=> 1 <= x`; DIMINDEX_GE_1] THEN
11811     ASM_REWRITE_TAC[IN_NUMSEG; REAL_MUL_LZERO; REAL_SUB_LT] THEN
11812     REPEAT(POP_ASSUM(K ALL_TAC)) THEN X_GEN_TAC `y:real^N` THEN
11813     MATCH_MP_TAC MONO_AND THEN CONJ_TAC THENL
11814      [MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `k:num` THEN
11815       DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
11816       ASM_REWRITE_TAC[] THEN
11817       MATCH_MP_TAC(REAL_ARITH `abs(xk - yk) <= d ==> d < xk ==> &0 <= yk`);
11818       GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o RAND_CONV o RAND_CONV)
11819        [GSYM CARD_NUMSEG_1] THEN
11820       ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
11821       SIMP_TAC[GSYM SUM_CONST; FINITE_NUMSEG] THEN
11822       MATCH_MP_TAC(REAL_ARITH
11823        `s2 <= s0 + s1 ==> s0 < &1 - s1 ==> s2 <= &1`) THEN
11824       REWRITE_TAC[GSYM SUM_ADD_NUMSEG] THEN
11825       MATCH_MP_TAC SUM_LE_NUMSEG THEN REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
11826       MATCH_MP_TAC(REAL_ARITH `abs(y - x) <= z ==> x <= z + y`)] THEN
11827     ASM_SIMP_TAC[GSYM VECTOR_SUB_COMPONENT; dist; COMPONENT_LE_NORM]]);;