Update from HH
[Multivariate Analysis/.git] / Multivariate / polytope.ml
1 (* ========================================================================= *)
2 (* Faces, extreme points, polytopes, polyhedra etc.                          *)
3 (* ========================================================================= *)
4
5 needs "Multivariate/paths.ml";;
6
7 (* ------------------------------------------------------------------------- *)
8 (* Faces of a (usually convex) set.                                          *)
9 (* ------------------------------------------------------------------------- *)
10
11 parse_as_infix("face_of",(12,"right"));;
12
13 let face_of = new_definition
14  `t face_of s <=>
15         t SUBSET s /\ convex t /\
16         !a b x. a IN s /\ b IN s /\ x IN t /\ x IN segment(a,b)
17                 ==> a IN t /\ b IN t`;;
18
19 let FACE_OF_TRANSLATION_EQ = prove
20  (`!a f s:real^N->bool.
21         (IMAGE (\x. a + x) f) face_of (IMAGE (\x. a + x) s) <=> f face_of s`,
22   REWRITE_TAC[face_of] THEN GEOM_TRANSLATE_TAC[]);;
23
24 add_translation_invariants [FACE_OF_TRANSLATION_EQ];;
25
26 let FACE_OF_LINEAR_IMAGE = prove
27  (`!f:real^M->real^N c s.
28       linear f /\ (!x y. f x = f y ==> x = y)
29       ==> ((IMAGE f c) face_of (IMAGE f s) <=> c face_of s)`,
30   REWRITE_TAC[face_of; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
31   REPEAT STRIP_TAC THEN MP_TAC(end_itlist CONJ
32    (mapfilter (ISPEC `f:real^M->real^N`) (!invariant_under_linear))) THEN
33   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN ASM_REWRITE_TAC[]);;
34
35 add_linear_invariants [FACE_OF_LINEAR_IMAGE];;
36
37 let FACE_OF_REFL = prove
38  (`!s. convex s ==> s face_of s`,
39   SIMP_TAC[face_of] THEN SET_TAC[]);;
40
41 let FACE_OF_REFL_EQ = prove
42  (`!s. s face_of s <=> convex s`,
43   SIMP_TAC[face_of] THEN SET_TAC[]);;
44
45 let EMPTY_FACE_OF = prove
46  (`!s. {} face_of s`,
47   REWRITE_TAC[face_of; CONVEX_EMPTY] THEN SET_TAC[]);;
48
49 let FACE_OF_EMPTY = prove
50  (`!s. s face_of {} <=> s = {}`,
51   REWRITE_TAC[face_of; SUBSET_EMPTY; NOT_IN_EMPTY] THEN
52   MESON_TAC[CONVEX_EMPTY]);;
53
54 let FACE_OF_TRANS = prove
55  (`!s t u. s face_of t /\ t face_of u
56            ==> s face_of u`,
57   REWRITE_TAC[face_of] THEN SET_TAC[]);;
58
59 let FACE_OF_FACE = prove
60  (`!f s t.
61         t face_of s
62         ==> (f face_of t <=> f face_of s /\ f SUBSET t)`,
63   REWRITE_TAC[face_of] THEN SET_TAC[]);;
64
65 let FACE_OF_SUBSET = prove
66  (`!f s t. f face_of s /\ f SUBSET t /\ t SUBSET s ==> f face_of t`,
67   REWRITE_TAC[face_of] THEN SET_TAC[]);;
68
69 let FACE_OF_SLICE = prove
70  (`!f s t.
71         f face_of s /\ convex t
72         ==> (f INTER t) face_of (s INTER t)`,
73   REPEAT GEN_TAC THEN REWRITE_TAC[face_of; IN_INTER] THEN STRIP_TAC THEN
74   REPEAT CONJ_TAC THENL
75    [ASM SET_TAC[];
76     ASM_MESON_TAC[CONVEX_INTER];
77     ASM_MESON_TAC[]]);;
78
79 let FACE_OF_INTER = prove
80  (`!s t1 t2. t1 face_of s /\ t2 face_of s
81              ==> (t1 INTER t2) face_of s`,
82   SIMP_TAC[face_of; CONVEX_INTER] THEN SET_TAC[]);;
83
84 let FACE_OF_INTERS = prove
85  (`!P s. ~(P = {}) /\ (!t. t IN P ==> t face_of s)
86          ==> (INTERS P) face_of s`,
87   REWRITE_TAC[face_of] THEN REPEAT STRIP_TAC THENL
88    [ASM SET_TAC[]; ASM_SIMP_TAC[CONVEX_INTERS]; ASM SET_TAC[]; ASM SET_TAC[]]);;
89
90 let FACE_OF_INTER_INTER = prove
91  (`!f t f' t'.
92      f face_of t /\ f' face_of t' ==> (f INTER f') face_of (t INTER t')`,
93   REWRITE_TAC[face_of; SUBSET; IN_INTER] THEN MESON_TAC[CONVEX_INTER]);;
94
95 let FACE_OF_STILLCONVEX = prove
96  (`!s t:real^N->bool.
97         convex s
98         ==> (t face_of s <=>
99              t SUBSET s /\
100              convex(s DIFF t) /\
101              t = (affine hull t) INTER s)`,
102   REPEAT STRIP_TAC THEN REWRITE_TAC[face_of] THEN
103   ASM_CASES_TAC `(t:real^N->bool) SUBSET s` THEN ASM_REWRITE_TAC[] THEN
104   EQ_TAC THEN STRIP_TAC THENL
105    [CONJ_TAC THENL
106      [REPEAT(POP_ASSUM MP_TAC) THEN
107       REWRITE_TAC[CONVEX_CONTAINS_SEGMENT; open_segment; IN_DIFF] THEN
108       REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; SUBSET_DIFF] THEN SET_TAC[];
109       ALL_TAC] THEN
110     REWRITE_TAC[EXTENSION] THEN X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
111      [ASM MESON_TAC[HULL_INC; SUBSET; IN_INTER]; ALL_TAC] THEN
112     ASM_CASES_TAC `t:real^N -> bool = {}` THEN
113     ASM_REWRITE_TAC[IN_INTER; AFFINE_HULL_EMPTY; NOT_IN_EMPTY] THEN
114     MP_TAC(ISPEC `t:real^N->bool` RELATIVE_INTERIOR_EQ_EMPTY) THEN
115     ASM_REWRITE_TAC[] THEN
116     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN
117     X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_RELATIVE_INTERIOR_CBALL] THEN
118     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
119     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
120     STRIP_TAC THEN ASM_CASES_TAC `x:real^N = y` THEN ASM_REWRITE_TAC[] THEN
121     FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `y:real^N`]) THEN
122     REWRITE_TAC[] THEN ONCE_REWRITE_TAC[SEGMENT_SYM] THEN
123     ASM_SIMP_TAC[LEFT_FORALL_IMP_THM; OPEN_SEGMENT_ALT] THEN
124     ANTS_TAC THENL [ALL_TAC; SIMP_TAC[]] THEN
125     RULE_ASSUM_TAC(REWRITE_RULE[SUBSET]) THEN ASM_SIMP_TAC[] THEN
126     ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
127     REWRITE_TAC[EXISTS_IN_GSPEC] THEN
128     EXISTS_TAC `min (&1 / &2) (e / norm(x - y:real^N))` THEN
129     REWRITE_TAC[REAL_LT_MIN; REAL_MIN_LT] THEN
130     CONV_TAC REAL_RAT_REDUCE_CONV THEN
131     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ] THEN
132     FIRST_X_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[IN_INTER; IN_CBALL; dist] THEN
133     CONJ_TAC THENL
134      [REWRITE_TAC[NORM_MUL; VECTOR_ARITH
135        `y - ((&1 - u) % y + u % x):real^N = u % (y - x)`] THEN
136       ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
137       REWRITE_TAC[NORM_SUB] THEN
138       MATCH_MP_TAC(REAL_ARITH `&0 < e ==> abs(min (&1 / &2) e) <= e`) THEN
139       ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ];
140       MATCH_MP_TAC(REWRITE_RULE[AFFINE_ALT] AFFINE_AFFINE_HULL) THEN
141       ASM_SIMP_TAC[HULL_INC]];
142     CONJ_TAC THENL
143      [ONCE_ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONVEX_INTER THEN
144       ASM_SIMP_TAC[AFFINE_IMP_CONVEX; AFFINE_AFFINE_HULL];
145       ALL_TAC] THEN
146     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`; `x:real^N`] THEN
147     SUBGOAL_THEN
148      `!a b x:real^N. a IN s /\ b IN s /\ x IN t /\ x IN segment(a,b) /\
149                      (a IN affine hull t ==> b IN affine hull t)
150                      ==> a IN t /\ b IN t`
151      (fun th -> MESON_TAC[th; SEGMENT_SYM]) THEN
152     REPEAT GEN_TAC THEN ASM_CASES_TAC `(a:real^N) IN affine hull t` THEN
153     ASM_REWRITE_TAC[] THENL [ASM SET_TAC[]; STRIP_TAC] THEN
154     ASM_CASES_TAC `a:real^N = b` THENL
155      [ASM_MESON_TAC[SEGMENT_REFL; NOT_IN_EMPTY]; ALL_TAC] THEN
156     SUBGOAL_THEN `(a:real^N) IN (s DIFF t) /\ b IN  (s DIFF t)`
157     STRIP_ASSUME_TAC THENL
158      [ASM_REWRITE_TAC[IN_DIFF] THEN ONCE_ASM_REWRITE_TAC[] THEN
159       ASM_REWRITE_TAC[IN_INTER] THEN
160       UNDISCH_TAC `~((a:real^N) IN affine hull t)` THEN
161       UNDISCH_TAC `(x:real^N) IN segment(a,b)` THEN
162       ASM_SIMP_TAC[OPEN_SEGMENT_ALT; CONTRAPOS_THM; IN_ELIM_THM] THEN
163       DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
164       FIRST_X_ASSUM(MP_TAC o AP_TERM `(%) (inv(&1 - u)) :real^N->real^N`) THEN
165       REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC] THEN
166       ASM_SIMP_TAC[REAL_MUL_LINV; REAL_ARITH `x < &1 ==> ~(&1 - x = &0)`] THEN
167       REWRITE_TAC[VECTOR_ARITH
168        `x:real^N = &1 % a + u % b <=> a = x + --u %  b`] THEN
169       DISCH_THEN SUBST1_TAC THEN DISCH_TAC THEN
170       MATCH_MP_TAC(REWRITE_RULE[affine] AFFINE_AFFINE_HULL) THEN
171       ASM_SIMP_TAC[HULL_INC] THEN
172       UNDISCH_TAC `u < &1` THEN CONV_TAC REAL_FIELD;
173       MP_TAC(ISPEC `s DIFF t:real^N->bool` CONVEX_CONTAINS_SEGMENT) THEN
174       ASM_REWRITE_TAC[] THEN
175       DISCH_THEN(MP_TAC o SPECL [`a:real^N`; `b:real^N`]) THEN
176       ASM_REWRITE_TAC[SUBSET; IN_DIFF] THEN
177       DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
178       ASM_MESON_TAC[segment; IN_DIFF]]]);;
179
180 let FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE_STRONG = prove
181  (`!s a:real^N b.
182         convex(s INTER {x | a dot x = b}) /\ (!x. x IN s ==> a dot x <= b)
183         ==> (s INTER {x | a dot x = b}) face_of s`,
184   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `c:real^N`; `d:real`] THEN
185   SIMP_TAC[face_of; INTER_SUBSET] THEN
186   STRIP_TAC THEN REWRITE_TAC[IN_INTER; IN_ELIM_THM] THEN
187   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`; `x:real^N`] THEN
188   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
189   MATCH_MP_TAC(REAL_ARITH
190    `a <= x /\ b <= x /\ ~(a < x) /\ ~(b < x) ==> a = x /\ b = x`) THEN
191   ASM_SIMP_TAC[] THEN UNDISCH_TAC `(x:real^N) IN segment(a,b)` THEN
192   ASM_CASES_TAC `a:real^N = b` THEN
193   ASM_REWRITE_TAC[SEGMENT_REFL; NOT_IN_EMPTY] THEN
194   ASM_SIMP_TAC[OPEN_SEGMENT_ALT; IN_ELIM_THM] THEN
195   DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
196   CONJ_TAC THEN DISCH_TAC THEN UNDISCH_TAC `(c:real^N) dot x = d` THEN
197   MATCH_MP_TAC(REAL_ARITH `x < a ==> x = a ==> F`) THEN
198   SUBST1_TAC(REAL_ARITH `d = (&1 - u) * d + u * d`) THEN
199   ASM_REWRITE_TAC[DOT_RADD; DOT_RMUL] THENL
200    [MATCH_MP_TAC REAL_LTE_ADD2; MATCH_MP_TAC REAL_LET_ADD2] THEN
201   ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_LT_LMUL_EQ; REAL_SUB_LT]);;
202
203 let FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE_STRONG = prove
204  (`!s a:real^N b.
205         convex(s INTER {x | a dot x = b}) /\ (!x. x IN s ==> a dot x >= b)
206         ==> (s INTER {x | a dot x = b}) face_of s`,
207   REWRITE_TAC[real_ge] THEN REPEAT STRIP_TAC THEN
208   MP_TAC(ISPECL [`s:real^N->bool`; `--a:real^N`; `--b:real`]
209     FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE_STRONG) THEN
210   ASM_REWRITE_TAC[DOT_LNEG; REAL_EQ_NEG2; REAL_LE_NEG2]);;
211
212 let FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE = prove
213  (`!s a:real^N b.
214         convex s /\ (!x. x IN s ==> a dot x <= b)
215         ==> (s INTER {x | a dot x = b}) face_of s`,
216   SIMP_TAC[FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE_STRONG;
217            CONVEX_INTER; CONVEX_HYPERPLANE]);;
218
219 let FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE = prove
220  (`!s a:real^N b.
221         convex s /\ (!x. x IN s ==> a dot x >= b)
222         ==> (s INTER {x | a dot x = b}) face_of s`,
223   SIMP_TAC[FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE_STRONG;
224            CONVEX_INTER; CONVEX_HYPERPLANE]);;
225
226 let FACE_OF_IMP_SUBSET = prove
227  (`!s t. t face_of s ==> t SUBSET s`,
228   SIMP_TAC[face_of]);;
229
230 let FACE_OF_IMP_CONVEX = prove
231  (`!s t. t face_of s ==> convex t`,
232   SIMP_TAC[face_of]);;
233
234 let FACE_OF_IMP_CLOSED = prove
235  (`!s t. convex s /\ closed s /\ t face_of s ==> closed t`,
236   REPEAT GEN_TAC THEN
237   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
238   ASM_SIMP_TAC[FACE_OF_STILLCONVEX] THEN
239   STRIP_TAC THEN ONCE_ASM_REWRITE_TAC[] THEN
240   ASM_SIMP_TAC[CLOSED_AFFINE; AFFINE_AFFINE_HULL; CLOSED_INTER]);;
241
242 let FACE_OF_IMP_COMPACT = prove
243  (`!s t. convex s /\ compact s /\ t face_of s ==> compact t`,
244   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
245   ASM_MESON_TAC[BOUNDED_SUBSET; FACE_OF_IMP_SUBSET; FACE_OF_IMP_CLOSED]);;
246
247 let FACE_OF_INTER_SUBFACE = prove
248  (`!c1 c2 d1 d2:real^N->bool.
249         (c1 INTER c2) face_of c1 /\ (c1 INTER c2) face_of c2 /\
250         d1 face_of c1 /\ d2 face_of c2
251         ==> (d1 INTER d2) face_of d1 /\ (d1 INTER d2) face_of d2`,
252  REPEAT STRIP_TAC THEN MATCH_MP_TAC FACE_OF_SUBSET THENL
253    [EXISTS_TAC `c1:real^N->bool`; EXISTS_TAC `c2:real^N->bool`] THEN
254   ASM_SIMP_TAC[FACE_OF_IMP_SUBSET; INTER_SUBSET] THEN
255   TRANS_TAC FACE_OF_TRANS `c1 INTER c2:real^N->bool` THEN
256   ASM_SIMP_TAC[FACE_OF_INTER_INTER]);;
257
258 let SUBSET_OF_FACE_OF = prove
259  (`!s t u:real^N->bool.
260       t face_of s /\ u SUBSET s /\
261       ~(DISJOINT t (relative_interior u))
262       ==> u SUBSET t`,
263   REWRITE_TAC[DISJOINT] THEN REPEAT STRIP_TAC THEN
264   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `c:real^N` THEN DISCH_TAC THEN
265   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
266   REWRITE_TAC[IN_INTER; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `b:real^N` THEN
267   REWRITE_TAC[IN_RELATIVE_INTERIOR_CBALL] THEN
268   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
269   DISCH_THEN(X_CHOOSE_THEN `e:real` MP_TAC) THEN
270   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
271   REWRITE_TAC[SUBSET; IN_CBALL; IN_INTER] THEN
272   ASM_CASES_TAC `c:real^N = b` THEN ASM_REWRITE_TAC[] THEN
273   ABBREV_TAC `d:real^N = b + e / norm(b - c) % (b - c)` THEN
274   DISCH_THEN(MP_TAC o SPEC `d:real^N`) THEN ANTS_TAC THENL
275    [EXPAND_TAC "d" THEN CONJ_TAC THENL
276      [REWRITE_TAC[NORM_ARITH `dist(b:real^N,b + e) = norm e`] THEN
277       REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
278       ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ] THEN
279       ASM_REAL_ARITH_TAC;
280       REWRITE_TAC[VECTOR_ARITH
281        `b + u % (b - c):real^N = (&1 - --u) % b + --u % c`] THEN
282       MATCH_MP_TAC(REWRITE_RULE[AFFINE_ALT] AFFINE_AFFINE_HULL) THEN
283       ASM_SIMP_TAC[HULL_INC]];
284     STRIP_TAC THEN
285     SUBGOAL_THEN `(d:real^N) IN t /\ c IN t` (fun th -> MESON_TAC[th]) THEN
286     FIRST_ASSUM(STRIP_ASSUME_TAC o GEN_REWRITE_RULE I [face_of]) THEN
287     FIRST_X_ASSUM MATCH_MP_TAC THEN EXISTS_TAC `b:real^N` THEN
288     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
289     SUBGOAL_THEN `~(b:real^N = d)` ASSUME_TAC THENL
290      [EXPAND_TAC "d" THEN
291       REWRITE_TAC[VECTOR_ARITH `b:real^N = b + e <=> e = vec 0`] THEN
292       ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ;
293                    VECTOR_MUL_EQ_0; REAL_LT_IMP_NZ];
294       ASM_REWRITE_TAC[segment; IN_DIFF; IN_INSERT; NOT_IN_EMPTY] THEN
295       REWRITE_TAC[IN_ELIM_THM] THEN
296       EXISTS_TAC `(e / norm(b - c:real^N)) / (&1 + e / norm(b - c))` THEN
297       ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ;
298                    REAL_ARITH `&0 < x ==> &0 < &1 + x`;
299                    REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ; REAL_MUL_LID] THEN
300       REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID] THEN
301       ASM_SIMP_TAC[REAL_FIELD `&0 < n ==> (&1 + e / n) * n = n + e`;
302                    NORM_POS_LT; VECTOR_SUB_EQ; REAL_LE_ADDL] THEN
303       ASM_SIMP_TAC[NORM_POS_LT; REAL_LT_IMP_LE; VECTOR_SUB_EQ] THEN
304       EXPAND_TAC "d" THEN REWRITE_TAC[VECTOR_ARITH
305        `b:real^N = (&1 - u) % (b + e % (b - c)) + u % c <=>
306         (u - e * (&1 - u)) % (b - c) = vec 0`] THEN
307       ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
308       MATCH_MP_TAC(REAL_FIELD
309        `&0 < e ==> e / (&1 + e) - e * (&1 - e / (&1 + e)) = &0`) THEN
310       ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ]]]);;
311
312 let FACE_OF_EQ = prove
313  (`!s t u:real^N->bool.
314         t face_of s /\ u face_of s /\
315         ~(DISJOINT (relative_interior t) (relative_interior u))
316         ==> t = u`,
317   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
318   CONJ_TAC THEN MATCH_MP_TAC SUBSET_OF_FACE_OF THEN
319   EXISTS_TAC `s:real^N->bool` THEN ASM_SIMP_TAC[FACE_OF_IMP_SUBSET] THENL
320    [MP_TAC(ISPEC `u:real^N->bool` RELATIVE_INTERIOR_SUBSET);
321     MP_TAC(ISPEC `t:real^N->bool` RELATIVE_INTERIOR_SUBSET)] THEN
322   ASM SET_TAC[]);;
323
324 let FACE_OF_DISJOINT_RELATIVE_INTERIOR = prove
325  (`!f s:real^N->bool.
326         f face_of s /\ ~(f = s) ==> f INTER relative_interior s = {}`,
327   REPEAT STRIP_TAC THEN
328   MP_TAC(ISPECL [`s:real^N->bool`; `f:real^N->bool`; `s:real^N->bool`]
329         SUBSET_OF_FACE_OF) THEN
330   FIRST_ASSUM(MP_TAC o MATCH_MP FACE_OF_IMP_SUBSET) THEN
331   ASM SET_TAC[]);;
332
333 let FACE_OF_DISJOINT_INTERIOR = prove
334  (`!f s:real^N->bool.
335         f face_of s /\ ~(f = s) ==> f INTER interior s = {}`,
336   REPEAT GEN_TAC THEN
337   DISCH_THEN(MP_TAC o MATCH_MP FACE_OF_DISJOINT_RELATIVE_INTERIOR) THEN
338   MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET_RELATIVE_INTERIOR) THEN
339   SET_TAC[]);;
340
341 let AFFINE_HULL_FACE_OF_DISJOINT_RELATIVE_INTERIOR = prove
342  (`!s f:real^N->bool.
343         convex s /\ f face_of s /\ ~(f = s)
344         ==> affine hull f INTER relative_interior s = {}`,
345   REPEAT STRIP_TAC THEN MATCH_MP_TAC(SET_RULE
346    `!s f. a INTER s = f /\ r SUBSET s /\ f INTER r = {}
347           ==> a INTER r = {}`) THEN
348   MAP_EVERY EXISTS_TAC [`s:real^N->bool`; `f:real^N->bool`] THEN
349   ASM_SIMP_TAC[FACE_OF_DISJOINT_RELATIVE_INTERIOR;
350                RELATIVE_INTERIOR_SUBSET] THEN
351   UNDISCH_TAC `(f:real^N->bool) face_of s` THEN
352   ASM_SIMP_TAC[FACE_OF_STILLCONVEX] THEN MESON_TAC[]);;
353
354 let FACE_OF_SUBSET_RELATIVE_BOUNDARY = prove
355  (`!s f:real^N->bool.
356         f face_of s /\ ~(f = s) ==> f SUBSET (s DIFF relative_interior s)`,
357   ASM_SIMP_TAC[SET_RULE `s SUBSET u DIFF t <=> s SUBSET u /\ s INTER t = {}`;
358                FACE_OF_DISJOINT_RELATIVE_INTERIOR; FACE_OF_IMP_SUBSET]);;
359
360 let FACE_OF_SUBSET_RELATIVE_FRONTIER = prove
361  (`!s f:real^N->bool.
362         f face_of s /\ ~(f = s) ==> f SUBSET relative_frontier s`,
363   REPEAT GEN_TAC THEN
364   DISCH_THEN(MP_TAC o MATCH_MP FACE_OF_SUBSET_RELATIVE_BOUNDARY) THEN
365   REWRITE_TAC[relative_frontier] THEN
366   MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[]);;
367
368 let FACE_OF_AFF_DIM_LT = prove
369  (`!f s:real^N->bool.
370         convex s /\ f face_of s /\ ~(f = s) ==> aff_dim f < aff_dim s`,
371   REPEAT GEN_TAC THEN
372   SIMP_TAC[INT_LT_LE; FACE_OF_IMP_SUBSET; AFF_DIM_SUBSET] THEN
373   REWRITE_TAC[IMP_CONJ; CONTRAPOS_THM] THEN
374   ASM_CASES_TAC `f:real^N->bool = {}` THENL
375    [CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN
376     ASM_REWRITE_TAC[AFF_DIM_EQ_MINUS1; AFF_DIM_EMPTY];
377     REPEAT STRIP_TAC THEN MATCH_MP_TAC FACE_OF_EQ THEN
378     EXISTS_TAC `s:real^N->bool` THEN ASM_SIMP_TAC[FACE_OF_REFL] THEN
379     MATCH_MP_TAC(SET_RULE `~(f = {}) /\ f SUBSET s ==> ~DISJOINT f s`) THEN
380     FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_CONVEX) THEN
381     ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY] THEN
382     MATCH_MP_TAC SUBSET_RELATIVE_INTERIOR THEN
383     ASM_MESON_TAC[FACE_OF_IMP_SUBSET; AFF_DIM_EQ_AFFINE_HULL; INT_LE_REFL]]);;
384
385 let FACE_OF_CONVEX_HULLS = prove
386  (`!f s:real^N->bool.
387         FINITE s /\ f SUBSET s /\
388         DISJOINT (affine hull f) (convex hull (s DIFF f))
389         ==> (convex hull f) face_of (convex hull s)`,
390   let lemma = prove
391    (`!s x y:real^N.
392           affine s /\ ~(k = &0) /\ ~(k = &1) /\ x IN s /\ inv(&1 - k) % y IN s
393           ==> inv(k) % (x - y) IN s`,
394     REWRITE_TAC[AFFINE_ALT] THEN REPEAT STRIP_TAC THEN
395     SUBGOAL_THEN
396      `inv(k) % (x - y):real^N = (&1 - inv k) % inv(&1 - k) % y + inv(k) % x`
397      (fun th -> ASM_SIMP_TAC[th]) THEN
398     REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_ARITH
399      `k % (x - y):real^N = a % b % y + k % x <=> (a * b + k) % y = vec 0`] THEN
400     DISJ1_TAC THEN MAP_EVERY UNDISCH_TAC [`~(k = &0)`; `~(k = &1)`] THEN
401     CONV_TAC REAL_FIELD) in
402   REPEAT STRIP_TAC THEN REWRITE_TAC[face_of] THEN
403   SUBGOAL_THEN `FINITE(f:real^N->bool)` ASSUME_TAC THENL
404    [ASM_MESON_TAC[FINITE_SUBSET]; ALL_TAC] THEN
405   FIRST_ASSUM(ASSUME_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
406   ASM_SIMP_TAC[HULL_MONO; CONVEX_CONVEX_HULL] THEN
407   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`; `w:real^N`] THEN
408   STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT]) THEN
409   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC
410    (X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC)) THEN
411   SUBGOAL_THEN `(w:real^N) IN affine hull f` ASSUME_TAC THENL
412    [ASM_MESON_TAC[CONVEX_HULL_SUBSET_AFFINE_HULL; SUBSET]; ALL_TAC] THEN
413   MAP_EVERY UNDISCH_TAC
414    [`(y:real^N) IN convex hull s`; `(x:real^N) IN convex hull s`] THEN
415   REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
416   DISCH_THEN(X_CHOOSE_THEN `a:real^N->real` STRIP_ASSUME_TAC) THEN
417   DISCH_THEN(X_CHOOSE_THEN `b:real^N->real` STRIP_ASSUME_TAC) THEN
418   ABBREV_TAC `(c:real^N->real) = \x. (&1 - u) * a x + u * b x` THEN
419   SUBGOAL_THEN `!x:real^N. x IN s ==> &0 <= c x` ASSUME_TAC THENL
420    [REPEAT STRIP_TAC THEN EXPAND_TAC "c" THEN REWRITE_TAC[] THEN
421     MATCH_MP_TAC REAL_LE_ADD THEN CONJ_TAC THEN MATCH_MP_TAC REAL_LE_MUL THEN
422     ASM_SIMP_TAC[] THEN ASM_REAL_ARITH_TAC;
423     ALL_TAC] THEN
424   ASM_CASES_TAC `sum (s DIFF f:real^N->bool) c = &0` THENL
425    [SUBGOAL_THEN `!x:real^N. x IN (s DIFF f) ==> c x = &0` MP_TAC THENL
426      [MATCH_MP_TAC SUM_POS_EQ_0 THEN ASM_MESON_TAC[FINITE_DIFF; IN_DIFF];
427       ALL_TAC] THEN
428     EXPAND_TAC "c" THEN
429     ASM_SIMP_TAC[IN_DIFF; REAL_LE_MUL; REAL_LT_IMP_LE; REAL_SUB_LT;
430      REAL_ARITH `&0 <= x /\ &0 <= y ==> (x + y = &0 <=> x = &0 /\ y = &0)`;
431      REAL_ENTIRE; REAL_SUB_0; REAL_LT_IMP_NE] THEN
432     STRIP_TAC THEN CONJ_TAC THENL
433      [EXISTS_TAC `a:real^N->real`; EXISTS_TAC `b:real^N->real`] THEN
434     ASM_SIMP_TAC[] THEN CONJ_TAC THEN FIRST_X_ASSUM(fun th g ->
435       (GEN_REWRITE_TAC RAND_CONV [GSYM th] THEN CONV_TAC SYM_CONV THEN
436        (MATCH_MP_TAC SUM_SUPERSET ORELSE MATCH_MP_TAC VSUM_SUPERSET)) g) THEN
437     ASM_SIMP_TAC[VECTOR_MUL_LZERO];
438     ALL_TAC] THEN
439   ABBREV_TAC `k = sum (s DIFF f:real^N->bool) c` THEN
440   SUBGOAL_THEN `&0 < k` ASSUME_TAC THENL
441    [ASM_REWRITE_TAC[REAL_LT_LE] THEN EXPAND_TAC "k" THEN
442     MATCH_MP_TAC SUM_POS_LE THEN ASM_SIMP_TAC[FINITE_DIFF; IN_DIFF];
443     ALL_TAC] THEN
444   ASM_CASES_TAC `k = &1` THENL
445    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_DISJOINT]) THEN
446     MATCH_MP_TAC(TAUT `b ==> ~b ==> c`) THEN
447     EXISTS_TAC `w:real^N` THEN
448     ASM_REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
449     EXISTS_TAC `c:real^N->real` THEN
450     ASM_SIMP_TAC[IN_DIFF; SUM_DIFF; VSUM_DIFF] THEN
451     SUBGOAL_THEN `vsum f (\x:real^N. c x % x) = vec 0` SUBST1_TAC THENL
452      [ALL_TAC;
453       EXPAND_TAC "c" THEN REWRITE_TAC[VECTOR_ADD_RDISTRIB] THEN
454       ASM_SIMP_TAC[VSUM_ADD; GSYM VECTOR_MUL_ASSOC; VSUM_LMUL] THEN
455       REWRITE_TAC[VECTOR_SUB_RZERO]] THEN
456     SUBGOAL_THEN `sum(s DIFF f) c = sum s c - sum f (c:real^N->real)`
457     MP_TAC THENL [ASM_MESON_TAC[SUM_DIFF]; ALL_TAC] THEN ASM_REWRITE_TAC[] THEN
458     SUBGOAL_THEN `sum s (c:real^N->real) = &1` SUBST1_TAC THENL
459      [EXPAND_TAC "c" THEN REWRITE_TAC[VECTOR_ADD_RDISTRIB] THEN
460       ASM_SIMP_TAC[SUM_ADD; GSYM REAL_MUL_ASSOC; SUM_LMUL] THEN
461       REAL_ARITH_TAC;
462       ALL_TAC] THEN
463     REWRITE_TAC[REAL_ARITH `&1 = &1 - x <=> x = &0`] THEN DISCH_TAC THEN
464     MP_TAC(ISPECL [`c:real^N->real`;`f:real^N->bool`] SUM_POS_EQ_0) THEN
465     ANTS_TAC THENL [ASM_MESON_TAC[FINITE_SUBSET; SUBSET]; ALL_TAC] THEN
466     SIMP_TAC[VECTOR_MUL_LZERO; VSUM_0];
467     ALL_TAC] THEN
468   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_DISJOINT]) THEN
469   MATCH_MP_TAC(TAUT `b ==> ~b ==> c`) THEN
470   EXISTS_TAC `inv(k) % (w - vsum f (\x:real^N. c x % x))` THEN CONJ_TAC THENL
471    [ALL_TAC;
472     SUBGOAL_THEN `w = vsum f (\x:real^N. c x % x) +
473                       vsum (s DIFF f) (\x:real^N. c x % x)`
474     SUBST1_TAC THENL
475      [ASM_SIMP_TAC[VSUM_DIFF; VECTOR_ARITH `a + b - a:real^N = b`] THEN
476       EXPAND_TAC "c" THEN REWRITE_TAC[VECTOR_ADD_RDISTRIB] THEN
477       ASM_SIMP_TAC[VSUM_ADD; GSYM VECTOR_MUL_ASSOC; VSUM_LMUL];
478       REWRITE_TAC[VECTOR_ADD_SUB]] THEN
479     ASM_SIMP_TAC[GSYM VSUM_LMUL; FINITE_DIFF] THEN
480     REWRITE_TAC[CONVEX_HULL_FINITE; IN_ELIM_THM] THEN
481     EXISTS_TAC `\x. inv k * (c:real^N->real) x` THEN
482     ASM_REWRITE_TAC[VECTOR_MUL_ASSOC] THEN
483     ASM_SIMP_TAC[IN_DIFF; REAL_LE_MUL; REAL_LE_INV_EQ; REAL_LT_IMP_LE] THEN
484     ASM_SIMP_TAC[SUM_LMUL; ETA_AX; REAL_MUL_LINV]] THEN
485   MATCH_MP_TAC lemma THEN REPEAT CONJ_TAC THENL
486    [REWRITE_TAC[AFFINE_AFFINE_HULL];
487     ASM_REWRITE_TAC[];
488     ASM_REWRITE_TAC[];
489     ASM_MESON_TAC[CONVEX_HULL_SUBSET_AFFINE_HULL; SUBSET];
490     ALL_TAC] THEN
491   ASM_SIMP_TAC[GSYM VSUM_LMUL; AFFINE_HULL_FINITE; IN_ELIM_THM] THEN
492   EXISTS_TAC `(\x. inv(&1 - k) * c x):real^N->real` THEN
493   REWRITE_TAC[VECTOR_MUL_ASSOC; SUM_LMUL] THEN
494   MATCH_MP_TAC(REAL_FIELD
495    `~(k = &1) /\ f = &1 - k ==> inv(&1 - k) * f = &1`) THEN
496   ASM_REWRITE_TAC[] THEN
497   SUBGOAL_THEN `sum(s DIFF f) c = sum s c - sum f (c:real^N->real)`
498   MP_TAC THENL [ASM_MESON_TAC[SUM_DIFF]; ALL_TAC] THEN ASM_REWRITE_TAC[] THEN
499   SUBGOAL_THEN `sum s (c:real^N->real) = &1` SUBST1_TAC THENL
500    [EXPAND_TAC "c" THEN REWRITE_TAC[VECTOR_ADD_RDISTRIB] THEN
501     ASM_SIMP_TAC[SUM_ADD; GSYM REAL_MUL_ASSOC; SUM_LMUL];
502     ALL_TAC] THEN
503   REAL_ARITH_TAC);;
504
505 let FACE_OF_CONVEX_HULL_INSERT = prove
506  (`!f s a:real^N.
507         FINITE s /\ ~(a IN affine hull s) /\ f face_of (convex hull s)
508         ==> f face_of (convex hull (a INSERT s))`,
509   REPEAT STRIP_TAC THEN MATCH_MP_TAC FACE_OF_TRANS THEN
510   EXISTS_TAC `convex hull s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
511   MATCH_MP_TAC FACE_OF_CONVEX_HULLS THEN
512   ASM_REWRITE_TAC[FINITE_INSERT; SET_RULE `s SUBSET a INSERT s`] THEN
513   FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
514    `~(a IN s) ==> t SUBSET {a} ==> DISJOINT s t`)) THEN
515   MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_SING] THEN SET_TAC[]);;
516
517 let FACE_OF_AFFINE_TRIVIAL = prove
518  (`!s f:real^N->bool.
519         affine s /\ f face_of s ==> f = {} \/ f = s`,
520   REPEAT STRIP_TAC THEN
521   ASM_CASES_TAC `f:real^N->bool = {}` THEN ASM_REWRITE_TAC[] THEN
522   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
523   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
524   FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_SUBSET) THEN
525   MATCH_MP_TAC SUBSET_ANTISYM THEN ASM_REWRITE_TAC[] THEN
526   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN
527   ASM_CASES_TAC `(b:real^N) IN f` THEN ASM_REWRITE_TAC[] THEN
528   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [face_of]) THEN
529   DISCH_THEN(MP_TAC o SPECL [`&2 % a - b:real^N`; `b:real^N`; `a:real^N`] o
530              CONJUNCT2 o CONJUNCT2) THEN
531   SUBGOAL_THEN `~(a:real^N = b)` ASSUME_TAC THENL
532    [ASM_MESON_TAC[]; ALL_TAC] THEN
533   ASM_SIMP_TAC[IN_SEGMENT; VECTOR_ARITH `&2 % a - b:real^N = b <=> a = b`] THEN
534   CONJ_TAC THENL
535    [REWRITE_TAC[VECTOR_ARITH `&2 % a - b:real^N = a + &1 % (a - b)`] THEN
536     MATCH_MP_TAC IN_AFFINE_ADD_MUL_DIFF THEN ASM SET_TAC[];
537     EXISTS_TAC `&1 / &2` THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
538     VECTOR_ARITH_TAC]);;
539
540 let FACE_OF_AFFINE_EQ = prove
541  (`!s:real^N->bool f. affine s ==> (f face_of s <=> f = {} \/ f = s)`,
542   MESON_TAC[FACE_OF_AFFINE_TRIVIAL; EMPTY_FACE_OF; FACE_OF_REFL;
543             AFFINE_IMP_CONVEX]);;
544
545 let INTERS_FACES_FINITE_BOUND = prove
546  (`!s f:(real^N->bool)->bool.
547         convex s /\ (!c. c IN f ==> c face_of s)
548         ==> ?f'. FINITE f' /\ f' SUBSET f /\ CARD f' <= dimindex(:N) + 1 /\
549                  INTERS f' = INTERS f`,
550   SUBGOAL_THEN
551    `!s f:(real^N->bool)->bool.
552         convex s /\ (!c. c IN f ==> c face_of s /\ ~(c = s))
553         ==> ?f'. FINITE f' /\ f' SUBSET f /\ CARD f' <= dimindex(:N) + 1 /\
554                  INTERS f' = INTERS f`
555   ASSUME_TAC THENL
556    [ALL_TAC;
557     REPEAT STRIP_TAC THEN
558     ASM_CASES_TAC `(s:real^N->bool) IN f` THENL
559      [ALL_TAC; FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_MESON_TAC[]] THEN
560     FIRST_ASSUM(DISJ_CASES_THEN2 SUBST1_TAC MP_TAC o MATCH_MP (SET_RULE
561      `s IN f ==> f = {s} \/ ?t. ~(t = s) /\ t IN f`)) THENL
562      [EXISTS_TAC `{s:real^N->bool}` THEN
563       SIMP_TAC[FINITE_INSERT; FINITE_EMPTY; SUBSET_REFL; CARD_CLAUSES] THEN
564       ARITH_TAC;
565       DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC)] THEN
566     FIRST_X_ASSUM(MP_TAC o SPECL [`s:real^N->bool`; `f DELETE
567       (s:real^N->bool)`]) THEN
568     ASM_SIMP_TAC[IN_DELETE; SUBSET_DELETE] THEN
569     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f':(real^N->bool)->bool` THEN
570     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
571     SUBGOAL_THEN `f = (s:real^N->bool) INSERT (f DELETE s)` MP_TAC THENL
572      [ASM SET_TAC[];
573       DISCH_THEN(fun th -> GEN_REWRITE_TAC (funpow 2 RAND_CONV) [th])] THEN
574     REWRITE_TAC[INTERS_INSERT] THEN
575     MATCH_MP_TAC(SET_RULE `t SUBSET s ==> t = s INTER t`) THEN
576     FIRST_X_ASSUM(MP_TAC o SPEC `t:real^N->bool`) THEN
577     ASM_REWRITE_TAC[] THEN
578     DISCH_THEN(ASSUME_TAC o MATCH_MP FACE_OF_IMP_SUBSET) THEN
579     MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `t:real^N->bool` THEN
580     ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET; IN_INTERS; IN_DELETE] THEN
581     ASM SET_TAC[]] THEN
582   REPEAT STRIP_TAC THEN ASM_CASES_TAC
583    `!f':(real^N->bool)->bool.
584         FINITE f' /\ f' SUBSET f /\ CARD f' <= dimindex(:N) + 1
585         ==> ?c. c IN f /\ c INTER (INTERS f') PSUBSET (INTERS f')`
586   THENL
587    [ALL_TAC;
588     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_FORALL_THM]) THEN
589     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
590     SIMP_TAC[NOT_IMP; GSYM CONJ_ASSOC] THEN
591     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
592     ASM_REWRITE_TAC[PSUBSET; INTER_SUBSET] THEN ASM SET_TAC[]] THEN
593   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE BINDER_CONV
594    [RIGHT_IMP_EXISTS_THM]) THEN
595   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
596   X_GEN_TAC `c:((real^N->bool)->bool)->real^N->bool` THEN DISCH_TAC THEN
597   CHOOSE_TAC(prove_recursive_functions_exist num_RECURSION
598    `d 0 = {c {} :real^N->bool} /\ !n. d(SUC n) = c(d n) INSERT d n`) THEN
599   SUBGOAL_THEN `!n:num. ~(d n:(real^N->bool)->bool = {})` ASSUME_TAC THENL
600    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN SET_TAC[]; ALL_TAC] THEN
601   SUBGOAL_THEN
602    `!n. n <= dimindex(:N) + 1
603         ==> (d n) SUBSET (f:(real^N->bool)->bool) /\
604             FINITE(d n) /\ CARD(d n) <= n + 1`
605   ASSUME_TAC THENL
606    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN
607     ASM_SIMP_TAC[INSERT_SUBSET; CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY;
608       EMPTY_SUBSET; ARITH_RULE `SUC n <= m + 1 ==> n <= m + 1`] THEN
609     REPEAT STRIP_TAC THEN TRY ASM_ARITH_TAC THEN
610     FIRST_X_ASSUM(MP_TAC o SPEC `(d:num->(real^N->bool)->bool) n`) THEN
611     FIRST_X_ASSUM(MP_TAC o check (is_imp o concl)) THEN
612     ANTS_TAC THENL [ASM_ARITH_TAC; STRIP_TAC] THEN ASM_REWRITE_TAC[] THEN
613     ANTS_TAC THENL [ASM_ARITH_TAC; SIMP_TAC[]];
614     ALL_TAC] THEN
615   SUBGOAL_THEN
616    `!n. n <= dimindex(:N)
617         ==> (INTERS(d(SUC n)):real^N->bool) PSUBSET INTERS(d n)`
618   ASSUME_TAC THENL
619    [REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[INTERS_INSERT] THEN
620     FIRST_X_ASSUM(MP_TAC o SPEC `(d:num->(real^N->bool)->bool) n`) THEN
621     ANTS_TAC THENL [ALL_TAC; SIMP_TAC[]] THEN
622     REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `n:num`)) THEN
623     ASM_SIMP_TAC[ARITH_RULE `n <= N ==> n <= N + 1`] THEN
624     ASM_ARITH_TAC;
625     ALL_TAC] THEN
626   FIRST_X_ASSUM(CONJUNCTS_THEN(K ALL_TAC)) THEN
627   SUBGOAL_THEN
628    `!n. n <= dimindex(:N) + 1
629         ==> aff_dim(INTERS(d n):real^N->bool) < &(dimindex(:N)) - &n`
630   MP_TAC THENL
631    [INDUCT_TAC THENL
632      [DISCH_TAC THEN REWRITE_TAC[INT_SUB_RZERO] THEN
633       MATCH_MP_TAC INT_LTE_TRANS THEN
634       EXISTS_TAC `aff_dim(s:real^N->bool)` THEN
635       REWRITE_TAC[AFF_DIM_LE_UNIV] THEN
636       MATCH_MP_TAC FACE_OF_AFF_DIM_LT THEN
637       ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
638        [MATCH_MP_TAC FACE_OF_INTERS THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
639         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY] o
640           SPEC `0`) THEN
641         DISCH_THEN(X_CHOOSE_TAC `e:real^N->bool`) THEN
642         FIRST_X_ASSUM(MP_TAC o SPEC `e:real^N->bool`) THEN
643         ANTS_TAC THENL [ASM SET_TAC[]; STRIP_TAC] THEN
644         MATCH_MP_TAC(SET_RULE
645          `!t. t PSUBSET s /\ u SUBSET t ==> ~(u = s)`) THEN
646         EXISTS_TAC `e:real^N->bool` THEN
647         FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_SUBSET) THEN
648         ASM SET_TAC[]];
649       DISCH_TAC THEN REWRITE_TAC[GSYM INT_OF_NUM_SUC] THEN
650       MATCH_MP_TAC(INT_ARITH
651        `!d':int. d < d' /\ d' < m - n ==> d < m - (n + &1)`) THEN
652       EXISTS_TAC `aff_dim(INTERS(d(n:num)):real^N->bool)` THEN
653       ASM_SIMP_TAC[ARITH_RULE `SUC n <= k + 1 ==> n <= k + 1`] THEN
654       MATCH_MP_TAC FACE_OF_AFF_DIM_LT THEN
655       ASM_SIMP_TAC[ARITH_RULE `SUC n <= m + 1 ==> n <= m`;
656                    SET_RULE `s PSUBSET t ==> ~(s = t)`] THEN
657       CONJ_TAC THENL
658        [MATCH_MP_TAC CONVEX_INTERS THEN
659         REPEAT STRIP_TAC THEN MATCH_MP_TAC FACE_OF_IMP_CONVEX THEN
660         EXISTS_TAC `s:real^N->bool` THEN
661         ASM_MESON_TAC[SUBSET; ARITH_RULE `SUC n <= m + 1 ==> n <= m + 1`];
662         ALL_TAC] THEN
663       MP_TAC(ISPECL [`INTERS(d(SUC n)):real^N->bool`;`s:real^N->bool`;
664                      `INTERS(d(n:num)):real^N->bool`] FACE_OF_FACE) THEN
665       ASM_SIMP_TAC[SET_RULE `s PSUBSET t ==> s SUBSET t`;
666                    ARITH_RULE `SUC n <= m + 1 ==> n <= m`] THEN
667       MATCH_MP_TAC(TAUT `a /\ b ==> (a ==> (c <=> b)) ==> c`) THEN
668       CONJ_TAC THEN MATCH_MP_TAC FACE_OF_INTERS THEN ASM_REWRITE_TAC[] THEN
669       ASM_MESON_TAC[SUBSET; ARITH_RULE `SUC n <= m + 1 ==> n <= m + 1`]];
670     ALL_TAC] THEN
671   DISCH_THEN(MP_TAC o SPEC `dimindex(:N) + 1`) THEN REWRITE_TAC[LE_REFL] THEN
672   MATCH_MP_TAC(TAUT `~p ==> p ==> q`) THEN REWRITE_TAC[INT_NOT_LT] THEN
673   REWRITE_TAC[GSYM INT_OF_NUM_ADD; INT_ARITH `d - (d + &1):int = -- &1`] THEN
674   REWRITE_TAC[AFF_DIM_GE]);;
675
676 let INTERS_FACES_FINITE_ALTBOUND = prove
677  (`!s f:(real^N->bool)->bool.
678         (!c. c IN f ==> c face_of s)
679         ==> ?f'. FINITE f' /\ f' SUBSET f /\ CARD f' <= dimindex(:N) + 2 /\
680                  INTERS f' = INTERS f`,
681   REPEAT STRIP_TAC THEN ASM_CASES_TAC
682    `!f':(real^N->bool)->bool.
683         FINITE f' /\ f' SUBSET f /\ CARD f' <= dimindex(:N) + 2
684         ==> ?c. c IN f /\ c INTER (INTERS f') PSUBSET (INTERS f')`
685   THENL
686    [ALL_TAC;
687     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_FORALL_THM]) THEN
688     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
689     SIMP_TAC[NOT_IMP; GSYM CONJ_ASSOC] THEN
690     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
691     ASM_REWRITE_TAC[PSUBSET; INTER_SUBSET] THEN ASM SET_TAC[]] THEN
692   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE BINDER_CONV
693    [RIGHT_IMP_EXISTS_THM]) THEN
694   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
695   X_GEN_TAC `c:((real^N->bool)->bool)->real^N->bool` THEN DISCH_TAC THEN
696   CHOOSE_TAC(prove_recursive_functions_exist num_RECURSION
697    `d 0 = {c {} :real^N->bool} /\ !n. d(SUC n) = c(d n) INSERT d n`) THEN
698   SUBGOAL_THEN `!n:num. ~(d n:(real^N->bool)->bool = {})` ASSUME_TAC THENL
699    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN SET_TAC[]; ALL_TAC] THEN
700   SUBGOAL_THEN
701    `!n. n <= dimindex(:N) + 2
702         ==> (d n) SUBSET (f:(real^N->bool)->bool) /\
703             FINITE(d n) /\ CARD(d n) <= n + 1`
704   ASSUME_TAC THENL
705    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN
706     ASM_SIMP_TAC[INSERT_SUBSET; CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY;
707       EMPTY_SUBSET; ARITH_RULE `SUC n <= m + 2 ==> n <= m + 2`] THEN
708     REPEAT STRIP_TAC THEN TRY ASM_ARITH_TAC THEN
709     FIRST_X_ASSUM(MP_TAC o SPEC `(d:num->(real^N->bool)->bool) n`) THEN
710     FIRST_X_ASSUM(MP_TAC o check (is_imp o concl)) THEN
711     ANTS_TAC THENL [ASM_ARITH_TAC; STRIP_TAC] THEN ASM_REWRITE_TAC[] THEN
712     ANTS_TAC THENL [ASM_ARITH_TAC; SIMP_TAC[]];
713     ALL_TAC] THEN
714   SUBGOAL_THEN
715    `!n. n <= dimindex(:N) + 1
716         ==> (INTERS(d(SUC n)):real^N->bool) PSUBSET INTERS(d n)`
717   ASSUME_TAC THENL
718    [REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[INTERS_INSERT] THEN
719     FIRST_X_ASSUM(MP_TAC o SPEC `(d:num->(real^N->bool)->bool) n`) THEN
720     ANTS_TAC THENL [ALL_TAC; SIMP_TAC[]] THEN
721     REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `n:num`)) THEN
722     ASM_SIMP_TAC[ARITH_RULE `n <= N + 1 ==> n <= N + 2`] THEN
723     ASM_ARITH_TAC;
724     ALL_TAC] THEN
725   FIRST_X_ASSUM(CONJUNCTS_THEN(K ALL_TAC)) THEN
726   SUBGOAL_THEN
727    `!n. n <= dimindex(:N) + 2
728         ==> aff_dim(INTERS(d n):real^N->bool) <= &(dimindex(:N)) - &n`
729   MP_TAC THENL
730    [INDUCT_TAC THEN REWRITE_TAC[INT_SUB_RZERO; AFF_DIM_LE_UNIV] THEN
731     DISCH_TAC THEN REWRITE_TAC[GSYM INT_OF_NUM_SUC] THEN
732     MATCH_MP_TAC(INT_ARITH
733      `!d':int. d < d' /\ d' <= m - n ==> d <= m - (n + &1)`) THEN
734     EXISTS_TAC `aff_dim(INTERS(d(n:num)):real^N->bool)` THEN
735     ASM_SIMP_TAC[ARITH_RULE `SUC n <= k + 2 ==> n <= k + 2`] THEN
736     MATCH_MP_TAC FACE_OF_AFF_DIM_LT THEN
737     ASM_SIMP_TAC[ARITH_RULE `SUC n <= m + 2 ==> n <= m + 1`;
738                  SET_RULE `s PSUBSET t ==> ~(s = t)`] THEN
739     CONJ_TAC THENL
740      [MATCH_MP_TAC CONVEX_INTERS THEN
741       REPEAT STRIP_TAC THEN MATCH_MP_TAC FACE_OF_IMP_CONVEX THEN
742       EXISTS_TAC `s:real^N->bool` THEN
743       ASM_MESON_TAC[SUBSET; ARITH_RULE `SUC n <= m + 2 ==> n <= m + 2`];
744       ALL_TAC] THEN
745     MP_TAC(ISPECL [`INTERS(d(SUC n)):real^N->bool`;`s:real^N->bool`;
746                    `INTERS(d(n:num)):real^N->bool`] FACE_OF_FACE) THEN
747     ASM_SIMP_TAC[SET_RULE `s PSUBSET t ==> s SUBSET t`;
748                  ARITH_RULE `SUC n <= m + 2 ==> n <= m + 1`] THEN
749     MATCH_MP_TAC(TAUT `a /\ b ==> (a ==> (c <=> b)) ==> c`) THEN
750     CONJ_TAC THEN MATCH_MP_TAC FACE_OF_INTERS THEN ASM_REWRITE_TAC[] THEN
751     ASM_MESON_TAC[SUBSET; ARITH_RULE `SUC n <= m + 2 ==> n <= m + 2`];
752     ALL_TAC] THEN
753   DISCH_THEN(MP_TAC o SPEC `dimindex(:N) + 2`) THEN REWRITE_TAC[LE_REFL] THEN
754   MATCH_MP_TAC(TAUT `~p ==> p ==> q`) THEN REWRITE_TAC[INT_NOT_LE] THEN
755   REWRITE_TAC[GSYM INT_OF_NUM_ADD; INT_ARITH
756     `d - (d + &2):int < i <=> -- &1 <= i`] THEN
757   REWRITE_TAC[AFF_DIM_GE]);;
758
759 let FACES_OF_TRANSLATION = prove
760  (`!s a:real^N.
761         {f | f face_of IMAGE (\x. a + x) s} =
762         IMAGE (IMAGE (\x. a + x)) {f | f face_of s}`,
763   REPEAT GEN_TAC THEN CONV_TAC SYM_CONV THEN
764   MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
765   REWRITE_TAC[IN_ELIM_THM; FACE_OF_TRANSLATION_EQ] THEN
766   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN
767   ONCE_REWRITE_TAC[TRANSLATION_GALOIS] THEN
768   REWRITE_TAC[EXISTS_REFL]);;
769
770 let FACES_OF_LINEAR_IMAGE = prove
771  (`!f:real^M->real^N s.
772         linear f /\ (!x y. f x = f y ==> x = y)
773         ==> {t | t face_of (IMAGE f s)} = IMAGE (IMAGE f) {t | t face_of s}`,
774   REPEAT GEN_TAC THEN DISCH_TAC THEN
775   REWRITE_TAC[face_of; SUBSET_IMAGE; SET_RULE
776    `{y | (?x. P x /\ y = f x) /\ Q y} = {f x |x| P x /\ Q(f x)}`] THEN
777   REWRITE_TAC[SET_RULE `IMAGE f {x | P x} = {f x | P x}`] THEN
778   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN
779   FIRST_ASSUM(fun th ->
780    REWRITE_TAC[MATCH_MP CONVEX_LINEAR_IMAGE_EQ th;
781                MATCH_MP OPEN_SEGMENT_LINEAR_IMAGE th;
782                MATCH_MP (SET_RULE
783    `(!x y. f x = f y ==> x = y)  ==> (!s x. f x IN IMAGE f s <=> x IN s)`)
784    (CONJUNCT2 th)]));;
785
786 let FACE_OF_CONIC = prove
787  (`!s f:real^N->bool. conic s /\ f face_of s ==> conic f`,
788   REPEAT GEN_TAC THEN REWRITE_TAC[face_of; conic] THEN STRIP_TAC THEN
789   MAP_EVERY X_GEN_TAC [`x:real^N`; `c:real`] THEN STRIP_TAC THEN
790   ASM_CASES_TAC `x:real^N = vec 0` THENL
791    [ASM_MESON_TAC[VECTOR_MUL_RZERO]; ALL_TAC] THEN
792   ASM_CASES_TAC `c = &1` THENL
793    [ASM_MESON_TAC[VECTOR_MUL_LID]; ALL_TAC] THEN
794   SUBGOAL_THEN `?d e. &0 <= d /\ &0 <= e /\ d < &1 /\ &1 < e /\ d < e /\
795                       (d = c \/ e = c)`
796   MP_TAC THENL
797    [FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
798      `~(c = &1) ==> c < &1 \/ &1 < c`))
799     THENL
800      [MAP_EVERY EXISTS_TAC [`c:real`; `&2`] THEN ASM_REAL_ARITH_TAC;
801       MAP_EVERY EXISTS_TAC [`&1 / &2`; `c:real`] THEN ASM_REAL_ARITH_TAC];
802     DISCH_THEN(REPEAT_TCL CHOOSE_THEN
803       (REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC)) THEN
804     FIRST_X_ASSUM(MP_TAC o SPECL
805      [`d % x :real^N`; `e % x:real^N`; `x:real^N`]) THEN
806     ANTS_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
807     SUBGOAL_THEN `(x:real^N) IN s` ASSUME_TAC THENL
808      [ASM SET_TAC[]; ASM_SIMP_TAC[IN_SEGMENT]] THEN
809     ASM_SIMP_TAC[VECTOR_MUL_RCANCEL; REAL_LT_IMP_NE] THEN
810     EXISTS_TAC `(&1 - d) / (e - d)`  THEN
811     ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_SUB_LT] THEN
812     REPEAT(CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
813     REWRITE_TAC[VECTOR_MUL_ASSOC; GSYM VECTOR_ADD_RDISTRIB] THEN
814     REWRITE_TAC[VECTOR_ARITH `x:real^N = a % x <=> (a - &1) % x = vec 0`] THEN
815     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0] THEN
816     UNDISCH_TAC `d:real < e` THEN CONV_TAC REAL_FIELD]);;
817
818 let FACE_OF_PCROSS = prove
819  (`!f s:real^M->bool f' s':real^N->bool.
820         f face_of s /\ f' face_of s' ==> (f PCROSS f') face_of (s PCROSS s')`,
821   REPEAT GEN_TAC THEN SIMP_TAC[face_of; CONVEX_PCROSS; PCROSS_MONO] THEN
822   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
823   REWRITE_TAC[IN_SEGMENT; FORALL_IN_PCROSS] THEN
824   REWRITE_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP; GSYM CONJ_ASSOC] THEN
825   REWRITE_TAC[GSYM PASTECART_CMUL; PASTECART_ADD; PASTECART_INJ] THEN
826   REWRITE_TAC[PASTECART_IN_PCROSS] THEN
827   MAP_EVERY X_GEN_TAC
828    [`a:real^M`; `a':real^N`; `b:real^M`; `b':real^N`] THEN
829   MAP_EVERY ASM_CASES_TAC [`b:real^M = a`; `b':real^N = a'`] THEN
830   ASM_REWRITE_TAC[VECTOR_ARITH `(&1 - u) % a + u % a:real^N = a`] THEN
831   ASM_MESON_TAC[]);;
832
833 let FACE_OF_PCROSS_DECOMP = prove
834  (`!s:real^M->bool s':real^N->bool c.
835         c face_of (s PCROSS s') <=>
836         ?f f'. f face_of s /\ f' face_of s' /\ c = f PCROSS f'`,
837   REPEAT GEN_TAC THEN EQ_TAC THENL
838    [ALL_TAC; STRIP_TAC THEN ASM_SIMP_TAC[FACE_OF_PCROSS]] THEN
839   ASM_CASES_TAC `c:real^(M,N)finite_sum->bool = {}` THENL
840    [ASM_MESON_TAC[EMPTY_FACE_OF; PCROSS_EMPTY]; DISCH_TAC] THEN
841   FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_CONVEX) THEN
842   MAP_EVERY EXISTS_TAC
843    [`IMAGE fstcart (c:real^(M,N)finite_sum->bool)`;
844     `IMAGE sndcart (c:real^(M,N)finite_sum->bool)`] THEN
845   MATCH_MP_TAC(TAUT `(p /\ q ==> r) /\ p /\ q ==> p /\ q /\ r`) THEN
846   CONJ_TAC THENL
847    [STRIP_TAC THEN MATCH_MP_TAC FACE_OF_EQ THEN
848     EXISTS_TAC `(s:real^M->bool) PCROSS (s':real^N->bool)` THEN
849     ASM_SIMP_TAC[FACE_OF_PCROSS; RELATIVE_INTERIOR_PCROSS] THEN
850     ASM_SIMP_TAC[RELATIVE_INTERIOR_LINEAR_IMAGE_CONVEX;
851                  LINEAR_FSTCART; LINEAR_SNDCART] THEN
852     MATCH_MP_TAC(SET_RULE `~(s = {}) /\ s SUBSET t ==> ~DISJOINT s t`) THEN
853     ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY] THEN
854     REWRITE_TAC[SUBSET; FORALL_PASTECART; PASTECART_IN_PCROSS; IN_IMAGE] THEN
855     REWRITE_TAC[EXISTS_PASTECART; FSTCART_PASTECART; SNDCART_PASTECART] THEN
856     MESON_TAC[];
857     ALL_TAC] THEN
858   FIRST_X_ASSUM(STRIP_ASSUME_TAC o GEN_REWRITE_RULE I [face_of]) THEN
859   REWRITE_TAC[face_of] THEN
860   ASM_SIMP_TAC[CONVEX_LINEAR_IMAGE; LINEAR_FSTCART; LINEAR_SNDCART] THEN
861   FIRST_ASSUM(MP_TAC o ISPEC `fstcart:real^(M,N)finite_sum->real^M` o
862         MATCH_MP IMAGE_SUBSET) THEN
863   FIRST_ASSUM(MP_TAC o ISPEC `sndcart:real^(M,N)finite_sum->real^N` o
864         MATCH_MP IMAGE_SUBSET) THEN
865   REWRITE_TAC[IMAGE_FSTCART_PCROSS; IMAGE_SNDCART_PCROSS] THEN
866   REPEAT(DISCH_THEN(ASSUME_TAC o MATCH_MP (SET_RULE
867    `s SUBSET (if p then {} else t) ==> s SUBSET t`))) THEN
868   ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
869    [MAP_EVERY X_GEN_TAC [`a:real^M`; `b:real^M`; `x:real^M`] THEN
870     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_IMAGE]) THEN
871     REWRITE_TAC[EXISTS_PASTECART; FSTCART_PASTECART] THEN
872     REWRITE_TAC[RIGHT_EXISTS_AND_THM; UNWIND_THM1] THEN
873     DISCH_THEN(X_CHOOSE_TAC `y:real^N`) THEN FIRST_X_ASSUM(MP_TAC o SPECL
874      [`pastecart (a:real^M) (y:real^N)`;
875       `pastecart (b:real^M) (y:real^N)`;
876       `pastecart (x:real^M) (y:real^N)`]) THEN
877     ASM_REWRITE_TAC[PASTECART_IN_PCROSS; IN_IMAGE; EXISTS_PASTECART] THEN
878     REWRITE_TAC[FSTCART_PASTECART; RIGHT_EXISTS_AND_THM; UNWIND_THM1] THEN
879     ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
880     UNDISCH_TAC `(c:real^(M,N)finite_sum->bool) SUBSET s PCROSS s'` THEN
881     REWRITE_TAC[SUBSET] THEN
882     DISCH_THEN(MP_TAC o SPEC `pastecart (x:real^M) (y:real^N)`);
883     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`; `x:real^N`] THEN
884     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_IMAGE]) THEN
885     REWRITE_TAC[EXISTS_PASTECART; SNDCART_PASTECART] THEN
886     REWRITE_TAC[RIGHT_EXISTS_AND_THM; UNWIND_THM1] THEN
887     DISCH_THEN(X_CHOOSE_TAC `y:real^M`) THEN FIRST_X_ASSUM(MP_TAC o SPECL
888      [`pastecart (y:real^M) (a:real^N)`;
889       `pastecart (y:real^M) (b:real^N)`;
890       `pastecart (y:real^M) (x:real^N)`]) THEN
891     ASM_REWRITE_TAC[PASTECART_IN_PCROSS; IN_IMAGE; EXISTS_PASTECART] THEN
892     REWRITE_TAC[SNDCART_PASTECART; RIGHT_EXISTS_AND_THM; UNWIND_THM1] THEN
893     ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
894     UNDISCH_TAC `(c:real^(M,N)finite_sum->bool) SUBSET s PCROSS s'` THEN
895     REWRITE_TAC[SUBSET] THEN
896     DISCH_THEN(MP_TAC o SPEC `pastecart (y:real^M) (x:real^N)`)] THEN
897   ASM_REWRITE_TAC[PASTECART_IN_PCROSS] THEN STRIP_TAC THEN
898   ASM_REWRITE_TAC[] THEN
899   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT]) THEN
900   REWRITE_TAC[IN_SEGMENT; PASTECART_INJ] THEN
901   REWRITE_TAC[PASTECART_ADD; GSYM PASTECART_CMUL;
902               VECTOR_ARITH `(&1 - u) % a + u % a:real^N = a`] THEN
903   MESON_TAC[]);;
904
905 let FACE_OF_PCROSS_EQ = prove
906  (`!f s:real^M->bool f' s':real^N->bool.
907         (f PCROSS f') face_of (s PCROSS s') <=>
908         f = {} \/ f' = {} \/ f face_of s /\ f' face_of s'`,
909   REPEAT GEN_TAC THEN MAP_EVERY ASM_CASES_TAC
910    [`f:real^M->bool = {}`; `f':real^N->bool = {}`] THEN
911   ASM_REWRITE_TAC[PCROSS_EMPTY; EMPTY_FACE_OF] THEN
912   ASM_REWRITE_TAC[FACE_OF_PCROSS_DECOMP; PCROSS_EQ] THEN MESON_TAC[]);;
913
914 let HYPERPLANE_FACE_OF_HALFSPACE_LE = prove
915  (`!a:real^N b. {x | a dot x = b} face_of {x | a dot x <= b}`,
916   REPEAT GEN_TAC THEN
917   ONCE_REWRITE_TAC[REAL_ARITH `a:real = b <=> a <= b /\ a = b`] THEN
918   REWRITE_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
919   MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN
920   REWRITE_TAC[IN_ELIM_THM; CONVEX_HALFSPACE_LE]);;
921
922 let HYPERPLANE_FACE_OF_HALFSPACE_GE = prove
923  (`!a:real^N b. {x | a dot x = b} face_of {x | a dot x >= b}`,
924   REPEAT GEN_TAC THEN
925   ONCE_REWRITE_TAC[REAL_ARITH `a:real = b <=> a >= b /\ a = b`] THEN
926   REWRITE_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
927   MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE THEN
928   REWRITE_TAC[IN_ELIM_THM; CONVEX_HALFSPACE_GE]);;
929
930 let FACE_OF_HALFSPACE_LE = prove
931  (`!f a:real^N b.
932          f face_of {x | a dot x <= b} <=>
933          f = {} \/ f = {x | a dot x = b} \/ f = {x | a dot x <= b}`,
934   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THENL
935    [ASM_SIMP_TAC[DOT_LZERO; SET_RULE `{x | p} = if p then UNIV else {}`] THEN
936     REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[FACE_OF_EMPTY]) THEN
937     ASM_SIMP_TAC[FACE_OF_AFFINE_EQ; AFFINE_UNIV; DISJ_ACI] THEN
938     ASM_REAL_ARITH_TAC;
939     ALL_TAC] THEN
940   EQ_TAC THEN STRIP_TAC THEN
941   ASM_SIMP_TAC[EMPTY_FACE_OF; FACE_OF_REFL; CONVEX_HALFSPACE_LE;
942                HYPERPLANE_FACE_OF_HALFSPACE_LE] THEN
943   MATCH_MP_TAC(TAUT `(~r ==> p \/ q) ==> p \/ q \/ r`) THEN DISCH_TAC THEN
944   SUBGOAL_THEN `f face_of {x:real^N | a dot x = b}` MP_TAC THENL
945    [ASM_SIMP_TAC[GSYM FRONTIER_HALFSPACE_LE] THEN
946     ASM_SIMP_TAC[CONV_RULE(RAND_CONV SYM_CONV)
947                   (SPEC_ALL RELATIVE_FRONTIER_NONEMPTY_INTERIOR);
948                  INTERIOR_HALFSPACE_LE; HALFSPACE_EQ_EMPTY_LT] THEN
949     MATCH_MP_TAC FACE_OF_SUBSET THEN
950     EXISTS_TAC `{x:real^N | a dot x <= b}` THEN
951     ASM_SIMP_TAC[FACE_OF_SUBSET_RELATIVE_FRONTIER] THEN
952     ASM_SIMP_TAC[relative_frontier; CLOSURE_CLOSED; CLOSED_HALFSPACE_LE] THEN
953     SET_TAC[];
954     ASM_SIMP_TAC[FACE_OF_AFFINE_EQ; AFFINE_HYPERPLANE]]);;
955
956 let FACE_OF_HALFSPACE_GE = prove
957  (`!f a:real^N b.
958          f face_of {x | a dot x >= b} <=>
959          f = {} \/ f = {x | a dot x = b} \/ f = {x | a dot x >= b}`,
960   REPEAT GEN_TAC THEN
961   MP_TAC(ISPECL [`f:real^N->bool`; `--a:real^N`; `--b:real`]
962         FACE_OF_HALFSPACE_LE) THEN
963   REWRITE_TAC[DOT_LNEG; REAL_LE_NEG2; REAL_EQ_NEG2; real_ge]);;
964
965 (* ------------------------------------------------------------------------- *)
966 (* Exposed faces (faces that are intersection with supporting hyperplane).   *)
967 (* ------------------------------------------------------------------------- *)
968
969 parse_as_infix("exposed_face_of",(12,"right"));;
970
971 let exposed_face_of = new_definition
972  `t exposed_face_of s <=>
973     t face_of s /\
974     ?a b. s SUBSET {x | a dot x <= b} /\ t = s INTER {x | a dot x = b}`;;
975
976 let EMPTY_EXPOSED_FACE_OF = prove
977  (`!s:real^N->bool. {} exposed_face_of s`,
978   GEN_TAC THEN REWRITE_TAC[exposed_face_of; EMPTY_FACE_OF] THEN
979   MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `&1:real`] THEN
980   REWRITE_TAC[DOT_LZERO] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN SET_TAC[]);;
981
982 let EXPOSED_FACE_OF_REFL_EQ = prove
983  (`!s:real^N->bool. s exposed_face_of s <=> convex s`,
984   GEN_TAC THEN REWRITE_TAC[exposed_face_of; FACE_OF_REFL_EQ] THEN
985   ASM_CASES_TAC `convex(s:real^N->bool)` THEN ASM_REWRITE_TAC[] THEN
986   MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `&0:real`] THEN
987   REWRITE_TAC[DOT_LZERO] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN SET_TAC[]);;
988
989 let EXPOSED_FACE_OF_REFL = prove
990  (`!s:real^N->bool. convex s ==> s exposed_face_of s`,
991   REWRITE_TAC[EXPOSED_FACE_OF_REFL_EQ]);;
992
993 let EXPOSED_FACE_OF = prove
994  (`!s t. t exposed_face_of s <=>
995              t face_of s /\
996              (t = {} \/ t = s \/
997               ?a b. ~(a = vec 0) /\
998                     s SUBSET {x:real^N | a dot x <= b} /\
999                     t = s INTER {x | a dot x = b})`,
1000   REPEAT GEN_TAC THEN ASM_CASES_TAC `t:real^N->bool = {}` THEN
1001   ASM_REWRITE_TAC[EMPTY_EXPOSED_FACE_OF; EMPTY_FACE_OF] THEN
1002   ASM_CASES_TAC `t:real^N->bool = s` THEN
1003   ASM_REWRITE_TAC[EXPOSED_FACE_OF_REFL_EQ; FACE_OF_REFL_EQ] THEN
1004   REWRITE_TAC[exposed_face_of] THEN AP_TERM_TAC THEN
1005   EQ_TAC THENL [REWRITE_TAC[LEFT_IMP_EXISTS_THM]; MESON_TAC[]] THEN
1006   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN
1007   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1008   MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real`] THEN
1009   ASM_CASES_TAC `a:real^N = vec 0` THEN ASM_REWRITE_TAC[] THEN
1010   FIRST_X_ASSUM SUBST_ALL_TAC THEN REPEAT(POP_ASSUM MP_TAC) THEN
1011   REWRITE_TAC[DOT_LZERO] THEN SET_TAC[]);;
1012
1013 let EXPOSED_FACE_OF_TRANSLATION_EQ = prove
1014  (`!a f s:real^N->bool.
1015         (IMAGE (\x. a + x) f) exposed_face_of (IMAGE (\x. a + x) s) <=>
1016         f exposed_face_of s`,
1017   REPEAT GEN_TAC THEN REWRITE_TAC[exposed_face_of; FACE_OF_TRANSLATION_EQ] THEN
1018   MP_TAC(ISPEC `\x:real^N. a + x` QUANTIFY_SURJECTION_THM) THEN
1019   REWRITE_TAC[] THEN ANTS_TAC THENL
1020    [MESON_TAC[VECTOR_ARITH `y + (x - y):real^N = x`]; ALL_TAC] THEN
1021   DISCH_THEN(fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
1022     [last(CONJUNCTS th)]) THEN
1023   REWRITE_TAC[end_itlist CONJ (!invariant_under_translation)] THEN
1024   REWRITE_TAC[DOT_RADD] THEN ONCE_REWRITE_TAC[REAL_ADD_SYM] THEN
1025   REWRITE_TAC[GSYM REAL_LE_SUB_LADD; GSYM REAL_EQ_SUB_LADD] THEN
1026   AP_TERM_TAC THEN AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
1027   X_GEN_TAC `c:real^N` THEN REWRITE_TAC[] THEN
1028   EQ_TAC THEN DISCH_THEN(X_CHOOSE_THEN `b:real` STRIP_ASSUME_TAC) THENL
1029    [EXISTS_TAC `b - (c:real^N) dot a`;
1030     EXISTS_TAC `b + (c:real^N) dot a`] THEN
1031   ASM_REWRITE_TAC[REAL_ARITH `(x + y) - y:real = x`]);;
1032
1033 add_translation_invariants [EXPOSED_FACE_OF_TRANSLATION_EQ];;
1034
1035 let EXPOSED_FACE_OF_LINEAR_IMAGE = prove
1036  (`!f:real^M->real^N c s.
1037       linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
1038       ==> ((IMAGE f c) exposed_face_of (IMAGE f s) <=> c exposed_face_of s)`,
1039   REPEAT STRIP_TAC THEN REWRITE_TAC[exposed_face_of] THEN
1040   BINOP_TAC THENL [ASM_MESON_TAC[FACE_OF_LINEAR_IMAGE]; ALL_TAC] THEN
1041   MP_TAC(ISPEC `f:real^M->real^N` QUANTIFY_SURJECTION_THM) THEN
1042   ASM_REWRITE_TAC[] THEN
1043   DISCH_THEN(fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
1044     [last(CONJUNCTS th)]) THEN
1045   ONCE_REWRITE_TAC[DOT_SYM] THEN ASM_SIMP_TAC[ADJOINT_WORKS] THEN
1046   MP_TAC(end_itlist CONJ
1047    (mapfilter (ISPEC `f:real^M->real^N`) (!invariant_under_linear))) THEN
1048   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
1049   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN AP_TERM_TAC THEN ABS_TAC THEN
1050   EQ_TAC THENL
1051    [DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
1052     EXISTS_TAC `adjoint(f:real^M->real^N) a` THEN ASM_REWRITE_TAC[];
1053     DISCH_THEN(X_CHOOSE_THEN `a:real^M` STRIP_ASSUME_TAC) THEN
1054     MP_TAC(ISPEC `adjoint(f:real^M->real^N)`
1055       LINEAR_SURJECTIVE_RIGHT_INVERSE) THEN
1056     ASM_SIMP_TAC[ADJOINT_SURJECTIVE; ADJOINT_LINEAR] THEN
1057     REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM; LEFT_IMP_EXISTS_THM] THEN
1058     X_GEN_TAC `g:real^M->real^N` THEN STRIP_TAC THEN
1059     EXISTS_TAC `(g:real^M->real^N) a` THEN ASM_REWRITE_TAC[]]);;
1060
1061 let EXPOSED_FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE = prove
1062  (`!s a:real^N b.
1063         convex s /\ (!x. x IN s ==> a dot x <= b)
1064         ==> (s INTER {x | a dot x = b}) exposed_face_of s`,
1065   SIMP_TAC[FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE; exposed_face_of] THEN
1066   SET_TAC[]);;
1067
1068 let EXPOSED_FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE = prove
1069  (`!s a:real^N b.
1070         convex s /\ (!x. x IN s ==> a dot x >= b)
1071         ==> (s INTER {x | a dot x = b}) exposed_face_of s`,
1072   REWRITE_TAC[real_ge] THEN REPEAT STRIP_TAC THEN
1073   MP_TAC(ISPECL [`s:real^N->bool`; `--a:real^N`; `--b:real`]
1074     EXPOSED_FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE) THEN
1075   ASM_REWRITE_TAC[DOT_LNEG; REAL_EQ_NEG2; REAL_LE_NEG2]);;
1076
1077 let EXPOSED_FACE_OF_INTER = prove
1078  (`!s t u:real^N->bool.
1079         t exposed_face_of s /\ u exposed_face_of s
1080         ==> (t INTER u) exposed_face_of s`,
1081   REPEAT GEN_TAC THEN SIMP_TAC[exposed_face_of; FACE_OF_INTER] THEN
1082   REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
1083   REWRITE_TAC[LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
1084   MAP_EVERY X_GEN_TAC
1085    [`a':real^N`; `b':real`; `a:real^N`; `b:real`] THEN
1086   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN STRIP_TAC THEN
1087   ASM_REWRITE_TAC[] THEN
1088   MAP_EVERY EXISTS_TAC [`a + a':real^N`; `b + b':real`] THEN
1089   REWRITE_TAC[SET_RULE
1090    `(s INTER t1) INTER (s INTER t2) = s INTER u <=>
1091     !x. x IN s ==> (x IN t1 /\ x IN t2 <=> x IN u)`] THEN
1092   ASM_SIMP_TAC[DOT_LADD; REAL_LE_ADD2; IN_ELIM_THM] THEN
1093   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1094   REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`)) THEN
1095   ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
1096
1097 let EXPOSED_FACE_OF_INTERS = prove
1098  (`!P s:real^N->bool.
1099         ~(P = {}) /\ (!t. t IN P ==> t exposed_face_of s)
1100         ==> INTERS P exposed_face_of s`,
1101   REPEAT STRIP_TAC THEN
1102   MP_TAC(ISPECL [`s:real^N->bool`; `P:(real^N->bool)->bool`]
1103     INTERS_FACES_FINITE_ALTBOUND) THEN
1104   ANTS_TAC THENL [ASM_MESON_TAC[exposed_face_of]; ALL_TAC] THEN
1105   DISCH_THEN(X_CHOOSE_THEN `Q:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
1106   FIRST_X_ASSUM(MP_TAC o SYM) THEN
1107   ASM_CASES_TAC `Q:(real^N->bool)->bool = {}` THENL
1108    [ASM_SIMP_TAC[INTERS_0] THEN
1109     REWRITE_TAC[SET_RULE `INTERS s = UNIV <=> !t. t IN s ==> t = UNIV`] THEN
1110     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
1111     ASM_MESON_TAC[];
1112     DISCH_THEN SUBST1_TAC THEN
1113     FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN
1114     SUBGOAL_THEN `!t:real^N->bool. t IN Q ==> t exposed_face_of s` MP_TAC THENL
1115      [ASM SET_TAC[]; UNDISCH_TAC `FINITE(Q:(real^N->bool)->bool)`] THEN
1116     SPEC_TAC(`Q:(real^N->bool)->bool`,`Q:(real^N->bool)->bool`) THEN
1117     POP_ASSUM_LIST(K ALL_TAC) THEN
1118     MATCH_MP_TAC FINITE_INDUCT_STRONG THEN REWRITE_TAC[FORALL_IN_INSERT] THEN
1119     MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `P:(real^N->bool)->bool`] THEN
1120     DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
1121     REWRITE_TAC[INTERS_INSERT] THEN
1122     ASM_CASES_TAC `P:(real^N->bool)->bool = {}` THEN
1123     ASM_SIMP_TAC[INTERS_0; INTER_UNIV; EXPOSED_FACE_OF_INTER]]);;
1124
1125 let EXPOSED_FACE_OF_SUMS = prove
1126  (`!s t f:real^N->bool.
1127         convex s /\ convex t /\
1128         f exposed_face_of {x + y | x IN s /\ y IN t}
1129         ==> ?k l. k exposed_face_of s /\ l exposed_face_of t /\
1130                   f = {x + y | x IN k /\ y IN l}`,
1131   REPEAT STRIP_TAC THEN
1132   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXPOSED_FACE_OF]) THEN
1133   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
1134   ASM_CASES_TAC `f:real^N->bool = {}` THENL
1135    [DISCH_TAC THEN REPEAT (EXISTS_TAC `{}:real^N->bool`) THEN
1136     ASM_REWRITE_TAC[EMPTY_EXPOSED_FACE_OF] THEN SET_TAC[];
1137     ALL_TAC] THEN
1138   ASM_CASES_TAC `f = {x + y :real^N | x IN s /\ y IN t}` THENL
1139    [DISCH_TAC THEN
1140     MAP_EVERY EXISTS_TAC [`s:real^N->bool`; `t:real^N->bool`] THEN
1141     ASM_SIMP_TAC[EXPOSED_FACE_OF_REFL];
1142     ALL_TAC] THEN
1143   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
1144   MAP_EVERY X_GEN_TAC [`u:real^N`; `z:real`] THEN
1145   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC; IN_ELIM_THM] THEN
1146   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
1147   DISCH_THEN SUBST_ALL_TAC THEN
1148   RULE_ASSUM_TAC(REWRITE_RULE[GSYM SUBSET_INTER_ABSORPTION]) THEN
1149   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
1150   REWRITE_TAC[EXISTS_IN_GSPEC; IN_INTER] THEN
1151   REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
1152   MAP_EVERY X_GEN_TAC [`a0:real^N`; `b0:real^N`] THEN STRIP_TAC THEN
1153   FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN
1154   EXISTS_TAC `s INTER {x:real^N | u dot x = u dot a0}` THEN
1155   EXISTS_TAC `t INTER {y:real^N | u dot y = u dot b0}` THEN
1156   REPEAT CONJ_TAC THENL
1157    [MATCH_MP_TAC EXPOSED_FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN
1158     ASM_REWRITE_TAC[] THEN X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
1159     FIRST_X_ASSUM(MP_TAC o SPECL [`a:real^N`; `b0:real^N`]) THEN
1160     ASM_REWRITE_TAC[DOT_RADD] THEN REAL_ARITH_TAC;
1161     MATCH_MP_TAC EXPOSED_FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN
1162     ASM_REWRITE_TAC[] THEN X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN
1163     FIRST_X_ASSUM(MP_TAC o SPECL [`a0:real^N`; `b:real^N`]) THEN
1164     ASM_REWRITE_TAC[DOT_RADD] THEN REAL_ARITH_TAC;
1165     ALL_TAC] THEN
1166   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THEN
1167   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC; IN_INTER; IMP_CONJ] THENL
1168    [ALL_TAC; SIMP_TAC[IN_INTER; IN_ELIM_THM; DOT_RADD] THEN MESON_TAC[]] THEN
1169   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN
1170   DISCH_TAC THEN DISCH_TAC THEN REWRITE_TAC[IN_ELIM_THM; DOT_RADD] THEN
1171   DISCH_TAC THEN MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real^N`] THEN
1172   ASM_REWRITE_TAC[] THEN
1173   FIRST_ASSUM(MP_TAC o SPECL  [`a:real^N`; `b0:real^N`]) THEN
1174   FIRST_X_ASSUM(MP_TAC o SPECL  [`a0:real^N`; `b:real^N`]) THEN
1175   ASM_REWRITE_TAC[DOT_RADD] THEN ASM_REAL_ARITH_TAC);;
1176
1177 let EXPOSED_FACE_OF_PARALLEL = prove
1178  (`!t s. t exposed_face_of s <=>
1179          t face_of s /\
1180           ?a b. s SUBSET {x:real^N | a dot x <= b} /\
1181                 t = s INTER {x | a dot x = b} /\
1182                 (~(t = {}) /\ ~(t = s) ==> ~(a = vec 0)) /\
1183                 (!w. w IN affine hull s /\ ~(t = s)
1184                      ==> (w + a) IN affine hull s)`,
1185   REPEAT GEN_TAC THEN REWRITE_TAC[exposed_face_of] THEN
1186   AP_TERM_TAC THEN EQ_TAC THENL
1187    [REWRITE_TAC[LEFT_IMP_EXISTS_THM];
1188     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN SIMP_TAC[]] THEN
1189   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN STRIP_TAC THEN
1190   MP_TAC(ISPECL [`affine hull s:real^N->bool`; `--a:real^N`; `--b:real`]
1191         AFFINE_PARALLEL_SLICE) THEN
1192   SIMP_TAC[AFFINE_AFFINE_HULL; DOT_LNEG; REAL_LE_NEG2; REAL_EQ_NEG2] THEN
1193   DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC) THENL
1194    [MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `&1`] THEN
1195     REWRITE_TAC[DOT_LZERO; REAL_POS; SET_RULE `{x | T} = UNIV`] THEN
1196     SIMP_TAC[SUBSET_UNIV; VECTOR_ADD_RID; REAL_ARITH `~(&0 = &1)`] THEN
1197     REWRITE_TAC[EMPTY_GSPEC] THEN ASM_REWRITE_TAC[INTER_EMPTY] THEN
1198     MATCH_MP_TAC(TAUT `p ==> p /\ ~(~p /\ q)`) THEN
1199     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
1200      `s' INTER t' = {}
1201       ==> s SUBSET s' /\ t SUBSET t' ==> s INTER t = {}`)) THEN
1202     REWRITE_TAC[HULL_SUBSET] THEN SIMP_TAC[SUBSET; IN_ELIM_THM; REAL_LE_REFL];
1203     SUBGOAL_THEN `t:real^N->bool = s` SUBST1_TAC THENL
1204      [FIRST_X_ASSUM SUBST1_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
1205       SUBGOAL_THEN `s SUBSET affine hull (s:real^N->bool)` MP_TAC THENL
1206        [REWRITE_TAC[HULL_SUBSET]; ASM SET_TAC[]];
1207       MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `&0`] THEN
1208       REWRITE_TAC[DOT_LZERO; SET_RULE `{x | T} = UNIV`; REAL_LE_REFL] THEN
1209       SET_TAC[]];
1210     FIRST_X_ASSUM(X_CHOOSE_THEN `a':real^N` MP_TAC) THEN
1211     DISCH_THEN(X_CHOOSE_THEN `b':real` STRIP_ASSUME_TAC) THEN
1212     MAP_EVERY EXISTS_TAC [`--a':real^N`; `--b':real`] THEN
1213     ASM_REWRITE_TAC[DOT_LNEG; REAL_LE_NEG2; REAL_EQ_NEG2] THEN
1214     REPEAT CONJ_TAC THENL
1215      [ONCE_REWRITE_TAC[REAL_ARITH `b <= a <=> ~(a <= b) \/ a = b`] THEN
1216       MATCH_MP_TAC(SET_RULE
1217        `!s'. s SUBSET s' /\
1218             s SUBSET (UNIV DIFF (s' INTER {x | P x})) UNION
1219                      (s' INTER {x | Q x})
1220             ==> s SUBSET {x | ~P x \/ Q x}`) THEN
1221       EXISTS_TAC `affine hull s:real^N->bool` THEN
1222       ASM_REWRITE_TAC[HULL_SUBSET] THEN
1223       MATCH_MP_TAC(SET_RULE
1224        `s SUBSET s' /\ s SUBSET (UNIV DIFF {x | P x}) UNION {x | Q x}
1225         ==> s SUBSET (UNIV DIFF (s' INTER {x | P x})) UNION
1226                      (s' INTER {x | Q x})`) THEN
1227       REWRITE_TAC[HULL_SUBSET] THEN MATCH_MP_TAC SUBSET_TRANS THEN
1228       EXISTS_TAC `{x:real^N | a dot x <= b}` THEN ASM_REWRITE_TAC[] THEN
1229       REWRITE_TAC[SUBSET; IN_DIFF; IN_UNIV; IN_UNION; IN_ELIM_THM] THEN
1230       REAL_ARITH_TAC;
1231       FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
1232        `s' INTER a = s' INTER b
1233         ==> s SUBSET s' ==> s INTER b = s INTER a`)) THEN
1234       REWRITE_TAC[HULL_SUBSET];
1235       ASM_REWRITE_TAC[VECTOR_NEG_EQ_0];
1236       ONCE_REWRITE_TAC[VECTOR_ARITH
1237        `w + --a:real^N = w + &1 % (w - (w + a))`] THEN
1238       ASM_SIMP_TAC[IN_AFFINE_ADD_MUL_DIFF; AFFINE_AFFINE_HULL]]]);;
1239
1240 (* ------------------------------------------------------------------------- *)
1241 (* Extreme points of a set, which are its singleton faces.                   *)
1242 (* ------------------------------------------------------------------------- *)
1243
1244 parse_as_infix("extreme_point_of",(12,"right"));;
1245
1246 let extreme_point_of = new_definition
1247  `x extreme_point_of s <=>
1248     x IN s /\ !a b. a IN s /\ b IN s ==> ~(x IN segment(a,b))`;;
1249
1250 let EXTREME_POINT_OF_STILLCONVEX = prove
1251  (`!s x:real^N.
1252         convex s ==> (x extreme_point_of s <=> x IN s /\ convex(s DELETE x))`,
1253   REWRITE_TAC[CONVEX_CONTAINS_SEGMENT; extreme_point_of; open_segment] THEN
1254   REWRITE_TAC[IN_DIFF; IN_DELETE; IN_INSERT; NOT_IN_EMPTY; SUBSET_DELETE] THEN
1255   SET_TAC[]);;
1256
1257 let FACE_OF_SING = prove
1258  (`!x s. {x} face_of s <=> x extreme_point_of s`,
1259   SIMP_TAC[face_of; extreme_point_of; SING_SUBSET; CONVEX_SING; IN_SING] THEN
1260   MESON_TAC[SEGMENT_REFL; NOT_IN_EMPTY]);;
1261
1262 let EXTREME_POINT_NOT_IN_RELATIVE_INTERIOR = prove
1263  (`!s x:real^N.
1264         x extreme_point_of s /\ ~(s = {x})
1265         ==> ~(x IN relative_interior s)`,
1266   REPEAT GEN_TAC THEN CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN
1267   REWRITE_TAC[GSYM FACE_OF_SING] THEN
1268   DISCH_THEN(MP_TAC o MATCH_MP FACE_OF_DISJOINT_RELATIVE_INTERIOR) THEN
1269   SET_TAC[]);;
1270
1271 let EXTREME_POINT_NOT_IN_INTERIOR = prove
1272  (`!s x:real^N. x extreme_point_of s ==> ~(x IN interior s)`,
1273   REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_CASES_TAC `s = {x:real^N}` THEN
1274   ASM_SIMP_TAC[EMPTY_INTERIOR_FINITE; FINITE_SING; NOT_IN_EMPTY] THEN
1275   DISCH_THEN(MP_TAC o MATCH_MP (REWRITE_RULE[SUBSET]
1276     INTERIOR_SUBSET_RELATIVE_INTERIOR)) THEN
1277   ASM_SIMP_TAC[EXTREME_POINT_NOT_IN_RELATIVE_INTERIOR]);;
1278
1279 let EXTREME_POINT_OF_FACE = prove
1280  (`!f s v. f face_of s
1281            ==> (v extreme_point_of f <=> v extreme_point_of s /\ v IN f)`,
1282   REWRITE_TAC[GSYM FACE_OF_SING; GSYM SING_SUBSET; FACE_OF_FACE]);;
1283
1284 let EXTREME_POINT_OF_MIDPOINT = prove
1285  (`!s x:real^N.
1286         convex s
1287         ==> (x extreme_point_of s <=>
1288              x IN s /\
1289              !a b. a IN s /\ b IN s /\ x = midpoint(a,b) ==> x = a /\ x = b)`,
1290   REPEAT STRIP_TAC THEN REWRITE_TAC[extreme_point_of] THEN
1291   AP_TERM_TAC THEN EQ_TAC THEN
1292   DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN
1293   DISCH_TAC THENL
1294    [FIRST_X_ASSUM(MP_TAC o SPECL [`a:real^N`; `b:real^N`]) THEN
1295     ASM_SIMP_TAC[MIDPOINT_IN_SEGMENT; MIDPOINT_REFL];
1296     ALL_TAC] THEN
1297   REWRITE_TAC[IN_SEGMENT] THEN DISCH_THEN(CONJUNCTS_THEN2
1298     ASSUME_TAC (X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC)) THEN
1299   ABBREV_TAC `d = min (&1 - u) u` THEN
1300   FIRST_X_ASSUM(MP_TAC o SPECL
1301    [`x - d / &2 % (b - a):real^N`; `x + d / &2 % (b - a):real^N`]) THEN
1302   REWRITE_TAC[NOT_IMP] THEN REPEAT CONJ_TAC THENL
1303    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
1304     ASM_REWRITE_TAC[VECTOR_ARITH
1305      `((&1 - u) % a + u % b) - d / &2 % (b - a):real^N =
1306       (&1 - (u - d / &2)) % a + (u - d / &2) % b`] THEN
1307     DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
1308     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONVEX_ALT]) THEN
1309     ASM_REWRITE_TAC[VECTOR_ARITH
1310      `((&1 - u) % a + u % b) + d / &2 % (b - a):real^N =
1311       (&1 - (u + d / &2)) % a + (u + d / &2) % b`] THEN
1312     DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC;
1313     REWRITE_TAC[midpoint] THEN VECTOR_ARITH_TAC;
1314     REWRITE_TAC[VECTOR_ARITH `x:real^N = x - d <=> d = vec 0`;
1315                 VECTOR_ARITH `x:real^N = x + d <=> d = vec 0`] THEN
1316     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN ASM_REAL_ARITH_TAC]);;
1317
1318 let EXTREME_POINT_OF_CONVEX_HULL = prove
1319  (`!x:real^N s. x extreme_point_of (convex hull s) ==> x IN s`,
1320   REPEAT GEN_TAC THEN
1321   SIMP_TAC[EXTREME_POINT_OF_STILLCONVEX; CONVEX_CONVEX_HULL] THEN
1322   MP_TAC(ISPECL [`convex:(real^N->bool)->bool`; `s:real^N->bool`;
1323                  `(convex hull s) DELETE (x:real^N)`] HULL_MINIMAL) THEN
1324   MP_TAC(ISPECL [`convex:(real^N->bool)->bool`; `s:real^N->bool`]
1325         HULL_SUBSET) THEN
1326   ASM SET_TAC[]);;
1327
1328 let EXTREME_POINTS_OF_CONVEX_HULL = prove
1329  (`!s. {x | x extreme_point_of (convex hull s)} SUBSET s`,
1330   REWRITE_TAC[SUBSET; IN_ELIM_THM; EXTREME_POINT_OF_CONVEX_HULL]);;
1331
1332 let EXTREME_POINT_OF_EMPTY = prove
1333  (`!x. ~(x extreme_point_of {})`,
1334   REWRITE_TAC[extreme_point_of; NOT_IN_EMPTY]);;
1335
1336 let EXTREME_POINT_OF_SING = prove
1337  (`!a x. x extreme_point_of {a} <=> x = a`,
1338   REWRITE_TAC[extreme_point_of; IN_SING] THEN
1339   MESON_TAC[SEGMENT_REFL; NOT_IN_EMPTY]);;
1340
1341 let EXTREME_POINT_OF_TRANSLATION_EQ = prove
1342  (`!a:real^N x s.
1343            (a + x) extreme_point_of (IMAGE (\x. a + x) s) <=>
1344            x extreme_point_of s`,
1345   REWRITE_TAC[extreme_point_of] THEN GEOM_TRANSLATE_TAC[]);;
1346
1347 add_translation_invariants [EXTREME_POINT_OF_TRANSLATION_EQ];;
1348
1349 let EXTREME_POINT_OF_LINEAR_IMAGE = prove
1350  (`!f:real^M->real^N.
1351       linear f /\ (!x y. f x = f y ==> x = y)
1352       ==> ((f x) extreme_point_of (IMAGE f s) <=> x extreme_point_of s)`,
1353   REWRITE_TAC[GSYM FACE_OF_SING] THEN GEOM_TRANSFORM_TAC[]);;
1354
1355 add_linear_invariants [EXTREME_POINT_OF_LINEAR_IMAGE];;
1356
1357 let EXTREME_POINTS_OF_TRANSLATION = prove
1358  (`!a s. {x:real^N | x extreme_point_of (IMAGE (\x. a + x) s)} =
1359          IMAGE (\x. a + x) {x | x extreme_point_of s}`,
1360   REPEAT GEN_TAC THEN CONV_TAC SYM_CONV THEN
1361   MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
1362   REWRITE_TAC[VECTOR_ARITH `a + x:real^N = y <=> x = y - a`; EXISTS_REFL] THEN
1363   REWRITE_TAC[IN_ELIM_THM; EXTREME_POINT_OF_TRANSLATION_EQ]);;
1364
1365 let EXTREME_POINT_OF_INTER = prove
1366  (`!x s t. x extreme_point_of s /\ x extreme_point_of t
1367            ==> x extreme_point_of (s INTER t)`,
1368   REWRITE_TAC[extreme_point_of; IN_INTER] THEN MESON_TAC[]);;
1369
1370 let EXTREME_POINTS_OF_LINEAR_IMAGE = prove
1371  (`!f:real^M->real^N.
1372         linear f /\ (!x y. f x = f y ==> x = y)
1373         ==> {y | y extreme_point_of (IMAGE f s)} =
1374             IMAGE f {x | x extreme_point_of s}`,
1375
1376   REPEAT GEN_TAC THEN DISCH_TAC THEN
1377   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_SEGMENT_LINEAR_IMAGE) THEN
1378   MATCH_MP_TAC SUBSET_ANTISYM THEN
1379   REWRITE_TAC[FORALL_IN_IMAGE; FORALL_IN_GSPEC; SUBSET;
1380               extreme_point_of; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
1381   ASM_SIMP_TAC[FUN_IN_IMAGE; IN_ELIM_THM; IMP_IMP; GSYM CONJ_ASSOC] THEN
1382   ASM SET_TAC[]);;
1383
1384 let EXTREME_POINT_OF_INTER_SUPPORTING_HYPERPLANE_LE = prove
1385  (`!s a b c. (!x. x IN s ==> a dot x <= b) /\
1386              s INTER {x | a dot x = b} = {c}
1387              ==> c extreme_point_of s`,
1388   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM FACE_OF_SING] THEN
1389   FIRST_ASSUM(SUBST1_TAC o SYM) THEN
1390   MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE_STRONG THEN
1391   ASM_REWRITE_TAC[CONVEX_SING]);;
1392
1393 let EXTREME_POINT_OF_INTER_SUPPORTING_HYPERPLANE_GE = prove
1394  (`!s a b c. (!x. x IN s ==> a dot x >= b) /\
1395              s INTER {x | a dot x = b} = {c}
1396              ==> c extreme_point_of s`,
1397   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM FACE_OF_SING] THEN
1398   FIRST_ASSUM(SUBST1_TAC o SYM) THEN
1399   MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE_STRONG THEN
1400   ASM_REWRITE_TAC[CONVEX_SING]);;
1401
1402 let EXPOSED_POINT_OF_INTER_SUPPORTING_HYPERPLANE_LE = prove
1403  (`!s a b c:real^N.
1404         (!x. x IN s ==> a dot x <= b) /\
1405         s INTER {x | a dot x = b} = {c}
1406         ==> {c} exposed_face_of s`,
1407   REPEAT STRIP_TAC THEN REWRITE_TAC[exposed_face_of] THEN CONJ_TAC THENL
1408    [REWRITE_TAC[FACE_OF_SING] THEN
1409     MATCH_MP_TAC EXTREME_POINT_OF_INTER_SUPPORTING_HYPERPLANE_LE;
1410     ALL_TAC] THEN
1411   MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real`] THEN ASM SET_TAC[]);;
1412
1413 let EXPOSED_POINT_OF_INTER_SUPPORTING_HYPERPLANE_GE = prove
1414  (`!s a b c:real^N.
1415         (!x. x IN s ==> a dot x >= b) /\
1416         s INTER {x | a dot x = b} = {c}
1417         ==> {c} exposed_face_of s`,
1418   REWRITE_TAC[real_ge] THEN REPEAT STRIP_TAC THEN
1419   MP_TAC(ISPECL [`s:real^N->bool`; `--a:real^N`; `--b:real`; `c:real^N`]
1420     EXPOSED_POINT_OF_INTER_SUPPORTING_HYPERPLANE_LE) THEN
1421   ASM_REWRITE_TAC[DOT_LNEG; REAL_EQ_NEG2; REAL_LE_NEG2]);;
1422
1423 let EXPOSED_POINT_OF_FURTHEST_POINT = prove
1424  (`!s a b:real^N.
1425         b IN s /\ (!x. x IN s ==> dist(a,x) <= dist(a,b))
1426         ==> {b} exposed_face_of s`,
1427   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN
1428   REWRITE_TAC[DIST_0; NORM_LE] THEN REPEAT STRIP_TAC THEN
1429   MATCH_MP_TAC EXPOSED_POINT_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN
1430   MAP_EVERY EXISTS_TAC [`b:real^N`; `(b:real^N) dot b`] THEN CONJ_TAC THENL
1431    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1432     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
1433     ASM_REWRITE_TAC[];
1434     MATCH_MP_TAC SUBSET_ANTISYM THEN
1435     ASM_REWRITE_TAC[IN_INTER; SING_SUBSET; IN_ELIM_THM] THEN
1436     REWRITE_TAC[SUBSET; IN_SING; IN_INTER; IN_ELIM_THM] THEN
1437     X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
1438     CONV_TAC SYM_CONV THEN ASM_REWRITE_TAC[VECTOR_EQ] THEN
1439     ASM_SIMP_TAC[GSYM REAL_LE_ANTISYM] THEN
1440     UNDISCH_TAC `(b:real^N) dot x = b dot b`] THEN
1441   MP_TAC(ISPEC `b - x:real^N` DOT_POS_LE) THEN
1442   REWRITE_TAC[DOT_LSUB; DOT_RSUB; DOT_SYM] THEN REAL_ARITH_TAC);;
1443
1444 let COLLINEAR_EXTREME_POINTS = prove
1445  (`!s. collinear s
1446        ==> FINITE {x:real^N | x extreme_point_of s} /\
1447            CARD {x | x extreme_point_of s} <= 2`,
1448   REWRITE_TAC[GSYM NOT_LT; TAUT `a /\ ~b <=> ~(a ==> b)`] THEN
1449   REWRITE_TAC[ARITH_RULE `2 < n <=> 3 <= n`] THEN REPEAT STRIP_TAC THEN
1450   FIRST_ASSUM(MP_TAC o MATCH_MP CHOOSE_SUBSET_STRONG) THEN
1451   CONV_TAC(ONCE_DEPTH_CONV HAS_SIZE_CONV) THEN
1452   REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN REWRITE_TAC[NOT_EXISTS_THM] THEN
1453   MAP_EVERY X_GEN_TAC
1454    [`t:real^N->bool`; `a:real^N`; `b:real^N`; `c:real^N`] THEN
1455   REPEAT STRIP_TAC THEN FIRST_X_ASSUM SUBST_ALL_TAC THEN
1456   SUBGOAL_THEN
1457    `(a:real^N) extreme_point_of s /\
1458     b extreme_point_of s /\ c extreme_point_of s`
1459   STRIP_ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
1460   SUBGOAL_THEN `(a:real^N) IN s /\ b IN s /\ c IN s` STRIP_ASSUME_TAC THENL
1461    [ASM_MESON_TAC[extreme_point_of]; ALL_TAC] THEN
1462   SUBGOAL_THEN `collinear {a:real^N,b,c}` MP_TAC THENL
1463    [MATCH_MP_TAC COLLINEAR_SUBSET THEN EXISTS_TAC `s:real^N->bool` THEN
1464     ASM SET_TAC[];
1465     REWRITE_TAC[COLLINEAR_BETWEEN_CASES; BETWEEN_IN_SEGMENT] THEN
1466     ASM_SIMP_TAC[SEGMENT_CLOSED_OPEN; IN_INSERT; NOT_IN_EMPTY; IN_UNION] THEN
1467     ASM_MESON_TAC[extreme_point_of]]);;
1468
1469 let EXTREME_POINT_OF_CONIC = prove
1470  (`!s x:real^N.
1471         conic s /\ x extreme_point_of s ==> x = vec 0`,
1472   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM FACE_OF_SING] THEN
1473   DISCH_THEN(MP_TAC o MATCH_MP FACE_OF_CONIC) THEN
1474   SIMP_TAC[conic; IN_SING; VECTOR_MUL_EQ_0; REAL_SUB_0; VECTOR_ARITH
1475     `c % x:real^N = x <=> (c - &1) % x = vec 0`] THEN
1476   MESON_TAC[REAL_ARITH `&0 <= &0 /\ ~(&1 = &0)`]);;
1477
1478 let EXTREME_POINT_OF_CONVEX_HULL_INSERT = prove
1479  (`!s a:real^N.
1480         FINITE s /\ ~(a IN convex hull s)
1481         ==> a extreme_point_of (convex hull (a INSERT s))`,
1482   REPEAT GEN_TAC THEN
1483   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_SIMP_TAC[HULL_INC] THEN
1484   STRIP_TAC THEN MP_TAC(ISPECL [`{a:real^N}`; `(a:real^N) INSERT s`]
1485     FACE_OF_CONVEX_HULLS) THEN
1486   ASM_REWRITE_TAC[FINITE_INSERT; AFFINE_HULL_SING; CONVEX_HULL_SING] THEN
1487   REWRITE_TAC[FACE_OF_SING] THEN DISCH_THEN MATCH_MP_TAC THEN
1488   ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> a INSERT s DIFF {a} = s`] THEN
1489   ASM SET_TAC[]);;
1490
1491 (* ------------------------------------------------------------------------- *)
1492 (* Facets.                                                                   *)
1493 (* ------------------------------------------------------------------------- *)
1494
1495 parse_as_infix("facet_of",(12, "right"));;
1496
1497 let facet_of = new_definition
1498  `f facet_of s <=> f face_of s /\ ~(f = {}) /\ aff_dim f = aff_dim s - &1`;;
1499
1500 let FACET_OF_EMPTY = prove
1501  (`!s. ~(s facet_of {})`,
1502   REWRITE_TAC[facet_of; FACE_OF_EMPTY] THEN CONV_TAC TAUT);;
1503
1504 let FACET_OF_REFL = prove
1505  (`!s. ~(s facet_of s)`,
1506   REWRITE_TAC[facet_of; INT_ARITH `~(x:int = x - &1)`]);;
1507
1508 let FACET_OF_IMP_FACE_OF = prove
1509  (`!f s. f facet_of s ==> f face_of s`,
1510   SIMP_TAC[facet_of]);;
1511
1512 let FACET_OF_IMP_SUBSET = prove
1513  (`!f s. f facet_of s ==> f SUBSET s`,
1514   SIMP_TAC[FACET_OF_IMP_FACE_OF; FACE_OF_IMP_SUBSET]);;
1515
1516 let FACET_OF_IMP_PROPER = prove
1517  (`!f s. f facet_of s ==> ~(f = {}) /\ ~(f = s)`,
1518   REWRITE_TAC[facet_of] THEN MESON_TAC[INT_ARITH `~(x - &1:int = x)`]);;
1519
1520 let FACET_OF_TRANSLATION_EQ = prove
1521  (`!a:real^N f s.
1522         (IMAGE (\x. a + x) f) facet_of (IMAGE (\x. a + x) s) <=> f facet_of s`,
1523   REWRITE_TAC[facet_of] THEN GEOM_TRANSLATE_TAC[]);;
1524
1525 add_translation_invariants [FACET_OF_TRANSLATION_EQ];;
1526
1527 let FACET_OF_LINEAR_IMAGE = prove
1528  (`!f:real^M->real^N c s.
1529       linear f /\ (!x y. f x = f y ==> x = y)
1530       ==> ((IMAGE f c) facet_of (IMAGE f s) <=> c facet_of s)`,
1531   REWRITE_TAC[facet_of] THEN GEOM_TRANSFORM_TAC[]);;
1532
1533 add_linear_invariants [FACET_OF_LINEAR_IMAGE];;
1534
1535 let HYPERPLANE_FACET_OF_HALFSPACE_LE = prove
1536  (`!a:real^N b.
1537         ~(a = vec 0) ==> {x | a dot x = b} facet_of {x | a dot x <= b}`,
1538   SIMP_TAC[facet_of; HYPERPLANE_FACE_OF_HALFSPACE_LE; HYPERPLANE_EQ_EMPTY;
1539            AFF_DIM_HYPERPLANE; AFF_DIM_HALFSPACE_LE]);;
1540
1541 let HYPERPLANE_FACET_OF_HALFSPACE_GE = prove
1542  (`!a:real^N b.
1543         ~(a = vec 0) ==> {x | a dot x = b} facet_of {x | a dot x >= b}`,
1544   SIMP_TAC[facet_of; HYPERPLANE_FACE_OF_HALFSPACE_GE; HYPERPLANE_EQ_EMPTY;
1545            AFF_DIM_HYPERPLANE; AFF_DIM_HALFSPACE_GE]);;
1546
1547 let FACET_OF_HALFSPACE_LE = prove
1548  (`!f a:real^N b.
1549         f facet_of {x | a dot x <= b} <=>
1550         ~(a = vec 0) /\ f = {x | a dot x = b}`,
1551   REPEAT GEN_TAC THEN
1552   EQ_TAC THEN ASM_SIMP_TAC[HYPERPLANE_FACET_OF_HALFSPACE_LE] THEN
1553   SIMP_TAC[AFF_DIM_HALFSPACE_LE; facet_of; FACE_OF_HALFSPACE_LE] THEN
1554   REWRITE_TAC[TAUT `(p \/ q) /\ ~p /\ r <=> (~p /\ q) /\ r`] THEN
1555   ASM_CASES_TAC `a:real^N = vec 0` THENL
1556    [ASM_REWRITE_TAC[DOT_LZERO; SET_RULE
1557      `{x | p} = if p then UNIV else {}`] THEN
1558     REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[TAUT `~(~p /\ p)`]) THEN
1559     TRY ASM_REAL_ARITH_TAC THEN
1560     DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
1561     ASM_REWRITE_TAC[AFF_DIM_UNIV] THEN TRY INT_ARITH_TAC THEN ASM SET_TAC[];
1562     DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
1563     ASM_REWRITE_TAC[AFF_DIM_HALFSPACE_LE] THEN INT_ARITH_TAC]);;
1564
1565 let FACET_OF_HALFSPACE_GE = prove
1566  (`!f a:real^N b.
1567         f facet_of {x | a dot x >= b} <=>
1568         ~(a = vec 0) /\ f = {x | a dot x = b}`,
1569   REPEAT GEN_TAC THEN
1570   MP_TAC(ISPECL [`f:real^N->bool`; `--a:real^N`; `--b:real`]
1571         FACET_OF_HALFSPACE_LE) THEN
1572   SIMP_TAC[DOT_LNEG; REAL_LE_NEG2; REAL_EQ_NEG2; VECTOR_NEG_EQ_0; real_ge]);;
1573
1574 (* ------------------------------------------------------------------------- *)
1575 (* Edges, i.e. faces of affine dimension 1.                                  *)
1576 (* ------------------------------------------------------------------------- *)
1577
1578 parse_as_infix("edge_of",(12, "right"));;
1579
1580 let edge_of = new_definition
1581  `e edge_of s <=> e face_of s /\ aff_dim e = &1`;;
1582
1583 let EDGE_OF_TRANSLATION_EQ = prove
1584  (`!a:real^N f s.
1585         (IMAGE (\x. a + x) f) edge_of (IMAGE (\x. a + x) s) <=> f edge_of s`,
1586   REWRITE_TAC[edge_of] THEN GEOM_TRANSLATE_TAC[]);;
1587
1588 add_translation_invariants [EDGE_OF_TRANSLATION_EQ];;
1589
1590 let EDGE_OF_LINEAR_IMAGE = prove
1591  (`!f:real^M->real^N c s.
1592       linear f /\ (!x y. f x = f y ==> x = y)
1593       ==> ((IMAGE f c) edge_of (IMAGE f s) <=> c edge_of s)`,
1594   REWRITE_TAC[edge_of] THEN GEOM_TRANSFORM_TAC[]);;
1595
1596 add_linear_invariants [EDGE_OF_LINEAR_IMAGE];;
1597
1598 let EDGE_OF_IMP_SUBSET = prove
1599  (`!s t. s edge_of t ==> s SUBSET t`,
1600   SIMP_TAC[edge_of; face_of]);;
1601
1602 (* ------------------------------------------------------------------------- *)
1603 (* Existence of extreme points.                                              *)
1604 (* ------------------------------------------------------------------------- *)
1605
1606 let DIFFERENT_NORM_3_COLLINEAR_POINTS = prove
1607  (`!a b x:real^N.
1608      ~(x IN segment(a,b) /\ norm(a) = norm(b) /\ norm(x) = norm(b))`,
1609   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = b` THEN
1610   ASM_SIMP_TAC[SEGMENT_REFL; NOT_IN_EMPTY; OPEN_SEGMENT_ALT] THEN
1611   REWRITE_TAC[IN_ELIM_THM] THEN DISCH_THEN
1612    (CONJUNCTS_THEN2 (X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) MP_TAC) THEN
1613   ASM_REWRITE_TAC[NORM_EQ] THEN REWRITE_TAC[VECTOR_ARITH
1614    `(x + y:real^N) dot (x + y) = x dot x + &2 * x dot y + y dot y`] THEN
1615   REWRITE_TAC[DOT_LMUL; DOT_RMUL] THEN
1616   DISCH_THEN(CONJUNCTS_THEN2 (ASSUME_TAC o SYM) MP_TAC) THEN
1617   UNDISCH_TAC `~(a:real^N = b)` THEN
1618   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM VECTOR_SUB_EQ] THEN
1619   REWRITE_TAC[GSYM DOT_EQ_0; VECTOR_ARITH
1620    `(a - b:real^N) dot (a - b) = a dot a + b dot b - &2 * a dot b`] THEN
1621   ASM_REWRITE_TAC[REAL_RING `a + a - &2 * ab = &0 <=> ab = a`] THEN
1622   SIMP_TAC[REAL_RING
1623    `(&1 - u) * (&1 - u) * a + &2 * (&1 - u) * u * x + u * u * a = a <=>
1624     x = a \/ u = &0 \/ u = &1`] THEN
1625   ASM_REAL_ARITH_TAC);;
1626
1627 let EXTREME_POINT_EXISTS_CONVEX = prove
1628  (`!s:real^N->bool.
1629         compact s /\ convex s /\ ~(s = {}) ==> ?x. x extreme_point_of s`,
1630   REPEAT STRIP_TAC THEN
1631   MP_TAC(ISPECL [`s:real^N->bool`; `vec 0:real^N`] DISTANCE_ATTAINS_SUP) THEN
1632   ASM_REWRITE_TAC[DIST_0; extreme_point_of] THEN
1633   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN
1634   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1635   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN
1636   REPEAT STRIP_TAC THEN
1637   MP_TAC(ISPECL [`a:real^N`; `b:real^N`; `x:real^N`]
1638      DIFFERENT_NORM_3_COLLINEAR_POINTS) THEN
1639   ASM_REWRITE_TAC[] THEN
1640   MATCH_MP_TAC(REAL_ARITH
1641    `a <= x /\ b <= x /\ (a < x ==> x < x) /\ (b < x ==> x < x)
1642     ==> a = b /\ x = b`) THEN
1643   ASM_SIMP_TAC[] THEN
1644   UNDISCH_TAC `(x:real^N) IN segment(a,b)` THEN
1645   ASM_CASES_TAC `a:real^N = b` THEN
1646   ASM_REWRITE_TAC[SEGMENT_REFL; NOT_IN_EMPTY] THEN
1647   ASM_SIMP_TAC[OPEN_SEGMENT_ALT; IN_ELIM_THM] THEN
1648   DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
1649   CONJ_TAC THEN DISCH_TAC THEN
1650   FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [th]) THEN
1651   MATCH_MP_TAC NORM_TRIANGLE_LT THEN REWRITE_TAC[NORM_MUL] THEN
1652   ASM_SIMP_TAC[REAL_ARITH
1653    `&0 < u /\ u < &1 ==> abs u = u /\ abs(&1 - u) = &1 - u`] THEN
1654   SUBST1_TAC(REAL_RING `norm(x:real^N) = (&1 - u) * norm x + u * norm x`) THENL
1655    [MATCH_MP_TAC REAL_LTE_ADD2; MATCH_MP_TAC REAL_LET_ADD2] THEN
1656   ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_LT_LMUL_EQ; REAL_SUB_LT]);;
1657
1658 (* ------------------------------------------------------------------------- *)
1659 (* Krein-Milman, the weaker form as in more general spaces first.            *)
1660 (* ------------------------------------------------------------------------- *)
1661
1662 let KREIN_MILMAN = prove
1663  (`!s:real^N->bool.
1664         convex s /\ compact s
1665         ==> s = closure(convex hull {x | x extreme_point_of s})`,
1666   GEN_TAC THEN
1667   ASM_CASES_TAC `s:real^N->bool = {}` THENL
1668    [ASM_REWRITE_TAC[extreme_point_of; NOT_IN_EMPTY; EMPTY_GSPEC] THEN
1669     REWRITE_TAC[CONVEX_HULL_EMPTY; CLOSURE_EMPTY];
1670     ALL_TAC] THEN
1671   STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
1672    [ALL_TAC;
1673     MATCH_MP_TAC CLOSURE_MINIMAL THEN ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN
1674     MATCH_MP_TAC HULL_MINIMAL THEN
1675     ASM_SIMP_TAC[SUBSET; IN_ELIM_THM; extreme_point_of]] THEN
1676   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
1677   X_GEN_TAC `u:real^N` THEN DISCH_TAC THEN
1678   MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
1679   MP_TAC(ISPECL [`closure(convex hull {x:real^N | x extreme_point_of s})`;
1680                  `u:real^N`] SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
1681   ASM_SIMP_TAC[CONVEX_CLOSURE; CLOSED_CLOSURE; CONVEX_CONVEX_HULL] THEN
1682   REWRITE_TAC[NOT_EXISTS_THM; TAUT `~(a /\ b) <=> a ==> ~b`] THEN
1683   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`] THEN REPEAT STRIP_TAC THEN
1684   MP_TAC(ISPECL [`\x:real^N. a dot x`; `s:real^N->bool`]
1685     CONTINUOUS_ATTAINS_INF) THEN
1686   ASM_REWRITE_TAC[CONTINUOUS_ON_LIFT_DOT] THEN
1687   DISCH_THEN(X_CHOOSE_THEN `m:real^N` STRIP_ASSUME_TAC) THEN
1688   ABBREV_TAC `t = {x:real^N | x IN s /\ a dot x = a dot m}` THEN
1689   SUBGOAL_THEN `?x:real^N. x extreme_point_of t` (X_CHOOSE_TAC `v:real^N`)
1690   THENL
1691    [MATCH_MP_TAC EXTREME_POINT_EXISTS_CONVEX THEN
1692     EXPAND_TAC "t" THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
1693     REWRITE_TAC[SET_RULE `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
1694     ASM_SIMP_TAC[CONVEX_INTER; CONVEX_HYPERPLANE; COMPACT_INTER_CLOSED;
1695                  CLOSED_HYPERPLANE] THEN
1696     ASM SET_TAC[];
1697     ALL_TAC] THEN
1698   SUBGOAL_THEN `(v:real^N) extreme_point_of s` ASSUME_TAC THENL
1699    [REWRITE_TAC[GSYM FACE_OF_SING] THEN MATCH_MP_TAC FACE_OF_TRANS THEN
1700     EXISTS_TAC `t:real^N->bool` THEN ASM_SIMP_TAC[FACE_OF_SING] THEN
1701     EXPAND_TAC "t" THEN
1702     REWRITE_TAC[SET_RULE `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
1703     MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE THEN
1704     ASM_SIMP_TAC[real_ge];
1705     SUBGOAL_THEN `(a:real^N) dot v > b` MP_TAC THENL
1706      [FIRST_X_ASSUM MATCH_MP_TAC THEN
1707       MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN
1708       MATCH_MP_TAC HULL_INC THEN ASM_REWRITE_TAC[IN_ELIM_THM];
1709       ALL_TAC] THEN
1710     REWRITE_TAC[real_gt; REAL_NOT_LT] THEN
1711     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `(a:real^N) dot u` THEN
1712     ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN
1713     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `(a:real^N) dot m` THEN
1714     ASM_SIMP_TAC[] THEN
1715     UNDISCH_TAC `(v:real^N) extreme_point_of t` THEN EXPAND_TAC "t" THEN
1716     SIMP_TAC[extreme_point_of; IN_ELIM_THM; REAL_LE_REFL]]);;
1717
1718 (* ------------------------------------------------------------------------- *)
1719 (* Now the sharper form.                                                     *)
1720 (* ------------------------------------------------------------------------- *)
1721
1722 let KREIN_MILMAN_MINKOWSKI = prove
1723  (`!s:real^N->bool.
1724         convex s /\ compact s
1725         ==> s = convex hull {x | x extreme_point_of s}`,
1726   SUBGOAL_THEN
1727    `!s:real^N->bool.
1728         convex s /\ compact s /\ (vec 0) IN s
1729         ==> (vec 0) IN convex hull {x | x extreme_point_of s}`
1730   ASSUME_TAC THENL
1731    [GEN_TAC THEN WF_INDUCT_TAC `dim(s:real^N->bool)` THEN STRIP_TAC THEN
1732     ASM_CASES_TAC `(vec 0:real^N) IN relative_interior s` THENL
1733      [MP_TAC(ISPEC `s:real^N->bool` KREIN_MILMAN) THEN
1734       ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
1735       UNDISCH_TAC `(vec 0:real^N) IN relative_interior s` THEN
1736       FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC
1737        (LAND_CONV o RAND_CONV o RAND_CONV) [th]) THEN
1738       SIMP_TAC[CONVEX_RELATIVE_INTERIOR_CLOSURE; CONVEX_CONVEX_HULL] THEN
1739       MESON_TAC[RELATIVE_INTERIOR_SUBSET; SUBSET];
1740       ALL_TAC] THEN
1741     SUBGOAL_THEN `~(relative_interior(s:real^N->bool) = {})` ASSUME_TAC THENL
1742      [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY] THEN ASM SET_TAC[];
1743       ALL_TAC] THEN
1744     MP_TAC(ISPECL [`s:real^N->bool`; `vec 0:real^N`]
1745           SUPPORTING_HYPERPLANE_RELATIVE_BOUNDARY) THEN
1746     ASM_REWRITE_TAC[DOT_RZERO] THEN
1747     DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
1748     MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`; `&0`]
1749       FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE) THEN
1750     ASM_REWRITE_TAC[real_ge] THEN DISCH_TAC THEN
1751     SUBGOAL_THEN
1752      `(vec 0:real^N) IN convex hull
1753           {x | x extreme_point_of (s INTER {x | a dot x = &0})}`
1754     MP_TAC THENL
1755      [ALL_TAC;
1756       MATCH_MP_TAC(SET_RULE `s SUBSET t ==> x IN s ==> x IN t`) THEN
1757       MATCH_MP_TAC HULL_MONO THEN REWRITE_TAC[SUBSET] THEN
1758       GEN_TAC THEN REWRITE_TAC[IN_ELIM_THM; GSYM FACE_OF_SING] THEN
1759       ASM_MESON_TAC[FACE_OF_TRANS]] THEN
1760     RULE_ASSUM_TAC(REWRITE_RULE[IMP_IMP]) THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
1761     ASM_SIMP_TAC[CONVEX_INTER; CONVEX_HYPERPLANE; COMPACT_INTER_CLOSED;
1762                  CLOSED_HYPERPLANE; IN_INTER; IN_ELIM_THM; DOT_RZERO] THEN
1763     REWRITE_TAC[GSYM NOT_LE] THEN DISCH_TAC THEN
1764     MP_TAC(ISPECL
1765      [`s INTER {x:real^N | a dot x = &0}`; `s:real^N->bool`]
1766           DIM_EQ_SPAN) THEN
1767     ASM_REWRITE_TAC[INTER_SUBSET; EXTENSION; NOT_FORALL_THM] THEN
1768     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
1769     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `c:real^N` THEN DISCH_TAC THEN
1770     MATCH_MP_TAC(TAUT `b /\ ~a ==> ~(a <=> b)`) THEN CONJ_TAC THENL
1771      [ASM_MESON_TAC[SUBSET; SPAN_INC; RELATIVE_INTERIOR_SUBSET]; ALL_TAC] THEN
1772     SUBGOAL_THEN
1773      `!x:real^N. x IN span (s INTER {x | a dot x = &0}) ==> a dot x = &0`
1774      (fun th -> ASM_MESON_TAC[th; REAL_LT_REFL]) THEN
1775     MATCH_MP_TAC SPAN_INDUCT THEN SIMP_TAC[IN_INTER; IN_ELIM_THM] THEN
1776     REWRITE_TAC[subspace; DOT_RZERO; DOT_RADD; DOT_RMUL; IN_ELIM_THM] THEN
1777     CONV_TAC REAL_RING;
1778     ALL_TAC] THEN
1779   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
1780    [REWRITE_TAC[SUBSET] THEN X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
1781     FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (\x:real^N. --a + x) s`) THEN
1782     ASM_SIMP_TAC[CONVEX_TRANSLATION_EQ; COMPACT_TRANSLATION_EQ] THEN
1783     REWRITE_TAC[IN_IMAGE; VECTOR_ARITH `vec 0:real^N = --a + x <=> x = a`] THEN
1784     ASM_REWRITE_TAC[UNWIND_THM2] THEN
1785     REWRITE_TAC[EXTREME_POINTS_OF_TRANSLATION; CONVEX_HULL_TRANSLATION] THEN
1786     REWRITE_TAC[IN_IMAGE; VECTOR_ARITH `vec 0:real^N = --a + x <=> x = a`] THEN
1787     REWRITE_TAC[UNWIND_THM2];
1788     MATCH_MP_TAC HULL_MINIMAL THEN
1789     ASM_SIMP_TAC[SUBSET; extreme_point_of; IN_ELIM_THM]]);;
1790
1791 (* ------------------------------------------------------------------------- *)
1792 (* Applying it to convex hulls of explicitly indicated finite sets.          *)
1793 (* ------------------------------------------------------------------------- *)
1794
1795 let KREIN_MILMAN_POLYTOPE = prove
1796  (`!s. FINITE s
1797        ==> convex hull s =
1798            convex hull {x | x extreme_point_of (convex hull s)}`,
1799   SIMP_TAC[KREIN_MILMAN_MINKOWSKI; CONVEX_CONVEX_HULL;
1800            COMPACT_CONVEX_HULL; FINITE_IMP_COMPACT]);;
1801
1802 let EXTREME_POINTS_OF_CONVEX_HULL_EQ = prove
1803  (`!s:real^N->bool.
1804         compact s /\
1805         (!t. t PSUBSET s ==> ~(convex hull t = convex hull s))
1806         ==> {x | x extreme_point_of (convex hull s)} = s`,
1807   REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC
1808    `{x:real^N | x extreme_point_of (convex hull s)}`) THEN
1809   MATCH_MP_TAC(SET_RULE
1810    `P /\ t SUBSET s ==> (t PSUBSET s ==> ~P) ==> t = s`) THEN
1811   REWRITE_TAC[EXTREME_POINTS_OF_CONVEX_HULL] THEN
1812   CONV_TAC SYM_CONV THEN MATCH_MP_TAC KREIN_MILMAN_MINKOWSKI THEN
1813   ASM_SIMP_TAC[CONVEX_CONVEX_HULL; COMPACT_CONVEX_HULL]);;
1814
1815 let EXTREME_POINT_OF_CONVEX_HULL_EQ = prove
1816  (`!s x:real^N.
1817         compact s /\
1818         (!t. t PSUBSET s ==> ~(convex hull t = convex hull s))
1819         ==> (x extreme_point_of (convex hull s) <=> x IN s)`,
1820   REPEAT GEN_TAC THEN
1821   DISCH_THEN(MP_TAC o MATCH_MP EXTREME_POINTS_OF_CONVEX_HULL_EQ) THEN
1822   SET_TAC[]);;
1823
1824 let EXTREME_POINT_OF_CONVEX_HULL_CONVEX_INDEPENDENT = prove
1825  (`!s x:real^N.
1826         compact s /\
1827         (!a. a IN s ==> ~(a IN convex hull (s DELETE a)))
1828         ==> (x extreme_point_of (convex hull s) <=> x IN s)`,
1829   REPEAT STRIP_TAC THEN MATCH_MP_TAC EXTREME_POINT_OF_CONVEX_HULL_EQ THEN
1830   ASM_REWRITE_TAC[PSUBSET_MEMBER] THEN X_GEN_TAC `t:real^N->bool` THEN
1831   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_TAC `a:real^N`)) THEN
1832   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N`) THEN
1833   ASM_REWRITE_TAC[] THEN
1834   SUBGOAL_THEN `s SUBSET convex hull (s DELETE (a:real^N))` MP_TAC THENL
1835    [ALL_TAC; ASM SET_TAC[]] THEN
1836   MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `convex hull t:real^N->bool` THEN
1837   CONJ_TAC THENL
1838    [ASM_REWRITE_TAC[HULL_SUBSET];
1839     MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]]);;
1840
1841 let EXTREME_POINT_OF_CONVEX_HULL_AFFINE_INDEPENDENT = prove
1842  (`!s x. ~affine_dependent s
1843          ==> (x extreme_point_of (convex hull s) <=> x IN s)`,
1844   REPEAT STRIP_TAC THEN
1845   MATCH_MP_TAC EXTREME_POINT_OF_CONVEX_HULL_CONVEX_INDEPENDENT THEN
1846   ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE; FINITE_IMP_COMPACT] THEN
1847   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [affine_dependent]) THEN
1848   MESON_TAC[SUBSET; CONVEX_HULL_SUBSET_AFFINE_HULL]);;
1849
1850 let EXTREME_POINT_OF_CONVEX_HULL_2 = prove
1851  (`!a b x. x extreme_point_of (convex hull {a,b}) <=> x = a \/ x = b`,
1852   REWRITE_TAC[SET_RULE `x = a \/ x = b <=> x IN {a,b}`] THEN
1853   SIMP_TAC[EXTREME_POINT_OF_CONVEX_HULL_AFFINE_INDEPENDENT;
1854            AFFINE_INDEPENDENT_2]);;
1855
1856 let EXTREME_POINT_OF_SEGMENT = prove
1857  (`!a b x:real^N. x extreme_point_of segment[a,b] <=> x = a \/ x = b`,
1858   REWRITE_TAC[SEGMENT_CONVEX_HULL; EXTREME_POINT_OF_CONVEX_HULL_2]);;
1859
1860 let FACE_OF_CONVEX_HULL_SUBSET = prove
1861  (`!s t:real^N->bool.
1862         compact s /\ t face_of (convex hull s)
1863         ==> ?s'. s' SUBSET s /\ t = convex hull s'`,
1864   REPEAT STRIP_TAC THEN EXISTS_TAC `{x:real^N | x extreme_point_of t}` THEN
1865   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN CONJ_TAC THENL
1866    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1867     MATCH_MP_TAC EXTREME_POINT_OF_CONVEX_HULL THEN
1868     ASM_MESON_TAC[FACE_OF_SING; FACE_OF_TRANS];
1869     MATCH_MP_TAC KREIN_MILMAN_MINKOWSKI THEN
1870     ASM_MESON_TAC[FACE_OF_IMP_CONVEX; FACE_OF_IMP_COMPACT;
1871                   COMPACT_CONVEX_HULL; CONVEX_CONVEX_HULL]]);;
1872
1873 let FACE_OF_CONVEX_HULL_AFFINE_INDEPENDENT = prove
1874  (`!s t:real^N->bool.
1875         ~affine_dependent s
1876         ==> (t face_of (convex hull s) <=>
1877              ?c. c SUBSET s /\ t = convex hull c)`,
1878   REPEAT STRIP_TAC THEN EQ_TAC THENL
1879    [ASM_MESON_TAC[AFFINE_INDEPENDENT_IMP_FINITE; FINITE_IMP_COMPACT;
1880                   FACE_OF_CONVEX_HULL_SUBSET];
1881     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1882     MATCH_MP_TAC FACE_OF_CONVEX_HULLS THEN
1883     ASM_SIMP_TAC[AFFINE_INDEPENDENT_IMP_FINITE] THEN
1884     MATCH_MP_TAC(SET_RULE `
1885      !t. u SUBSET t /\ DISJOINT s t ==> DISJOINT s u`) THEN
1886     EXISTS_TAC `affine hull (s DIFF c:real^N->bool)` THEN
1887     REWRITE_TAC[CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
1888     MATCH_MP_TAC DISJOINT_AFFINE_HULL THEN
1889     EXISTS_TAC `s:real^N->bool` THEN ASM SET_TAC[]]);;
1890
1891 let FACET_OF_CONVEX_HULL_AFFINE_INDEPENDENT = prove
1892  (`!s t:real^N->bool.
1893         ~affine_dependent s
1894         ==> (t facet_of (convex hull s) <=>
1895              ~(t = {}) /\ ?u. u IN s /\ t = convex hull (s DELETE u))`,
1896   REPEAT STRIP_TAC THEN
1897   ASM_SIMP_TAC[facet_of; FACE_OF_CONVEX_HULL_AFFINE_INDEPENDENT] THEN
1898   REWRITE_TAC[AFF_DIM_CONVEX_HULL] THEN EQ_TAC THENL
1899    [DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
1900     DISCH_THEN(X_CHOOSE_THEN `c:real^N->bool` MP_TAC) THEN
1901     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC) THEN
1902     UNDISCH_TAC
1903      `aff_dim(convex hull c:real^N->bool) = aff_dim(s:real^N->bool) - &1` THEN
1904     SUBGOAL_THEN `~affine_dependent(c:real^N->bool)` ASSUME_TAC THENL
1905      [ASM_MESON_TAC[AFFINE_INDEPENDENT_SUBSET];
1906       ASM_SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT; AFF_DIM_CONVEX_HULL]] THEN
1907     REWRITE_TAC[INT_ARITH `x - &1:int = y - &1 - &1 <=> y = x + &1`] THEN
1908     REWRITE_TAC[INT_OF_NUM_ADD; INT_OF_NUM_EQ] THEN DISCH_TAC THEN
1909     SUBGOAL_THEN `(s DIFF c:real^N->bool) HAS_SIZE 1` MP_TAC THENL
1910      [ASM_SIMP_TAC[HAS_SIZE; FINITE_DIFF; CARD_DIFF;
1911                    AFFINE_INDEPENDENT_IMP_FINITE] THEN ARITH_TAC;
1912       CONV_TAC(LAND_CONV HAS_SIZE_CONV) THEN
1913       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^N` THEN
1914       DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
1915        `s DIFF t = {a} ==> t SUBSET s ==> s = a INSERT t`)) THEN
1916       ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST_ALL_TAC THEN
1917       UNDISCH_TAC `CARD((u:real^N) INSERT c) = CARD c + 1` THEN
1918       ASM_SIMP_TAC[CARD_CLAUSES; AFFINE_INDEPENDENT_IMP_FINITE] THEN
1919       COND_CASES_TAC THENL [ARITH_TAC; DISCH_THEN(K ALL_TAC)] THEN
1920       CONJ_TAC THENL [ALL_TAC; AP_TERM_TAC] THEN ASM SET_TAC[]];
1921     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN ASM_REWRITE_TAC[] THEN
1922     DISCH_THEN(X_CHOOSE_THEN `u:real^N` MP_TAC) THEN
1923     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC) THEN
1924     CONJ_TAC THENL [MESON_TAC[DELETE_SUBSET]; ALL_TAC] THEN
1925     ASM_SIMP_TAC[AFF_DIM_CONVEX_HULL] THEN
1926     SUBGOAL_THEN `~affine_dependent(s DELETE (u:real^N))` ASSUME_TAC THENL
1927      [ASM_MESON_TAC[AFFINE_INDEPENDENT_SUBSET; DELETE_SUBSET];
1928       ASM_SIMP_TAC[AFF_DIM_AFFINE_INDEPENDENT]] THEN
1929     REWRITE_TAC[INT_ARITH `x - &1:int = y - &1 - &1 <=> y = x + &1`] THEN
1930     REWRITE_TAC[INT_OF_NUM_ADD; INT_OF_NUM_EQ] THEN
1931     ASM_SIMP_TAC[CARD_DELETE; AFFINE_INDEPENDENT_IMP_FINITE] THEN
1932     MATCH_MP_TAC(ARITH_RULE `~(s = 0) ==> s = s - 1 + 1`) THEN
1933     ASM_SIMP_TAC[CARD_EQ_0; AFFINE_INDEPENDENT_IMP_FINITE] THEN
1934     ASM SET_TAC[]]);;
1935
1936 let FACET_OF_CONVEX_HULL_AFFINE_INDEPENDENT_ALT = prove
1937  (`!s t:real^N->bool.
1938         ~affine_dependent s
1939         ==> (t facet_of (convex hull s) <=>
1940              2 <= CARD s /\ ?u. u IN s /\ t = convex hull (s DELETE u))`,
1941   REPEAT STRIP_TAC THEN
1942   ASM_SIMP_TAC[FACET_OF_CONVEX_HULL_AFFINE_INDEPENDENT] THEN
1943   REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN AP_TERM_TAC THEN
1944   GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
1945   X_GEN_TAC `u:real^N` THEN
1946   ASM_CASES_TAC `t = convex hull (s DELETE (u:real^N))` THEN
1947   ASM_REWRITE_TAC[CONVEX_HULL_EQ_EMPTY] THEN
1948   ASM_CASES_TAC `(u:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
1949   SUBGOAL_THEN `CARD s = 1 + CARD(s DELETE (u:real^N))` SUBST1_TAC THENL
1950    [ASM_SIMP_TAC[CARD_DELETE; AFFINE_INDEPENDENT_IMP_FINITE] THEN
1951     MATCH_MP_TAC(ARITH_RULE `~(s = 0) ==> s = 1 + s - 1`) THEN
1952     ASM_SIMP_TAC[CARD_EQ_0; AFFINE_INDEPENDENT_IMP_FINITE] THEN
1953     ASM SET_TAC[];
1954     REWRITE_TAC[ARITH_RULE `2 <= 1 + x <=> ~(x = 0)`] THEN
1955     ASM_SIMP_TAC[CARD_EQ_0; AFFINE_INDEPENDENT_IMP_FINITE; FINITE_DELETE]]);;
1956
1957 let SEGMENT_FACE_OF = prove
1958  (`!s a b:real^N.
1959     segment[a,b] face_of s ==> a extreme_point_of s /\ b extreme_point_of s`,
1960   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM FACE_OF_SING] THEN
1961   MATCH_MP_TAC FACE_OF_TRANS THEN EXISTS_TAC `segment[a:real^N,b]` THEN
1962   ASM_REWRITE_TAC[] THEN REWRITE_TAC[FACE_OF_SING; EXTREME_POINT_OF_SEGMENT]);;
1963
1964 let SEGMENT_EDGE_OF = prove
1965  (`!s a b:real^N.
1966         segment[a,b] edge_of s
1967         ==> ~(a = b) /\ a extreme_point_of s /\ b extreme_point_of s`,
1968   REPEAT GEN_TAC THEN DISCH_TAC THEN CONJ_TAC THENL
1969    [ALL_TAC; ASM_MESON_TAC[edge_of; SEGMENT_FACE_OF]] THEN
1970   POP_ASSUM MP_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
1971   SIMP_TAC[SEGMENT_REFL; edge_of; AFF_DIM_SING] THEN INT_ARITH_TAC);;
1972
1973 let COMPACT_CONVEX_COLLINEAR_SEGMENT = prove
1974  (`!s:real^N->bool.
1975         ~(s = {}) /\ compact s /\ convex s /\ collinear s
1976         ==> ?a b. s = segment[a,b]`,
1977   REPEAT STRIP_TAC THEN
1978   MP_TAC(ISPEC `s:real^N->bool` KREIN_MILMAN_MINKOWSKI) THEN
1979   FIRST_ASSUM(MP_TAC o MATCH_MP COLLINEAR_EXTREME_POINTS) THEN
1980   REWRITE_TAC[ARITH_RULE `n <= 2 <=> n = 0 \/ n = 1 \/ n = 2`] THEN
1981   REWRITE_TAC[LEFT_OR_DISTRIB; GSYM HAS_SIZE] THEN
1982   CONV_TAC(ONCE_DEPTH_CONV HAS_SIZE_CONV) THEN
1983   STRIP_TAC THEN ASM_REWRITE_TAC[CONVEX_HULL_EMPTY; SEGMENT_CONVEX_HULL] THEN
1984   DISCH_THEN SUBST1_TAC THEN MESON_TAC[SET_RULE `{a} = {a,a}`]);;
1985
1986 let KREIN_MILMAN_RELATIVE_FRONTIER = prove
1987  (`!s:real^N->bool.
1988         convex s /\ compact s /\ ~(?a. s = {a})
1989         ==> s = convex hull (s DIFF relative_interior s)`,
1990   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
1991    [MATCH_MP_TAC SUBSET_TRANS THEN
1992     EXISTS_TAC `convex hull {x:real^N | x extreme_point_of s}` THEN
1993     CONJ_TAC THENL
1994      [ASM_SIMP_TAC[GSYM KREIN_MILMAN_MINKOWSKI; SUBSET_REFL];
1995       MATCH_MP_TAC HULL_MONO THEN SIMP_TAC[SUBSET; IN_ELIM_THM; IN_DIFF] THEN
1996       ASM_MESON_TAC[EXTREME_POINT_NOT_IN_RELATIVE_INTERIOR; extreme_point_of]];
1997     MATCH_MP_TAC SUBSET_TRANS THEN
1998     EXISTS_TAC `convex hull s:real^N->bool` THEN CONJ_TAC THENL
1999      [MATCH_MP_TAC HULL_MONO THEN SET_TAC[];
2000       ASM_SIMP_TAC[HULL_P; SUBSET_REFL]]]);;
2001
2002 let KREIN_MILMAN_FRONTIER = prove
2003  (`!s:real^N->bool.
2004         convex s /\ compact s
2005         ==> s = convex hull (frontier s)`,
2006   REPEAT STRIP_TAC THEN
2007   ASM_SIMP_TAC[frontier; COMPACT_IMP_CLOSED; CLOSURE_CLOSED] THEN
2008   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
2009    [MATCH_MP_TAC SUBSET_TRANS THEN
2010     EXISTS_TAC `convex hull {x:real^N | x extreme_point_of s}` THEN
2011     CONJ_TAC THENL
2012      [ASM_SIMP_TAC[GSYM KREIN_MILMAN_MINKOWSKI; SUBSET_REFL];
2013       MATCH_MP_TAC HULL_MONO THEN SIMP_TAC[SUBSET; IN_ELIM_THM; IN_DIFF] THEN
2014       ASM_MESON_TAC[EXTREME_POINT_NOT_IN_INTERIOR; extreme_point_of]];
2015     MATCH_MP_TAC SUBSET_TRANS THEN
2016     EXISTS_TAC `convex hull s:real^N->bool` THEN CONJ_TAC THENL
2017      [MATCH_MP_TAC HULL_MONO THEN SET_TAC[];
2018       ASM_SIMP_TAC[HULL_P; SUBSET_REFL]]]);;
2019
2020 let EXTREME_POINT_OF_CONVEX_HULL_INSERT_EQ = prove
2021  (`!s a x:real^N.
2022         FINITE s /\ ~(a IN affine hull s)
2023         ==> (x extreme_point_of (convex hull (a INSERT s)) <=>
2024              x = a \/ x extreme_point_of (convex hull s))`,
2025   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM AFFINE_HULL_CONVEX_HULL] THEN
2026   STRIP_TAC THEN ONCE_REWRITE_TAC[SET_RULE `a INSERT s = {a} UNION s`] THEN
2027   ONCE_REWRITE_TAC[HULL_UNION_RIGHT] THEN
2028   MP_TAC(ISPEC `convex hull s:real^N->bool` KREIN_MILMAN_MINKOWSKI) THEN
2029   ANTS_TAC THENL
2030    [ASM_SIMP_TAC[CONVEX_CONVEX_HULL; COMPACT_CONVEX_HULL; FINITE_IMP_COMPACT];
2031     ALL_TAC] THEN
2032   FIRST_X_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] FINITE_SUBSET)) THEN
2033   DISCH_THEN(MP_TAC o SPEC
2034    `{x:real^N | x extreme_point_of convex hull s}`) THEN
2035   REWRITE_TAC[EXTREME_POINTS_OF_CONVEX_HULL] THEN
2036   ABBREV_TAC `v = {x:real^N | x extreme_point_of (convex hull s)}` THEN
2037   DISCH_TAC THEN DISCH_THEN SUBST_ALL_TAC THEN
2038   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE (RAND_CONV o RAND_CONV)
2039    [AFFINE_HULL_CONVEX_HULL]) THEN
2040   ASM_CASES_TAC `(a:real^N) IN v` THEN ASM_SIMP_TAC[HULL_INC] THEN
2041   STRIP_TAC THEN REWRITE_TAC[GSYM HULL_UNION_RIGHT] THEN
2042   REWRITE_TAC[SET_RULE `{a} UNION s = a INSERT s`] THEN EQ_TAC THENL
2043    [DISCH_THEN(MP_TAC o MATCH_MP EXTREME_POINT_OF_CONVEX_HULL) THEN
2044     ASM SET_TAC[];
2045     STRIP_TAC THENL
2046      [ASM_REWRITE_TAC[] THEN
2047       MATCH_MP_TAC EXTREME_POINT_OF_CONVEX_HULL_INSERT THEN
2048       ASM_MESON_TAC[CONVEX_HULL_SUBSET_AFFINE_HULL; SUBSET];
2049       REWRITE_TAC[GSYM FACE_OF_SING] THEN
2050       MATCH_MP_TAC FACE_OF_TRANS THEN
2051       EXISTS_TAC `convex hull v:real^N->bool` THEN
2052       ASM_REWRITE_TAC[FACE_OF_SING] THEN
2053       MATCH_MP_TAC FACE_OF_CONVEX_HULLS THEN
2054       ASM_SIMP_TAC[FINITE_INSERT; AFFINE_HULL_SING; CONVEX_HULL_SING;
2055                SET_RULE `~(a IN s) ==> a INSERT s DIFF s = {a}`] THEN
2056       ASM SET_TAC[]]]);;
2057
2058 let FACE_OF_CONVEX_HULL_INSERT_EQ = prove
2059  (`!f s a:real^N.
2060         FINITE s /\ ~(a IN affine hull s)
2061         ==> (f face_of (convex hull (a INSERT s)) <=>
2062              f face_of (convex hull s) \/
2063              ?f'. f' face_of (convex hull s) /\
2064                   f = convex hull (a INSERT f'))`,
2065   let lemma = prove
2066    (`!a b c p:real^N u v w x.
2067           x % p = u % a + v % b + w % c
2068           ==> !s. u + v + w = x /\ ~(x = &0) /\ affine s /\
2069                   a IN s /\ b IN s /\ c IN s
2070                   ==> p IN s`,
2071     REPEAT STRIP_TAC THEN
2072     FIRST_X_ASSUM(MP_TAC o AP_TERM `(%) (inv x):real^N->real^N`) THEN
2073     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID] THEN
2074     DISCH_THEN SUBST1_TAC THEN
2075     REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC] THEN
2076     MATCH_MP_TAC(SET_RULE `!t. x IN t /\ t SUBSET s ==> x IN s`) THEN
2077     EXISTS_TAC `affine hull {a:real^N,b,c}` THEN
2078     ASM_SIMP_TAC[HULL_MINIMAL; INSERT_SUBSET; EMPTY_SUBSET] THEN
2079     REWRITE_TAC[AFFINE_HULL_3; IN_ELIM_THM] THEN MAP_EVERY EXISTS_TAC
2080      [`inv x * u:real`; `inv x * v:real`; `inv x * w:real`] THEN
2081     REWRITE_TAC[] THEN UNDISCH_TAC `u + v + w:real = x` THEN
2082     UNDISCH_TAC `~(x = &0)` THEN CONV_TAC REAL_FIELD) in
2083   REPEAT STRIP_TAC THEN EQ_TAC THENL
2084    [DISCH_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
2085       FACE_OF_CONVEX_HULL_SUBSET)) THEN
2086     ASM_SIMP_TAC[COMPACT_INSERT; FINITE_IMP_COMPACT] THEN
2087     DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
2088     FIRST_X_ASSUM SUBST_ALL_TAC THEN ASM_CASES_TAC `(a:real^N) IN t` THENL
2089      [ALL_TAC;
2090       DISJ1_TAC THEN MATCH_MP_TAC FACE_OF_SUBSET THEN
2091       EXISTS_TAC `convex hull ((a:real^N) INSERT s)` THEN
2092       ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC HULL_MONO THEN
2093       ASM SET_TAC[]] THEN
2094     DISJ2_TAC THEN
2095     EXISTS_TAC `(convex hull t) INTER (convex hull s):real^N->bool` THEN
2096     CONJ_TAC THENL
2097      [MATCH_MP_TAC FACE_OF_SUBSET THEN
2098       EXISTS_TAC `convex hull ((a:real^N) INSERT s)` THEN
2099       SIMP_TAC[INTER_SUBSET; HULL_MONO; SET_RULE `s SUBSET (a INSERT s)`] THEN
2100       MATCH_MP_TAC FACE_OF_INTER THEN ASM_REWRITE_TAC[] THEN
2101       MATCH_MP_TAC FACE_OF_CONVEX_HULL_INSERT THEN
2102       ASM_REWRITE_TAC[FACE_OF_REFL_EQ; CONVEX_CONVEX_HULL];
2103       MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THEN
2104       MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[CONVEX_CONVEX_HULL] THEN
2105       ASM_SIMP_TAC[INSERT_SUBSET; HULL_INC; INTER_SUBSET] THEN
2106       REWRITE_TAC[SUBSET] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_INC THEN
2107       ASM_CASES_TAC `x:real^N = a` THEN ASM_REWRITE_TAC[IN_INSERT] THEN
2108       REWRITE_TAC[IN_INTER] THEN CONJ_TAC THEN MATCH_MP_TAC HULL_INC THEN
2109       ASM SET_TAC[]];
2110     ALL_TAC] THEN
2111   DISCH_THEN(DISJ_CASES_THEN ASSUME_TAC) THENL
2112    [MATCH_MP_TAC FACE_OF_CONVEX_HULL_INSERT THEN ASM_REWRITE_TAC[];
2113     FIRST_X_ASSUM(X_CHOOSE_THEN `f':real^N->bool` MP_TAC)] THEN
2114   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC SUBST1_TAC) THEN
2115   SPEC_TAC(`f':real^N->bool`,`f:real^N->bool`) THEN REPEAT STRIP_TAC THEN
2116   ASM_CASES_TAC `s:real^N->bool = {}` THENL
2117    [UNDISCH_TAC `(f:real^N->bool) face_of convex hull s` THEN
2118     ASM_SIMP_TAC[FACE_OF_EMPTY; CONVEX_HULL_EMPTY; FACE_OF_REFL_EQ] THEN
2119     REWRITE_TAC[CONVEX_CONVEX_HULL];
2120     ALL_TAC] THEN
2121   ASM_CASES_TAC `f:real^N->bool = {}` THENL
2122    [ASM_REWRITE_TAC[CONVEX_HULL_SING; FACE_OF_SING] THEN
2123     MATCH_MP_TAC EXTREME_POINT_OF_CONVEX_HULL_INSERT THEN
2124     ASM_REWRITE_TAC[] THEN
2125     ASM_MESON_TAC[CONVEX_HULL_SUBSET_AFFINE_HULL; SUBSET];
2126     ALL_TAC] THEN
2127   REWRITE_TAC[face_of; CONVEX_CONVEX_HULL] THEN CONJ_TAC THENL
2128    [MATCH_MP_TAC HULL_MINIMAL THEN
2129     SIMP_TAC[INSERT_SUBSET; HULL_INC; IN_INSERT; CONVEX_CONVEX_HULL] THEN
2130     MATCH_MP_TAC SUBSET_TRANS THEN
2131     EXISTS_TAC `convex hull s:real^N->bool` THEN
2132     ASM_SIMP_TAC[HULL_MONO; SET_RULE `s SUBSET (a INSERT s)`] THEN
2133     ASM_MESON_TAC[FACE_OF_IMP_SUBSET];
2134     ALL_TAC] THEN
2135   ASM_REWRITE_TAC[CONVEX_HULL_INSERT_ALT] THEN
2136   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_GSPEC] THEN
2137   REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC] THEN
2138   X_GEN_TAC `ub:real` THEN STRIP_TAC THEN
2139   X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
2140   X_GEN_TAC `uc:real` THEN STRIP_TAC THEN
2141   X_GEN_TAC `c:real^N` THEN STRIP_TAC THEN
2142   X_GEN_TAC `ux:real` THEN STRIP_TAC THEN
2143   X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
2144   FIRST_X_ASSUM(STRIP_ASSUME_TAC o GEN_REWRITE_RULE I [face_of]) THEN
2145   SUBGOAL_THEN `convex hull f:real^N->bool = f` SUBST_ALL_TAC THENL
2146    [ASM_MESON_TAC[CONVEX_HULL_EQ]; ALL_TAC] THEN
2147   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT]) THEN
2148   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `v:real` MP_TAC)) THEN
2149   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
2150   REWRITE_TAC[VECTOR_ARITH
2151    `(&1 - ux) % a + ux % x:real^N =
2152     (&1 - v) % ((&1 - ub) % a + ub % b) + v % ((&1 - uc) % a + uc % c) <=>
2153     ((&1 - ux) - ((&1 - v) * (&1 - ub) + v * (&1 - uc))) % a +
2154     (ux % x - (((&1 - v) * ub) % b + (v * uc) % c)) = vec 0`] THEN
2155   ASM_CASES_TAC `&1 - ux - ((&1 - v) * (&1 - ub) + v * (&1 - uc)) = &0` THENL
2156    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN
2157     FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REAL_RING
2158      `(&1 - ux) - ((&1 - v) * (&1 - ub) + v * (&1 - uc)) = &0
2159       ==> (&1 - v) * ub + v * uc = ux`)) THEN
2160     ASM_CASES_TAC `uc = &0` THENL
2161      [UNDISCH_THEN `uc = &0` SUBST_ALL_TAC THEN
2162       FIRST_X_ASSUM(SUBST_ALL_TAC o MATCH_MP (REAL_ARITH
2163        `a + v * &0 = b ==> b = a`)) THEN
2164       REWRITE_TAC[REAL_MUL_RZERO; VECTOR_MUL_LZERO; VECTOR_ADD_RID] THEN
2165       REWRITE_TAC[VECTOR_SUB_EQ; VECTOR_MUL_LCANCEL; REAL_ENTIRE] THEN
2166       STRIP_TAC THENL
2167        [ASM_REAL_ARITH_TAC;
2168         ASM_MESON_TAC[VECTOR_MUL_LZERO];
2169         ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2170         REWRITE_TAC[IN_ELIM_THM] THEN
2171         MAP_EVERY EXISTS_TAC [`&0`; `x:real^N`] THEN
2172         ASM_REWRITE_TAC[] THEN CONV_TAC VECTOR_ARITH];
2173       ALL_TAC] THEN
2174     ASM_CASES_TAC `ub = &0` THENL
2175      [UNDISCH_THEN `ub = &0` SUBST_ALL_TAC THEN
2176       FIRST_X_ASSUM(SUBST_ALL_TAC o MATCH_MP (REAL_ARITH
2177        `v * &0 + a = b ==> b = a`)) THEN
2178       REWRITE_TAC[REAL_MUL_RZERO; VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN
2179       REWRITE_TAC[VECTOR_SUB_EQ; VECTOR_MUL_LCANCEL; REAL_ENTIRE] THEN
2180       STRIP_TAC THENL
2181        [ASM_REAL_ARITH_TAC;
2182         ASM_MESON_TAC[VECTOR_MUL_LZERO];
2183         ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
2184         REWRITE_TAC[IN_ELIM_THM] THEN
2185         MAP_EVERY EXISTS_TAC [`&0`; `x:real^N`] THEN
2186         ASM_REWRITE_TAC[] THEN CONV_TAC VECTOR_ARITH];
2187       ALL_TAC] THEN
2188     DISCH_THEN(fun th ->
2189       SUBGOAL_THEN
2190        `(b:real^N) IN f /\ (c:real^N) IN f`
2191       MP_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN MP_TAC th) THEN
2192     ASM_CASES_TAC `ux = &0` THENL
2193      [DISCH_THEN(K ALL_TAC) THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
2194       EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[] THEN
2195       FIRST_X_ASSUM(MP_TAC o MATCH_MP (REAL_ARITH
2196        `&1 - ux - a = &0 ==> ux = &0 ==> ~(a < &1)`)) THEN
2197       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(TAUT `p ==> ~p ==> q`) THEN
2198       MATCH_MP_TAC REAL_LTE_TRANS THEN
2199       EXISTS_TAC `(&1 - v) * &1 + v * &1` THEN
2200       CONJ_TAC THENL [ALL_TAC; REAL_ARITH_TAC] THEN
2201       MATCH_MP_TAC(REAL_ARITH
2202        `x <= y /\ w <= z /\ ~(x = y /\ w = z) ==> x + w < y + z`) THEN
2203       ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_SUB_LT; REAL_EQ_MUL_LCANCEL] THEN
2204       REPEAT(CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
2205       ASM_SIMP_TAC[REAL_SUB_0; REAL_LT_IMP_NE] THEN
2206       REWRITE_TAC[REAL_ARITH `&1 - x = &1 <=> x = &0`] THEN
2207       DISCH_THEN(CONJUNCTS_THEN SUBST_ALL_TAC) THEN
2208       ASM_MESON_TAC[VECTOR_MUL_LZERO];
2209       ALL_TAC] THEN
2210     REWRITE_TAC[VECTOR_SUB_EQ] THEN ASM_CASES_TAC `c:real^N = b` THENL
2211      [ASM_REWRITE_TAC[GSYM VECTOR_ADD_RDISTRIB; VECTOR_MUL_LCANCEL] THEN
2212       ASM_MESON_TAC[];
2213       ALL_TAC] THEN
2214     DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
2215     EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[IN_SEGMENT] THEN
2216     EXISTS_TAC `(v * uc) / ux:real` THEN
2217     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LT_LDIV_EQ; REAL_ARITH
2218      `&0 <= x /\ ~(x = &0) ==> &0 < x`] THEN
2219     REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID] THEN REPEAT CONJ_TAC THENL
2220      [MATCH_MP_TAC REAL_LT_MUL THEN ASM_REAL_ARITH_TAC;
2221       EXPAND_TAC "ux" THEN REWRITE_TAC[REAL_ARITH `b < a + b <=> &0 < a`] THEN
2222       MATCH_MP_TAC REAL_LT_MUL THEN ASM_REAL_ARITH_TAC;
2223       FIRST_X_ASSUM(MP_TAC o AP_TERM `(%) (inv ux) :real^N->real^N`) THEN
2224       ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV] THEN
2225       REWRITE_TAC[VECTOR_MUL_LID] THEN DISCH_THEN SUBST1_TAC THEN
2226       REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC] THEN
2227       BINOP_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
2228       REWRITE_TAC[REAL_ARITH `inv u * v * uc:real = (v * uc) / u`] THEN
2229       UNDISCH_TAC `(&1 - v) * ub + v * uc = ux` THEN
2230       UNDISCH_TAC `~(ux = &0)` THEN CONV_TAC REAL_FIELD];
2231     DISCH_THEN(MP_TAC o MATCH_MP (VECTOR_ARITH
2232      `a + (b - c):real^N = vec 0 ==> a = c + --b`)) THEN
2233     REWRITE_TAC[GSYM VECTOR_ADD_ASSOC; GSYM VECTOR_MUL_LNEG] THEN
2234     DISCH_THEN(MP_TAC o SPEC `affine hull s:real^N->bool` o
2235       MATCH_MP lemma) THEN
2236     ASM_REWRITE_TAC[AFFINE_AFFINE_HULL] THEN
2237     MATCH_MP_TAC(TAUT `p ==> ~p ==> q`) THEN
2238     CONJ_TAC THENL [CONV_TAC REAL_RING; REPEAT CONJ_TAC] THEN
2239     MATCH_MP_TAC(REWRITE_RULE[SUBSET] CONVEX_HULL_SUBSET_AFFINE_HULL) THEN
2240     ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;
2241
2242 (* ------------------------------------------------------------------------- *)
2243 (* Polytopes.                                                                *)
2244 (* ------------------------------------------------------------------------- *)
2245
2246 let polytope = new_definition
2247  `polytope s <=> ?v. FINITE v /\ s = convex hull v`;;
2248
2249 let POLYTOPE_TRANSLATION_EQ = prove
2250  (`!a s. polytope (IMAGE (\x:real^N. a + x) s) <=> polytope s`,
2251   REWRITE_TAC[polytope] THEN GEOM_TRANSLATE_TAC[]);;
2252
2253 add_translation_invariants [POLYTOPE_TRANSLATION_EQ];;
2254
2255 let POLYTOPE_LINEAR_IMAGE = prove
2256  (`!f:real^M->real^N p.
2257         linear f /\ polytope p ==> polytope(IMAGE f p)`,
2258   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2259   REWRITE_TAC[polytope] THEN
2260   DISCH_THEN(X_CHOOSE_THEN `s:real^M->bool` STRIP_ASSUME_TAC) THEN
2261   EXISTS_TAC `IMAGE (f:real^M->real^N) s` THEN
2262   ASM_SIMP_TAC[CONVEX_HULL_LINEAR_IMAGE; FINITE_IMAGE]);;
2263
2264 let POLYTOPE_LINEAR_IMAGE_EQ = prove
2265  (`!f:real^M->real^N s.
2266         linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
2267         ==> (polytope (IMAGE f s) <=> polytope s)`,
2268   REPEAT STRIP_TAC THEN REWRITE_TAC[polytope] THEN
2269   MP_TAC(ISPEC `f:real^M->real^N` QUANTIFY_SURJECTION_THM) THEN
2270   ASM_REWRITE_TAC[] THEN
2271   DISCH_THEN(fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)[th]) THEN
2272   MP_TAC(end_itlist CONJ
2273    (mapfilter (ISPEC `f:real^M->real^N`) (!invariant_under_linear))) THEN
2274   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN ASM_REWRITE_TAC[]);;
2275
2276 let POLYTOPE_EMPTY = prove
2277  (`polytope {}`,
2278   REWRITE_TAC[polytope] THEN MESON_TAC[FINITE_EMPTY; CONVEX_HULL_EMPTY]);;
2279
2280 let POLYTOPE_NEGATIONS = prove
2281  (`!s:real^N->bool. polytope s ==> polytope(IMAGE (--) s)`,
2282   SIMP_TAC[POLYTOPE_LINEAR_IMAGE; LINEAR_NEGATION]);;
2283
2284 let POLYTOPE_CONVEX_HULL = prove
2285  (`!s. FINITE s ==> polytope(convex hull s)`,
2286   REWRITE_TAC[polytope] THEN MESON_TAC[]);;
2287
2288 let POLYTOPE_PCROSS = prove
2289  (`!s:real^M->bool t:real^N->bool.
2290         polytope s /\ polytope t ==> polytope(s PCROSS t)`,
2291   REPEAT GEN_TAC THEN REWRITE_TAC[polytope] THEN
2292   MESON_TAC[CONVEX_HULL_PCROSS; FINITE_PCROSS]);;
2293
2294 let POLYTOPE_PCROSS_EQ = prove
2295  (`!s:real^M->bool t:real^N->bool.
2296         polytope(s PCROSS t) <=>
2297         s = {} \/ t = {} \/ polytope s /\ polytope t`,
2298   REPEAT GEN_TAC THEN
2299   ASM_CASES_TAC `s:real^M->bool = {}` THEN
2300   ASM_REWRITE_TAC[PCROSS_EMPTY; POLYTOPE_EMPTY] THEN
2301   ASM_CASES_TAC `t:real^N->bool = {}` THEN
2302   ASM_REWRITE_TAC[PCROSS_EMPTY; POLYTOPE_EMPTY] THEN
2303   EQ_TAC THEN REWRITE_TAC[POLYTOPE_PCROSS] THEN REPEAT STRIP_TAC THENL
2304    [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
2305                     `(s:real^M->bool) PCROSS (t:real^N->bool)`]
2306        POLYTOPE_LINEAR_IMAGE) THEN
2307     ASM_REWRITE_TAC[LINEAR_FSTCART];
2308     MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
2309                    `(s:real^M->bool) PCROSS (t:real^N->bool)`]
2310        POLYTOPE_LINEAR_IMAGE) THEN
2311     ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN
2312   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
2313   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS;
2314               FSTCART_PASTECART; SNDCART_PASTECART] THEN
2315   ASM SET_TAC[]);;
2316
2317 let FACE_OF_POLYTOPE_POLYTOPE = prove
2318  (`!f s:real^N->bool. polytope s /\ f face_of s ==> polytope f`,
2319   REWRITE_TAC[polytope] THEN
2320   MESON_TAC[FINITE_SUBSET; FACE_OF_CONVEX_HULL_SUBSET; FINITE_IMP_COMPACT]);;
2321
2322 let FINITE_POLYTOPE_FACES = prove
2323  (`!s:real^N->bool. polytope s ==> FINITE {f | f face_of s}`,
2324   GEN_TAC THEN REWRITE_TAC[polytope; LEFT_IMP_EXISTS_THM] THEN
2325   X_GEN_TAC `v:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2326   MATCH_MP_TAC FINITE_SUBSET THEN
2327   EXISTS_TAC `IMAGE ((hull) convex) {t:real^N->bool | t SUBSET v}` THEN
2328   ASM_SIMP_TAC[FINITE_POWERSET; FINITE_IMAGE] THEN
2329   GEN_REWRITE_TAC I [SUBSET] THEN
2330   REWRITE_TAC[FORALL_IN_GSPEC; IN_IMAGE; IN_ELIM_THM] THEN
2331   ASM_MESON_TAC[FACE_OF_CONVEX_HULL_SUBSET; FINITE_IMP_COMPACT]);;
2332
2333 let FINITE_POLYTOPE_FACETS = prove
2334  (`!s:real^N->bool. polytope s ==> FINITE {f | f facet_of s}`,
2335   REWRITE_TAC[facet_of] THEN ONCE_REWRITE_TAC[SET_RULE
2336    `{x | P x /\ Q x} = {x | x IN {x | P x} /\ Q x}`] THEN
2337   SIMP_TAC[FINITE_RESTRICT; FINITE_POLYTOPE_FACES]);;
2338
2339 let POLYTOPE_SCALING = prove
2340  (`!c s:real^N->bool. polytope s ==> polytope (IMAGE (\x. c % x) s)`,
2341   REPEAT GEN_TAC THEN REWRITE_TAC[polytope] THEN DISCH_THEN
2342    (X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
2343   EXISTS_TAC `IMAGE (\x:real^N. c % x) u` THEN
2344   ASM_SIMP_TAC[CONVEX_HULL_SCALING; FINITE_IMAGE]);;
2345
2346 let POLYTOPE_SCALING_EQ = prove
2347  (`!c s:real^N->bool.
2348      ~(c = &0) ==> (polytope (IMAGE (\x. c % x) s) <=> polytope s)`,
2349   REPEAT STRIP_TAC THEN EQ_TAC THEN REWRITE_TAC[POLYTOPE_SCALING] THEN
2350   DISCH_THEN(MP_TAC o SPEC `inv c:real` o MATCH_MP POLYTOPE_SCALING) THEN
2351   ASM_SIMP_TAC[GSYM IMAGE_o; o_DEF; VECTOR_MUL_ASSOC;
2352                REAL_MUL_LINV; VECTOR_MUL_LID; IMAGE_ID]);;
2353
2354 let POLYTOPE_SUMS = prove
2355  (`!s t:real^N->bool.
2356         polytope s /\ polytope t ==> polytope {x + y | x IN s /\ y IN t}`,
2357   REPEAT GEN_TAC THEN REWRITE_TAC[polytope] THEN DISCH_THEN(CONJUNCTS_THEN2
2358    (X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC)
2359    (X_CHOOSE_THEN `v:real^N->bool` STRIP_ASSUME_TAC)) THEN
2360   EXISTS_TAC `{x + y:real^N | x IN u /\ y IN v}` THEN
2361   ASM_SIMP_TAC[FINITE_PRODUCT_DEPENDENT; CONVEX_HULL_SUMS]);;
2362
2363 let POLYTOPE_IMP_COMPACT = prove
2364  (`!s. polytope s ==> compact s`,
2365   SIMP_TAC[polytope; LEFT_IMP_EXISTS_THM; COMPACT_CONVEX_HULL;
2366            FINITE_IMP_COMPACT; FINITE_INSERT; FINITE_EMPTY]);;
2367
2368 let POLYTOPE_IMP_CONVEX = prove
2369  (`!s. polytope s ==> convex s`,
2370   SIMP_TAC[polytope; LEFT_IMP_EXISTS_THM; CONVEX_CONVEX_HULL]);;
2371
2372 let POLYTOPE_IMP_CLOSED = prove
2373  (`!s. polytope s ==> closed s`,
2374   SIMP_TAC[POLYTOPE_IMP_COMPACT; COMPACT_IMP_CLOSED]);;
2375
2376 let POLYTOPE_IMP_BOUNDED = prove
2377  (`!s. polytope s ==> bounded s`,
2378   SIMP_TAC[POLYTOPE_IMP_COMPACT; COMPACT_IMP_BOUNDED]);;
2379
2380 let POLYTOPE_INTERVAL = prove
2381  (`!a b. polytope(interval[a,b])`,
2382   REWRITE_TAC[polytope] THEN MESON_TAC[CLOSED_INTERVAL_AS_CONVEX_HULL]);;
2383
2384 let POLYTOPE_SING = prove
2385  (`!a. polytope {a}`,
2386   MESON_TAC[POLYTOPE_INTERVAL; INTERVAL_SING]);;
2387
2388 (* ------------------------------------------------------------------------- *)
2389 (* Polyhedra.                                                                *)
2390 (* ------------------------------------------------------------------------- *)
2391
2392 let polyhedron = new_definition
2393  `polyhedron s <=>
2394         ?f. FINITE f /\
2395             s = INTERS f /\
2396             (!h. h IN f ==> ?a b. ~(a = vec 0) /\ h = {x | a dot x <= b})`;;
2397
2398 let POLYHEDRON_INTER = prove
2399  (`!s t:real^N->bool.
2400         polyhedron s /\ polyhedron t ==> polyhedron (s INTER t)`,
2401   REPEAT GEN_TAC THEN REWRITE_TAC[polyhedron] THEN
2402   DISCH_THEN(CONJUNCTS_THEN2
2403    (X_CHOOSE_TAC `f:(real^N->bool)->bool`)
2404    (X_CHOOSE_TAC `g:(real^N->bool)->bool`)) THEN
2405   EXISTS_TAC `f UNION g:(real^N->bool)->bool` THEN
2406   ASM_REWRITE_TAC[SET_RULE `INTERS(f UNION g) = INTERS f INTER INTERS g`] THEN
2407   REWRITE_TAC[FINITE_UNION; IN_UNION] THEN
2408   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[]);;
2409
2410 let POLYHEDRON_UNIV = prove
2411  (`polyhedron(:real^N)`,
2412   REWRITE_TAC[polyhedron] THEN EXISTS_TAC `{}:(real^N->bool)->bool` THEN
2413   REWRITE_TAC[INTERS_0; NOT_IN_EMPTY; FINITE_RULES]);;
2414
2415 let POLYHEDRON_POSITIVE_ORTHANT = prove
2416  (`polyhedron {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> &0 <= x$i}`,
2417   REWRITE_TAC[polyhedron] THEN
2418   EXISTS_TAC `IMAGE (\i. {x:real^N | &0 <= x$i}) (1..dimindex(:N))` THEN
2419   SIMP_TAC[FINITE_IMAGE; FINITE_NUMSEG; FORALL_IN_IMAGE] THEN CONJ_TAC THENL
2420    [GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[INTERS_IMAGE] THEN
2421     REWRITE_TAC[IN_ELIM_THM; IN_NUMSEG];
2422     X_GEN_TAC `k:num` THEN REWRITE_TAC[IN_NUMSEG] THEN STRIP_TAC THEN
2423     MAP_EVERY EXISTS_TAC [`--basis k:real^N`; `&0`] THEN
2424     ASM_SIMP_TAC[VECTOR_NEG_EQ_0; DOT_LNEG; DOT_BASIS; BASIS_NONZERO] THEN
2425     REWRITE_TAC[REAL_ARITH `--x <= &0 <=> &0 <= x`]]);;
2426
2427 let POLYHEDRON_INTERS = prove
2428  (`!f:(real^N->bool)->bool.
2429         FINITE f /\ (!s. s IN f ==> polyhedron s) ==> polyhedron(INTERS f)`,
2430   REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
2431   REWRITE_TAC[NOT_IN_EMPTY; INTERS_0; POLYHEDRON_UNIV] THEN
2432   ASM_SIMP_TAC[INTERS_INSERT; FORALL_IN_INSERT; POLYHEDRON_INTER]);;
2433
2434 let POLYHEDRON_EMPTY = prove
2435  (`polyhedron({}:real^N->bool)`,
2436   REWRITE_TAC[polyhedron] THEN
2437   EXISTS_TAC `{{x:real^N | basis 1 dot x <= -- &1},
2438                {x | --(basis 1) dot x <= -- &1}}` THEN
2439   REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY; INTERS_2; FORALL_IN_INSERT] THEN
2440   REWRITE_TAC[NOT_IN_EMPTY; INTER; IN_ELIM_THM; DOT_LNEG] THEN
2441   REWRITE_TAC[REAL_ARITH `~(a <= -- &1 /\ --a <= -- &1)`; EMPTY_GSPEC] THEN
2442   CONJ_TAC THENL
2443    [MAP_EVERY EXISTS_TAC [`basis 1:real^N`; `-- &1`];
2444     MAP_EVERY EXISTS_TAC [`--(basis 1):real^N`; `-- &1`]] THEN
2445   SIMP_TAC[VECTOR_NEG_EQ_0; BASIS_NONZERO; DOT_LNEG;
2446            DIMINDEX_GE_1; LE_REFL]);;
2447
2448 let POLYHEDRON_HALFSPACE_LE = prove
2449  (`!a b. polyhedron {x:real^N | a dot x <= b}`,
2450   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THENL
2451    [ASM_SIMP_TAC[DOT_LZERO; SET_RULE `{x | p} = if p then UNIV else {}`] THEN
2452     COND_CASES_TAC THEN ASM_REWRITE_TAC[POLYHEDRON_EMPTY; POLYHEDRON_UNIV];
2453     REWRITE_TAC[polyhedron] THEN EXISTS_TAC `{{x:real^N | a dot x <= b}}` THEN
2454     REWRITE_TAC[FINITE_SING; INTERS_1; FORALL_IN_INSERT; NOT_IN_EMPTY] THEN
2455     MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real`] THEN ASM_REWRITE_TAC[]]);;
2456
2457 let POLYHEDRON_HALFSPACE_GE = prove
2458  (`!a b. polyhedron {x:real^N | a dot x >= b}`,
2459   REWRITE_TAC[REAL_ARITH `a:real >= b <=> --a <= --b`] THEN
2460   REWRITE_TAC[GSYM DOT_LNEG; POLYHEDRON_HALFSPACE_LE]);;
2461
2462 let POLYHEDRON_HYPERPLANE = prove
2463  (`!a b. polyhedron {x:real^N | a dot x = b}`,
2464   REWRITE_TAC[REAL_ARITH `x:real = b <=> x <= b /\ x >= b`] THEN
2465   REWRITE_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
2466   SIMP_TAC[POLYHEDRON_INTER; POLYHEDRON_HALFSPACE_LE;
2467            POLYHEDRON_HALFSPACE_GE]);;
2468
2469 let AFFINE_IMP_POLYHEDRON = prove
2470  (`!s:real^N->bool. affine s ==> polyhedron s`,
2471   REPEAT STRIP_TAC THEN MP_TAC(ISPEC `s:real^N->bool`
2472     AFFINE_HULL_FINITE_INTERSECTION_HYPERPLANES) THEN
2473   ASM_SIMP_TAC[HULL_P; RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
2474   STRIP_TAC THEN ASM_SIMP_TAC[] THEN
2475   MATCH_MP_TAC POLYHEDRON_INTERS THEN ASM_REWRITE_TAC[] THEN
2476   X_GEN_TAC `h:real^N->bool` THEN DISCH_TAC THEN
2477   FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
2478   ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o CONJUNCT2) THEN
2479   REWRITE_TAC[POLYHEDRON_HYPERPLANE]);;
2480
2481 let POLYHEDRON_IMP_CLOSED = prove
2482  (`!s:real^N->bool. polyhedron s ==> closed s`,
2483   REWRITE_TAC[polyhedron; RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
2484   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2485   MATCH_MP_TAC CLOSED_INTERS THEN
2486   X_GEN_TAC `h:real^N->bool` THEN DISCH_TAC THEN
2487   FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
2488   ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o CONJUNCT2) THEN
2489   REWRITE_TAC[CLOSED_HALFSPACE_LE]);;
2490
2491 let POLYHEDRON_IMP_CONVEX = prove
2492  (`!s:real^N->bool. polyhedron s ==> convex s`,
2493   REWRITE_TAC[polyhedron; RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
2494   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2495   MATCH_MP_TAC CONVEX_INTERS THEN
2496   X_GEN_TAC `h:real^N->bool` THEN DISCH_TAC THEN
2497   FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
2498   ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o CONJUNCT2) THEN
2499   REWRITE_TAC[CONVEX_HALFSPACE_LE]);;
2500
2501 let POLYHEDRON_AFFINE_HULL = prove
2502  (`!s. polyhedron(affine hull s)`,
2503   SIMP_TAC[AFFINE_IMP_POLYHEDRON; AFFINE_AFFINE_HULL]);;
2504
2505 (* ------------------------------------------------------------------------- *)
2506 (* Canonical polyedron representation making facial structure explicit.      *)
2507 (* ------------------------------------------------------------------------- *)
2508
2509 let POLYHEDRON_INTER_AFFINE = prove
2510  (`!s. polyhedron s <=>
2511         ?f. FINITE f /\
2512             s = (affine hull s) INTER (INTERS f) /\
2513             (!h. h IN f
2514                  ==> ?a b. ~(a = vec 0) /\ h = {x:real^N | a dot x <= b})`,
2515   GEN_TAC THEN EQ_TAC THENL
2516    [REWRITE_TAC[polyhedron] THEN MATCH_MP_TAC MONO_EXISTS THEN
2517     GEN_TAC THEN STRIP_TAC THEN REPEAT CONJ_TAC THEN
2518     TRY(FIRST_ASSUM ACCEPT_TAC) THEN
2519     MATCH_MP_TAC(SET_RULE `s = t /\ s SUBSET u ==> s = u INTER t`) THEN
2520     REWRITE_TAC[HULL_SUBSET] THEN ASM_REWRITE_TAC[];
2521     STRIP_TAC THEN ONCE_ASM_REWRITE_TAC[] THEN
2522     MATCH_MP_TAC POLYHEDRON_INTER THEN REWRITE_TAC[POLYHEDRON_AFFINE_HULL] THEN
2523     MATCH_MP_TAC POLYHEDRON_INTERS THEN ASM_REWRITE_TAC[] THEN
2524     ASM_MESON_TAC[POLYHEDRON_HALFSPACE_LE]]);;
2525
2526 let POLYHEDRON_INTER_AFFINE_PARALLEL = prove
2527  (`!s:real^N->bool.
2528         polyhedron s <=>
2529         ?f. FINITE f /\
2530             s = (affine hull s) INTER (INTERS f) /\
2531             (!h. h IN f
2532                  ==> ?a b. ~(a = vec 0) /\ h = {x:real^N | a dot x <= b} /\
2533                            (!x. x IN affine hull s
2534                                 ==> (x + a) IN affine hull s))`,
2535   GEN_TAC THEN REWRITE_TAC[POLYHEDRON_INTER_AFFINE] THEN EQ_TAC THENL
2536    [ALL_TAC; MATCH_MP_TAC MONO_EXISTS THEN MESON_TAC[]] THEN
2537   DISCH_THEN(X_CHOOSE_THEN `f:(real^N->bool)->bool` MP_TAC) THEN
2538   ASM_CASES_TAC `s:real^N->bool = {}` THENL
2539    [DISCH_THEN(K ALL_TAC) THEN EXISTS_TAC `{}:(real^N->bool)->bool` THEN
2540     ASM_SIMP_TAC[AFFINE_HULL_EMPTY; INTER_EMPTY; NOT_IN_EMPTY; FINITE_EMPTY];
2541     ALL_TAC] THEN
2542   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
2543    [ASM_REWRITE_TAC[NOT_IN_EMPTY; INTERS_0; INTER_UNIV] THEN
2544     DISCH_THEN(ASSUME_TAC o SYM o CONJUNCT2) THEN
2545     EXISTS_TAC `{}:(real^N->bool)->bool` THEN
2546     ASM_REWRITE_TAC[NOT_IN_EMPTY; INTERS_0; INTER_UNIV; FINITE_EMPTY];
2547     ALL_TAC] THEN
2548   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 (ASSUME_TAC o GSYM) MP_TAC)) THEN
2549   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
2550    [RIGHT_IMP_EXISTS_THM] THEN
2551   REWRITE_TAC[LEFT_IMP_EXISTS_THM; SKOLEM_THM] THEN
2552   MAP_EVERY X_GEN_TAC
2553    [`a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`] THEN
2554   DISCH_THEN(ASSUME_TAC o GSYM) THEN
2555   SUBGOAL_THEN
2556    `!h. h IN f /\ ~(affine hull s SUBSET h)
2557         ==> ?a' b'. ~(a' = vec 0) /\
2558                   affine hull s INTER {x:real^N | a' dot x <= b'} =
2559                   affine hull s INTER h /\
2560                   !w. w IN affine hull s ==> (w + a') IN affine hull s`
2561   MP_TAC THENL
2562    [GEN_TAC THEN STRIP_TAC THEN
2563     FIRST_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
2564     REWRITE_TAC[ASSUME `(h:real^N->bool) IN f`] THEN
2565     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC o GSYM) THEN
2566     MP_TAC(ISPECL [`affine hull s:real^N->bool`;
2567                    `(a:(real^N->bool)->real^N) h`;
2568                    `(b:(real^N->bool)->real) h`]
2569                 AFFINE_PARALLEL_SLICE) THEN
2570     REWRITE_TAC[AFFINE_AFFINE_HULL] THEN MATCH_MP_TAC(TAUT
2571      `~p /\ ~q /\ (r ==> r') ==> (p \/ q \/ r ==> r')`) THEN
2572     ASM_SIMP_TAC[] THEN CONJ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
2573     DISCH_TAC THEN
2574     UNDISCH_TAC `~(s:real^N->bool = {})` THEN
2575     EXPAND_TAC "s" THEN REWRITE_TAC[GSYM INTERS_INSERT] THEN
2576     MATCH_MP_TAC(SET_RULE
2577      `!t. t SUBSET s /\ INTERS t = {} ==> INTERS s = {}`) THEN
2578     EXISTS_TAC `{affine hull s,h:real^N->bool}` THEN
2579     ASM_REWRITE_TAC[INTERS_2] THEN ASM SET_TAC[];
2580     ALL_TAC] THEN
2581   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
2582   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
2583   FIRST_X_ASSUM(K ALL_TAC o SPEC `{}:real^N->bool`) THEN
2584   MAP_EVERY X_GEN_TAC
2585     [`a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`] THEN
2586   DISCH_TAC THEN
2587   EXISTS_TAC `IMAGE (\h:real^N->bool. {x:real^N | a h dot x <= b h})
2588                     {h | h IN f /\ ~(affine hull s SUBSET h)}` THEN
2589   ASM_SIMP_TAC[FINITE_IMAGE; FINITE_RESTRICT; FORALL_IN_IMAGE] THEN
2590   REWRITE_TAC[FORALL_IN_GSPEC] THEN CONJ_TAC THENL
2591    [ALL_TAC;
2592     X_GEN_TAC `h:real^N->bool` THEN STRIP_TAC THEN
2593     MAP_EVERY EXISTS_TAC
2594      [`(a:(real^N->bool)->real^N) h`; `(b:(real^N->bool)->real) h`] THEN
2595     ASM_MESON_TAC[]] THEN
2596   FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [GSYM th]) THEN
2597   GEN_REWRITE_TAC I [EXTENSION] THEN X_GEN_TAC `x:real^N` THEN
2598   REWRITE_TAC[INTERS_IMAGE; IN_INTER; IN_ELIM_THM] THEN
2599   ASM_CASES_TAC `(x:real^N) IN affine hull s` THEN
2600   ASM_REWRITE_TAC[IN_INTERS] THEN AP_TERM_TAC THEN ABS_TAC THEN
2601   ASM SET_TAC[]);;
2602
2603 let POLYHEDRON_INTER_AFFINE_PARALLEL_MINIMAL = prove
2604  (`!s. polyhedron s <=>
2605         ?f. FINITE f /\
2606             s = (affine hull s) INTER (INTERS f) /\
2607             (!h. h IN f
2608                  ==> ?a b. ~(a = vec 0) /\ h = {x:real^N | a dot x <= b} /\
2609                            (!x. x IN affine hull s
2610                                 ==> (x + a) IN affine hull s)) /\
2611             !f'. f' PSUBSET f ==> s PSUBSET (affine hull s) INTER (INTERS f')`,
2612   GEN_TAC THEN REWRITE_TAC[POLYHEDRON_INTER_AFFINE_PARALLEL] THEN
2613   EQ_TAC THENL [ALL_TAC; MATCH_MP_TAC MONO_EXISTS THEN MESON_TAC[]] THEN
2614   GEN_REWRITE_TAC LAND_CONV
2615    [MESON[HAS_SIZE]
2616      `(?f. FINITE f /\ P f) <=> (?n f. f HAS_SIZE n /\ P f)`] THEN
2617   GEN_REWRITE_TAC LAND_CONV [num_WOP] THEN
2618   DISCH_THEN(X_CHOOSE_THEN `n:num` (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC)) THEN
2619   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[HAS_SIZE] THEN
2620   X_GEN_TAC `f:(real^N->bool)->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
2621   CONJ_TAC THENL [FIRST_ASSUM ACCEPT_TAC; ALL_TAC] THEN
2622   X_GEN_TAC `f':(real^N->bool)->bool` THEN DISCH_TAC THEN
2623   FIRST_X_ASSUM(MP_TAC o SPEC `CARD(f':(real^N->bool)->bool)`) THEN
2624   ANTS_TAC THENL [ASM_MESON_TAC[CARD_PSUBSET]; ALL_TAC] THEN
2625   REWRITE_TAC[NOT_EXISTS_THM; HAS_SIZE] THEN
2626   DISCH_THEN(MP_TAC o SPEC `f':(real^N->bool)->bool`) THEN
2627   MATCH_MP_TAC(TAUT `a /\ c /\ (~b ==> d) ==> ~(a /\ b /\ c) ==> d`) THEN
2628   CONJ_TAC THENL [ASM_MESON_TAC[PSUBSET; FINITE_SUBSET]; ALL_TAC] THEN
2629   CONJ_TAC THENL
2630    [REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM SET_TAC[];
2631     MATCH_MP_TAC(SET_RULE `s SUBSET t ==> ~(s = t) ==> s PSUBSET t`) THEN
2632     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [th]) THEN
2633     ASM SET_TAC[]]);;
2634
2635 let POLYHEDRON_INTER_AFFINE_MINIMAL = prove
2636  (`!s. polyhedron s <=>
2637         ?f. FINITE f /\
2638             s = (affine hull s) INTER (INTERS f) /\
2639             (!h. h IN f
2640                  ==> ?a b. ~(a = vec 0) /\ h = {x:real^N | a dot x <= b}) /\
2641             !f'. f' PSUBSET f ==> s PSUBSET (affine hull s) INTER (INTERS f')`,
2642   GEN_TAC THEN EQ_TAC THENL
2643    [REWRITE_TAC[POLYHEDRON_INTER_AFFINE_PARALLEL_MINIMAL];
2644     REWRITE_TAC[POLYHEDRON_INTER_AFFINE]] THEN
2645   MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN MESON_TAC[]);;
2646
2647 let RELATIVE_INTERIOR_POLYHEDRON_EXPLICIT = prove
2648  (`!s:real^N->bool f a b.
2649         FINITE f /\
2650         s = affine hull s INTER INTERS f /\
2651         (!h. h IN f ==> ~(a h = vec 0) /\ h = {x | a h dot x <= b h}) /\
2652         (!f'. f' PSUBSET f ==> s PSUBSET affine hull s INTER INTERS f')
2653         ==> relative_interior s =
2654                 {x | x IN s /\ !h. h IN f ==> a h dot x < b h}`,
2655   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2656   DISCH_THEN(CONJUNCTS_THEN2 (ASSUME_TAC o SYM) STRIP_ASSUME_TAC) THEN
2657   GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[IN_ELIM_THM] THEN
2658   X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
2659    [ALL_TAC;
2660     STRIP_TAC THEN ASM_REWRITE_TAC[RELATIVE_INTERIOR; IN_ELIM_THM] THEN
2661     EXISTS_TAC `INTERS {interior h | (h:real^N->bool) IN f}` THEN
2662     ASM_SIMP_TAC[SIMPLE_IMAGE; OPEN_INTERS; FINITE_IMAGE; OPEN_INTERIOR;
2663                  FORALL_IN_IMAGE; IN_INTERS] THEN
2664     CONJ_TAC THENL
2665      [X_GEN_TAC `h:real^N->bool` THEN DISCH_TAC THEN
2666       REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`)) THEN
2667       ASM_REWRITE_TAC[] THEN REPEAT DISCH_TAC THEN
2668       FIRST_ASSUM(SUBST1_TAC o CONJUNCT2) THEN
2669       ASM_SIMP_TAC[INTERIOR_HALFSPACE_LE; IN_ELIM_THM];
2670       FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [SYM th]) THEN
2671       MATCH_MP_TAC(SET_RULE
2672        `(!s. s IN f ==> i s SUBSET s)
2673         ==> INTERS (IMAGE i f) INTER t SUBSET t INTER INTERS f`) THEN
2674       REWRITE_TAC[INTERIOR_SUBSET]]] THEN
2675   DISCH_TAC THEN
2676   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR]) THEN
2677   DISCH_TAC THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `i:real^N->bool` THEN
2678   DISCH_TAC THEN
2679   FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (i:real^N->bool)`) THEN ANTS_TAC THENL
2680    [ASM SET_TAC[];
2681     REWRITE_TAC[PSUBSET_ALT; IN_INTER; IN_INTERS; IN_DELETE]] THEN
2682   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2683   DISCH_THEN(X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC) THEN
2684   SUBGOAL_THEN `(a:(real^N->bool)->real^N) i dot z > b i` ASSUME_TAC THENL
2685    [UNDISCH_TAC `~((z:real^N) IN s)` THEN
2686     FIRST_ASSUM(SUBST1_TAC o SYM) THEN REWRITE_TAC[IN_INTER; IN_INTERS] THEN
2687     ASM_REWRITE_TAC[REAL_ARITH `a:real > b <=> ~(a <= b)`] THEN ASM SET_TAC[];
2688     ALL_TAC] THEN
2689   SUBGOAL_THEN `~(z:real^N = x)` ASSUME_TAC THENL
2690    [ASM_MESON_TAC[]; ALL_TAC] THEN
2691   SUBGOAL_THEN
2692    `?l. &0 < l /\ l < &1 /\ (l % z + (&1 - l) % x:real^N) IN s`
2693   STRIP_ASSUME_TAC THENL
2694    [FIRST_ASSUM(X_CHOOSE_THEN `e:real` MP_TAC o CONJUNCT2) THEN
2695     REWRITE_TAC[SUBSET; IN_INTER; IN_BALL; dist] THEN STRIP_TAC THEN
2696     EXISTS_TAC `min (&1 / &2) (e / &2 / norm(z - x:real^N))` THEN
2697     REWRITE_TAC[REAL_MIN_LT; REAL_LT_MIN] THEN
2698     CONV_TAC REAL_RAT_REDUCE_CONV THEN
2699     ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ] THEN
2700     FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
2701      [REWRITE_TAC[VECTOR_ARITH
2702        `x - (l % z + (&1 - l) % x):real^N = --l % (z - x)`] THEN
2703       REWRITE_TAC[NORM_MUL; REAL_ABS_NEG] THEN
2704       ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
2705       MATCH_MP_TAC(REAL_ARITH
2706        `&0 < a /\ &0 < b /\ b < c ==> abs(min a b) < c`) THEN
2707       ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ] THEN
2708       REWRITE_TAC[REAL_LT_01; real_div; REAL_MUL_ASSOC] THEN
2709       MATCH_MP_TAC REAL_LT_RMUL THEN
2710       ASM_REWRITE_TAC[REAL_LT_INV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
2711       UNDISCH_TAC `&0 < e` THEN REAL_ARITH_TAC;
2712       ONCE_REWRITE_TAC[VECTOR_ADD_SYM] THEN
2713       MATCH_MP_TAC(REWRITE_RULE[AFFINE_ALT] AFFINE_AFFINE_HULL) THEN
2714       ASM SET_TAC[]];
2715     ALL_TAC] THEN
2716   MATCH_MP_TAC REAL_LT_RCANCEL_IMP THEN EXISTS_TAC `&1 - l` THEN
2717   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
2718   REWRITE_TAC[REAL_ARITH `a < b * (&1 - l) <=> l * b + a < b`] THEN
2719   MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC
2720    `l * (a:(real^N->bool)->real^N) i dot z + (a i dot x) * (&1 - l)` THEN
2721   ASM_SIMP_TAC[REAL_LT_RADD; REAL_LT_LMUL_EQ; GSYM real_gt] THEN
2722   ONCE_REWRITE_TAC[REAL_ARITH `a * (&1 - b) = (&1 - b) * a`] THEN
2723   REWRITE_TAC[GSYM DOT_RMUL; GSYM DOT_RADD] THEN ASM SET_TAC[]);;
2724
2725 let FACET_OF_POLYHEDRON_EXPLICIT = prove
2726  (`!s:real^N->bool f a b.
2727         FINITE f /\
2728         s = affine hull s INTER INTERS f /\
2729         (!h. h IN f ==> ~(a h = vec 0) /\ h = {x | a h dot x <= b h}) /\
2730         (!f'. f' PSUBSET f ==> s PSUBSET affine hull s INTER INTERS f')
2731         ==> !c. c facet_of s <=>
2732                 ?h. h IN f /\ c = s INTER {x | a h dot x = b h}`,
2733   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
2734    [ASM_REWRITE_TAC[INTER_EMPTY; AFFINE_HULL_EMPTY; SET_RULE `~(s PSUBSET s)`;
2735                     FACET_OF_EMPTY] THEN
2736     ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
2737     ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
2738     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
2739     DISCH_THEN(X_CHOOSE_TAC `h:real^N->bool`) THEN DISCH_THEN
2740      (MP_TAC o SPEC `f DELETE (h:real^N->bool)` o last o CONJUNCTS) THEN
2741     ASM SET_TAC[];
2742     STRIP_TAC] THEN
2743   SUBGOAL_THEN `polyhedron(s:real^N->bool)` ASSUME_TAC THENL
2744    [REWRITE_TAC[POLYHEDRON_INTER_AFFINE] THEN
2745     REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN ASM_MESON_TAC[];
2746     ALL_TAC] THEN
2747   FIRST_ASSUM(ASSUME_TAC o MATCH_MP POLYHEDRON_IMP_CONVEX) THEN
2748   SUBGOAL_THEN
2749    `!h:real^N->bool.
2750        h IN f ==> (s INTER {x:real^N | a h dot x = b h}) facet_of s`
2751   (LABEL_TAC "face") THENL
2752    [REPEAT STRIP_TAC THEN REWRITE_TAC[facet_of] THEN CONJ_TAC THENL
2753      [MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN
2754       CONJ_TAC THENL
2755        [MATCH_MP_TAC POLYHEDRON_IMP_CONVEX THEN
2756         REWRITE_TAC[POLYHEDRON_INTER_AFFINE] THEN
2757         REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN ASM_MESON_TAC[];
2758         X_GEN_TAC `x:real^N` THEN FIRST_X_ASSUM SUBST1_TAC THEN
2759         REWRITE_TAC[IN_INTER; IN_INTERS] THEN
2760         DISCH_THEN(MP_TAC o SPEC `h:real^N->bool` o CONJUNCT2) THEN
2761         ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
2762         FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
2763         ASM_REWRITE_TAC[] THEN ASM SET_TAC[]];
2764       ALL_TAC] THEN
2765     MP_TAC(ISPEC `s:real^N->bool` RELATIVE_INTERIOR_EQ_EMPTY) THEN
2766     ASM_SIMP_TAC[] THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
2767     DISCH_THEN(X_CHOOSE_TAC `x:real^N`) THEN
2768     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_RELATIVE_INTERIOR]) THEN
2769     DISCH_TAC THEN
2770     FIRST_ASSUM(MP_TAC o SPEC `f DELETE (h:real^N->bool)`) THEN
2771     ANTS_TAC THENL
2772      [ASM SET_TAC[];
2773       REWRITE_TAC[PSUBSET_ALT; IN_INTER; IN_INTERS; IN_DELETE]] THEN
2774     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2775     DISCH_THEN(X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC) THEN
2776     SUBGOAL_THEN `(a:(real^N->bool)->real^N) h dot z > b h` ASSUME_TAC THENL
2777      [UNDISCH_TAC `~((z:real^N) IN s)` THEN
2778       FIRST_ASSUM(SUBST1_TAC o SYM) THEN
2779       REWRITE_TAC[IN_INTER; IN_INTERS] THEN
2780       ASM_REWRITE_TAC[REAL_ARITH `a:real > b <=> ~(a <= b)`] THEN
2781       ASM SET_TAC[];
2782       ALL_TAC] THEN
2783     SUBGOAL_THEN `~(z:real^N = x)` ASSUME_TAC THENL
2784      [ASM_MESON_TAC[]; ALL_TAC] THEN
2785     MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
2786                    `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
2787            RELATIVE_INTERIOR_POLYHEDRON_EXPLICIT) THEN
2788     ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
2789      [FIRST_ASSUM ACCEPT_TAC; ALL_TAC] THEN
2790     GEN_REWRITE_TAC LAND_CONV [EXTENSION] THEN
2791     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
2792     ASM_REWRITE_TAC[IN_ELIM_THM] THEN
2793     DISCH_THEN(fun th ->
2794       MP_TAC(SPEC `h:real^N->bool` th) THEN ASM_REWRITE_TAC[] THEN
2795       DISCH_TAC THEN ASSUME_TAC th) THEN
2796     SUBGOAL_THEN `(a:(real^N->bool)->real^N) h dot x < a h dot z`
2797     ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
2798     ABBREV_TAC `l = (b h - (a:(real^N->bool)->real^N) h dot x) /
2799                     (a h dot z - a h dot x)` THEN
2800     SUBGOAL_THEN `&0 < l /\ l < &1` STRIP_ASSUME_TAC THENL
2801      [EXPAND_TAC "l" THEN
2802       ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_SUB_LT] THEN
2803       ASM_REAL_ARITH_TAC;
2804       ALL_TAC] THEN
2805     ABBREV_TAC `w:real^N = (&1 - l) % x + l % z:real^N` THEN
2806     SUBGOAL_THEN
2807      `!i. i IN f /\ ~(i = h) ==> (a:(real^N->bool)->real^N) i dot w < b i`
2808     ASSUME_TAC THENL
2809      [X_GEN_TAC `i:real^N->bool` THEN STRIP_TAC THEN EXPAND_TAC "w" THEN
2810       REWRITE_TAC[DOT_RADD; DOT_RMUL] THEN
2811       MATCH_MP_TAC(REAL_ARITH
2812        `(&1 - l) * x < (&1 - l) * z /\ l * y <= l * z
2813         ==> (&1 - l) * x + l * y < z`) THEN
2814       ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_LT_IMP_LE;
2815                    REAL_LT_LMUL_EQ; REAL_SUB_LT] THEN
2816       UNDISCH_TAC `!t:real^N->bool. t IN f /\ ~(t = h) ==> z IN t` THEN
2817       DISCH_THEN(MP_TAC o SPEC `i:real^N->bool`) THEN ASM SET_TAC[];
2818       ALL_TAC] THEN
2819     SUBGOAL_THEN `(a:(real^N->bool)->real^N) h dot w = b h` ASSUME_TAC THENL
2820      [EXPAND_TAC "w" THEN REWRITE_TAC[VECTOR_ARITH
2821          `(&1 - l) % x + l % z:real^N = x + l % (z - x)`] THEN
2822       EXPAND_TAC "l" THEN REWRITE_TAC[DOT_RADD; DOT_RSUB; DOT_RMUL] THEN
2823       ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_LT_IMP_NE; REAL_SUB_0] THEN
2824       REAL_ARITH_TAC;
2825       ALL_TAC] THEN
2826     SUBGOAL_THEN `(w:real^N) IN s` ASSUME_TAC THENL
2827      [FIRST_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [th]) THEN
2828       REWRITE_TAC[IN_INTER; IN_INTERS] THEN CONJ_TAC THENL
2829        [EXPAND_TAC "w" THEN
2830         MATCH_MP_TAC(REWRITE_RULE[AFFINE_ALT] AFFINE_AFFINE_HULL) THEN
2831         ASM_REWRITE_TAC[] THEN MATCH_MP_TAC HULL_INC THEN
2832         ASM_MESON_TAC[RELATIVE_INTERIOR_SUBSET; SUBSET];
2833         ALL_TAC] THEN
2834       X_GEN_TAC `i:real^N->bool` THEN DISCH_TAC THEN
2835       ASM_CASES_TAC `i:real^N->bool = h` THENL
2836        [ASM SET_TAC[REAL_LE_REFL]; ALL_TAC] THEN
2837       SUBGOAL_THEN `convex(i:real^N->bool)` MP_TAC THENL
2838        [REPEAT(FIRST_X_ASSUM(MP_TAC o C MATCH_MP
2839          (ASSUME `(i:real^N->bool) IN f`))) THEN
2840         REPEAT(DISCH_THEN(fun th -> ONCE_REWRITE_TAC[th])) THEN
2841         REWRITE_TAC[CONVEX_HALFSPACE_LE];
2842         ALL_TAC] THEN
2843       REWRITE_TAC[CONVEX_ALT] THEN EXPAND_TAC "w" THEN
2844       DISCH_THEN MATCH_MP_TAC THEN
2845       ASM_SIMP_TAC[] THEN FIRST_X_ASSUM(MP_TAC o CONJUNCT1) THEN
2846       FIRST_ASSUM(fun t -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [t]) THEN
2847       REWRITE_TAC[IN_INTER; IN_INTERS] THEN ASM_SIMP_TAC[REAL_LT_IMP_LE];
2848       ALL_TAC] THEN
2849     CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
2850     ONCE_REWRITE_TAC[GSYM AFF_DIM_AFFINE_HULL] THEN
2851     SUBGOAL_THEN
2852      `affine hull (s INTER {x | (a:(real^N->bool)->real^N) h dot x = b h}) =
2853       (affine hull s) INTER {x | a h dot x = b h}`
2854     SUBST1_TAC THENL
2855      [ALL_TAC;
2856       SIMP_TAC[AFF_DIM_AFFINE_INTER_HYPERPLANE; AFFINE_AFFINE_HULL] THEN
2857       COND_CASES_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
2858       COND_CASES_TAC THENL [ASM SET_TAC[REAL_LT_REFL]; REFL_TAC]] THEN
2859     MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET_INTER] THEN
2860     REPEAT CONJ_TAC THENL
2861      [MATCH_MP_TAC HULL_MONO THEN SET_TAC[];
2862       MATCH_MP_TAC(SET_RULE
2863        `s SUBSET affine hull t /\ affine hull t = t ==> s SUBSET t`) THEN
2864       REWRITE_TAC[AFFINE_HULL_EQ; AFFINE_HYPERPLANE] THEN
2865       MATCH_MP_TAC HULL_MONO THEN SET_TAC[];
2866       ALL_TAC] THEN
2867     REWRITE_TAC[SUBSET; IN_INTER; IN_ELIM_THM] THEN
2868     X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
2869     SUBGOAL_THEN
2870      `?t. &0 < t /\
2871           !j. j IN f /\ ~(j:real^N->bool = h)
2872               ==> t * (a j dot y - a j dot w) <= b j - a j dot (w:real^N)`
2873     STRIP_ASSUME_TAC THENL
2874      [ASM_CASES_TAC `f DELETE (h:real^N->bool) = {}` THENL
2875        [ASM_REWRITE_TAC[GSYM IN_DELETE; NOT_IN_EMPTY] THEN
2876         EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01];
2877         ALL_TAC] THEN
2878       EXISTS_TAC `inf (IMAGE
2879        (\j. if &0 < a j dot y - a j dot (w:real^N)
2880             then (b j - a j dot w) / (a j dot y - a j dot w)
2881             else &1) (f DELETE (h:real^N->bool)))` THEN
2882       MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
2883        [ASM_SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; FINITE_DELETE;
2884                      IMAGE_EQ_EMPTY; FORALL_IN_IMAGE; IN_DELETE] THEN
2885         ONCE_REWRITE_TAC[COND_RAND] THEN ONCE_REWRITE_TAC[COND_RATOR] THEN
2886         ASM_SIMP_TAC[REAL_LT_DIV; REAL_SUB_LT; REAL_LT_01; COND_ID];
2887         REWRITE_TAC[REAL_SUB_LT] THEN DISCH_TAC] THEN
2888       X_GEN_TAC `j:real^N->bool` THEN STRIP_TAC THEN
2889       ASM_CASES_TAC `a j dot (w:real^N) < a(j:real^N->bool) dot y` THENL
2890        [ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; REAL_INF_LE_FINITE; REAL_SUB_LT;
2891                      FINITE_IMAGE; FINITE_DELETE; IMAGE_EQ_EMPTY] THEN
2892         REWRITE_TAC[EXISTS_IN_IMAGE] THEN EXISTS_TAC `j:real^N->bool` THEN
2893         ASM_REWRITE_TAC[IN_DELETE; REAL_LE_REFL];
2894         MATCH_MP_TAC(REAL_ARITH `&0 <= --x /\ &0 < y ==> x <= y`) THEN
2895         ASM_SIMP_TAC[REAL_SUB_LT; GSYM REAL_MUL_RNEG; REAL_LE_MUL_EQ] THEN
2896         ASM_REAL_ARITH_TAC];
2897       ALL_TAC] THEN
2898     ABBREV_TAC `c:real^N = (&1 - t) % w + t % y` THEN
2899     SUBGOAL_THEN `y:real^N = (&1 - inv t) % w + inv(t) % c` SUBST1_TAC THENL
2900      [EXPAND_TAC "c" THEN
2901       REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC] THEN
2902       ASM_SIMP_TAC[REAL_MUL_LINV; REAL_LT_IMP_NZ;
2903                 REAL_FIELD `&0 < x ==> inv x * (&1 - x) = inv x - &1`] THEN
2904       VECTOR_ARITH_TAC;
2905       ALL_TAC] THEN
2906     MATCH_MP_TAC(REWRITE_RULE[AFFINE_ALT] AFFINE_AFFINE_HULL) THEN
2907     CONJ_TAC THEN MATCH_MP_TAC HULL_INC THEN
2908     ASM_REWRITE_TAC[IN_INTER; IN_ELIM_THM] THEN
2909     MATCH_MP_TAC(TAUT `b /\ (b ==> a) ==> a /\ b`) THEN CONJ_TAC THENL
2910      [EXPAND_TAC "c" THEN REWRITE_TAC[DOT_RADD; DOT_RMUL] THEN
2911       ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RING;
2912       DISCH_TAC] THEN
2913     FIRST_ASSUM(fun t -> GEN_REWRITE_TAC RAND_CONV [t]) THEN
2914     REWRITE_TAC[IN_INTER; IN_INTERS] THEN CONJ_TAC THENL
2915      [EXPAND_TAC "c" THEN
2916       MATCH_MP_TAC(REWRITE_RULE[AFFINE_ALT] AFFINE_AFFINE_HULL) THEN
2917       ASM_SIMP_TAC[HULL_INC];
2918       ALL_TAC] THEN
2919     X_GEN_TAC `j:real^N->bool` THEN DISCH_TAC THEN
2920     FIRST_X_ASSUM(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC o C MATCH_MP
2921       (ASSUME `(j:real^N->bool) IN f`)) THEN
2922     DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN
2923     ASM_CASES_TAC `j:real^N->bool = h` THEN ASM_SIMP_TAC[REAL_EQ_IMP_LE] THEN
2924     EXPAND_TAC "c" THEN REWRITE_TAC[DOT_RADD; DOT_RMUL] THEN
2925     REWRITE_TAC[REAL_ARITH
2926      `(&1 - t) * x + t * y <= z <=> t * (y - x) <= z - x`] THEN
2927     ASM_SIMP_TAC[];
2928     ALL_TAC] THEN
2929   X_GEN_TAC `c:real^N->bool` THEN EQ_TAC THENL
2930    [ALL_TAC; STRIP_TAC THEN ASM_SIMP_TAC[]] THEN
2931   REWRITE_TAC[facet_of] THEN STRIP_TAC THEN
2932   FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_CONVEX) THEN
2933   SUBGOAL_THEN `~(relative_interior(c:real^N->bool) = {})` MP_TAC THENL
2934    [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY]; ALL_TAC] THEN
2935   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
2936   DISCH_THEN(X_CHOOSE_TAC `x:real^N`) THEN
2937   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
2938                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
2939          RELATIVE_INTERIOR_POLYHEDRON_EXPLICIT) THEN
2940   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL [FIRST_ASSUM ACCEPT_TAC; ALL_TAC] THEN
2941   GEN_REWRITE_TAC LAND_CONV [EXTENSION] THEN
2942   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[IN_ELIM_THM] THEN
2943   SUBGOAL_THEN `~(c:real^N->bool = s)` ASSUME_TAC THENL
2944    [ASM_MESON_TAC[INT_ARITH`~(i:int = i - &1)`]; ALL_TAC] THEN
2945   SUBGOAL_THEN `~((x:real^N) IN relative_interior s)` ASSUME_TAC THENL
2946    [UNDISCH_TAC `~(c:real^N->bool = s)` THEN REWRITE_TAC[CONTRAPOS_THM] THEN
2947     DISCH_TAC THEN MATCH_MP_TAC FACE_OF_EQ THEN
2948     EXISTS_TAC `s:real^N->bool` THEN ASM_SIMP_TAC[FACE_OF_REFL] THEN
2949     ASM SET_TAC[];
2950     ALL_TAC] THEN
2951   SUBGOAL_THEN `(x:real^N) IN s` MP_TAC THENL
2952    [FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET] o MATCH_MP
2953        FACE_OF_IMP_SUBSET) THEN
2954     ASM_SIMP_TAC[REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET];
2955     ALL_TAC] THEN
2956   ASM_SIMP_TAC[] THEN DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
2957   FIRST_ASSUM(fun t -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [t]) THEN
2958   REWRITE_TAC[IN_INTER; IN_INTERS] THEN STRIP_TAC THEN
2959   REWRITE_TAC[NOT_FORALL_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
2960   X_GEN_TAC `i:real^N->bool` THEN REWRITE_TAC[NOT_IMP] THEN STRIP_TAC THEN
2961   ASM_REWRITE_TAC[] THEN
2962   SUBGOAL_THEN `(a:(real^N->bool)->real^N) i dot x = b i` ASSUME_TAC THENL
2963    [MATCH_MP_TAC(REAL_ARITH `x <= y /\ ~(x < y) ==> x = y`) THEN
2964     ASM_REWRITE_TAC[] THEN UNDISCH_THEN
2965      `!t:real^N->bool. t IN f ==> x IN t` (MP_TAC o SPEC `i:real^N->bool`) THEN
2966     ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MP_TAC o CONJUNCT2 o C MATCH_MP
2967      (ASSUME `(i:real^N->bool) IN f`)) THEN SET_TAC[];
2968     ALL_TAC] THEN
2969   SUBGOAL_THEN `c SUBSET (s INTER {x:real^N | a(i:real^N->bool) dot x = b i})`
2970   ASSUME_TAC THENL
2971    [MATCH_MP_TAC SUBSET_OF_FACE_OF THEN EXISTS_TAC `s:real^N->bool` THEN
2972     ASM_SIMP_TAC[FACE_OF_IMP_SUBSET] THEN
2973     RULE_ASSUM_TAC(REWRITE_RULE[facet_of]) THEN ASM_SIMP_TAC[] THEN
2974     REWRITE_TAC[DISJOINT; GSYM MEMBER_NOT_EMPTY] THEN
2975     EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[IN_INTER; IN_ELIM_THM];
2976     ALL_TAC] THEN
2977   SUBGOAL_THEN `c face_of (s INTER {x:real^N | a(i:real^N->bool) dot x = b i})`
2978   ASSUME_TAC THENL
2979    [MP_TAC(ISPECL [`c:real^N->bool`; `s:real^N->bool`;
2980                    `s INTER {x:real^N | a(i:real^N->bool) dot x = b i}`]
2981                 FACE_OF_FACE) THEN
2982     RULE_ASSUM_TAC(REWRITE_RULE[facet_of]) THEN ASM_SIMP_TAC[];
2983     ALL_TAC] THEN
2984   MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
2985   SUBGOAL_THEN
2986    `aff_dim(c:real^N->bool) <
2987     aff_dim(s INTER {x:real^N | a(i:real^N->bool) dot x = b i})`
2988   MP_TAC THENL
2989    [MATCH_MP_TAC FACE_OF_AFF_DIM_LT THEN
2990     ASM_SIMP_TAC[CONVEX_INTER; CONVEX_HYPERPLANE];
2991     RULE_ASSUM_TAC(REWRITE_RULE[facet_of]) THEN ASM_SIMP_TAC[INT_LT_REFL]]);;
2992
2993 let FACE_OF_POLYHEDRON_SUBSET_EXPLICIT = prove
2994  (`!s:real^N->bool f a b.
2995         FINITE f /\
2996         s = affine hull s INTER INTERS f /\
2997         (!h. h IN f ==> ~(a h = vec 0) /\ h = {x | a h dot x <= b h}) /\
2998         (!f'. f' PSUBSET f ==> s PSUBSET affine hull s INTER INTERS f')
2999         ==> !c. c face_of s /\ ~(c = {}) /\ ~(c = s)
3000                 ==> ?h. h IN f /\ c SUBSET (s INTER {x | a h dot x = b h})`,
3001   REPEAT GEN_TAC THEN ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
3002    [DISCH_THEN(MP_TAC o SYM o CONJUNCT1 o CONJUNCT2) THEN
3003     ASM_REWRITE_TAC[INTERS_0; INTER_UNIV; AFFINE_HULL_EQ] THEN
3004     MESON_TAC[FACE_OF_AFFINE_TRIVIAL];
3005     ALL_TAC] THEN
3006   DISCH_THEN(fun th -> STRIP_ASSUME_TAC th THEN MP_TAC th) THEN
3007   DISCH_THEN(ASSUME_TAC o MATCH_MP FACET_OF_POLYHEDRON_EXPLICIT) THEN
3008   REPEAT STRIP_TAC THEN
3009   FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_CONVEX) THEN
3010   FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_SUBSET) THEN
3011   SUBGOAL_THEN `polyhedron(s:real^N->bool)` ASSUME_TAC THENL
3012    [REWRITE_TAC[POLYHEDRON_INTER_AFFINE] THEN
3013     REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN ASM_MESON_TAC[];
3014     ALL_TAC] THEN
3015   FIRST_ASSUM(ASSUME_TAC o MATCH_MP POLYHEDRON_IMP_CONVEX) THEN
3016   SUBGOAL_THEN
3017    `!h:real^N->bool.
3018         h IN f ==> (s INTER {x:real^N | a h dot x = b h}) face_of s`
3019   ASSUME_TAC THENL
3020    [REPEAT STRIP_TAC THEN
3021     MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN CONJ_TAC THENL
3022      [MATCH_MP_TAC POLYHEDRON_IMP_CONVEX THEN
3023       REWRITE_TAC[POLYHEDRON_INTER_AFFINE] THEN
3024       REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN ASM_MESON_TAC[];
3025       X_GEN_TAC `x:real^N` THEN FIRST_X_ASSUM SUBST1_TAC THEN
3026       REWRITE_TAC[IN_INTER; IN_INTERS] THEN
3027       DISCH_THEN(MP_TAC o SPEC `h:real^N->bool` o CONJUNCT2) THEN
3028       ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
3029       FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
3030       ASM_REWRITE_TAC[] THEN ASM SET_TAC[]];
3031     ALL_TAC] THEN
3032   SUBGOAL_THEN `~(relative_interior(c:real^N->bool) = {})` MP_TAC THENL
3033    [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY]; ALL_TAC] THEN
3034   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
3035   DISCH_THEN(X_CHOOSE_TAC `x:real^N`) THEN
3036   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3037                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3038          RELATIVE_INTERIOR_POLYHEDRON_EXPLICIT) THEN
3039   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL [FIRST_ASSUM ACCEPT_TAC; ALL_TAC] THEN
3040   GEN_REWRITE_TAC LAND_CONV [EXTENSION] THEN
3041   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[IN_ELIM_THM] THEN
3042   SUBGOAL_THEN `~((x:real^N) IN relative_interior s)` ASSUME_TAC THENL
3043    [UNDISCH_TAC `~(c:real^N->bool = s)` THEN REWRITE_TAC[CONTRAPOS_THM] THEN
3044     DISCH_TAC THEN MATCH_MP_TAC FACE_OF_EQ THEN
3045     EXISTS_TAC `s:real^N->bool` THEN ASM_SIMP_TAC[FACE_OF_REFL] THEN
3046     ASM SET_TAC[];
3047     ALL_TAC] THEN
3048   SUBGOAL_THEN `(x:real^N) IN s` MP_TAC THENL
3049    [FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET] o MATCH_MP
3050        FACE_OF_IMP_SUBSET) THEN
3051     ASM_SIMP_TAC[REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET];
3052     ALL_TAC] THEN
3053   ASM_SIMP_TAC[] THEN DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
3054   FIRST_ASSUM(fun t -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [t]) THEN
3055   REWRITE_TAC[IN_INTER; IN_INTERS] THEN STRIP_TAC THEN
3056   REWRITE_TAC[NOT_FORALL_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
3057   X_GEN_TAC `i:real^N->bool` THEN REWRITE_TAC[NOT_IMP] THEN STRIP_TAC THEN
3058   ASM_REWRITE_TAC[] THEN
3059   SUBGOAL_THEN `(a:(real^N->bool)->real^N) i dot x = b i` ASSUME_TAC THENL
3060    [MATCH_MP_TAC(REAL_ARITH `x <= y /\ ~(x < y) ==> x = y`) THEN
3061     ASM_REWRITE_TAC[] THEN UNDISCH_THEN
3062      `!t:real^N->bool. t IN f ==> x IN t` (MP_TAC o SPEC `i:real^N->bool`) THEN
3063     ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MP_TAC o CONJUNCT2 o C MATCH_MP
3064      (ASSUME `(i:real^N->bool) IN f`)) THEN SET_TAC[];
3065     ALL_TAC] THEN
3066   MATCH_MP_TAC SUBSET_OF_FACE_OF THEN EXISTS_TAC `s:real^N->bool` THEN
3067   ASM_SIMP_TAC[FACE_OF_IMP_SUBSET] THEN
3068   RULE_ASSUM_TAC(REWRITE_RULE[facet_of]) THEN ASM_SIMP_TAC[] THEN
3069   REWRITE_TAC[DISJOINT; GSYM MEMBER_NOT_EMPTY] THEN
3070   EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[IN_INTER; IN_ELIM_THM]);;
3071
3072 let FACE_OF_POLYHEDRON_EXPLICIT = prove
3073  (`!s:real^N->bool f a b.
3074         FINITE f /\
3075         s = affine hull s INTER INTERS f /\
3076         (!h. h IN f ==> ~(a h = vec 0) /\ h = {x | a h dot x <= b h}) /\
3077         (!f'. f' PSUBSET f ==> s PSUBSET affine hull s INTER INTERS f')
3078         ==> !c. c face_of s /\ ~(c = {}) /\ ~(c = s)
3079                 ==> c = INTERS {s INTER {x | a h dot x = b h} |h|
3080                                 h IN f /\
3081                                 c SUBSET (s INTER {x | a h dot x = b h})}`,
3082   let lemma = prove
3083    (`!t s. (!a. P a ==> t SUBSET s INTER INTERS {f x | P x})
3084            ==> t SUBSET INTERS {s INTER f x | P x}`,
3085     ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN
3086     REWRITE_TAC[INTERS_IMAGE] THEN SET_TAC[]) in
3087   REPEAT GEN_TAC THEN
3088   DISCH_THEN(fun th -> STRIP_ASSUME_TAC th THEN MP_TAC th) THEN
3089   DISCH_THEN(ASSUME_TAC o MATCH_MP FACET_OF_POLYHEDRON_EXPLICIT) THEN
3090   REPEAT STRIP_TAC THEN
3091   FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_CONVEX) THEN
3092   FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_SUBSET) THEN
3093   SUBGOAL_THEN `polyhedron(s:real^N->bool)` ASSUME_TAC THENL
3094    [REWRITE_TAC[POLYHEDRON_INTER_AFFINE] THEN
3095     REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN ASM_MESON_TAC[];
3096     ALL_TAC] THEN
3097   FIRST_ASSUM(ASSUME_TAC o MATCH_MP POLYHEDRON_IMP_CONVEX) THEN
3098   SUBGOAL_THEN
3099    `!h:real^N->bool.
3100         h IN f ==> (s INTER {x:real^N | a h dot x = b h}) face_of s`
3101   ASSUME_TAC THENL
3102    [REPEAT STRIP_TAC THEN
3103     MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN CONJ_TAC THENL
3104      [MATCH_MP_TAC POLYHEDRON_IMP_CONVEX THEN
3105       REWRITE_TAC[POLYHEDRON_INTER_AFFINE] THEN
3106       REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN ASM_MESON_TAC[];
3107       X_GEN_TAC `x:real^N` THEN FIRST_X_ASSUM SUBST1_TAC THEN
3108       REWRITE_TAC[IN_INTER; IN_INTERS] THEN
3109       DISCH_THEN(MP_TAC o SPEC `h:real^N->bool` o CONJUNCT2) THEN
3110       ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
3111       FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
3112       ASM_REWRITE_TAC[] THEN ASM SET_TAC[]];
3113     ALL_TAC] THEN
3114   SUBGOAL_THEN `~(relative_interior(c:real^N->bool) = {})` MP_TAC THENL
3115    [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY]; ALL_TAC] THEN
3116   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN
3117   X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN
3118   SUBGOAL_THEN `(z:real^N) IN s` ASSUME_TAC THENL
3119    [FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET]) THEN
3120     MATCH_MP_TAC(REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET) THEN
3121     ASM_REWRITE_TAC[];
3122     ALL_TAC] THEN
3123   MATCH_MP_TAC FACE_OF_EQ THEN EXISTS_TAC `s:real^N->bool` THEN
3124   ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
3125    [MATCH_MP_TAC FACE_OF_INTERS THEN ASM_SIMP_TAC[FORALL_IN_GSPEC] THEN
3126     ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN REWRITE_TAC[IMAGE_EQ_EMPTY] THEN
3127     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
3128     MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3129                    `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3130          FACE_OF_POLYHEDRON_SUBSET_EXPLICIT) THEN
3131     ASM_REWRITE_TAC[] THEN ANTS_TAC THENL[FIRST_ASSUM ACCEPT_TAC; ALL_TAC] THEN
3132     DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[];
3133     ALL_TAC] THEN
3134   SUBGOAL_THEN
3135    `{s INTER {x | a(h:real^N->bool) dot x = b h} |h|
3136      h IN f /\ c SUBSET (s INTER {x:real^N | a h dot x = b h})} =
3137     {s INTER {x | a(h:real^N->bool) dot x = b h} |h|
3138      h IN f /\ z IN s INTER {x:real^N | a h dot x = b h}}`
3139   SUBST1_TAC THENL
3140    [MATCH_MP_TAC(SET_RULE
3141      `(!x. P x <=> Q x) ==> {f x | P x} = {f x | Q x}`) THEN
3142     X_GEN_TAC `h:real^N->bool` THEN EQ_TAC THEN STRIP_TAC THEN
3143     ASM_REWRITE_TAC[] THENL
3144      [FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET]) THEN
3145       MATCH_MP_TAC(REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET) THEN
3146       ASM_REWRITE_TAC[];
3147       MATCH_MP_TAC SUBSET_OF_FACE_OF THEN EXISTS_TAC `s:real^N->bool` THEN
3148       ASM_SIMP_TAC[] THEN ASM SET_TAC[]];
3149     ALL_TAC] THEN
3150   REWRITE_TAC[DISJOINT; GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN
3151   EXISTS_TAC `z:real^N` THEN ASM_REWRITE_TAC[IN_ELIM_THM] THEN
3152   SUBGOAL_THEN
3153    `?e. &0 < e /\ !h. h IN f /\ a(h:real^N->bool) dot z < b h
3154                       ==> ball(z,e) SUBSET {w:real^N | a h dot w < b h}`
3155   (CHOOSE_THEN (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "*"))) THENL
3156    [REWRITE_TAC[SET_RULE
3157      `(!h. P h ==> s SUBSET t h) <=> s SUBSET INTERS (IMAGE t {h | P h})`] THEN
3158     MATCH_MP_TAC(MESON[OPEN_CONTAINS_BALL]
3159      `open s /\ x IN s ==> ?e. &0 < e /\ ball(x,e) SUBSET s`) THEN
3160     SIMP_TAC[IN_INTERS; FORALL_IN_IMAGE; IN_ELIM_THM] THEN
3161     MATCH_MP_TAC OPEN_INTERS THEN
3162     ASM_SIMP_TAC[FORALL_IN_IMAGE; FINITE_IMAGE; FINITE_RESTRICT] THEN
3163     REWRITE_TAC[OPEN_HALFSPACE_LT];
3164     ALL_TAC] THEN
3165   ASM_REWRITE_TAC[IN_RELATIVE_INTERIOR] THEN
3166   ASM_SIMP_TAC[IN_INTERS; FORALL_IN_GSPEC; IN_ELIM_THM; IN_INTER] THEN
3167   EXISTS_TAC `e:real` THEN ASM_REWRITE_TAC[] THEN
3168   MATCH_MP_TAC lemma THEN X_GEN_TAC `i:real^N->bool` THEN STRIP_TAC THEN
3169   FIRST_ASSUM(fun th -> GEN_REWRITE_TAC (RAND_CONV o LAND_CONV) [th]) THEN
3170   MATCH_MP_TAC(SET_RULE
3171    `ae SUBSET as /\ ae SUBSET hs /\
3172     b INTER hs SUBSET fs
3173     ==> (b INTER ae) SUBSET (as INTER fs) INTER hs`) THEN
3174   REPEAT CONJ_TAC THENL
3175    [MATCH_MP_TAC HULL_MONO THEN
3176     REWRITE_TAC[SUBSET; IN_INTERS; FORALL_IN_GSPEC] THEN ASM SET_TAC[];
3177     SIMP_TAC[SET_RULE `s SUBSET INTERS f <=> !t. t IN f ==> s SUBSET t`] THEN
3178     REWRITE_TAC[FORALL_IN_GSPEC] THEN X_GEN_TAC `j:real^N->bool` THEN
3179     STRIP_TAC THEN MATCH_MP_TAC HULL_MINIMAL THEN
3180     REWRITE_TAC[AFFINE_HYPERPLANE] THEN
3181     REWRITE_TAC[SUBSET; IN_INTERS; FORALL_IN_GSPEC] THEN ASM SET_TAC[];
3182     ALL_TAC] THEN
3183   REWRITE_TAC[SET_RULE `s SUBSET INTERS f <=> !t. t IN f ==> s SUBSET t`] THEN
3184   X_GEN_TAC `j:real^N->bool` THEN DISCH_TAC THEN
3185   SUBGOAL_THEN `(a:(real^N->bool)->real^N) j dot z <= b j` MP_TAC THENL
3186    [ASM SET_TAC[]; REWRITE_TAC[REAL_LE_LT]] THEN
3187   STRIP_TAC THENL [ASM SET_TAC[REAL_LT_IMP_LE]; ALL_TAC] THEN
3188   MATCH_MP_TAC(SET_RULE
3189   `(?s. s IN f /\ s SUBSET t) ==> u INTER INTERS f SUBSET t`) THEN
3190   REWRITE_TAC[EXISTS_IN_GSPEC] THEN EXISTS_TAC `j:real^N->bool` THEN
3191   ASM SET_TAC[REAL_LE_REFL]);;
3192
3193 (* ------------------------------------------------------------------------- *)
3194 (* More general corollaries from the explicit representation.                *)
3195 (* ------------------------------------------------------------------------- *)
3196
3197 let FACET_OF_POLYHEDRON = prove
3198  (`!s:real^N->bool c.
3199         polyhedron s /\ c facet_of s
3200         ==> ?a b. ~(a = vec 0) /\
3201                   s SUBSET {x | a dot x <= b} /\
3202                   c = s INTER {x | a dot x = b}`,
3203   REPEAT STRIP_TAC THEN FIRST_ASSUM
3204    (MP_TAC o GEN_REWRITE_RULE I [POLYHEDRON_INTER_AFFINE_MINIMAL]) THEN
3205   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
3206    [RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
3207   SIMP_TAC[LEFT_IMP_EXISTS_THM; RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
3208   MAP_EVERY X_GEN_TAC
3209    [`f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
3210     `b:(real^N->bool)->real`] THEN
3211   STRIP_TAC THEN
3212   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3213                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3214         FACET_OF_POLYHEDRON_EXPLICIT) THEN
3215   ANTS_TAC THENL [ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
3216   DISCH_THEN(MP_TAC o SPEC `c:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
3217   DISCH_THEN(X_CHOOSE_THEN `i:real^N->bool` STRIP_ASSUME_TAC) THEN
3218   EXISTS_TAC `(a:(real^N->bool)->real^N) i` THEN
3219   EXISTS_TAC `(b:(real^N->bool)->real) i` THEN ASM_SIMP_TAC[] THEN
3220   FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [th]) THEN
3221   MATCH_MP_TAC(SET_RULE `t SUBSET u ==> (s INTER t) SUBSET u`) THEN
3222   MATCH_MP_TAC(SET_RULE `t IN f ==> INTERS f SUBSET t`) THEN ASM_MESON_TAC[]);;
3223
3224 let FACE_OF_POLYHEDRON = prove
3225  (`!s:real^N->bool c.
3226         polyhedron s /\ c face_of s /\ ~(c = {}) /\ ~(c = s)
3227         ==> c = INTERS {f | f facet_of s /\ c SUBSET f}`,
3228   REPEAT STRIP_TAC THEN FIRST_ASSUM
3229    (MP_TAC o GEN_REWRITE_RULE I [POLYHEDRON_INTER_AFFINE_MINIMAL]) THEN
3230   REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
3231   SIMP_TAC[LEFT_IMP_EXISTS_THM; RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
3232   MAP_EVERY X_GEN_TAC
3233    [`f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
3234     `b:(real^N->bool)->real`] THEN
3235   STRIP_TAC THEN
3236   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3237                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3238          FACET_OF_POLYHEDRON_EXPLICIT) THEN
3239   ANTS_TAC THENL [ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
3240   DISCH_THEN(fun th -> REWRITE_TAC[th]) THEN
3241   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3242                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3243          FACE_OF_POLYHEDRON_EXPLICIT) THEN
3244   ANTS_TAC THENL [ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
3245   DISCH_THEN(MP_TAC o SPEC `c:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
3246   DISCH_THEN(fun th -> GEN_REWRITE_TAC LAND_CONV [th]) THEN
3247   AP_TERM_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
3248   X_GEN_TAC `h:real^N->bool` THEN REWRITE_TAC[IN_ELIM_THM] THEN MESON_TAC[]);;
3249
3250 let FACE_OF_POLYHEDRON_SUBSET_FACET = prove
3251  (`!s:real^N->bool c.
3252         polyhedron s /\ c face_of s /\ ~(c = {}) /\ ~(c = s)
3253         ==> ?f. f facet_of s /\ c SUBSET f`,
3254   REPEAT STRIP_TAC THEN
3255   FIRST_ASSUM(ASSUME_TAC o MATCH_MP FACE_OF_IMP_SUBSET) THEN
3256   MP_TAC(ISPECL [`s:real^N->bool`; `c:real^N->bool`] FACE_OF_POLYHEDRON) THEN
3257   ASM_CASES_TAC `{f:real^N->bool | f facet_of s /\ c SUBSET f} = {}` THEN
3258   ASM SET_TAC[]);;
3259
3260 let EXPOSED_FACE_OF_POLYHEDRON = prove
3261  (`!s f:real^N->bool. polyhedron s ==> (f exposed_face_of s <=> f face_of s)`,
3262   REPEAT STRIP_TAC THEN EQ_TAC THENL [SIMP_TAC[exposed_face_of]; ALL_TAC] THEN
3263   DISCH_TAC THEN ASM_CASES_TAC `f:real^N->bool = {}` THEN
3264   ASM_REWRITE_TAC[EMPTY_EXPOSED_FACE_OF] THEN
3265   ASM_CASES_TAC `f:real^N->bool = s` THEN
3266   ASM_SIMP_TAC[EXPOSED_FACE_OF_REFL; POLYHEDRON_IMP_CONVEX] THEN
3267   MP_TAC(ISPECL [`s:real^N->bool`; `f:real^N->bool`] FACE_OF_POLYHEDRON) THEN
3268   ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST1_TAC THEN
3269   MATCH_MP_TAC EXPOSED_FACE_OF_INTERS THEN
3270   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; FORALL_IN_GSPEC] THEN
3271   ASM_SIMP_TAC[FACE_OF_POLYHEDRON_SUBSET_FACET; IN_ELIM_THM] THEN
3272   ASM_SIMP_TAC[exposed_face_of; FACET_OF_IMP_FACE_OF] THEN
3273   ASM_MESON_TAC[FACET_OF_POLYHEDRON]);;
3274
3275 let FACE_OF_POLYHEDRON_POLYHEDRON = prove
3276  (`!s:real^N->bool c. polyhedron s /\ c face_of s ==> polyhedron c`,
3277   REPEAT STRIP_TAC THEN FIRST_ASSUM
3278    (MP_TAC o GEN_REWRITE_RULE I [POLYHEDRON_INTER_AFFINE_MINIMAL]) THEN
3279   REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
3280   SIMP_TAC[LEFT_IMP_EXISTS_THM; RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
3281   MAP_EVERY X_GEN_TAC
3282    [`f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
3283     `b:(real^N->bool)->real`] THEN
3284   STRIP_TAC THEN
3285   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3286                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3287          FACE_OF_POLYHEDRON_EXPLICIT) THEN
3288   ANTS_TAC THENL [ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
3289   DISCH_THEN(MP_TAC o SPEC `c:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
3290   ASM_CASES_TAC `c:real^N->bool = {}` THEN
3291   ASM_REWRITE_TAC[POLYHEDRON_EMPTY] THEN
3292   ASM_CASES_TAC `c:real^N->bool = s` THEN ASM_REWRITE_TAC[] THEN
3293   DISCH_THEN SUBST1_TAC THEN MATCH_MP_TAC POLYHEDRON_INTERS THEN
3294   REWRITE_TAC[FORALL_IN_GSPEC] THEN
3295   ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN
3296   ASM_SIMP_TAC[FINITE_IMAGE; FINITE_RESTRICT] THEN
3297   REPEAT STRIP_TAC THEN REWRITE_TAC[IMAGE_ID] THEN
3298   MATCH_MP_TAC POLYHEDRON_INTER THEN
3299   ASM_REWRITE_TAC[POLYHEDRON_HYPERPLANE]);;
3300
3301 let FINITE_POLYHEDRON_FACES = prove
3302  (`!s:real^N->bool. polyhedron s ==> FINITE {f | f face_of s}`,
3303   REPEAT STRIP_TAC THEN FIRST_ASSUM
3304    (MP_TAC o GEN_REWRITE_RULE I [POLYHEDRON_INTER_AFFINE_MINIMAL]) THEN
3305   REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
3306   SIMP_TAC[LEFT_IMP_EXISTS_THM; RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
3307   MAP_EVERY X_GEN_TAC
3308    [`f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
3309     `b:(real^N->bool)->real`] THEN
3310   STRIP_TAC THEN
3311   MATCH_MP_TAC(MESON[FINITE_DELETE]
3312    `!a b. FINITE (s DELETE a DELETE b) ==> FINITE s`) THEN
3313   MAP_EVERY EXISTS_TAC [`{}:real^N->bool`; `s:real^N->bool`] THEN
3314   MATCH_MP_TAC FINITE_SUBSET THEN
3315   EXISTS_TAC
3316    `{INTERS {s INTER {x:real^N | a(h:real^N->bool) dot x = b h} | h | h IN f'}
3317     |f'| f' SUBSET f}` THEN
3318   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [SIMPLE_IMAGE_GEN] THEN
3319   ASM_SIMP_TAC[FINITE_POWERSET; FINITE_IMAGE] THEN
3320   GEN_REWRITE_TAC I [SUBSET] THEN REWRITE_TAC[IN_DELETE; IN_ELIM_THM] THEN
3321   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3322                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3323          FACE_OF_POLYHEDRON_EXPLICIT) THEN
3324   ANTS_TAC THENL [ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
3325   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `c:real^N->bool` THEN
3326   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
3327   DISCH_TAC THEN EXISTS_TAC
3328    `{h:real^N->bool |
3329      h IN f /\ c SUBSET s INTER {x:real^N | a h dot x = b h}}` THEN
3330   CONJ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
3331   ASM_REWRITE_TAC[IN_ELIM_THM] THEN FIRST_ASSUM ACCEPT_TAC);;
3332
3333 let FINITE_POLYHEDRON_EXPOSED_FACES = prove
3334  (`!s:real^N->bool. polyhedron s ==> FINITE {f | f exposed_face_of s}`,
3335   SIMP_TAC[EXPOSED_FACE_OF_POLYHEDRON; FINITE_POLYHEDRON_FACES]);;
3336
3337 let FINITE_POLYHEDRON_EXTREME_POINTS = prove
3338  (`!s:real^N->bool. polyhedron s ==> FINITE {v | v extreme_point_of s}`,
3339   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM FACE_OF_SING] THEN
3340   ONCE_REWRITE_TAC[SET_RULE `{v} face_of s <=> {v} IN {f | f face_of s}`] THEN
3341   MATCH_MP_TAC FINITE_FINITE_PREIMAGE THEN
3342   ASM_SIMP_TAC[FINITE_POLYHEDRON_FACES] THEN X_GEN_TAC `f:real^N->bool` THEN
3343   DISCH_TAC THEN ASM_CASES_TAC `!a:real^N. ~({a} = f)` THEN
3344   ASM_REWRITE_TAC[EMPTY_GSPEC; FINITE_EMPTY] THEN
3345   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_FORALL_THM]) THEN
3346   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
3347   GEN_TAC THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
3348   REWRITE_TAC[SET_RULE `{v | {v} = {a}} = {a}`; FINITE_SING]);;
3349
3350 let FINITE_POLYHEDRON_FACETS = prove
3351  (`!s:real^N->bool. polyhedron s ==> FINITE {f | f facet_of s}`,
3352   REWRITE_TAC[facet_of] THEN ONCE_REWRITE_TAC[SET_RULE
3353    `{x | P x /\ Q x} = {x | x IN {x | P x} /\ Q x}`] THEN
3354   SIMP_TAC[FINITE_RESTRICT; FINITE_POLYHEDRON_FACES]);;
3355
3356 let RELATIVE_INTERIOR_OF_POLYHEDRON = prove
3357  (`!s:real^N->bool.
3358         polyhedron s
3359         ==> relative_interior s = s DIFF UNIONS {f | f facet_of s}`,
3360   REPEAT STRIP_TAC THEN FIRST_ASSUM
3361    (MP_TAC o GEN_REWRITE_RULE I [POLYHEDRON_INTER_AFFINE_MINIMAL]) THEN
3362   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
3363    [RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
3364   SIMP_TAC[LEFT_IMP_EXISTS_THM; RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
3365   MAP_EVERY X_GEN_TAC
3366    [`f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
3367     `b:(real^N->bool)->real`] THEN
3368   STRIP_TAC THEN
3369   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3370                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3371         FACET_OF_POLYHEDRON_EXPLICIT) THEN
3372   MP_TAC(ISPECL [`s:real^N->bool`; `f:(real^N->bool)->bool`;
3373                  `a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`]
3374         RELATIVE_INTERIOR_POLYHEDRON_EXPLICIT) THEN
3375   ASM_REWRITE_TAC[] THEN
3376   ANTS_TAC THENL [ASM_MESON_TAC[]; DISCH_THEN SUBST1_TAC] THEN
3377   ANTS_TAC THENL [ASM_MESON_TAC[]; DISCH_TAC] THEN
3378   ASM_REWRITE_TAC[] THEN
3379   MATCH_MP_TAC(SET_RULE
3380    `(!x. x IN s ==> P x \/ x IN t) /\ (!x. x IN t ==> ~P x)
3381     ==> {x | x IN s /\ P x} = s DIFF t`) THEN
3382   REWRITE_TAC[FORALL_IN_UNIONS] THEN
3383   REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ; FORALL_IN_GSPEC] THEN
3384   CONJ_TAC THENL
3385    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
3386     REWRITE_TAC[IN_UNIONS; IN_ELIM_THM] THEN
3387     REWRITE_TAC[LEFT_AND_EXISTS_THM; TAUT `(a /\ b) /\ c <=> b /\ a /\ c`] THEN
3388     ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
3389     ASM_REWRITE_TAC[UNWIND_THM2; IN_ELIM_THM; IN_INTER] THEN
3390     MATCH_MP_TAC(SET_RULE
3391      `(!x. P x ==> Q x \/ R x) ==> (!x. P x ==> Q x) \/ (?x. P x /\ R x)`) THEN
3392     X_GEN_TAC `h:real^N->bool` THEN DISCH_TAC THEN
3393     REWRITE_TAC[GSYM REAL_LE_LT] THEN
3394     SUBGOAL_THEN `(x:real^N) IN INTERS f` MP_TAC THENL
3395      [ASM SET_TAC[]; ALL_TAC] THEN
3396     REWRITE_TAC[IN_INTERS] THEN
3397     DISCH_THEN(MP_TAC o SPEC `h:real^N->bool`) THEN
3398     SUBGOAL_THEN `h = {x:real^N | a h dot x <= b h}` MP_TAC THENL
3399      [ASM_MESON_TAC[]; ASM_REWRITE_TAC[] THEN SET_TAC[]];
3400     X_GEN_TAC `h:real^N->bool` THEN
3401     DISCH_THEN(X_CHOOSE_THEN `g:real^N->bool` STRIP_ASSUME_TAC) THEN
3402     X_GEN_TAC `x:real^N` THEN ASM_REWRITE_TAC[IN_INTER; IN_ELIM_THM] THEN
3403     ASM_MESON_TAC[REAL_LT_REFL]]);;
3404
3405 let RELATIVE_BOUNDARY_OF_POLYHEDRON = prove
3406  (`!s:real^N->bool.
3407         polyhedron s
3408         ==> s DIFF relative_interior s = UNIONS {f | f facet_of s}`,
3409   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[RELATIVE_INTERIOR_OF_POLYHEDRON] THEN
3410   MATCH_MP_TAC(SET_RULE `f SUBSET s ==> s DIFF (s DIFF f) = f`) THEN
3411   REWRITE_TAC[SUBSET; FORALL_IN_UNIONS; IN_ELIM_THM] THEN
3412   MESON_TAC[FACET_OF_IMP_SUBSET; SUBSET]);;
3413
3414 let RELATIVE_FRONTIER_OF_POLYHEDRON = prove
3415  (`!s:real^N->bool.
3416         polyhedron s ==> relative_frontier s = UNIONS {f | f facet_of s}`,
3417   SIMP_TAC[relative_frontier; POLYHEDRON_IMP_CLOSED; CLOSURE_CLOSED] THEN
3418   REWRITE_TAC[RELATIVE_BOUNDARY_OF_POLYHEDRON]);;
3419
3420 let RELATIVE_FRONTIER_OF_POLYHEDRON_ALT = prove
3421  (`!s:real^N->bool.
3422         polyhedron s
3423         ==> relative_frontier s = UNIONS {f | f face_of s /\ ~(f = s)}`,
3424   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3425    [ASM_SIMP_TAC[RELATIVE_FRONTIER_OF_POLYHEDRON; facet_of] THEN
3426     MATCH_MP_TAC SUBSET_UNIONS THEN SIMP_TAC[SUBSET; IN_ELIM_THM] THEN
3427     MESON_TAC[INT_ARITH `~(f - &1:int = f)`];
3428     REWRITE_TAC[SUBSET; FORALL_IN_UNIONS; IN_ELIM_THM] THEN
3429     MESON_TAC[REWRITE_RULE[SUBSET] FACE_OF_SUBSET_RELATIVE_FRONTIER]]);;
3430
3431 let FACETS_OF_POLYHEDRON_EXPLICIT_DISTINCT = prove
3432  (`!s:real^N->bool f a b.
3433         FINITE f /\
3434         s = affine hull s INTER INTERS f /\
3435         (!h. h IN f ==> ~(a h = vec 0) /\ h = {x | a h dot x <= b h}) /\
3436         (!f'. f' PSUBSET f ==> s PSUBSET affine hull s INTER INTERS f')
3437         ==> !h1 h2. h1 IN f /\ h2 IN f /\
3438                     s INTER {x | a h1 dot x = b h1} =
3439                     s INTER {x | a h2 dot x = b h2}
3440                     ==> h1 = h2`,
3441   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
3442    [ASM_REWRITE_TAC[AFFINE_HULL_EMPTY; INTER_EMPTY; PSUBSET_IRREFL] THEN
3443     ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
3444     ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
3445     ASM_MESON_TAC[SET_RULE `~(s = {}) ==> {} PSUBSET s`];
3446     STRIP_TAC] THEN
3447   SUBGOAL_THEN `polyhedron(s:real^N->bool)` ASSUME_TAC THENL
3448    [REWRITE_TAC[POLYHEDRON_INTER_AFFINE] THEN
3449     REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN ASM_MESON_TAC[];
3450     ALL_TAC] THEN
3451   SUBGOAL_THEN `~(relative_interior s:real^N->bool = {})` MP_TAC THENL
3452    [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY; POLYHEDRON_IMP_CONVEX];
3453     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
3454     DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC)] THEN
3455   DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
3456   MP_TAC(ISPECL
3457     [`s:real^N->bool`; `f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
3458      `b:(real^N->bool)->real`] RELATIVE_INTERIOR_POLYHEDRON_EXPLICIT) THEN
3459   ANTS_TAC THENL
3460    [ASM_SIMP_TAC[] THEN ASM_MESON_TAC[]; DISCH_THEN SUBST1_TAC] THEN
3461   REWRITE_TAC[IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
3462   MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
3463   FIRST_ASSUM(MP_TAC o SPEC `f DELETE (h2:real^N->bool)`) THEN
3464   ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[PSUBSET_ALT]] THEN
3465   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_THEN `x:real^N` MP_TAC)) THEN
3466   REWRITE_TAC[IN_INTER; IN_INTERS; IN_DELETE] THEN STRIP_TAC THEN
3467   MP_TAC(ISPECL [`segment[x:real^N,z]`; `s:real^N->bool`]
3468         CONNECTED_INTER_RELATIVE_FRONTIER) THEN
3469   PURE_REWRITE_TAC[relative_frontier] THEN ANTS_TAC THENL
3470    [REWRITE_TAC[CONNECTED_SEGMENT; GSYM MEMBER_NOT_EMPTY] THEN
3471     REPEAT CONJ_TAC THENL
3472      [ASM_MESON_TAC[CONVEX_CONTAINS_SEGMENT; AFFINE_AFFINE_HULL;
3473                     HULL_INC; AFFINE_IMP_CONVEX];
3474       EXISTS_TAC `z:real^N` THEN ASM_REWRITE_TAC[IN_INTER; ENDS_IN_SEGMENT];
3475       EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[IN_DIFF; ENDS_IN_SEGMENT]];
3476     ALL_TAC] THEN
3477   PURE_REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
3478   ASM_SIMP_TAC[POLYHEDRON_IMP_CLOSED; CLOSURE_CLOSED;
3479          LEFT_IMP_EXISTS_THM; IN_INTER] THEN
3480   X_GEN_TAC `y:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3481   DISCH_THEN(fun th -> STRIP_ASSUME_TAC(REWRITE_RULE[IN_DIFF] th) THEN
3482         MP_TAC th) THEN
3483   ASM_SIMP_TAC[RELATIVE_BOUNDARY_OF_POLYHEDRON] THEN
3484   MP_TAC(ISPECL
3485     [`s:real^N->bool`; `f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
3486      `b:(real^N->bool)->real`] FACET_OF_POLYHEDRON_EXPLICIT) THEN
3487   ANTS_TAC THENL
3488    [ASM_SIMP_TAC[] THEN ASM_MESON_TAC[];
3489     DISCH_THEN(fun th -> ONCE_REWRITE_TAC[th])] THEN
3490   REWRITE_TAC[SET_RULE `{y | ?x. x IN s /\ y = f x} = IMAGE f s`] THEN
3491   REWRITE_TAC[UNIONS_IMAGE; IN_ELIM_THM; IN_INTER] THEN
3492   DISCH_THEN(X_CHOOSE_THEN `h:real^N->bool` STRIP_ASSUME_TAC) THEN
3493   SUBGOAL_THEN
3494    `?k:real^N->bool. k IN f /\ ~(k = h2) /\ a k dot (y:real^N) = b k`
3495   STRIP_ASSUME_TAC THENL
3496    [ASM_CASES_TAC `h:real^N->bool = h2` THENL
3497      [EXISTS_TAC `h1:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
3498       UNDISCH_TAC `s INTER {x:real^N | a(h1:real^N->bool) dot x = b h1} =
3499                    s INTER {x | a h2 dot x = b h2}` THEN
3500       REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM] THEN ASM_MESON_TAC[];
3501       ASM_MESON_TAC[]];
3502     ALL_TAC] THEN
3503   SUBGOAL_THEN
3504    `(a:(real^N->bool)->real^N) k dot z < b k /\ a k dot x <= b k`
3505   STRIP_ASSUME_TAC THENL [ASM_SIMP_TAC[] THEN ASM SET_TAC[]; ALL_TAC] THEN
3506   SUBGOAL_THEN `y IN segment(x:real^N,z)` MP_TAC THENL
3507    [ASM_REWRITE_TAC[IN_OPEN_SEGMENT_ALT] THEN ASM_MESON_TAC[];
3508     REWRITE_TAC[IN_SEGMENT] THEN STRIP_TAC] THEN
3509   UNDISCH_TAC `(a:(real^N->bool)->real^N) k dot y = b k` THEN
3510   ASM_REWRITE_TAC[DOT_RADD; DOT_RMUL] THEN
3511   MATCH_MP_TAC(REAL_ARITH
3512    `(&1 - u) * x <= (&1 - u) * b /\ u * y < u * b
3513     ==> ~((&1 - u) * x + u * y = b)`) THEN
3514   ASM_SIMP_TAC[REAL_LT_LMUL_EQ; REAL_LE_LMUL_EQ; REAL_SUB_LT]);;
3515
3516 (* ------------------------------------------------------------------------- *)
3517 (* A characterization of polyhedra as having finitely many faces.            *)
3518 (* ------------------------------------------------------------------------- *)
3519
3520 let POLYHEDRON_EQ_FINITE_EXPOSED_FACES = prove
3521  (`!s:real^N->bool.
3522     polyhedron s <=> closed s /\ convex s /\ FINITE {f | f exposed_face_of s}`,
3523   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
3524   ASM_SIMP_TAC[POLYHEDRON_IMP_CLOSED; POLYHEDRON_IMP_CONVEX;
3525                FINITE_POLYHEDRON_EXPOSED_FACES] THEN
3526   ASM_CASES_TAC `s:real^N->bool = {}` THEN
3527   ASM_REWRITE_TAC[POLYHEDRON_EMPTY] THEN
3528   ABBREV_TAC
3529    `f = {h:real^N->bool | h exposed_face_of s /\ ~(h = {}) /\ ~(h = s)}` THEN
3530   SUBGOAL_THEN `FINITE(f:(real^N->bool)->bool)` ASSUME_TAC THENL
3531    [EXPAND_TAC "f" THEN
3532     ONCE_REWRITE_TAC[SET_RULE
3533      `{x | P x /\ Q x} = {x | x IN {x | P x} /\ Q x}`] THEN
3534     ASM_SIMP_TAC[FINITE_RESTRICT];
3535     ALL_TAC] THEN
3536   SUBGOAL_THEN
3537    `!h:real^N->bool.
3538         h IN f
3539         ==> h face_of s /\
3540             ?a b. ~(a = vec 0) /\
3541                   s SUBSET {x | a dot x <= b} /\
3542                   h = s INTER {x | a dot x = b}`
3543   MP_TAC THENL
3544    [EXPAND_TAC "f" THEN REWRITE_TAC[EXPOSED_FACE_OF; IN_ELIM_THM] THEN
3545     MESON_TAC[];
3546     ALL_TAC] THEN
3547   REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM; FORALL_AND_THM;
3548               TAUT `a ==> b /\ c <=> (a ==> b) /\ (a ==> c)`] THEN
3549   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3550   DISCH_THEN(X_CHOOSE_THEN `a:(real^N->bool)->real^N` MP_TAC) THEN
3551   DISCH_THEN(X_CHOOSE_THEN `b:(real^N->bool)->real` STRIP_ASSUME_TAC) THEN
3552   SUBGOAL_THEN
3553    `s = affine hull s INTER
3554         INTERS {{x:real^N | a(h:real^N->bool) dot x <= b h} | h IN f}`
3555   SUBST1_TAC THENL
3556    [ALL_TAC;
3557     MATCH_MP_TAC POLYHEDRON_INTER THEN REWRITE_TAC[POLYHEDRON_AFFINE_HULL] THEN
3558     MATCH_MP_TAC POLYHEDRON_INTERS THEN ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
3559     ASM_SIMP_TAC[FINITE_IMAGE; FORALL_IN_IMAGE; POLYHEDRON_HALFSPACE_LE]] THEN
3560   MATCH_MP_TAC SUBSET_ANTISYM THEN
3561   REWRITE_TAC[SUBSET_INTER; HULL_SUBSET;
3562               SET_RULE `s SUBSET INTERS f <=> !h. h IN f ==> s SUBSET h`] THEN
3563   ASM_REWRITE_TAC[FORALL_IN_GSPEC] THEN
3564   REWRITE_TAC[SUBSET; IN_INTER; IN_INTERS; FORALL_IN_GSPEC] THEN
3565   X_GEN_TAC `p:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN DISCH_TAC THEN
3566   MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
3567   SUBGOAL_THEN `~(relative_interior(s:real^N->bool) = {})` MP_TAC THENL
3568    [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY];
3569     GEN_REWRITE_TAC LAND_CONV [GSYM MEMBER_NOT_EMPTY] THEN
3570     DISCH_THEN(X_CHOOSE_TAC `c:real^N`)] THEN
3571   SUBGOAL_THEN
3572    `?x:real^N. x IN segment[c,p] /\ x IN (s DIFF relative_interior s)`
3573   MP_TAC THENL
3574    [MP_TAC(ISPEC `segment[c:real^N,p]` CONNECTED_OPEN_IN) THEN
3575     REWRITE_TAC[CONNECTED_SEGMENT; NOT_EXISTS_THM] THEN
3576     DISCH_THEN(MP_TAC o SPECL
3577      [`segment[c:real^N,p] INTER relative_interior s`;
3578       `segment[c:real^N,p] INTER (UNIV DIFF s)`]) THEN
3579     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
3580     REWRITE_TAC[IN_DIFF; NOT_EXISTS_THM] THEN DISCH_TAC THEN
3581     REPEAT CONJ_TAC THENL
3582      [MATCH_MP_TAC OPEN_IN_SUBTOPOLOGY_INTER_SUBSET THEN
3583       EXISTS_TAC `affine hull s:real^N->bool` THEN
3584       SIMP_TAC[OPEN_IN_RELATIVE_INTERIOR; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY;
3585         OPEN_IN_SUBTOPOLOGY_REFL; SUBSET_UNIV; OPEN_IN_INTER;
3586         TOPSPACE_EUCLIDEAN] THEN
3587       REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC HULL_MINIMAL THEN
3588       SIMP_TAC[AFFINE_IMP_CONVEX; AFFINE_AFFINE_HULL] THEN
3589       ASM_REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET] THEN
3590       ASM_MESON_TAC[RELATIVE_INTERIOR_SUBSET; HULL_INC; SUBSET];
3591       REWRITE_TAC[OPEN_IN_OPEN] THEN EXISTS_TAC `(:real^N) DIFF s` THEN
3592       ASM_REWRITE_TAC[GSYM closed];
3593      MP_TAC(ISPEC `s:real^N->bool` RELATIVE_INTERIOR_SUBSET) THEN ASM SET_TAC[];
3594      MP_TAC(ISPEC `s:real^N->bool` RELATIVE_INTERIOR_SUBSET) THEN SET_TAC[];
3595       REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN
3596       ASM_MESON_TAC[ENDS_IN_SEGMENT];
3597       REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_DIFF; IN_INTER; IN_UNIV] THEN
3598       ASM_MESON_TAC[ENDS_IN_SEGMENT]];
3599     REWRITE_TAC[IN_SEGMENT; LEFT_AND_EXISTS_THM] THEN
3600     ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
3601     REWRITE_TAC[GSYM CONJ_ASSOC; RIGHT_EXISTS_AND_THM; UNWIND_THM2] THEN
3602     DISCH_THEN(X_CHOOSE_THEN `l:real` MP_TAC) THEN
3603     ASM_CASES_TAC `l = &0` THEN
3604     ASM_REWRITE_TAC[VECTOR_ADD_RID; VECTOR_MUL_LZERO; REAL_SUB_RZERO;
3605                     VECTOR_MUL_LID; IN_DIFF] THEN
3606     ASM_CASES_TAC `l = &1` THEN
3607     ASM_REWRITE_TAC[VECTOR_ADD_LID; VECTOR_MUL_LZERO; REAL_SUB_REFL;
3608                     VECTOR_MUL_LID; IN_DIFF] THEN
3609     ASM_REWRITE_TAC[REAL_LE_LT] THEN STRIP_TAC] THEN
3610   ABBREV_TAC `x:real^N = (&1 - l) % c + l % p` THEN
3611   SUBGOAL_THEN `?h:real^N->bool. h IN f /\ x IN h` STRIP_ASSUME_TAC THENL
3612    [MP_TAC(ISPECL [`s:real^N->bool`; `(&1 - l) % c + l % p:real^N`]
3613       SUPPORTING_HYPERPLANE_RELATIVE_FRONTIER) THEN
3614     ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN
3615     DISCH_THEN(X_CHOOSE_THEN `d:real^N` STRIP_ASSUME_TAC) THEN
3616     EXPAND_TAC "f" THEN
3617     EXISTS_TAC `s INTER {y:real^N | d dot y = d dot x}` THEN
3618     ASM_REWRITE_TAC[IN_INTER; IN_ELIM_THM] THEN REPEAT CONJ_TAC THENL
3619      [MATCH_MP_TAC EXPOSED_FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE THEN
3620       ASM_SIMP_TAC[real_ge; REWRITE_RULE[SUBSET] CLOSURE_SUBSET];
3621       ASM SET_TAC[];
3622       REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM] THEN
3623       DISCH_THEN(MP_TAC o SPEC `c:real^N`) THEN
3624       ASM_MESON_TAC[SUBSET; REAL_LT_REFL; RELATIVE_INTERIOR_SUBSET]];
3625     ALL_TAC] THEN
3626   SUBGOAL_THEN `{y:real^N | a(h:real^N->bool) dot y = b h} face_of
3627                 {y | a h dot y <= b h}`
3628   MP_TAC THENL
3629    [MATCH_MP_TAC(MESON[]
3630      `(t INTER s) face_of t /\ t INTER s = s ==> s face_of t`) THEN
3631     CONJ_TAC THENL
3632      [MATCH_MP_TAC FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN
3633       REWRITE_TAC[IN_ELIM_THM; CONVEX_HALFSPACE_LE];
3634       SET_TAC[REAL_LE_REFL]];
3635     ALL_TAC] THEN
3636   REWRITE_TAC[face_of] THEN
3637   DISCH_THEN(MP_TAC o SPECL [`c:real^N`; `p:real^N`; `x:real^N`] o
3638         CONJUNCT2 o CONJUNCT2) THEN
3639   ASM_SIMP_TAC[IN_ELIM_THM; NOT_IMP; GSYM CONJ_ASSOC] THEN
3640   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REWRITE_RULE[SUBSET]
3641       RELATIVE_INTERIOR_SUBSET)) THEN
3642   REPEAT CONJ_TAC THENL
3643    [ASM SET_TAC[];
3644     ASM SET_TAC[];
3645     REWRITE_TAC[IN_SEGMENT] THEN ASM SET_TAC[];
3646     STRIP_TAC] THEN
3647   MP_TAC(ISPECL [`s:real^N->bool`; `h:real^N->bool`; `s:real^N->bool`]
3648         SUBSET_OF_FACE_OF) THEN
3649   ASM SET_TAC[]);;
3650
3651 let POLYHEDRON_EQ_FINITE_FACES = prove
3652  (`!s:real^N->bool.
3653         polyhedron s <=>
3654         closed s /\ convex s /\ FINITE {f | f face_of s}`,
3655   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
3656   ASM_SIMP_TAC[POLYHEDRON_IMP_CLOSED; POLYHEDRON_IMP_CONVEX;
3657                FINITE_POLYHEDRON_FACES] THEN
3658   REWRITE_TAC[POLYHEDRON_EQ_FINITE_EXPOSED_FACES] THEN
3659   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC FINITE_SUBSET THEN
3660   EXISTS_TAC `{f:real^N->bool | f face_of s}` THEN
3661   ASM_REWRITE_TAC[] THEN
3662   SIMP_TAC[SUBSET; IN_ELIM_THM; exposed_face_of]);;
3663
3664 let POLYHEDRON_TRANSLATION_EQ = prove
3665  (`!a s. polyhedron (IMAGE (\x:real^N. a + x) s) <=> polyhedron s`,
3666   REPEAT STRIP_TAC THEN REWRITE_TAC[POLYHEDRON_EQ_FINITE_FACES] THEN
3667   REWRITE_TAC[CLOSED_TRANSLATION_EQ] THEN AP_TERM_TAC THEN
3668   REWRITE_TAC[CONVEX_TRANSLATION_EQ] THEN AP_TERM_TAC THEN
3669   MP_TAC(ISPEC `IMAGE (\x:real^N. a + x)` QUANTIFY_SURJECTION_THM) THEN
3670   REWRITE_TAC[SURJECTIVE_IMAGE; EXISTS_REFL;
3671     VECTOR_ARITH `a + x:real^N = y <=> x = y - a`] THEN
3672   DISCH_THEN(fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [th]) THEN
3673   REWRITE_TAC[FACE_OF_TRANSLATION_EQ] THEN
3674   MATCH_MP_TAC FINITE_IMAGE_INJ_EQ THEN
3675   MATCH_MP_TAC(MESON[]
3676    `(!x y. Q x y ==> R x y) ==> (!x y. P x /\ P y /\ Q x y ==> R x y)`) THEN
3677   REWRITE_TAC[INJECTIVE_IMAGE] THEN VECTOR_ARITH_TAC);;
3678
3679 add_translation_invariants [POLYHEDRON_TRANSLATION_EQ];;
3680
3681 let POLYHEDRON_LINEAR_IMAGE_EQ = prove
3682  (`!f:real^M->real^N s.
3683         linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
3684         ==> (polyhedron (IMAGE f s) <=> polyhedron s)`,
3685   REPEAT STRIP_TAC THEN REWRITE_TAC[POLYHEDRON_EQ_FINITE_FACES] THEN
3686   BINOP_TAC THENL
3687    [ASM_MESON_TAC[CLOSED_INJECTIVE_LINEAR_IMAGE_EQ]; ALL_TAC] THEN
3688   BINOP_TAC THENL [ASM_MESON_TAC[CONVEX_LINEAR_IMAGE_EQ]; ALL_TAC] THEN
3689   MP_TAC(ISPEC `IMAGE (f:real^M->real^N)` QUANTIFY_SURJECTION_THM) THEN
3690   ASM_REWRITE_TAC[SURJECTIVE_IMAGE] THEN
3691   DISCH_THEN(fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [th]) THEN
3692   MP_TAC(ISPEC `f:real^M->real^N` FACE_OF_LINEAR_IMAGE) THEN
3693   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
3694   MATCH_MP_TAC FINITE_IMAGE_INJ_EQ THEN
3695   FIRST_ASSUM(ASSUME_TAC o GEN_REWRITE_RULE I [GSYM INJECTIVE_IMAGE]) THEN
3696   ASM_REWRITE_TAC[IMP_CONJ]);;
3697
3698 add_linear_invariants [POLYHEDRON_LINEAR_IMAGE_EQ];;
3699
3700 let POLYHEDRON_NEGATIONS = prove
3701  (`!s:real^N->bool. polyhedron s ==> polyhedron(IMAGE (--) s)`,
3702   GEN_TAC THEN MATCH_MP_TAC EQ_IMP THEN CONV_TAC SYM_CONV THEN
3703   MATCH_MP_TAC POLYHEDRON_LINEAR_IMAGE_EQ THEN
3704   REWRITE_TAC[VECTOR_ARITH `--x:real^N = y <=> x = --y`; EXISTS_REFL] THEN
3705   REWRITE_TAC[LINEAR_NEGATION] THEN VECTOR_ARITH_TAC);;
3706
3707 (* ------------------------------------------------------------------------- *)
3708 (* Relation between polytopes and polyhedra.                                 *)
3709 (* ------------------------------------------------------------------------- *)
3710
3711 let POLYTOPE_EQ_BOUNDED_POLYHEDRON = prove
3712  (`!s:real^N->bool. polytope s <=> polyhedron s /\ bounded s`,
3713   GEN_TAC THEN EQ_TAC THENL
3714    [SIMP_TAC[FINITE_POLYTOPE_FACES; POLYHEDRON_EQ_FINITE_FACES;
3715              POLYTOPE_IMP_CLOSED; POLYTOPE_IMP_CONVEX; POLYTOPE_IMP_BOUNDED];
3716     STRIP_TAC THEN REWRITE_TAC[polytope] THEN
3717     EXISTS_TAC `{v:real^N | v extreme_point_of s}` THEN
3718     ASM_SIMP_TAC[FINITE_POLYHEDRON_EXTREME_POINTS] THEN
3719     MATCH_MP_TAC KREIN_MILMAN_MINKOWSKI THEN
3720     ASM_SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; POLYHEDRON_IMP_CLOSED;
3721                  POLYHEDRON_IMP_CONVEX]]);;
3722
3723 let POLYTOPE_INTER = prove
3724  (`!s t. polytope s /\ polytope t ==> polytope(s INTER t)`,
3725   SIMP_TAC[POLYTOPE_EQ_BOUNDED_POLYHEDRON; POLYHEDRON_INTER; BOUNDED_INTER]);;
3726
3727 let POLYTOPE_INTER_POLYHEDRON = prove
3728  (`!s t:real^N->bool. polytope s /\ polyhedron t ==> polytope(s INTER t)`,
3729   SIMP_TAC[POLYTOPE_EQ_BOUNDED_POLYHEDRON; POLYHEDRON_INTER] THEN
3730   MESON_TAC[BOUNDED_SUBSET; INTER_SUBSET]);;
3731
3732 let POLYHEDRON_INTER_POLYTOPE = prove
3733  (`!s t:real^N->bool. polyhedron s /\ polytope t ==> polytope(s INTER t)`,
3734   SIMP_TAC[POLYTOPE_EQ_BOUNDED_POLYHEDRON; POLYHEDRON_INTER] THEN
3735   MESON_TAC[BOUNDED_SUBSET; INTER_SUBSET]);;
3736
3737 let POLYTOPE_IMP_POLYHEDRON = prove
3738  (`!p. polytope p ==> polyhedron p`,
3739   SIMP_TAC[POLYTOPE_EQ_BOUNDED_POLYHEDRON]);;
3740
3741 let POLYTOPE_FACET_EXISTS = prove
3742  (`!p:real^N->bool. polytope p /\ &0 < aff_dim p ==> ?f. f facet_of p`,
3743   GEN_TAC THEN ASM_CASES_TAC `p:real^N->bool = {}` THEN
3744   ASM_REWRITE_TAC[AFF_DIM_EMPTY] THEN CONV_TAC INT_REDUCE_CONV THEN
3745   STRIP_TAC THEN
3746   MP_TAC(ISPEC `p:real^N->bool` EXTREME_POINT_EXISTS_CONVEX) THEN
3747   ASM_SIMP_TAC[POLYTOPE_IMP_COMPACT; POLYTOPE_IMP_CONVEX] THEN
3748   DISCH_THEN(X_CHOOSE_TAC `v:real^N`) THEN
3749   MP_TAC(ISPECL [`p:real^N->bool`; `{v:real^N}`]
3750     FACE_OF_POLYHEDRON_SUBSET_FACET) THEN
3751   ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
3752   ASM_SIMP_TAC[POLYTOPE_IMP_POLYHEDRON; FACE_OF_SING; NOT_INSERT_EMPTY] THEN
3753   ASM_MESON_TAC[AFF_DIM_SING; INT_LT_REFL]);;
3754
3755 let POLYHEDRON_INTERVAL = prove
3756  (`!a b. polyhedron(interval[a,b])`,
3757   MESON_TAC[POLYTOPE_IMP_POLYHEDRON; POLYTOPE_INTERVAL]);;
3758
3759 let POLYHEDRON_CONVEX_HULL = prove
3760  (`!s. FINITE s ==> polyhedron(convex hull s)`,
3761   SIMP_TAC[POLYTOPE_CONVEX_HULL; POLYTOPE_IMP_POLYHEDRON]);;
3762
3763 (* ------------------------------------------------------------------------- *)
3764 (* Polytope is union of convex hulls of facets plus any point inside.        *)
3765 (* ------------------------------------------------------------------------- *)
3766
3767 let POLYTOPE_UNION_CONVEX_HULL_FACETS = prove
3768  (`!s p:real^N->bool.
3769         polytope p /\ &0 < aff_dim p /\ ~(s = {}) /\ s SUBSET p
3770         ==> p = UNIONS { convex hull (s UNION f) | f facet_of p}`,
3771   let lemma = SET_RULE `{f x | p x} = {y | ?x. p x /\ y = f x}` in
3772   MATCH_MP_TAC SET_PROVE_CASES THEN REWRITE_TAC[] THEN
3773   X_GEN_TAC `a:real^N` THEN ONCE_REWRITE_TAC[lemma] THEN
3774   GEOM_ORIGIN_TAC `a:real^N` THEN ONCE_REWRITE_TAC[GSYM lemma] THEN
3775   X_GEN_TAC `s:real^N->bool` THEN DISCH_THEN(K ALL_TAC) THEN
3776   MP_TAC(SET_RULE `(vec 0:real^N) IN (vec 0 INSERT s)`) THEN
3777   SPEC_TAC(`(vec 0:real^N) INSERT s`,`s:real^N->bool`) THEN
3778   X_GEN_TAC `s:real^N->bool` THEN DISCH_TAC THEN
3779   X_GEN_TAC `p:real^N->bool` THEN STRIP_TAC THEN
3780   FIRST_ASSUM(STRIP_ASSUME_TAC o
3781    GEN_REWRITE_RULE I [POLYTOPE_EQ_BOUNDED_POLYHEDRON]) THEN
3782   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3783    [ALL_TAC;
3784     REWRITE_TAC[SUBSET; FORALL_IN_UNIONS; IMP_CONJ] THEN
3785     REWRITE_TAC[FORALL_IN_GSPEC; RIGHT_FORALL_IMP_THM] THEN
3786     X_GEN_TAC `f:real^N->bool` THEN DISCH_TAC THEN
3787     REWRITE_TAC[GSYM SUBSET] THEN MATCH_MP_TAC SUBSET_TRANS THEN
3788     EXISTS_TAC `convex hull p:real^N->bool` THEN CONJ_TAC THENL
3789      [MATCH_MP_TAC HULL_MONO THEN
3790       FIRST_ASSUM(MP_TAC o MATCH_MP FACET_OF_IMP_SUBSET) THEN ASM SET_TAC[];
3791       ASM_MESON_TAC[CONVEX_HULL_EQ; POLYHEDRON_IMP_CONVEX; SUBSET_REFL]]] THEN
3792   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `v:real^N` THEN DISCH_TAC THEN
3793   ASM_CASES_TAC `v:real^N = vec 0` THENL
3794    [MP_TAC(ISPEC `p:real^N->bool` POLYTOPE_FACET_EXISTS) THEN
3795     ASM_REWRITE_TAC[IN_UNIONS; EXISTS_IN_GSPEC] THEN
3796     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN DISCH_TAC THEN
3797     ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[HULL_INC; IN_UNION];
3798     ALL_TAC] THEN
3799   SUBGOAL_THEN `?t. &1 < t /\ ~((t % v:real^N) IN p)` STRIP_ASSUME_TAC THENL
3800    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
3801     DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
3802     EXISTS_TAC `max (&2) ((B + &1) / norm (v:real^N))` THEN
3803     CONJ_TAC THENL [REAL_ARITH_TAC; ALL_TAC] THEN
3804     FIRST_X_ASSUM(MATCH_MP_TAC o
3805      GEN_REWRITE_RULE BINDER_CONV [GSYM CONTRAPOS_THM]) THEN
3806     ASM_SIMP_TAC[NORM_MUL; GSYM REAL_LE_RDIV_EQ; NORM_POS_LT] THEN
3807     MATCH_MP_TAC(REAL_ARITH `a < b ==> ~(abs(max (&2) b) <= a)`) THEN
3808     ASM_SIMP_TAC[REAL_LT_DIV2_EQ; NORM_POS_LT] THEN REAL_ARITH_TAC;
3809     ALL_TAC] THEN
3810   SUBGOAL_THEN `(vec 0:real^N) IN p` ASSUME_TAC THENL
3811    [ASM SET_TAC[]; ALL_TAC] THEN
3812   MP_TAC(ISPECL [`segment[vec 0,t % v:real^N] INTER p`; `vec 0:real^N`]
3813         DISTANCE_ATTAINS_SUP) THEN
3814   ANTS_TAC THENL
3815    [ASM_SIMP_TAC[COMPACT_INTER_CLOSED; POLYHEDRON_IMP_CLOSED; COMPACT_SEGMENT;
3816                  GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN
3817     ASM_MESON_TAC[ENDS_IN_SEGMENT];
3818     REWRITE_TAC[IN_INTER; GSYM CONJ_ASSOC; IMP_CONJ] THEN
3819     REWRITE_TAC[segment; FORALL_IN_GSPEC; EXISTS_IN_GSPEC] THEN
3820     REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID; DIST_0] THEN
3821     REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC; NORM_MUL; REAL_MUL_ASSOC] THEN
3822     ASM_SIMP_TAC[REAL_LE_RMUL_EQ; NORM_POS_LT; LEFT_IMP_EXISTS_THM;
3823                  REAL_ARITH `&1 < t ==> &0 < abs t`] THEN
3824     X_GEN_TAC `u:real` THEN
3825     ASM_CASES_TAC `u = &1` THEN ASM_REWRITE_TAC[VECTOR_MUL_LID] THEN
3826     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
3827     ASM_SIMP_TAC[real_abs] THEN DISCH_TAC] THEN
3828   SUBGOAL_THEN `inv(t) <= u` ASSUME_TAC THENL
3829    [FIRST_X_ASSUM MATCH_MP_TAC THEN
3830     ASM_SIMP_TAC[REAL_INV_LE_1; REAL_LT_IMP_LE; REAL_LE_INV_EQ;
3831                  REAL_ARITH `&1 < t ==> &0 <= t`] THEN
3832     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID;
3833                  REAL_ARITH `&1 < t ==> ~(t = &0)`];
3834     ALL_TAC] THEN
3835   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REAL_ARITH `&1 < t ==> &0 < t`)) THEN
3836   SUBGOAL_THEN `&0 < u /\ u < &1` STRIP_ASSUME_TAC THENL
3837    [ASM_REWRITE_TAC[REAL_LT_LE] THEN
3838     DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
3839     UNDISCH_TAC `inv t <= &0` THEN REWRITE_TAC[REAL_NOT_LE] THEN
3840     ASM_REWRITE_TAC[REAL_LT_INV_EQ];
3841     ALL_TAC] THEN
3842   MATCH_MP_TAC(SET_RULE `!t. t SUBSET s /\ x IN t ==> x IN s`) THEN
3843   EXISTS_TAC `convex hull {vec 0:real^N,u % t % v}` THEN CONJ_TAC THENL
3844    [ALL_TAC;
3845     REWRITE_TAC[CONVEX_HULL_2; VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
3846     REWRITE_TAC[IN_ELIM_THM] THEN
3847     MAP_EVERY EXISTS_TAC [`&1 - inv(u * t)`; `inv(u * t):real`] THEN
3848     REWRITE_TAC[REAL_ARITH `&1 - x + x = &1`; REAL_SUB_LE; REAL_LE_INV_EQ] THEN
3849     ASM_SIMP_TAC[REAL_LE_MUL; REAL_LT_IMP_LE; VECTOR_MUL_ASSOC] THEN
3850     ASM_SIMP_TAC[GSYM REAL_MUL_ASSOC; REAL_ENTIRE; REAL_MUL_LINV;
3851                  REAL_LT_IMP_NZ; VECTOR_MUL_LID] THEN
3852     MATCH_MP_TAC REAL_INV_LE_1 THEN ASM_SIMP_TAC[GSYM REAL_LE_LDIV_EQ] THEN
3853     ASM_REWRITE_TAC[real_div; REAL_MUL_LID]] THEN
3854   SUBGOAL_THEN
3855    `(u % t % v:real^N) IN (p DIFF relative_interior p)`
3856   MP_TAC THENL
3857    [ALL_TAC;
3858     ASM_SIMP_TAC[RELATIVE_INTERIOR_OF_POLYHEDRON] THEN
3859     DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
3860      `x IN s DIFF (s DIFF t) ==> x IN t`)) THEN
3861     REWRITE_TAC[IN_UNIONS; EXISTS_IN_GSPEC] THEN
3862     DISCH_THEN(X_CHOOSE_THEN `f:real^N->bool` STRIP_ASSUME_TAC) THEN
3863     MATCH_MP_TAC(SET_RULE
3864      `(?s. s IN f /\ t SUBSET s) ==> t SUBSET UNIONS f`) THEN
3865     REWRITE_TAC[EXISTS_IN_GSPEC] THEN EXISTS_TAC `f:real^N->bool` THEN
3866     ASM_SIMP_TAC[SUBSET_HULL; CONVEX_CONVEX_HULL] THEN
3867     ASM_SIMP_TAC[HULL_INC; IN_UNION; INSERT_SUBSET; EMPTY_SUBSET]] THEN
3868   ASM_REWRITE_TAC[IN_DIFF; IN_RELATIVE_INTERIOR] THEN
3869   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
3870   REWRITE_TAC[SUBSET; IN_BALL; IN_INTER; dist] THEN
3871   ABBREV_TAC `k = min (e / &2 / norm(t % v:real^N)) (&1 - u)` THEN
3872   SUBGOAL_THEN `&0 < k` ASSUME_TAC THENL
3873    [EXPAND_TAC "k" THEN REWRITE_TAC[REAL_LT_MIN] THEN
3874     ASM_REWRITE_TAC[REAL_SUB_LT] THEN MATCH_MP_TAC REAL_LT_DIV THEN
3875     ASM_SIMP_TAC[REAL_HALF; NORM_POS_LT; VECTOR_MUL_EQ_0; REAL_LT_IMP_NZ];
3876     ALL_TAC] THEN
3877   DISCH_THEN(MP_TAC o SPEC `(u + k) % t % v:real^N`) THEN
3878   REWRITE_TAC[VECTOR_ARITH `u % x - (u + k) % x:real^N = --k % x`] THEN
3879   ONCE_REWRITE_TAC[NORM_MUL] THEN REWRITE_TAC[REAL_ABS_NEG; NOT_IMP] THEN
3880   REPEAT CONJ_TAC THENL
3881    [MATCH_MP_TAC(REAL_ARITH `&0 < e /\ x <= e / &2 ==> x < e`) THEN
3882     ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; NORM_POS_LT; VECTOR_MUL_EQ_0;
3883                  REAL_LT_IMP_NZ] THEN
3884     ASM_SIMP_TAC[real_abs; REAL_LT_IMP_LE] THEN
3885     EXPAND_TAC "k" THEN REAL_ARITH_TAC;
3886     ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC] THEN
3887     REPEAT(MATCH_MP_TAC SPAN_MUL) THEN ASM_SIMP_TAC[SPAN_SUPERSET];
3888     DISCH_TAC THEN
3889     FIRST_X_ASSUM(MP_TAC o SPEC `u + k:real`) THEN
3890     ASM_REWRITE_TAC[NOT_IMP] THEN
3891     MATCH_MP_TAC(REAL_ARITH
3892      `&0 <= u /\ &0 < x /\ x <= &1 - u
3893       ==> (&0 <= u + x /\ u + x <= &1) /\ ~(u + x <= u)`) THEN
3894     ASM_REWRITE_TAC[] THEN EXPAND_TAC "k" THEN REAL_ARITH_TAC]);;
3895
3896 (* ------------------------------------------------------------------------- *)
3897 (* Finitely generated cone is polyhedral, and hence closed.                  *)
3898 (* ------------------------------------------------------------------------- *)
3899
3900 let POLYHEDRON_CONVEX_CONE_HULL = prove
3901  (`!s:real^N->bool. FINITE s ==> polyhedron(convex_cone hull s)`,
3902   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN DISCH_TAC THENL
3903    [ASM_REWRITE_TAC[CONVEX_CONE_HULL_EMPTY] THEN
3904     ASM_SIMP_TAC[POLYTOPE_IMP_POLYHEDRON; POLYTOPE_SING];
3905     ALL_TAC] THEN
3906   SUBGOAL_THEN
3907     `polyhedron(convex hull ((vec 0:real^N) INSERT s))`
3908   MP_TAC THENL
3909    [MATCH_MP_TAC POLYTOPE_IMP_POLYHEDRON THEN
3910     REWRITE_TAC[polytope] THEN ASM_MESON_TAC[FINITE_INSERT];
3911     REWRITE_TAC[polyhedron] THEN
3912     DISCH_THEN(X_CHOOSE_THEN `f:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
3913     RULE_ASSUM_TAC(REWRITE_RULE[SKOLEM_THM; RIGHT_IMP_EXISTS_THM]) THEN
3914     FIRST_X_ASSUM(X_CHOOSE_THEN `a:(real^N->bool)->real^N` MP_TAC) THEN
3915     DISCH_THEN(X_CHOOSE_TAC `b:(real^N->bool)->real`)] THEN
3916   SUBGOAL_THEN `~(f:(real^N->bool)->bool = {})` ASSUME_TAC THENL
3917    [DISCH_THEN SUBST_ALL_TAC THEN FIRST_X_ASSUM(MP_TAC o
3918      GEN_REWRITE_RULE RAND_CONV [INTERS_0]) THEN
3919     DISCH_THEN(MP_TAC o AP_TERM `bounded:(real^N->bool)->bool`) THEN
3920     ASM_SIMP_TAC[NOT_BOUNDED_UNIV; BOUNDED_CONVEX_HULL; FINITE_IMP_BOUNDED;
3921                  FINITE_INSERT; FINITE_EMPTY];
3922     ALL_TAC] THEN
3923   EXISTS_TAC `{h:real^N->bool | h IN f /\ b h = &0}` THEN
3924   ASM_SIMP_TAC[FINITE_RESTRICT; IN_ELIM_THM] THEN CONJ_TAC THENL
3925    [ALL_TAC;
3926     X_GEN_TAC `h:real^N->bool` THEN STRIP_TAC THEN
3927     FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
3928     ASM_REWRITE_TAC[] THEN DISCH_TAC THEN ONCE_ASM_REWRITE_TAC[] THEN
3929     MAP_EVERY EXISTS_TAC
3930      [`(a:(real^N->bool)->real^N) h`; `(b:(real^N->bool)->real) h`] THEN
3931     ASM_REWRITE_TAC[]] THEN
3932   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
3933    [MATCH_MP_TAC HULL_MINIMAL THEN CONJ_TAC THENL
3934      [MATCH_MP_TAC SUBSET_TRANS THEN
3935       EXISTS_TAC `convex hull ((vec 0:real^N) INSERT s)` THEN CONJ_TAC THENL
3936        [SIMP_TAC[SUBSET; HULL_INC; IN_INSERT]; ASM_REWRITE_TAC[]] THEN
3937       MATCH_MP_TAC(SET_RULE `s SUBSET t ==> INTERS t SUBSET INTERS s`) THEN
3938       SET_TAC[];
3939       MATCH_MP_TAC CONVEX_CONE_INTERS THEN
3940       X_GEN_TAC `h:real^N->bool` THEN REWRITE_TAC[IN_ELIM_THM] THEN
3941       STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN
3942       ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o CONJUNCT2) THEN
3943       REWRITE_TAC[CONVEX_CONE_HALFSPACE_LE]];
3944     ALL_TAC] THEN
3945   REWRITE_TAC[SUBSET; IN_INTERS; IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN
3946   DISCH_TAC THEN
3947   SUBGOAL_THEN `!h:real^N->bool. h IN f ==> ?t. &0 < t /\ (t % x) IN h`
3948   MP_TAC THENL
3949    [X_GEN_TAC `h:real^N->bool` THEN DISCH_TAC THEN
3950     ASM_CASES_TAC `(b:(real^N->bool)->real) h = &0` THENL
3951      [EXISTS_TAC `&1` THEN ASM_SIMP_TAC[REAL_LT_01; VECTOR_MUL_LID];
3952       ALL_TAC] THEN
3953     SUBGOAL_THEN `&0 < (b:(real^N->bool)->real) h` ASSUME_TAC THENL
3954      [ASM_REWRITE_TAC[REAL_LT_LE] THEN
3955       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
3956       DISCH_THEN(MP_TAC o SPEC `vec 0:real^N`) THEN
3957       SIMP_TAC[HULL_INC; IN_INSERT; IN_INTERS] THEN
3958       DISCH_THEN(MP_TAC o SPEC `h:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
3959       SUBGOAL_THEN `h = {x:real^N | a h dot x <= b h}`
3960        (fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [th])
3961       THENL [ASM_MESON_TAC[]; REWRITE_TAC[IN_ELIM_THM; DOT_RZERO]];
3962       ALL_TAC] THEN
3963     SUBGOAL_THEN `(vec 0:real^N) IN interior h` MP_TAC THENL
3964      [SUBGOAL_THEN `h = {x:real^N | a h dot x <= b h}` SUBST1_TAC THENL
3965        [ASM_MESON_TAC[];
3966         ASM_SIMP_TAC[INTERIOR_HALFSPACE_LE; IN_ELIM_THM; DOT_RZERO]];
3967       REWRITE_TAC[IN_INTERIOR; SUBSET; IN_BALL_0; LEFT_IMP_EXISTS_THM] THEN
3968       X_GEN_TAC `e:real` THEN STRIP_TAC THEN
3969       ASM_CASES_TAC `x:real^N = vec 0` THENL
3970        [EXISTS_TAC `&1` THEN
3971         ASM_SIMP_TAC[VECTOR_MUL_RZERO; REAL_LT_01; NORM_0];
3972         EXISTS_TAC `e / &2 / norm(x:real^N)` THEN
3973         ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT] THEN
3974         FIRST_X_ASSUM MATCH_MP_TAC THEN
3975         REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NUM; REAL_ABS_NORM] THEN
3976         ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN ASM_REAL_ARITH_TAC]];
3977     ALL_TAC] THEN
3978   REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
3979   X_GEN_TAC `t:(real^N->bool)->real` THEN DISCH_TAC THEN
3980   SUBGOAL_THEN `x:real^N = inv(inf(IMAGE t (f:(real^N->bool)->bool))) %
3981                            inf(IMAGE t f) % x`
3982   SUBST1_TAC THENL
3983    [GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_MUL_LID] THEN
3984     REWRITE_TAC[VECTOR_MUL_ASSOC] THEN AP_THM_TAC THEN AP_TERM_TAC THEN
3985     CONV_TAC SYM_CONV THEN MATCH_MP_TAC REAL_MUL_LINV THEN
3986     MATCH_MP_TAC REAL_LT_IMP_NZ THEN
3987     ASM_SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
3988     ASM_SIMP_TAC[FORALL_IN_IMAGE];
3989     ALL_TAC] THEN
3990   MATCH_MP_TAC(REWRITE_RULE[conic] CONIC_CONVEX_CONE_HULL) THEN
3991   ASM_SIMP_TAC[REAL_LE_INV_EQ; REAL_LE_INF_FINITE; FINITE_IMAGE;
3992                IMAGE_EQ_EMPTY; REAL_LT_IMP_LE; FORALL_IN_IMAGE] THEN
3993   MATCH_MP_TAC(SET_RULE `!s t. s SUBSET t /\ x IN s ==> x IN t`) THEN
3994   EXISTS_TAC `convex hull ((vec 0:real^N) INSERT s)` THEN CONJ_TAC THENL
3995    [MATCH_MP_TAC HULL_MINIMAL THEN
3996     REWRITE_TAC[CONVEX_CONVEX_CONE_HULL] THEN
3997     ASM_SIMP_TAC[INSERT_SUBSET; HULL_SUBSET; CONVEX_CONE_HULL_CONTAINS_0];
3998     ASM_REWRITE_TAC[IN_INTERS] THEN X_GEN_TAC `h:real^N->bool` THEN
3999     DISCH_TAC THEN
4000     SUBGOAL_THEN `inf(IMAGE (t:(real^N->bool)->real) f) % x:real^N =
4001                   (&1 - inf(IMAGE t f) / t h) % vec 0 +
4002                   (inf(IMAGE t f) / t h) % t h % x`
4003     SUBST1_TAC THENL
4004      [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; VECTOR_MUL_RZERO; VECTOR_ADD_LID;
4005                    REAL_DIV_RMUL; REAL_LT_IMP_NZ];
4006       ALL_TAC] THEN
4007     MATCH_MP_TAC IN_CONVEX_SET THEN
4008     ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ] THEN
4009     REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID] THEN
4010     ASM_SIMP_TAC[REAL_INF_LE_FINITE; REAL_LE_INF_FINITE;
4011                  FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
4012     ASM_REWRITE_TAC[FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
4013     ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN REPEAT CONJ_TAC THENL
4014      [SUBGOAL_THEN `h = {x:real^N | a h dot x <= b h}` SUBST1_TAC THENL
4015        [ASM_MESON_TAC[]; ASM_SIMP_TAC[CONVEX_HALFSPACE_LE]];
4016       SUBGOAL_THEN `(vec 0:real^N) IN convex hull (vec 0 INSERT s)` MP_TAC
4017       THENL [SIMP_TAC[HULL_INC; IN_INSERT]; ALL_TAC] THEN
4018       ASM_REWRITE_TAC[IN_INTERS] THEN ASM_MESON_TAC[];
4019       ASM SET_TAC[REAL_LE_REFL]]]);;
4020
4021 let CLOSED_CONVEX_CONE_HULL = prove
4022  (`!s:real^N->bool. FINITE s ==> closed(convex_cone hull s)`,
4023   MESON_TAC[POLYHEDRON_IMP_CLOSED; POLYHEDRON_CONVEX_CONE_HULL]);;
4024
4025 (* ------------------------------------------------------------------------- *)
4026 (* And conversely, a polyhedral cone is finitely generated.                  *)
4027 (* ------------------------------------------------------------------------- *)
4028
4029 let FINITELY_GENERATED_CONIC_POLYHEDRON = prove
4030  (`!s:real^N->bool.
4031         polyhedron s /\ conic s /\ ~(s = {})
4032         ==> ?c. FINITE c /\ s = convex_cone hull c`,
4033   REPEAT STRIP_TAC THEN
4034   SUBGOAL_THEN `?p:real^N->bool. polytope p /\ vec 0 IN interior p`
4035   STRIP_ASSUME_TAC THENL
4036    [EXISTS_TAC `interval[--vec 1:real^N,vec 1:real^N]` THEN
4037     REWRITE_TAC[POLYTOPE_INTERVAL; INTERIOR_CLOSED_INTERVAL] THEN
4038     SIMP_TAC[IN_INTERVAL; VECTOR_NEG_COMPONENT; VEC_COMPONENT] THEN
4039     CONV_TAC REAL_RAT_REDUCE_CONV;
4040     ALL_TAC] THEN
4041   SUBGOAL_THEN `polytope(s INTER p:real^N->bool)` MP_TAC THENL
4042    [REWRITE_TAC[POLYTOPE_EQ_BOUNDED_POLYHEDRON] THEN
4043     ASM_SIMP_TAC[BOUNDED_INTER; POLYTOPE_IMP_BOUNDED]THEN
4044     ASM_SIMP_TAC[POLYHEDRON_INTER; POLYTOPE_IMP_POLYHEDRON];
4045     REWRITE_TAC[polytope] THEN MATCH_MP_TAC MONO_EXISTS] THEN
4046   X_GEN_TAC `c:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4047   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
4048    [ALL_TAC;
4049     ASM_SIMP_TAC[SUBSET_HULL; POLYHEDRON_IMP_CONVEX; convex_cone] THEN
4050     MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `s INTER p:real^N->bool` THEN
4051     REWRITE_TAC[INTER_SUBSET] THEN ASM_REWRITE_TAC[HULL_SUBSET]] THEN
4052   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4053   SUBGOAL_THEN `?t. &0 < t /\ (t % x:real^N) IN p` STRIP_ASSUME_TAC THENL
4054    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR]) THEN
4055     REWRITE_TAC[SUBSET; IN_BALL_0; LEFT_IMP_EXISTS_THM] THEN
4056     X_GEN_TAC `e:real` THEN STRIP_TAC THEN
4057     ASM_CASES_TAC `x:real^N = vec 0` THENL
4058      [EXISTS_TAC `&1` THEN ASM_REWRITE_TAC[VECTOR_MUL_RZERO; REAL_LT_01] THEN
4059       ASM_SIMP_TAC[NORM_0];
4060       EXISTS_TAC `e / &2 / norm(x:real^N)` THEN
4061       ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; NORM_POS_LT] THEN
4062       FIRST_X_ASSUM MATCH_MP_TAC THEN
4063       REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_ABS_NUM] THEN
4064       ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN ASM_REAL_ARITH_TAC];
4065     ALL_TAC] THEN
4066   SUBGOAL_THEN `x:real^N = inv t % t % x` SUBST1_TAC THENL
4067    [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID;
4068                  REAL_LT_IMP_NZ];
4069     ALL_TAC] THEN
4070   MATCH_MP_TAC(REWRITE_RULE[conic] CONIC_CONVEX_CONE_HULL) THEN
4071   ASM_SIMP_TAC[REAL_LE_INV_EQ; REAL_LT_IMP_LE] THEN
4072   MATCH_MP_TAC(SET_RULE `!s. x IN s /\ s SUBSET t ==> x IN t`) THEN
4073   EXISTS_TAC `convex hull c:real^N->bool` THEN
4074   REWRITE_TAC[CONVEX_HULL_SUBSET_CONVEX_CONE_HULL] THEN
4075   FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN ASM_REWRITE_TAC[IN_INTER] THEN
4076   FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [conic]) THEN
4077   ASM_SIMP_TAC[REAL_LT_IMP_LE]);;
4078
4079 (* ------------------------------------------------------------------------- *)
4080 (* Decomposition of polyhedron into cone plus polytope and more corollaries. *)
4081 (* ------------------------------------------------------------------------- *)
4082
4083 let POLYHEDRON_POLYTOPE_SUMS = prove
4084  (`!s t:real^N->bool.
4085     polyhedron s /\ polytope t ==> polyhedron {x + y | x IN s /\ y IN t}`,
4086   REPEAT STRIP_TAC THEN
4087   REWRITE_TAC[POLYHEDRON_EQ_FINITE_EXPOSED_FACES] THEN REPEAT CONJ_TAC THENL
4088    [MATCH_MP_TAC CLOSED_COMPACT_SUMS THEN
4089     ASM_SIMP_TAC[POLYHEDRON_IMP_CLOSED; POLYTOPE_IMP_COMPACT];
4090     MATCH_MP_TAC CONVEX_SUMS THEN
4091     ASM_SIMP_TAC[POLYHEDRON_IMP_CONVEX; POLYTOPE_IMP_CONVEX];
4092     MATCH_MP_TAC FINITE_SUBSET THEN
4093     EXISTS_TAC `{ {x + y:real^N | x IN k /\ y IN l} |
4094                   k exposed_face_of s /\ l exposed_face_of t}` THEN
4095     CONJ_TAC THENL
4096      [ONCE_REWRITE_TAC[SET_RULE `k exposed_face_of s <=>
4097                                  k IN {f | f exposed_face_of s}`] THEN
4098       MATCH_MP_TAC FINITE_PRODUCT_DEPENDENT THEN
4099       ASM_SIMP_TAC[FINITE_POLYHEDRON_EXPOSED_FACES;
4100                    POLYTOPE_IMP_POLYHEDRON];
4101       REWRITE_TAC[SUBSET; IN_ELIM_THM; GSYM CONJ_ASSOC] THEN
4102       REPEAT STRIP_TAC THEN MATCH_MP_TAC EXPOSED_FACE_OF_SUMS THEN
4103       ASM_SIMP_TAC[POLYHEDRON_IMP_CONVEX; POLYTOPE_IMP_CONVEX]]]);;
4104
4105 let POLYHEDRON_AS_CONE_PLUS_CONV = prove
4106  (`!s:real^N->bool.
4107         polyhedron s <=> ?t u. FINITE t /\ FINITE u /\
4108                                s = {x + y | x IN convex_cone hull t /\
4109                                             y IN convex hull u}`,
4110   REPEAT GEN_TAC THEN EQ_TAC THENL
4111    [REWRITE_TAC[polyhedron; LEFT_IMP_EXISTS_THM];
4112     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4113     MATCH_MP_TAC POLYHEDRON_POLYTOPE_SUMS THEN
4114     ASM_SIMP_TAC[POLYTOPE_CONVEX_HULL; POLYHEDRON_CONVEX_CONE_HULL]] THEN
4115   REWRITE_TAC[polyhedron; LEFT_IMP_EXISTS_THM] THEN
4116   X_GEN_TAC `f:(real^N->bool)->bool` THEN
4117   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4118   DISCH_THEN(CONJUNCTS_THEN2 (ASSUME_TAC o SYM) MP_TAC) THEN
4119   GEN_REWRITE_TAC (LAND_CONV o REDEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4120   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC
4121    [`a:(real^N->bool)->real^N`; `b:(real^N->bool)->real`] THEN
4122   ONCE_REWRITE_TAC[MESON[] `h = {x | P x} <=> {x | P x} = h`] THEN
4123   DISCH_TAC THEN
4124   ABBREV_TAC
4125    `s':real^(N,1)finite_sum->bool =
4126         {x | &0 <= drop(sndcart x) /\
4127              !h:real^N->bool.
4128                 h IN f ==> a h dot (fstcart x) <= b h * drop(sndcart x)}` THEN
4129   SUBGOAL_THEN
4130    `?t u. FINITE t /\ FINITE u /\
4131           (!y:real^(N,1)finite_sum. y IN t ==> drop(sndcart y) = &0) /\
4132           (!y. y IN u ==> drop(sndcart y) = &1) /\
4133           s' = convex_cone hull (t UNION u)`
4134   STRIP_ASSUME_TAC THENL
4135    [MP_TAC(ISPEC `s':real^(N,1)finite_sum->bool`
4136         FINITELY_GENERATED_CONIC_POLYHEDRON) THEN
4137     ANTS_TAC THENL
4138      [EXPAND_TAC "s'" THEN REPEAT CONJ_TAC THENL
4139        [REWRITE_TAC[polyhedron] THEN
4140         EXISTS_TAC
4141          `{ x:real^(N,1)finite_sum |
4142             pastecart (vec 0) (--vec 1) dot x <= &0} INSERT
4143           { {x | pastecart (a h) (--lift(b h)) dot x <= &0} |
4144             (h:real^N->bool) IN f}` THEN
4145         REWRITE_TAC[FINITE_INSERT; INTERS_INSERT; SIMPLE_IMAGE] THEN
4146         ASM_SIMP_TAC[FINITE_IMAGE; FORALL_IN_INSERT; FORALL_IN_IMAGE] THEN
4147         REPEAT CONJ_TAC THENL
4148          [EXPAND_TAC "s'" THEN
4149           REWRITE_TAC[EXTENSION; IN_ELIM_THM; FORALL_PASTECART; IN_INTER;
4150            DOT_PASTECART; INTERS_IMAGE; FSTCART_PASTECART;
4151            SNDCART_PASTECART; DOT_1; GSYM drop; DROP_NEG; LIFT_DROP] THEN
4152           REWRITE_TAC[DROP_VEC; DOT_LZERO; REAL_MUL_LNEG; GSYM real_sub] THEN
4153           REWRITE_TAC[REAL_MUL_LID; REAL_ARITH `x - y <= &0 <=> x <= y`];
4154           EXISTS_TAC `pastecart (vec 0) (--vec 1):real^(N,1)finite_sum` THEN
4155           EXISTS_TAC `&0` THEN
4156           REWRITE_TAC[PASTECART_EQ_VEC; VECTOR_NEG_EQ_0; VEC_EQ] THEN
4157           ARITH_TAC;
4158           X_GEN_TAC `h:real^N->bool` THEN DISCH_TAC THEN MAP_EVERY EXISTS_TAC
4159            [`pastecart (a(h:real^N->bool)) (--lift(b h)):real^(N,1)finite_sum`;
4160             `&0`] THEN
4161           ASM_SIMP_TAC[PASTECART_EQ_VEC]];
4162         REWRITE_TAC[conic; IN_ELIM_THM; FSTCART_CMUL; SNDCART_CMUL] THEN
4163         SIMP_TAC[DROP_CMUL; DOT_RMUL; REAL_LE_MUL] THEN
4164         MESON_TAC[REAL_LE_LMUL; REAL_MUL_AC];
4165         REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
4166         EXISTS_TAC `vec 0:real^(N,1)finite_sum` THEN
4167         REWRITE_TAC[IN_ELIM_THM; FSTCART_VEC; SNDCART_VEC] THEN
4168         REWRITE_TAC[DROP_VEC; DOT_RZERO; REAL_LE_REFL; REAL_MUL_RZERO]];
4169       DISCH_THEN(X_CHOOSE_THEN `c:real^(N,1)finite_sum->bool`
4170         STRIP_ASSUME_TAC) THEN
4171       MAP_EVERY EXISTS_TAC
4172        [`{x:real^(N,1)finite_sum | x IN c /\ drop(sndcart x) = &0}`;
4173         `IMAGE (\x. inv(drop(sndcart x)) % x)
4174            {x:real^(N,1)finite_sum | x IN c /\ ~(drop(sndcart x) = &0)}`] THEN
4175       ASM_SIMP_TAC[FINITE_IMAGE; FINITE_RESTRICT; FORALL_IN_IMAGE] THEN
4176       SIMP_TAC[IN_ELIM_THM; SNDCART_CMUL; DROP_CMUL; REAL_MUL_LINV] THEN
4177       SUBGOAL_THEN
4178        `!x:real^(N,1)finite_sum. x IN c ==> &0 <= drop(sndcart x)`
4179       ASSUME_TAC THENL
4180        [GEN_TAC THEN DISCH_TAC THEN
4181         SUBGOAL_THEN `(x:real^(N,1)finite_sum) IN s'` MP_TAC THENL
4182          [ASM_MESON_TAC[HULL_INC]; EXPAND_TAC "s'"] THEN
4183         SIMP_TAC[IN_ELIM_THM];
4184         ALL_TAC] THEN
4185       MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THEN
4186       MATCH_MP_TAC HULL_MINIMAL THEN
4187       REWRITE_TAC[CONVEX_CONE_CONVEX_CONE_HULL; UNION_SUBSET] THEN
4188       SIMP_TAC[SUBSET; IN_ELIM_THM; HULL_INC; FORALL_IN_IMAGE] THEN
4189       X_GEN_TAC `x:real^(N,1)finite_sum` THEN DISCH_TAC THEN
4190       FIRST_X_ASSUM(MP_TAC o SPEC `x:real^(N,1)finite_sum`) THEN
4191       ASM_SIMP_TAC[CONVEX_CONE_HULL_MUL; HULL_INC; REAL_LE_INV_EQ] THEN
4192       ASM_REWRITE_TAC[REAL_ARITH `&0 <= x <=> x = &0 \/ &0 < x`] THEN
4193       STRIP_TAC THENL
4194        [MATCH_MP_TAC HULL_INC THEN ASM_REWRITE_TAC[IN_UNION; IN_ELIM_THM];
4195         SUBGOAL_THEN
4196          `x:real^(N,1)finite_sum =
4197                 drop(sndcart x) % inv(drop(sndcart x)) % x`
4198         SUBST1_TAC THENL
4199          [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; REAL_LT_IMP_NZ] THEN
4200           REWRITE_TAC[VECTOR_MUL_LID];
4201           MATCH_MP_TAC CONVEX_CONE_HULL_MUL THEN
4202           ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN MATCH_MP_TAC HULL_INC THEN
4203           REWRITE_TAC[IN_UNION] THEN DISJ2_TAC THEN
4204           REWRITE_TAC[IN_IMAGE] THEN EXISTS_TAC `x:real^(N,1)finite_sum` THEN
4205           ASM_SIMP_TAC[IN_ELIM_THM; REAL_LT_IMP_NZ]]]];
4206     EXISTS_TAC `IMAGE fstcart (t:real^(N,1)finite_sum->bool)` THEN
4207     EXISTS_TAC `IMAGE fstcart (u:real^(N,1)finite_sum->bool)` THEN
4208     ASM_SIMP_TAC[FINITE_IMAGE] THEN
4209     SUBGOAL_THEN `s = {x:real^N | pastecart x (vec 1:real^1) IN s'}`
4210     SUBST1_TAC THENL
4211      [MAP_EVERY EXPAND_TAC ["s"; "s'"] THEN
4212       REWRITE_TAC[IN_ELIM_THM; SNDCART_PASTECART; DROP_VEC; REAL_POS] THEN
4213       GEN_REWRITE_TAC I [EXTENSION] THEN
4214       REWRITE_TAC[FSTCART_PASTECART; IN_ELIM_THM; IN_INTERS; REAL_MUL_RID] THEN
4215       ASM SET_TAC[];
4216       ASM_REWRITE_TAC[CONVEX_CONE_HULL_UNION]] THEN
4217     REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN X_GEN_TAC `z:real^N` THEN
4218     SIMP_TAC[CONVEX_CONE_HULL_LINEAR_IMAGE; CONVEX_HULL_LINEAR_IMAGE;
4219              LINEAR_FSTCART] THEN
4220     REWRITE_TAC[GSYM CONJ_ASSOC; RIGHT_EXISTS_AND_THM] THEN
4221     REWRITE_TAC[EXISTS_IN_IMAGE] THEN
4222     AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
4223     X_GEN_TAC `a:real^(N,1)finite_sum` THEN REWRITE_TAC[] THEN
4224     MATCH_MP_TAC(TAUT `(p ==> (q <=> r)) ==> (p /\ q <=> p /\ r)`) THEN
4225     DISCH_TAC THEN AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN
4226     X_GEN_TAC `b:real^(N,1)finite_sum` THEN REWRITE_TAC[PASTECART_EQ] THEN
4227     REWRITE_TAC[FSTCART_PASTECART; SNDCART_PASTECART; FSTCART_ADD;
4228                 SNDCART_ADD] THEN
4229     ASM_CASES_TAC `fstcart(a:real^(N,1)finite_sum) +
4230                    fstcart(b:real^(N,1)finite_sum) = z` THEN
4231     ASM_REWRITE_TAC[] THEN
4232     SUBGOAL_THEN `sndcart(a:real^(N,1)finite_sum) = vec 0` SUBST1_TAC THENL
4233      [UNDISCH_TAC `(a:real^(N,1)finite_sum) IN convex_cone hull t` THEN
4234       SPEC_TAC(`a:real^(N,1)finite_sum`,`a:real^(N,1)finite_sum`) THEN
4235       MATCH_MP_TAC HULL_INDUCT THEN ASM_SIMP_TAC[GSYM DROP_EQ; DROP_VEC] THEN
4236       REWRITE_TAC[convex_cone; convex; conic; IN_ELIM_THM] THEN
4237       SIMP_TAC[SNDCART_ADD; SNDCART_CMUL; DROP_ADD; DROP_CMUL] THEN
4238       REWRITE_TAC[REAL_MUL_RZERO; REAL_ADD_RID; GSYM MEMBER_NOT_EMPTY] THEN
4239       EXISTS_TAC `vec 0:real^(N,1)finite_sum` THEN
4240       REWRITE_TAC[IN_ELIM_THM; SNDCART_VEC; DROP_VEC];
4241       REWRITE_TAC[VECTOR_ADD_LID]] THEN
4242     ASM_CASES_TAC `u:real^(N,1)finite_sum->bool = {}` THENL
4243      [ASM_REWRITE_TAC[CONVEX_CONE_HULL_EMPTY; CONVEX_HULL_EMPTY] THEN
4244       REWRITE_TAC[IN_SING; NOT_IN_EMPTY] THEN
4245       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4246       ASM_REWRITE_TAC[SNDCART_VEC; VEC_EQ] THEN ARITH_TAC;
4247       ALL_TAC] THEN
4248     ASM_SIMP_TAC[CONVEX_CONE_HULL_CONVEX_HULL_NONEMPTY; IN_ELIM_THM] THEN
4249     SUBGOAL_THEN
4250      `!y:real^(N,1)finite_sum. y IN convex hull u ==> sndcart y = vec 1`
4251      (LABEL_TAC "*")
4252     THENL
4253      [MATCH_MP_TAC HULL_INDUCT THEN ASM_SIMP_TAC[GSYM DROP_EQ; DROP_VEC] THEN
4254       REWRITE_TAC[convex; IN_ELIM_THM] THEN
4255       SIMP_TAC[SNDCART_ADD; SNDCART_CMUL; DROP_ADD; DROP_CMUL] THEN
4256       SIMP_TAC[REAL_MUL_RID];
4257       ALL_TAC] THEN
4258     EQ_TAC THEN REWRITE_TAC[LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THENL
4259      [MAP_EVERY X_GEN_TAC [`c:real`; `d:real^(N,1)finite_sum`] THEN
4260       DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
4261       ASM_SIMP_TAC[SNDCART_CMUL; VECTOR_MUL_EQ_0; VECTOR_ARITH
4262        `x:real^N = c % x <=> (c - &1) % x = vec 0`] THEN
4263       ASM_SIMP_TAC[REAL_SUB_0; VEC_EQ; ARITH_EQ; VECTOR_MUL_LID];
4264       DISCH_TAC THEN ASM_SIMP_TAC[] THEN EXISTS_TAC `&1` THEN
4265       ASM_REWRITE_TAC[REAL_POS; VECTOR_MUL_LID] THEN ASM_MESON_TAC[]]]);;
4266
4267 let POLYHEDRON_LINEAR_IMAGE = prove
4268  (`!f:real^M->real^N s.
4269         linear f /\ polyhedron s ==> polyhedron(IMAGE f s)`,
4270   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4271   REWRITE_TAC[POLYHEDRON_AS_CONE_PLUS_CONV; LEFT_IMP_EXISTS_THM] THEN
4272   MAP_EVERY X_GEN_TAC [`t:real^M->bool`; `u:real^M->bool`] THEN STRIP_TAC THEN
4273   EXISTS_TAC `IMAGE (f:real^M->real^N) t` THEN
4274   EXISTS_TAC `IMAGE (f:real^M->real^N) u` THEN
4275   ASM_SIMP_TAC[FINITE_IMAGE] THEN
4276   ASM_SIMP_TAC[CONVEX_CONE_HULL_LINEAR_IMAGE; CONVEX_HULL_LINEAR_IMAGE] THEN
4277   REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM] THEN
4278   FIRST_X_ASSUM(MP_TAC o MATCH_MP LINEAR_ADD) THEN MESON_TAC[]);;
4279
4280 let POLYHEDRON_SUMS = prove
4281  (`!s t:real^N->bool.
4282     polyhedron s /\ polyhedron t ==> polyhedron {x + y | x IN s /\ y IN t}`,
4283   REPEAT GEN_TAC THEN REWRITE_TAC[POLYHEDRON_AS_CONE_PLUS_CONV] THEN
4284   REWRITE_TAC[LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
4285   REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
4286   MAP_EVERY X_GEN_TAC
4287    [`t1:real^N->bool`; `u1:real^N->bool`;
4288     `t2:real^N->bool`; `u2:real^N->bool`] THEN
4289   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4290   EXISTS_TAC `t1 UNION t2:real^N->bool` THEN
4291   EXISTS_TAC `{u + v:real^N | u IN u1 /\ v IN u2}` THEN
4292   REWRITE_TAC[CONVEX_CONE_HULL_UNION; CONVEX_HULL_SUMS] THEN
4293   ASM_SIMP_TAC[FINITE_PRODUCT_DEPENDENT; FINITE_UNION] THEN
4294   REWRITE_TAC[SET_RULE
4295    `{h x y | x IN {f a b | P a /\ Q b} /\
4296              y IN {g a b | R a /\ S b}} =
4297     {h (f a b) (g c d) | P a /\ Q b /\ R c /\ S d}`] THEN
4298   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN MESON_TAC[VECTOR_ADD_AC]);;
4299
4300 (* ------------------------------------------------------------------------- *)
4301 (* Farkas's lemma (2 variants) and stronger separation for polyhedra.        *)
4302 (* ------------------------------------------------------------------------- *)
4303
4304 let FARKAS_LEMMA = prove
4305  (`!A:real^N^M b.
4306         (?x:real^N.
4307             A ** x = b /\
4308             (!i. 1 <= i /\ i <= dimindex(:N) ==> &0 <= x$i)) <=>
4309         ~(?y:real^M.
4310             b dot y < &0 /\
4311             (!i. 1 <= i /\ i <= dimindex(:N) ==> &0 <= (transp A ** y)$i))`,
4312   REPEAT STRIP_TAC THEN MATCH_MP_TAC(TAUT
4313    `(q ==> ~p) /\ (~p ==> q) ==> (p <=> ~q)`) THEN
4314   CONJ_TAC THENL
4315    [REPEAT STRIP_TAC THEN
4316     SUBGOAL_THEN `y dot ((A:real^N^M) ** x - b) = &0` MP_TAC THENL
4317      [ASM_REWRITE_TAC[VECTOR_SUB_REFL; DOT_RZERO]; ALL_TAC] THEN
4318     RULE_ASSUM_TAC(ONCE_REWRITE_RULE[DOT_SYM]) THEN
4319     REWRITE_TAC[DOT_RSUB; REAL_SUB_0] THEN
4320     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
4321      `y < &0 ==> &0 <= x ==> ~(x = y)`)) THEN
4322     ONCE_REWRITE_TAC[GSYM DOT_LMUL_MATRIX] THEN
4323     REWRITE_TAC[VECTOR_MATRIX_MUL_TRANSP; dot] THEN
4324     MATCH_MP_TAC SUM_POS_LE THEN
4325     ASM_SIMP_TAC[REAL_LE_MUL; IN_NUMSEG; FINITE_NUMSEG];
4326     DISCH_TAC THEN MP_TAC(ISPECL
4327      [`{(A:real^N^M) ** (x:real^N) |
4328         !i. 1 <= i /\ i <= dimindex(:N) ==> &0 <= x$i}`;
4329       `b:real^M`] SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
4330     REWRITE_TAC[FORALL_IN_GSPEC] THEN ANTS_TAC THENL
4331      [REWRITE_TAC[IN_ELIM_THM; CONJ_ASSOC] THEN
4332       CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
4333       ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN
4334       SIMP_TAC[CONVEX_POSITIVE_ORTHANT; CONVEX_LINEAR_IMAGE;
4335                MATRIX_VECTOR_MUL_LINEAR] THEN
4336       MATCH_MP_TAC POLYHEDRON_IMP_CLOSED THEN
4337       MATCH_MP_TAC POLYHEDRON_LINEAR_IMAGE THEN
4338       REWRITE_TAC[MATRIX_VECTOR_MUL_LINEAR; POLYHEDRON_POSITIVE_ORTHANT];
4339       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real^M` THEN
4340       DISCH_THEN(X_CHOOSE_THEN `c:real` STRIP_ASSUME_TAC) THEN
4341       ONCE_REWRITE_TAC[DOT_SYM] THEN
4342       FIRST_ASSUM(MP_TAC o SPEC `vec 0:real^N`) THEN
4343       REWRITE_TAC[MATRIX_VECTOR_MUL_RZERO; DOT_RZERO] THEN
4344       REWRITE_TAC[real_gt; VEC_COMPONENT; REAL_LE_REFL] THEN
4345       DISCH_TAC THEN CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
4346       X_GEN_TAC `k:num` THEN STRIP_TAC THEN
4347       ONCE_REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
4348       FIRST_X_ASSUM(MP_TAC o SPEC
4349        `c / (transp(A:real^N^M) ** (y:real^M))$k % basis k:real^N`) THEN
4350       ASM_SIMP_TAC[VECTOR_MUL_COMPONENT; BASIS_COMPONENT] THEN
4351       ONCE_REWRITE_TAC[GSYM DOT_LMUL_MATRIX] THEN
4352       ASM_SIMP_TAC[DOT_RMUL; DOT_BASIS; VECTOR_MATRIX_MUL_TRANSP] THEN
4353       ASM_SIMP_TAC[REAL_FIELD `y < &0 ==> x / y * y = x`] THEN
4354       REWRITE_TAC[REAL_LT_REFL; real_gt] THEN
4355       GEN_TAC THEN COND_CASES_TAC THEN
4356       ASM_REWRITE_TAC[REAL_MUL_RZERO; REAL_LE_REFL; REAL_MUL_RID] THEN
4357       ONCE_REWRITE_TAC[REAL_ARITH `x / y:real = --x * -- inv y`] THEN
4358       MATCH_MP_TAC REAL_LE_MUL THEN
4359       REWRITE_TAC[REAL_ARITH `&0 <= --x <=> ~(&0 < x)`; REAL_LT_INV_EQ] THEN
4360       ASM_REAL_ARITH_TAC]]);;
4361
4362 let FARKAS_LEMMA_ALT = prove
4363  (`!A:real^N^M b.
4364         (?x:real^N.
4365             (!i. 1 <= i /\ i <= dimindex(:M) ==> (A ** x)$i <= b$i)) <=>
4366         ~(?y:real^M.
4367             (!i. 1 <= i /\ i <= dimindex(:M) ==> &0 <= y$i) /\
4368             y ** A = vec 0 /\ b dot y < &0)`,
4369   REPEAT GEN_TAC THEN
4370   MATCH_MP_TAC(TAUT `~(p /\ q) /\ (~p ==> q) ==> (p <=> ~q)`) THEN
4371   REPEAT STRIP_TAC THENL
4372    [SUBGOAL_THEN `&0 <= (b - (A:real^N^M) ** x) dot y` MP_TAC THENL
4373      [REWRITE_TAC[dot] THEN MATCH_MP_TAC SUM_POS_LE THEN
4374       REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
4375       REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_MUL THEN
4376       ASM_SIMP_TAC[VECTOR_SUB_COMPONENT; REAL_SUB_LE];
4377       REWRITE_TAC[DOT_LSUB; REAL_SUB_LE] THEN REWRITE_TAC[REAL_NOT_LE] THEN
4378       GEN_REWRITE_TAC RAND_CONV [DOT_SYM] THEN
4379       REWRITE_TAC[GSYM DOT_LMUL_MATRIX] THEN
4380       ASM_REWRITE_TAC[DOT_LZERO]];
4381     MP_TAC(ISPECL
4382      [`{(A:real^N^M) ** (x:real^N) + s |x,s|
4383         !i. 1 <= i /\ i <= dimindex(:M) ==> &0 <= s$i}`;
4384       `b:real^M`] SEPARATING_HYPERPLANE_CLOSED_POINT) THEN
4385     REWRITE_TAC[FORALL_IN_GSPEC] THEN ANTS_TAC THENL
4386      [REWRITE_TAC[IN_ELIM_THM; CONJ_ASSOC] THEN CONJ_TAC THENL
4387        [ONCE_REWRITE_TAC[SET_RULE
4388          `{f x + y | x,y | P y} =
4389           {z + y | z,y | z IN IMAGE (f:real^M->real^N) (:real^M) /\
4390                          y IN {w | P w}}`] THEN
4391         SIMP_TAC[CONVEX_SUMS; CONVEX_POSITIVE_ORTHANT; CONVEX_LINEAR_IMAGE;
4392                  MATRIX_VECTOR_MUL_LINEAR; CONVEX_UNIV] THEN
4393         MATCH_MP_TAC POLYHEDRON_IMP_CLOSED THEN
4394         MATCH_MP_TAC POLYHEDRON_SUMS THEN
4395         ASM_SIMP_TAC[POLYHEDRON_LINEAR_IMAGE; POLYHEDRON_UNIV;
4396           MATRIX_VECTOR_MUL_LINEAR; POLYHEDRON_POSITIVE_ORTHANT];
4397         POP_ASSUM MP_TAC THEN REWRITE_TAC[CONTRAPOS_THM] THEN
4398         MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN
4399         ASM_SIMP_TAC[VECTOR_ADD_COMPONENT; REAL_LE_ADDR]];
4400       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real^M` THEN
4401       DISCH_THEN(X_CHOOSE_THEN `c:real` STRIP_ASSUME_TAC) THEN
4402       ONCE_REWRITE_TAC[DOT_SYM] THEN
4403       FIRST_ASSUM(MP_TAC o SPECL [`vec 0:real^N`; `vec 0:real^M`]) THEN
4404       REWRITE_TAC[MATRIX_VECTOR_MUL_RZERO; VECTOR_ADD_RID; DOT_RZERO] THEN
4405       REWRITE_TAC[real_gt; VEC_COMPONENT; REAL_LE_REFL] THEN
4406       DISCH_TAC THEN REWRITE_TAC[CONJ_ASSOC] THEN
4407       CONJ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN CONJ_TAC THENL
4408        [X_GEN_TAC `k:num` THEN STRIP_TAC THEN
4409         ONCE_REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
4410         FIRST_X_ASSUM(MP_TAC o SPECL
4411          [`vec 0:real^N`; `--c / --((y:real^M)$k) % basis k:real^M`]) THEN
4412         ASM_SIMP_TAC[MATRIX_VECTOR_MUL_RZERO; VECTOR_ADD_LID;
4413                      DOT_RMUL; DOT_BASIS; REAL_FIELD
4414                       `y < &0 ==> c / --y * y = --c`] THEN
4415         SIMP_TAC[REAL_NEG_NEG; REAL_LT_REFL; VECTOR_MUL_COMPONENT; real_gt] THEN
4416         ASM_SIMP_TAC[BASIS_COMPONENT] THEN REPEAT STRIP_TAC THEN
4417         COND_CASES_TAC THEN
4418         ASM_REWRITE_TAC[REAL_MUL_RZERO; REAL_MUL_RID; REAL_LE_REFL] THEN
4419         MATCH_MP_TAC REAL_LE_DIV THEN ASM_REAL_ARITH_TAC;
4420         FIRST_X_ASSUM(MP_TAC o SPECL
4421          [`c / norm((y:real^M) ** (A:real^N^M)) pow 2 %
4422            (transp A ** y)`; `vec 0:real^M`]) THEN
4423         SIMP_TAC[VEC_COMPONENT; REAL_LE_REFL; VECTOR_ADD_RID] THEN
4424         ONCE_REWRITE_TAC[GSYM DOT_LMUL_MATRIX] THEN
4425         REWRITE_TAC[GSYM VECTOR_MATRIX_MUL_TRANSP; DOT_RMUL] THEN
4426         ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
4427         ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_POW_2; DOT_EQ_0] THEN
4428         REAL_ARITH_TAC]]]);;
4429
4430 let SEPARATING_HYPERPLANE_POLYHEDRA = prove
4431  (`!s t:real^N->bool.
4432         polyhedron s /\ polyhedron t /\ ~(s = {}) /\ ~(t = {}) /\ DISJOINT s t
4433         ==> ?a b. ~(a = vec 0) /\
4434                   (!x. x IN s ==> a dot x < b) /\
4435                   (!x. x IN t ==> a dot x > b)`,
4436   REPEAT STRIP_TAC THEN
4437   MP_TAC(ISPEC `{x + y:real^N | x IN s /\ y IN IMAGE (--) t}`
4438         SEPARATING_HYPERPLANE_CLOSED_0) THEN
4439   ANTS_TAC THENL
4440    [ASM_SIMP_TAC[CONVEX_SUMS; CONVEX_NEGATIONS; POLYHEDRON_IMP_CONVEX] THEN
4441     CONJ_TAC THENL
4442      [MATCH_MP_TAC POLYHEDRON_IMP_CLOSED THEN
4443       MATCH_MP_TAC POLYHEDRON_SUMS THEN ASM_SIMP_TAC[POLYHEDRON_NEGATIONS];
4444       REWRITE_TAC[IN_IMAGE; IN_ELIM_THM] THEN
4445       REWRITE_TAC[VECTOR_ARITH `y = --x:real^N <=> --y = x`] THEN
4446       REWRITE_TAC[UNWIND_THM1] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
4447       REWRITE_TAC[VECTOR_ARITH `vec 0:real^N = x + y <=> y = --x`] THEN
4448       REWRITE_TAC[UNWIND_THM2; VECTOR_NEG_NEG] THEN ASM SET_TAC[]];
4449     REWRITE_TAC[FORALL_IN_GSPEC; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
4450     REWRITE_TAC[FORALL_IN_IMAGE; GSYM VECTOR_SUB; LEFT_IMP_EXISTS_THM] THEN
4451     MAP_EVERY X_GEN_TAC [`a:real^N`; `k:real`] THEN
4452     REWRITE_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP; DOT_RSUB] THEN STRIP_TAC THEN
4453     EXISTS_TAC `--a:real^N` THEN ASM_REWRITE_TAC[VECTOR_NEG_EQ_0] THEN
4454     MP_TAC(ISPEC `IMAGE (\x:real^N. a dot x) s` INF) THEN
4455     MP_TAC(ISPEC `IMAGE (\x:real^N. a dot x) t` SUP) THEN
4456     ASM_REWRITE_TAC[FORALL_IN_IMAGE; IMAGE_EQ_EMPTY] THEN
4457     MAP_EVERY ABBREV_TAC
4458      [`u = inf(IMAGE (\x:real^N. a dot x) s)`;
4459       `v = sup(IMAGE (\x:real^N. a dot x) t)`] THEN
4460     ANTS_TAC THENL
4461      [MP_TAC(GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]
4462         (ASSUME `~(s:real^N->bool = {})`)) THEN
4463       DISCH_THEN(X_CHOOSE_TAC `z:real^N`) THEN
4464       EXISTS_TAC `a dot (z:real^N) - k` THEN
4465       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4466       FIRST_X_ASSUM(MP_TAC o SPECL [`z:real^N`; `x:real^N`]) THEN
4467       ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
4468       STRIP_TAC] THEN
4469     ANTS_TAC THENL
4470      [MP_TAC(GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]
4471         (ASSUME `~(t:real^N->bool = {})`)) THEN
4472       DISCH_THEN(X_CHOOSE_TAC `z:real^N`) THEN
4473       EXISTS_TAC `a dot (z:real^N) + k` THEN
4474       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4475       FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `z:real^N`]) THEN
4476       ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC;
4477       STRIP_TAC] THEN
4478     SUBGOAL_THEN `k <= u - v` ASSUME_TAC THENL
4479      [REWRITE_TAC[REAL_LE_SUB_LADD] THEN EXPAND_TAC "u" THEN
4480       MATCH_MP_TAC REAL_LE_INF THEN
4481       ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
4482       GEN_TAC THEN DISCH_TAC THEN
4483       ONCE_REWRITE_TAC[REAL_ARITH `k + v <= u <=> v <= u - k`] THEN
4484       EXPAND_TAC "v" THEN MATCH_MP_TAC REAL_SUP_LE THEN
4485       ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
4486       ASM_MESON_TAC[REAL_ARITH `x - y > k ==> y <= x - k`];
4487       EXISTS_TAC `--((u + v) / &2)` THEN REWRITE_TAC[real_gt] THEN
4488       REWRITE_TAC[DOT_LNEG; REAL_LT_NEG2] THEN REPEAT STRIP_TAC THENL
4489        [MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `u:real`;
4490         MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `v:real`] THEN
4491       ASM_SIMP_TAC[] THEN ASM_REAL_ARITH_TAC]]);;
4492
4493 (* ------------------------------------------------------------------------- *)
4494 (* Relative and absolute frontier of a polytope.                             *)
4495 (* ------------------------------------------------------------------------- *)
4496
4497 let RELATIVE_BOUNDARY_OF_CONVEX_HULL = prove
4498  (`!s:real^N->bool.
4499         ~affine_dependent s
4500         ==> (convex hull s) DIFF relative_interior(convex hull s) =
4501             UNIONS { convex hull (s DELETE a) | a | a IN s}`,
4502   REPEAT STRIP_TAC THEN
4503   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
4504   REPEAT_TCL DISJ_CASES_THEN MP_TAC (ARITH_RULE
4505     `CARD(s:real^N->bool) = 0 \/ CARD s = 1 \/ 2 <= CARD s`)
4506   THENL
4507    [ASM_SIMP_TAC[CARD_EQ_0; CONVEX_HULL_EMPTY] THEN SET_TAC[];
4508     DISCH_TAC THEN MP_TAC(HAS_SIZE_CONV `(s:real^N->bool) HAS_SIZE 1`) THEN
4509     ASM_SIMP_TAC[HAS_SIZE; LEFT_IMP_EXISTS_THM; CONVEX_HULL_SING] THEN
4510     REWRITE_TAC[RELATIVE_INTERIOR_SING; DIFF_EQ_EMPTY] THEN
4511     REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN REWRITE_TAC[EMPTY_UNIONS] THEN
4512     REWRITE_TAC[FORALL_IN_GSPEC; IN_SING; FORALL_UNWIND_THM2] THEN
4513     REWRITE_TAC[CONVEX_HULL_EQ_EMPTY] THEN SET_TAC[];
4514     DISCH_TAC THEN
4515     ASM_SIMP_TAC[POLYHEDRON_CONVEX_HULL; RELATIVE_BOUNDARY_OF_POLYHEDRON] THEN
4516     ASM_SIMP_TAC[FACET_OF_CONVEX_HULL_AFFINE_INDEPENDENT_ALT] THEN
4517     SET_TAC[]]);;
4518
4519 let RELATIVE_FRONTIER_OF_CONVEX_HULL = prove
4520  (`!s:real^N->bool.
4521         ~affine_dependent s
4522         ==> relative_frontier(convex hull s) =
4523             UNIONS { convex hull (s DELETE a) | a | a IN s}`,
4524   REPEAT STRIP_TAC THEN
4525   FIRST_ASSUM(ASSUME_TAC o MATCH_MP AFFINE_INDEPENDENT_IMP_FINITE) THEN
4526   ASM_SIMP_TAC[relative_frontier; GSYM RELATIVE_BOUNDARY_OF_CONVEX_HULL] THEN
4527   AP_THM_TAC THEN AP_TERM_TAC THEN MATCH_MP_TAC CLOSURE_CLOSED THEN
4528   ASM_SIMP_TAC[COMPACT_IMP_CLOSED; FINITE_IMP_COMPACT; COMPACT_CONVEX_HULL]);;
4529
4530 let FRONTIER_OF_CONVEX_HULL = prove
4531  (`!s:real^N->bool.
4532         s HAS_SIZE (dimindex(:N) + 1)
4533         ==> frontier(convex hull s) =
4534                UNIONS { convex hull (s DELETE a) | a | a IN s}`,
4535   REWRITE_TAC[HAS_SIZE] THEN REPEAT STRIP_TAC THEN
4536   ASM_CASES_TAC `affine_dependent(s:real^N->bool)` THENL
4537    [REWRITE_TAC[frontier] THEN MATCH_MP_TAC EQ_TRANS THEN
4538     EXISTS_TAC `(convex hull s:real^N->bool) DIFF {}` THEN CONJ_TAC THENL
4539      [BINOP_TAC THEN
4540       ASM_SIMP_TAC[INTERIOR_CONVEX_HULL_EQ_EMPTY; frontier; HAS_SIZE] THEN
4541       MATCH_MP_TAC CLOSURE_CLOSED THEN
4542       ASM_SIMP_TAC[CLOSURE_CLOSED; COMPACT_IMP_CLOSED; COMPACT_CONVEX_HULL;
4543                    FINITE_IMP_COMPACT; FINITE_INSERT; FINITE_EMPTY];
4544       REWRITE_TAC[DIFF_EMPTY] THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
4545       CONJ_TAC THENL
4546        [GEN_REWRITE_TAC LAND_CONV [CARATHEODORY_AFF_DIM] THEN
4547         ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
4548         GEN_REWRITE_TAC I [SUBSET] THEN
4549         REWRITE_TAC[IN_ELIM_THM; UNIONS_IMAGE] THEN
4550         X_GEN_TAC `x:real^N` THEN
4551         DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
4552         MP_TAC(ISPEC `s:real^N->bool` AFFINE_INDEPENDENT_IFF_CARD) THEN
4553         ASM_REWRITE_TAC[GSYM INT_OF_NUM_ADD] THEN
4554         REWRITE_TAC[INT_ARITH `(x + &1) - &1:int = x`] THEN DISCH_TAC THEN
4555         SUBGOAL_THEN `(t:real^N->bool) PSUBSET s` ASSUME_TAC THENL
4556          [ASM_REWRITE_TAC[PSUBSET] THEN
4557           DISCH_THEN(MP_TAC o AP_TERM `CARD:(real^N->bool)->num`) THEN
4558           MATCH_MP_TAC(ARITH_RULE `t:num < s ==> t = s ==> F`) THEN
4559           ASM_REWRITE_TAC[ARITH_RULE `x < n + 1 <=> x <= n`] THEN
4560           REWRITE_TAC[GSYM INT_OF_NUM_LE] THEN MATCH_MP_TAC INT_LE_TRANS THEN
4561           EXISTS_TAC `aff_dim(s:real^N->bool) + &1` THEN
4562           ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(INT_ARITH
4563            `s:int <= n /\ ~(s = n) ==> s + &1 <= n`) THEN
4564           ASM_REWRITE_TAC[AFF_DIM_LE_UNIV];
4565           SUBGOAL_THEN `?a:real^N. a IN s /\ ~(a IN t)` MP_TAC THENL
4566            [ASM SET_TAC[]; MATCH_MP_TAC MONO_EXISTS] THEN
4567           X_GEN_TAC `a:real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4568           SUBGOAL_THEN
4569            `(convex hull t) SUBSET convex hull (s DELETE (a:real^N))`
4570           MP_TAC THENL
4571            [MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]; ASM SET_TAC[]]];
4572         ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN REWRITE_TAC[UNIONS_IMAGE] THEN
4573         REWRITE_TAC[SUBSET; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
4574         ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
4575         REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; GSYM SUBSET] THEN
4576         REPEAT STRIP_TAC THEN MATCH_MP_TAC HULL_MONO THEN SET_TAC[]]];
4577     MATCH_MP_TAC EQ_TRANS THEN
4578     EXISTS_TAC
4579      `(convex hull s) DIFF relative_interior(convex hull s):real^N->bool` THEN
4580     CONJ_TAC THENL
4581      [ASM_SIMP_TAC[GSYM RELATIVE_BOUNDARY_OF_CONVEX_HULL; frontier] THEN
4582       BINOP_TAC THENL
4583        [MATCH_MP_TAC CLOSURE_CLOSED THEN
4584         ASM_SIMP_TAC[CLOSURE_CLOSED; COMPACT_IMP_CLOSED; COMPACT_CONVEX_HULL;
4585                      FINITE_IMP_COMPACT; FINITE_INSERT; FINITE_EMPTY];
4586         CONV_TAC SYM_CONV THEN MATCH_MP_TAC RELATIVE_INTERIOR_INTERIOR THEN
4587         REWRITE_TAC[AFFINE_HULL_CONVEX_HULL] THEN
4588         REWRITE_TAC[GSYM AFF_DIM_EQ_FULL] THEN
4589         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I
4590           [AFFINE_INDEPENDENT_IFF_CARD]) THEN
4591         ASM_REWRITE_TAC[GSYM INT_OF_NUM_ADD] THEN INT_ARITH_TAC];
4592       ASM_SIMP_TAC[RELATIVE_BOUNDARY_OF_POLYHEDRON;
4593                    POLYHEDRON_CONVEX_HULL; FINITE_INSERT; FINITE_EMPTY] THEN
4594       ASM_SIMP_TAC[FACET_OF_CONVEX_HULL_AFFINE_INDEPENDENT_ALT] THEN
4595       REWRITE_TAC[ARITH_RULE `2 <= n + 1 <=> 1 <= n`; DIMINDEX_GE_1] THEN
4596       ASM SET_TAC[]]]);;
4597
4598 (* ------------------------------------------------------------------------- *)
4599 (* Special case of a triangle.                                               *)
4600 (* ------------------------------------------------------------------------- *)
4601
4602 let RELATIVE_BOUNDARY_OF_TRIANGLE = prove
4603  (`!a b c:real^N.
4604         ~collinear {a,b,c}
4605         ==> convex hull {a,b,c} DIFF relative_interior(convex hull {a,b,c}) =
4606             segment[a,b] UNION segment[b,c] UNION segment[c,a]`,
4607   REPEAT STRIP_TAC THEN
4608   ONCE_REWRITE_TAC[SET_RULE `s UNION t UNION u = t UNION u UNION s`] THEN
4609   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV
4610    [COLLINEAR_3_EQ_AFFINE_DEPENDENT]) THEN
4611   REWRITE_TAC[DE_MORGAN_THM; SEGMENT_CONVEX_HULL] THEN STRIP_TAC THEN
4612   ASM_SIMP_TAC[RELATIVE_BOUNDARY_OF_CONVEX_HULL] THEN
4613   ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
4614   REWRITE_TAC[IMAGE_CLAUSES; UNIONS_INSERT; UNIONS_0; UNION_EMPTY] THEN
4615   REPEAT BINOP_TAC THEN REWRITE_TAC[] THEN ASM SET_TAC[]);;
4616
4617 let RELATIVE_FRONTIER_OF_TRIANGLE = prove
4618  (`!a b c:real^N.
4619         ~collinear {a,b,c}
4620         ==> relative_frontier(convex hull {a,b,c}) =
4621             segment[a,b] UNION segment[b,c] UNION segment[c,a]`,
4622   REPEAT STRIP_TAC THEN
4623   ASM_SIMP_TAC[GSYM RELATIVE_BOUNDARY_OF_TRIANGLE; relative_frontier] THEN
4624   AP_THM_TAC THEN AP_TERM_TAC THEN MATCH_MP_TAC CLOSURE_CLOSED THEN
4625   ASM_SIMP_TAC[COMPACT_IMP_CLOSED; FINITE_IMP_COMPACT; COMPACT_CONVEX_HULL;
4626                FINITE_INSERT; FINITE_EMPTY]);;
4627
4628 let FRONTIER_OF_TRIANGLE = prove
4629  (`!a b c:real^2.
4630         frontier(convex hull {a,b,c}) =
4631             segment[a,b] UNION segment[b,c] UNION segment[c,a]`,
4632   REPEAT STRIP_TAC THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN
4633   ONCE_REWRITE_TAC[SET_RULE `s UNION t UNION u = t UNION u UNION s`] THEN
4634   MAP_EVERY (fun t -> ASM_CASES_TAC t THENL
4635    [ASM_REWRITE_TAC[INSERT_AC; UNION_ACI] THEN
4636     SIMP_TAC[GSYM SEGMENT_CONVEX_HULL; frontier; CLOSURE_SEGMENT;
4637              INTERIOR_SEGMENT; DIMINDEX_2; LE_REFL; DIFF_EMPTY] THEN
4638     REWRITE_TAC[CONVEX_HULL_SING] THEN
4639     REWRITE_TAC[SET_RULE `s = s UNION {a} <=> a IN s`;
4640                 SET_RULE `s = {a} UNION s <=> a IN s`] THEN
4641     REWRITE_TAC[ENDS_IN_SEGMENT];
4642     ALL_TAC])
4643    [`b:real^2 = a`; `c:real^2 = a`; `c:real^2 = b`] THEN
4644   SUBGOAL_THEN `{a:real^2,b,c} HAS_SIZE (dimindex(:2) + 1)` ASSUME_TAC THENL
4645    [SIMP_TAC[HAS_SIZE; CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
4646     ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; DIMINDEX_2] THEN
4647     CONV_TAC NUM_REDUCE_CONV;
4648     ASM_SIMP_TAC[FRONTIER_OF_CONVEX_HULL] THEN
4649     ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
4650     REWRITE_TAC[IMAGE_CLAUSES; UNIONS_INSERT; UNIONS_0; UNION_EMPTY] THEN
4651     REPEAT BINOP_TAC THEN REWRITE_TAC[] THEN ASM SET_TAC[]]);;
4652
4653 let INSIDE_OF_TRIANGLE = prove
4654  (`!a b c:real^2.
4655         inside(segment[a,b] UNION segment[b,c] UNION segment[c,a]) =
4656                 interior(convex hull {a,b,c})`,
4657   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM FRONTIER_OF_TRIANGLE] THEN
4658   MATCH_MP_TAC INSIDE_FRONTIER_EQ_INTERIOR THEN
4659   REWRITE_TAC[CONVEX_CONVEX_HULL] THEN MATCH_MP_TAC BOUNDED_CONVEX_HULL THEN
4660   MATCH_MP_TAC FINITE_IMP_BOUNDED THEN
4661   REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY]);;
4662
4663 let INTERIOR_OF_TRIANGLE = prove
4664  (`!a b c:real^2.
4665         interior(convex hull {a,b,c}) =
4666         (convex hull {a,b,c}) DIFF
4667         (segment[a,b] UNION segment[b,c] UNION segment[c,a])`,
4668   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM FRONTIER_OF_TRIANGLE; frontier] THEN
4669   MATCH_MP_TAC(SET_RULE `i SUBSET s /\ c = s ==> i = s DIFF (c DIFF i)`) THEN
4670   REWRITE_TAC[INTERIOR_SUBSET] THEN MATCH_MP_TAC CLOSURE_CONVEX_HULL THEN
4671   SIMP_TAC[FINITE_IMP_COMPACT; FINITE_INSERT; FINITE_EMPTY]);;
4672
4673 (* ------------------------------------------------------------------------- *)
4674 (* A ridge is the intersection of precisely two facets.                      *)
4675 (* ------------------------------------------------------------------------- *)
4676
4677 let POLYHEDRON_RIDGE_TWO_FACETS = prove
4678  (`!p:real^N->bool r.
4679     polyhedron p /\ r face_of p /\ ~(r = {}) /\ aff_dim r = aff_dim p - &2
4680     ==> ?f1 f2. f1 face_of p /\ aff_dim f1 = aff_dim p - &1 /\
4681                 f2 face_of p /\ aff_dim f2 = aff_dim p - &1 /\
4682                  ~(f1 = f2) /\ r SUBSET f1 /\ r SUBSET f2 /\ f1 INTER f2 = r /\
4683                 !f. f face_of p /\ aff_dim f = aff_dim p - &1 /\ r SUBSET f
4684                     ==> f = f1 \/ f = f2`,
4685   REPEAT STRIP_TAC THEN
4686   MP_TAC(ISPECL [`p:real^N->bool`; `r:real^N->bool`] FACE_OF_POLYHEDRON) THEN
4687   ANTS_TAC THENL [ASM_MESON_TAC[INT_ARITH `~(p:int = p - &2)`]; ALL_TAC] THEN
4688   SUBGOAL_THEN `&2 <= aff_dim(p:real^N->bool)` ASSUME_TAC THENL
4689    [MP_TAC(ISPEC `r:real^N->bool` AFF_DIM_GE) THEN
4690     MP_TAC(ISPEC `r:real^N->bool` AFF_DIM_EQ_MINUS1) THEN
4691     ASM_REWRITE_TAC[] THEN INT_ARITH_TAC;
4692     ALL_TAC] THEN
4693   SUBGOAL_THEN
4694    `{f:real^N->bool | f facet_of p /\ r SUBSET f} =
4695     {f | f face_of p /\ aff_dim f = aff_dim p - &1 /\ r SUBSET f}`
4696   SUBST1_TAC THENL
4697    [GEN_REWRITE_TAC I [EXTENSION] THEN
4698     ASM_REWRITE_TAC[IN_ELIM_THM; facet_of] THEN
4699     X_GEN_TAC `f:real^N->bool` THEN
4700     ASM_CASES_TAC `f:real^N->bool = {}` THEN
4701     ASM_REWRITE_TAC[AFF_DIM_EMPTY; GSYM CONJ_ASSOC] THEN ASM_INT_ARITH_TAC;
4702     DISCH_THEN(MP_TAC o SYM)] THEN
4703   ASM_CASES_TAC
4704    `{f:real^N->bool | f face_of p /\ aff_dim f = aff_dim p - &1 /\ r SUBSET f}
4705     = {}`
4706   THENL
4707    [ASM_REWRITE_TAC[INTERS_0] THEN DISCH_THEN(ASSUME_TAC o SYM) THEN
4708     UNDISCH_TAC `aff_dim(r:real^N->bool) = aff_dim(p:real^N->bool) - &2` THEN
4709     ASM_REWRITE_TAC[AFF_DIM_UNIV; DIMINDEX_3] THEN
4710     MP_TAC(ISPEC `p:real^N->bool` AFF_DIM_LE_UNIV) THEN INT_ARITH_TAC;
4711     ALL_TAC] THEN
4712   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
4713   REWRITE_TAC[LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN
4714   X_GEN_TAC `f1:real^N->bool` THEN STRIP_TAC THEN
4715   ASM_CASES_TAC
4716    `{f:real^N->bool | f face_of p /\ aff_dim f = aff_dim p - &1 /\ r SUBSET f}
4717     = {f1}`
4718   THENL
4719    [ASM_REWRITE_TAC[INTERS_1] THEN
4720     ASM_MESON_TAC[INT_ARITH `~(x - &2:int = x - &1)`];
4721     ALL_TAC] THEN
4722   FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE
4723    `~(s = {a}) ==> a IN s ==> ?b. ~(b = a) /\ b IN s`)) THEN
4724   ASM_REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
4725   X_GEN_TAC `f2:real^N->bool` THEN STRIP_TAC THEN
4726   ASM_CASES_TAC
4727    `{f:real^N->bool | f face_of p /\ aff_dim f = aff_dim p - &1 /\ r SUBSET f}
4728     = {f1,f2}`
4729   THENL
4730    [ASM_REWRITE_TAC[INTERS_2] THEN DISCH_TAC THEN
4731     MAP_EVERY EXISTS_TAC [`f1:real^N->bool`; `f2:real^N->bool`] THEN
4732     ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
4733     ALL_TAC] THEN
4734   FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE
4735    `~(s = {a,b})
4736     ==> a IN s /\ b IN s ==> ?c. ~(c = a) /\ ~(c = b) /\ c IN s`)) THEN
4737   ASM_REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
4738   X_GEN_TAC `f3:real^N->bool` THEN STRIP_TAC THEN DISCH_TAC THEN
4739   UNDISCH_TAC `aff_dim(r:real^N->bool) = aff_dim(p:real^N->bool) - &2` THEN
4740   MATCH_MP_TAC(TAUT `~p ==> p ==> q`) THEN
4741   MATCH_MP_TAC(INT_ARITH `~(p - &2:int <= x:int) ==> ~(x = p - &2)`) THEN
4742   DISCH_TAC THEN SUBGOAL_THEN
4743    `~(f1:real^N->bool = {}) /\
4744     ~(f2:real^N->bool = {}) /\
4745     ~(f3:real^N->bool = {})`
4746   STRIP_ASSUME_TAC THENL
4747    [REPEAT CONJ_TAC THEN DISCH_THEN SUBST_ALL_TAC THEN
4748     RULE_ASSUM_TAC(REWRITE_RULE[AFF_DIM_EMPTY]) THEN ASM_INT_ARITH_TAC;
4749     ALL_TAC] THEN
4750   MP_TAC(ISPEC `p:real^N->bool` POLYHEDRON_INTER_AFFINE_PARALLEL_MINIMAL) THEN
4751   REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
4752   REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
4753   ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC
4754    [`f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
4755     `b:(real^N->bool)->real`] THEN
4756   ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN
4757   REWRITE_TAC[VECTOR_ARITH `vec 0:real^N = v <=> v = vec 0`] THEN
4758   STRIP_TAC THEN MP_TAC(ISPECL
4759    [`p:real^N->bool`; `f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
4760     `b:(real^N->bool)->real`] FACET_OF_POLYHEDRON_EXPLICIT) THEN
4761   ASM_SIMP_TAC[] THEN DISCH_THEN(fun th ->
4762     MP_TAC(SPEC `f1:real^N->bool` th) THEN
4763     MP_TAC(SPEC `f2:real^N->bool` th) THEN
4764     MP_TAC(SPEC `f3:real^N->bool` th)) THEN
4765   ASM_REWRITE_TAC[facet_of] THEN
4766   DISCH_THEN(X_CHOOSE_THEN `h3:real^N->bool` (STRIP_ASSUME_TAC o GSYM)) THEN
4767   DISCH_THEN(X_CHOOSE_THEN `h2:real^N->bool` (STRIP_ASSUME_TAC o GSYM)) THEN
4768   DISCH_THEN(X_CHOOSE_THEN `h1:real^N->bool` (STRIP_ASSUME_TAC o GSYM)) THEN
4769   SUBGOAL_THEN `~((a:(real^N->bool)->real^N) h1 = a h2) /\
4770                  ~(a h2 = a h3) /\ ~(a h1 = a h3)`
4771   STRIP_ASSUME_TAC THENL
4772    [REPEAT CONJ_TAC THENL
4773      [DISJ_CASES_TAC(REAL_ARITH
4774        `b(h1:real^N->bool) <= b h2 \/ b h2 <= b h1`)
4775       THENL
4776        [FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h2:real^N->bool)`);
4777         FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h1:real^N->bool)`)] THEN
4778       (ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4779        MATCH_MP_TAC(SET_RULE `(p ==> s = t) ==> s PSUBSET t ==> ~p`) THEN
4780        DISCH_TAC THEN
4781        FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [SYM th]) THEN
4782        AP_TERM_TAC)
4783       THENL
4784        [SUBGOAL_THEN `f DELETE h2 = h1 INSERT (f DIFF {h1,h2}) /\
4785                       f = (h2:real^N->bool) INSERT h1 INSERT (f DIFF {h1,h2})`
4786          (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC];
4787         SUBGOAL_THEN `f DELETE h1 = h2 INSERT (f DIFF {h1,h2}) /\
4788                       f = (h1:real^N->bool) INSERT h2 INSERT (f DIFF {h1,h2})`
4789          (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC]] THEN
4790       REWRITE_TAC[INTERS_INSERT] THEN MATCH_MP_TAC(SET_RULE
4791        `b SUBSET a ==> a INTER b INTER s = b INTER s`) THEN
4792       FIRST_X_ASSUM(fun th ->
4793        MP_TAC(SPEC `h1:real^N->bool` th) THEN
4794        MP_TAC(SPEC `h2:real^N->bool` th)) THEN
4795       ASM_REWRITE_TAC[IMP_IMP] THEN
4796       DISCH_THEN(fun th -> ONCE_REWRITE_TAC[GSYM th]) THEN
4797       REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN ASM_REAL_ARITH_TAC;
4798       DISJ_CASES_TAC(REAL_ARITH
4799        `b(h2:real^N->bool) <= b h3 \/ b h3 <= b h2`)
4800       THENL
4801        [FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h3:real^N->bool)`);
4802         FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h2:real^N->bool)`)] THEN
4803       (ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4804        MATCH_MP_TAC(SET_RULE `(p ==> s = t) ==> s PSUBSET t ==> ~p`) THEN
4805        DISCH_TAC THEN
4806        FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [SYM th]) THEN
4807        AP_TERM_TAC)
4808       THENL
4809        [SUBGOAL_THEN `f DELETE h3 = h2 INSERT (f DIFF {h2,h3}) /\
4810                       f = (h3:real^N->bool) INSERT h2 INSERT (f DIFF {h2,h3})`
4811          (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC];
4812         SUBGOAL_THEN `f DELETE h2 = h3 INSERT (f DIFF {h2,h3}) /\
4813                       f = (h2:real^N->bool) INSERT h3 INSERT (f DIFF {h2,h3})`
4814          (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC]] THEN
4815       REWRITE_TAC[INTERS_INSERT] THEN MATCH_MP_TAC(SET_RULE
4816        `b SUBSET a ==> a INTER b INTER s = b INTER s`) THEN
4817       FIRST_X_ASSUM(fun th ->
4818        MP_TAC(SPEC `h2:real^N->bool` th) THEN
4819        MP_TAC(SPEC `h3:real^N->bool` th)) THEN
4820       ASM_REWRITE_TAC[IMP_IMP] THEN
4821       DISCH_THEN(fun th -> ONCE_REWRITE_TAC[GSYM th]) THEN
4822       REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN ASM_REAL_ARITH_TAC;
4823       DISJ_CASES_TAC(REAL_ARITH
4824        `b(h1:real^N->bool) <= b h3 \/ b h3 <= b h1`)
4825       THENL
4826        [FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h3:real^N->bool)`);
4827         FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h1:real^N->bool)`)] THEN
4828       (ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4829        MATCH_MP_TAC(SET_RULE `(p ==> s = t) ==> s PSUBSET t ==> ~p`) THEN
4830        DISCH_TAC THEN
4831        FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [SYM th]) THEN
4832        AP_TERM_TAC)
4833       THENL
4834        [SUBGOAL_THEN `f DELETE h3 = h1 INSERT (f DIFF {h1,h3}) /\
4835                       f = (h3:real^N->bool) INSERT h1 INSERT (f DIFF {h1,h3})`
4836          (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC];
4837         SUBGOAL_THEN `f DELETE h1 = h3 INSERT (f DIFF {h1,h3}) /\
4838                       f = (h1:real^N->bool) INSERT h3 INSERT (f DIFF {h1,h3})`
4839          (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC]] THEN
4840       REWRITE_TAC[INTERS_INSERT] THEN MATCH_MP_TAC(SET_RULE
4841        `b SUBSET a ==> a INTER b INTER s = b INTER s`) THEN
4842       FIRST_X_ASSUM(fun th ->
4843        MP_TAC(SPEC `h1:real^N->bool` th) THEN
4844        MP_TAC(SPEC `h3:real^N->bool` th)) THEN
4845       ASM_REWRITE_TAC[IMP_IMP] THEN
4846       DISCH_THEN(fun th -> ONCE_REWRITE_TAC[GSYM th]) THEN
4847       REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN ASM_REAL_ARITH_TAC];
4848     ALL_TAC] THEN
4849   SUBGOAL_THEN
4850    `~({x | a h1 dot x <= b h1} INTER {x | a h2 dot x <= b h2}
4851       SUBSET {x | a h3 dot x <= b h3}) /\
4852     ~({x | a h1 dot x <= b h1} INTER {x | a h3 dot x <= b h3}
4853       SUBSET {x | a h2 dot x <= b h2}) /\
4854     ~({x | a h2 dot x <= b h2} INTER {x | a h3 dot x <= b h3}
4855       SUBSET {x:real^N | a(h1:real^N->bool) dot x <= b h1})`
4856   MP_TAC THENL
4857    [ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THENL
4858      [FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h3:real^N->bool)`);
4859       FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h2:real^N->bool)`);
4860       FIRST_X_ASSUM(MP_TAC o SPEC `f DELETE (h1:real^N->bool)`)] THEN
4861     (ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4862      FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC
4863        (LAND_CONV o LAND_CONV) [SYM th]) THEN
4864      MATCH_MP_TAC(SET_RULE `s = t ==> s PSUBSET t ==> F`) THEN
4865      AP_TERM_TAC)
4866     THENL
4867      [SUBGOAL_THEN
4868        `f DELETE (h3:real^N->bool) = h1 INSERT h2 INSERT (f DELETE h3) /\
4869         f =  h1 INSERT h2 INSERT h3 INSERT (f DELETE h3)`
4870        (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC];
4871       SUBGOAL_THEN
4872        `f DELETE (h2:real^N->bool) = h1 INSERT h3 INSERT (f DELETE h2) /\
4873         f =  h2 INSERT h1 INSERT h3 INSERT (f DELETE h2)`
4874        (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC];
4875       SUBGOAL_THEN
4876        `f DELETE (h1:real^N->bool) = h2 INSERT h3 INSERT (f DELETE h1) /\
4877         f =  h1 INSERT h2 INSERT h3 INSERT (f DELETE h1)`
4878        (fun th -> ONCE_REWRITE_TAC[th]) THENL [ASM SET_TAC[]; ALL_TAC]] THEN
4879     REWRITE_TAC[INTERS_INSERT] THEN REWRITE_TAC[GSYM INTER_ASSOC] THEN
4880     AP_THM_TAC THEN AP_TERM_TAC THEN ASM SET_TAC[];
4881     ALL_TAC] THEN
4882   SUBGOAL_THEN
4883    `?w. (a:(real^N->bool)->real^N) h1 dot w < b h1 /\
4884         a h2 dot w < b h2 /\ a h3 dot w < b h3`
4885    (CHOOSE_THEN MP_TAC)
4886   THENL
4887    [SUBGOAL_THEN `~(relative_interior p :real^N->bool = {})` MP_TAC THENL
4888      [ASM_SIMP_TAC[RELATIVE_INTERIOR_EQ_EMPTY; POLYHEDRON_IMP_CONVEX] THEN
4889       ASM SET_TAC[];
4890       ALL_TAC] THEN
4891     MP_TAC(ISPECL
4892      [`p:real^N->bool`; `f:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
4893       `b:(real^N->bool)->real`] RELATIVE_INTERIOR_POLYHEDRON_EXPLICIT) THEN
4894     ASM_SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC) THEN
4895     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
4896     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
4897     DISCH_THEN(MP_TAC o CONJUNCT2) THEN ASM_SIMP_TAC[];
4898     ALL_TAC] THEN
4899   SUBGOAL_THEN
4900    `!x. x IN r ==> (a h1) dot (x:real^N) = b h1 /\
4901                    (a h2) dot x = b h2 /\
4902                    (a (h3:real^N->bool)) dot x = b h3`
4903   MP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4904   SUBGOAL_THEN `?z:real^N. z IN r` CHOOSE_TAC THENL
4905    [ASM SET_TAC[]; ALL_TAC] THEN
4906   MAP_EVERY UNDISCH_TAC
4907    [`~((a:(real^N->bool)->real^N) h1 = a h2)`;
4908     `~((a:(real^N->bool)->real^N) h1 = a h3)`;
4909     `~((a:(real^N->bool)->real^N) h2 = a h3)`;
4910     `aff_dim(p:real^N->bool) - &2 <= aff_dim(r:real^N->bool)`] THEN
4911   MAP_EVERY (fun t ->
4912     FIRST_X_ASSUM(fun th -> MP_TAC(SPEC t th) THEN ASM_REWRITE_TAC[] THEN
4913                             ASSUME_TAC th) THEN
4914     DISCH_THEN(MP_TAC o SPEC `z:real^N` o CONJUNCT2 o CONJUNCT2))
4915    [`h1:real^N->bool`; `h2:real^N->bool`; `h3:real^N->bool`] THEN
4916   SUBGOAL_THEN `(z:real^N) IN (affine hull p)` ASSUME_TAC THENL
4917    [MATCH_MP_TAC HULL_INC THEN ASM SET_TAC[];
4918     ASM_REWRITE_TAC[]] THEN
4919   UNDISCH_TAC `(z:real^N) IN (affine hull p)` THEN
4920   SUBGOAL_THEN `(a h1) dot (z:real^N) = b h1 /\
4921                 (a h2) dot z = b h2 /\
4922                 (a (h3:real^N->bool)) dot z = b h3`
4923   (REPEAT_TCL CONJUNCTS_THEN (SUBST1_TAC o SYM))
4924   THENL [ASM SET_TAC[]; ALL_TAC] THEN
4925   SUBGOAL_THEN `(r:real^N->bool) SUBSET affine hull p` MP_TAC THENL
4926    [ASM_MESON_TAC[FACE_OF_IMP_SUBSET; HULL_SUBSET; SUBSET_TRANS]; ALL_TAC] THEN
4927   SUBGOAL_THEN
4928    `~((a:(real^N->bool)->real^N) h1 = vec 0) /\
4929     ~((a:(real^N->bool)->real^N) h2 = vec 0) /\
4930     ~((a:(real^N->bool)->real^N) h3 = vec 0)`
4931   MP_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC] THEN
4932   UNDISCH_TAC `(z:real^N) IN r` THEN POP_ASSUM_LIST(K ALL_TAC) THEN
4933   MAP_EVERY SPEC_TAC
4934    [`(a:(real^N->bool)->real^N) h1`,`a1:real^N`;
4935     `(a:(real^N->bool)->real^N) h2`,`a2:real^N`;
4936     `(a:(real^N->bool)->real^N) h3`,`a3:real^N`] THEN
4937   REPEAT GEN_TAC THEN
4938   GEN_GEOM_ORIGIN_TAC `z:real^N` ["a1"; "a2"; "a3"] THEN
4939   REWRITE_TAC[VECTOR_ADD_RID; VECTOR_ADD_LID] THEN
4940   REWRITE_TAC[DOT_RADD; IMAGE_CLAUSES;
4941    REAL_ARITH `a + b:real <= a <=> b <= &0`;
4942    REAL_ARITH `a + b:real < a <=> b < &0`;
4943    REAL_ARITH `a + b:real = a <=> b = &0`] THEN
4944
4945   REPEAT STRIP_TAC THEN
4946   SUBGOAL_THEN `aff_dim(p:real^N->bool) = &(dim p)` SUBST_ALL_TAC THENL
4947    [ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC]; ALL_TAC] THEN
4948   SUBGOAL_THEN `aff_dim(r:real^N->bool) = &(dim r)` SUBST_ALL_TAC THENL
4949    [ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC]; ALL_TAC] THEN
4950   RULE_ASSUM_TAC(REWRITE_RULE[INT_OF_NUM_ADD; INT_OF_NUM_LE;
4951     INT_ARITH `p - &2:int <= q <=> p <= q + &2`]) THEN
4952   MP_TAC(ISPECL
4953    [`{a1:real^N,a2,a3}`; `r:real^N->bool`] DIM_ORTHOGONAL_SUM) THEN
4954   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
4955   ASM_SIMP_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY] THEN
4956   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (ARITH_RULE
4957     `p <= r + 2 ==> u <= p /\ 3 <= t ==> ~(u = t + r)`)) THEN
4958   SUBGOAL_THEN `affine hull p :real^N->bool = span p` SUBST_ALL_TAC THENL
4959    [ASM_MESON_TAC[AFFINE_HULL_EQ_SPAN]; ALL_TAC] THEN
4960   CONJ_TAC THENL
4961    [GEN_REWRITE_TAC RAND_CONV [GSYM DIM_SPAN] THEN
4962     MATCH_MP_TAC DIM_SUBSET THEN ASM SET_TAC[];
4963     ALL_TAC] THEN
4964   MP_TAC(ISPEC `{a1:real^N,a2,a3}` DEPENDENT_BIGGERSET_GENERAL) THEN
4965   SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY; ARITH] THEN
4966   ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; ARITH] THEN
4967   GEN_REWRITE_TAC LAND_CONV [GSYM CONTRAPOS_THM] THEN
4968   REWRITE_TAC[ARITH_RULE `~(3 > x) <=> 3 <= x`] THEN
4969   DISCH_THEN MATCH_MP_TAC THEN
4970   REWRITE_TAC[dependent; EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN
4971   ASM_REWRITE_TAC[DELETE_INSERT; EMPTY_DELETE] THEN
4972   REWRITE_TAC[SPAN_2; IN_ELIM_THM; IN_UNIV] THEN
4973   POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
4974   W(fun (asl,w) -> let fv = frees w
4975                    and av = [`a1:real^N`; `a2:real^N`; `a3:real^N`] in
4976      MAP_EVERY (fun t -> SPEC_TAC(t,t)) (subtract fv av @ av)) THEN
4977   REWRITE_TAC[LEFT_FORALL_IMP_THM] THEN
4978   MATCH_MP_TAC(MESON[]
4979    `(!a1 a2 a3. P a1 a2 a3 ==> P a2 a1 a3 /\ P a3 a1 a2) /\
4980     (!a1 a2 a3. Q a1 a2 a3 ==> ~(P a1 a2 a3))
4981     ==> !a3 a2 a1. P a1 a2 a3
4982                    ==> ~(Q a1 a2 a3 \/ Q a2 a1 a3 \/ Q a3 a1 a2)`) THEN
4983   CONJ_TAC THENL
4984    [REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
4985      `(p ==> q) /\ (p ==> r) ==> p ==> q /\ r`) THEN
4986     CONJ_TAC THEN REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
4987     REWRITE_TAC[CONJ_ACI] THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
4988     ASM SET_TAC[];
4989     ALL_TAC] THEN
4990   REPEAT GEN_TAC THEN DISCH_THEN
4991    (X_CHOOSE_THEN `u:real` (X_CHOOSE_TAC `v:real`)) THEN
4992   REWRITE_TAC[NOT_EXISTS_THM] THEN REPEAT GEN_TAC THEN
4993   ASM_CASES_TAC `u = &0` THENL
4994    [ASM_REWRITE_TAC[VECTOR_ADD_LID; VECTOR_MUL_LZERO] THEN
4995     REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC (REAL_ARITH
4996      `v = &0 \/ &0 < v \/ &0 < --v`)
4997     THENL
4998      [ASM_REWRITE_TAC[VECTOR_MUL_LZERO];
4999       REWRITE_TAC[DOT_LMUL; REAL_ARITH `a * b <= &0 <=> &0 <= a * --b`] THEN
5000       ASM_SIMP_TAC[REAL_LE_MUL_EQ] THEN
5001       REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_INTER] THEN REAL_ARITH_TAC;
5002       REWRITE_TAC[DOT_LMUL; REAL_ARITH `a * b < &0 <=> &0 < --a * b`] THEN
5003       ASM_SIMP_TAC[REAL_LT_MUL_EQ] THEN REAL_ARITH_TAC];
5004     ALL_TAC] THEN
5005   ASM_CASES_TAC `v = &0` THENL
5006    [ASM_REWRITE_TAC[VECTOR_ADD_RID; VECTOR_MUL_LZERO] THEN
5007     REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC (REAL_ARITH
5008      `u = &0 \/ &0 < u \/ &0 < --u`)
5009     THENL
5010      [ASM_REWRITE_TAC[VECTOR_MUL_LZERO];
5011       REWRITE_TAC[DOT_LMUL; REAL_ARITH `a * b <= &0 <=> &0 <= a * --b`] THEN
5012       ASM_SIMP_TAC[REAL_LE_MUL_EQ] THEN
5013       REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_INTER] THEN REAL_ARITH_TAC;
5014       REWRITE_TAC[DOT_LMUL; REAL_ARITH `a * b < &0 <=> &0 < --a * b`] THEN
5015       ASM_SIMP_TAC[REAL_LT_MUL_EQ] THEN REAL_ARITH_TAC];
5016     ALL_TAC] THEN
5017   STRIP_TAC THEN
5018   SUBGOAL_THEN
5019    `&0 < u /\ &0 < v \/ &0 < u /\ &0 < --v \/
5020     &0 < --u /\ &0 < v \/ &0 < --u /\ &0 < --v`
5021   STRIP_ASSUME_TAC THENL
5022    [ASM_REAL_ARITH_TAC;
5023     UNDISCH_TAC
5024      `~({x | a2 dot x <= &0} INTER {x | a3 dot x <= &0} SUBSET
5025         {x:real^N | a1 dot x <= &0})` THEN
5026     ASM_REWRITE_TAC[SUBSET; IN_INTER; IN_ELIM_THM] THEN
5027     REWRITE_TAC[DOT_LADD; DOT_LMUL] THEN
5028     REWRITE_TAC[REAL_ARITH `x <= &0 <=> &0 <= --x`] THEN
5029     REWRITE_TAC[REAL_NEG_ADD; GSYM REAL_MUL_RNEG] THEN
5030     ASM_SIMP_TAC[REAL_LE_MUL; REAL_LE_ADD; REAL_LT_IMP_LE];
5031     UNDISCH_TAC
5032      `~({x | a1 dot x <= &0} INTER {x | a3 dot x <= &0} SUBSET
5033         {x:real^N | a2 dot x <= &0})` THEN
5034     ASM_REWRITE_TAC[SUBSET; IN_INTER; IN_ELIM_THM] THEN
5035     GEN_TAC THEN REWRITE_TAC[DOT_LADD; DOT_LMUL] THEN
5036     MATCH_MP_TAC(REAL_ARITH
5037      `(&0 < u * a2 <=> &0 < a2) /\ (&0 < --v * a3 <=> &0 < a3)
5038       ==> u * a2 + v * a3 <= &0 /\ a3 <= &0 ==> a2 <= &0`) THEN
5039     ASM_SIMP_TAC[REAL_LT_MUL_EQ];
5040     UNDISCH_TAC
5041      `~({x | a1 dot x <= &0} INTER {x | a2 dot x <= &0} SUBSET
5042         {x:real^N | a3 dot x <= &0})` THEN
5043     ASM_REWRITE_TAC[SUBSET; IN_INTER; IN_ELIM_THM] THEN
5044     GEN_TAC THEN REWRITE_TAC[DOT_LADD; DOT_LMUL] THEN
5045     MATCH_MP_TAC(REAL_ARITH
5046      `(&0 < --u * a2 <=> &0 < a2) /\ (&0 < v * a3 <=> &0 < a3)
5047       ==> u * a2 + v * a3 <= &0 /\ a2 <= &0 ==> a3 <= &0`) THEN
5048     ASM_SIMP_TAC[REAL_LT_MUL_EQ];
5049     UNDISCH_TAC `(a1:real^N) dot w < &0` THEN
5050     ASM_REWRITE_TAC[DOT_LADD; DOT_LMUL] THEN
5051     MATCH_MP_TAC(REAL_ARITH
5052      `&0 < --u * --a /\ &0 < --v * --b ==> ~(u * a + v * b < &0)`) THEN
5053     CONJ_TAC THEN MATCH_MP_TAC REAL_LT_MUL THEN ASM_REAL_ARITH_TAC]);;
5054
5055 (* ------------------------------------------------------------------------- *)
5056 (* Lower bounds on then number of 0 and n-1 dimensional faces.               *)
5057 (* ------------------------------------------------------------------------- *)
5058
5059 let POLYTOPE_VERTEX_LOWER_BOUND = prove
5060  (`!p:real^N->bool.
5061         polytope p ==> aff_dim p + &1 <= &(CARD {v | v extreme_point_of p})`,
5062   REPEAT STRIP_TAC THEN
5063   MATCH_MP_TAC INT_LE_TRANS THEN
5064   EXISTS_TAC `aff_dim(convex hull {v:real^N | v extreme_point_of p}) + &1` THEN
5065   CONJ_TAC THENL
5066    [ASM_SIMP_TAC[GSYM KREIN_MILMAN_MINKOWSKI; POLYTOPE_IMP_CONVEX;
5067                  POLYTOPE_IMP_COMPACT; INT_LE_REFL];
5068     REWRITE_TAC[AFF_DIM_CONVEX_HULL; GSYM INT_LE_SUB_LADD] THEN
5069     MATCH_MP_TAC AFF_DIM_LE_CARD THEN
5070     MATCH_MP_TAC FINITE_POLYHEDRON_EXTREME_POINTS THEN
5071     ASM_SIMP_TAC[POLYTOPE_IMP_POLYHEDRON]]);;
5072
5073 let POLYTOPE_FACET_LOWER_BOUND = prove
5074  (`!p:real^N->bool.
5075         polytope p /\ ~(aff_dim p = &0)
5076         ==> aff_dim p + &1 <= &(CARD {f | f facet_of p})`,
5077   GEN_TAC THEN ASM_CASES_TAC `p:real^N->bool = {}` THEN
5078   ASM_SIMP_TAC[AFF_DIM_EMPTY; FACET_OF_EMPTY; EMPTY_GSPEC; CARD_CLAUSES] THEN
5079   CONV_TAC INT_REDUCE_CONV THEN STRIP_TAC THEN
5080   SUBGOAL_THEN
5081    `?n. {f:real^N->bool | f facet_of p} HAS_SIZE n /\ aff_dim p + &1 <= &n`
5082     (fun th -> MESON_TAC[th; HAS_SIZE]) THEN
5083   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
5084   DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
5085   POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
5086   GEOM_ORIGIN_TAC `z:real^N` THEN REPEAT GEN_TAC THEN REPEAT STRIP_TAC THEN
5087   EXISTS_TAC `CARD {f:real^N->bool | f facet_of p}` THEN
5088   ASM_SIMP_TAC[FINITE_POLYTOPE_FACETS; HAS_SIZE] THEN
5089   UNDISCH_TAC `~(aff_dim(p:real^N->bool) = &0)` THEN
5090   ASM_SIMP_TAC[AFF_DIM_DIM_0; HULL_INC; INT_OF_NUM_ADD; INT_OF_NUM_LE] THEN
5091   REWRITE_TAC[INT_OF_NUM_EQ] THEN DISCH_TAC THEN
5092   MP_TAC(ISPEC `p:real^N->bool` POLYHEDRON_INTER_AFFINE_PARALLEL_MINIMAL) THEN
5093   ASM_SIMP_TAC[POLYTOPE_IMP_POLYHEDRON] THEN
5094   REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
5095   REWRITE_TAC[RIGHT_AND_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
5096   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC
5097    [`H:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
5098     `b:(real^N->bool)->real`] THEN
5099   ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN
5100   REWRITE_TAC[VECTOR_ARITH `vec 0:real^N = v <=> v = vec 0`] THEN
5101   ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC] THEN
5102   STRIP_TAC THEN MP_TAC(ISPECL
5103    [`p:real^N->bool`; `H:(real^N->bool)->bool`; `a:(real^N->bool)->real^N`;
5104     `b:(real^N->bool)->real`] FACET_OF_POLYHEDRON_EXPLICIT) THEN
5105   ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC] THEN DISCH_THEN(K ALL_TAC) THEN
5106   SUBGOAL_THEN `!h:real^N->bool. h IN H ==> &0 <= b h` ASSUME_TAC THENL
5107    [UNDISCH_TAC `(vec 0:real^N) IN p` THEN EXPAND_TAC "p" THEN
5108     REWRITE_TAC[IN_INTER; IN_INTERS] THEN DISCH_THEN(MP_TAC o CONJUNCT2) THEN
5109     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `h:real^N->bool` THEN
5110     ASM_CASES_TAC `(h:real^N->bool) IN H` THEN ASM_REWRITE_TAC[] THEN
5111     FIRST_X_ASSUM(MP_TAC o SPEC `h:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
5112     DISCH_THEN(fun t -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM t]) THEN
5113     REWRITE_TAC[IN_ELIM_THM; DOT_RZERO];
5114     ALL_TAC] THEN
5115   MATCH_MP_TAC LE_TRANS THEN
5116   EXISTS_TAC `(CARD(H:(real^N->bool)->bool))` THEN CONJ_TAC THENL
5117    [MATCH_MP_TAC(ARITH_RULE `~(h <= a) ==> a + 1 <= h`) THEN DISCH_TAC THEN
5118     ASM_CASES_TAC `H:(real^N->bool)->bool = {}` THENL
5119      [UNDISCH_THEN `H:(real^N->bool)->bool = {}` SUBST_ALL_TAC THEN
5120       RULE_ASSUM_TAC(REWRITE_RULE[INTERS_0; INTER_UNIV]) THEN
5121       UNDISCH_TAC `~(dim(p:real^N->bool) = 0)` THEN
5122       REWRITE_TAC[DIM_EQ_0] THEN EXPAND_TAC "p" THEN
5123       REWRITE_TAC[ASSUME `H:(real^N->bool)->bool = {}`; INTERS_0] THEN
5124       REWRITE_TAC[INTER_UNIV] THEN
5125       ASM_CASES_TAC `?n:real^N. n IN span p /\ ~(n = vec 0)` THENL
5126        [ALL_TAC; ASM SET_TAC[]] THEN
5127       FIRST_X_ASSUM(CHOOSE_THEN STRIP_ASSUME_TAC) THEN
5128       FIRST_ASSUM(MP_TAC o MATCH_MP POLYTOPE_IMP_BOUNDED) THEN
5129       REWRITE_TAC[BOUNDED_POS] THEN DISCH_THEN(X_CHOOSE_THEN `B:real`
5130        (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5131       DISCH_THEN(MP_TAC o SPEC `(B + &1) / norm n % n:real^N`) THEN
5132       ANTS_TAC THENL [ASM_MESON_TAC[SPAN_MUL]; ALL_TAC] THEN
5133       REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
5134       ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN REAL_ARITH_TAC;
5135       ALL_TAC] THEN
5136     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
5137     DISCH_THEN(X_CHOOSE_TAC `h:real^N->bool`) THEN
5138     SUBGOAL_THEN
5139      `span(IMAGE (a:(real^N->bool)->real^N) (H DELETE h))
5140       PSUBSET span(p)`
5141     MP_TAC THENL
5142      [REWRITE_TAC[PSUBSET] THEN CONJ_TAC THENL
5143        [MATCH_MP_TAC SPAN_SUBSET_SUBSPACE THEN
5144         REWRITE_TAC[SUBSPACE_SPAN; SUBSET; FORALL_IN_IMAGE; IN_DELETE] THEN
5145         ASM_MESON_TAC[SPAN_ADD; SPAN_SUPERSET; VECTOR_ADD_LID];
5146         DISCH_THEN(MP_TAC o AP_TERM `dim:(real^N->bool)->num`) THEN
5147         REWRITE_TAC[DIM_SPAN] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
5148          (ARITH_RULE `h <= p ==> h':num < h ==> ~(h' = p)`)) THEN
5149         MATCH_MP_TAC LET_TRANS THEN
5150         EXISTS_TAC `CARD(IMAGE (a:(real^N->bool)->real^N) (H DELETE h))` THEN
5151         ASM_SIMP_TAC[DIM_LE_CARD; FINITE_DELETE; FINITE_IMAGE] THEN
5152         MATCH_MP_TAC LET_TRANS THEN
5153         EXISTS_TAC `CARD(H DELETE (h:real^N->bool))` THEN
5154         ASM_SIMP_TAC[CARD_IMAGE_LE; FINITE_DELETE] THEN
5155         ASM_SIMP_TAC[CARD_DELETE; ARITH_RULE `n - 1 < n <=> ~(n = 0)`] THEN
5156         ASM_SIMP_TAC[CARD_EQ_0] THEN ASM SET_TAC[]];
5157       DISCH_THEN(MP_TAC o MATCH_MP ORTHOGONAL_TO_SUBSPACE_EXISTS_GEN)] THEN
5158     REWRITE_TAC[NOT_EXISTS_THM] THEN X_GEN_TAC `n:real^N` THEN STRIP_TAC THEN
5159     FIRST_ASSUM(MP_TAC o MATCH_MP POLYTOPE_IMP_BOUNDED) THEN
5160     REWRITE_TAC[BOUNDED_POS] THEN
5161     DISCH_THEN(X_CHOOSE_THEN `B:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5162     DISJ_CASES_TAC(REAL_ARITH
5163      `&0 <= (a:(real^N->bool)->real^N) h dot n \/
5164       &0 <= --((a:(real^N->bool)->real^N) h dot n)`)
5165     THENL
5166      [DISCH_THEN(MP_TAC o SPEC `--(B + &1) / norm(n) % n:real^N`);
5167       DISCH_THEN(MP_TAC o SPEC `(B + &1) / norm(n) % n:real^N`)] THEN
5168     (ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM;
5169                   REAL_DIV_RMUL; NORM_EQ_0; REAL_ABS_NEG;
5170                   REAL_ARITH `~(abs(B + &1) <= B)`] THEN
5171      EXPAND_TAC "p" THEN REWRITE_TAC[IN_INTER; IN_INTERS] THEN
5172      ASM_SIMP_TAC[SPAN_MUL] THEN X_GEN_TAC `k:real^N->bool` THEN
5173      DISCH_TAC THEN
5174      SUBGOAL_THEN `k = {x:real^N | a k dot x <= b k}` SUBST1_TAC THENL
5175       [ASM_SIMP_TAC[]; ALL_TAC] THEN
5176      ASM_CASES_TAC `k:real^N->bool = h` THEN
5177      ASM_REWRITE_TAC[IN_ELIM_THM; DOT_RMUL] THENL
5178       [ALL_TAC;
5179        MATCH_MP_TAC(REAL_ARITH `x = &0 /\ &0 <= y ==> x <= y`) THEN
5180        ASM_SIMP_TAC[REAL_ENTIRE] THEN DISJ2_TAC THEN
5181        FIRST_X_ASSUM(MP_TAC o SPEC `(a:(real^N->bool)->real^N) k`) THEN
5182        REWRITE_TAC[orthogonal; DOT_SYM] THEN DISCH_THEN MATCH_MP_TAC THEN
5183        MATCH_MP_TAC SPAN_SUPERSET THEN ASM SET_TAC[]]) THENL
5184      [MATCH_MP_TAC(REAL_ARITH `&0 <= --x * y /\ &0 <= z ==> x * y <= z`);
5185       MATCH_MP_TAC(REAL_ARITH `&0 <= x * --y /\ &0 <= z ==> x * y <= z`)] THEN
5186     ASM_SIMP_TAC[] THEN MATCH_MP_TAC REAL_LE_MUL THEN
5187     REWRITE_TAC[REAL_ARITH `--a / b:real = --(a / b)`; REAL_NEG_NEG] THEN
5188     ASM_SIMP_TAC[REAL_LE_RDIV_EQ; NORM_POS_LT] THEN ASM_REAL_ARITH_TAC;
5189     REWRITE_TAC[SET_RULE `{f | ?h. h IN s /\ f = g h} = IMAGE g s`] THEN
5190     MATCH_MP_TAC(ARITH_RULE `m:num = n ==> n <= m`) THEN
5191     MATCH_MP_TAC CARD_IMAGE_INJ THEN ASM_REWRITE_TAC[] THEN
5192     MATCH_MP_TAC FACETS_OF_POLYHEDRON_EXPLICIT_DISTINCT THEN
5193     ASM_SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC]]);;
5194
5195 (* ------------------------------------------------------------------------- *)
5196 (* The notion of n-simplex where n is an integer >= -1.                      *)
5197 (* ------------------------------------------------------------------------- *)
5198
5199 parse_as_infix("simplex",(12,"right"));;
5200
5201 let simplex = new_definition
5202  `n simplex s <=> ?c. ~(affine_dependent c) /\
5203                       &(CARD c):int = n + &1 /\
5204                       s = convex hull c`;;
5205
5206 let SIMPLEX = prove
5207  (`n simplex s <=> ?c. FINITE c /\
5208                        ~(affine_dependent c) /\
5209                        &(CARD c):int = n + &1 /\
5210                        s = convex hull c`,
5211   REWRITE_TAC[simplex] THEN MESON_TAC[AFFINE_INDEPENDENT_IMP_FINITE]);;
5212
5213 let CONVEX_SIMPLEX = prove
5214  (`!n s. n simplex s ==> convex s`,
5215   REWRITE_TAC[simplex] THEN MESON_TAC[CONVEX_CONVEX_HULL]);;
5216
5217 let COMPACT_SIMPLEX = prove
5218  (`!n s. n simplex s ==> compact s`,
5219   REWRITE_TAC[SIMPLEX] THEN
5220   MESON_TAC[FINITE_IMP_COMPACT; COMPACT_CONVEX_HULL]);;
5221
5222 let SIMPLEX_IMP_POLYTOPE = prove
5223  (`!n s. n simplex s ==> polytope s`,
5224   REWRITE_TAC[simplex; polytope] THEN
5225   MESON_TAC[AFFINE_INDEPENDENT_IMP_FINITE]);;
5226
5227 let SIMPLEX_DIM_GE = prove
5228  (`!n s. n simplex s ==> -- &1 <= n`,
5229   REWRITE_TAC[simplex] THEN INT_ARITH_TAC);;
5230
5231 let SIMPLEX_EMPTY = prove
5232  (`!n. n simplex {} <=> n = -- &1`,
5233   GEN_TAC THEN REWRITE_TAC[SIMPLEX] THEN
5234   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [EQ_SYM_EQ] THEN
5235   REWRITE_TAC[CONVEX_HULL_EQ_EMPTY; CONJ_ASSOC] THEN
5236   ONCE_REWRITE_TAC[CONJ_SYM] THEN REWRITE_TAC[UNWIND_THM2] THEN
5237   REWRITE_TAC[FINITE_EMPTY; CARD_CLAUSES; AFFINE_INDEPENDENT_EMPTY] THEN
5238   INT_ARITH_TAC);;
5239
5240 let SIMPLEX_MINUS_1 = prove
5241  (`!s. (-- &1) simplex s <=> s = {}`,
5242   GEN_TAC THEN REWRITE_TAC[SIMPLEX; INT_ADD_LINV; INT_OF_NUM_EQ] THEN
5243   ONCE_REWRITE_TAC[TAUT `a /\ b <=> ~(a ==> ~b)`] THEN
5244   SIMP_TAC[CARD_EQ_0] THEN REWRITE_TAC[NOT_IMP] THEN
5245   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c /\ d <=> c /\ a /\ b /\ d`] THEN
5246   REWRITE_TAC[UNWIND_THM2; FINITE_EMPTY; AFFINE_INDEPENDENT_EMPTY] THEN
5247   REWRITE_TAC[CONVEX_HULL_EMPTY]);;
5248
5249 let AFF_DIM_SIMPLEX = prove
5250  (`!s n. n simplex s ==> aff_dim s = n`,
5251   REWRITE_TAC[simplex; INT_ARITH `x:int = n + &1 <=> n = x - &1`] THEN
5252   REPEAT STRIP_TAC THEN
5253   ASM_SIMP_TAC[AFF_DIM_CONVEX_HULL; AFF_DIM_AFFINE_INDEPENDENT]);;
5254
5255 let SIMPLEX_EXTREME_POINTS = prove
5256  (`!n s:real^N->bool.
5257        n simplex s
5258        ==> FINITE {v | v extreme_point_of s} /\
5259            ~(affine_dependent {v | v extreme_point_of s}) /\
5260            &(CARD {v | v extreme_point_of s}) = n + &1 /\
5261            s = convex hull {v | v extreme_point_of s}`,
5262   REPEAT GEN_TAC THEN REWRITE_TAC[SIMPLEX; LEFT_IMP_EXISTS_THM] THEN
5263   X_GEN_TAC `c:real^N->bool` THEN DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN
5264   SUBGOAL_THEN `{v:real^N | v extreme_point_of s} = c`
5265    (fun th -> ASM_REWRITE_TAC[th]) THEN
5266   FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
5267   MATCH_MP_TAC(SET_RULE `s SUBSET t /\ ~(s PSUBSET t) ==> s = t`) THEN
5268   REWRITE_TAC[SUBSET; IN_ELIM_THM; EXTREME_POINT_OF_CONVEX_HULL] THEN
5269   ABBREV_TAC `c' = {v:real^N | v extreme_point_of (convex hull c)}` THEN
5270   DISCH_TAC THEN
5271   SUBGOAL_THEN `convex hull c:real^N->bool = convex hull c'` ASSUME_TAC THENL
5272    [EXPAND_TAC "c'" THEN MATCH_MP_TAC KREIN_MILMAN_MINKOWSKI THEN
5273     REWRITE_TAC[CONVEX_CONVEX_HULL] THEN MATCH_MP_TAC COMPACT_CONVEX_HULL THEN
5274     ASM_MESON_TAC[HAS_SIZE; FINITE_IMP_COMPACT];
5275     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [PSUBSET_MEMBER]) THEN
5276     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5277     DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
5278     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [affine_dependent]) THEN
5279     REWRITE_TAC[] THEN EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN
5280     SUBGOAL_THEN `(a:real^N) IN convex hull c'` MP_TAC THENL
5281      [ASM_MESON_TAC[HULL_INC]; ALL_TAC] THEN
5282     DISCH_THEN(MP_TAC o MATCH_MP (REWRITE_RULE[SUBSET]
5283       CONVEX_HULL_SUBSET_AFFINE_HULL)) THEN
5284     SUBGOAL_THEN `c' SUBSET (c DELETE (a:real^N))` MP_TAC THENL
5285      [ASM SET_TAC[]; ASM_MESON_TAC[HULL_MONO; SUBSET]]]);;
5286
5287 let SIMPLEX_FACE_OF_SIMPLEX = prove
5288  (`!n s f:real^N->bool.
5289         n simplex s /\ f face_of s ==> ?m. m <= n /\ m simplex f`,
5290   REPEAT STRIP_TAC THEN
5291   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SIMPLEX]) THEN
5292   REWRITE_TAC[HAS_SIZE; LEFT_IMP_EXISTS_THM] THEN
5293   X_GEN_TAC `c:real^N->bool` THEN STRIP_TAC THEN
5294   FIRST_X_ASSUM SUBST_ALL_TAC THEN
5295   SUBGOAL_THEN `?c':real^N->bool. c' SUBSET c /\ f = convex hull c'`
5296   STRIP_ASSUME_TAC THENL
5297    [ASM_SIMP_TAC[FACE_OF_CONVEX_HULL_SUBSET; FINITE_IMP_COMPACT]; ALL_TAC] THEN
5298   EXISTS_TAC `&(CARD(c':real^N->bool)) - &1:int` THEN ASM_REWRITE_TAC[] THEN
5299   CONJ_TAC THENL
5300    [FIRST_X_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] CARD_SUBSET)) THEN
5301     ASM_REWRITE_TAC[GSYM INT_OF_NUM_LE] THEN INT_ARITH_TAC;
5302     REWRITE_TAC[simplex] THEN EXISTS_TAC `c':real^N->bool` THEN
5303     ASM_REWRITE_TAC[INT_ARITH `a - &1 + &1:int = a`] THEN
5304     ASM_MESON_TAC[AFFINE_DEPENDENT_MONO]]);;
5305
5306 let FACE_OF_SIMPLEX_SUBSET = prove
5307  (`!n s f:real^N->bool.
5308         n simplex s /\ f face_of s
5309         ==> ?c. c SUBSET {x | x extreme_point_of s} /\ f = convex hull c`,
5310   REPEAT STRIP_TAC THEN
5311   FIRST_ASSUM(MP_TAC o MATCH_MP SIMPLEX_EXTREME_POINTS) THEN
5312   ABBREV_TAC `c = {x:real^N | x extreme_point_of s}` THEN
5313   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5314   DISCH_THEN SUBST_ALL_TAC THEN
5315   RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
5316   ASM_MESON_TAC[FACE_OF_CONVEX_HULL_SUBSET; FINITE_IMP_COMPACT]);;
5317
5318 let SUBSET_FACE_OF_SIMPLEX = prove
5319  (`!s n c:real^N->bool.
5320       n simplex s /\ c SUBSET {x | x extreme_point_of s}
5321       ==> (convex hull c) face_of s`,
5322   REPEAT STRIP_TAC THEN
5323   FIRST_ASSUM(MP_TAC o MATCH_MP SIMPLEX_EXTREME_POINTS) THEN
5324   REWRITE_TAC[HAS_SIZE] THEN
5325   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC)) THEN
5326   DISCH_THEN SUBST1_TAC THEN MATCH_MP_TAC FACE_OF_CONVEX_HULLS THEN
5327   ASM_REWRITE_TAC[] THEN
5328   MATCH_MP_TAC(SET_RULE `!t. u SUBSET t /\ DISJOINT s t ==> DISJOINT s u`) THEN
5329   EXISTS_TAC `affine hull ({v:real^N | v extreme_point_of s} DIFF c)` THEN
5330   REWRITE_TAC[CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
5331   MATCH_MP_TAC DISJOINT_AFFINE_HULL THEN
5332   EXISTS_TAC `{v:real^N | v extreme_point_of s}` THEN
5333   ASM_REWRITE_TAC[] THEN SET_TAC[]);;
5334
5335 let FACES_OF_SIMPLEX = prove
5336  (`!n s. n simplex s
5337          ==> {f | f face_of s} =
5338              {convex hull c | c SUBSET {v | v extreme_point_of s}}`,
5339   REPEAT STRIP_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
5340   REWRITE_TAC[IN_ELIM_THM] THEN
5341   ASM_MESON_TAC[FACE_OF_SIMPLEX_SUBSET; SUBSET_FACE_OF_SIMPLEX]);;
5342
5343 let HAS_SIZE_FACES_OF_SIMPLEX = prove
5344  (`!n s:real^N->bool.
5345         n simplex s
5346         ==> {f | f face_of s} HAS_SIZE 2 EXP (num_of_int(n + &1))`,
5347   REPEAT GEN_TAC THEN DISCH_TAC THEN
5348   FIRST_ASSUM(SUBST1_TAC o MATCH_MP FACES_OF_SIMPLEX) THEN
5349   FIRST_X_ASSUM(STRIP_ASSUME_TAC o GSYM o MATCH_MP SIMPLEX_EXTREME_POINTS) THEN
5350   ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN
5351   REWRITE_TAC[IN_ELIM_THM] THEN CONJ_TAC THENL
5352    [REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ];
5353     MATCH_MP_TAC HAS_SIZE_POWERSET THEN
5354     ASM_REWRITE_TAC[HAS_SIZE; NUM_OF_INT_OF_NUM]] THEN
5355   SUBGOAL_THEN
5356    `!a b. a SUBSET {v:real^N | v extreme_point_of s} /\
5357           b SUBSET {v | v extreme_point_of s} /\
5358           convex hull a SUBSET convex hull b
5359           ==> a SUBSET b`
5360    (fun th -> MESON_TAC[th]) THEN
5361   REPEAT STRIP_TAC THEN REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN
5362   DISCH_TAC THEN
5363   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [affine_dependent]) THEN
5364   REWRITE_TAC[NOT_EXISTS_THM] THEN DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
5365   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN REWRITE_TAC[] THEN
5366   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5367   MATCH_MP_TAC(SET_RULE
5368    `!s t u. x IN s /\ s SUBSET t /\ t SUBSET u /\ u SUBSET v ==> x IN v`) THEN
5369   MAP_EVERY EXISTS_TAC
5370    [`convex hull a:real^N->bool`; `convex hull b:real^N->bool`;
5371     `affine hull b:real^N->bool`] THEN
5372   ASM_SIMP_TAC[HULL_INC; CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
5373   MATCH_MP_TAC HULL_MONO THEN ASM SET_TAC[]);;
5374
5375 let FINITE_FACES_OF_SIMPLEX = prove
5376  (`!n s. n simplex s ==> FINITE {f | f face_of s}`,
5377   REPEAT GEN_TAC THEN
5378   DISCH_THEN(MP_TAC o MATCH_MP HAS_SIZE_FACES_OF_SIMPLEX) THEN
5379   SIMP_TAC[HAS_SIZE]);;
5380
5381 let CARD_FACES_OF_SIMPLEX = prove
5382  (`!n s. n simplex s ==> CARD {f | f face_of s} = 2 EXP (num_of_int(n + &1))`,
5383   REPEAT GEN_TAC THEN
5384   DISCH_THEN(MP_TAC o MATCH_MP HAS_SIZE_FACES_OF_SIMPLEX) THEN
5385   SIMP_TAC[HAS_SIZE]);;
5386
5387 let CHOOSE_SIMPLEX = prove
5388  (`!n. --(&1) <= n /\ n <= &(dimindex(:N)) ==> ?s:real^N->bool. n simplex s`,
5389   X_GEN_TAC `d:int` THEN
5390   REWRITE_TAC[INT_ARITH `--(&1):int <= n <=> n = --(&1) \/ &0 <= n`] THEN
5391   DISCH_THEN(CONJUNCTS_THEN2 DISJ_CASES_TAC MP_TAC) THENL
5392    [ASM_MESON_TAC[SIMPLEX_EMPTY]; ALL_TAC] THEN
5393   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM INT_OF_NUM_EXISTS]) THEN
5394   DISCH_THEN(X_CHOOSE_THEN `n:num` SUBST1_TAC) THEN
5395   REWRITE_TAC[INT_OF_NUM_LE; GSYM DIM_UNIV] THEN DISCH_TAC THEN
5396   FIRST_ASSUM(MP_TAC o MATCH_MP CHOOSE_SUBSPACE_OF_SUBSPACE) THEN
5397   DISCH_THEN(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
5398   MP_TAC(ISPEC `s:real^N->bool` BASIS_EXISTS) THEN
5399   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
5400   X_GEN_TAC `c:real^N->bool` THEN STRIP_TAC THEN
5401   EXISTS_TAC `convex hull ((vec 0:real^N) INSERT c)` THEN
5402   REWRITE_TAC[simplex] THEN EXISTS_TAC `(vec 0:real^N) INSERT c` THEN
5403   FIRST_ASSUM(ASSUME_TAC o MATCH_MP INDEPENDENT_NONZERO) THEN
5404   FIRST_ASSUM(ASSUME_TAC o MATCH_MP INDEPENDENT_IMP_FINITE) THEN
5405   ASM_SIMP_TAC[CARD_CLAUSES; GSYM INT_OF_NUM_SUC] THEN
5406   ASM_SIMP_TAC[INDEPENDENT_IMP_AFFINE_DEPENDENT_0] THEN
5407   ASM_MESON_TAC[HAS_SIZE]);;
5408
5409 let CHOOSE_POLYTOPE = prove
5410  (`!n. --(&1) <= n /\ n <= &(dimindex(:N))
5411        ==> ?s:real^N->bool. polytope s /\ aff_dim s = n`,
5412   MESON_TAC[CHOOSE_SIMPLEX; SIMPLEX_IMP_POLYTOPE; AFF_DIM_SIMPLEX]);;
5413
5414 (* ------------------------------------------------------------------------- *)
5415 (* Simplicial complexes and triangulations.                                  *)
5416 (* ------------------------------------------------------------------------- *)
5417
5418 let simplicial_complex = new_definition
5419  `simplicial_complex c <=>
5420         FINITE c /\
5421         (!s. s IN c ==> ?n. n simplex s) /\
5422         (!f s. s IN c /\ f face_of s ==> f IN c) /\
5423         (!s s'. s IN c /\ s' IN c
5424                 ==> (s INTER s') face_of s /\ (s INTER s') face_of s')`;;
5425
5426 let triangulation = new_definition
5427  `triangulation(tr:(real^N->bool)->bool) <=>
5428         FINITE tr /\
5429         (!t. t IN tr ==> ?n. n simplex t) /\
5430         (!t t'. t IN tr /\ t' IN tr
5431                 ==> (t INTER t') face_of t /\ (t INTER t') face_of t')`;;
5432
5433 let SIMPLICIAL_COMPLEX_IMP_TRIANGULATION = prove
5434  (`!tr. simplicial_complex tr ==> triangulation tr`,
5435   REWRITE_TAC[triangulation; simplicial_complex] THEN MESON_TAC[]);;
5436
5437 let TRIANGULATION_UNION = prove
5438  (`!tr1 tr2.
5439         triangulation(tr1 UNION tr2) <=>
5440         triangulation tr1 /\ triangulation tr2 /\
5441         (!s t. s IN tr1 /\ t IN tr2
5442                ==> s INTER t face_of s /\ s INTER t face_of t)`,
5443   REWRITE_TAC[triangulation; FINITE_UNION; IN_UNION] THEN
5444   MESON_TAC[INTER_COMM]);;
5445
5446 let TRIANGULATION_INTER_SIMPLEX = prove
5447  (`!tr t t':real^N->bool.
5448         triangulation tr /\ t IN tr /\ t' IN tr
5449         ==> t INTER t' = convex hull ({x | x extreme_point_of t} INTER
5450                                       {x | x extreme_point_of t'})`,
5451   REWRITE_TAC[triangulation] THEN REPEAT STRIP_TAC THEN
5452   FIRST_X_ASSUM(MP_TAC o SPECL [`t:real^N->bool`; `t':real^N->bool`]) THEN
5453   ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
5454   FIRST_X_ASSUM(fun th -> MAP_EVERY (MP_TAC o C SPEC th)
5455    [`t:real^N->bool`; `t':real^N->bool`]) THEN
5456   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
5457   X_GEN_TAC `m:int` THEN DISCH_TAC THEN X_GEN_TAC `n:int` THEN DISCH_TAC THEN
5458   MP_TAC(ISPECL [`m:int`; `t':real^N->bool`;
5459                  `t INTER t':real^N->bool`] FACE_OF_SIMPLEX_SUBSET) THEN
5460   MP_TAC(ISPECL [`n:int`; `t:real^N->bool`;
5461                  `t INTER t':real^N->bool`] FACE_OF_SIMPLEX_SUBSET) THEN
5462   ASM_SIMP_TAC[] THEN
5463   DISCH_THEN(X_CHOOSE_THEN `d:real^N->bool` (STRIP_ASSUME_TAC o GSYM)) THEN
5464   DISCH_THEN(X_CHOOSE_THEN `d':real^N->bool` (STRIP_ASSUME_TAC o GSYM)) THEN
5465   MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
5466    [ALL_TAC;
5467     MATCH_MP_TAC HULL_MINIMAL THEN
5468     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[CONVEX_INTER; CONVEX_SIMPLEX]] THEN
5469     SIMP_TAC[SUBSET; IN_INTER; IN_ELIM_THM; extreme_point_of]] THEN
5470   MATCH_MP_TAC SUBSET_TRANS THEN
5471   EXISTS_TAC `convex hull {x:real^N | x extreme_point_of (t INTER t')}` THEN
5472   CONJ_TAC THENL
5473    [MATCH_MP_TAC(SET_RULE `s = t ==> s SUBSET t`) THEN
5474     MATCH_MP_TAC KREIN_MILMAN_MINKOWSKI THEN
5475     ASM_MESON_TAC[COMPACT_INTER; CONVEX_INTER; COMPACT_SIMPLEX; CONVEX_SIMPLEX];
5476     MATCH_MP_TAC HULL_MONO THEN REWRITE_TAC[SUBSET_INTER] THEN CONJ_TAC THENL
5477      [SUBST1_TAC(SYM(ASSUME `convex hull d:real^N->bool = t INTER t'`));
5478       SUBST1_TAC(SYM(ASSUME `convex hull d':real^N->bool = t INTER t'`))] THEN
5479     REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN GEN_TAC THEN
5480     DISCH_THEN(MP_TAC o MATCH_MP EXTREME_POINT_OF_CONVEX_HULL) THEN
5481     ASM SET_TAC[]]);;
5482
5483 let TRIANGULATION_SIMPLICIAL_COMPLEX = prove
5484  (`!tr. triangulation tr
5485         ==> simplicial_complex {f:real^N->bool | ?t. t IN tr /\ f face_of t}`,
5486   let lemma = prove
5487    (`{f | ?t. t IN tr /\ P f t} = UNIONS (IMAGE (\t. {f | P f t}) tr)`,
5488     GEN_REWRITE_TAC I [EXTENSION] THEN
5489     REWRITE_TAC[IN_ELIM_THM; IN_UNIONS; IN_IMAGE; LEFT_AND_EXISTS_THM] THEN
5490     ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
5491     REWRITE_TAC[GSYM CONJ_ASSOC; UNWIND_THM2; IN_ELIM_THM]) in
5492   REWRITE_TAC[triangulation; simplicial_complex] THEN
5493   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_GSPEC] THEN
5494   REWRITE_TAC[IN_ELIM_THM] THEN GEN_TAC THEN
5495   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
5496   REWRITE_TAC[RIGHT_IMP_FORALL_THM; IMP_IMP] THEN STRIP_TAC THEN
5497   REPEAT CONJ_TAC THENL
5498    [REWRITE_TAC[lemma] THEN ASM_SIMP_TAC[FINITE_UNIONS; FINITE_IMAGE] THEN
5499     ASM_REWRITE_TAC[FORALL_IN_IMAGE] THEN
5500     ASM_MESON_TAC[FINITE_FACES_OF_SIMPLEX];
5501     ASM_MESON_TAC[SIMPLEX_FACE_OF_SIMPLEX];
5502     ASM_MESON_TAC[FACE_OF_TRANS];
5503     ASM_MESON_TAC[FACE_OF_INTER_SUBFACE]]);;
5504
5505 (* ------------------------------------------------------------------------- *)
5506 (* Subdividing a cell complex (not necessarily simplicial).                  *)
5507 (* ------------------------------------------------------------------------- *)
5508
5509 let CELL_COMPLEX_SUBDIVISION_EXISTS = prove
5510  (`!m:(real^N->bool)->bool d e.
5511      &0 < e /\
5512      FINITE m /\
5513      (!c. c IN m ==> polytope c) /\
5514      (!c. c IN m ==> aff_dim c <= d) /\
5515      (!c1 c2. c1 IN m /\ c2 IN m
5516               ==> c1 INTER c2 face_of c1 /\ c1 INTER c2 face_of c2)
5517      ==> ?m'. (!c. c IN m' ==> diameter c < e) /\
5518               UNIONS m' = UNIONS m /\
5519               FINITE m' /\
5520               (!c. c IN m' ==> polytope c) /\
5521               (!c. c IN m' ==> aff_dim c <= d) /\
5522               (!c1 c2. c1 IN m' /\ c2 IN m'
5523                        ==> c1 INTER c2 face_of c1 /\ c1 INTER c2 face_of c2)`,
5524   let lemma1 = prove
5525    (`a < abs(x - y)
5526      ==> &0 < a
5527          ==> ?n. integer n /\ (x < n * a /\ n * a < y \/
5528                                y <  n * a /\ n * a < x)`,
5529     REPEAT STRIP_TAC THEN
5530     ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ; GSYM REAL_LT_RDIV_EQ] THEN
5531     MATCH_MP_TAC INTEGER_EXISTS_BETWEEN_ABS_LT THEN
5532     REWRITE_TAC[real_div; GSYM REAL_SUB_RDISTRIB; REAL_ABS_MUL] THEN
5533     ASM_SIMP_TAC[REAL_ABS_INV; REAL_ARITH `&0 < x ==> abs x = x`] THEN
5534     ASM_SIMP_TAC[GSYM real_div; REAL_LT_RDIV_EQ;
5535                  REAL_MUL_LID; REAL_LT_IMP_LE])
5536   and lemma2 = prove
5537    (`!m:(real^N->bool)->bool d.
5538         FINITE m /\
5539         (!c. c IN m ==> polytope c) /\
5540         (!c. c IN m ==> aff_dim c <= d) /\
5541         (!c1 c2. c1 IN m /\ c2 IN m
5542                  ==> c1 INTER c2 face_of c1 /\ c1 INTER c2 face_of c2)
5543         ==> !i. FINITE i
5544                 ==> ?m'. UNIONS m' = UNIONS m /\
5545                          FINITE m' /\
5546                          (!c. c IN m' ==> polytope c) /\
5547                          (!c. c IN m' ==> aff_dim c <= d) /\
5548                          (!c1 c2. c1 IN m' /\ c2 IN m'
5549                                   ==> c1 INTER c2 face_of c1 /\
5550                                       c1 INTER c2 face_of c2) /\
5551                          (!c x y. c IN m' /\ x IN c /\ y IN c
5552                                   ==> !a b. (a,b) IN i
5553                                             ==> a dot x <= b /\ a dot y <= b \/
5554                                                 a dot x >= b /\ a dot y >= b)`,
5555     REPEAT GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5556     REWRITE_TAC[NOT_IN_EMPTY; FORALL_PAIR_THM] THEN CONJ_TAC THENL
5557      [EXISTS_TAC `m:(real^N->bool)->bool` THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN
5558     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real`; `i:(real^N#real)->bool`] THEN
5559     GEN_REWRITE_TAC I [IMP_CONJ] THEN
5560     DISCH_THEN(X_CHOOSE_THEN `n:(real^N->bool)->bool` MP_TAC) THEN
5561     DISCH_THEN(CONJUNCTS_THEN2 (SUBST1_TAC o SYM) MP_TAC) THEN
5562     POP_ASSUM_LIST(K ALL_TAC) THEN REPEAT STRIP_TAC THEN
5563     EXISTS_TAC `{c INTER {x:real^N | a dot x <= b} | c IN n} UNION
5564                 {c INTER {x:real^N | a dot x >= b} | c IN n}` THEN
5565     REPEAT CONJ_TAC THENL
5566      [REWRITE_TAC[UNIONS_UNION; GSYM INTER_UNIONS; GSYM UNION_OVER_INTER] THEN
5567       MATCH_MP_TAC(SET_RULE `(!x. x IN s) ==> t INTER s = t`) THEN
5568       REWRITE_TAC[IN_UNION; IN_ELIM_THM] THEN REAL_ARITH_TAC;
5569       ASM_SIMP_TAC[FINITE_UNION; SIMPLE_IMAGE; FINITE_IMAGE];
5570       REWRITE_TAC[IN_UNION; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
5571       ASM_SIMP_TAC[POLYTOPE_INTER_POLYHEDRON; POLYHEDRON_HALFSPACE_LE;
5572                    POLYHEDRON_HALFSPACE_GE];
5573       REWRITE_TAC[IN_UNION; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
5574       ASM_MESON_TAC[INT_LE_TRANS; AFF_DIM_SUBSET; INTER_SUBSET];
5575       REWRITE_TAC[IN_UNION; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
5576       ASM_REWRITE_TAC[] THEN
5577       ONCE_REWRITE_TAC[SET_RULE
5578       `(s INTER t) INTER (s' INTER t') = (s INTER s') INTER (t INTER t')`] THEN
5579       MATCH_MP_TAC FACE_OF_INTER_INTER THEN ASM_SIMP_TAC[] THEN
5580       SIMP_TAC[SET_RULE `s INTER s = s`; FACE_OF_REFL; CONVEX_HALFSPACE_LE;
5581                CONVEX_HALFSPACE_GE] THEN
5582       REWRITE_TAC[INTER; IN_ELIM_THM; HYPERPLANE_FACE_OF_HALFSPACE_LE;
5583                   HYPERPLANE_FACE_OF_HALFSPACE_GE;
5584                   REAL_ARITH `a <= b /\ a >= b <=> a = b`;
5585                   REAL_ARITH `a >= b /\ a <= b <=> a = b`];
5586       REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; IN_UNION; FORALL_AND_THM;
5587                   IN_INSERT;
5588                   TAUT `p \/ q ==> r <=> (p ==> r) /\ (q ==> r)`] THEN
5589       REWRITE_TAC[FORALL_IN_GSPEC; IN_INTER; IN_ELIM_THM; PAIR_EQ] THEN
5590       SIMP_TAC[] THEN ASM_MESON_TAC[]]) in
5591   REPEAT STRIP_TAC THEN
5592   SUBGOAL_THEN `bounded(UNIONS m:real^N->bool)` MP_TAC THENL
5593    [ASM_SIMP_TAC[BOUNDED_UNIONS; POLYTOPE_IMP_BOUNDED]; ALL_TAC] THEN
5594   REWRITE_TAC[BOUNDED_POS_LT; LEFT_IMP_EXISTS_THM] THEN
5595   X_GEN_TAC `B:real` THEN REWRITE_TAC[] THEN STRIP_TAC THEN
5596   MP_TAC(ISPECL [`--B / (e / &2 / &(dimindex(:N)))`;
5597                  `B / (e / &2 / &(dimindex(:N)))`] FINITE_INTSEG) THEN
5598   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ; REAL_HALF;
5599                REAL_LT_DIV; REAL_OF_NUM_LT; DIMINDEX_GE_1; LE_1] THEN
5600   REWRITE_TAC[REAL_BOUNDS_LE] THEN ABBREV_TAC
5601    `k = {i | integer i /\ abs(i * e / &2 / &(dimindex(:N))) <= B}` THEN
5602   DISCH_TAC THEN
5603   MP_TAC(ISPECL [`m:(real^N->bool)->bool`; `d:int`] lemma2) THEN
5604   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC
5605    `{ (basis i:real^N,j * e / &2 / &(dimindex(:N))) |
5606       i IN 1..dimindex(:N) /\ j IN k}`) THEN
5607   ASM_SIMP_TAC[FINITE_PRODUCT_DEPENDENT; FINITE_NUMSEG] THEN
5608   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `n:(real^N->bool)->bool` THEN
5609   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
5610   X_GEN_TAC `c:real^N->bool` THEN DISCH_TAC THEN
5611   MATCH_MP_TAC(REAL_ARITH `&0 < e /\ x <= e / &2 ==> x < e`) THEN
5612   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC DIAMETER_LE THEN
5613   CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
5614   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
5615   W(MP_TAC o PART_MATCH lhand NORM_LE_L1 o lhand o snd) THEN
5616   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
5617   MATCH_MP_TAC SUM_BOUND_GEN THEN
5618   REWRITE_TAC[FINITE_NUMSEG; CARD_NUMSEG_1; NUMSEG_EMPTY] THEN
5619   REWRITE_TAC[NOT_LT; DIMINDEX_GE_1; IN_NUMSEG; VECTOR_SUB_COMPONENT] THEN
5620   X_GEN_TAC `i:num` THEN STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
5621   DISCH_THEN(MP_TAC o MATCH_MP lemma1) THEN
5622   ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV;
5623                REAL_OF_NUM_LT; DIMINDEX_GE_1; LE_1] THEN
5624   DISCH_THEN(X_CHOOSE_THEN `j:real` (CONJUNCTS_THEN ASSUME_TAC)) THEN
5625   FIRST_X_ASSUM(MP_TAC o SPECL [`c:real^N->bool`; `x:real^N`; `y:real^N`]) THEN
5626   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o
5627     SPECL [`basis i:real^N`; `j * e / &2 / &(dimindex(:N))`]) THEN
5628   ASM_SIMP_TAC[DOT_BASIS; IN_ELIM_THM; NOT_IMP] THEN
5629   CONJ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
5630   MAP_EVERY EXISTS_TAC [`i:num`; `j:real`] THEN ASM_REWRITE_TAC[IN_NUMSEG] THEN
5631   EXPAND_TAC "k" THEN ASM_REWRITE_TAC[IN_ELIM_THM] THEN
5632   FIRST_X_ASSUM DISJ_CASES_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
5633    (REAL_ARITH `a < x /\ x < b
5634                 ==> abs a <= c /\ abs b <= c ==> abs x <= c`)) THEN
5635   CONJ_TAC THEN
5636   W(MP_TAC o PART_MATCH (lhand o rand) COMPONENT_LE_NORM o lhand o snd) THEN
5637   ASM_REWRITE_TAC[] THEN
5638   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
5639   MATCH_MP_TAC REAL_LT_IMP_LE THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
5640   ASM SET_TAC[]);;