Update from HH
[hl193./.git] / Multivariate / topology.ml
1 (* ========================================================================= *)
2 (* Elementary topology in Euclidean space.                                   *)
3 (*                                                                           *)
4 (*              (c) Copyright, John Harrison 1998-2008                       *)
5 (*              (c) Copyright, Valentina Bruno 2010                          *)
6 (* ========================================================================= *)
7
8 needs "Library/card.ml";;
9 needs "Multivariate/determinants.ml";;
10
11 (* ------------------------------------------------------------------------- *)
12 (* General notion of a topology.                                             *)
13 (* ------------------------------------------------------------------------- *)
14
15 let istopology = new_definition
16  `istopology L <=>
17         {} IN L /\
18         (!s t. s IN L /\ t IN L ==> (s INTER t) IN L) /\
19         (!k. k SUBSET L ==> (UNIONS k) IN L)`;;
20
21 let topology_tybij_th = prove
22  (`?t:(A->bool)->bool. istopology t`,
23   EXISTS_TAC `UNIV:(A->bool)->bool` THEN REWRITE_TAC[istopology; IN_UNIV]);;
24
25 let topology_tybij =
26   new_type_definition "topology" ("topology","open_in") topology_tybij_th;;
27
28 let ISTOPOLOGY_OPEN_IN = prove
29  (`istopology(open_in top)`,
30   MESON_TAC[topology_tybij]);;
31
32 let TOPOLOGY_EQ = prove
33  (`!top1 top2. top1 = top2 <=> !s. open_in top1 s <=> open_in top2 s`,
34   REPEAT GEN_TAC THEN GEN_REWRITE_TAC RAND_CONV [GSYM FUN_EQ_THM] THEN
35   REWRITE_TAC[ETA_AX] THEN MESON_TAC[topology_tybij]);;
36
37 (* ------------------------------------------------------------------------- *)
38 (* Infer the "universe" from union of all sets in the topology.              *)
39 (* ------------------------------------------------------------------------- *)
40
41 let topspace = new_definition
42  `topspace top = UNIONS {s | open_in top s}`;;
43
44 (* ------------------------------------------------------------------------- *)
45 (* Main properties of open sets.                                             *)
46 (* ------------------------------------------------------------------------- *)
47
48 let OPEN_IN_CLAUSES = prove
49  (`!top:(A)topology.
50         open_in top {} /\
51         (!s t. open_in top s /\ open_in top t ==> open_in top (s INTER t)) /\
52         (!k. (!s. s IN k ==> open_in top s) ==> open_in top (UNIONS k))`,
53   SIMP_TAC[IN; SUBSET; SIMP_RULE[istopology; IN; SUBSET] ISTOPOLOGY_OPEN_IN]);;
54
55 let OPEN_IN_SUBSET = prove
56  (`!top s. open_in top s ==> s SUBSET (topspace top)`,
57   REWRITE_TAC[topspace] THEN SET_TAC[]);;
58
59 let OPEN_IN_EMPTY = prove
60  (`!top. open_in top {}`,
61   REWRITE_TAC[OPEN_IN_CLAUSES]);;
62
63 let OPEN_IN_INTER = prove
64  (`!top s t. open_in top s /\ open_in top t ==> open_in top (s INTER t)`,
65   REWRITE_TAC[OPEN_IN_CLAUSES]);;
66
67 let OPEN_IN_UNIONS = prove
68  (`!top k. (!s. s IN k ==> open_in top s) ==> open_in top (UNIONS k)`,
69   REWRITE_TAC[OPEN_IN_CLAUSES]);;
70
71 let OPEN_IN_UNION = prove
72  (`!top s t. open_in top s /\ open_in top t ==> open_in top (s UNION t)`,
73   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM UNIONS_2] THEN
74   MATCH_MP_TAC OPEN_IN_UNIONS THEN ASM SET_TAC[]);;
75
76 let OPEN_IN_TOPSPACE = prove
77  (`!top. open_in top (topspace top)`,
78   SIMP_TAC[topspace; OPEN_IN_UNIONS; IN_ELIM_THM]);;
79
80 let OPEN_IN_INTERS = prove
81  (`!top s:(A->bool)->bool.
82         FINITE s /\ ~(s = {}) /\ (!t. t IN s ==> open_in top t)
83         ==> open_in top (INTERS s)`,
84   GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
85   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
86   REWRITE_TAC[INTERS_INSERT; IMP_IMP; NOT_INSERT_EMPTY; FORALL_IN_INSERT] THEN
87   MAP_EVERY X_GEN_TAC [`s:A->bool`; `f:(A->bool)->bool`] THEN
88   ASM_CASES_TAC `f:(A->bool)->bool = {}` THEN
89   ASM_SIMP_TAC[INTERS_0; INTER_UNIV] THEN REPEAT STRIP_TAC THEN
90   MATCH_MP_TAC OPEN_IN_INTER THEN ASM_SIMP_TAC[]);;
91
92 let OPEN_IN_SUBOPEN = prove
93  (`!top s:A->bool.
94         open_in top s <=>
95         !x. x IN s ==> ?t. open_in top t /\ x IN t /\ t SUBSET s`,
96   REPEAT GEN_TAC THEN EQ_TAC THENL [MESON_TAC[SUBSET_REFL]; ALL_TAC] THEN
97   REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
98   REWRITE_TAC[TAUT `a ==> b /\ c <=> (a ==> b) /\ (a ==> c)`] THEN
99   REWRITE_TAC[FORALL_AND_THM; LEFT_IMP_EXISTS_THM] THEN
100   ONCE_REWRITE_TAC[GSYM FORALL_IN_IMAGE] THEN REPEAT STRIP_TAC THEN
101   FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_UNIONS) THEN
102   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
103
104 (* ------------------------------------------------------------------------- *)
105 (* Closed sets.                                                              *)
106 (* ------------------------------------------------------------------------- *)
107
108 let closed_in = new_definition
109  `closed_in top s <=>
110         s SUBSET (topspace top) /\ open_in top (topspace top DIFF s)`;;
111
112 let CLOSED_IN_SUBSET = prove
113  (`!top s. closed_in top s ==> s SUBSET (topspace top)`,
114   MESON_TAC[closed_in]);;
115
116 let CLOSED_IN_EMPTY = prove
117  (`!top. closed_in top {}`,
118   REWRITE_TAC[closed_in; EMPTY_SUBSET; DIFF_EMPTY; OPEN_IN_TOPSPACE]);;
119
120 let CLOSED_IN_TOPSPACE = prove
121  (`!top. closed_in top (topspace top)`,
122   REWRITE_TAC[closed_in; SUBSET_REFL; DIFF_EQ_EMPTY; OPEN_IN_EMPTY]);;
123
124 let CLOSED_IN_UNION = prove
125  (`!top s t. closed_in top s /\ closed_in top t ==> closed_in top (s UNION t)`,
126   SIMP_TAC[closed_in; UNION_SUBSET; OPEN_IN_INTER;
127            SET_RULE `u DIFF (s UNION t) = (u DIFF s) INTER (u DIFF t)`]);;
128
129 let CLOSED_IN_INTERS = prove
130  (`!top k:(A->bool)->bool.
131         ~(k = {}) /\ (!s. s IN k ==> closed_in top s)
132         ==> closed_in top (INTERS k)`,
133   REPEAT GEN_TAC THEN REWRITE_TAC[closed_in] THEN REPEAT STRIP_TAC THENL
134    [ASM SET_TAC[]; ALL_TAC] THEN
135   SUBGOAL_THEN `topspace top DIFF INTERS k :A->bool =
136                 UNIONS {topspace top DIFF s | s IN k}` SUBST1_TAC
137   THENL [ALL_TAC; MATCH_MP_TAC OPEN_IN_UNIONS THEN ASM SET_TAC[]] THEN
138   GEN_REWRITE_TAC I [EXTENSION] THEN ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
139   REWRITE_TAC[IN_UNIONS; IN_INTERS; IN_DIFF; EXISTS_IN_IMAGE] THEN
140   MESON_TAC[]);;
141
142 let CLOSED_IN_INTER = prove
143  (`!top s t. closed_in top s /\ closed_in top t ==> closed_in top (s INTER t)`,
144   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM INTERS_2] THEN
145   MATCH_MP_TAC CLOSED_IN_INTERS THEN ASM SET_TAC[]);;
146
147 let OPEN_IN_CLOSED_IN_EQ = prove
148  (`!top s. open_in top s <=>
149            s SUBSET topspace top /\ closed_in top (topspace top DIFF s)`,
150   REWRITE_TAC[closed_in; SET_RULE `(u DIFF s) SUBSET u`] THEN
151   REWRITE_TAC[SET_RULE `u DIFF (u DIFF s) = u INTER s`] THEN
152   MESON_TAC[OPEN_IN_SUBSET; SET_RULE `s SUBSET t ==> t INTER s = s`]);;
153
154 let OPEN_IN_CLOSED_IN = prove
155  (`!s. s SUBSET topspace top
156        ==> (open_in top s <=> closed_in top (topspace top DIFF s))`,
157   SIMP_TAC[OPEN_IN_CLOSED_IN_EQ]);;
158
159 let OPEN_IN_DIFF = prove
160  (`!top s t:A->bool.
161       open_in top s /\ closed_in top t ==> open_in top (s DIFF t)`,
162   REPEAT STRIP_TAC THEN
163   SUBGOAL_THEN `s DIFF t :A->bool = s INTER (topspace top DIFF t)`
164   SUBST1_TAC THENL
165    [FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_SUBSET) THEN SET_TAC[];
166     MATCH_MP_TAC OPEN_IN_INTER THEN ASM_MESON_TAC[closed_in]]);;
167
168 let CLOSED_IN_DIFF = prove
169  (`!top s t:A->bool.
170         closed_in top s /\ open_in top t ==> closed_in top (s DIFF t)`,
171   REPEAT STRIP_TAC THEN
172   SUBGOAL_THEN `s DIFF t :A->bool = s INTER (topspace top DIFF t)`
173   SUBST1_TAC THENL
174    [FIRST_X_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET) THEN SET_TAC[];
175     MATCH_MP_TAC CLOSED_IN_INTER THEN ASM_MESON_TAC[OPEN_IN_CLOSED_IN_EQ]]);;
176
177 let CLOSED_IN_UNIONS = prove
178  (`!top s. FINITE s /\ (!t. t IN s ==> closed_in top t)
179            ==> closed_in top (UNIONS s)`,
180   GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
181   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
182   REWRITE_TAC[UNIONS_INSERT; UNIONS_0; CLOSED_IN_EMPTY; IN_INSERT] THEN
183   MESON_TAC[CLOSED_IN_UNION]);;
184
185 (* ------------------------------------------------------------------------- *)
186 (* Subspace topology.                                                        *)
187 (* ------------------------------------------------------------------------- *)
188
189 let subtopology = new_definition
190  `subtopology top u = topology {s INTER u | open_in top s}`;;
191
192 let ISTOPLOGY_SUBTOPOLOGY = prove
193  (`!top u:A->bool. istopology {s INTER u | open_in top s}`,
194   REWRITE_TAC[istopology; SET_RULE
195    `{s INTER u | open_in top s} =
196     IMAGE (\s. s INTER u) {s | open_in top s}`] THEN
197   REWRITE_TAC[IMP_CONJ; FORALL_IN_IMAGE; RIGHT_FORALL_IMP_THM] THEN
198   REWRITE_TAC[SUBSET_IMAGE; IN_IMAGE; IN_ELIM_THM; SUBSET] THEN
199   REPEAT GEN_TAC THEN REPEAT CONJ_TAC THENL
200    [EXISTS_TAC `{}:A->bool` THEN REWRITE_TAC[OPEN_IN_EMPTY; INTER_EMPTY];
201     SIMP_TAC[SET_RULE `(s INTER u) INTER t INTER u = (s INTER t) INTER u`] THEN
202     ASM_MESON_TAC[OPEN_IN_INTER];
203     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
204     MAP_EVERY X_GEN_TAC [`f:(A->bool)->bool`; `g:(A->bool)->bool`] THEN
205     STRIP_TAC THEN EXISTS_TAC `UNIONS g :A->bool` THEN
206     ASM_SIMP_TAC[OPEN_IN_UNIONS; INTER_UNIONS] THEN SET_TAC[]]);;
207
208 let OPEN_IN_SUBTOPOLOGY = prove
209  (`!top u s. open_in (subtopology top u) s <=>
210                 ?t. open_in top t /\ s = t INTER u`,
211   REWRITE_TAC[subtopology] THEN
212   SIMP_TAC[REWRITE_RULE[CONJUNCT2 topology_tybij] ISTOPLOGY_SUBTOPOLOGY] THEN
213   REWRITE_TAC[EXTENSION; IN_ELIM_THM]);;
214
215 let TOPSPACE_SUBTOPOLOGY = prove
216  (`!top u. topspace(subtopology top u) = topspace top INTER u`,
217   REWRITE_TAC[topspace; OPEN_IN_SUBTOPOLOGY; INTER_UNIONS] THEN
218   REPEAT STRIP_TAC THEN AP_TERM_TAC THEN
219   GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[IN_ELIM_THM]);;
220
221 let CLOSED_IN_SUBTOPOLOGY = prove
222  (`!top u s. closed_in (subtopology top u) s <=>
223                 ?t:A->bool. closed_in top t /\ s = t INTER u`,
224   REWRITE_TAC[closed_in; TOPSPACE_SUBTOPOLOGY] THEN
225   REWRITE_TAC[SUBSET_INTER; OPEN_IN_SUBTOPOLOGY; RIGHT_AND_EXISTS_THM] THEN
226   REPEAT STRIP_TAC THEN EQ_TAC THEN
227   DISCH_THEN(X_CHOOSE_THEN `t:A->bool` STRIP_ASSUME_TAC) THEN
228   EXISTS_TAC `topspace top DIFF t :A->bool` THEN
229   ASM_SIMP_TAC[CLOSED_IN_TOPSPACE; OPEN_IN_DIFF; CLOSED_IN_DIFF;
230                OPEN_IN_TOPSPACE] THEN
231   ASM SET_TAC[]);;
232
233 let OPEN_IN_SUBTOPOLOGY_EMPTY = prove
234  (`!top s. open_in (subtopology top {}) s <=> s = {}`,
235   REWRITE_TAC[OPEN_IN_SUBTOPOLOGY; INTER_EMPTY] THEN
236   MESON_TAC[OPEN_IN_EMPTY]);;
237
238 let CLOSED_IN_SUBTOPOLOGY_EMPTY = prove
239  (`!top s. closed_in (subtopology top {}) s <=> s = {}`,
240   REWRITE_TAC[CLOSED_IN_SUBTOPOLOGY; INTER_EMPTY] THEN
241   MESON_TAC[CLOSED_IN_EMPTY]);;
242
243 let OPEN_IN_SUBTOPOLOGY_REFL = prove
244  (`!top u:A->bool. open_in (subtopology top u) u <=> u SUBSET topspace top`,
245   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_SUBTOPOLOGY] THEN EQ_TAC THENL
246    [REPEAT STRIP_TAC THEN ONCE_ASM_REWRITE_TAC[] THEN
247     MATCH_MP_TAC(SET_RULE `s SUBSET u ==> s INTER t SUBSET u`) THEN
248     ASM_SIMP_TAC[OPEN_IN_SUBSET];
249     DISCH_TAC THEN EXISTS_TAC `topspace top:A->bool` THEN
250     REWRITE_TAC[OPEN_IN_TOPSPACE] THEN ASM SET_TAC[]]);;
251
252 let CLOSED_IN_SUBTOPOLOGY_REFL = prove
253  (`!top u:A->bool. closed_in (subtopology top u) u <=> u SUBSET topspace top`,
254   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN_SUBTOPOLOGY] THEN EQ_TAC THENL
255    [REPEAT STRIP_TAC THEN ONCE_ASM_REWRITE_TAC[] THEN
256     MATCH_MP_TAC(SET_RULE `s SUBSET u ==> s INTER t SUBSET u`) THEN
257     ASM_SIMP_TAC[CLOSED_IN_SUBSET];
258     DISCH_TAC THEN EXISTS_TAC `topspace top:A->bool` THEN
259     REWRITE_TAC[CLOSED_IN_TOPSPACE] THEN ASM SET_TAC[]]);;
260
261 let SUBTOPOLOGY_SUPERSET = prove
262  (`!top s:A->bool. topspace top SUBSET s ==> subtopology top s = top`,
263   REPEAT GEN_TAC THEN SIMP_TAC[TOPOLOGY_EQ; OPEN_IN_SUBTOPOLOGY] THEN
264   DISCH_TAC THEN X_GEN_TAC `u:A->bool` THEN EQ_TAC THENL
265    [DISCH_THEN(CHOOSE_THEN(CONJUNCTS_THEN2 MP_TAC SUBST1_TAC)) THEN
266     DISCH_THEN(fun th -> MP_TAC th THEN
267       ASSUME_TAC(MATCH_MP OPEN_IN_SUBSET th)) THEN
268     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[];
269     DISCH_TAC THEN EXISTS_TAC `u:A->bool` THEN
270     FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_SUBSET) THEN ASM SET_TAC[]]);;
271
272 let SUBTOPOLOGY_TOPSPACE = prove
273  (`!top. subtopology top (topspace top) = top`,
274   SIMP_TAC[SUBTOPOLOGY_SUPERSET; SUBSET_REFL]);;
275
276 let SUBTOPOLOGY_UNIV = prove
277  (`!top. subtopology top UNIV = top`,
278   SIMP_TAC[SUBTOPOLOGY_SUPERSET; SUBSET_UNIV]);;
279
280 let OPEN_IN_IMP_SUBSET = prove
281  (`!top s t. open_in (subtopology top s) t ==> t SUBSET s`,
282   REWRITE_TAC[OPEN_IN_SUBTOPOLOGY] THEN SET_TAC[]);;
283
284 let CLOSED_IN_IMP_SUBSET = prove
285  (`!top s t. closed_in (subtopology top s) t ==> t SUBSET s`,
286   REWRITE_TAC[closed_in; TOPSPACE_SUBTOPOLOGY] THEN SET_TAC[]);;
287
288 let OPEN_IN_SUBTOPOLOGY_UNION = prove
289  (`!top s t u:A->bool.
290         open_in (subtopology top t) s /\ open_in (subtopology top u) s
291         ==> open_in (subtopology top (t UNION u)) s`,
292   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_SUBTOPOLOGY] THEN
293   DISCH_THEN(CONJUNCTS_THEN2
294    (X_CHOOSE_THEN `s':A->bool` STRIP_ASSUME_TAC)
295    (X_CHOOSE_THEN `t':A->bool` STRIP_ASSUME_TAC)) THEN
296   EXISTS_TAC `s' INTER t':A->bool` THEN ASM_SIMP_TAC[OPEN_IN_INTER] THEN
297   ASM SET_TAC[]);;
298
299 let CLOSED_IN_SUBTOPOLOGY_UNION = prove
300  (`!top s t u:A->bool.
301         closed_in (subtopology top t) s /\ closed_in (subtopology top u) s
302         ==> closed_in (subtopology top (t UNION u)) s`,
303   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN_SUBTOPOLOGY] THEN
304   DISCH_THEN(CONJUNCTS_THEN2
305    (X_CHOOSE_THEN `s':A->bool` STRIP_ASSUME_TAC)
306    (X_CHOOSE_THEN `t':A->bool` STRIP_ASSUME_TAC)) THEN
307   EXISTS_TAC `s' INTER t':A->bool` THEN ASM_SIMP_TAC[CLOSED_IN_INTER] THEN
308   ASM SET_TAC[]);;
309
310 (* ------------------------------------------------------------------------- *)
311 (* The universal Euclidean versions are what we use most of the time.        *)
312 (* ------------------------------------------------------------------------- *)
313
314 let open_def = new_definition
315   `open s <=> !x. x IN s ==> ?e. &0 < e /\ !x'. dist(x',x) < e ==> x' IN s`;;
316
317 let closed = new_definition
318   `closed(s:real^N->bool) <=> open(UNIV DIFF s)`;;
319
320 let euclidean = new_definition
321  `euclidean = topology open`;;
322
323 let OPEN_EMPTY = prove
324  (`open {}`,
325   REWRITE_TAC[open_def; NOT_IN_EMPTY]);;
326
327 let OPEN_UNIV = prove
328  (`open(:real^N)`,
329   REWRITE_TAC[open_def; IN_UNIV] THEN MESON_TAC[REAL_LT_01]);;
330
331 let OPEN_INTER = prove
332  (`!s t. open s /\ open t ==> open (s INTER t)`,
333   REPEAT GEN_TAC THEN REWRITE_TAC[open_def; AND_FORALL_THM; IN_INTER] THEN
334   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
335   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
336   ASM_REWRITE_TAC[] THEN DISCH_THEN(CONJUNCTS_THEN2
337    (X_CHOOSE_TAC `d1:real`) (X_CHOOSE_TAC `d2:real`)) THEN
338   MP_TAC(SPECL [`d1:real`; `d2:real`] REAL_DOWN2) THEN
339   ASM_MESON_TAC[REAL_LT_TRANS]);;
340
341 let OPEN_UNIONS = prove
342  (`(!s. s IN f ==> open s) ==> open(UNIONS f)`,
343   REWRITE_TAC[open_def; IN_UNIONS] THEN MESON_TAC[]);;
344
345 let OPEN_EXISTS_IN = prove
346  (`!P Q:A->real^N->bool.
347         (!a. P a ==> open {x | Q a x}) ==> open {x | ?a. P a /\ Q a x}`,
348   REPEAT STRIP_TAC THEN
349   SUBGOAL_THEN `open(UNIONS {{x | Q (a:A) (x:real^N)} | P a})` MP_TAC THENL
350    [MATCH_MP_TAC OPEN_UNIONS THEN ASM_REWRITE_TAC[FORALL_IN_GSPEC];
351     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN REWRITE_TAC[UNIONS_GSPEC] THEN
352     SET_TAC[]]);;
353
354 let OPEN_EXISTS = prove
355  (`!Q:A->real^N->bool. (!a. open {x | Q a x}) ==> open {x | ?a. Q a x}`,
356   MP_TAC(ISPEC `\x:A. T` OPEN_EXISTS_IN) THEN REWRITE_TAC[]);;
357
358 let OPEN_IN = prove
359  (`!s:real^N->bool. open s <=> open_in euclidean s`,
360   GEN_TAC THEN REWRITE_TAC[euclidean] THEN CONV_TAC SYM_CONV THEN
361   AP_THM_TAC THEN REWRITE_TAC[GSYM(CONJUNCT2 topology_tybij)] THEN
362   REWRITE_TAC[REWRITE_RULE[IN] istopology] THEN
363   REWRITE_TAC[OPEN_EMPTY; OPEN_INTER; SUBSET] THEN
364   MESON_TAC[IN; OPEN_UNIONS]);;
365
366 let TOPSPACE_EUCLIDEAN = prove
367  (`topspace euclidean = (:real^N)`,
368   REWRITE_TAC[topspace; EXTENSION; IN_UNIV; IN_UNIONS; IN_ELIM_THM] THEN
369   MESON_TAC[OPEN_UNIV; IN_UNIV; OPEN_IN]);;
370
371 let TOPSPACE_EUCLIDEAN_SUBTOPOLOGY = prove
372  (`!s. topspace (subtopology euclidean s) = s`,
373   REWRITE_TAC[TOPSPACE_EUCLIDEAN; TOPSPACE_SUBTOPOLOGY; INTER_UNIV]);;
374
375 let OPEN_IN_REFL = prove
376  (`!s:real^N->bool. open_in (subtopology euclidean s) s`,
377   REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_REFL; TOPSPACE_EUCLIDEAN; SUBSET_UNIV]);;
378
379 let CLOSED_IN_REFL = prove
380  (`!s:real^N->bool. closed_in (subtopology euclidean s) s`,
381   REWRITE_TAC[CLOSED_IN_SUBTOPOLOGY_REFL; TOPSPACE_EUCLIDEAN; SUBSET_UNIV]);;
382
383 let CLOSED_IN = prove
384  (`!s:real^N->bool. closed s <=> closed_in euclidean s`,
385   REWRITE_TAC[closed; closed_in; TOPSPACE_EUCLIDEAN; OPEN_IN; SUBSET_UNIV]);;
386
387 let OPEN_UNION = prove
388  (`!s t. open s /\ open t ==> open(s UNION t)`,
389   REWRITE_TAC[OPEN_IN; OPEN_IN_UNION]);;
390
391 let OPEN_SUBOPEN = prove
392  (`!s. open s <=> !x. x IN s ==> ?t. open t /\ x IN t /\ t SUBSET s`,
393   REWRITE_TAC[OPEN_IN; GSYM OPEN_IN_SUBOPEN]);;
394
395 let CLOSED_EMPTY = prove
396  (`closed {}`,
397   REWRITE_TAC[CLOSED_IN; CLOSED_IN_EMPTY]);;
398
399 let CLOSED_UNIV = prove
400  (`closed(UNIV:real^N->bool)`,
401   REWRITE_TAC[CLOSED_IN; GSYM TOPSPACE_EUCLIDEAN; CLOSED_IN_TOPSPACE]);;
402
403 let CLOSED_UNION = prove
404  (`!s t. closed s /\ closed t ==> closed(s UNION t)`,
405   REWRITE_TAC[CLOSED_IN; CLOSED_IN_UNION]);;
406
407 let CLOSED_INTER = prove
408  (`!s t. closed s /\ closed t ==> closed(s INTER t)`,
409   REWRITE_TAC[CLOSED_IN; CLOSED_IN_INTER]);;
410
411 let CLOSED_INTERS = prove
412  (`!f. (!s:real^N->bool. s IN f ==> closed s) ==> closed(INTERS f)`,
413   REWRITE_TAC[CLOSED_IN] THEN REPEAT STRIP_TAC THEN
414   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
415   ASM_SIMP_TAC[CLOSED_IN_INTERS; INTERS_0] THEN
416   REWRITE_TAC[GSYM TOPSPACE_EUCLIDEAN; CLOSED_IN_TOPSPACE]);;
417
418 let CLOSED_FORALL_IN = prove
419  (`!P Q:A->real^N->bool.
420         (!a. P a ==> closed {x | Q a x}) ==> closed {x | !a. P a ==> Q a x}`,
421   REPEAT STRIP_TAC THEN
422   SUBGOAL_THEN `closed(INTERS {{x | Q (a:A) (x:real^N)} | P a})` MP_TAC THENL
423    [MATCH_MP_TAC CLOSED_INTERS THEN ASM_REWRITE_TAC[FORALL_IN_GSPEC];
424     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN REWRITE_TAC[INTERS_GSPEC] THEN
425     SET_TAC[]]);;
426
427 let CLOSED_FORALL = prove
428  (`!Q:A->real^N->bool. (!a. closed {x | Q a x}) ==> closed {x | !a. Q a x}`,
429   MP_TAC(ISPEC `\x:A. T` CLOSED_FORALL_IN) THEN REWRITE_TAC[]);;
430
431 let OPEN_CLOSED = prove
432  (`!s:real^N->bool. open s <=> closed(UNIV DIFF s)`,
433   SIMP_TAC[OPEN_IN; CLOSED_IN; TOPSPACE_EUCLIDEAN; SUBSET_UNIV;
434            OPEN_IN_CLOSED_IN_EQ]);;
435
436 let OPEN_DIFF = prove
437  (`!s t. open s /\ closed t ==> open(s DIFF t)`,
438   REWRITE_TAC[OPEN_IN; CLOSED_IN; OPEN_IN_DIFF]);;
439
440 let CLOSED_DIFF = prove
441  (`!s t. closed s /\ open t ==> closed(s DIFF t)`,
442   REWRITE_TAC[OPEN_IN; CLOSED_IN; CLOSED_IN_DIFF]);;
443
444 let OPEN_INTERS = prove
445  (`!s. FINITE s /\ (!t. t IN s ==> open t) ==> open(INTERS s)`,
446   REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
447   REWRITE_TAC[INTERS_INSERT; INTERS_0; OPEN_UNIV; IN_INSERT] THEN
448   MESON_TAC[OPEN_INTER]);;
449
450 let CLOSED_UNIONS = prove
451  (`!s. FINITE s /\ (!t. t IN s ==> closed t) ==> closed(UNIONS s)`,
452   REWRITE_TAC[IMP_CONJ] THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
453   REWRITE_TAC[UNIONS_INSERT; UNIONS_0; CLOSED_EMPTY; IN_INSERT] THEN
454   MESON_TAC[CLOSED_UNION]);;
455
456 (* ------------------------------------------------------------------------- *)
457 (* Open and closed balls and spheres.                                        *)
458 (* ------------------------------------------------------------------------- *)
459
460 let ball = new_definition
461   `ball(x,e) = { y | dist(x,y) < e}`;;
462
463 let cball = new_definition
464   `cball(x,e) = { y | dist(x,y) <= e}`;;
465
466 let sphere = new_definition
467   `sphere(x,e) = { y | dist(x,y) = e}`;;
468
469 let IN_BALL = prove
470  (`!x y e. y IN ball(x,e) <=> dist(x,y) < e`,
471   REWRITE_TAC[ball; IN_ELIM_THM]);;
472
473 let IN_CBALL = prove
474  (`!x y e. y IN cball(x,e) <=> dist(x,y) <= e`,
475   REWRITE_TAC[cball; IN_ELIM_THM]);;
476
477 let IN_SPHERE = prove
478  (`!x y e. y IN sphere(x,e) <=> dist(x,y) = e`,
479   REWRITE_TAC[sphere; IN_ELIM_THM]);;
480
481 let IN_BALL_0 = prove
482  (`!x e. x IN ball(vec 0,e) <=> norm(x) < e`,
483   REWRITE_TAC[IN_BALL; dist; VECTOR_SUB_LZERO; NORM_NEG]);;
484
485 let IN_CBALL_0 = prove
486  (`!x e. x IN cball(vec 0,e) <=> norm(x) <= e`,
487   REWRITE_TAC[IN_CBALL; dist; VECTOR_SUB_LZERO; NORM_NEG]);;
488
489 let IN_SPHERE_0 = prove
490  (`!x e. x IN sphere(vec 0,e) <=> norm(x) = e`,
491   REWRITE_TAC[IN_SPHERE; dist; VECTOR_SUB_LZERO; NORM_NEG]);;
492
493 let BALL_TRIVIAL = prove
494  (`!x. ball(x,&0) = {}`,
495   REWRITE_TAC[EXTENSION; IN_BALL; IN_SING; NOT_IN_EMPTY] THEN NORM_ARITH_TAC);;
496
497 let CBALL_TRIVIAL = prove
498  (`!x. cball(x,&0) = {x}`,
499   REWRITE_TAC[EXTENSION; IN_CBALL; IN_SING; NOT_IN_EMPTY] THEN NORM_ARITH_TAC);;
500
501 let CENTRE_IN_CBALL = prove
502  (`!x e. x IN cball(x,e) <=> &0 <= e`,
503   MESON_TAC[IN_CBALL; DIST_REFL]);;
504
505 let BALL_SUBSET_CBALL = prove
506  (`!x e. ball(x,e) SUBSET cball(x,e)`,
507   REWRITE_TAC[IN_BALL; IN_CBALL; SUBSET] THEN REAL_ARITH_TAC);;
508
509 let SPHERE_SUBSET_CBALL = prove
510  (`!x e. sphere(x,e) SUBSET cball(x,e)`,
511   REWRITE_TAC[IN_SPHERE; IN_CBALL; SUBSET] THEN REAL_ARITH_TAC);;
512
513 let SUBSET_BALL = prove
514  (`!x d e. d <= e ==> ball(x,d) SUBSET ball(x,e)`,
515   REWRITE_TAC[SUBSET; IN_BALL] THEN MESON_TAC[REAL_LTE_TRANS]);;
516
517 let SUBSET_CBALL = prove
518  (`!x d e. d <= e ==> cball(x,d) SUBSET cball(x,e)`,
519   REWRITE_TAC[SUBSET; IN_CBALL] THEN MESON_TAC[REAL_LE_TRANS]);;
520
521 let BALL_MAX_UNION = prove
522  (`!a r s. ball(a,max r s) = ball(a,r) UNION ball(a,s)`,
523   REWRITE_TAC[IN_BALL; IN_UNION; EXTENSION] THEN REAL_ARITH_TAC);;
524
525 let BALL_MIN_INTER = prove
526  (`!a r s. ball(a,min r s) = ball(a,r) INTER ball(a,s)`,
527   REWRITE_TAC[IN_BALL; IN_INTER; EXTENSION] THEN REAL_ARITH_TAC);;
528
529 let CBALL_MAX_UNION = prove
530  (`!a r s. cball(a,max r s) = cball(a,r) UNION cball(a,s)`,
531   REWRITE_TAC[IN_CBALL; IN_UNION; EXTENSION] THEN REAL_ARITH_TAC);;
532
533 let CBALL_MIN_INTER = prove
534  (`!x d e. cball(x,min d e) = cball(x,d) INTER cball(x,e)`,
535   REWRITE_TAC[EXTENSION; IN_INTER; IN_CBALL] THEN REAL_ARITH_TAC);;
536
537 let BALL_TRANSLATION = prove
538  (`!a x r. ball(a + x,r) = IMAGE (\y. a + y) (ball(x,r))`,
539   REWRITE_TAC[ball] THEN GEOM_TRANSLATE_TAC[]);;
540
541 let CBALL_TRANSLATION = prove
542  (`!a x r. cball(a + x,r) = IMAGE (\y. a + y) (cball(x,r))`,
543   REWRITE_TAC[cball] THEN GEOM_TRANSLATE_TAC[]);;
544
545 let SPHERE_TRANSLATION = prove
546  (`!a x r. sphere(a + x,r) = IMAGE (\y. a + y) (sphere(x,r))`,
547   REWRITE_TAC[sphere] THEN GEOM_TRANSLATE_TAC[]);;
548
549 add_translation_invariants
550   [BALL_TRANSLATION; CBALL_TRANSLATION; SPHERE_TRANSLATION];;
551
552 let BALL_LINEAR_IMAGE = prove
553  (`!f:real^M->real^N x r.
554         linear f /\ (!y. ?x. f x = y) /\ (!x. norm(f x) = norm x)
555         ==> ball(f x,r) = IMAGE f (ball(x,r))`,
556   REWRITE_TAC[ball] THEN GEOM_TRANSFORM_TAC[]);;
557
558 let CBALL_LINEAR_IMAGE = prove
559  (`!f:real^M->real^N x r.
560         linear f /\ (!y. ?x. f x = y) /\ (!x. norm(f x) = norm x)
561         ==> cball(f x,r) = IMAGE f (cball(x,r))`,
562   REWRITE_TAC[cball] THEN GEOM_TRANSFORM_TAC[]);;
563
564 let SPHERE_LINEAR_IMAGE = prove
565  (`!f:real^M->real^N x r.
566         linear f /\ (!y. ?x. f x = y) /\ (!x. norm(f x) = norm x)
567         ==> sphere(f x,r) = IMAGE f (sphere(x,r))`,
568   REWRITE_TAC[sphere] THEN GEOM_TRANSFORM_TAC[]);;
569
570 add_linear_invariants
571   [BALL_LINEAR_IMAGE; CBALL_LINEAR_IMAGE; SPHERE_LINEAR_IMAGE];;
572
573 let BALL_SCALING = prove
574  (`!c. &0 < c ==> !x r. ball(c % x,c * r) = IMAGE (\x. c % x) (ball(x,r))`,
575   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN
576   MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN REWRITE_TAC[] THEN CONJ_TAC THENL
577    [ASM_MESON_TAC[SURJECTIVE_SCALING; REAL_LT_IMP_NZ]; ALL_TAC] THEN
578   REWRITE_TAC[IN_BALL; DIST_MUL] THEN
579   ASM_SIMP_TAC[REAL_ARITH `&0 < c ==> abs c = c`; REAL_LT_LMUL_EQ]);;
580
581 let CBALL_SCALING = prove
582  (`!c. &0 < c ==> !x r. cball(c % x,c * r) = IMAGE (\x. c % x) (cball(x,r))`,
583   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN
584   MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN REWRITE_TAC[] THEN CONJ_TAC THENL
585    [ASM_MESON_TAC[SURJECTIVE_SCALING; REAL_LT_IMP_NZ]; ALL_TAC] THEN
586   REWRITE_TAC[IN_CBALL; DIST_MUL] THEN
587   ASM_SIMP_TAC[REAL_ARITH `&0 < c ==> abs c = c`; REAL_LE_LMUL_EQ]);;
588
589 add_scaling_theorems [BALL_SCALING; CBALL_SCALING];;
590
591 let CBALL_DIFF_BALL = prove
592  (`!a r. cball(a,r) DIFF ball(a,r) = sphere(a,r)`,
593   REWRITE_TAC[ball; cball; sphere; EXTENSION; IN_DIFF; IN_ELIM_THM] THEN
594   REAL_ARITH_TAC);;
595
596 let BALL_UNION_SPHERE = prove
597  (`!a r. ball(a,r) UNION sphere(a,r) = cball(a,r)`,
598   REWRITE_TAC[ball; cball; sphere; EXTENSION; IN_UNION; IN_ELIM_THM] THEN
599   REAL_ARITH_TAC);;
600
601 let SPHERE_UNION_BALL = prove
602  (`!a r. sphere(a,r) UNION ball(a,r)  = cball(a,r)`,
603   REWRITE_TAC[ball; cball; sphere; EXTENSION; IN_UNION; IN_ELIM_THM] THEN
604   REAL_ARITH_TAC);;
605
606 let CBALL_DIFF_SPHERE = prove
607  (`!a r. cball(a,r) DIFF sphere(a,r) = ball(a,r)`,
608   REWRITE_TAC[EXTENSION; IN_DIFF; IN_SPHERE; IN_BALL; IN_CBALL] THEN
609   REAL_ARITH_TAC);;
610
611 let OPEN_BALL = prove
612  (`!x e. open(ball(x,e))`,
613   REWRITE_TAC[open_def; ball; IN_ELIM_THM] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
614   MESON_TAC[REAL_SUB_LT; REAL_LT_SUB_LADD; REAL_ADD_SYM; REAL_LET_TRANS;
615             DIST_TRIANGLE_ALT]);;
616
617 let CENTRE_IN_BALL = prove
618  (`!x e. x IN ball(x,e) <=> &0 < e`,
619   MESON_TAC[IN_BALL; DIST_REFL]);;
620
621 let OPEN_CONTAINS_BALL = prove
622  (`!s. open s <=> !x. x IN s ==> ?e. &0 < e /\ ball(x,e) SUBSET s`,
623   REWRITE_TAC[open_def; SUBSET; IN_BALL] THEN REWRITE_TAC[DIST_SYM]);;
624
625 let OPEN_CONTAINS_BALL_EQ = prove
626  (`!s. open s ==> (!x. x IN s <=> ?e. &0 < e /\ ball(x,e) SUBSET s)`,
627   MESON_TAC[OPEN_CONTAINS_BALL; SUBSET; CENTRE_IN_BALL]);;
628
629 let BALL_EQ_EMPTY = prove
630  (`!x e. (ball(x,e) = {}) <=> e <= &0`,
631   REWRITE_TAC[EXTENSION; IN_BALL; NOT_IN_EMPTY; REAL_NOT_LT] THEN
632   MESON_TAC[DIST_POS_LE; REAL_LE_TRANS; DIST_REFL]);;
633
634 let BALL_EMPTY = prove
635  (`!x e. e <= &0 ==> ball(x,e) = {}`,
636   REWRITE_TAC[BALL_EQ_EMPTY]);;
637
638 let OPEN_CONTAINS_CBALL = prove
639  (`!s. open s <=> !x. x IN s ==> ?e. &0 < e /\ cball(x,e) SUBSET s`,
640   GEN_TAC THEN REWRITE_TAC[OPEN_CONTAINS_BALL] THEN EQ_TAC THENL
641    [ALL_TAC; ASM_MESON_TAC[SUBSET_TRANS; BALL_SUBSET_CBALL]] THEN
642   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
643   REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL] THEN
644   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
645   EXISTS_TAC `e / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
646   SUBGOAL_THEN `e / &2 < e` (fun th -> ASM_MESON_TAC[th; REAL_LET_TRANS]) THEN
647   ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
648   UNDISCH_TAC `&0 < e` THEN REAL_ARITH_TAC);;
649
650 let OPEN_CONTAINS_CBALL_EQ = prove
651  (`!s. open s ==> (!x. x IN s <=> ?e. &0 < e /\ cball(x,e) SUBSET s)`,
652   MESON_TAC[OPEN_CONTAINS_CBALL; SUBSET; REAL_LT_IMP_LE; CENTRE_IN_CBALL]);;
653
654 let SPHERE_EQ_EMPTY = prove
655  (`!a:real^N r. sphere(a,r) = {} <=> r < &0`,
656   REWRITE_TAC[sphere; EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY] THEN
657   REPEAT GEN_TAC THEN EQ_TAC THENL [ALL_TAC; CONV_TAC NORM_ARITH] THEN
658   MESON_TAC[VECTOR_CHOOSE_DIST; REAL_NOT_LE]);;
659
660 let SPHERE_EMPTY = prove
661  (`!a:real^N r. r < &0 ==> sphere(a,r) = {}`,
662   REWRITE_TAC[SPHERE_EQ_EMPTY]);;
663
664 let NEGATIONS_BALL = prove
665  (`!r. IMAGE (--) (ball(vec 0:real^N,r)) = ball(vec 0,r)`,
666   GEN_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
667   REWRITE_TAC[IN_BALL_0; NORM_NEG] THEN MESON_TAC[VECTOR_NEG_NEG]);;
668
669 let NEGATIONS_CBALL = prove
670  (`!r. IMAGE (--) (cball(vec 0:real^N,r)) = cball(vec 0,r)`,
671   GEN_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
672   REWRITE_TAC[IN_CBALL_0; NORM_NEG] THEN MESON_TAC[VECTOR_NEG_NEG]);;
673
674 let NEGATIONS_SPHERE = prove
675  (`!r. IMAGE (--) (sphere(vec 0:real^N,r)) = sphere(vec 0,r)`,
676   GEN_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
677   REWRITE_TAC[IN_SPHERE_0; NORM_NEG] THEN MESON_TAC[VECTOR_NEG_NEG]);;
678
679 let ORTHOGONAL_TRANSFORMATION_BALL = prove
680  (`!f:real^N->real^N r.
681     orthogonal_transformation f ==> IMAGE f (ball(vec 0,r)) = ball(vec 0,r)`,
682   REWRITE_TAC[EXTENSION; IN_IMAGE; IN_BALL_0] THEN
683   MESON_TAC[ORTHOGONAL_TRANSFORMATION_INVERSE; ORTHOGONAL_TRANSFORMATION]);;
684
685 let ORTHOGONAL_TRANSFORMATION_CBALL = prove
686  (`!f:real^N->real^N r.
687     orthogonal_transformation f ==> IMAGE f (cball(vec 0,r)) = cball(vec 0,r)`,
688   REWRITE_TAC[EXTENSION; IN_IMAGE; IN_CBALL_0] THEN
689   MESON_TAC[ORTHOGONAL_TRANSFORMATION_INVERSE; ORTHOGONAL_TRANSFORMATION]);;
690
691 let ORTHOGONAL_TRANSFORMATION_SPHERE = prove
692  (`!f:real^N->real^N r.
693     orthogonal_transformation f
694     ==> IMAGE f (sphere(vec 0,r)) = sphere(vec 0,r)`,
695   REWRITE_TAC[EXTENSION; IN_IMAGE; IN_SPHERE_0] THEN
696   MESON_TAC[ORTHOGONAL_TRANSFORMATION_INVERSE; ORTHOGONAL_TRANSFORMATION]);;
697
698 (* ------------------------------------------------------------------------- *)
699 (* Basic "localization" results are handy for connectedness.                 *)
700 (* ------------------------------------------------------------------------- *)
701
702 let OPEN_IN_OPEN = prove
703  (`!s:real^N->bool u.
704         open_in (subtopology euclidean u) s <=> ?t. open t /\ (s = u INTER t)`,
705   REPEAT STRIP_TAC THEN REWRITE_TAC[OPEN_IN_SUBTOPOLOGY; GSYM OPEN_IN] THEN
706   REWRITE_TAC[INTER_ACI]);;
707
708 let OPEN_IN_INTER_OPEN = prove
709  (`!s t u:real^N->bool.
710         open_in (subtopology euclidean u) s /\ open t
711         ==> open_in (subtopology euclidean u) (s INTER t)`,
712   REWRITE_TAC[OPEN_IN_OPEN] THEN REPEAT STRIP_TAC THEN
713   ASM_REWRITE_TAC[INTER_ASSOC] THEN ASM_MESON_TAC[OPEN_INTER]);;
714
715 let OPEN_IN_OPEN_INTER = prove
716  (`!u s. open s ==> open_in (subtopology euclidean u) (u INTER s)`,
717   REWRITE_TAC[OPEN_IN_OPEN] THEN MESON_TAC[]);;
718
719 let OPEN_OPEN_IN_TRANS = prove
720  (`!s t. open s /\ open t /\ t SUBSET s
721          ==> open_in (subtopology euclidean s) t`,
722   MESON_TAC[OPEN_IN_OPEN_INTER; SET_RULE `t SUBSET s ==> t = s INTER t`]);;
723
724 let OPEN_SUBSET = prove
725  (`!s t:real^N->bool.
726         s SUBSET t /\ open s ==> open_in (subtopology euclidean t) s`,
727   REPEAT STRIP_TAC THEN REWRITE_TAC[OPEN_IN_OPEN] THEN
728   EXISTS_TAC `s:real^N->bool` THEN ASM SET_TAC[]);;
729
730 let CLOSED_IN_CLOSED = prove
731  (`!s:real^N->bool u.
732     closed_in (subtopology euclidean u) s <=> ?t. closed t /\ (s = u INTER t)`,
733   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSED_IN_SUBTOPOLOGY; GSYM CLOSED_IN] THEN
734   REWRITE_TAC[INTER_ACI]);;
735
736 let CLOSED_SUBSET_EQ = prove
737  (`!u s:real^N->bool.
738         closed s ==> (closed_in (subtopology euclidean u) s <=> s SUBSET u)`,
739   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
740    [FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET) THEN
741     REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY];
742     REWRITE_TAC[CLOSED_IN_CLOSED] THEN EXISTS_TAC `s:real^N->bool` THEN
743     ASM SET_TAC[]]);;
744
745 let CLOSED_IN_INTER_CLOSED = prove
746  (`!s t u:real^N->bool.
747         closed_in (subtopology euclidean u) s /\ closed t
748         ==> closed_in (subtopology euclidean u) (s INTER t)`,
749   REWRITE_TAC[CLOSED_IN_CLOSED] THEN REPEAT STRIP_TAC THEN
750   ASM_REWRITE_TAC[INTER_ASSOC] THEN ASM_MESON_TAC[CLOSED_INTER]);;
751
752 let CLOSED_IN_CLOSED_INTER = prove
753  (`!u s. closed s ==> closed_in (subtopology euclidean u) (u INTER s)`,
754   REWRITE_TAC[CLOSED_IN_CLOSED] THEN MESON_TAC[]);;
755
756 let CLOSED_SUBSET = prove
757  (`!s t:real^N->bool.
758         s SUBSET t /\ closed s ==> closed_in (subtopology euclidean t) s`,
759   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSED_IN_CLOSED] THEN
760   EXISTS_TAC `s:real^N->bool` THEN ASM SET_TAC[]);;
761
762 let OPEN_IN_SUBSET_TRANS = prove
763  (`!s t u:real^N->bool.
764         open_in (subtopology euclidean u) s /\ s SUBSET t /\ t SUBSET u
765         ==> open_in (subtopology euclidean t) s`,
766   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN; LEFT_AND_EXISTS_THM] THEN
767   MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]);;
768
769 let CLOSED_IN_SUBSET_TRANS = prove
770  (`!s t u:real^N->bool.
771         closed_in (subtopology euclidean u) s /\ s SUBSET t /\ t SUBSET u
772         ==> closed_in (subtopology euclidean t) s`,
773   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN_CLOSED; LEFT_AND_EXISTS_THM] THEN
774   MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]);;
775
776 let open_in = prove
777  (`!u s:real^N->bool.
778         open_in (subtopology euclidean u) s <=>
779           s SUBSET u /\
780           !x. x IN s ==> ?e. &0 < e /\
781                              !x'. x' IN u /\ dist(x',x) < e ==> x' IN s`,
782   REPEAT GEN_TAC THEN
783   REWRITE_TAC[OPEN_IN_SUBTOPOLOGY; GSYM OPEN_IN] THEN EQ_TAC THENL
784    [REWRITE_TAC[open_def] THEN ASM SET_TAC[INTER_SUBSET; IN_INTER];
785     ALL_TAC] THEN
786   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
787   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
788   REWRITE_TAC[SKOLEM_THM] THEN DISCH_THEN(X_CHOOSE_TAC `d:real^N->real`) THEN
789   EXISTS_TAC `UNIONS {b | ?x:real^N. (b = ball(x,d x)) /\ x IN s}` THEN
790   CONJ_TAC THENL
791    [MATCH_MP_TAC OPEN_UNIONS THEN
792     ASM_SIMP_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM; OPEN_BALL];
793     GEN_REWRITE_TAC I [EXTENSION] THEN
794     REWRITE_TAC[IN_INTER; IN_UNIONS; IN_ELIM_THM] THEN
795     ASM_MESON_TAC[SUBSET; DIST_REFL; DIST_SYM; IN_BALL]]);;
796
797 let OPEN_IN_CONTAINS_BALL = prove
798  (`!s t:real^N->bool.
799         open_in (subtopology euclidean t) s <=>
800         s SUBSET t /\
801         !x. x IN s ==> ?e. &0 < e /\ ball(x,e) INTER t SUBSET s`,
802   REWRITE_TAC[open_in; INTER; SUBSET; IN_ELIM_THM; IN_BALL] THEN
803   MESON_TAC[DIST_SYM]);;
804
805 let OPEN_IN_CONTAINS_CBALL = prove
806  (`!s t:real^N->bool.
807         open_in (subtopology euclidean t) s <=>
808         s SUBSET t /\
809         !x. x IN s ==> ?e. &0 < e /\ cball(x,e) INTER t SUBSET s`,
810   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_CONTAINS_BALL] THEN
811   AP_TERM_TAC THEN REWRITE_TAC[IN_BALL; IN_INTER; SUBSET; IN_CBALL] THEN
812   MESON_TAC[REAL_ARITH `&0 < e ==> &0 < e / &2 /\ (x <= e / &2 ==> x < e)`;
813             REAL_LT_IMP_LE]);;
814
815 (* ------------------------------------------------------------------------- *)
816 (* These "transitivity" results are handy too.                               *)
817 (* ------------------------------------------------------------------------- *)
818
819 let OPEN_IN_TRANS = prove
820  (`!s t u. open_in (subtopology euclidean t) s /\
821            open_in (subtopology euclidean u) t
822            ==> open_in (subtopology euclidean u) s`,
823   ASM_MESON_TAC[OPEN_IN_OPEN; OPEN_IN; OPEN_INTER; INTER_ASSOC]);;
824
825 let OPEN_IN_TRANS_EQ = prove
826  (`!s t:real^N->bool.
827         (!u. open_in (subtopology euclidean t) u
828              ==> open_in (subtopology euclidean s) t)
829         <=> open_in (subtopology euclidean s) t`,
830   MESON_TAC[OPEN_IN_TRANS; OPEN_IN_REFL]);;
831
832 let OPEN_IN_OPEN_TRANS = prove
833  (`!s t. open_in (subtopology euclidean t) s /\ open t ==> open s`,
834   REWRITE_TAC[ONCE_REWRITE_RULE[GSYM SUBTOPOLOGY_UNIV] OPEN_IN] THEN
835   REWRITE_TAC[OPEN_IN_TRANS]);;
836
837 let CLOSED_IN_TRANS = prove
838  (`!s t u. closed_in (subtopology euclidean t) s /\
839            closed_in (subtopology euclidean u) t
840            ==> closed_in (subtopology euclidean u) s`,
841   ASM_MESON_TAC[CLOSED_IN_CLOSED; CLOSED_IN; CLOSED_INTER; INTER_ASSOC]);;
842
843 let CLOSED_IN_TRANS_EQ = prove
844  (`!s t:real^N->bool.
845         (!u. closed_in (subtopology euclidean t) u
846              ==> closed_in (subtopology euclidean s) t)
847         <=> closed_in (subtopology euclidean s) t`,
848   MESON_TAC[CLOSED_IN_TRANS; CLOSED_IN_REFL]);;
849
850 let CLOSED_IN_CLOSED_TRANS = prove
851  (`!s t. closed_in (subtopology euclidean t) s /\ closed t ==> closed s`,
852   REWRITE_TAC[ONCE_REWRITE_RULE[GSYM SUBTOPOLOGY_UNIV] CLOSED_IN] THEN
853   REWRITE_TAC[CLOSED_IN_TRANS]);;
854
855 let OPEN_IN_SUBTOPOLOGY_INTER_SUBSET = prove
856  (`!s u v. open_in (subtopology euclidean u) (u INTER s) /\ v SUBSET u
857            ==> open_in (subtopology euclidean v) (v INTER s)`,
858   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN; LEFT_AND_EXISTS_THM] THEN
859   MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]);;
860
861 let OPEN_IN_OPEN_EQ = prove
862  (`!s t. open s
863          ==> (open_in (subtopology euclidean s) t <=> open t /\ t SUBSET s)`,
864   MESON_TAC[OPEN_OPEN_IN_TRANS; OPEN_IN_OPEN_TRANS; open_in]);;
865
866 let CLOSED_IN_CLOSED_EQ = prove
867  (`!s t. closed s
868          ==> (closed_in (subtopology euclidean s) t <=>
869               closed t /\ t SUBSET s)`,
870   MESON_TAC[CLOSED_SUBSET; CLOSED_IN_CLOSED_TRANS; closed_in;
871             TOPSPACE_EUCLIDEAN_SUBTOPOLOGY]);;
872
873 (* ------------------------------------------------------------------------- *)
874 (* Also some invariance theorems for relative topology.                      *)
875 (* ------------------------------------------------------------------------- *)
876
877 let OPEN_IN_TRANSLATION_EQ = prove
878  (`!a s t. open_in (subtopology euclidean (IMAGE (\x. a + x) t))
879                    (IMAGE (\x. a + x) s) <=>
880            open_in (subtopology euclidean t) s`,
881   REWRITE_TAC[open_in] THEN GEOM_TRANSLATE_TAC[]);;
882
883 add_translation_invariants [OPEN_IN_TRANSLATION_EQ];;
884
885 let CLOSED_IN_TRANSLATION_EQ = prove
886  (`!a s t. closed_in (subtopology euclidean (IMAGE (\x. a + x) t))
887                    (IMAGE (\x. a + x) s) <=>
888            closed_in (subtopology euclidean t) s`,
889   REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
890   GEOM_TRANSLATE_TAC[]);;
891
892 add_translation_invariants [CLOSED_IN_TRANSLATION_EQ];;
893
894 let OPEN_IN_INJECTIVE_LINEAR_IMAGE = prove
895  (`!f:real^M->real^N s t.
896           linear f /\ (!x y. f x = f y ==> x = y)
897           ==> (open_in (subtopology euclidean (IMAGE f t)) (IMAGE f s) <=>
898                open_in (subtopology euclidean t) s)`,
899   REWRITE_TAC[open_in; FORALL_IN_IMAGE; IMP_CONJ; SUBSET] THEN
900   REPEAT STRIP_TAC THEN
901   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (SET_RULE
902    `(!x y. f x = f y ==> x = y) ==> (!x s. f x IN IMAGE f s <=> x IN s)`)) THEN
903   ASM_REWRITE_TAC[] THEN
904   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_BOUNDED_POS) THEN
905   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_BOUNDED_BELOW_POS) THEN
906   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
907   X_GEN_TAC `B2:real` THEN STRIP_TAC THEN
908   X_GEN_TAC `B1:real` THEN STRIP_TAC THEN
909   AP_TERM_TAC THEN AP_TERM_TAC THEN
910   GEN_REWRITE_TAC I [FUN_EQ_THM] THEN X_GEN_TAC `x:real^M` THEN
911   REWRITE_TAC[] THEN AP_TERM_TAC THEN
912   FIRST_ASSUM(ASSUME_TAC o GSYM o MATCH_MP LINEAR_SUB) THEN
913   ASM_REWRITE_TAC[dist; IMP_IMP] THEN EQ_TAC THEN
914   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THENL
915    [EXISTS_TAC `e / B1:real`; EXISTS_TAC `e * B2:real`] THEN
916   ASM_SIMP_TAC[REAL_LT_MUL; REAL_LT_DIV] THEN
917   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THENL
918    [MATCH_MP_TAC(REAL_ARITH
919      `norm(f x) <= B1 * norm(x) /\ norm(x) * B1 < e ==> norm(f x) < e`) THEN
920     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ];
921     MATCH_MP_TAC(REAL_ARITH
922      `norm x <= norm (f x :real^N) / B2 /\ norm(f x) / B2 < e
923       ==> norm x < e`) THEN
924     ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LT_LDIV_EQ]]);;
925
926 add_linear_invariants [OPEN_IN_INJECTIVE_LINEAR_IMAGE];;
927
928 let CLOSED_IN_INJECTIVE_LINEAR_IMAGE = prove
929  (`!f:real^M->real^N s t.
930           linear f /\ (!x y. f x = f y ==> x = y)
931           ==> (closed_in (subtopology euclidean (IMAGE f t)) (IMAGE f s) <=>
932                closed_in (subtopology euclidean t) s)`,
933   REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
934   GEOM_TRANSFORM_TAC[]);;
935
936 add_linear_invariants [CLOSED_IN_INJECTIVE_LINEAR_IMAGE];;
937
938 (* ------------------------------------------------------------------------- *)
939 (* Connectedness.                                                            *)
940 (* ------------------------------------------------------------------------- *)
941
942 let connected = new_definition
943   `connected s <=>
944       ~(?e1 e2. open e1 /\ open e2 /\ s SUBSET (e1 UNION e2) /\
945                 (e1 INTER e2 INTER s = {}) /\
946                 ~(e1 INTER s = {}) /\ ~(e2 INTER s = {}))`;;
947
948 let CONNECTED_CLOSED = prove
949  (`!s:real^N->bool.
950         connected s <=>
951         ~(?e1 e2. closed e1 /\ closed e2 /\ s SUBSET (e1 UNION e2) /\
952                   (e1 INTER e2 INTER s = {}) /\
953                   ~(e1 INTER s = {}) /\ ~(e2 INTER s = {}))`,
954   GEN_TAC THEN REWRITE_TAC[connected] THEN AP_TERM_TAC THEN
955   EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
956   MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN STRIP_TAC THEN
957   MAP_EVERY EXISTS_TAC [`(:real^N) DIFF v`; `(:real^N) DIFF u`] THEN
958   ASM_REWRITE_TAC[GSYM closed; GSYM OPEN_CLOSED] THEN ASM SET_TAC[]);;
959
960 let CONNECTED_OPEN_IN = prove
961  (`!s. connected s <=>
962            ~(?e1 e2.
963                  open_in (subtopology euclidean s) e1 /\
964                  open_in (subtopology euclidean s) e2 /\
965                  s SUBSET e1 UNION e2 /\
966                  e1 INTER e2 = {} /\
967                  ~(e1 = {}) /\
968                  ~(e2 = {}))`,
969   GEN_TAC THEN REWRITE_TAC[connected; OPEN_IN_OPEN] THEN
970   REWRITE_TAC[LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
971   CONV_TAC(ONCE_DEPTH_CONV UNWIND_CONV) THEN
972   AP_TERM_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
973   SET_TAC[]);;
974
975 let CONNECTED_OPEN_IN_EQ = prove
976  (`!s. connected s <=>
977            ~(?e1 e2.
978                  open_in (subtopology euclidean s) e1 /\
979                  open_in (subtopology euclidean s) e2 /\
980                  e1 UNION e2 = s /\ e1 INTER e2 = {} /\
981                  ~(e1 = {}) /\ ~(e2 = {}))`,
982   GEN_TAC THEN REWRITE_TAC[CONNECTED_OPEN_IN] THEN
983   AP_TERM_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
984   EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[SUBSET_REFL] THEN
985   RULE_ASSUM_TAC(REWRITE_RULE[OPEN_IN_CLOSED_IN_EQ;
986    TOPSPACE_EUCLIDEAN_SUBTOPOLOGY]) THEN
987   ASM SET_TAC[]);;
988
989 let CONNECTED_CLOSED_IN = prove
990  (`!s. connected s <=>
991            ~(?e1 e2.
992                  closed_in (subtopology euclidean s) e1 /\
993                  closed_in (subtopology euclidean s) e2 /\
994                  s SUBSET e1 UNION e2 /\
995                  e1 INTER e2 = {} /\
996                  ~(e1 = {}) /\
997                  ~(e2 = {}))`,
998   GEN_TAC THEN REWRITE_TAC[CONNECTED_CLOSED; CLOSED_IN_CLOSED] THEN
999   REWRITE_TAC[LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
1000   CONV_TAC(ONCE_DEPTH_CONV UNWIND_CONV) THEN
1001   AP_TERM_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
1002   SET_TAC[]);;
1003
1004 let CONNECTED_CLOSED_IN_EQ = prove
1005  (`!s. connected s <=>
1006            ~(?e1 e2.
1007                  closed_in (subtopology euclidean s) e1 /\
1008                  closed_in (subtopology euclidean s) e2 /\
1009
1010                  e1 UNION e2 = s /\ e1 INTER e2 = {} /\
1011                  ~(e1 = {}) /\ ~(e2 = {}))`,
1012   GEN_TAC THEN REWRITE_TAC[CONNECTED_CLOSED_IN] THEN
1013   AP_TERM_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
1014   EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[SUBSET_REFL] THEN
1015   RULE_ASSUM_TAC(REWRITE_RULE[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY]) THEN
1016   ASM SET_TAC[]);;
1017
1018 let CONNECTED_CLOPEN = prove
1019  (`!s. connected s <=>
1020         !t. open_in (subtopology euclidean s) t /\
1021             closed_in (subtopology euclidean s) t ==> t = {} \/ t = s`,
1022   GEN_TAC THEN REWRITE_TAC[connected; OPEN_IN_OPEN; CLOSED_IN_CLOSED] THEN
1023   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o BINDER_CONV) [GSYM EXISTS_DIFF] THEN
1024   ONCE_REWRITE_TAC[TAUT `(~a <=> b) <=> (a <=> ~b)`] THEN
1025   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; GSYM CONJ_ASSOC; DE_MORGAN_THM] THEN
1026   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c /\ d <=> b /\ a /\ c /\ d`] THEN
1027   REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN REWRITE_TAC[GSYM closed] THEN
1028   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN AP_TERM_TAC THEN ABS_TAC THEN
1029   REWRITE_TAC[LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
1030   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN AP_TERM_TAC THEN ABS_TAC THEN
1031   REWRITE_TAC[TAUT `(a /\ b) /\ (c /\ d) /\ e <=> a /\ c /\ b /\ d /\ e`] THEN
1032   REWRITE_TAC[RIGHT_EXISTS_AND_THM; UNWIND_THM2] THEN
1033   AP_TERM_TAC THEN AP_TERM_TAC THEN SET_TAC[]);;
1034
1035 let CONNECTED_CLOSED_SET = prove
1036  (`!s:real^N->bool.
1037         closed s
1038         ==> (connected s <=>
1039              ~(?e1 e2. closed e1 /\ closed e2 /\ ~(e1 = {}) /\ ~(e2 = {}) /\
1040                        e1 UNION e2 = s /\ e1 INTER e2 = {}))`,
1041   REPEAT STRIP_TAC THEN EQ_TAC THENL
1042    [REWRITE_TAC[CONNECTED_CLOSED; CONTRAPOS_THM] THEN
1043     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
1044     SIMP_TAC[] THEN SET_TAC[];
1045     REWRITE_TAC[CONNECTED_CLOSED_IN; CONTRAPOS_THM; LEFT_IMP_EXISTS_THM] THEN
1046     REWRITE_TAC[CLOSED_IN_CLOSED; LEFT_IMP_EXISTS_THM; IMP_CONJ] THEN
1047     REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN REWRITE_TAC[IMP_IMP] THEN
1048     MAP_EVERY X_GEN_TAC
1049      [`e1:real^N->bool`; `e2:real^N->bool`;
1050       `u:real^N->bool`; `v:real^N->bool`] THEN
1051     STRIP_TAC THEN MAP_EVERY (C UNDISCH_THEN SUBST_ALL_TAC)
1052      [`e1:real^N->bool = s INTER u`;
1053       `e2:real^N->bool = s INTER v`] THEN
1054     MAP_EVERY EXISTS_TAC
1055      [`s INTER u:real^N->bool`; `s INTER v:real^N->bool`] THEN
1056     ASM_SIMP_TAC[CLOSED_INTER] THEN ASM SET_TAC[]]);;
1057
1058 let CONNECTED_OPEN_SET = prove
1059  (`!s:real^N->bool.
1060         open s
1061         ==> (connected s <=>
1062              ~(?e1 e2. open e1 /\ open e2 /\ ~(e1 = {}) /\ ~(e2 = {}) /\
1063                        e1 UNION e2 = s /\ e1 INTER e2 = {}))`,
1064   REPEAT STRIP_TAC THEN EQ_TAC THENL
1065    [REWRITE_TAC[connected; CONTRAPOS_THM] THEN
1066     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
1067     SIMP_TAC[] THEN SET_TAC[];
1068     REWRITE_TAC[CONNECTED_OPEN_IN; CONTRAPOS_THM; LEFT_IMP_EXISTS_THM] THEN
1069     REWRITE_TAC[OPEN_IN_OPEN; LEFT_IMP_EXISTS_THM; IMP_CONJ] THEN
1070     REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN REWRITE_TAC[IMP_IMP] THEN
1071     MAP_EVERY X_GEN_TAC
1072      [`e1:real^N->bool`; `e2:real^N->bool`;
1073       `u:real^N->bool`; `v:real^N->bool`] THEN
1074     STRIP_TAC THEN MAP_EVERY (C UNDISCH_THEN SUBST_ALL_TAC)
1075      [`e1:real^N->bool = s INTER u`;
1076       `e2:real^N->bool = s INTER v`] THEN
1077     MAP_EVERY EXISTS_TAC
1078      [`s INTER u:real^N->bool`; `s INTER v:real^N->bool`] THEN
1079     ASM_SIMP_TAC[OPEN_INTER] THEN ASM SET_TAC[]]);;
1080
1081 let CONNECTED_EMPTY = prove
1082  (`connected {}`,
1083   REWRITE_TAC[connected; INTER_EMPTY]);;
1084
1085 let CONNECTED_SING = prove
1086  (`!a. connected{a}`,
1087   REWRITE_TAC[connected] THEN SET_TAC[]);;
1088
1089 let CONNECTED_UNIONS = prove
1090  (`!P:(real^N->bool)->bool.
1091         (!s. s IN P ==> connected s) /\ ~(INTERS P = {})
1092         ==> connected(UNIONS P)`,
1093   GEN_TAC THEN REWRITE_TAC[connected; NOT_EXISTS_THM] THEN STRIP_TAC THEN
1094   MAP_EVERY X_GEN_TAC [`e1:real^N->bool`; `e2:real^N->bool`] THEN
1095   STRIP_TAC THEN UNDISCH_TAC `~(INTERS P :real^N->bool = {})` THEN
1096   PURE_REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTERS] THEN
1097   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
1098   SUBGOAL_THEN `(a:real^N) IN e1 \/ a IN e2` STRIP_ASSUME_TAC THENL
1099    [ASM SET_TAC[];
1100     UNDISCH_TAC `~(e2 INTER UNIONS P:real^N->bool = {})`;
1101     UNDISCH_TAC `~(e1 INTER UNIONS P:real^N->bool = {})`] THEN
1102   PURE_REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER; IN_UNIONS] THEN
1103   DISCH_THEN(X_CHOOSE_THEN `b:real^N`
1104    (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
1105   DISCH_THEN(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
1106   UNDISCH_TAC `!t:real^N->bool. t IN P ==> a IN t` THEN
1107   DISCH_THEN(MP_TAC o SPEC `s:real^N->bool`) THEN
1108   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
1109   FIRST_X_ASSUM(MP_TAC o SPEC `s:real^N->bool`) THEN
1110   ASM_REWRITE_TAC[] THEN
1111   DISCH_THEN(MP_TAC o SPECL [`e1:real^N->bool`; `e2:real^N->bool`]) THEN
1112   ASM SET_TAC[]);;
1113
1114 let CONNECTED_UNION = prove
1115  (`!s t:real^N->bool.
1116         connected s /\ connected t /\ ~(s INTER t = {})
1117         ==> connected (s UNION t)`,
1118   REWRITE_TAC[GSYM UNIONS_2; GSYM INTERS_2] THEN
1119   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_UNIONS THEN
1120   ASM SET_TAC[]);;
1121
1122 let CONNECTED_DIFF_OPEN_FROM_CLOSED = prove
1123  (`!s t u:real^N->bool.
1124         s SUBSET t /\ t SUBSET u /\
1125         open s /\ closed t /\ connected u /\ connected(t DIFF s)
1126         ==> connected(u DIFF s)`,
1127   REPEAT STRIP_TAC THEN REWRITE_TAC[connected; NOT_EXISTS_THM] THEN
1128   MAP_EVERY X_GEN_TAC [`v:real^N->bool`; `w:real^N->bool`] THEN STRIP_TAC THEN
1129   UNDISCH_TAC `connected(t DIFF s:real^N->bool)` THEN SIMP_TAC[connected] THEN
1130   MAP_EVERY EXISTS_TAC [`v:real^N->bool`; `w:real^N->bool`] THEN
1131   ASM_REWRITE_TAC[] THEN
1132   REPLICATE_TAC 2 (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
1133   POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN
1134   MAP_EVERY (fun t -> SPEC_TAC(t,t)) [`v:real^N->bool`; `w:real^N->bool`] THEN
1135   MATCH_MP_TAC(MESON[]
1136    `(!v w. P v w ==> P w v) /\ (!w v. P v w /\ Q w ==> F)
1137     ==> !w v. P v w ==> ~(Q v) /\ ~(Q w)`) THEN
1138   CONJ_TAC THENL [SIMP_TAC[CONJ_ACI; INTER_ACI; UNION_ACI]; ALL_TAC] THEN
1139   REPEAT STRIP_TAC THEN
1140   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [connected]) THEN SIMP_TAC[] THEN
1141   MAP_EVERY EXISTS_TAC [`v UNION s:real^N->bool`; `w DIFF t:real^N->bool`] THEN
1142   ASM_SIMP_TAC[OPEN_UNION; OPEN_DIFF] THEN ASM SET_TAC[]);;
1143
1144 let CONNECTED_DISJOINT_UNIONS_OPEN_UNIQUE = prove
1145  (`!f:(real^N->bool)->bool f'.
1146          pairwise DISJOINT f /\ pairwise DISJOINT f' /\
1147         (!s. s IN f ==> open s /\ connected s /\ ~(s = {})) /\
1148         (!s. s IN f' ==> open s /\ connected s /\ ~(s = {})) /\
1149         UNIONS f = UNIONS f'
1150         ==> f = f'`,
1151   GEN_REWRITE_TAC (funpow 2 BINDER_CONV o RAND_CONV) [EXTENSION] THEN
1152   MATCH_MP_TAC(MESON[]
1153    `(!s t. P s t ==> P t s) /\ (!s t x. P s t /\ x IN s ==> x IN t)
1154     ==> (!s t. P s t ==> (!x. x IN s <=> x IN t))`) THEN
1155   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
1156   GEN_TAC THEN GEN_TAC THEN X_GEN_TAC `s:real^N->bool` THEN STRIP_TAC THEN
1157   SUBGOAL_THEN
1158    `?t a:real^N. t IN f' /\ a IN s /\ a IN t` STRIP_ASSUME_TAC
1159   THENL [ASM SET_TAC[]; ALL_TAC] THEN
1160   SUBGOAL_THEN `s:real^N->bool = t` (fun th -> ASM_REWRITE_TAC[th]) THEN
1161   REWRITE_TAC[EXTENSION] THEN POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN
1162   MAP_EVERY (fun t -> SPEC_TAC(t,t))
1163    [`s:real^N->bool`; `t:real^N->bool`;
1164     `f:(real^N->bool)->bool`; `f':(real^N->bool)->bool`] THEN
1165   MATCH_MP_TAC(MESON[]
1166    `(!f f' s t. P f f' s t ==> P f' f t s) /\
1167     (!f f' s t x. P f f' s t /\ x IN s ==> x IN t)
1168     ==> (!f' f t s. P f f' s t ==> (!x. x IN s <=> x IN t))`) THEN
1169   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
1170   REPLICATE_TAC 4 GEN_TAC THEN X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
1171   UNDISCH_TAC
1172    `!s:real^N->bool. s IN f ==> open s /\ connected s /\ ~(s = {})` THEN
1173   DISCH_THEN(MP_TAC o SPEC `s:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
1174   STRIP_TAC THEN ASM_CASES_TAC `(b:real^N) IN t` THEN
1175   ASM_REWRITE_TAC[] THEN
1176   UNDISCH_TAC `connected(s:real^N->bool)` THEN
1177   REWRITE_TAC[connected] THEN
1178   MAP_EVERY EXISTS_TAC
1179    [`t:real^N->bool`; `UNIONS(f' DELETE (t:real^N->bool))`] THEN
1180   REPEAT STRIP_TAC THENL
1181    [ASM_SIMP_TAC[];
1182     MATCH_MP_TAC OPEN_UNIONS THEN ASM_SIMP_TAC[IN_DELETE];
1183     REWRITE_TAC[GSYM UNIONS_INSERT] THEN ASM SET_TAC[];
1184     MATCH_MP_TAC(SET_RULE `t INTER u = {} ==> t INTER u INTER s = {}`) THEN
1185     REWRITE_TAC[INTER_UNIONS; EMPTY_UNIONS; FORALL_IN_GSPEC] THEN
1186     REWRITE_TAC[IN_DELETE; GSYM DISJOINT] THEN ASM_MESON_TAC[pairwise];
1187     ASM SET_TAC[];
1188     ASM SET_TAC[]]);;
1189
1190 let CONNECTED_FROM_CLOSED_UNION_AND_INTER = prove
1191  (`!s t:real^N->bool.
1192         closed s /\ closed t /\ connected(s UNION t) /\ connected(s INTER t)
1193         ==> connected s /\ connected t`,
1194   MATCH_MP_TAC(MESON[]
1195    `(!s t. P s t ==> P t s) /\ (!s t. P s t ==> Q s)
1196     ==> !s t. P s t ==> Q s /\ Q t`) THEN
1197   CONJ_TAC THENL [SIMP_TAC[UNION_COMM; INTER_COMM]; REPEAT STRIP_TAC] THEN
1198   ASM_SIMP_TAC[CONNECTED_CLOSED_SET] THEN
1199   REWRITE_TAC[NOT_EXISTS_THM] THEN
1200   MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
1201   STRIP_TAC THEN ASM_CASES_TAC
1202    `~(s INTER t SUBSET (u:real^N->bool)) /\ ~(s INTER t SUBSET v)`
1203   THENL
1204    [UNDISCH_TAC `connected(s INTER t:real^N->bool)` THEN
1205     ASM_SIMP_TAC[CONNECTED_CLOSED] THEN
1206     MAP_EVERY EXISTS_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
1207     ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
1208     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [DE_MORGAN_THM]) THEN
1209     REWRITE_TAC[] THEN STRIP_TAC THEN
1210     UNDISCH_TAC `connected(s UNION t:real^N->bool)` THEN
1211     ASM_SIMP_TAC[CONNECTED_CLOSED] THENL
1212      [MAP_EVERY EXISTS_TAC [`t UNION u:real^N->bool`; `v:real^N->bool`] THEN
1213       ASM_SIMP_TAC[CLOSED_UNION] THEN ASM SET_TAC[];
1214       MAP_EVERY EXISTS_TAC [`t UNION v:real^N->bool`; `u:real^N->bool`] THEN
1215       ASM_SIMP_TAC[CLOSED_UNION] THEN ASM SET_TAC[]]]);;
1216
1217 let CONNECTED_FROM_OPEN_UNION_AND_INTER = prove
1218  (`!s t:real^N->bool.
1219         open s /\ open t /\ connected(s UNION t) /\ connected(s INTER t)
1220         ==> connected s /\ connected t`,
1221   MATCH_MP_TAC(MESON[]
1222    `(!s t. P s t ==> P t s) /\ (!s t. P s t ==> Q s)
1223     ==> !s t. P s t ==> Q s /\ Q t`) THEN
1224   CONJ_TAC THENL [SIMP_TAC[UNION_COMM; INTER_COMM]; REPEAT STRIP_TAC] THEN
1225   ASM_SIMP_TAC[CONNECTED_OPEN_SET] THEN
1226   REWRITE_TAC[NOT_EXISTS_THM] THEN
1227   MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
1228   STRIP_TAC THEN ASM_CASES_TAC
1229    `~(s INTER t SUBSET (u:real^N->bool)) /\ ~(s INTER t SUBSET v)`
1230   THENL
1231    [UNDISCH_TAC `connected(s INTER t:real^N->bool)` THEN
1232     ASM_SIMP_TAC[connected] THEN
1233     MAP_EVERY EXISTS_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
1234     ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
1235     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [DE_MORGAN_THM]) THEN
1236     REWRITE_TAC[] THEN STRIP_TAC THEN
1237     UNDISCH_TAC `connected(s UNION t:real^N->bool)` THEN
1238     ASM_SIMP_TAC[connected] THENL
1239      [MAP_EVERY EXISTS_TAC [`t UNION u:real^N->bool`; `v:real^N->bool`] THEN
1240       ASM_SIMP_TAC[OPEN_UNION] THEN ASM SET_TAC[];
1241       MAP_EVERY EXISTS_TAC [`t UNION v:real^N->bool`; `u:real^N->bool`] THEN
1242       ASM_SIMP_TAC[OPEN_UNION] THEN ASM SET_TAC[]]]);;
1243
1244 (* ------------------------------------------------------------------------- *)
1245 (* Sort of induction principle for connected sets.                           *)
1246 (* ------------------------------------------------------------------------- *)
1247
1248 let CONNECTED_INDUCTION = prove
1249  (`!P Q s:real^N->bool.
1250         connected s /\
1251         (!t a. open_in (subtopology euclidean s) t /\ a IN t
1252                ==> ?z. z IN t /\ P z) /\
1253         (!a. a IN s
1254              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
1255                      !x y. x IN t /\ y IN t /\ P x /\ P y /\ Q x ==> Q y)
1256         ==> !a b. a IN s /\ b IN s /\ P a /\ P b /\ Q a ==> Q b`,
1257   REPEAT STRIP_TAC THEN
1258   GEN_REWRITE_TAC I [TAUT `p <=> ~ ~p`] THEN DISCH_TAC THEN
1259   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONNECTED_OPEN_IN]) THEN
1260   REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
1261    [`{b:real^N | ?t. open_in (subtopology euclidean s) t /\ b IN t /\
1262                      !x. x IN t /\ P x ==> Q x}`;
1263     `{b:real^N | ?t. open_in (subtopology euclidean s) t /\ b IN t /\
1264                      !x. x IN t /\ P x ==> ~(Q x)}`] THEN
1265   REPEAT CONJ_TAC THENL
1266    [ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN
1267     X_GEN_TAC `c:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
1268     MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[];
1269     ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN
1270     X_GEN_TAC `c:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
1271     MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[];
1272     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNION] THEN
1273     X_GEN_TAC `c:real^N` THEN DISCH_TAC THEN
1274     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N`) THEN ASM SET_TAC[];
1275     REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY; IN_ELIM_THM] THEN
1276     X_GEN_TAC `c:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2
1277      (X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC)
1278      (X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC)) THEN
1279     FIRST_X_ASSUM(MP_TAC o SPECL [`t INTER u:real^N->bool`; `c:real^N`]) THEN
1280     ASM_SIMP_TAC[OPEN_IN_INTER] THEN ASM SET_TAC[];
1281     ASM SET_TAC[];
1282     ASM SET_TAC[]]);;
1283
1284 let CONNECTED_EQUIVALENCE_RELATION_GEN = prove
1285  (`!P R s:real^N->bool.
1286         connected s /\
1287         (!x y. R x y ==> R y x) /\
1288         (!x y z. R x y /\ R y z ==> R x z) /\
1289         (!t a. open_in (subtopology euclidean s) t /\ a IN t
1290                ==> ?z. z IN t /\ P z) /\
1291         (!a. a IN s
1292              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
1293                      !x y. x IN t /\ y IN t /\ P x /\ P y ==> R x y)
1294         ==> !a b. a IN s /\ b IN s /\ P a /\ P b ==> R a b`,
1295   REPEAT GEN_TAC THEN STRIP_TAC THEN
1296   SUBGOAL_THEN
1297    `!a:real^N. a IN s /\ P a
1298                ==> !b c. b IN s /\ c IN s /\ P b /\ P c /\ R a b ==> R a c`
1299   MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
1300   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC CONNECTED_INDUCTION THEN
1301   ASM_MESON_TAC[]);;
1302
1303 let CONNECTED_INDUCTION_SIMPLE = prove
1304  (`!P s:real^N->bool.
1305         connected s /\
1306         (!a. a IN s
1307              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
1308                      !x y. x IN t /\ y IN t /\ P x ==> P y)
1309         ==> !a b. a IN s /\ b IN s /\ P a ==> P b`,
1310   MP_TAC(ISPEC `\x:real^N. T` CONNECTED_INDUCTION) THEN
1311   REWRITE_TAC[] THEN
1312   REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN MESON_TAC[]);;
1313
1314 let CONNECTED_EQUIVALENCE_RELATION = prove
1315  (`!R s:real^N->bool.
1316         connected s /\
1317         (!x y. R x y ==> R y x) /\
1318         (!x y z. R x y /\ R y z ==> R x z) /\
1319         (!a. a IN s
1320              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
1321                      !x. x IN t ==> R a x)
1322         ==> !a b. a IN s /\ b IN s ==> R a b`,
1323   REPEAT GEN_TAC THEN STRIP_TAC THEN
1324   SUBGOAL_THEN
1325    `!a:real^N. a IN s ==> !b c. b IN s /\ c IN s /\ R a b ==> R a c`
1326   MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
1327   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC CONNECTED_INDUCTION_SIMPLE THEN
1328   ASM_MESON_TAC[]);;
1329
1330 (* ------------------------------------------------------------------------- *)
1331 (* Limit points.                                                             *)
1332 (* ------------------------------------------------------------------------- *)
1333
1334 parse_as_infix ("limit_point_of",(12,"right"));;
1335
1336 let limit_point_of = new_definition
1337  `x limit_point_of s <=>
1338         !t. x IN t /\ open t ==> ?y. ~(y = x) /\ y IN s /\ y IN t`;;
1339
1340 let LIMPT_SUBSET = prove
1341  (`!x s t. x limit_point_of s /\ s SUBSET t ==> x limit_point_of t`,
1342   REWRITE_TAC[limit_point_of; SUBSET] THEN MESON_TAC[]);;
1343
1344 let LIMPT_APPROACHABLE = prove
1345  (`!x s. x limit_point_of s <=>
1346                 !e. &0 < e ==> ?x'. x' IN s /\ ~(x' = x) /\ dist(x',x) < e`,
1347   REPEAT GEN_TAC THEN REWRITE_TAC[limit_point_of] THEN
1348   MESON_TAC[open_def; DIST_SYM; OPEN_BALL; CENTRE_IN_BALL; IN_BALL]);;
1349
1350 let LIMPT_APPROACHABLE_LE = prove
1351  (`!x s. x limit_point_of s <=>
1352                 !e. &0 < e ==> ?x'. x' IN s /\ ~(x' = x) /\ dist(x',x) <= e`,
1353   REPEAT GEN_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN
1354   MATCH_MP_TAC(TAUT `(~a <=> ~b) ==> (a <=> b)`) THEN
1355   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
1356   REWRITE_TAC[TAUT `~(a /\ b /\ c) <=> c ==> ~(a /\ b)`; APPROACHABLE_LT_LE]);;
1357
1358 let LIMPT_UNIV = prove
1359  (`!x:real^N. x limit_point_of UNIV`,
1360   GEN_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE; IN_UNIV] THEN
1361   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1362   SUBGOAL_THEN `?c:real^N. norm(c) = e / &2` CHOOSE_TAC THENL
1363    [ASM_SIMP_TAC[VECTOR_CHOOSE_SIZE; REAL_HALF; REAL_LT_IMP_LE];
1364     ALL_TAC] THEN
1365   EXISTS_TAC `x + c:real^N` THEN
1366   REWRITE_TAC[dist; VECTOR_EQ_ADDR] THEN ASM_REWRITE_TAC[VECTOR_ADD_SUB] THEN
1367   SUBGOAL_THEN `&0 < e / &2 /\ e / &2 < e`
1368    (fun th -> ASM_MESON_TAC[th; NORM_0; REAL_LT_REFL]) THEN
1369   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
1370   UNDISCH_TAC `&0 < e` THEN REAL_ARITH_TAC);;
1371
1372 let CLOSED_LIMPT = prove
1373  (`!s. closed s <=> !x. x limit_point_of s ==> x IN s`,
1374   REWRITE_TAC[closed] THEN ONCE_REWRITE_TAC[OPEN_SUBOPEN] THEN
1375   REWRITE_TAC[limit_point_of; IN_DIFF; IN_UNIV; SUBSET] THEN MESON_TAC[]);;
1376
1377 let LIMPT_EMPTY = prove
1378  (`!x. ~(x limit_point_of {})`,
1379   REWRITE_TAC[LIMPT_APPROACHABLE; NOT_IN_EMPTY] THEN MESON_TAC[REAL_LT_01]);;
1380
1381 let NO_LIMIT_POINT_IMP_CLOSED = prove
1382  (`!s. ~(?x. x limit_point_of s) ==> closed s`,
1383   MESON_TAC[CLOSED_LIMPT]);;
1384
1385 let CLOSED_POSITIVE_ORTHANT = prove
1386  (`closed {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
1387                           ==> &0 <= x$i}`,
1388   REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE] THEN
1389   REWRITE_TAC[IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1390   X_GEN_TAC `i:num` THEN STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
1391   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `--(x:real^N $ i)`) THEN
1392   ASM_REWRITE_TAC[REAL_LT_RNEG; REAL_ADD_LID; NOT_EXISTS_THM] THEN
1393   X_GEN_TAC `y:real^N` THEN
1394   MATCH_MP_TAC(TAUT `(a ==> ~c) ==> ~(a /\ b /\ c)`) THEN DISCH_TAC THEN
1395   MATCH_MP_TAC(REAL_ARITH `!b. abs x <= b /\ b <= a ==> ~(a + x < &0)`) THEN
1396   EXISTS_TAC `abs((y - x :real^N)$i)` THEN
1397   ASM_SIMP_TAC[dist; COMPONENT_LE_NORM] THEN
1398   ASM_SIMP_TAC[VECTOR_SUB_COMPONENT; REAL_ARITH
1399    `x < &0 /\ &0 <= y ==> abs(x) <= abs(y - x)`]);;
1400
1401 let FINITE_SET_AVOID = prove
1402  (`!a:real^N s. FINITE s
1403                 ==> ?d. &0 < d /\ !x. x IN s /\ ~(x = a) ==> d <= dist(a,x)`,
1404   GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
1405   REWRITE_TAC[NOT_IN_EMPTY] THEN
1406   CONJ_TAC THENL [MESON_TAC[REAL_LT_01]; ALL_TAC] THEN
1407   MAP_EVERY X_GEN_TAC [`x:real^N`; `s:real^N->bool`] THEN
1408   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
1409   FIRST_X_ASSUM(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
1410   ASM_CASES_TAC `x:real^N = a` THEN REWRITE_TAC[IN_INSERT] THENL
1411    [ASM_MESON_TAC[]; ALL_TAC] THEN
1412   EXISTS_TAC `min d (dist(a:real^N,x))` THEN
1413   ASM_REWRITE_TAC[REAL_LT_MIN; GSYM DIST_NZ; REAL_MIN_LE] THEN
1414   ASM_MESON_TAC[REAL_LE_REFL]);;
1415
1416 let LIMIT_POINT_FINITE = prove
1417  (`!s a. FINITE s ==> ~(a limit_point_of s)`,
1418   REWRITE_TAC[LIMPT_APPROACHABLE; GSYM REAL_NOT_LE] THEN
1419   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM; REAL_NOT_LE;
1420     REAL_NOT_LT; TAUT `~(a /\ b /\ c) <=> a /\ b ==> ~c`] THEN
1421   MESON_TAC[FINITE_SET_AVOID; DIST_SYM]);;
1422
1423 let LIMPT_SING = prove
1424  (`!x y:real^N. ~(x limit_point_of {y})`,
1425   SIMP_TAC[LIMIT_POINT_FINITE; FINITE_SING]);;
1426
1427 let LIMIT_POINT_UNION = prove
1428  (`!s t x:real^N. x limit_point_of (s UNION t) <=>
1429                   x limit_point_of s \/ x limit_point_of t`,
1430   REPEAT GEN_TAC THEN EQ_TAC THENL
1431    [ALL_TAC; MESON_TAC[LIMPT_SUBSET; SUBSET_UNION]] THEN
1432   REWRITE_TAC[LIMPT_APPROACHABLE; IN_UNION] THEN DISCH_TAC THEN
1433   MATCH_MP_TAC(TAUT `(~a ==> b) ==> a \/ b`) THEN
1434   REWRITE_TAC[NOT_FORALL_THM; LEFT_IMP_EXISTS_THM; NOT_IMP] THEN
1435   X_GEN_TAC `e:real` THEN STRIP_TAC THEN X_GEN_TAC `d:real` THEN DISCH_TAC THEN
1436   FIRST_X_ASSUM(MP_TAC o SPEC `min d e`) THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
1437   ASM_MESON_TAC[]);;
1438
1439 let LIMPT_INSERT = prove
1440  (`!s x y:real^N. x limit_point_of (y INSERT s) <=> x limit_point_of s`,
1441   ONCE_REWRITE_TAC[SET_RULE `y INSERT s = {y} UNION s`] THEN
1442   REWRITE_TAC[LIMIT_POINT_UNION] THEN
1443   SIMP_TAC[FINITE_SING; LIMIT_POINT_FINITE]);;
1444
1445 let LIMPT_OF_LIMPTS = prove
1446  (`!x:real^N s.
1447      x limit_point_of {y | y limit_point_of s} ==> x limit_point_of s`,
1448   REWRITE_TAC[LIMPT_APPROACHABLE; IN_ELIM_THM] THEN REPEAT GEN_TAC THEN
1449   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1450   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
1451   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
1452   FIRST_X_ASSUM(MP_TAC o SPEC `dist(y:real^N,x)`) THEN
1453   ASM_SIMP_TAC[DIST_POS_LT] THEN MATCH_MP_TAC MONO_EXISTS THEN
1454   GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1455   REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
1456
1457 let CLOSED_LIMPTS = prove
1458  (`!s. closed {x:real^N | x limit_point_of s}`,
1459   REWRITE_TAC[CLOSED_LIMPT; IN_ELIM_THM; LIMPT_OF_LIMPTS]);;
1460
1461 let DISCRETE_IMP_CLOSED = prove
1462  (`!s:real^N->bool e.
1463         &0 < e /\
1464         (!x y. x IN s /\ y IN s /\ norm(y - x) < e ==> y = x)
1465         ==> closed s`,
1466   REPEAT STRIP_TAC THEN
1467   SUBGOAL_THEN `!x:real^N. ~(x limit_point_of s)`
1468     (fun th -> MESON_TAC[th; CLOSED_LIMPT]) THEN
1469   GEN_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN DISCH_TAC THEN
1470   FIRST_ASSUM(MP_TAC o SPEC `e / &2`) THEN
1471   REWRITE_TAC[REAL_HALF; ASSUME `&0 < e`] THEN
1472   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
1473   FIRST_X_ASSUM(MP_TAC o SPEC `min (e / &2) (dist(x:real^N,y))`) THEN
1474   ASM_SIMP_TAC[REAL_LT_MIN; DIST_POS_LT; REAL_HALF] THEN
1475   DISCH_THEN(X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC) THEN
1476   FIRST_X_ASSUM(MP_TAC o SPECL [`y:real^N`; `z:real^N`]) THEN
1477   ASM_REWRITE_TAC[] THEN ASM_NORM_ARITH_TAC);;
1478
1479 let LIMPT_OF_UNIV = prove
1480  (`!x. x limit_point_of (:real^N)`,
1481   GEN_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE; IN_UNIV] THEN
1482   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1483   MP_TAC(ISPECL [`x:real^N`; `e / &2`] VECTOR_CHOOSE_DIST) THEN
1484   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
1485   POP_ASSUM MP_TAC THEN CONV_TAC NORM_ARITH);;
1486
1487 let LIMPT_OF_OPEN_IN = prove
1488  (`!s t x:real^N.
1489         open_in (subtopology euclidean s) t /\ x limit_point_of s /\ x IN t
1490         ==> x limit_point_of t`,
1491   REWRITE_TAC[open_in; SUBSET; LIMPT_APPROACHABLE] THEN
1492   REPEAT GEN_TAC THEN STRIP_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1493   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
1494   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
1495   FIRST_X_ASSUM(MP_TAC o SPEC `min d e / &2`) THEN
1496   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
1497   GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THEN
1498   TRY(FIRST_X_ASSUM MATCH_MP_TAC) THEN ASM_REWRITE_TAC[] THEN
1499   ASM_REAL_ARITH_TAC);;
1500
1501 let LIMPT_OF_OPEN = prove
1502  (`!s x:real^N. open s /\ x IN s ==> x limit_point_of s`,
1503   REWRITE_TAC[OPEN_IN] THEN ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_UNIV] THEN
1504   MESON_TAC[LIMPT_OF_OPEN_IN; LIMPT_OF_UNIV]);;
1505
1506 let OPEN_IN_SING = prove
1507  (`!s a. open_in (subtopology euclidean s) {a} <=>
1508          a IN s /\ ~(a limit_point_of s)`,
1509   REWRITE_TAC[open_in; LIMPT_APPROACHABLE; SING_SUBSET; IN_SING] THEN
1510   REWRITE_TAC[FORALL_UNWIND_THM2] THEN MESON_TAC[]);;
1511
1512 (* ------------------------------------------------------------------------- *)
1513 (* Interior of a set.                                                        *)
1514 (* ------------------------------------------------------------------------- *)
1515
1516 let interior = new_definition
1517   `interior s = {x | ?t. open t /\ x IN t /\ t SUBSET s}`;;
1518
1519 let INTERIOR_EQ = prove
1520  (`!s. (interior s = s) <=> open s`,
1521   GEN_TAC THEN REWRITE_TAC[EXTENSION; interior; IN_ELIM_THM] THEN
1522   GEN_REWRITE_TAC RAND_CONV [OPEN_SUBOPEN] THEN MESON_TAC[SUBSET]);;
1523
1524 let INTERIOR_OPEN = prove
1525  (`!s. open s ==> (interior s = s)`,
1526   MESON_TAC[INTERIOR_EQ]);;
1527
1528 let INTERIOR_EMPTY = prove
1529  (`interior {} = {}`,
1530   SIMP_TAC[INTERIOR_OPEN; OPEN_EMPTY]);;
1531
1532 let INTERIOR_UNIV = prove
1533  (`interior(:real^N) = (:real^N)`,
1534   SIMP_TAC[INTERIOR_OPEN; OPEN_UNIV]);;
1535
1536 let OPEN_INTERIOR = prove
1537  (`!s. open(interior s)`,
1538   GEN_TAC THEN REWRITE_TAC[interior] THEN GEN_REWRITE_TAC I [OPEN_SUBOPEN] THEN
1539   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
1540
1541 let INTERIOR_INTERIOR = prove
1542  (`!s. interior(interior s) = interior s`,
1543   MESON_TAC[INTERIOR_EQ; OPEN_INTERIOR]);;
1544
1545 let INTERIOR_SUBSET = prove
1546  (`!s. (interior s) SUBSET s`,
1547   REWRITE_TAC[SUBSET; interior; IN_ELIM_THM] THEN MESON_TAC[]);;
1548
1549 let SUBSET_INTERIOR = prove
1550  (`!s t. s SUBSET t ==> (interior s) SUBSET (interior t)`,
1551   REWRITE_TAC[interior; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
1552
1553 let INTERIOR_MAXIMAL = prove
1554  (`!s t. t SUBSET s /\ open t ==> t SUBSET (interior s)`,
1555   REWRITE_TAC[interior; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
1556
1557 let INTERIOR_MAXIMAL_EQ = prove
1558  (`!s t:real^N->bool. open s ==> (s SUBSET interior t <=> s SUBSET t)`,
1559   MESON_TAC[INTERIOR_MAXIMAL; SUBSET_TRANS; INTERIOR_SUBSET]);;
1560
1561 let INTERIOR_UNIQUE = prove
1562  (`!s t. t SUBSET s /\ open t /\ (!t'. t' SUBSET s /\ open t' ==> t' SUBSET t)
1563          ==> (interior s = t)`,
1564   MESON_TAC[SUBSET_ANTISYM; INTERIOR_MAXIMAL; INTERIOR_SUBSET;
1565             OPEN_INTERIOR]);;
1566
1567 let IN_INTERIOR = prove
1568  (`!x s. x IN interior s <=> ?e. &0 < e /\ ball(x,e) SUBSET s`,
1569   REWRITE_TAC[interior; IN_ELIM_THM] THEN
1570   MESON_TAC[OPEN_CONTAINS_BALL; SUBSET_TRANS; CENTRE_IN_BALL; OPEN_BALL]);;
1571
1572 let OPEN_SUBSET_INTERIOR = prove
1573  (`!s t. open s ==> (s SUBSET interior t <=> s SUBSET t)`,
1574   MESON_TAC[INTERIOR_MAXIMAL; INTERIOR_SUBSET; SUBSET_TRANS]);;
1575
1576 let INTERIOR_INTER = prove
1577  (`!s t:real^N->bool. interior(s INTER t) = interior s INTER interior t`,
1578   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
1579    [REWRITE_TAC[SUBSET_INTER] THEN CONJ_TAC THEN
1580     MATCH_MP_TAC SUBSET_INTERIOR THEN REWRITE_TAC[INTER_SUBSET];
1581     MATCH_MP_TAC INTERIOR_MAXIMAL THEN SIMP_TAC[OPEN_INTER; OPEN_INTERIOR] THEN
1582     MATCH_MP_TAC(SET_RULE
1583       `s SUBSET s' /\ t SUBSET t' ==> s INTER t SUBSET s' INTER t'`) THEN
1584     REWRITE_TAC[INTERIOR_SUBSET]]);;
1585
1586 let INTERIOR_FINITE_INTERS = prove
1587  (`!s:(real^N->bool)->bool.
1588         FINITE s ==> interior(INTERS s) = INTERS(IMAGE interior s)`,
1589   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
1590   REWRITE_TAC[INTERS_0; INTERS_INSERT; INTERIOR_UNIV; IMAGE_CLAUSES] THEN
1591   SIMP_TAC[INTERIOR_INTER]);;
1592
1593 let INTERIOR_INTERS_SUBSET = prove
1594  (`!f. interior(INTERS f) SUBSET INTERS (IMAGE interior f)`,
1595   REWRITE_TAC[SUBSET; IN_INTERIOR; IN_INTERS; FORALL_IN_IMAGE] THEN
1596   MESON_TAC[]);;
1597
1598 let UNION_INTERIOR_SUBSET = prove
1599  (`!s t:real^N->bool.
1600         interior s UNION interior t SUBSET interior(s UNION t)`,
1601   SIMP_TAC[INTERIOR_MAXIMAL_EQ; OPEN_UNION; OPEN_INTERIOR] THEN
1602   REPEAT GEN_TAC THEN MATCH_MP_TAC(SET_RULE
1603    `s SUBSET s' /\ t SUBSET t' ==> (s UNION t) SUBSET (s' UNION t')`) THEN
1604   REWRITE_TAC[INTERIOR_SUBSET]);;
1605
1606 let INTERIOR_EQ_EMPTY = prove
1607  (`!s:real^N->bool. interior s = {} <=> !t. open t /\ t SUBSET s ==> t = {}`,
1608   MESON_TAC[INTERIOR_MAXIMAL_EQ; SUBSET_EMPTY;
1609             OPEN_INTERIOR; INTERIOR_SUBSET]);;
1610
1611 let INTERIOR_EQ_EMPTY_ALT = prove
1612  (`!s:real^N->bool.
1613         interior s = {} <=>
1614         !t. open t /\ ~(t = {}) ==> ~(t DIFF s = {})`,
1615   GEN_TAC THEN REWRITE_TAC[INTERIOR_EQ_EMPTY] THEN SET_TAC[]);;
1616
1617 let INTERIOR_LIMIT_POINT = prove
1618  (`!s x:real^N. x IN interior s ==> x limit_point_of s`,
1619   REPEAT GEN_TAC THEN
1620   REWRITE_TAC[IN_INTERIOR; IN_ELIM_THM; SUBSET; IN_BALL] THEN
1621   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
1622   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `d:real` THEN
1623   DISCH_TAC THEN
1624   MP_TAC(ISPECL [`x:real^N`; `min d e / &2`] VECTOR_CHOOSE_DIST) THEN
1625   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
1626   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
1627   REPEAT CONJ_TAC THENL
1628    [FIRST_X_ASSUM MATCH_MP_TAC;
1629     CONV_TAC (RAND_CONV SYM_CONV) THEN REWRITE_TAC[GSYM DIST_EQ_0];
1630     ONCE_REWRITE_TAC[DIST_SYM]] THEN
1631   ASM_REAL_ARITH_TAC);;
1632
1633 let INTERIOR_SING = prove
1634  (`!a:real^N. interior {a} = {}`,
1635   REWRITE_TAC[EXTENSION; NOT_IN_EMPTY] THEN
1636   MESON_TAC[INTERIOR_LIMIT_POINT; LIMPT_SING]);;
1637
1638 let INTERIOR_CLOSED_UNION_EMPTY_INTERIOR = prove
1639  (`!s t:real^N->bool.
1640         closed(s) /\ interior(t) = {}
1641         ==> interior(s UNION t) = interior(s)`,
1642   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
1643   SIMP_TAC[SUBSET_INTERIOR; SUBSET_UNION] THEN
1644   REWRITE_TAC[SUBSET; IN_INTERIOR; IN_INTER; IN_UNION] THEN
1645   X_GEN_TAC `x:real^N` THEN MATCH_MP_TAC MONO_EXISTS THEN
1646   X_GEN_TAC `e:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1647   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
1648   SUBGOAL_THEN `(y:real^N) limit_point_of s`
1649    (fun th -> ASM_MESON_TAC[CLOSED_LIMPT; th]) THEN
1650   REWRITE_TAC[IN_INTERIOR; NOT_IN_EMPTY; LIMPT_APPROACHABLE] THEN
1651   X_GEN_TAC `d:real` THEN DISCH_TAC THEN
1652   SUBGOAL_THEN
1653    `?z:real^N. ~(z IN t) /\ ~(z = y) /\ dist(z,y) < d /\ dist(x,z) < e`
1654    (fun th -> ASM_MESON_TAC[th; IN_BALL]) THEN
1655   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_BALL]) THEN
1656   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
1657   REWRITE_TAC[IN_INTERIOR; NOT_IN_EMPTY; NOT_EXISTS_THM] THEN
1658   ABBREV_TAC `k = min d (e - dist(x:real^N,y))` THEN
1659   SUBGOAL_THEN `&0 < k` ASSUME_TAC THENL
1660    [ASM_ARITH_TAC; ALL_TAC] THEN
1661   SUBGOAL_THEN `?w:real^N. dist(y,w) = k / &2` CHOOSE_TAC THENL
1662    [ASM_SIMP_TAC[VECTOR_CHOOSE_DIST; REAL_HALF; REAL_LT_IMP_LE]; ALL_TAC] THEN
1663   DISCH_THEN(MP_TAC o SPECL [`w:real^N`; `k / &4`]) THEN
1664   ASM_SIMP_TAC[SUBSET; NOT_FORALL_THM; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH;
1665                NOT_IMP; IN_BALL] THEN
1666   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `z:real^N` THEN
1667   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN ASM_REWRITE_TAC[] THEN
1668   ASM_NORM_ARITH_TAC);;
1669
1670 let INTERIOR_UNION_EQ_EMPTY = prove
1671  (`!s t:real^N->bool.
1672         closed s \/ closed t
1673         ==> (interior(s UNION t) = {} <=>
1674              interior s = {} /\ interior t = {})`,
1675   REPEAT GEN_TAC THEN DISCH_TAC THEN EQ_TAC THENL
1676    [ASM_MESON_TAC[SUBSET_UNION; SUBSET_INTERIOR; SUBSET_EMPTY];
1677     ASM_MESON_TAC[UNION_COMM; INTERIOR_CLOSED_UNION_EMPTY_INTERIOR]]);;
1678
1679 let INTERIOR_UNIONS_OPEN_SUBSETS = prove
1680  (`!s:real^N->bool. UNIONS {t | open t /\ t SUBSET s} = interior s`,
1681   GEN_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC INTERIOR_UNIQUE THEN
1682   SIMP_TAC[OPEN_UNIONS; IN_ELIM_THM] THEN SET_TAC[]);;
1683
1684 (* ------------------------------------------------------------------------- *)
1685 (* Closure of a set.                                                         *)
1686 (* ------------------------------------------------------------------------- *)
1687
1688 let closure = new_definition
1689   `closure s = s UNION {x | x limit_point_of s}`;;
1690
1691 let CLOSURE_INTERIOR = prove
1692  (`!s:real^N->bool. closure s = UNIV DIFF (interior (UNIV DIFF s))`,
1693   REWRITE_TAC[EXTENSION; closure; IN_UNION; IN_DIFF; IN_UNIV; interior;
1694               IN_ELIM_THM; limit_point_of; SUBSET] THEN
1695   MESON_TAC[]);;
1696
1697 let INTERIOR_CLOSURE = prove
1698  (`!s:real^N->bool. interior s = UNIV DIFF (closure (UNIV DIFF s))`,
1699   let lemma = prove(`!s t. UNIV DIFF (UNIV DIFF t) = t`,SET_TAC[]) in
1700   REWRITE_TAC[CLOSURE_INTERIOR; lemma]);;
1701
1702 let CLOSED_CLOSURE = prove
1703  (`!s. closed(closure s)`,
1704   let lemma = prove(`UNIV DIFF (UNIV DIFF s) = s`,SET_TAC[]) in
1705   REWRITE_TAC[closed; CLOSURE_INTERIOR; lemma; OPEN_INTERIOR]);;
1706
1707 let CLOSURE_HULL = prove
1708  (`!s. closure s = closed hull s`,
1709   GEN_TAC THEN MATCH_MP_TAC(GSYM HULL_UNIQUE) THEN
1710   REWRITE_TAC[CLOSED_CLOSURE; SUBSET] THEN
1711   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM; CLOSED_LIMPT] THEN
1712   MESON_TAC[limit_point_of]);;
1713
1714 let CLOSURE_EQ = prove
1715  (`!s. (closure s = s) <=> closed s`,
1716   SIMP_TAC[CLOSURE_HULL; HULL_EQ; CLOSED_INTERS]);;
1717
1718 let CLOSURE_CLOSED = prove
1719  (`!s. closed s ==> (closure s = s)`,
1720   MESON_TAC[CLOSURE_EQ]);;
1721
1722 let CLOSURE_CLOSURE = prove
1723  (`!s. closure(closure s) = closure s`,
1724   REWRITE_TAC[CLOSURE_HULL; HULL_HULL]);;
1725
1726 let CLOSURE_SUBSET = prove
1727  (`!s. s SUBSET (closure s)`,
1728   REWRITE_TAC[CLOSURE_HULL; HULL_SUBSET]);;
1729
1730 let SUBSET_CLOSURE = prove
1731  (`!s t. s SUBSET t ==> (closure s) SUBSET (closure t)`,
1732   REWRITE_TAC[CLOSURE_HULL; HULL_MONO]);;
1733
1734 let CLOSURE_UNION = prove
1735  (`!s t:real^N->bool. closure(s UNION t) = closure s UNION closure t`,
1736   REWRITE_TAC[LIMIT_POINT_UNION; closure] THEN SET_TAC[]);;
1737
1738 let CLOSURE_INTER_SUBSET = prove
1739  (`!s t. closure(s INTER t) SUBSET closure(s) INTER closure(t)`,
1740   REPEAT GEN_TAC THEN REWRITE_TAC[SUBSET_INTER] THEN
1741   CONJ_TAC THEN MATCH_MP_TAC SUBSET_CLOSURE THEN SET_TAC[]);;
1742
1743 let CLOSURE_INTERS_SUBSET = prove
1744  (`!f. closure(INTERS f) SUBSET INTERS(IMAGE closure f)`,
1745   REWRITE_TAC[SET_RULE `s SUBSET INTERS f <=> !t. t IN f ==> s SUBSET t`] THEN
1746   REWRITE_TAC[FORALL_IN_IMAGE] THEN REPEAT STRIP_TAC THEN
1747   MATCH_MP_TAC SUBSET_CLOSURE THEN ASM SET_TAC[]);;
1748
1749 let CLOSURE_MINIMAL = prove
1750  (`!s t. s SUBSET t /\ closed t ==> (closure s) SUBSET t`,
1751   REWRITE_TAC[HULL_MINIMAL; CLOSURE_HULL]);;
1752
1753 let CLOSURE_MINIMAL_EQ = prove
1754  (`!s t:real^N->bool. closed t ==> (closure s SUBSET t <=> s SUBSET t)`,
1755   MESON_TAC[SUBSET_TRANS; CLOSURE_SUBSET; CLOSURE_MINIMAL]);;
1756
1757 let CLOSURE_UNIQUE = prove
1758  (`!s t. s SUBSET t /\ closed t /\
1759          (!t'. s SUBSET t' /\ closed t' ==> t SUBSET t')
1760          ==> (closure s = t)`,
1761   REWRITE_TAC[CLOSURE_HULL; HULL_UNIQUE]);;
1762
1763 let CLOSURE_EMPTY = prove
1764  (`closure {} = {}`,
1765   SIMP_TAC[CLOSURE_CLOSED; CLOSED_EMPTY]);;
1766
1767 let CLOSURE_UNIV = prove
1768  (`closure(:real^N) = (:real^N)`,
1769   SIMP_TAC[CLOSURE_CLOSED; CLOSED_UNIV]);;
1770
1771 let CLOSURE_UNIONS = prove
1772  (`!f. FINITE f ==> closure(UNIONS f) = UNIONS {closure s | s IN f}`,
1773   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
1774   REWRITE_TAC[UNIONS_0; UNIONS_INSERT; SET_RULE `{f x | x IN {}} = {}`;
1775      SET_RULE `{f x | x IN a INSERT s} = (f a) INSERT {f x | x IN s}`] THEN
1776   SIMP_TAC[CLOSURE_EMPTY; CLOSURE_UNION]);;
1777
1778 let CLOSURE_EQ_EMPTY = prove
1779  (`!s. closure s = {} <=> s = {}`,
1780   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CLOSURE_EMPTY] THEN
1781   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> t = {} ==> s = {}`) THEN
1782   REWRITE_TAC[CLOSURE_SUBSET]);;
1783
1784 let CLOSURE_SUBSET_EQ = prove
1785  (`!s:real^N->bool. closure s SUBSET s <=> closed s`,
1786   GEN_TAC THEN REWRITE_TAC[GSYM CLOSURE_EQ] THEN
1787   MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[]);;
1788
1789 let OPEN_INTER_CLOSURE_EQ_EMPTY = prove
1790  (`!s t:real^N->bool.
1791         open s ==> (s INTER (closure t) = {} <=> s INTER t = {})`,
1792   REPEAT STRIP_TAC THEN EQ_TAC THENL
1793    [MP_TAC(ISPEC `t:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[]; ALL_TAC] THEN
1794   DISCH_TAC THEN REWRITE_TAC[CLOSURE_INTERIOR] THEN
1795   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> s INTER (UNIV DIFF t) = {}`) THEN
1796   ASM_SIMP_TAC[OPEN_SUBSET_INTERIOR] THEN ASM SET_TAC[]);;
1797
1798 let OPEN_INTER_CLOSURE_SUBSET = prove
1799  (`!s t:real^N->bool.
1800         open s ==> (s INTER (closure t)) SUBSET closure(s INTER t)`,
1801   REPEAT STRIP_TAC THEN
1802   SIMP_TAC[SUBSET; IN_INTER; closure; IN_UNION; IN_ELIM_THM] THEN
1803   X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1804   DISJ2_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN
1805   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1806   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [open_def]) THEN
1807   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
1808   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
1809   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIMPT_APPROACHABLE]) THEN
1810   DISCH_THEN(MP_TAC o SPEC `min d e`) THEN
1811   ASM_REWRITE_TAC[REAL_LT_MIN; IN_INTER] THEN
1812   MATCH_MP_TAC MONO_EXISTS THEN ASM_MESON_TAC[]);;
1813
1814 let CLOSURE_OPEN_INTER_SUPERSET = prove
1815  (`!s t:real^N->bool.
1816         open s /\ s SUBSET closure t ==> closure(s INTER t) = closure s`,
1817   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
1818   SIMP_TAC[SUBSET_CLOSURE; INTER_SUBSET] THEN
1819   MATCH_MP_TAC CLOSURE_MINIMAL THEN REWRITE_TAC[CLOSED_CLOSURE] THEN
1820   W(MP_TAC o PART_MATCH (rand o rand)
1821     OPEN_INTER_CLOSURE_SUBSET o rand o snd) THEN
1822   ASM_REWRITE_TAC[] THEN
1823   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] SUBSET_TRANS) THEN ASM SET_TAC[]);;
1824
1825 let CLOSURE_COMPLEMENT = prove
1826  (`!s:real^N->bool. closure(UNIV DIFF s) = UNIV DIFF interior(s)`,
1827   REWRITE_TAC[SET_RULE `s = UNIV DIFF t <=> UNIV DIFF s = t`] THEN
1828   REWRITE_TAC[GSYM INTERIOR_CLOSURE]);;
1829
1830 let INTERIOR_COMPLEMENT = prove
1831  (`!s:real^N->bool. interior(UNIV DIFF s) = UNIV DIFF closure(s)`,
1832   REWRITE_TAC[SET_RULE `s = UNIV DIFF t <=> UNIV DIFF s = t`] THEN
1833   REWRITE_TAC[GSYM CLOSURE_INTERIOR]);;
1834
1835 let CONNECTED_INTERMEDIATE_CLOSURE = prove
1836  (`!s t:real^N->bool.
1837         connected s /\ s SUBSET t /\ t SUBSET closure s ==> connected t`,
1838   REPEAT GEN_TAC THEN REWRITE_TAC[connected; NOT_EXISTS_THM] THEN
1839   STRIP_TAC THEN
1840   MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN STRIP_TAC THEN
1841   FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^N->bool`; `v:real^N->bool`]) THEN
1842   ASM_REWRITE_TAC[] THEN ASSUME_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN
1843   REPLICATE_TAC 2 (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
1844   REWRITE_TAC[GSYM DE_MORGAN_THM] THEN STRIP_TAC THENL
1845    [SUBGOAL_THEN `(closure s) SUBSET ((:real^N) DIFF u)` MP_TAC THENL
1846      [MATCH_MP_TAC CLOSURE_MINIMAL THEN ASM_REWRITE_TAC[GSYM OPEN_CLOSED];
1847       ALL_TAC];
1848     SUBGOAL_THEN `(closure s) SUBSET ((:real^N) DIFF v)` MP_TAC THENL
1849      [MATCH_MP_TAC CLOSURE_MINIMAL THEN ASM_REWRITE_TAC[GSYM OPEN_CLOSED];
1850       ALL_TAC]] THEN
1851   ASM SET_TAC[]);;
1852
1853 let CONNECTED_CLOSURE = prove
1854  (`!s:real^N->bool. connected s ==> connected(closure s)`,
1855   MESON_TAC[CONNECTED_INTERMEDIATE_CLOSURE; CLOSURE_SUBSET; SUBSET_REFL]);;
1856
1857 let CONNECTED_UNION_STRONG = prove
1858  (`!s t:real^N->bool.
1859         connected s /\ connected t /\ ~(closure s INTER t = {})
1860         ==> connected(s UNION t)`,
1861   REPEAT STRIP_TAC THEN
1862   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
1863   DISCH_THEN(X_CHOOSE_TAC `p:real^N`) THEN
1864   SUBGOAL_THEN `s UNION t = ((p:real^N) INSERT s) UNION t` SUBST1_TAC THENL
1865    [ASM SET_TAC[]; ALL_TAC] THEN
1866   MATCH_MP_TAC CONNECTED_UNION THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
1867    [MATCH_MP_TAC CONNECTED_INTERMEDIATE_CLOSURE THEN
1868     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
1869     MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
1870     ASM SET_TAC[]]);;
1871
1872 let INTERIOR_DIFF = prove
1873  (`!s t. interior(s DIFF t) = interior(s) DIFF closure(t)`,
1874   ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
1875   REWRITE_TAC[INTERIOR_INTER; CLOSURE_INTERIOR] THEN SET_TAC[]);;
1876
1877 let LIMPT_OF_CLOSURE = prove
1878  (`!x:real^N s. x limit_point_of closure s <=> x limit_point_of s`,
1879   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM; LIMIT_POINT_UNION] THEN
1880   REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT `(q ==> p) ==> (p \/ q <=> p)`) THEN
1881   REWRITE_TAC[LIMPT_OF_LIMPTS]);;
1882
1883 let CLOSED_IN_LIMPT = prove
1884  (`!s t. closed_in (subtopology euclidean t) s <=>
1885          s SUBSET t /\ !x:real^N. x limit_point_of s /\ x IN t ==> x IN s`,
1886   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN_CLOSED] THEN EQ_TAC THENL
1887    [DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
1888     ASM_SIMP_TAC[IN_INTER] THEN
1889     ASM_MESON_TAC[CLOSED_LIMPT; LIMPT_SUBSET; INTER_SUBSET];
1890     STRIP_TAC THEN EXISTS_TAC `closure s :real^N->bool` THEN
1891     REWRITE_TAC[CLOSED_CLOSURE] THEN REWRITE_TAC[closure] THEN
1892     ASM SET_TAC[]]);;
1893
1894 let CLOSED_IN_INTER_CLOSURE = prove
1895  (`!s t:real^N->bool.
1896         closed_in (subtopology euclidean s) t <=> s INTER closure t = t`,
1897   REWRITE_TAC[closure; CLOSED_IN_LIMPT] THEN SET_TAC[]);;
1898
1899 let INTERIOR_CLOSURE_IDEMP = prove
1900  (`!s:real^N->bool.
1901         interior(closure(interior(closure s))) = interior(closure s)`,
1902   GEN_TAC THEN MATCH_MP_TAC INTERIOR_UNIQUE THEN
1903   ASM_MESON_TAC[OPEN_INTERIOR; CLOSURE_SUBSET; CLOSURE_CLOSURE; SUBSET_TRANS;
1904                 OPEN_SUBSET_INTERIOR;SUBSET_CLOSURE; INTERIOR_SUBSET]);;
1905
1906 let CLOSURE_INTERIOR_IDEMP = prove
1907  (`!s:real^N->bool.
1908         closure(interior(closure(interior s))) = closure(interior s)`,
1909   GEN_TAC THEN
1910   ONCE_REWRITE_TAC[SET_RULE `s = t <=> UNIV DIFF s = UNIV DIFF t`] THEN
1911   REWRITE_TAC[GSYM INTERIOR_COMPLEMENT; GSYM CLOSURE_COMPLEMENT] THEN
1912   REWRITE_TAC[INTERIOR_CLOSURE_IDEMP]);;
1913
1914 let NOWHERE_DENSE_UNION = prove
1915  (`!s t:real^N->bool.
1916         interior(closure(s UNION t)) = {} <=>
1917         interior(closure s) = {} /\ interior(closure t) = {}`,
1918   SIMP_TAC[CLOSURE_UNION; INTERIOR_UNION_EQ_EMPTY; CLOSED_CLOSURE]);;
1919
1920 let NOWHERE_DENSE = prove
1921  (`!s:real^N->bool.
1922         interior(closure s) = {} <=>
1923         !t. open t /\ ~(t = {})
1924             ==> ?u. open u /\ ~(u = {}) /\ u SUBSET t /\ u INTER s = {}`,
1925   GEN_TAC THEN REWRITE_TAC[INTERIOR_EQ_EMPTY_ALT] THEN EQ_TAC THEN
1926   DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THENL
1927    [EXISTS_TAC `t DIFF closure s:real^N->bool` THEN
1928     ASM_SIMP_TAC[OPEN_DIFF; CLOSED_CLOSURE] THEN
1929     MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[];
1930     FIRST_X_ASSUM(MP_TAC o SPEC `t:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
1931     DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
1932     MP_TAC(ISPECL [`u:real^N->bool`; `s:real^N->bool`]
1933         OPEN_INTER_CLOSURE_EQ_EMPTY) THEN
1934     ASM SET_TAC[]]);;
1935
1936 let INTERIOR_CLOSURE_INTER_OPEN = prove
1937  (`!s t:real^N->bool.
1938         open s /\ open t
1939         ==> interior(closure(s INTER t)) =
1940             interior(closure s) INTER interior(closure t)`,
1941   REPEAT STRIP_TAC THEN REWRITE_TAC[SET_RULE
1942    `u = s INTER t <=> s INTER t SUBSET u /\ u SUBSET s /\ u SUBSET t`] THEN
1943   SIMP_TAC[SUBSET_INTERIOR; SUBSET_CLOSURE; INTER_SUBSET] THEN
1944   MATCH_MP_TAC INTERIOR_MAXIMAL THEN SIMP_TAC[OPEN_INTER; OPEN_INTERIOR] THEN
1945   REWRITE_TAC[SET_RULE `s SUBSET t <=> s INTER (UNIV DIFF t) = {}`;
1946               GSYM INTERIOR_COMPLEMENT] THEN
1947   REWRITE_TAC[GSYM INTERIOR_INTER] THEN
1948   REWRITE_TAC[INTERIOR_EQ_EMPTY] THEN
1949   X_GEN_TAC `u:real^N->bool` THEN STRIP_TAC THEN
1950   MP_TAC(ISPECL [`u INTER s:real^N->bool`; `t:real^N->bool`]
1951         OPEN_INTER_CLOSURE_EQ_EMPTY) THEN
1952   MP_TAC(ISPECL [`u:real^N->bool`; `s:real^N->bool`]
1953         OPEN_INTER_CLOSURE_EQ_EMPTY) THEN
1954   ASM_SIMP_TAC[OPEN_INTER] THEN ASM SET_TAC[]);;
1955
1956 let CLOSURE_INTERIOR_UNION_CLOSED = prove
1957  (`!s t:real^N->bool.
1958         closed s /\ closed t
1959         ==> closure(interior(s UNION t)) =
1960             closure(interior s) UNION closure(interior t)`,
1961   REPEAT GEN_TAC THEN REWRITE_TAC[closed] THEN
1962   DISCH_THEN(MP_TAC o MATCH_MP INTERIOR_CLOSURE_INTER_OPEN) THEN
1963   REWRITE_TAC[CLOSURE_COMPLEMENT; INTERIOR_COMPLEMENT;
1964               SET_RULE `(UNIV DIFF s) INTER (UNIV DIFF t) =
1965                         UNIV DIFF (s UNION t)`] THEN
1966   SET_TAC[]);;
1967
1968 let REGULAR_OPEN_INTER = prove
1969  (`!s t:real^N->bool.
1970         interior(closure s) = s /\ interior(closure t) = t
1971         ==> interior(closure(s INTER t)) = s INTER t`,
1972   MESON_TAC[INTERIOR_CLOSURE_INTER_OPEN; OPEN_INTERIOR]);;
1973
1974 let REGULAR_CLOSED_UNION = prove
1975  (`!s t:real^N->bool.
1976         closure(interior s) = s /\ closure(interior t) = t
1977         ==> closure(interior(s UNION t)) = s UNION t`,
1978   MESON_TAC[CLOSURE_INTERIOR_UNION_CLOSED; CLOSED_CLOSURE]);;
1979
1980 let DIFF_CLOSURE_SUBSET = prove
1981  (`!s t:real^N->bool. closure(s) DIFF closure t SUBSET closure(s DIFF t)`,
1982   REPEAT GEN_TAC THEN
1983   MP_TAC(ISPECL [`(:real^N) DIFF closure t`; `s:real^N->bool`]
1984         OPEN_INTER_CLOSURE_SUBSET) THEN
1985   REWRITE_TAC[SET_RULE `(UNIV DIFF t) INTER s = s DIFF t`] THEN
1986   REWRITE_TAC[GSYM closed; CLOSED_CLOSURE] THEN
1987   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] SUBSET_TRANS) THEN
1988   MATCH_MP_TAC SUBSET_CLOSURE THEN
1989   MATCH_MP_TAC(SET_RULE `t SUBSET u ==> s DIFF u SUBSET s DIFF t`) THEN
1990   REWRITE_TAC[CLOSURE_SUBSET]);;
1991
1992 (* ------------------------------------------------------------------------- *)
1993 (* Frontier (aka boundary).                                                  *)
1994 (* ------------------------------------------------------------------------- *)
1995
1996 let frontier = new_definition
1997   `frontier s = (closure s) DIFF (interior s)`;;
1998
1999 let FRONTIER_CLOSED = prove
2000  (`!s. closed(frontier s)`,
2001   SIMP_TAC[frontier; CLOSED_DIFF; CLOSED_CLOSURE; OPEN_INTERIOR]);;
2002
2003 let FRONTIER_CLOSURES = prove
2004  (`!s:real^N->bool. frontier s = (closure s) INTER (closure(UNIV DIFF s))`,
2005   let lemma = prove(`s DIFF (UNIV DIFF t) = s INTER t`,SET_TAC[]) in
2006   REWRITE_TAC[frontier; INTERIOR_CLOSURE; lemma]);;
2007
2008 let FRONTIER_STRADDLE = prove
2009  (`!a:real^N s.
2010      a IN frontier s <=>
2011         !e. &0 < e ==> (?x. x IN s /\ dist(a,x) < e) /\
2012                        (?x. ~(x IN s) /\ dist(a,x) < e)`,
2013   REPEAT GEN_TAC THEN REWRITE_TAC[FRONTIER_CLOSURES; IN_INTER] THEN
2014   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM; limit_point_of;
2015               IN_UNIV; IN_DIFF] THEN
2016   ASM_MESON_TAC[IN_BALL; SUBSET; OPEN_CONTAINS_BALL;
2017                 CENTRE_IN_BALL; OPEN_BALL; DIST_REFL]);;
2018
2019 let FRONTIER_SUBSET_CLOSED = prove
2020  (`!s. closed s ==> (frontier s) SUBSET s`,
2021   MESON_TAC[frontier; CLOSURE_CLOSED; SUBSET_DIFF]);;
2022
2023 let FRONTIER_EMPTY = prove
2024  (`frontier {} = {}`,
2025   REWRITE_TAC[frontier; CLOSURE_EMPTY; EMPTY_DIFF]);;
2026
2027 let FRONTIER_UNIV = prove
2028  (`frontier(:real^N) = {}`,
2029   REWRITE_TAC[frontier; CLOSURE_UNIV; INTERIOR_UNIV] THEN SET_TAC[]);;
2030
2031 let FRONTIER_SUBSET_EQ = prove
2032  (`!s:real^N->bool. (frontier s) SUBSET s <=> closed s`,
2033   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[FRONTIER_SUBSET_CLOSED] THEN
2034   REWRITE_TAC[frontier] THEN
2035   DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
2036    `s DIFF t SUBSET u ==> t SUBSET u ==> s SUBSET u`)) THEN
2037   REWRITE_TAC[INTERIOR_SUBSET; CLOSURE_SUBSET_EQ]);;
2038
2039 let FRONTIER_COMPLEMENT = prove
2040  (`!s:real^N->bool. frontier(UNIV DIFF s) = frontier s`,
2041   REWRITE_TAC[frontier; CLOSURE_COMPLEMENT; INTERIOR_COMPLEMENT] THEN
2042   SET_TAC[]);;
2043
2044 let FRONTIER_DISJOINT_EQ = prove
2045  (`!s. (frontier s) INTER s = {} <=> open s`,
2046   ONCE_REWRITE_TAC[GSYM FRONTIER_COMPLEMENT; OPEN_CLOSED] THEN
2047   REWRITE_TAC[GSYM FRONTIER_SUBSET_EQ] THEN SET_TAC[]);;
2048
2049 let FRONTIER_INTER_SUBSET = prove
2050  (`!s t. frontier(s INTER t) SUBSET frontier(s) UNION frontier(t)`,
2051   REPEAT GEN_TAC THEN REWRITE_TAC[frontier; INTERIOR_INTER] THEN
2052   MATCH_MP_TAC(SET_RULE
2053    `cst SUBSET cs INTER ct
2054     ==> cst DIFF (s INTER t) SUBSET (cs DIFF s) UNION (ct DIFF t)`) THEN
2055   REWRITE_TAC[CLOSURE_INTER_SUBSET]);;
2056
2057 let FRONTIER_UNION_SUBSET = prove
2058  (`!s t:real^N->bool. frontier(s UNION t) SUBSET frontier s UNION frontier t`,
2059   ONCE_REWRITE_TAC[GSYM FRONTIER_COMPLEMENT] THEN
2060   REWRITE_TAC[SET_RULE `u DIFF (s UNION t) = (u DIFF s) INTER (u DIFF t)`] THEN
2061   REWRITE_TAC[FRONTIER_INTER_SUBSET]);;
2062
2063 let FRONTIER_INTERIORS = prove
2064  (`!s. frontier s = (:real^N) DIFF interior(s) DIFF interior((:real^N) DIFF s)`,
2065   REWRITE_TAC[frontier; CLOSURE_INTERIOR] THEN SET_TAC[]);;
2066
2067 let FRONTIER_FRONTIER_SUBSET = prove
2068  (`!s:real^N->bool. frontier(frontier s) SUBSET frontier s`,
2069   GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [frontier] THEN
2070   SIMP_TAC[CLOSURE_CLOSED; FRONTIER_CLOSED] THEN SET_TAC[]);;
2071
2072 let INTERIOR_FRONTIER = prove
2073  (`!s:real^N->bool.
2074         interior(frontier s) = interior(closure s) DIFF closure(interior s)`,
2075   ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
2076   REWRITE_TAC[GSYM INTERIOR_COMPLEMENT; GSYM INTERIOR_INTER; frontier] THEN
2077   GEN_TAC THEN AP_TERM_TAC THEN SET_TAC[]);;
2078
2079 let INTERIOR_FRONTIER_EMPTY = prove
2080  (`!s:real^N->bool. open s \/ closed s ==> interior(frontier s) = {}`,
2081   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[INTERIOR_FRONTIER] THEN
2082   ASM_SIMP_TAC[CLOSURE_CLOSED; INTERIOR_OPEN] THEN
2083   REWRITE_TAC[SET_RULE `s DIFF t = {} <=> s SUBSET t`] THEN
2084   REWRITE_TAC[INTERIOR_SUBSET; CLOSURE_SUBSET]);;
2085
2086 let FRONTIER_FRONTIER = prove
2087  (`!s:real^N->bool. open s \/ closed s ==> frontier(frontier s) = frontier s`,
2088   GEN_TAC THEN GEN_REWRITE_TAC (RAND_CONV o LAND_CONV) [frontier] THEN
2089   SIMP_TAC[INTERIOR_FRONTIER_EMPTY; CLOSURE_CLOSED; FRONTIER_CLOSED] THEN
2090   REWRITE_TAC[DIFF_EMPTY]);;
2091
2092 let FRONTIER_FRONTIER_FRONTIER = prove
2093  (`!s:real^N->bool. frontier(frontier(frontier s)) = frontier(frontier s)`,
2094   SIMP_TAC[FRONTIER_FRONTIER; FRONTIER_CLOSED]);;
2095
2096 let UNION_FRONTIER = prove
2097  (`!s t:real^N->bool.
2098         frontier(s) UNION frontier(t) =
2099         frontier(s UNION t) UNION
2100         frontier(s INTER t) UNION
2101         frontier(s) INTER frontier(t)`,
2102   let lemma = prove
2103    (`!s t x. x IN frontier s /\ x IN interior t ==> x IN frontier(s INTER t)`,
2104     REWRITE_TAC[FRONTIER_STRADDLE; IN_INTER; IN_INTERIOR; SUBSET; IN_BALL] THEN
2105     REPEAT GEN_TAC THEN
2106     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_TAC `d:real`)) THEN
2107     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2108     FIRST_X_ASSUM(MP_TAC o SPEC `min d e:real`) THEN
2109     ASM_REWRITE_TAC[REAL_LT_MIN] THEN ASM_MESON_TAC[]) in
2110   REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; UNION_SUBSET;
2111               FRONTIER_UNION_SUBSET; FRONTIER_INTER_SUBSET;
2112               SET_RULE `s INTER t SUBSET s UNION t`] THEN
2113   REWRITE_TAC[GSYM UNION_SUBSET] THEN REWRITE_TAC[SUBSET; IN_UNION] THEN
2114   MATCH_MP_TAC(MESON[]
2115    `(!s t x. P s x ==> R x s t) /\ (!s t x. R x s t <=> R x t s)
2116     ==> (!s t x. P s x \/ P t x ==> R x s t)`) THEN
2117   CONJ_TAC THENL [REPEAT STRIP_TAC; REWRITE_TAC[UNION_COMM; INTER_COMM]] THEN
2118   ASM_CASES_TAC `(x:real^N) IN frontier t` THEN ASM_REWRITE_TAC[IN_INTER] THEN
2119   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE (RAND_CONV o RAND_CONV)
2120         [FRONTIER_INTERIORS]) THEN
2121   REWRITE_TAC[DE_MORGAN_THM; IN_DIFF; IN_UNIV] THEN
2122   GEN_REWRITE_TAC RAND_CONV [DISJ_SYM] THEN MATCH_MP_TAC MONO_OR THEN
2123   ASM_SIMP_TAC[lemma] THEN
2124   POP_ASSUM MP_TAC THEN ONCE_REWRITE_TAC[GSYM FRONTIER_COMPLEMENT] THEN
2125   SIMP_TAC[lemma; SET_RULE
2126     `UNIV DIFF (s UNION t) = (UNIV DIFF s) INTER (UNIV DIFF t)`]);;
2127
2128 let CONNECTED_INTER_FRONTIER = prove
2129  (`!s t:real^N->bool.
2130         connected s /\ ~(s INTER t = {}) /\ ~(s DIFF t = {})
2131         ==> ~(s INTER frontier t = {})`,
2132   REWRITE_TAC[FRONTIER_INTERIORS] THEN REPEAT STRIP_TAC THEN
2133   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONNECTED_OPEN_IN]) THEN
2134   REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
2135    [`s INTER interior t:real^N->bool`;
2136     `s INTER (interior((:real^N) DIFF t))`] THEN
2137   SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_INTERIOR] THEN
2138   MAP_EVERY (MP_TAC o C ISPEC INTERIOR_SUBSET)
2139    [`t:real^N->bool`; `(:real^N) DIFF t`] THEN
2140   ASM SET_TAC[]);;
2141
2142 let INTERIOR_CLOSED_EQ_EMPTY_AS_FRONTIER = prove
2143  (`!s:real^N->bool.
2144         closed s /\ interior s = {} <=> ?t. open t /\ s = frontier t`,
2145   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THENL
2146    [EXISTS_TAC `(:real^N) DIFF s` THEN
2147     ASM_SIMP_TAC[OPEN_DIFF; OPEN_UNIV; FRONTIER_COMPLEMENT] THEN
2148     ASM_SIMP_TAC[frontier; CLOSURE_CLOSED; DIFF_EMPTY];
2149     ASM_SIMP_TAC[FRONTIER_CLOSED; INTERIOR_FRONTIER_EMPTY]]);;
2150
2151 let FRONTIER_UNION = prove
2152  (`!s t:real^N->bool.
2153         closure s INTER closure t = {}
2154         ==> frontier(s UNION t) = frontier(s) UNION frontier(t)`,
2155   REPEAT STRIP_TAC THEN
2156   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[FRONTIER_UNION_SUBSET] THEN
2157   GEN_REWRITE_TAC RAND_CONV [frontier] THEN
2158   REWRITE_TAC[CLOSURE_UNION] THEN MATCH_MP_TAC(SET_RULE
2159    `(fs SUBSET cs /\ ft SUBSET ct) /\ k INTER fs = {} /\ k INTER ft = {}
2160     ==> (fs UNION ft) SUBSET (cs UNION ct) DIFF k`) THEN
2161   CONJ_TAC THENL [REWRITE_TAC[frontier] THEN SET_TAC[]; ALL_TAC] THEN
2162   CONJ_TAC THENL
2163    [ALL_TAC;
2164     ONCE_REWRITE_TAC[UNION_COMM] THEN
2165     RULE_ASSUM_TAC(ONCE_REWRITE_RULE[INTER_COMM])] THEN
2166   FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
2167    `s INTER t = {} ==> s' SUBSET s /\ s' INTER u INTER (UNIV DIFF t) = {}
2168       ==> u INTER s' = {}`)) THEN
2169   REWRITE_TAC[frontier; SUBSET_DIFF; GSYM INTERIOR_COMPLEMENT] THEN
2170   REWRITE_TAC[GSYM INTERIOR_INTER; SET_RULE
2171    `(s UNION t) INTER (UNIV DIFF t) = s DIFF t`] THEN
2172   MATCH_MP_TAC(SET_RULE
2173     `ti SUBSET si ==> (c DIFF si) INTER ti = {}`) THEN
2174   SIMP_TAC[SUBSET_INTERIOR; SUBSET_DIFF]);;
2175
2176 let CLOSURE_UNION_FRONTIER = prove
2177  (`!s:real^N->bool. closure s = s UNION frontier s`,
2178   GEN_TAC THEN REWRITE_TAC[frontier] THEN
2179   MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET) THEN
2180   MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN
2181   SET_TAC[]);;
2182
2183 let FRONTIER_INTERIOR_SUBSET = prove
2184  (`!s:real^N->bool. frontier(interior s) SUBSET frontier s`,
2185   GEN_TAC THEN REWRITE_TAC[frontier; INTERIOR_INTERIOR] THEN
2186   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> s DIFF u SUBSET t DIFF u`) THEN
2187   SIMP_TAC[SUBSET_CLOSURE; INTERIOR_SUBSET]);;
2188
2189 let FRONTIER_CLOSURE_SUBSET = prove
2190  (`!s:real^N->bool. frontier(closure s) SUBSET frontier s`,
2191   GEN_TAC THEN REWRITE_TAC[frontier; CLOSURE_CLOSURE] THEN
2192   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> u DIFF t SUBSET u DIFF s`) THEN
2193   SIMP_TAC[SUBSET_INTERIOR; CLOSURE_SUBSET]);;
2194
2195 let SET_DIFF_FRONTIER = prove
2196  (`!s:real^N->bool. s DIFF frontier s = interior s`,
2197   GEN_TAC THEN REWRITE_TAC[frontier] THEN
2198   MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET) THEN
2199   MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN
2200   SET_TAC[]);;
2201
2202 let FRONTIER_INTER_SUBSET_INTER = prove
2203  (`!s t:real^N->bool.
2204         frontier(s INTER t) SUBSET closure s INTER frontier t UNION
2205                                    frontier s INTER closure t`,
2206   REPEAT GEN_TAC THEN REWRITE_TAC[frontier; INTERIOR_INTER] THEN
2207   MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`]
2208         CLOSURE_INTER_SUBSET) THEN
2209   SET_TAC[]);;
2210
2211 (* ------------------------------------------------------------------------- *)
2212 (* A variant of nets (slightly non-standard but good for our purposes).      *)
2213 (* ------------------------------------------------------------------------- *)
2214
2215 let net_tybij = new_type_definition "net" ("mk_net","netord")
2216  (prove
2217    (`?g:A->A->bool. !x y. (!z. g z x ==> g z y) \/ (!z. g z y ==> g z x)`,
2218     EXISTS_TAC `\x:A y:A. F` THEN REWRITE_TAC[]));;
2219
2220 let NET = prove
2221  (`!n x y. (!z. netord n z x ==> netord n z y) \/
2222            (!z. netord n z y ==> netord n z x)`,
2223    REWRITE_TAC[net_tybij; ETA_AX]);;
2224
2225 let OLDNET = prove
2226  (`!n x y. netord n x x /\ netord n y y
2227            ==> ?z. netord n z z /\
2228                    !w. netord n w z ==> netord n w x /\ netord n w y`,
2229   MESON_TAC[NET]);;
2230
2231 let NET_DILEMMA = prove
2232  (`!net. (?a. (?x. netord net x a) /\ (!x. netord net x a ==> P x)) /\
2233          (?b. (?x. netord net x b) /\ (!x. netord net x b ==> Q x))
2234          ==> ?c. (?x. netord net x c) /\ (!x. netord net x c ==> P x /\ Q x)`,
2235   MESON_TAC[NET]);;
2236
2237 (* ------------------------------------------------------------------------- *)
2238 (* Common nets and the "within" modifier for nets.                           *)
2239 (* ------------------------------------------------------------------------- *)
2240
2241 parse_as_infix("within",(14,"right"));;
2242 parse_as_infix("in_direction",(14,"right"));;
2243
2244 let at = new_definition
2245   `at a = mk_net(\x y. &0 < dist(x,a) /\ dist(x,a) <= dist(y,a))`;;
2246
2247 let at_infinity = new_definition
2248   `at_infinity = mk_net(\x y. norm(x) >= norm(y))`;;
2249
2250 let at_posinfinity = new_definition
2251   `at_posinfinity = mk_net(\x y:real. x >= y)`;;
2252
2253 let at_neginfinity = new_definition
2254   `at_neginfinity = mk_net(\x y:real. x <= y)`;;
2255
2256 let sequentially = new_definition
2257   `sequentially = mk_net(\m:num n. m >= n)`;;
2258
2259 let within = new_definition
2260   `net within s = mk_net(\x y. netord net x y /\ x IN s)`;;
2261
2262 let in_direction = new_definition
2263   `a in_direction v = (at a) within {b | ?c. &0 <= c /\ (b - a = c % v)}`;;
2264
2265 (* ------------------------------------------------------------------------- *)
2266 (* Prove that they are all nets.                                             *)
2267 (* ------------------------------------------------------------------------- *)
2268
2269 let NET_PROVE_TAC[def] =
2270   REWRITE_TAC[GSYM FUN_EQ_THM; def] THEN
2271   REWRITE_TAC[ETA_AX] THEN
2272   ASM_SIMP_TAC[GSYM(CONJUNCT2 net_tybij)];;
2273
2274 let AT = prove
2275  (`!a:real^N x y.
2276         netord(at a) x y <=> &0 < dist(x,a) /\ dist(x,a) <= dist(y,a)`,
2277   GEN_TAC THEN NET_PROVE_TAC[at] THEN
2278   MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS; REAL_LET_TRANS]);;
2279
2280 let AT_INFINITY = prove
2281  (`!x y. netord at_infinity x y <=> norm(x) >= norm(y)`,
2282   NET_PROVE_TAC[at_infinity] THEN
2283   REWRITE_TAC[real_ge; REAL_LE_REFL] THEN
2284   MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS]);;
2285
2286 let AT_POSINFINITY = prove
2287  (`!x y. netord at_posinfinity x y <=> x >= y`,
2288   NET_PROVE_TAC[at_posinfinity] THEN
2289   REWRITE_TAC[real_ge; REAL_LE_REFL] THEN
2290   MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS]);;
2291
2292 let AT_NEGINFINITY = prove
2293  (`!x y. netord at_neginfinity x y <=> x <= y`,
2294   NET_PROVE_TAC[at_neginfinity] THEN
2295   REWRITE_TAC[real_ge; REAL_LE_REFL] THEN
2296   MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS]);;
2297
2298 let SEQUENTIALLY = prove
2299  (`!m n. netord sequentially m n <=> m >= n`,
2300   NET_PROVE_TAC[sequentially] THEN REWRITE_TAC[GE; LE_REFL] THEN
2301   MESON_TAC[LE_CASES; LE_REFL; LE_TRANS]);;
2302
2303 let WITHIN = prove
2304  (`!n s x y. netord(n within s) x y <=> netord n x y /\ x IN s`,
2305   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[within; GSYM FUN_EQ_THM] THEN
2306   REWRITE_TAC[GSYM(CONJUNCT2 net_tybij); ETA_AX] THEN
2307   MESON_TAC[NET]);;
2308
2309 let IN_DIRECTION = prove
2310  (`!a v x y. netord(a in_direction v) x y <=>
2311                 &0 < dist(x,a) /\ dist(x,a) <= dist(y,a) /\
2312                  ?c. &0 <= c /\ (x - a = c % v)`,
2313   REWRITE_TAC[WITHIN; AT; in_direction; IN_ELIM_THM; CONJ_ACI]);;
2314
2315 let WITHIN_UNIV = prove
2316  (`!x:real^N. at x within UNIV = at x`,
2317   REWRITE_TAC[within; at; IN_UNIV] THEN REWRITE_TAC[ETA_AX; net_tybij]);;
2318
2319 let WITHIN_WITHIN = prove
2320  (`!net s t. (net within s) within t = net within (s INTER t)`,
2321   ONCE_REWRITE_TAC[within] THEN
2322   REWRITE_TAC[WITHIN; IN_INTER; GSYM CONJ_ASSOC]);;
2323
2324 (* ------------------------------------------------------------------------- *)
2325 (* Identify trivial limits, where we can't approach arbitrarily closely.     *)
2326 (* ------------------------------------------------------------------------- *)
2327
2328 let trivial_limit = new_definition
2329   `trivial_limit net <=>
2330      (!a:A b. a = b) \/
2331      ?a:A b. ~(a = b) /\ !x. ~(netord(net) x a) /\ ~(netord(net) x b)`;;
2332
2333 let TRIVIAL_LIMIT_WITHIN = prove
2334  (`!a:real^N. trivial_limit (at a within s) <=> ~(a limit_point_of s)`,
2335   REWRITE_TAC[trivial_limit; LIMPT_APPROACHABLE_LE; WITHIN; AT; DIST_NZ] THEN
2336   REPEAT GEN_TAC THEN EQ_TAC THENL
2337    [DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL
2338      [MESON_TAC[REAL_LT_01; REAL_LT_REFL; VECTOR_CHOOSE_DIST;
2339                 DIST_REFL; REAL_LT_IMP_LE];
2340       DISCH_THEN(X_CHOOSE_THEN `b:real^N` (X_CHOOSE_THEN `c:real^N`
2341         STRIP_ASSUME_TAC)) THEN
2342       SUBGOAL_THEN `&0 < dist(a,b:real^N) \/ &0 < dist(a,c:real^N)` MP_TAC THEN
2343       ASM_MESON_TAC[DIST_TRIANGLE; DIST_SYM; GSYM DIST_NZ; GSYM DIST_EQ_0;
2344                     REAL_ARITH `x <= &0 + &0 ==> ~(&0 < x)`]];
2345     REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; LEFT_IMP_EXISTS_THM] THEN
2346     X_GEN_TAC `e:real` THEN DISCH_TAC THEN DISJ2_TAC THEN
2347     EXISTS_TAC `a:real^N` THEN
2348     SUBGOAL_THEN `?b:real^N. dist(a,b) = e` MP_TAC THENL
2349      [ASM_SIMP_TAC[VECTOR_CHOOSE_DIST; REAL_LT_IMP_LE]; ALL_TAC] THEN
2350     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN
2351     DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
2352     ASM_MESON_TAC[REAL_NOT_LE; DIST_REFL; DIST_NZ; DIST_SYM]]);;
2353
2354 let TRIVIAL_LIMIT_AT = prove
2355  (`!a. ~(trivial_limit (at a))`,
2356   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
2357   REWRITE_TAC[TRIVIAL_LIMIT_WITHIN; LIMPT_UNIV]);;
2358
2359 let TRIVIAL_LIMIT_AT_INFINITY = prove
2360  (`~(trivial_limit at_infinity)`,
2361   REWRITE_TAC[trivial_limit; AT_INFINITY; real_ge] THEN
2362   MESON_TAC[REAL_LE_REFL; VECTOR_CHOOSE_SIZE; REAL_LT_01; REAL_LT_LE]);;
2363
2364 let TRIVIAL_LIMIT_AT_POSINFINITY = prove
2365  (`~(trivial_limit at_posinfinity)`,
2366   REWRITE_TAC[trivial_limit; AT_POSINFINITY; DE_MORGAN_THM] THEN
2367   CONJ_TAC THENL
2368    [DISCH_THEN(MP_TAC o SPECL [`&0`; `&1`]) THEN REAL_ARITH_TAC; ALL_TAC] THEN
2369   REWRITE_TAC[DE_MORGAN_THM; NOT_EXISTS_THM; real_ge; REAL_NOT_LE] THEN
2370   MESON_TAC[REAL_LT_TOTAL; REAL_LT_ANTISYM]);;
2371
2372 let TRIVIAL_LIMIT_AT_NEGINFINITY = prove
2373  (`~(trivial_limit at_neginfinity)`,
2374   REWRITE_TAC[trivial_limit; AT_NEGINFINITY; DE_MORGAN_THM] THEN
2375   CONJ_TAC THENL
2376    [DISCH_THEN(MP_TAC o SPECL [`&0`; `&1`]) THEN REAL_ARITH_TAC; ALL_TAC] THEN
2377   REWRITE_TAC[DE_MORGAN_THM; NOT_EXISTS_THM; real_ge; REAL_NOT_LE] THEN
2378   MESON_TAC[REAL_LT_TOTAL; REAL_LT_ANTISYM]);;
2379
2380 let TRIVIAL_LIMIT_SEQUENTIALLY = prove
2381  (`~(trivial_limit sequentially)`,
2382   REWRITE_TAC[trivial_limit; SEQUENTIALLY] THEN
2383   MESON_TAC[GE_REFL; NOT_SUC]);;
2384
2385 let LIM_WITHIN_CLOSED_TRIVIAL = prove
2386  (`!a s. closed s /\ ~(a IN s) ==> trivial_limit (at a within s)`,
2387   REWRITE_TAC[TRIVIAL_LIMIT_WITHIN] THEN MESON_TAC[CLOSED_LIMPT]);;
2388
2389 let NONTRIVIAL_LIMIT_WITHIN = prove
2390  (`!net s. trivial_limit net ==> trivial_limit(net within s)`,
2391   REWRITE_TAC[trivial_limit; WITHIN] THEN MESON_TAC[]);;
2392
2393 (* ------------------------------------------------------------------------- *)
2394 (* Some property holds "sufficiently close" to the limit point.              *)
2395 (* ------------------------------------------------------------------------- *)
2396
2397 let eventually = new_definition
2398  `eventually p net <=>
2399         trivial_limit net \/
2400         ?y. (?x. netord net x y) /\ (!x. netord net x y ==> p x)`;;
2401
2402 let EVENTUALLY_HAPPENS = prove
2403  (`!net p. eventually p net ==> trivial_limit net \/ ?x. p x`,
2404   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2405
2406 let EVENTUALLY_WITHIN_LE = prove
2407  (`!s a:real^M p.
2408      eventually p (at a within s) <=>
2409         ?d. &0 < d /\ !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) <= d ==> p(x)`,
2410   REWRITE_TAC[eventually; AT; WITHIN; TRIVIAL_LIMIT_WITHIN] THEN
2411   REWRITE_TAC[LIMPT_APPROACHABLE_LE; DIST_NZ] THEN
2412   REPEAT GEN_TAC THEN EQ_TAC THENL [MESON_TAC[REAL_LTE_TRANS]; ALL_TAC] THEN
2413   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
2414   MATCH_MP_TAC(TAUT `(a ==> b) ==> ~a \/ b`) THEN DISCH_TAC THEN
2415   SUBGOAL_THEN `?b:real^M. dist(a,b) = d` MP_TAC THENL
2416    [ASM_SIMP_TAC[VECTOR_CHOOSE_DIST; REAL_LT_IMP_LE]; ALL_TAC] THEN
2417   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^M` THEN
2418   DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
2419   ASM_MESON_TAC[REAL_NOT_LE; DIST_REFL; DIST_NZ; DIST_SYM]);;
2420
2421 let EVENTUALLY_WITHIN = prove
2422  (`!s a:real^M p.
2423      eventually p (at a within s) <=>
2424         ?d. &0 < d /\ !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) < d ==> p(x)`,
2425   REWRITE_TAC[EVENTUALLY_WITHIN_LE] THEN
2426   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> c ==> a /\ b ==> d`] THEN
2427   REWRITE_TAC[APPROACHABLE_LT_LE]);;
2428
2429 let EVENTUALLY_AT = prove
2430  (`!a p. eventually p (at a) <=>
2431          ?d. &0 < d /\ !x. &0 < dist(x,a) /\ dist(x,a) < d ==> p(x)`,
2432   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
2433   REWRITE_TAC[EVENTUALLY_WITHIN; IN_UNIV]);;
2434
2435 let EVENTUALLY_SEQUENTIALLY = prove
2436  (`!p. eventually p sequentially <=> ?N. !n. N <= n ==> p n`,
2437   REWRITE_TAC[eventually; SEQUENTIALLY; GE; LE_REFL;
2438     TRIVIAL_LIMIT_SEQUENTIALLY] THEN  MESON_TAC[LE_REFL]);;
2439
2440 let EVENTUALLY_AT_INFINITY = prove
2441  (`!p. eventually p at_infinity <=> ?b. !x. norm(x) >= b ==> p x`,
2442   REWRITE_TAC[eventually; AT_INFINITY; TRIVIAL_LIMIT_AT_INFINITY] THEN
2443   REPEAT GEN_TAC THEN EQ_TAC THENL [MESON_TAC[REAL_LE_REFL]; ALL_TAC] THEN
2444   MESON_TAC[real_ge; REAL_LE_REFL; VECTOR_CHOOSE_SIZE;
2445     REAL_ARITH `&0 <= b \/ (!x. x >= &0 ==> x >= b)`]);;
2446
2447 let EVENTUALLY_AT_POSINFINITY = prove
2448  (`!p. eventually p at_posinfinity <=> ?b. !x. x >= b ==> p x`,
2449   REWRITE_TAC[eventually; TRIVIAL_LIMIT_AT_POSINFINITY; AT_POSINFINITY] THEN
2450   MESON_TAC[REAL_ARITH `x >= x`]);;
2451
2452 let EVENTUALLY_AT_NEGINFINITY = prove
2453  (`!p. eventually p at_neginfinity <=> ?b. !x. x <= b ==> p x`,
2454   REWRITE_TAC[eventually; TRIVIAL_LIMIT_AT_NEGINFINITY; AT_NEGINFINITY] THEN
2455   MESON_TAC[REAL_LE_REFL]);;
2456
2457 let EVENTUALLY_AT_INFINITY_POS = prove
2458  (`!p:real^N->bool.
2459         eventually p at_infinity <=> ?b. &0 < b /\ !x. norm x >= b ==> p x`,
2460   GEN_TAC THEN REWRITE_TAC[EVENTUALLY_AT_INFINITY; real_ge] THEN
2461   MESON_TAC[REAL_ARITH `&0 < abs b + &1 /\ (abs b + &1 <= x ==> b <= x)`]);;
2462
2463 let ALWAYS_EVENTUALLY = prove
2464  (`(!x. p x) ==> eventually p net`,
2465   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[eventually; trivial_limit] THEN
2466   MESON_TAC[]);;
2467
2468 (* ------------------------------------------------------------------------- *)
2469 (* Combining theorems for "eventually".                                      *)
2470 (* ------------------------------------------------------------------------- *)
2471
2472 let EVENTUALLY_AND = prove
2473  (`!net:(A net) p q.
2474         eventually (\x. p x /\ q x) net <=>
2475         eventually p net /\ eventually q net`,
2476   REPEAT GEN_TAC THEN REWRITE_TAC[eventually] THEN
2477   ASM_CASES_TAC `trivial_limit(net:(A net))` THEN ASM_REWRITE_TAC[] THEN
2478   EQ_TAC THEN SIMP_TAC[NET_DILEMMA] THEN MESON_TAC[]);;
2479
2480 let EVENTUALLY_MONO = prove
2481  (`!net:(A net) p q.
2482         (!x. p x ==> q x) /\ eventually p net
2483         ==> eventually q net`,
2484   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2485
2486 let EVENTUALLY_MP = prove
2487  (`!net:(A net) p q.
2488         eventually (\x. p x ==> q x) net /\ eventually p net
2489         ==> eventually q net`,
2490   REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
2491   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2492
2493 let EVENTUALLY_FALSE = prove
2494  (`!net. eventually (\x. F) net <=> trivial_limit net`,
2495   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2496
2497 let EVENTUALLY_TRUE = prove
2498  (`!net. eventually (\x. T) net <=> T`,
2499   REWRITE_TAC[eventually; trivial_limit] THEN MESON_TAC[]);;
2500
2501 let NOT_EVENTUALLY = prove
2502  (`!net p. (!x. ~(p x)) /\ ~(trivial_limit net) ==> ~(eventually p net)`,
2503   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2504
2505 let EVENTUALLY_FORALL = prove
2506  (`!net:(A net) p s:B->bool.
2507         FINITE s /\ ~(s = {})
2508         ==> (eventually (\x. !a. a IN s ==> p a x) net <=>
2509              !a. a IN s ==> eventually (p a) net)`,
2510   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
2511   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
2512   REWRITE_TAC[FORALL_IN_INSERT; EVENTUALLY_AND; ETA_AX] THEN
2513   MAP_EVERY X_GEN_TAC [`b:B`; `t:B->bool`] THEN
2514   ASM_CASES_TAC `t:B->bool = {}` THEN
2515   ASM_SIMP_TAC[NOT_IN_EMPTY; EVENTUALLY_TRUE]);;
2516
2517 let FORALL_EVENTUALLY = prove
2518  (`!net:(A net) p s:B->bool.
2519         FINITE s /\ ~(s = {})
2520         ==> ((!a. a IN s ==> eventually (p a) net) <=>
2521              eventually (\x. !a. a IN s ==> p a x) net)`,
2522   SIMP_TAC[EVENTUALLY_FORALL]);;
2523
2524 (* ------------------------------------------------------------------------- *)
2525 (* Limits, defined as vacuously true when the limit is trivial.              *)
2526 (* ------------------------------------------------------------------------- *)
2527
2528 parse_as_infix("-->",(12,"right"));;
2529
2530 let tendsto = new_definition
2531   `(f --> l) net <=> !e. &0 < e ==> eventually (\x. dist(f(x),l) < e) net`;;
2532
2533 let lim = new_definition
2534  `lim net f = @l. (f --> l) net`;;
2535
2536 let LIM = prove
2537  (`(f --> l) net <=>
2538         trivial_limit net \/
2539         !e. &0 < e ==> ?y. (?x. netord(net) x y) /\
2540                            !x. netord(net) x y ==> dist(f(x),l) < e`,
2541   REWRITE_TAC[tendsto; eventually] THEN MESON_TAC[]);;
2542
2543 (* ------------------------------------------------------------------------- *)
2544 (* Show that they yield usual definitions in the various cases.              *)
2545 (* ------------------------------------------------------------------------- *)
2546
2547 let LIM_WITHIN_LE = prove
2548  (`!f:real^M->real^N l a s.
2549         (f --> l)(at a within s) <=>
2550            !e. &0 < e ==> ?d. &0 < d /\
2551                               !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) <= d
2552                                    ==> dist(f(x),l) < e`,
2553   REWRITE_TAC[tendsto; EVENTUALLY_WITHIN_LE]);;
2554
2555 let LIM_WITHIN = prove
2556  (`!f:real^M->real^N l a s.
2557       (f --> l) (at a within s) <=>
2558         !e. &0 < e
2559             ==> ?d. &0 < d /\
2560                     !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) < d
2561                     ==> dist(f(x),l) < e`,
2562   REWRITE_TAC[tendsto; EVENTUALLY_WITHIN] THEN MESON_TAC[]);;
2563
2564 let LIM_AT_LE = prove
2565  (`!f l a. (f --> l) (at a) <=>
2566            !e. &0 < e
2567                ==> ?d. &0 < d /\
2568                        !x. &0 < dist(x,a) /\ dist(x,a) <= d
2569                            ==> dist (f x,l) < e`,
2570   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
2571   REWRITE_TAC[LIM_WITHIN_LE; IN_UNIV]);;
2572
2573 let LIM_AT = prove
2574  (`!f l:real^N a:real^M.
2575       (f --> l) (at a) <=>
2576               !e. &0 < e
2577                   ==> ?d. &0 < d /\ !x. &0 < dist(x,a) /\ dist(x,a) < d
2578                           ==> dist(f(x),l) < e`,
2579   REWRITE_TAC[tendsto; EVENTUALLY_AT] THEN MESON_TAC[]);;
2580
2581 let LIM_AT_INFINITY = prove
2582  (`!f l. (f --> l) at_infinity <=>
2583                !e. &0 < e ==> ?b. !x. norm(x) >= b ==> dist(f(x),l) < e`,
2584   REWRITE_TAC[tendsto; EVENTUALLY_AT_INFINITY] THEN MESON_TAC[]);;
2585
2586 let LIM_AT_INFINITY_POS = prove
2587  (`!f l. (f --> l) at_infinity <=>
2588          !e. &0 < e ==> ?b. &0 < b /\ !x. norm x >= b ==> dist(f x,l) < e`,
2589   REPEAT GEN_TAC THEN REWRITE_TAC[LIM_AT_INFINITY] THEN
2590   MESON_TAC[REAL_ARITH `&0 < abs b + &1 /\ (x >= abs b + &1 ==> x >= b)`]);;
2591
2592 let LIM_AT_POSINFINITY = prove
2593  (`!f l. (f --> l) at_posinfinity <=>
2594                !e. &0 < e ==> ?b. !x. x >= b ==> dist(f(x),l) < e`,
2595   REWRITE_TAC[tendsto; EVENTUALLY_AT_POSINFINITY] THEN MESON_TAC[]);;
2596
2597 let LIM_AT_NEGINFINITY = prove
2598  (`!f l. (f --> l) at_neginfinity <=>
2599                !e. &0 < e ==> ?b. !x. x <= b ==> dist(f(x),l) < e`,
2600   REWRITE_TAC[tendsto; EVENTUALLY_AT_NEGINFINITY] THEN MESON_TAC[]);;
2601
2602 let LIM_SEQUENTIALLY = prove
2603  (`!s l. (s --> l) sequentially <=>
2604           !e. &0 < e ==> ?N. !n. N <= n ==> dist(s(n),l) < e`,
2605   REWRITE_TAC[tendsto; EVENTUALLY_SEQUENTIALLY] THEN MESON_TAC[]);;
2606
2607 let LIM_EVENTUALLY = prove
2608  (`!net f l. eventually (\x. f x = l) net ==> (f --> l) net`,
2609   REWRITE_TAC[eventually; LIM] THEN MESON_TAC[DIST_REFL]);;
2610
2611 let LIM_POSINFINITY_SEQUENTIALLY = prove
2612  (`!f l. (f --> l) at_posinfinity ==> ((\n. f(&n)) --> l) sequentially`,
2613   REPEAT GEN_TAC THEN
2614   REWRITE_TAC[LIM_AT_POSINFINITY; LIM_SEQUENTIALLY] THEN
2615   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2616   FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
2617   DISCH_THEN(X_CHOOSE_TAC `B:real`) THEN
2618   MP_TAC(ISPEC `B:real` REAL_ARCH_SIMPLE) THEN
2619   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
2620   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
2621   RULE_ASSUM_TAC(REWRITE_RULE[GSYM REAL_OF_NUM_LE]) THEN ASM_REAL_ARITH_TAC);;
2622
2623 let LIM_INFINITY_POSINFINITY_LIFT = prove
2624  (`!f l:real^N. (f --> l) at_infinity ==> ((f o lift) --> l) at_posinfinity`,
2625   REWRITE_TAC[LIM_AT_INFINITY; LIM_AT_POSINFINITY; o_THM] THEN
2626   REWRITE_TAC[FORALL_DROP; NORM_REAL; GSYM drop; LIFT_DROP] THEN
2627   MESON_TAC[REAL_ARITH `x >= b ==> abs(x) >= b`]);;
2628
2629 (* ------------------------------------------------------------------------- *)
2630 (* The expected monotonicity property.                                       *)
2631 (* ------------------------------------------------------------------------- *)
2632
2633 let LIM_WITHIN_EMPTY = prove
2634  (`!f l x. (f --> l) (at x within {})`,
2635   REWRITE_TAC[LIM_WITHIN; NOT_IN_EMPTY] THEN MESON_TAC[REAL_LT_01]);;
2636
2637 let LIM_WITHIN_SUBSET = prove
2638  (`!f l a s.
2639     (f --> l) (at a within s) /\ t SUBSET s ==> (f --> l) (at a within t)`,
2640   REWRITE_TAC[LIM_WITHIN; SUBSET] THEN MESON_TAC[]);;
2641
2642 let LIM_UNION = prove
2643  (`!f x l s t.
2644         (f --> l) (at x within s) /\ (f --> l) (at x within t)
2645         ==> (f --> l) (at x within (s UNION t))`,
2646   REPEAT GEN_TAC THEN REWRITE_TAC[LIM_WITHIN; IN_UNION] THEN
2647   REWRITE_TAC[AND_FORALL_THM] THEN MATCH_MP_TAC MONO_FORALL THEN
2648   X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_SIMP_TAC[] THEN
2649   DISCH_THEN(CONJUNCTS_THEN2
2650    (X_CHOOSE_TAC `d1:real`) (X_CHOOSE_TAC `d2:real`)) THEN
2651   EXISTS_TAC `min d1 d2` THEN ASM_MESON_TAC[REAL_LT_MIN]);;
2652
2653 let LIM_UNION_UNIV = prove
2654  (`!f x l s t.
2655         (f --> l) (at x within s) /\ (f --> l) (at x within t) /\
2656         s UNION t = (:real^N)
2657         ==> (f --> l) (at x)`,
2658   MESON_TAC[LIM_UNION; WITHIN_UNIV]);;
2659
2660 (* ------------------------------------------------------------------------- *)
2661 (* Composition of limits.                                                    *)
2662 (* ------------------------------------------------------------------------- *)
2663
2664 let LIM_COMPOSE_WITHIN = prove
2665  (`!net f:A->real^N g:real^N->real^P s y z.
2666     (f --> y) net /\
2667     eventually (\w. f w IN s /\ (f w = y ==> g y = z)) net /\
2668     (g --> z) (at y within s)
2669     ==> ((g o f) --> z) net`,
2670   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto; CONJ_ASSOC] THEN
2671   ONCE_REWRITE_TAC[LEFT_AND_FORALL_THM] THEN
2672   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2673   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
2674   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
2675   REWRITE_TAC[EVENTUALLY_WITHIN; GSYM DIST_NZ; o_DEF] THEN
2676   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
2677   FIRST_X_ASSUM(MP_TAC o SPEC `d:real`) THEN
2678   ASM_REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
2679   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2680   ASM_MESON_TAC[DIST_REFL]);;
2681
2682 let LIM_COMPOSE_AT = prove
2683  (`!net f:A->real^N g:real^N->real^P y z.
2684     (f --> y) net /\
2685     eventually (\w. f w = y ==> g y = z) net /\
2686     (g --> z) (at y)
2687     ==> ((g o f) --> z) net`,
2688   REPEAT STRIP_TAC THEN
2689   MP_TAC(ISPECL [`net:(A)net`; `f:A->real^N`; `g:real^N->real^P`;
2690                  `(:real^N)`; `y:real^N`; `z:real^P`]
2691         LIM_COMPOSE_WITHIN) THEN
2692   ASM_REWRITE_TAC[IN_UNIV; WITHIN_UNIV]);;
2693
2694 (* ------------------------------------------------------------------------- *)
2695 (* Interrelations between restricted and unrestricted limits.                *)
2696 (* ------------------------------------------------------------------------- *)
2697
2698 let LIM_AT_WITHIN = prove
2699  (`!f l a s. (f --> l)(at a) ==> (f --> l)(at a within s)`,
2700   REWRITE_TAC[LIM_AT; LIM_WITHIN] THEN MESON_TAC[]);;
2701
2702 let LIM_WITHIN_OPEN = prove
2703  (`!f l a:real^M s.
2704      a IN s /\ open s ==> ((f --> l)(at a within s) <=> (f --> l)(at a))`,
2705   REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[LIM_AT_WITHIN] THEN
2706   REWRITE_TAC[LIM_AT; LIM_WITHIN] THEN
2707   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
2708   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
2709    DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN
2710   FIRST_X_ASSUM(MP_TAC o SPEC `a:real^M` o GEN_REWRITE_RULE I [open_def]) THEN
2711   ASM_REWRITE_TAC[] THEN
2712   DISCH_THEN(X_CHOOSE_THEN `d2:real` STRIP_ASSUME_TAC) THEN
2713   MP_TAC(SPECL [`d1:real`; `d2:real`] REAL_DOWN2) THEN ASM_REWRITE_TAC[] THEN
2714   ASM_MESON_TAC[REAL_LT_TRANS]);;
2715
2716 (* ------------------------------------------------------------------------- *)
2717 (* More limit point characterizations.                                       *)
2718 (* ------------------------------------------------------------------------- *)
2719
2720 let LIMPT_SEQUENTIAL_INJ = prove
2721  (`!x:real^N s.
2722       x limit_point_of s <=>
2723              ?f. (!n. f(n) IN (s DELETE x)) /\
2724                  (!m n. f m = f n <=> m = n) /\
2725                  (f --> x) sequentially`,
2726   REPEAT GEN_TAC THEN
2727   REWRITE_TAC[LIMPT_APPROACHABLE; LIM_SEQUENTIALLY; IN_DELETE] THEN
2728   EQ_TAC THENL [ALL_TAC; MESON_TAC[GE; LE_REFL]] THEN
2729   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
2730   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
2731   X_GEN_TAC `y:real->real^N` THEN DISCH_TAC THEN
2732   (STRIP_ASSUME_TAC o  prove_recursive_functions_exist num_RECURSION)
2733    `(z 0 = y (&1)) /\
2734     (!n. z (SUC n):real^N = y(min (inv(&2 pow (SUC n))) (dist(z n,x))))` THEN
2735   EXISTS_TAC `z:num->real^N` THEN
2736   SUBGOAL_THEN
2737    `!n. z(n) IN s /\ ~(z n:real^N = x) /\ dist(z n,x) < inv(&2 pow n)`
2738   ASSUME_TAC THENL
2739    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
2740     ASM_SIMP_TAC[REAL_LT_01] THEN FIRST_X_ASSUM(MP_TAC o SPEC
2741      `min (inv(&2 pow (SUC n))) (dist(z n:real^N,x))`) THEN
2742     ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_INV_EQ; REAL_LT_POW2; DIST_POS_LT];
2743     ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
2744      [MATCH_MP_TAC WLOG_LT THEN REWRITE_TAC[EQ_SYM_EQ] THEN
2745       SUBGOAL_THEN `!m n:num. m < n ==> dist(z n:real^N,x) < dist(z m,x)`
2746        (fun th -> MESON_TAC[th; REAL_LT_REFL; LT_REFL]) THEN
2747       MATCH_MP_TAC TRANSITIVE_STEPWISE_LT THEN
2748       CONJ_TAC THENL [REAL_ARITH_TAC; GEN_TAC THEN ASM_REWRITE_TAC[]] THEN
2749       FIRST_X_ASSUM(MP_TAC o SPEC
2750        `min (inv(&2 pow (SUC n))) (dist(z n:real^N,x))`) THEN
2751       ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_INV_EQ; REAL_LT_POW2; DIST_POS_LT];
2752       X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2753       MP_TAC(ISPECL [`inv(&2)`; `e:real`] REAL_ARCH_POW_INV) THEN
2754       ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
2755       X_GEN_TAC `N:num` THEN REWRITE_TAC[REAL_POW_INV] THEN DISCH_TAC THEN
2756       X_GEN_TAC `n:num` THEN DISCH_TAC THEN
2757       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
2758         REAL_LT_TRANS)) THEN
2759       MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `inv(&2 pow n)` THEN
2760       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
2761       ASM_REWRITE_TAC[REAL_LT_POW2] THEN MATCH_MP_TAC REAL_POW_MONO THEN
2762       REWRITE_TAC[REAL_OF_NUM_LE] THEN ASM_ARITH_TAC]]);;
2763
2764 let LIMPT_SEQUENTIAL = prove
2765  (`!x:real^N s.
2766       x limit_point_of s <=>
2767              ?f. (!n. f(n) IN (s DELETE x)) /\ (f --> x) sequentially`,
2768   REPEAT GEN_TAC THEN EQ_TAC THENL
2769    [REWRITE_TAC[LIMPT_SEQUENTIAL_INJ] THEN MESON_TAC[];
2770     REWRITE_TAC[LIMPT_APPROACHABLE; LIM_SEQUENTIALLY; IN_DELETE] THEN
2771     MESON_TAC[GE; LE_REFL]]);;
2772
2773 let [LIMPT_INFINITE_OPEN; LIMPT_INFINITE_BALL; LIMPT_INFINITE_CBALL] =
2774     (CONJUNCTS o prove)
2775  (`(!s x:real^N.
2776         x limit_point_of s <=> !t. x IN t /\ open t ==> INFINITE(s INTER t)) /\
2777    (!s x:real^N.
2778         x limit_point_of s <=> !e. &0 < e ==> INFINITE(s INTER ball(x,e))) /\
2779    (!s x:real^N.
2780         x limit_point_of s <=> !e. &0 < e ==> INFINITE(s INTER cball(x,e)))`,
2781   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
2782    `(q ==> p) /\ (r ==> s) /\ (s ==> q) /\ (p ==> r)
2783     ==> (p <=> q) /\ (p <=> r) /\ (p <=> s)`) THEN
2784   REPEAT CONJ_TAC THENL
2785    [REWRITE_TAC[limit_point_of; INFINITE; SET_RULE
2786      `(?y. ~(y = x) /\ y IN s /\ y IN t) <=> ~(s INTER t SUBSET {x})`] THEN
2787     MESON_TAC[FINITE_SUBSET; FINITE_SING];
2788     MESON_TAC[INFINITE_SUPERSET; BALL_SUBSET_CBALL;
2789               SET_RULE `t SUBSET u ==> s INTER t SUBSET s INTER u`];
2790     MESON_TAC[INFINITE_SUPERSET; OPEN_CONTAINS_CBALL;
2791               SET_RULE `t SUBSET u ==> s INTER t SUBSET s INTER u`];
2792     REWRITE_TAC[LIMPT_SEQUENTIAL_INJ; IN_DELETE; FORALL_AND_THM] THEN
2793     DISCH_THEN(X_CHOOSE_THEN `f:num->real^N` STRIP_ASSUME_TAC) THEN
2794     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2795     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
2796     DISCH_THEN(MP_TAC o SPEC `e:real`) THEN
2797     ASM_REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[DIST_SYM] IN_BALL)] THEN
2798     DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN
2799     MATCH_MP_TAC INFINITE_SUPERSET THEN
2800     EXISTS_TAC `IMAGE (f:num->real^N) (from N)` THEN
2801     ASM_SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_FROM; IN_INTER] THEN
2802     ASM_MESON_TAC[INFINITE_IMAGE_INJ; INFINITE_FROM]]);;
2803
2804 let INFINITE_OPEN_IN = prove
2805  (`!u s:real^N->bool.
2806       open_in (subtopology euclidean u) s /\ (?x. x IN s /\ x limit_point_of u)
2807       ==> INFINITE s`,
2808   REPEAT STRIP_TAC THEN
2809   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
2810   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
2811   FIRST_X_ASSUM(MP_TAC o SPEC `t:real^N->bool` o
2812         GEN_REWRITE_RULE I [LIMPT_INFINITE_OPEN]) THEN
2813   FIRST_X_ASSUM SUBST_ALL_TAC THEN ASM SET_TAC[]);;
2814
2815 (* ------------------------------------------------------------------------- *)
2816 (* Condensation points.                                                      *)
2817 (* ------------------------------------------------------------------------- *)
2818
2819 parse_as_infix ("condensation_point_of",(12,"right"));;
2820
2821 let condensation_point_of = new_definition
2822  `x condensation_point_of s <=>
2823         !t. x IN t /\ open t ==> ~COUNTABLE(s INTER t)`;;
2824
2825 let CONDENSATION_POINT_OF_SUBSET = prove
2826  (`!x:real^N s t.
2827         x condensation_point_of s /\ s SUBSET t ==> x condensation_point_of t`,
2828   REPEAT GEN_TAC THEN
2829   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
2830   REWRITE_TAC[condensation_point_of] THEN
2831   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
2832   REWRITE_TAC[CONTRAPOS_THM] THEN
2833   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] COUNTABLE_SUBSET) THEN
2834   ASM SET_TAC[]);;
2835
2836 let CONDENSATION_POINT_IMP_LIMPT = prove
2837  (`!x s. x condensation_point_of s ==> x limit_point_of s`,
2838   REWRITE_TAC[condensation_point_of; LIMPT_INFINITE_OPEN; INFINITE] THEN
2839   MESON_TAC[FINITE_IMP_COUNTABLE]);;
2840
2841 let CONDENSATION_POINT_INFINITE_BALL,CONDENSATION_POINT_INFINITE_CBALL =
2842   (CONJ_PAIR o prove)
2843  (`(!s x:real^N.
2844         x condensation_point_of s <=>
2845         !e. &0 < e ==> ~COUNTABLE(s INTER ball(x,e))) /\
2846    (!s x:real^N.
2847         x condensation_point_of s <=>
2848         !e. &0 < e ==> ~COUNTABLE(s INTER cball(x,e)))`,
2849   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
2850    `(p ==> q) /\ (q ==> r) /\ (r ==> p)
2851     ==> (p <=> q) /\ (p <=> r)`) THEN
2852   REWRITE_TAC[condensation_point_of] THEN REPEAT CONJ_TAC THENL
2853    [MESON_TAC[OPEN_BALL; CENTRE_IN_BALL];
2854     MESON_TAC[BALL_SUBSET_CBALL; COUNTABLE_SUBSET;
2855               SET_RULE `t SUBSET u ==> s INTER t SUBSET s INTER u`];
2856     MESON_TAC[COUNTABLE_SUBSET; OPEN_CONTAINS_CBALL;
2857               SET_RULE `t SUBSET u ==> s INTER t SUBSET s INTER u`]]);;
2858
2859 (* ------------------------------------------------------------------------- *)
2860 (* Basic arithmetical combining theorems for limits.                         *)
2861 (* ------------------------------------------------------------------------- *)
2862
2863 let LIM_LINEAR = prove
2864  (`!net:(A)net h f l.
2865         (f --> l) net /\ linear h ==> ((\x. h(f x)) --> h l) net`,
2866   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
2867   ASM_CASES_TAC `trivial_limit (net:(A)net)` THEN ASM_REWRITE_TAC[] THEN
2868   STRIP_TAC THEN FIRST_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o
2869     MATCH_MP LINEAR_BOUNDED_POS) THEN
2870   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2871   FIRST_X_ASSUM(MP_TAC o SPEC `e / B`) THEN
2872   ASM_SIMP_TAC[REAL_LT_DIV; dist; GSYM LINEAR_SUB; REAL_LT_RDIV_EQ] THEN
2873   ASM_MESON_TAC[REAL_LET_TRANS; REAL_MUL_SYM]);;
2874
2875 let LIM_CONST = prove
2876  (`!net a:real^N. ((\x. a) --> a) net`,
2877   SIMP_TAC[LIM; DIST_REFL; trivial_limit] THEN MESON_TAC[]);;
2878
2879 let LIM_CMUL = prove
2880  (`!f l c. (f --> l) net ==> ((\x. c % f x) --> c % l) net`,
2881   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_LINEAR THEN
2882   ASM_REWRITE_TAC[REWRITE_RULE[ETA_AX]
2883     (MATCH_MP LINEAR_COMPOSE_CMUL LINEAR_ID)]);;
2884
2885 let LIM_CMUL_EQ = prove
2886  (`!net f l c.
2887         ~(c = &0) ==> (((\x. c % f x) --> c % l) net <=> (f --> l) net)`,
2888   REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[LIM_CMUL] THEN
2889   DISCH_THEN(MP_TAC o SPEC `inv c:real` o MATCH_MP LIM_CMUL) THEN
2890   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID; ETA_AX]);;
2891
2892 let LIM_NEG = prove
2893  (`!net f l:real^N. (f --> l) net ==> ((\x. --(f x)) --> --l) net`,
2894   REPEAT GEN_TAC THEN REWRITE_TAC[LIM; dist] THEN
2895   REWRITE_TAC[VECTOR_ARITH `--x - --y = --(x - y:real^N)`; NORM_NEG]);;
2896
2897 let LIM_NEG_EQ = prove
2898  (`!net f l:real^N. ((\x. --(f x)) --> --l) net <=> (f --> l) net`,
2899   REPEAT GEN_TAC THEN EQ_TAC THEN
2900   DISCH_THEN(MP_TAC o MATCH_MP LIM_NEG) THEN
2901   REWRITE_TAC[VECTOR_NEG_NEG; ETA_AX]);;
2902
2903 let LIM_ADD = prove
2904  (`!net:(A)net f g l m.
2905     (f --> l) net /\ (g --> m) net ==> ((\x. f(x) + g(x)) --> l + m) net`,
2906   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
2907   ASM_CASES_TAC `trivial_limit (net:(A)net)` THEN
2908   ASM_REWRITE_TAC[AND_FORALL_THM] THEN
2909   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2910   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
2911   DISCH_THEN(MP_TAC o MATCH_MP NET_DILEMMA) THEN MATCH_MP_TAC MONO_EXISTS THEN
2912   MESON_TAC[REAL_HALF; DIST_TRIANGLE_ADD; REAL_LT_ADD2; REAL_LET_TRANS]);;
2913
2914 let LIM_ABS = prove
2915  (`!net:(A)net f:A->real^N l.
2916      (f --> l) net
2917      ==> ((\x. lambda i. (abs(f(x)$i))) --> (lambda i. abs(l$i)):real^N) net`,
2918   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
2919   ASM_CASES_TAC `trivial_limit (net:(A)net)` THEN ASM_REWRITE_TAC[] THEN
2920   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
2921   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
2922   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
2923   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
2924   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
2925   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
2926   MATCH_MP_TAC(NORM_ARITH
2927    `norm(x - y) <= norm(a - b) ==> dist(a,b) < e ==> dist(x,y) < e`) THEN
2928   MATCH_MP_TAC NORM_LE_COMPONENTWISE THEN
2929   SIMP_TAC[LAMBDA_BETA; VECTOR_SUB_COMPONENT] THEN
2930   REAL_ARITH_TAC);;
2931
2932 let LIM_SUB = prove
2933  (`!net:(A)net f g l m.
2934     (f --> l) net /\ (g --> m) net ==> ((\x. f(x) - g(x)) --> l - m) net`,
2935   REWRITE_TAC[real_sub; VECTOR_SUB] THEN ASM_SIMP_TAC[LIM_ADD; LIM_NEG]);;
2936
2937 let LIM_MAX = prove
2938  (`!net:(A)net f g l:real^N m:real^N.
2939     (f --> l) net /\ (g --> m) net
2940     ==> ((\x. lambda i. max (f(x)$i) (g(x)$i))
2941          --> (lambda i. max (l$i) (m$i)):real^N) net`,
2942   REPEAT GEN_TAC THEN DISCH_TAC THEN
2943   FIRST_ASSUM(MP_TAC o MATCH_MP LIM_ADD) THEN
2944   FIRST_ASSUM(MP_TAC o MATCH_MP LIM_SUB) THEN
2945   DISCH_THEN(MP_TAC o MATCH_MP LIM_ABS) THEN
2946   REWRITE_TAC[IMP_IMP] THEN
2947   DISCH_THEN(MP_TAC o MATCH_MP LIM_ADD) THEN
2948   DISCH_THEN(MP_TAC o SPEC `inv(&2)` o MATCH_MP LIM_CMUL) THEN
2949   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN BINOP_TAC THEN
2950   SIMP_TAC[FUN_EQ_THM; CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
2951            VECTOR_SUB_COMPONENT; LAMBDA_BETA] THEN
2952   REAL_ARITH_TAC);;
2953
2954 let LIM_MIN = prove
2955  (`!net:(A)net f g l:real^N m:real^N.
2956     (f --> l) net /\ (g --> m) net
2957     ==> ((\x. lambda i. min (f(x)$i) (g(x)$i))
2958          --> (lambda i. min (l$i) (m$i)):real^N) net`,
2959   REPEAT GEN_TAC THEN
2960   DISCH_THEN(CONJUNCTS_THEN(MP_TAC o MATCH_MP LIM_NEG)) THEN
2961   REWRITE_TAC[IMP_IMP] THEN
2962   DISCH_THEN(MP_TAC o MATCH_MP LIM_NEG o MATCH_MP LIM_MAX) THEN
2963   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN BINOP_TAC THEN
2964   SIMP_TAC[FUN_EQ_THM; CART_EQ; LAMBDA_BETA; VECTOR_NEG_COMPONENT] THEN
2965   REAL_ARITH_TAC);;
2966
2967 let LIM_NORM = prove
2968  (`!net f:A->real^N l.
2969         (f --> l) net ==> ((\x. lift(norm(f x))) --> lift(norm l)) net`,
2970   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto; DIST_LIFT] THEN
2971   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
2972   REWRITE_TAC[] THEN
2973   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2974   REWRITE_TAC[] THEN NORM_ARITH_TAC);;
2975
2976 let LIM_NULL = prove
2977  (`!net f l. (f --> l) net <=> ((\x. f(x) - l) --> vec 0) net`,
2978   REWRITE_TAC[LIM; dist; VECTOR_SUB_RZERO]);;
2979
2980 let LIM_NULL_NORM = prove
2981  (`!net f. (f --> vec 0) net <=> ((\x. lift(norm(f x))) --> vec 0) net`,
2982   REWRITE_TAC[LIM; dist; VECTOR_SUB_RZERO; REAL_ABS_NORM; NORM_LIFT]);;
2983
2984 let LIM_NULL_CMUL_EQ = prove
2985  (`!net f c.
2986         ~(c = &0) ==> (((\x. c % f x) --> vec 0) net <=> (f --> vec 0) net)`,
2987   MESON_TAC[LIM_CMUL_EQ; VECTOR_MUL_RZERO]);;
2988
2989 let LIM_NULL_CMUL = prove
2990  (`!net f c. (f --> vec 0) net ==> ((\x. c % f x) --> vec 0) net`,
2991   REPEAT GEN_TAC THEN ASM_CASES_TAC `c = &0` THEN
2992   ASM_SIMP_TAC[LIM_NULL_CMUL_EQ; VECTOR_MUL_LZERO; LIM_CONST]);;
2993
2994 let LIM_NULL_ADD = prove
2995  (`!net f g:A->real^N.
2996         (f --> vec 0) net /\ (g --> vec 0) net
2997         ==> ((\x. f x + g x) --> vec 0) net`,
2998   REPEAT GEN_TAC THEN
2999   DISCH_THEN(MP_TAC o MATCH_MP LIM_ADD) THEN
3000   REWRITE_TAC[VECTOR_ADD_LID]);;
3001
3002 let LIM_NULL_SUB = prove
3003  (`!net f g:A->real^N.
3004         (f --> vec 0) net /\ (g --> vec 0) net
3005         ==> ((\x. f x - g x) --> vec 0) net`,
3006   REPEAT GEN_TAC THEN
3007   DISCH_THEN(MP_TAC o MATCH_MP LIM_SUB) THEN
3008   REWRITE_TAC[VECTOR_SUB_RZERO]);;
3009
3010 let LIM_NULL_COMPARISON = prove
3011  (`!net f g. eventually (\x. norm(f x) <= g x) net /\
3012              ((\x. lift(g x)) --> vec 0) net
3013              ==> (f --> vec 0) net`,
3014   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto; RIGHT_AND_FORALL_THM] THEN
3015   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
3016   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
3017   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
3018   REWRITE_TAC[dist; VECTOR_SUB_RZERO; NORM_LIFT] THEN REAL_ARITH_TAC);;
3019
3020 let LIM_COMPONENT = prove
3021  (`!net f i l:real^N. (f --> l) net /\ 1 <= i /\ i <= dimindex(:N)
3022                       ==> ((\a. lift(f(a)$i)) --> lift(l$i)) net`,
3023   REWRITE_TAC[LIM; dist; GSYM LIFT_SUB; NORM_LIFT] THEN
3024   SIMP_TAC[GSYM VECTOR_SUB_COMPONENT] THEN
3025   MESON_TAC[COMPONENT_LE_NORM; REAL_LET_TRANS]);;
3026
3027 let LIM_TRANSFORM_BOUND = prove
3028  (`!f g. eventually (\n. norm(f n) <= norm(g n)) net /\ (g --> vec 0) net
3029          ==> (f --> vec 0) net`,
3030   REPEAT GEN_TAC THEN
3031   REWRITE_TAC[tendsto; RIGHT_AND_FORALL_THM] THEN
3032   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
3033   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
3034   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
3035   REWRITE_TAC[dist; VECTOR_SUB_RZERO] THEN REAL_ARITH_TAC);;
3036
3037 let LIM_NULL_CMUL_BOUNDED = prove
3038  (`!f g:A->real^N B.
3039         eventually (\a. g a = vec 0 \/ abs(f a) <= B) net /\
3040         (g --> vec 0) net
3041         ==> ((\n. f n % g n) --> vec 0) net`,
3042   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto] THEN STRIP_TAC THEN
3043   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3044   FIRST_X_ASSUM(MP_TAC o SPEC `e / (abs B + &1)`) THEN
3045   ASM_SIMP_TAC[REAL_LT_DIV; REAL_ARITH `&0 < abs x + &1`] THEN
3046   UNDISCH_TAC `eventually (\a. g a:real^N = vec 0 \/ abs(f a) <= B)
3047                            (net:(A net))` THEN
3048   REWRITE_TAC[IMP_IMP; GSYM EVENTUALLY_AND] THEN
3049   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MP) THEN
3050   REWRITE_TAC[dist; VECTOR_SUB_RZERO; o_THM; NORM_LIFT; NORM_MUL] THEN
3051   MATCH_MP_TAC ALWAYS_EVENTUALLY THEN X_GEN_TAC `x:A` THEN REWRITE_TAC[] THEN
3052   ASM_CASES_TAC `(g:A->real^N) x = vec 0` THEN
3053   ASM_REWRITE_TAC[NORM_0; REAL_MUL_RZERO] THEN
3054   STRIP_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN
3055   EXISTS_TAC `B * e / (abs B + &1)` THEN
3056   ASM_SIMP_TAC[REAL_LE_MUL2; REAL_ABS_POS; NORM_POS_LE; REAL_LT_IMP_LE] THEN
3057   REWRITE_TAC[REAL_ARITH `c * (a / b) = (c * a) / b`] THEN
3058   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_ARITH `&0 < abs x + &1`] THEN
3059   MATCH_MP_TAC(REAL_ARITH
3060    `e * B <= e * abs B /\ &0 < e ==> B * e < e * (abs B + &1)`) THEN
3061   ASM_SIMP_TAC[REAL_LE_LMUL_EQ] THEN REAL_ARITH_TAC);;
3062
3063 let LIM_NULL_VMUL_BOUNDED = prove
3064  (`!f g:A->real^N B.
3065         ((lift o f) --> vec 0) net /\
3066         eventually (\a. f a = &0 \/ norm(g a) <= B) net
3067         ==> ((\n. f n % g n) --> vec 0) net`,
3068   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto] THEN STRIP_TAC THEN
3069   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3070   FIRST_X_ASSUM(MP_TAC o SPEC `e / (abs B + &1)`) THEN
3071   ASM_SIMP_TAC[REAL_LT_DIV; REAL_ARITH `&0 < abs x + &1`] THEN
3072   UNDISCH_TAC `eventually(\a. f a = &0 \/ norm((g:A->real^N) a) <= B) net` THEN
3073   REWRITE_TAC[IMP_IMP; GSYM EVENTUALLY_AND] THEN
3074   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MP) THEN
3075   REWRITE_TAC[dist; VECTOR_SUB_RZERO; o_THM; NORM_LIFT; NORM_MUL] THEN
3076   MATCH_MP_TAC ALWAYS_EVENTUALLY THEN X_GEN_TAC `x:A` THEN REWRITE_TAC[] THEN
3077   ASM_CASES_TAC `(f:A->real) x = &0` THEN
3078   ASM_REWRITE_TAC[REAL_ABS_NUM; REAL_MUL_LZERO] THEN
3079   STRIP_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN
3080   EXISTS_TAC `e / (abs B + &1) * B` THEN
3081   ASM_SIMP_TAC[REAL_LE_MUL2; REAL_ABS_POS; NORM_POS_LE; REAL_LT_IMP_LE] THEN
3082   REWRITE_TAC[REAL_ARITH `(a / b) * c = (a * c) / b`] THEN
3083   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_ARITH `&0 < abs x + &1`] THEN
3084   MATCH_MP_TAC(REAL_ARITH
3085    `e * B <= e * abs B /\ &0 < e ==> e * B < e * (abs B + &1)`) THEN
3086   ASM_SIMP_TAC[REAL_LE_LMUL_EQ] THEN REAL_ARITH_TAC);;
3087
3088 let LIM_VSUM = prove
3089  (`!net f:A->B->real^N l s.
3090         FINITE s /\ (!i. i IN s ==> ((f i) --> (l i)) net)
3091         ==> ((\x. vsum s (\i. f i x)) --> vsum s l) net`,
3092   REPLICATE_TAC 3 GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
3093   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
3094   SIMP_TAC[VSUM_CLAUSES; LIM_CONST; LIM_ADD; IN_INSERT; ETA_AX]);;
3095
3096 (* ------------------------------------------------------------------------- *)
3097 (* Deducing things about the limit from the elements.                        *)
3098 (* ------------------------------------------------------------------------- *)
3099
3100 let LIM_IN_CLOSED_SET = prove
3101  (`!net f:A->real^N s l.
3102         closed s /\ eventually (\x. f(x) IN s) net /\
3103         ~(trivial_limit net) /\ (f --> l) net
3104         ==> l IN s`,
3105   REWRITE_TAC[closed] THEN REPEAT STRIP_TAC THEN
3106   MATCH_MP_TAC(SET_RULE `~(x IN (UNIV DIFF s)) ==> x IN s`) THEN
3107   DISCH_TAC THEN
3108   FIRST_ASSUM(MP_TAC o SPEC `l:real^N` o GEN_REWRITE_RULE I
3109           [OPEN_CONTAINS_BALL]) THEN
3110   ASM_REWRITE_TAC[SUBSET; IN_BALL; IN_DIFF; IN_UNION] THEN
3111   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
3112   FIRST_X_ASSUM(MP_TAC o SPEC `e:real` o GEN_REWRITE_RULE I [tendsto]) THEN
3113   UNDISCH_TAC `eventually (\x. (f:A->real^N) x IN s) net` THEN
3114   ASM_REWRITE_TAC[GSYM EVENTUALLY_AND; TAUT `a ==> ~b <=> ~(a /\ b)`] THEN
3115   MATCH_MP_TAC NOT_EVENTUALLY THEN ASM_MESON_TAC[DIST_SYM]);;
3116
3117 (* ------------------------------------------------------------------------- *)
3118 (* Need to prove closed(cball(x,e)) before deducing this as a corollary.     *)
3119 (* ------------------------------------------------------------------------- *)
3120
3121 let LIM_NORM_UBOUND = prove
3122  (`!net:(A)net f (l:real^N) b.
3123       ~(trivial_limit net) /\
3124       (f --> l) net /\
3125       eventually (\x. norm(f x) <= b) net
3126       ==> norm(l) <= b`,
3127   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3128   ASM_REWRITE_TAC[LIM] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3129   ASM_REWRITE_TAC[eventually] THEN
3130   STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
3131   ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN DISCH_TAC THEN
3132   SUBGOAL_THEN
3133    `?x:A. dist(f(x):real^N,l) < norm(l:real^N) - b /\ norm(f x) <= b`
3134   (CHOOSE_THEN MP_TAC) THENL [ASM_MESON_TAC[NET]; ALL_TAC] THEN
3135   REWRITE_TAC[REAL_NOT_LT; REAL_LE_SUB_RADD; DE_MORGAN_THM; dist] THEN
3136   NORM_ARITH_TAC);;
3137
3138 let LIM_NORM_LBOUND = prove
3139  (`!net:(A)net f (l:real^N) b.
3140       ~(trivial_limit net) /\ (f --> l) net /\
3141       eventually (\x. b <= norm(f x)) net
3142       ==> b <= norm(l)`,
3143   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3144   ASM_REWRITE_TAC[LIM] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3145   ASM_REWRITE_TAC[eventually] THEN
3146   STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
3147   ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN DISCH_TAC THEN
3148   SUBGOAL_THEN
3149    `?x:A. dist(f(x):real^N,l) < b - norm(l:real^N) /\ b <= norm(f x)`
3150   (CHOOSE_THEN MP_TAC) THENL [ASM_MESON_TAC[NET]; ALL_TAC] THEN
3151   REWRITE_TAC[REAL_NOT_LT; REAL_LE_SUB_RADD; DE_MORGAN_THM; dist] THEN
3152   NORM_ARITH_TAC);;
3153
3154 (* ------------------------------------------------------------------------- *)
3155 (* Uniqueness of the limit, when nontrivial.                                 *)
3156 (* ------------------------------------------------------------------------- *)
3157
3158 let LIM_UNIQUE = prove
3159  (`!net:(A)net f l:real^N l'.
3160       ~(trivial_limit net) /\ (f --> l) net /\ (f --> l') net ==> (l = l')`,
3161   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3162   DISCH_THEN(ASSUME_TAC o REWRITE_RULE[VECTOR_SUB_REFL] o MATCH_MP LIM_SUB) THEN
3163   SUBGOAL_THEN `!e. &0 < e ==> norm(l:real^N - l') <= e` MP_TAC THENL
3164    [GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC LIM_NORM_UBOUND THEN
3165     MAP_EVERY EXISTS_TAC [`net:(A)net`; `\x:A. vec 0 : real^N`] THEN
3166     ASM_SIMP_TAC[NORM_0; REAL_LT_IMP_LE; eventually] THEN
3167     ASM_MESON_TAC[trivial_limit];
3168     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[DIST_NZ; dist] THEN
3169     DISCH_TAC THEN DISCH_THEN(MP_TAC o SPEC `norm(l - l':real^N) / &2`) THEN
3170     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LE_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
3171     UNDISCH_TAC `&0 < norm(l - l':real^N)` THEN REAL_ARITH_TAC]);;
3172
3173 let TENDSTO_LIM = prove
3174  (`!net f l. ~(trivial_limit net) /\ (f --> l) net ==> lim net f = l`,
3175   REWRITE_TAC[lim] THEN MESON_TAC[LIM_UNIQUE]);;
3176
3177 let LIM_CONST_EQ = prove
3178  (`!net:(A net) c d:real^N.
3179         ((\x. c) --> d) net <=> trivial_limit net \/ c = d`,
3180   REPEAT GEN_TAC THEN
3181   ASM_CASES_TAC `trivial_limit (net:A net)` THEN ASM_REWRITE_TAC[] THENL
3182    [ASM_REWRITE_TAC[LIM]; ALL_TAC] THEN
3183   EQ_TAC THEN SIMP_TAC[LIM_CONST] THEN DISCH_TAC THEN
3184   MATCH_MP_TAC(SPEC `net:A net` LIM_UNIQUE) THEN
3185   EXISTS_TAC `(\x. c):A->real^N` THEN ASM_REWRITE_TAC[LIM_CONST]);;
3186
3187 (* ------------------------------------------------------------------------- *)
3188 (* Some unwieldy but occasionally useful theorems about uniform limits.      *)
3189 (* ------------------------------------------------------------------------- *)
3190
3191 let UNIFORM_LIM_ADD = prove
3192  (`!net:(A)net P f g l m.
3193         (!e. &0 < e
3194              ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
3195         (!e. &0 < e
3196              ==> eventually (\x. !n. P n ==> norm(g n x - m n) < e) net)
3197         ==> !e. &0 < e
3198                 ==> eventually
3199                      (\x. !n. P n
3200                               ==> norm((f n x + g n x) - (l n + m n)) < e)
3201                      net`,
3202   REPEAT GEN_TAC THEN REWRITE_TAC[AND_FORALL_THM] THEN DISCH_TAC THEN
3203   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3204   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
3205   ASM_REWRITE_TAC[REAL_HALF; GSYM EVENTUALLY_AND] THEN
3206   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
3207   GEN_TAC THEN REWRITE_TAC[AND_FORALL_THM] THEN
3208   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `n:B` THEN
3209   ASM_CASES_TAC `(P:B->bool) n` THEN ASM_REWRITE_TAC[] THEN
3210   CONV_TAC NORM_ARITH);;
3211
3212 let UNIFORM_LIM_SUB = prove
3213  (`!net:(A)net P f g l m.
3214         (!e. &0 < e
3215              ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
3216         (!e. &0 < e
3217              ==> eventually (\x. !n. P n ==> norm(g n x - m n) < e) net)
3218         ==> !e. &0 < e
3219                 ==> eventually
3220                      (\x. !n. P n
3221                               ==> norm((f n x - g n x) - (l n - m n)) < e)
3222                      net`,
3223   REPEAT GEN_TAC THEN REWRITE_TAC[AND_FORALL_THM] THEN DISCH_TAC THEN
3224   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3225   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
3226   ASM_REWRITE_TAC[REAL_HALF; GSYM EVENTUALLY_AND] THEN
3227   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
3228   GEN_TAC THEN REWRITE_TAC[AND_FORALL_THM] THEN
3229   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `n:B` THEN
3230   ASM_CASES_TAC `(P:B->bool) n` THEN ASM_REWRITE_TAC[] THEN
3231   CONV_TAC NORM_ARITH);;
3232
3233 (* ------------------------------------------------------------------------- *)
3234 (* Limit under bilinear function, uniform version first.                     *)
3235 (* ------------------------------------------------------------------------- *)
3236
3237 let UNIFORM_LIM_BILINEAR = prove
3238  (`!net:(A)net P (h:real^M->real^N->real^P) f g l m b1 b2.
3239         bilinear h /\
3240         eventually (\x. !n. P n ==> norm(l n) <= b1) net /\
3241         eventually (\x. !n. P n ==> norm(m n) <= b2) net /\
3242         (!e. &0 < e
3243              ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
3244         (!e. &0 < e
3245              ==> eventually (\x. !n. P n ==> norm(g n x - m n) < e) net)
3246         ==> !e. &0 < e
3247                 ==> eventually
3248                      (\x. !n. P n
3249                               ==> norm(h (f n x) (g n x) - h (l n) (m n)) < e)
3250                      net`,
3251   REPEAT GEN_TAC THEN
3252   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3253   FIRST_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o  MATCH_MP
3254    BILINEAR_BOUNDED_POS) THEN
3255   REWRITE_TAC[AND_FORALL_THM; RIGHT_AND_FORALL_THM] THEN DISCH_TAC THEN
3256   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3257   FIRST_X_ASSUM(MP_TAC o SPEC
3258    `min (abs b2 + &1) (e / &2 / (B * (abs b1 + abs b2 + &2)))`) THEN
3259   ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; REAL_LT_MUL; REAL_LT_MIN;
3260                REAL_ARITH `&0 < abs x + &1`;
3261                REAL_ARITH `&0 < abs x + abs y + &2`] THEN
3262   REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
3263   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
3264   X_GEN_TAC `x:A` THEN REWRITE_TAC[AND_FORALL_THM] THEN
3265   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `n:B` THEN
3266   ASM_CASES_TAC `(P:B->bool) n` THEN ASM_REWRITE_TAC[] THEN
3267   STRIP_TAC THEN
3268   ONCE_REWRITE_TAC[VECTOR_ARITH
3269     `h a b - h c d :real^N = (h a b - h a d) + (h a d - h c d)`] THEN
3270   ASM_SIMP_TAC[GSYM BILINEAR_LSUB; GSYM BILINEAR_RSUB] THEN
3271   MATCH_MP_TAC NORM_TRIANGLE_LT THEN
3272   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
3273    (MESON[REAL_LE_ADD2; REAL_LET_TRANS]
3274      `(!x y. norm(h x y:real^P) <= B * norm x * norm y)
3275        ==> B * norm a * norm b + B * norm c * norm d < e
3276            ==> norm(h a b) + norm(h c d) < e`)) THEN
3277   MATCH_MP_TAC(REAL_ARITH
3278    `x * B < e / &2 /\ y * B < e / &2 ==> B * x + B * y < e`) THEN
3279   CONJ_TAC THEN ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ] THENL
3280    [ONCE_REWRITE_TAC[REAL_MUL_SYM]; ALL_TAC] THEN
3281   MATCH_MP_TAC REAL_LET_TRANS THEN
3282   EXISTS_TAC `e / &2 / (B * (abs b1 + abs b2 + &2)) *
3283              (abs b1 + abs b2 + &1)` THEN
3284   (CONJ_TAC THENL
3285     [MATCH_MP_TAC REAL_LE_MUL2 THEN
3286      ASM_SIMP_TAC[NORM_POS_LE; REAL_LT_IMP_LE] THEN
3287      ASM_SIMP_TAC[REAL_ARITH `a <= b2 ==> a <= abs b1 + abs b2 + &1`] THEN
3288      ASM_MESON_TAC[NORM_ARITH
3289        `norm(f - l:real^P) < abs b2 + &1 /\ norm(l) <= b1
3290         ==> norm(f) <= abs b1 + abs b2 + &1`];
3291      ONCE_REWRITE_TAC[real_div] THEN
3292      ASM_SIMP_TAC[REAL_LT_LMUL_EQ; REAL_HALF; GSYM REAL_MUL_ASSOC;
3293                   REAL_INV_MUL] THEN
3294      REWRITE_TAC[REAL_ARITH `B * inv x * y < B <=> B * y / x < B * &1`] THEN
3295      ASM_SIMP_TAC[REAL_LT_INV_EQ; REAL_LT_LMUL_EQ; REAL_LT_LDIV_EQ;
3296                   REAL_ARITH `&0 < abs x + abs y + &2`] THEN
3297      REAL_ARITH_TAC]));;
3298
3299 let LIM_BILINEAR = prove
3300  (`!net:(A)net (h:real^M->real^N->real^P) f g l m.
3301         (f --> l) net /\ (g --> m) net /\ bilinear h
3302         ==> ((\x. h (f x) (g x)) --> (h l m)) net`,
3303   REPEAT STRIP_TAC THEN
3304   MP_TAC(ISPECL
3305    [`net:(A)net`; `\x:one. T`; `h:real^M->real^N->real^P`;
3306     `\n:one. (f:A->real^M)`; `\n:one. (g:A->real^N)`;
3307     `\n:one. (l:real^M)`; `\n:one. (m:real^N)`;
3308     `norm(l:real^M)`; `norm(m:real^N)`]
3309    UNIFORM_LIM_BILINEAR) THEN
3310   ASM_REWRITE_TAC[REAL_LE_REFL; EVENTUALLY_TRUE] THEN
3311   ASM_REWRITE_TAC[GSYM dist; GSYM tendsto]);;
3312
3313 (* ------------------------------------------------------------------------- *)
3314 (* These are special for limits out of the same vector space.                *)
3315 (* ------------------------------------------------------------------------- *)
3316
3317 let LIM_WITHIN_ID = prove
3318  (`!a s. ((\x. x) --> a) (at a within s)`,
3319   REWRITE_TAC[LIM_WITHIN] THEN MESON_TAC[]);;
3320
3321 let LIM_AT_ID = prove
3322  (`!a. ((\x. x) --> a) (at a)`,
3323   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[LIM_WITHIN_ID]);;
3324
3325 let LIM_AT_ZERO = prove
3326  (`!f:real^M->real^N l a.
3327         (f --> l) (at a) <=> ((\x. f(a + x)) --> l) (at(vec 0))`,
3328   REPEAT GEN_TAC THEN REWRITE_TAC[LIM_AT] THEN
3329   AP_TERM_TAC THEN ABS_TAC THEN
3330   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
3331   AP_TERM_TAC THEN ABS_TAC THEN
3332   ASM_CASES_TAC `&0 < d` THEN ASM_REWRITE_TAC[] THEN
3333   EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `x:real^M` THENL
3334    [FIRST_X_ASSUM(MP_TAC o SPEC `a + x:real^M`) THEN
3335     REWRITE_TAC[dist; VECTOR_ADD_SUB; VECTOR_SUB_RZERO];
3336     FIRST_X_ASSUM(MP_TAC o SPEC `x - a:real^M`) THEN
3337     REWRITE_TAC[dist; VECTOR_SUB_RZERO; VECTOR_SUB_ADD2]]);;
3338
3339 (* ------------------------------------------------------------------------- *)
3340 (* It's also sometimes useful to extract the limit point from the net.       *)
3341 (* ------------------------------------------------------------------------- *)
3342
3343 let netlimit = new_definition
3344   `netlimit net = @a. !x. ~(netord net x a)`;;
3345
3346 let NETLIMIT_WITHIN = prove
3347  (`!a:real^N s. ~(trivial_limit (at a within s))
3348                 ==> (netlimit (at a within s) = a)`,
3349   REWRITE_TAC[trivial_limit; netlimit; AT; WITHIN; DE_MORGAN_THM] THEN
3350   REPEAT STRIP_TAC THEN MATCH_MP_TAC SELECT_UNIQUE THEN REWRITE_TAC[] THEN
3351   SUBGOAL_THEN
3352    `!x:real^N. ~(&0 < dist(x,a) /\ dist(x,a) <= dist(a,a) /\ x IN s)`
3353   ASSUME_TAC THENL
3354    [ASM_MESON_TAC[DIST_REFL; REAL_NOT_LT]; ASM_MESON_TAC[]]);;
3355
3356 let NETLIMIT_AT = prove
3357  (`!a. netlimit(at a) = a`,
3358   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
3359   MATCH_MP_TAC NETLIMIT_WITHIN THEN
3360   SIMP_TAC[TRIVIAL_LIMIT_AT; WITHIN_UNIV]);;
3361
3362 (* ------------------------------------------------------------------------- *)
3363 (* Transformation of limit.                                                  *)
3364 (* ------------------------------------------------------------------------- *)
3365
3366 let LIM_TRANSFORM = prove
3367  (`!net f g l.
3368      ((\x. f x - g x) --> vec 0) net /\ (f --> l) net ==> (g --> l) net`,
3369   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP LIM_SUB) THEN
3370   DISCH_THEN(MP_TAC o MATCH_MP LIM_NEG) THEN MATCH_MP_TAC EQ_IMP THEN
3371   AP_THM_TAC THEN BINOP_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN
3372   VECTOR_ARITH_TAC);;
3373
3374 let LIM_TRANSFORM_EVENTUALLY = prove
3375  (`!net f g l.
3376         eventually (\x. f x = g x) net /\ (f --> l) net ==> (g --> l) net`,
3377   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
3378   DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o MATCH_MP LIM_EVENTUALLY) MP_TAC) THEN
3379   MESON_TAC[LIM_TRANSFORM]);;
3380
3381 let LIM_TRANSFORM_WITHIN = prove
3382  (`!f g x s d.
3383         &0 < d /\
3384         (!x'. x' IN s /\ &0 < dist(x',x) /\ dist(x',x) < d ==> f(x') = g(x')) /\
3385         (f --> l) (at x within s)
3386         ==> (g --> l) (at x within s)`,
3387   REPEAT GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
3388   DISCH_TAC THEN DISCH_TAC THEN
3389   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM) THEN
3390   REWRITE_TAC[LIM_WITHIN] THEN REPEAT STRIP_TAC THEN EXISTS_TAC `d:real` THEN
3391   ASM_SIMP_TAC[VECTOR_SUB_REFL; DIST_REFL]);;
3392
3393 let LIM_TRANSFORM_AT = prove
3394  (`!f g x d.
3395         &0 < d /\
3396         (!x'. &0 < dist(x',x) /\ dist(x',x) < d ==> f(x') = g(x')) /\
3397         (f --> l) (at x)
3398         ==> (g --> l) (at x)`,
3399   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN MESON_TAC[LIM_TRANSFORM_WITHIN]);;
3400
3401 let LIM_TRANSFORM_EQ = prove
3402  (`!net f:A->real^N g l.
3403      ((\x. f x - g x) --> vec 0) net ==> ((f --> l) net <=> (g --> l) net)`,
3404   REPEAT STRIP_TAC THEN EQ_TAC THEN
3405   DISCH_TAC THEN MATCH_MP_TAC LIM_TRANSFORM THENL
3406    [EXISTS_TAC `f:A->real^N` THEN ASM_REWRITE_TAC[];
3407     EXISTS_TAC `g:A->real^N` THEN ASM_REWRITE_TAC[] THEN
3408     ONCE_REWRITE_TAC[GSYM LIM_NEG_EQ] THEN
3409     ASM_REWRITE_TAC[VECTOR_NEG_SUB; VECTOR_NEG_0]]);;
3410
3411 let LIM_TRANSFORM_WITHIN_SET = prove
3412  (`!f a s t.
3413         eventually (\x. x IN s <=> x IN t) (at a)
3414         ==> ((f --> l) (at a within s) <=> (f --> l) (at a within t))`,
3415   REPEAT GEN_TAC THEN REWRITE_TAC[EVENTUALLY_AT; LIM_WITHIN] THEN
3416   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
3417   EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3418   FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
3419   DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
3420   EXISTS_TAC `min d k:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
3421   ASM_MESON_TAC[]);;
3422
3423 (* ------------------------------------------------------------------------- *)
3424 (* Common case assuming being away from some crucial point like 0.           *)
3425 (* ------------------------------------------------------------------------- *)
3426
3427 let LIM_TRANSFORM_AWAY_WITHIN = prove
3428  (`!f:real^M->real^N g a b s.
3429         ~(a = b) /\
3430         (!x. x IN s /\ ~(x = a) /\ ~(x = b) ==> f(x) = g(x)) /\
3431         (f --> l) (at a within s)
3432         ==> (g --> l) (at a within s)`,
3433   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_TRANSFORM_WITHIN THEN
3434   MAP_EVERY EXISTS_TAC [`f:real^M->real^N`; `dist(a:real^M,b)`] THEN
3435   ASM_REWRITE_TAC[GSYM DIST_NZ] THEN X_GEN_TAC `y:real^M` THEN
3436   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
3437   ASM_MESON_TAC[DIST_SYM; REAL_LT_REFL]);;
3438
3439 let LIM_TRANSFORM_AWAY_AT = prove
3440  (`!f:real^M->real^N g a b.
3441         ~(a = b) /\
3442         (!x. ~(x = a) /\ ~(x = b) ==> f(x) = g(x)) /\
3443         (f --> l) (at a)
3444         ==> (g --> l) (at a)`,
3445   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
3446   MESON_TAC[LIM_TRANSFORM_AWAY_WITHIN]);;
3447
3448 (* ------------------------------------------------------------------------- *)
3449 (* Alternatively, within an open set.                                        *)
3450 (* ------------------------------------------------------------------------- *)
3451
3452 let LIM_TRANSFORM_WITHIN_OPEN = prove
3453  (`!f g:real^M->real^N s a l.
3454         open s /\ a IN s /\
3455         (!x. x IN s /\ ~(x = a) ==> f x = g x) /\
3456         (f --> l) (at a)
3457         ==> (g --> l) (at a)`,
3458   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_TRANSFORM_AT THEN
3459   EXISTS_TAC `f:real^M->real^N` THEN ASM_REWRITE_TAC[] THEN
3460   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
3461   DISCH_THEN(MP_TAC o SPEC `a:real^M`) THEN ASM_REWRITE_TAC[] THEN
3462   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[SUBSET; IN_BALL] THEN
3463   ASM_MESON_TAC[DIST_NZ; DIST_SYM]);;
3464
3465 let LIM_TRANSFORM_WITHIN_OPEN_IN = prove
3466  (`!f g:real^M->real^N s t a l.
3467         open_in (subtopology euclidean t) s /\ a IN s /\
3468         (!x. x IN s /\ ~(x = a) ==> f x = g x) /\
3469         (f --> l) (at a within t)
3470         ==> (g --> l) (at a within t)`,
3471   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_TRANSFORM_WITHIN THEN
3472   EXISTS_TAC `f:real^M->real^N` THEN ASM_REWRITE_TAC[] THEN
3473   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_CONTAINS_BALL]) THEN
3474   DISCH_THEN(MP_TAC o SPEC `a:real^M` o CONJUNCT2) THEN ASM_REWRITE_TAC[] THEN
3475   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[SUBSET; IN_INTER; IN_BALL] THEN
3476   ASM_MESON_TAC[DIST_NZ; DIST_SYM]);;
3477
3478 (* ------------------------------------------------------------------------- *)
3479 (* Another quite common idiom of an explicit conditional in a sequence.      *)
3480 (* ------------------------------------------------------------------------- *)
3481
3482 let LIM_CASES_FINITE_SEQUENTIALLY = prove
3483  (`!f g l. FINITE {n | P n}
3484            ==> (((\n. if P n then f n else g n) --> l) sequentially <=>
3485                 (g --> l) sequentially)`,
3486   REPEAT STRIP_TAC THEN EQ_TAC THEN
3487   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM_EVENTUALLY) THEN
3488   FIRST_ASSUM(MP_TAC o SPEC `\n:num. n` o MATCH_MP UPPER_BOUND_FINITE_SET) THEN
3489   REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
3490   X_GEN_TAC `N:num` THEN DISCH_TAC THEN SIMP_TAC[EVENTUALLY_SEQUENTIALLY] THEN
3491   EXISTS_TAC `N + 1` THEN
3492   ASM_MESON_TAC[ARITH_RULE `~(x <= n /\ n + 1 <= x)`]);;
3493
3494 let LIM_CASES_COFINITE_SEQUENTIALLY = prove
3495  (`!f g l. FINITE {n | ~P n}
3496            ==> (((\n. if P n then f n else g n) --> l) sequentially <=>
3497                 (f --> l) sequentially)`,
3498   ONCE_REWRITE_TAC[TAUT `(if p then x else y) = (if ~p then y else x)`] THEN
3499   REWRITE_TAC[LIM_CASES_FINITE_SEQUENTIALLY]);;
3500
3501 let LIM_CASES_SEQUENTIALLY = prove
3502  (`!f g l m. (((\n. if m <= n then f n else g n) --> l) sequentially <=>
3503               (f --> l) sequentially) /\
3504              (((\n. if m < n then f n else g n) --> l) sequentially <=>
3505               (f --> l) sequentially) /\
3506              (((\n. if n <= m then f n else g n) --> l) sequentially <=>
3507               (g --> l) sequentially) /\
3508              (((\n. if n < m then f n else g n) --> l) sequentially <=>
3509               (g --> l) sequentially)`,
3510   SIMP_TAC[LIM_CASES_FINITE_SEQUENTIALLY; LIM_CASES_COFINITE_SEQUENTIALLY;
3511            NOT_LE; NOT_LT; FINITE_NUMSEG_LT; FINITE_NUMSEG_LE]);;
3512
3513 (* ------------------------------------------------------------------------- *)
3514 (* A congruence rule allowing us to transform limits assuming not at point.  *)
3515 (* ------------------------------------------------------------------------- *)
3516
3517 let LIM_CONG_WITHIN = prove
3518  (`(!x. ~(x = a) ==> f x = g x)
3519    ==> (((\x. f x) --> l) (at a within s) <=> ((g --> l) (at a within s)))`,
3520   REWRITE_TAC[LIM_WITHIN; GSYM DIST_NZ] THEN SIMP_TAC[]);;
3521
3522 let LIM_CONG_AT = prove
3523  (`(!x. ~(x = a) ==> f x = g x)
3524    ==> (((\x. f x) --> l) (at a) <=> ((g --> l) (at a)))`,
3525   REWRITE_TAC[LIM_AT; GSYM DIST_NZ] THEN SIMP_TAC[]);;
3526
3527 extend_basic_congs [LIM_CONG_WITHIN; LIM_CONG_AT];;
3528
3529 (* ------------------------------------------------------------------------- *)
3530 (* Useful lemmas on closure and set of possible sequential limits.           *)
3531 (* ------------------------------------------------------------------------- *)
3532
3533 let CLOSURE_SEQUENTIAL = prove
3534  (`!s l:real^N.
3535      l IN closure(s) <=> ?x. (!n. x(n) IN s) /\ (x --> l) sequentially`,
3536   REWRITE_TAC[closure; IN_UNION; LIMPT_SEQUENTIAL; IN_ELIM_THM; IN_DELETE] THEN
3537   REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
3538     `((b ==> c) /\ (~a /\ c ==> b)) /\ (a ==> c) ==> (a \/ b <=> c)`) THEN
3539   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN DISCH_TAC THEN
3540   EXISTS_TAC `\n:num. l:real^N` THEN
3541   ASM_REWRITE_TAC[LIM_CONST]);;
3542
3543 let CLOSED_CONTAINS_SEQUENTIAL_LIMIT = prove
3544  (`!s x l:real^N.
3545         closed s /\ (!n. x n IN s) /\ (x --> l) sequentially ==> l IN s`,
3546   MESON_TAC[CLOSURE_SEQUENTIAL; CLOSURE_CLOSED]);;
3547
3548 let CLOSED_SEQUENTIAL_LIMITS = prove
3549  (`!s. closed s <=>
3550        !x l. (!n. x(n) IN s) /\ (x --> l) sequentially ==> l IN s`,
3551   MESON_TAC[CLOSURE_SEQUENTIAL; CLOSURE_CLOSED;
3552             CLOSED_LIMPT; LIMPT_SEQUENTIAL; IN_DELETE]);;
3553
3554 let CLOSURE_APPROACHABLE = prove
3555  (`!x s. x IN closure(s) <=> !e. &0 < e ==> ?y. y IN s /\ dist(y,x) < e`,
3556   REWRITE_TAC[closure; LIMPT_APPROACHABLE; IN_UNION; IN_ELIM_THM] THEN
3557   MESON_TAC[DIST_REFL]);;
3558
3559 let CLOSED_APPROACHABLE = prove
3560  (`!x s. closed s
3561          ==> ((!e. &0 < e ==> ?y. y IN s /\ dist(y,x) < e) <=> x IN s)`,
3562   MESON_TAC[CLOSURE_CLOSED; CLOSURE_APPROACHABLE]);;
3563
3564 let IN_CLOSURE_DELETE = prove
3565  (`!s x:real^N. x IN closure(s DELETE x) <=> x limit_point_of s`,
3566   SIMP_TAC[CLOSURE_APPROACHABLE; LIMPT_APPROACHABLE; IN_DELETE; CONJ_ASSOC]);;
3567
3568 (* ------------------------------------------------------------------------- *)
3569 (* Some other lemmas about sequences.                                        *)
3570 (* ------------------------------------------------------------------------- *)
3571
3572 let SEQ_OFFSET = prove
3573  (`!f l k. (f --> l) sequentially ==> ((\i. f(i + k)) --> l) sequentially`,
3574   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
3575   MESON_TAC[ARITH_RULE `N <= n ==> N <= n + k:num`]);;
3576
3577 let SEQ_OFFSET_NEG = prove
3578  (`!f l k. (f --> l) sequentially ==> ((\i. f(i - k)) --> l) sequentially`,
3579   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
3580   MESON_TAC[ARITH_RULE `N + k <= n ==> N <= n - k:num`]);;
3581
3582 let SEQ_OFFSET_REV = prove
3583  (`!f l k. ((\i. f(i + k)) --> l) sequentially ==> (f --> l) sequentially`,
3584   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
3585   MESON_TAC[ARITH_RULE `N + k <= n ==> N <= n - k /\ (n - k) + k = n:num`]);;
3586
3587 let SEQ_HARMONIC = prove
3588  (`((\n. lift(inv(&n))) --> vec 0) sequentially`,
3589   REWRITE_TAC[LIM_SEQUENTIALLY] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3590   FIRST_ASSUM(X_CHOOSE_THEN `N:num` STRIP_ASSUME_TAC o
3591     GEN_REWRITE_RULE I [REAL_ARCH_INV]) THEN
3592   EXISTS_TAC `N:num` THEN REPEAT STRIP_TAC THEN
3593   REWRITE_TAC[dist; VECTOR_SUB_RZERO; NORM_LIFT] THEN
3594   ASM_REWRITE_TAC[REAL_ABS_INV; REAL_ABS_NUM] THEN
3595   MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&N)` THEN
3596   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
3597   ASM_REWRITE_TAC[REAL_OF_NUM_LT; REAL_OF_NUM_LE; LT_NZ]);;
3598
3599 (* ------------------------------------------------------------------------- *)
3600 (* More properties of closed balls.                                          *)
3601 (* ------------------------------------------------------------------------- *)
3602
3603 let CLOSED_CBALL = prove
3604  (`!x:real^N e. closed(cball(x,e))`,
3605   REWRITE_TAC[CLOSED_SEQUENTIAL_LIMITS; IN_CBALL; dist] THEN
3606   GEN_TAC THEN GEN_TAC THEN X_GEN_TAC `s:num->real^N` THEN
3607   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
3608   MATCH_MP_TAC(ISPEC `sequentially` LIM_NORM_UBOUND) THEN
3609   EXISTS_TAC `\n. x - (s:num->real^N) n` THEN
3610   REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; EVENTUALLY_SEQUENTIALLY] THEN
3611   ASM_SIMP_TAC[LIM_SUB; LIM_CONST; SEQUENTIALLY] THEN MESON_TAC[GE_REFL]);;
3612
3613 let IN_INTERIOR_CBALL = prove
3614  (`!x s. x IN interior s <=> ?e. &0 < e /\ cball(x,e) SUBSET s`,
3615   REWRITE_TAC[interior; IN_ELIM_THM] THEN
3616   MESON_TAC[OPEN_CONTAINS_CBALL; SUBSET_TRANS;
3617             BALL_SUBSET_CBALL; CENTRE_IN_BALL; OPEN_BALL]);;
3618
3619 let LIMPT_BALL = prove
3620  (`!x:real^N y e. y limit_point_of ball(x,e) <=> &0 < e /\ y IN cball(x,e)`,
3621   REPEAT GEN_TAC THEN ASM_CASES_TAC `&0 < e` THENL
3622    [ALL_TAC; ASM_MESON_TAC[LIMPT_EMPTY; REAL_NOT_LT; BALL_EQ_EMPTY]] THEN
3623   ASM_REWRITE_TAC[] THEN EQ_TAC THENL
3624    [MESON_TAC[CLOSED_CBALL; CLOSED_LIMPT; LIMPT_SUBSET; BALL_SUBSET_CBALL];
3625     REWRITE_TAC[IN_CBALL; LIMPT_APPROACHABLE; IN_BALL]] THEN
3626   DISCH_TAC THEN X_GEN_TAC `d:real` THEN DISCH_TAC THEN
3627   ASM_CASES_TAC `y:real^N = x` THEN ASM_REWRITE_TAC[DIST_NZ] THENL
3628    [MP_TAC(SPECL [`d:real`; `e:real`] REAL_DOWN2) THEN
3629     ASM_REWRITE_TAC[] THEN
3630     GEN_MESON_TAC 0 40 1 [VECTOR_CHOOSE_DIST; DIST_SYM; REAL_LT_IMP_LE];
3631     ALL_TAC] THEN
3632   MP_TAC(SPECL [`norm(y:real^N - x)`; `d:real`] REAL_DOWN2) THEN
3633   RULE_ASSUM_TAC(REWRITE_RULE[DIST_NZ; dist]) THEN ASM_REWRITE_TAC[] THEN
3634   DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
3635   EXISTS_TAC `(y:real^N) - (k / dist(y,x)) % (y - x)` THEN
3636   REWRITE_TAC[dist; VECTOR_ARITH `(y - c % z) - y = --c % z`] THEN
3637   REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_ABS_NEG] THEN
3638   ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_LT_IMP_NZ] THEN
3639   REWRITE_TAC[VECTOR_ARITH `x - (y - k % (y - x)) = (&1 - k) % (x - y)`] THEN
3640   ASM_SIMP_TAC[REAL_ARITH `&0 < k ==> &0 < abs k`; NORM_MUL] THEN
3641   ASM_SIMP_TAC[REAL_ARITH `&0 < k /\ k < d ==> abs k < d`] THEN
3642   MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `norm(x:real^N - y)` THEN
3643   ASM_REWRITE_TAC[] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN
3644   MATCH_MP_TAC REAL_LT_RMUL THEN CONJ_TAC THENL
3645    [ALL_TAC; ASM_MESON_TAC[NORM_SUB]] THEN
3646   MATCH_MP_TAC(REAL_ARITH `&0 < k /\ k < &1 ==> abs(&1 - k) < &1`) THEN
3647   ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_MUL_LZERO;
3648                REAL_MUL_LID]);;
3649
3650 let CLOSURE_BALL = prove
3651  (`!x:real^N e. &0 < e ==> (closure(ball(x,e)) = cball(x,e))`,
3652   SIMP_TAC[EXTENSION; closure; IN_ELIM_THM; IN_UNION; LIMPT_BALL] THEN
3653   REWRITE_TAC[IN_BALL; IN_CBALL] THEN REAL_ARITH_TAC);;
3654
3655 let INTERIOR_BALL = prove
3656  (`!a r. interior(ball(a,r)) = ball(a,r)`,
3657   SIMP_TAC[INTERIOR_OPEN; OPEN_BALL]);;
3658
3659 let INTERIOR_CBALL = prove
3660  (`!x:real^N e. interior(cball(x,e)) = ball(x,e)`,
3661   REPEAT GEN_TAC THEN ASM_CASES_TAC `&0 <= e` THENL
3662    [ALL_TAC;
3663     SUBGOAL_THEN `cball(x:real^N,e) = {} /\ ball(x:real^N,e) = {}`
3664      (fun th -> REWRITE_TAC[th; INTERIOR_EMPTY]) THEN
3665     REWRITE_TAC[IN_BALL; IN_CBALL; EXTENSION; NOT_IN_EMPTY] THEN
3666     CONJ_TAC THEN X_GEN_TAC `y:real^N` THEN
3667     MP_TAC(ISPECL [`x:real^N`; `y:real^N`] DIST_POS_LE) THEN
3668     POP_ASSUM MP_TAC THEN REAL_ARITH_TAC] THEN
3669   MATCH_MP_TAC INTERIOR_UNIQUE THEN
3670   REWRITE_TAC[BALL_SUBSET_CBALL; OPEN_BALL] THEN
3671   X_GEN_TAC `t:real^N->bool` THEN
3672   SIMP_TAC[SUBSET; IN_CBALL; IN_BALL; REAL_LT_LE] THEN STRIP_TAC THEN
3673   X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
3674   FIRST_X_ASSUM(MP_TAC o SPEC `z:real^N` o GEN_REWRITE_RULE I [open_def]) THEN
3675   ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` MP_TAC) THEN
3676   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3677   ASM_CASES_TAC `z:real^N = x` THENL
3678    [FIRST_X_ASSUM SUBST_ALL_TAC THEN
3679     FIRST_X_ASSUM(X_CHOOSE_TAC `k:real` o MATCH_MP REAL_DOWN) THEN
3680     SUBGOAL_THEN `?w:real^N. dist(w,x) = k` STRIP_ASSUME_TAC THENL
3681      [ASM_MESON_TAC[VECTOR_CHOOSE_DIST; DIST_SYM; REAL_LT_IMP_LE];
3682       ASM_MESON_TAC[REAL_NOT_LE; DIST_REFL; DIST_SYM]];
3683     RULE_ASSUM_TAC(REWRITE_RULE[DIST_NZ]) THEN
3684     DISCH_THEN(MP_TAC o SPEC `z + ((d / &2) / dist(z,x)) % (z - x:real^N)`) THEN
3685     REWRITE_TAC[dist; VECTOR_ADD_SUB; NORM_MUL; REAL_ABS_DIV;
3686                 REAL_ABS_NORM; REAL_ABS_NUM] THEN
3687     ASM_SIMP_TAC[REAL_DIV_RMUL; GSYM dist; REAL_LT_IMP_NZ] THEN
3688     ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
3689     ASM_REWRITE_TAC[REAL_ARITH `abs d < d * &2 <=> &0 < d`] THEN
3690     DISCH_THEN(ANTE_RES_THEN MP_TAC) THEN REWRITE_TAC[dist] THEN
3691     REWRITE_TAC[VECTOR_ARITH `x - (z + k % (z - x)) = (&1 + k) % (x - z)`] THEN
3692     REWRITE_TAC[REAL_NOT_LE; NORM_MUL] THEN
3693     GEN_REWRITE_TAC LAND_CONV [GSYM REAL_MUL_LID] THEN
3694     ONCE_REWRITE_TAC[NORM_SUB] THEN
3695     ASM_SIMP_TAC[REAL_LT_RMUL_EQ; GSYM dist] THEN
3696     MATCH_MP_TAC(REAL_ARITH `&0 < x ==> &1 < abs(&1 + x)`) THEN
3697     ONCE_REWRITE_TAC[DIST_SYM] THEN
3698     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH]]);;
3699
3700 let FRONTIER_BALL = prove
3701  (`!a e. &0 < e ==> frontier(ball(a,e)) = sphere(a,e)`,
3702   SIMP_TAC[frontier; sphere; CLOSURE_BALL; INTERIOR_OPEN; OPEN_BALL;
3703            REAL_LT_IMP_LE] THEN
3704   REWRITE_TAC[EXTENSION; IN_DIFF; IN_ELIM_THM; IN_BALL; IN_CBALL] THEN
3705   REAL_ARITH_TAC);;
3706
3707 let FRONTIER_CBALL = prove
3708  (`!a e. frontier(cball(a,e)) = sphere(a,e)`,
3709   SIMP_TAC[frontier; sphere; INTERIOR_CBALL; CLOSED_CBALL; CLOSURE_CLOSED;
3710            REAL_LT_IMP_LE] THEN
3711   REWRITE_TAC[EXTENSION; IN_DIFF; IN_ELIM_THM; IN_BALL; IN_CBALL] THEN
3712   REAL_ARITH_TAC);;
3713
3714 let CBALL_EQ_EMPTY = prove
3715  (`!x e. (cball(x,e) = {}) <=> e < &0`,
3716   REWRITE_TAC[EXTENSION; IN_CBALL; NOT_IN_EMPTY; REAL_NOT_LE] THEN
3717   MESON_TAC[DIST_POS_LE; DIST_REFL; REAL_LTE_TRANS]);;
3718
3719 let CBALL_EMPTY = prove
3720  (`!x e. e < &0 ==> cball(x,e) = {}`,
3721   REWRITE_TAC[CBALL_EQ_EMPTY]);;
3722
3723 let CBALL_EQ_SING = prove
3724  (`!x:real^N e. (cball(x,e) = {x}) <=> e = &0`,
3725   REPEAT GEN_TAC THEN REWRITE_TAC[EXTENSION; IN_CBALL; IN_SING] THEN
3726   EQ_TAC THENL [ALL_TAC; MESON_TAC[DIST_LE_0]] THEN
3727   DISCH_THEN(fun th -> MP_TAC(SPEC `x + (e / &2) % basis 1:real^N` th) THEN
3728                        MP_TAC(SPEC `x:real^N` th)) THEN
3729   REWRITE_TAC[dist; VECTOR_ARITH `x - (x + e):real^N = --e`;
3730               VECTOR_ARITH `x + e = x <=> e:real^N = vec 0`] THEN
3731   REWRITE_TAC[NORM_NEG; NORM_MUL; VECTOR_MUL_EQ_0; NORM_0; VECTOR_SUB_REFL] THEN
3732   SIMP_TAC[NORM_BASIS; BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1] THEN
3733   REAL_ARITH_TAC);;
3734
3735 let CBALL_SING = prove
3736  (`!x e. e = &0 ==> cball(x,e) = {x}`,
3737   REWRITE_TAC[CBALL_EQ_SING]);;
3738
3739 let SPHERE_SING = prove
3740  (`!x e. e = &0 ==> sphere(x,e) = {x}`,
3741   SIMP_TAC[sphere; DIST_EQ_0; SING_GSPEC]);;
3742
3743 let SPHERE_EQ_SING = prove
3744  (`!a:real^N r x. sphere(a,r) = {x} <=> x = a /\ r = &0`,
3745   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[SPHERE_SING] THEN
3746   ASM_CASES_TAC `r < &0` THEN ASM_SIMP_TAC[SPHERE_EMPTY; NOT_INSERT_EMPTY] THEN
3747   ASM_CASES_TAC `r = &0` THEN ASM_SIMP_TAC[SPHERE_SING] THENL
3748    [ASM SET_TAC[]; ALL_TAC] THEN
3749   MATCH_MP_TAC(SET_RULE
3750    `!y. (x IN s ==> y IN s /\ ~(y = x)) ==> ~(s = {x})`) THEN
3751   EXISTS_TAC `a - (x - a):real^N` THEN REWRITE_TAC[IN_SPHERE] THEN
3752   REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC NORM_ARITH);;
3753
3754 (* ------------------------------------------------------------------------- *)
3755 (* For points in the interior, localization of limits makes no difference.   *)
3756 (* ------------------------------------------------------------------------- *)
3757
3758 let EVENTUALLY_WITHIN_INTERIOR = prove
3759  (`!p s x.
3760         x IN interior s
3761         ==> (eventually p (at x within s) <=> eventually p (at x))`,
3762   REWRITE_TAC[EVENTUALLY_WITHIN; EVENTUALLY_AT; IN_INTERIOR] THEN
3763   REPEAT GEN_TAC THEN SIMP_TAC[SUBSET; IN_BALL; LEFT_IMP_FORALL_THM] THEN
3764   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
3765   EQ_TAC THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
3766   EXISTS_TAC `min (d:real) e` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
3767   ASM_MESON_TAC[DIST_SYM]);;
3768
3769 let LIM_WITHIN_INTERIOR = prove
3770  (`!f l s x.
3771         x IN interior s
3772         ==> ((f --> l) (at x within s) <=> (f --> l) (at x))`,
3773   SIMP_TAC[tendsto; EVENTUALLY_WITHIN_INTERIOR]);;
3774
3775 let NETLIMIT_WITHIN_INTERIOR = prove
3776  (`!s x:real^N. x IN interior s ==> netlimit(at x within s) = x`,
3777   REPEAT STRIP_TAC THEN MATCH_MP_TAC NETLIMIT_WITHIN THEN
3778   REWRITE_TAC[TRIVIAL_LIMIT_WITHIN] THEN
3779   FIRST_ASSUM(MP_TAC o MATCH_MP(REWRITE_RULE[OPEN_CONTAINS_BALL]
3780    (SPEC_ALL OPEN_INTERIOR))) THEN
3781   ASM_MESON_TAC[LIMPT_SUBSET; LIMPT_BALL; CENTRE_IN_CBALL; REAL_LT_IMP_LE;
3782                 SUBSET_TRANS; INTERIOR_SUBSET]);;
3783
3784 (* ------------------------------------------------------------------------- *)
3785 (* A non-singleton connected set is perfect (i.e. has no isolated points).   *)
3786 (* ------------------------------------------------------------------------- *)
3787
3788 let CONNECTED_IMP_PERFECT = prove
3789  (`!s x:real^N.
3790         connected s /\ ~(?a. s = {a}) /\ x IN s ==> x limit_point_of s`,
3791   REPEAT STRIP_TAC THEN REWRITE_TAC[limit_point_of] THEN
3792   X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
3793   MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
3794   FIRST_ASSUM(MP_TAC o SPEC `x:real^N` o GEN_REWRITE_RULE I
3795    [OPEN_CONTAINS_CBALL]) THEN
3796   ASM_REWRITE_TAC[] THEN
3797   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
3798   FIRST_X_ASSUM(MP_TAC o SPEC `{x:real^N}` o
3799     GEN_REWRITE_RULE I [CONNECTED_CLOPEN]) THEN
3800   REWRITE_TAC[NOT_IMP] THEN REPEAT CONJ_TAC THENL
3801    [REWRITE_TAC[OPEN_IN_OPEN] THEN EXISTS_TAC `t:real^N->bool` THEN
3802     ASM SET_TAC[];
3803     REWRITE_TAC[CLOSED_IN_CLOSED] THEN
3804     EXISTS_TAC `cball(x:real^N,e)` THEN REWRITE_TAC[CLOSED_CBALL] THEN
3805     REWRITE_TAC[EXTENSION; IN_INTER; IN_SING] THEN
3806     ASM_MESON_TAC[CENTRE_IN_CBALL; SUBSET; REAL_LT_IMP_LE];
3807     ASM SET_TAC[]]);;
3808
3809 let CONNECTED_IMP_PERFECT_CLOSED = prove
3810  (`!s x. connected s /\ closed s /\ ~(?a. s = {a})
3811          ==> (x limit_point_of s <=> x IN s)`,
3812   MESON_TAC[CONNECTED_IMP_PERFECT; CLOSED_LIMPT]);;
3813
3814 (* ------------------------------------------------------------------------- *)
3815 (* Boundedness.                                                              *)
3816 (* ------------------------------------------------------------------------- *)
3817
3818 let bounded = new_definition
3819   `bounded s <=> ?a. !x:real^N. x IN s ==> norm(x) <= a`;;
3820
3821 let BOUNDED_EMPTY = prove
3822  (`bounded {}`,
3823   REWRITE_TAC[bounded; NOT_IN_EMPTY]);;
3824
3825 let BOUNDED_SUBSET = prove
3826  (`!s t. bounded t /\ s SUBSET t ==> bounded s`,
3827   MESON_TAC[bounded; SUBSET]);;
3828
3829 let BOUNDED_INTERIOR = prove
3830  (`!s:real^N->bool. bounded s ==> bounded(interior s)`,
3831   MESON_TAC[BOUNDED_SUBSET; INTERIOR_SUBSET]);;
3832
3833 let BOUNDED_CLOSURE = prove
3834  (`!s:real^N->bool. bounded s ==> bounded(closure s)`,
3835   REWRITE_TAC[bounded; CLOSURE_SEQUENTIAL] THEN
3836   GEN_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
3837   MESON_TAC[REWRITE_RULE[eventually] LIM_NORM_UBOUND;
3838             TRIVIAL_LIMIT_SEQUENTIALLY; trivial_limit]);;
3839
3840 let BOUNDED_CLOSURE_EQ = prove
3841  (`!s:real^N->bool. bounded(closure s) <=> bounded s`,
3842   GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[BOUNDED_CLOSURE] THEN
3843   MESON_TAC[BOUNDED_SUBSET; CLOSURE_SUBSET]);;
3844
3845 let BOUNDED_CBALL = prove
3846  (`!x:real^N e. bounded(cball(x,e))`,
3847   REPEAT GEN_TAC THEN REWRITE_TAC[bounded] THEN
3848   EXISTS_TAC `norm(x:real^N) + e` THEN REWRITE_TAC[IN_CBALL; dist] THEN
3849   NORM_ARITH_TAC);;
3850
3851 let BOUNDED_BALL = prove
3852  (`!x e. bounded(ball(x,e))`,
3853   MESON_TAC[BALL_SUBSET_CBALL; BOUNDED_CBALL; BOUNDED_SUBSET]);;
3854
3855 let FINITE_IMP_BOUNDED = prove
3856  (`!s:real^N->bool. FINITE s ==> bounded s`,
3857   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN REWRITE_TAC[BOUNDED_EMPTY] THEN
3858   REWRITE_TAC[bounded; IN_INSERT] THEN X_GEN_TAC `x:real^N` THEN GEN_TAC THEN
3859   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `B:real`) STRIP_ASSUME_TAC) THEN
3860   EXISTS_TAC `norm(x:real^N) + abs B` THEN REPEAT STRIP_TAC THEN
3861   ASM_MESON_TAC[NORM_POS_LE; REAL_ARITH
3862    `(y <= b /\ &0 <= x ==> y <= x + abs b) /\ x <= x + abs b`]);;
3863
3864 let BOUNDED_UNION = prove
3865  (`!s t. bounded (s UNION t) <=> bounded s /\ bounded t`,
3866   REWRITE_TAC[bounded; IN_UNION] THEN MESON_TAC[REAL_LE_MAX]);;
3867
3868 let BOUNDED_UNIONS = prove
3869  (`!f. FINITE f /\ (!s. s IN f ==> bounded s) ==> bounded(UNIONS f)`,
3870   REWRITE_TAC[IMP_CONJ] THEN
3871   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
3872   REWRITE_TAC[UNIONS_0; BOUNDED_EMPTY; IN_INSERT; UNIONS_INSERT] THEN
3873   MESON_TAC[BOUNDED_UNION]);;
3874
3875 let BOUNDED_POS = prove
3876  (`!s. bounded s <=> ?b. &0 < b /\ !x. x IN s ==> norm(x) <= b`,
3877   REWRITE_TAC[bounded] THEN
3878   MESON_TAC[REAL_ARITH `&0 < &1 + abs(y) /\ (x <= y ==> x <= &1 + abs(y))`]);;
3879
3880 let BOUNDED_POS_LT = prove
3881  (`!s. bounded s <=> ?b. &0 < b /\ !x. x IN s ==> norm(x) < b`,
3882   REWRITE_TAC[bounded] THEN
3883   MESON_TAC[REAL_LT_IMP_LE;
3884             REAL_ARITH `&0 < &1 + abs(y) /\ (x <= y ==> x < &1 + abs(y))`]);;
3885
3886 let BOUNDED_INTER = prove
3887  (`!s t. bounded s \/ bounded t ==> bounded (s INTER t)`,
3888   MESON_TAC[BOUNDED_SUBSET; INTER_SUBSET]);;
3889
3890 let BOUNDED_DIFF = prove
3891  (`!s t. bounded s ==> bounded (s DIFF t)`,
3892   MESON_TAC[BOUNDED_SUBSET; SUBSET_DIFF]);;
3893
3894 let BOUNDED_INSERT = prove
3895  (`!x s. bounded(x INSERT s) <=> bounded s`,
3896   ONCE_REWRITE_TAC[SET_RULE `x INSERT s = {x} UNION s`] THEN
3897   SIMP_TAC[BOUNDED_UNION; FINITE_IMP_BOUNDED; FINITE_RULES]);;
3898
3899 let BOUNDED_SING = prove
3900  (`!a. bounded {a}`,
3901   REWRITE_TAC[BOUNDED_INSERT; BOUNDED_EMPTY]);;
3902
3903 let BOUNDED_INTERS = prove
3904  (`!f:(real^N->bool)->bool.
3905         (?s:real^N->bool. s IN f /\ bounded s) ==> bounded(INTERS f)`,
3906   REWRITE_TAC[LEFT_IMP_EXISTS_THM; IMP_CONJ] THEN REPEAT GEN_TAC THEN
3907   DISCH_TAC THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] BOUNDED_SUBSET) THEN
3908   ASM SET_TAC[]);;
3909
3910 let NOT_BOUNDED_UNIV = prove
3911  (`~(bounded (:real^N))`,
3912   REWRITE_TAC[BOUNDED_POS; NOT_FORALL_THM; NOT_EXISTS_THM; IN_UNIV;
3913               DE_MORGAN_THM; REAL_NOT_LE] THEN
3914   X_GEN_TAC `B:real` THEN ASM_CASES_TAC `&0 < B` THEN ASM_REWRITE_TAC[] THEN
3915   MP_TAC(SPEC `B + &1` VECTOR_CHOOSE_SIZE) THEN
3916   ASM_SIMP_TAC[REAL_ARITH `&0 < B ==> &0 <= B + &1`] THEN
3917   MATCH_MP_TAC MONO_EXISTS THEN REAL_ARITH_TAC);;
3918
3919 let COBOUNDED_IMP_UNBOUNDED = prove
3920  (`!s. bounded((:real^N) DIFF s) ==> ~bounded s`,
3921   GEN_TAC THEN REWRITE_TAC[TAUT `a ==> ~b <=> ~(a /\ b)`] THEN
3922   REWRITE_TAC[GSYM BOUNDED_UNION; SET_RULE `UNIV DIFF s UNION s = UNIV`] THEN
3923   REWRITE_TAC[NOT_BOUNDED_UNIV]);;
3924
3925 let BOUNDED_LINEAR_IMAGE = prove
3926  (`!f:real^M->real^N s. bounded s /\ linear f ==> bounded(IMAGE f s)`,
3927   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS] THEN
3928   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `B1:real`) MP_TAC) THEN
3929   DISCH_THEN(X_CHOOSE_TAC `B2:real` o MATCH_MP LINEAR_BOUNDED_POS) THEN
3930   EXISTS_TAC `B2 * B1` THEN ASM_SIMP_TAC[REAL_LT_MUL; FORALL_IN_IMAGE] THEN
3931   X_GEN_TAC `x:real^M` THEN STRIP_TAC THEN
3932   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `B2 * norm(x:real^M)` THEN
3933   ASM_SIMP_TAC[REAL_LE_LMUL_EQ]);;
3934
3935 let BOUNDED_LINEAR_IMAGE_EQ = prove
3936  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
3937          ==> (bounded (IMAGE f s) <=> bounded s)`,
3938   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE BOUNDED_LINEAR_IMAGE));;
3939
3940 add_linear_invariants [BOUNDED_LINEAR_IMAGE_EQ];;
3941
3942 let BOUNDED_SCALING = prove
3943  (`!c s. bounded s ==> bounded (IMAGE (\x. c % x) s)`,
3944   REPEAT STRIP_TAC THEN MATCH_MP_TAC BOUNDED_LINEAR_IMAGE THEN
3945   ASM_SIMP_TAC[LINEAR_COMPOSE_CMUL; LINEAR_ID]);;
3946
3947 let BOUNDED_NEGATIONS = prove
3948  (`!s. bounded s ==> bounded (IMAGE (--) s)`,
3949   GEN_TAC THEN
3950   DISCH_THEN(MP_TAC o SPEC `-- &1` o MATCH_MP BOUNDED_SCALING) THEN
3951   REWRITE_TAC[bounded; IN_IMAGE; VECTOR_MUL_LNEG; VECTOR_MUL_LID]);;
3952
3953 let BOUNDED_TRANSLATION = prove
3954  (`!a:real^N s. bounded s ==> bounded (IMAGE (\x. a + x) s)`,
3955   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE] THEN
3956   DISCH_THEN(X_CHOOSE_TAC `B:real`) THEN
3957   EXISTS_TAC `B + norm(a:real^N)` THEN POP_ASSUM MP_TAC THEN
3958   MATCH_MP_TAC MONO_AND THEN CONJ_TAC THENL [NORM_ARITH_TAC; ALL_TAC] THEN
3959   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
3960   REWRITE_TAC[] THEN NORM_ARITH_TAC);;
3961
3962 let BOUNDED_TRANSLATION_EQ = prove
3963  (`!a s. bounded (IMAGE (\x:real^N. a + x) s) <=> bounded s`,
3964   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[BOUNDED_TRANSLATION] THEN
3965   DISCH_THEN(MP_TAC o SPEC `--a:real^N` o MATCH_MP BOUNDED_TRANSLATION) THEN
3966   REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID;
3967               VECTOR_ARITH `--a + a + x:real^N = x`]);;
3968
3969 add_translation_invariants [BOUNDED_TRANSLATION_EQ];;
3970
3971 let BOUNDED_DIFFS = prove
3972  (`!s t:real^N->bool.
3973         bounded s /\ bounded t ==> bounded {x - y | x IN s /\ y IN t}`,
3974   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS] THEN
3975   DISCH_THEN(CONJUNCTS_THEN2
3976    (X_CHOOSE_TAC `B:real`) (X_CHOOSE_TAC `C:real`)) THEN
3977   EXISTS_TAC `B + C:real` THEN REWRITE_TAC[IN_ELIM_THM] THEN
3978   CONJ_TAC THENL [ASM_REAL_ARITH_TAC; REPEAT STRIP_TAC] THEN
3979   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(NORM_ARITH
3980    `norm x <= a /\ norm y <= b ==> norm(x - y) <= a + b`) THEN
3981   ASM_SIMP_TAC[]);;
3982
3983 let BOUNDED_SUMS = prove
3984  (`!s t:real^N->bool.
3985         bounded s /\ bounded t ==> bounded {x + y | x IN s /\ y IN t}`,
3986   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS] THEN
3987   DISCH_THEN(CONJUNCTS_THEN2
3988    (X_CHOOSE_TAC `B:real`) (X_CHOOSE_TAC `C:real`)) THEN
3989   EXISTS_TAC `B + C:real` THEN REWRITE_TAC[IN_ELIM_THM] THEN
3990   CONJ_TAC THENL [ASM_REAL_ARITH_TAC; REPEAT STRIP_TAC] THEN
3991   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(NORM_ARITH
3992    `norm x <= a /\ norm y <= b ==> norm(x + y) <= a + b`) THEN
3993   ASM_SIMP_TAC[]);;
3994
3995 let BOUNDED_SUMS_IMAGE = prove
3996  (`!f g t. bounded {f x | x IN t} /\ bounded {g x | x IN t}
3997            ==> bounded {f x + g x | x IN t}`,
3998   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP BOUNDED_SUMS) THEN
3999   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] BOUNDED_SUBSET) THEN
4000   SET_TAC[]);;
4001
4002 let BOUNDED_SUMS_IMAGES = prove
4003  (`!f:A->B->real^N t s.
4004         FINITE s /\
4005         (!a. a IN s ==> bounded {f x a | x IN t})
4006         ==> bounded { vsum s (f x) | x IN t}`,
4007   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
4008   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
4009   SIMP_TAC[VSUM_CLAUSES] THEN CONJ_TAC THENL
4010    [DISCH_THEN(K ALL_TAC) THEN MATCH_MP_TAC BOUNDED_SUBSET THEN
4011     EXISTS_TAC `{vec 0:real^N}` THEN
4012     SIMP_TAC[FINITE_IMP_BOUNDED; FINITE_RULES] THEN SET_TAC[];
4013     ALL_TAC] THEN
4014   REPEAT STRIP_TAC THEN MATCH_MP_TAC BOUNDED_SUMS_IMAGE THEN
4015   ASM_SIMP_TAC[IN_INSERT]);;
4016
4017 let BOUNDED_SUBSET_BALL = prove
4018  (`!s x:real^N. bounded(s) ==> ?r. &0 < r /\ s SUBSET ball(x,r)`,
4019   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS] THEN
4020   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
4021   EXISTS_TAC `&2 * B + norm(x:real^N)` THEN
4022   ASM_SIMP_TAC[NORM_POS_LE; REAL_ARITH
4023     `&0 < B /\ &0 <= x ==> &0 < &2 * B + x`] THEN
4024   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
4025   FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[IN_BALL] THEN
4026   UNDISCH_TAC `&0 < B` THEN NORM_ARITH_TAC);;
4027
4028 let BOUNDED_SUBSET_CBALL = prove
4029  (`!s x:real^N. bounded(s) ==> ?r. &0 < r /\ s SUBSET cball(x,r)`,
4030   MESON_TAC[BOUNDED_SUBSET_BALL; SUBSET_TRANS; BALL_SUBSET_CBALL]);;
4031
4032 let UNBOUNDED_INTER_COBOUNDED = prove
4033  (`!s t. ~bounded s /\ bounded((:real^N) DIFF t) ==> ~(s INTER t = {})`,
4034   REWRITE_TAC[SET_RULE `s INTER t = {} <=> s SUBSET (:real^N) DIFF t`] THEN
4035   MESON_TAC[BOUNDED_SUBSET]);;
4036
4037 let COBOUNDED_INTER_UNBOUNDED = prove
4038  (`!s t. bounded((:real^N) DIFF s) /\ ~bounded t ==> ~(s INTER t = {})`,
4039   REWRITE_TAC[SET_RULE `s INTER t = {} <=> t SUBSET (:real^N) DIFF s`] THEN
4040   MESON_TAC[BOUNDED_SUBSET]);;
4041
4042 let SUBSPACE_BOUNDED_EQ_TRIVIAL = prove
4043  (`!s:real^N->bool. subspace s ==> (bounded s <=> s = {vec 0})`,
4044   REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[BOUNDED_SING] THEN
4045   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4046   DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
4047    `~(s = {a}) ==> a IN s ==> ?b. b IN s /\ ~(b = a)`)) THEN
4048   ASM_SIMP_TAC[SUBSPACE_0] THEN
4049   DISCH_THEN(X_CHOOSE_THEN `v:real^N` STRIP_ASSUME_TAC) THEN
4050   REWRITE_TAC[bounded; NOT_EXISTS_THM] THEN X_GEN_TAC `B:real` THEN
4051   DISCH_THEN(MP_TAC o SPEC `(B + &1) / norm v % v:real^N`) THEN
4052   ASM_SIMP_TAC[SUBSPACE_MUL; NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
4053   ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN REAL_ARITH_TAC);;
4054
4055 let BOUNDED_COMPONENTWISE = prove
4056  (`!s:real^N->bool.
4057         bounded s <=> !i. 1 <= i /\ i <= dimindex(:N)
4058                           ==> bounded (IMAGE (\x. lift(x$i)) s)`,
4059   GEN_TAC THEN REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE; NORM_LIFT] THEN
4060   EQ_TAC THENL [ASM_MESON_TAC[COMPONENT_LE_NORM; REAL_LE_TRANS]; ALL_TAC] THEN
4061   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4062   SIMP_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `b:num->real` THEN
4063   DISCH_TAC THEN EXISTS_TAC `sum(1..dimindex(:N)) b` THEN CONJ_TAC THENL
4064    [MATCH_MP_TAC REAL_LET_TRANS THEN
4065     EXISTS_TAC `sum(1..dimindex(:N)) (\i. &0)` THEN
4066     SIMP_TAC[SUM_POS_LE_NUMSEG; REAL_POS] THEN
4067     MATCH_MP_TAC SUM_LT_ALL THEN
4068     ASM_SIMP_TAC[IN_NUMSEG; FINITE_NUMSEG; NUMSEG_EMPTY] THEN
4069     REWRITE_TAC[NOT_LT; DIMINDEX_GE_1];
4070     REPEAT STRIP_TAC THEN
4071     W(MP_TAC o PART_MATCH lhand NORM_LE_L1 o lhand o snd) THEN
4072     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
4073     MATCH_MP_TAC SUM_LE THEN ASM_SIMP_TAC[IN_NUMSEG; FINITE_NUMSEG]]);;
4074
4075 (* ------------------------------------------------------------------------- *)
4076 (* Some theorems on sups and infs using the notion "bounded".                *)
4077 (* ------------------------------------------------------------------------- *)
4078
4079 let BOUNDED_LIFT = prove
4080  (`!s. bounded(IMAGE lift s) <=>  ?a. !x. x IN s ==> abs(x) <= a`,
4081   REWRITE_TAC[bounded; FORALL_LIFT; NORM_LIFT; LIFT_IN_IMAGE_LIFT]);;
4082
4083 let BOUNDED_HAS_SUP = prove
4084  (`!s. bounded(IMAGE lift s) /\ ~(s = {})
4085        ==> (!x. x IN s ==> x <= sup s) /\
4086            (!b. (!x. x IN s ==> x <= b) ==> sup s <= b)`,
4087   REWRITE_TAC[BOUNDED_LIFT; IMAGE_EQ_EMPTY] THEN
4088   MESON_TAC[SUP; REAL_ARITH `abs(x) <= a ==> x <= a`]);;
4089
4090 let SUP_INSERT = prove
4091  (`!x s. bounded (IMAGE lift s)
4092          ==> sup(x INSERT s) = if s = {} then x else max x (sup s)`,
4093   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_SUP_UNIQUE THEN
4094   COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_SING] THENL
4095    [MESON_TAC[REAL_LE_REFL]; ALL_TAC] THEN
4096   REWRITE_TAC[REAL_LE_MAX; REAL_LT_MAX; IN_INSERT] THEN
4097   MP_TAC(ISPEC `s:real->bool` BOUNDED_HAS_SUP) THEN ASM_REWRITE_TAC[] THEN
4098   REPEAT STRIP_TAC THEN ASM_MESON_TAC[REAL_LE_REFL; REAL_NOT_LT]);;
4099
4100 let BOUNDED_HAS_INF = prove
4101  (`!s. bounded(IMAGE lift s) /\ ~(s = {})
4102        ==> (!x. x IN s ==> inf s <= x) /\
4103            (!b. (!x. x IN s ==> b <= x) ==> b <= inf s)`,
4104   REWRITE_TAC[BOUNDED_LIFT; IMAGE_EQ_EMPTY] THEN
4105   MESON_TAC[INF; REAL_ARITH `abs(x) <= a ==> --a <= x`]);;
4106
4107 let INF_INSERT = prove
4108  (`!x s. bounded (IMAGE lift s)
4109          ==> inf(x INSERT s) = if s = {} then x else min x (inf s)`,
4110   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INF_UNIQUE THEN
4111   COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_SING] THENL
4112    [MESON_TAC[REAL_LE_REFL]; ALL_TAC] THEN
4113   REWRITE_TAC[REAL_MIN_LE; REAL_MIN_LT; IN_INSERT] THEN
4114   MP_TAC(ISPEC `s:real->bool` BOUNDED_HAS_INF) THEN ASM_REWRITE_TAC[] THEN
4115   REPEAT STRIP_TAC THEN ASM_MESON_TAC[REAL_LE_REFL; REAL_NOT_LT]);;
4116
4117 (* ------------------------------------------------------------------------- *)
4118 (* Subset and overlapping relations on balls.                                *)
4119 (* ------------------------------------------------------------------------- *)
4120
4121 let SUBSET_BALLS = prove
4122  (`(!a a':real^N r r'.
4123       ball(a,r) SUBSET ball(a',r') <=> dist(a,a') + r <= r' \/ r <= &0) /\
4124    (!a a':real^N r r'.
4125       ball(a,r) SUBSET cball(a',r') <=> dist(a,a') + r <= r' \/ r <= &0) /\
4126    (!a a':real^N r r'.
4127       cball(a,r) SUBSET ball(a',r') <=> dist(a,a') + r < r' \/ r < &0) /\
4128    (!a a':real^N r r'.
4129       cball(a,r) SUBSET cball(a',r') <=> dist(a,a') + r <= r' \/ r < &0)`,
4130   let lemma = prove
4131    (`(!a':real^N r r'.
4132        cball(a,r) SUBSET cball(a',r') <=> dist(a,a') + r <= r' \/ r < &0) /\
4133      (!a':real^N r r'.
4134        cball(a,r) SUBSET ball(a',r') <=> dist(a,a') + r < r' \/ r < &0)`,
4135     CONJ_TAC THEN
4136     (GEOM_ORIGIN_TAC `a':real^N` THEN
4137     REPEAT GEN_TAC THEN REWRITE_TAC[SUBSET; IN_CBALL; IN_BALL] THEN
4138     EQ_TAC THENL [REWRITE_TAC[DIST_0]; NORM_ARITH_TAC] THEN
4139     DISJ_CASES_TAC(REAL_ARITH `r < &0 \/ &0 <= r`) THEN
4140     ASM_REWRITE_TAC[] THEN DISCH_TAC THEN DISJ1_TAC THEN
4141     ASM_CASES_TAC `a:real^N = vec 0` THENL
4142      [FIRST_X_ASSUM(MP_TAC o SPEC `r % basis 1:real^N`) THEN
4143       ASM_SIMP_TAC[DIST_0; NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL];
4144       FIRST_X_ASSUM(MP_TAC o SPEC `(&1 + r / norm(a)) % a:real^N`) THEN
4145       SIMP_TAC[dist; VECTOR_ARITH `a - (&1 + x) % a:real^N = --(x % a)`] THEN
4146       ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; NORM_NEG; REAL_POS;
4147                    REAL_LE_DIV; NORM_POS_LE; REAL_ADD_RDISTRIB; REAL_DIV_RMUL;
4148                NORM_EQ_0; REAL_ARITH `&0 <= x ==> abs(&1 + x) = &1 + x`]] THEN
4149     UNDISCH_TAC `&0 <= r` THEN NORM_ARITH_TAC))
4150   and tac = DISCH_THEN(MP_TAC o MATCH_MP SUBSET_CLOSURE) THEN
4151             ASM_SIMP_TAC[CLOSED_CBALL; CLOSURE_CLOSED; CLOSURE_BALL] in
4152   REWRITE_TAC[AND_FORALL_THM] THEN GEOM_ORIGIN_TAC `a':real^N` THEN
4153   REPEAT STRIP_TAC THEN
4154   (EQ_TAC THENL
4155     [ALL_TAC; REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL] THEN NORM_ARITH_TAC]) THEN
4156   MATCH_MP_TAC(SET_RULE
4157    `(s = {} <=> q) /\ (s SUBSET t /\ ~(s = {}) /\ ~(t = {}) ==> p)
4158     ==> s SUBSET t ==> p \/ q`) THEN
4159   REWRITE_TAC[BALL_EQ_EMPTY; CBALL_EQ_EMPTY; REAL_NOT_LE; REAL_NOT_LT] THEN
4160   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THENL
4161    [tac; tac; ALL_TAC; ALL_TAC] THEN REWRITE_TAC[lemma] THEN
4162   REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
4163
4164 let INTER_BALLS_EQ_EMPTY = prove
4165  (`(!a b:real^N r s. ball(a,r) INTER ball(b,s) = {} <=>
4166                      r <= &0 \/ s <= &0 \/ r + s <= dist(a,b)) /\
4167    (!a b:real^N r s. ball(a,r) INTER cball(b,s) = {} <=>
4168                      r <= &0 \/ s < &0 \/ r + s <= dist(a,b)) /\
4169    (!a b:real^N r s. cball(a,r) INTER ball(b,s) = {} <=>
4170                      r < &0 \/ s <= &0 \/ r + s <= dist(a,b)) /\
4171    (!a b:real^N r s. cball(a,r) INTER cball(b,s) = {} <=>
4172                      r < &0 \/ s < &0 \/ r + s < dist(a,b))`,
4173   REPEAT STRIP_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN
4174   GEOM_BASIS_MULTIPLE_TAC 1 `b:real^N` THEN REPEAT STRIP_TAC THEN
4175   REWRITE_TAC[EXTENSION; NOT_IN_EMPTY; IN_INTER; IN_CBALL; IN_BALL] THEN
4176   (EQ_TAC THENL
4177     [ALL_TAC;
4178      SPEC_TAC(`b % basis 1:real^N`,`v:real^N`) THEN CONV_TAC NORM_ARITH]) THEN
4179   DISCH_THEN(MP_TAC o GEN `c:real` o SPEC `c % basis 1:real^N`) THEN
4180   SIMP_TAC[NORM_MUL; NORM_BASIS; LE_REFL; DIMINDEX_GE_1; dist; NORM_NEG;
4181            VECTOR_SUB_LZERO; GSYM VECTOR_SUB_RDISTRIB; REAL_MUL_RID] THEN
4182   ASM_REWRITE_TAC[real_abs] THEN REWRITE_TAC[GSYM real_abs] THEN
4183   DISCH_THEN(fun th ->
4184     MP_TAC(SPEC `min b r:real` th) THEN
4185     MP_TAC(SPEC `max (&0) (b - s:real)` th) THEN
4186     MP_TAC(SPEC `(r + (b - s)) / &2` th)) THEN
4187   ASM_REAL_ARITH_TAC);;
4188
4189 (* ------------------------------------------------------------------------- *)
4190 (* Every closed set is a G_Delta.                                            *)
4191 (* ------------------------------------------------------------------------- *)
4192
4193 let CLOSED_AS_GDELTA = prove
4194  (`!s:real^N->bool.
4195         closed s
4196         ==> ?g. COUNTABLE g /\
4197                 (!u. u IN g ==> open u) /\
4198                 INTERS g = s`,
4199   REPEAT STRIP_TAC THEN EXISTS_TAC
4200    `{ UNIONS { ball(x:real^N,inv(&n + &1)) | x IN s} | n IN (:num)}` THEN
4201   SIMP_TAC[SIMPLE_IMAGE; COUNTABLE_IMAGE; NUM_COUNTABLE] THEN
4202   SIMP_TAC[FORALL_IN_IMAGE; OPEN_UNIONS; OPEN_BALL] THEN
4203   MATCH_MP_TAC(SET_RULE
4204    `closure s = s /\ s SUBSET t /\ t SUBSET closure s
4205     ==> t = s`) THEN
4206   ASM_REWRITE_TAC[CLOSURE_EQ] THEN CONJ_TAC THENL
4207    [REWRITE_TAC[SUBSET_INTERS; FORALL_IN_IMAGE; IN_UNIV] THEN
4208     X_GEN_TAC `n:num` THEN REWRITE_TAC[UNIONS_IMAGE; SUBSET; IN_ELIM_THM] THEN
4209     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN EXISTS_TAC `x:real^N` THEN
4210     ASM_REWRITE_TAC[CENTRE_IN_BALL; REAL_LT_INV_EQ] THEN REAL_ARITH_TAC;
4211     REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE; INTERS_IMAGE; IN_UNIV] THEN
4212     X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_ELIM_THM; UNIONS_IMAGE] THEN
4213     DISCH_TAC THEN X_GEN_TAC `e:real` THEN  DISCH_TAC THEN
4214     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [REAL_ARCH_INV]) THEN
4215     DISCH_THEN(X_CHOOSE_THEN `n:num` STRIP_ASSUME_TAC) THEN
4216     FIRST_X_ASSUM(MP_TAC o SPEC `n:num`) THEN REWRITE_TAC[IN_BALL] THEN
4217     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real^N` THEN
4218     MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
4219     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LT_TRANS) THEN
4220     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
4221         REAL_LT_TRANS)) THEN
4222     MATCH_MP_TAC REAL_LT_INV2 THEN
4223     REWRITE_TAC[REAL_OF_NUM_ADD; REAL_OF_NUM_LT] THEN ASM_ARITH_TAC]);;
4224
4225 (* ------------------------------------------------------------------------- *)
4226 (* Compactness (the definition is the one based on convegent subsequences).  *)
4227 (* ------------------------------------------------------------------------- *)
4228
4229 let compact = new_definition
4230   `compact s <=>
4231         !f:num->real^N.
4232             (!n. f(n) IN s)
4233             ==> ?l r. l IN s /\ (!m n:num. m < n ==> r(m) < r(n)) /\
4234                       ((f o r) --> l) sequentially`;;
4235
4236 let MONOTONE_BIGGER = prove
4237  (`!r. (!m n. m < n ==> r(m) < r(n)) ==> !n:num. n <= r(n)`,
4238   GEN_TAC THEN DISCH_TAC THEN INDUCT_TAC THEN
4239   ASM_MESON_TAC[LE_0; ARITH_RULE `n <= m /\ m < p ==> SUC n <= p`; LT]);;
4240
4241 let LIM_SUBSEQUENCE = prove
4242  (`!s r l. (!m n. m < n ==> r(m) < r(n)) /\ (s --> l) sequentially
4243            ==> (s o r --> l) sequentially`,
4244   REWRITE_TAC[LIM_SEQUENTIALLY; o_THM] THEN
4245   MESON_TAC[MONOTONE_BIGGER; LE_TRANS]);;
4246
4247 let MONOTONE_SUBSEQUENCE = prove
4248  (`!s:num->real. ?r:num->num.
4249            (!m n. m < n ==> r(m) < r(n)) /\
4250            ((!m n. m <= n ==> s(r(m)) <= s(r(n))) \/
4251             (!m n. m <= n ==> s(r(n)) <= s(r(m))))`,
4252   GEN_TAC THEN
4253   ASM_CASES_TAC `!n:num. ?p. n < p /\ !m. p <= m ==> s(m) <= s(p)` THEN
4254   POP_ASSUM MP_TAC THEN
4255   REWRITE_TAC[NOT_FORALL_THM; NOT_EXISTS_THM; NOT_IMP; DE_MORGAN_THM] THEN
4256   REWRITE_TAC[RIGHT_OR_EXISTS_THM; SKOLEM_THM; REAL_NOT_LE; REAL_NOT_LT] THENL
4257    [ABBREV_TAC `N = 0`; DISCH_THEN(X_CHOOSE_THEN `N:num` MP_TAC)] THEN
4258   DISCH_THEN(X_CHOOSE_THEN `next:num->num` STRIP_ASSUME_TAC) THEN
4259   (MP_TAC o prove_recursive_functions_exist num_RECURSION)
4260    `(r 0 = next(SUC N)) /\ (!n. r(SUC n) = next(r n))` THEN
4261   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN STRIP_TAC THENL
4262    [SUBGOAL_THEN `!m:num n:num. r n <= m ==> s(m) <= s(r n):real`
4263     ASSUME_TAC THEN TRY CONJ_TAC THEN TRY DISJ2_TAC THEN
4264     GEN_TAC THEN INDUCT_TAC THEN ASM_REWRITE_TAC[LT; LE] THEN
4265     ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_REFL; LT_IMP_LE; LT_TRANS];
4266     SUBGOAL_THEN `!n. N < (r:num->num) n` ASSUME_TAC THEN
4267     TRY(CONJ_TAC THENL [GEN_TAC; DISJ1_TAC THEN GEN_TAC]) THEN
4268     INDUCT_TAC THEN ASM_REWRITE_TAC[LT; LE] THEN
4269     TRY STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
4270     ASM_MESON_TAC[REAL_LT_REFL; LT_LE; LTE_TRANS; REAL_LE_REFL;
4271                   REAL_LT_LE; REAL_LE_TRANS; LT]]);;
4272
4273 let CONVERGENT_BOUNDED_INCREASING = prove
4274  (`!s:num->real b. (!m n. m <= n ==> s m <= s n) /\ (!n. abs(s n) <= b)
4275                    ==> ?l. !e. &0 < e ==> ?N. !n. N <= n ==> abs(s n - l) < e`,
4276   REPEAT STRIP_TAC THEN
4277   MP_TAC(SPEC `\x. ?n. (s:num->real) n = x` REAL_COMPLETE) THEN
4278   REWRITE_TAC[] THEN ANTS_TAC THENL
4279    [ASM_MESON_TAC[REAL_ARITH `abs(x) <= b ==> x <= b`]; ALL_TAC] THEN
4280   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real` THEN STRIP_TAC THEN
4281   X_GEN_TAC `e:real` THEN STRIP_TAC THEN
4282   FIRST_X_ASSUM(MP_TAC o SPEC `l - e`) THEN
4283   ASM_MESON_TAC[REAL_ARITH `&0 < e ==> ~(l <= l - e)`;
4284       REAL_ARITH `x <= y /\ y <= l /\ ~(x <= l - e) ==> abs(y - l) < e`]);;
4285
4286 let CONVERGENT_BOUNDED_MONOTONE = prove
4287  (`!s:num->real b. (!n. abs(s n) <= b) /\
4288                    ((!m n. m <= n ==> s m <= s n) \/
4289                     (!m n. m <= n ==> s n <= s m))
4290                    ==> ?l. !e. &0 < e ==> ?N. !n. N <= n ==> abs(s n - l) < e`,
4291   REPEAT STRIP_TAC THENL
4292    [ASM_MESON_TAC[CONVERGENT_BOUNDED_INCREASING]; ALL_TAC] THEN
4293   MP_TAC(SPEC `\n. --((s:num->real) n)` CONVERGENT_BOUNDED_INCREASING) THEN
4294   ASM_REWRITE_TAC[REAL_LE_NEG2; REAL_ABS_NEG] THEN
4295   ASM_MESON_TAC[REAL_ARITH `abs(x - --l) = abs(--x - l)`]);;
4296
4297 let COMPACT_REAL_LEMMA = prove
4298  (`!s b. (!n:num. abs(s n) <= b)
4299          ==> ?l r. (!m n:num. m < n ==> r(m) < r(n)) /\
4300                    !e. &0 < e ==> ?N. !n. N <= n ==> abs(s(r n) - l) < e`,
4301   REPEAT GEN_TAC THEN DISCH_TAC THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
4302   MP_TAC(SPEC `s:num->real` MONOTONE_SUBSEQUENCE) THEN
4303   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN DISCH_TAC THEN ASM_SIMP_TAC[] THEN
4304   MATCH_MP_TAC CONVERGENT_BOUNDED_MONOTONE THEN ASM_MESON_TAC[]);;
4305
4306 let COMPACT_LEMMA = prove
4307  (`!s. bounded s /\ (!n. (x:num->real^N) n IN s)
4308        ==> !d. d <= dimindex(:N)
4309                ==> ?l:real^N r. (!m n. m < n ==> r m < (r:num->num) n) /\
4310                          !e. &0 < e
4311                              ==> ?N. !n i. 1 <= i /\ i <= d
4312                                            ==> N <= n
4313                                                ==> abs(x(r n)$i - l$i) < e`,
4314   GEN_TAC THEN REWRITE_TAC[bounded] THEN
4315   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `b:real`) ASSUME_TAC) THEN
4316   INDUCT_TAC THENL
4317    [REWRITE_TAC[ARITH_RULE `1 <= i /\ i <= 0 <=> F`; CONJ_ASSOC] THEN
4318     DISCH_TAC THEN EXISTS_TAC `\n:num. n` THEN REWRITE_TAC[];
4319     ALL_TAC] THEN
4320   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o check (is_imp o concl)) THEN
4321   ASM_SIMP_TAC[ARITH_RULE `SUC d <= n ==> d <= n`] THEN STRIP_TAC THEN
4322   MP_TAC(SPECL [`\n:num. (x:num->real^N) (r n) $ (SUC d)`; `b:real`]
4323          COMPACT_REAL_LEMMA) THEN
4324   REWRITE_TAC[] THEN ANTS_TAC THENL
4325    [ASM_MESON_TAC[REAL_LE_TRANS; COMPONENT_LE_NORM; ARITH_RULE `1 <= SUC n`];
4326     ALL_TAC] THEN
4327   DISCH_THEN(X_CHOOSE_THEN `y:real` (X_CHOOSE_THEN `s:num->num`
4328         STRIP_ASSUME_TAC)) THEN
4329   MAP_EVERY EXISTS_TAC
4330    [`(lambda k. if k = SUC d then y else (l:real^N)$k):real^N`;
4331     `(r:num->num) o (s:num->num)`] THEN
4332   ASM_SIMP_TAC[o_THM] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
4333   REPEAT(FIRST_ASSUM(C UNDISCH_THEN (MP_TAC o SPEC `e:real`) o concl)) THEN
4334   ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_TAC `N1:num`) THEN
4335   DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN EXISTS_TAC `N1 + N2:num` THEN
4336   FIRST_ASSUM(fun th -> SIMP_TAC[LAMBDA_BETA; MATCH_MP(ARITH_RULE
4337    `SUC d <= n ==> !i. 1 <= i /\ i <= SUC d ==> 1 <= i /\ i <= n`) th]) THEN
4338   REWRITE_TAC[LE] THEN REPEAT STRIP_TAC THEN
4339   ASM_REWRITE_TAC[] THEN TRY COND_CASES_TAC THEN
4340   ASM_MESON_TAC[MONOTONE_BIGGER; LE_TRANS;
4341     ARITH_RULE `N1 + N2 <= n ==> N2 <= n:num /\ N1 <= n`;
4342     ARITH_RULE `1 <= i /\ i <= d /\ SUC d <= n
4343                 ==> ~(i = SUC d) /\ 1 <= SUC d /\ d <= n /\ i <= n`]);;
4344
4345 let BOUNDED_CLOSED_IMP_COMPACT = prove
4346  (`!s:real^N->bool. bounded s /\ closed s ==> compact s`,
4347   REPEAT STRIP_TAC THEN REWRITE_TAC[compact] THEN
4348   X_GEN_TAC `x:num->real^N` THEN DISCH_TAC THEN
4349   MP_TAC(ISPEC `s:real^N->bool` COMPACT_LEMMA) THEN
4350   ASM_REWRITE_TAC[] THEN
4351   DISCH_THEN(MP_TAC o SPEC `dimindex(:N)`) THEN
4352   REWRITE_TAC[LE_REFL] THEN
4353   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real^N` THEN
4354   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `r:num->num` THEN ASM_SIMP_TAC[] THEN
4355   STRIP_TAC THEN MATCH_MP_TAC(TAUT `(b ==> a) /\ b ==> a /\ b`) THEN
4356   REPEAT STRIP_TAC THENL
4357    [FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[CLOSED_SEQUENTIAL_LIMITS]) THEN
4358     EXISTS_TAC `(x:num->real^N) o (r:num->num)` THEN
4359     ASM_REWRITE_TAC[o_THM];
4360     ALL_TAC] THEN
4361   REWRITE_TAC[LIM_SEQUENTIALLY] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
4362   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2 / &(dimindex(:N))`) THEN
4363   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; DIMINDEX_NONZERO;
4364                REAL_HALF; ARITH_RULE `0 < n <=> ~(n = 0)`] THEN
4365   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
4366   REWRITE_TAC[dist] THEN REPEAT STRIP_TAC THEN
4367   MATCH_MP_TAC(MATCH_MP (REAL_ARITH `a <= b ==> b < e ==> a < e`)
4368                         (SPEC_ALL NORM_LE_L1)) THEN
4369   MATCH_MP_TAC REAL_LET_TRANS THEN
4370   EXISTS_TAC `sum (1..dimindex(:N))
4371                   (\k. e / &2 / &(dimindex(:N)))` THEN
4372   CONJ_TAC THENL
4373    [MATCH_MP_TAC SUM_LE_NUMSEG THEN
4374     SIMP_TAC[o_THM; LAMBDA_BETA; vector_sub] THEN
4375     ASM_MESON_TAC[REAL_LT_IMP_LE; LE_TRANS];
4376     ASM_SIMP_TAC[SUM_CONST_NUMSEG; ADD_SUB; REAL_DIV_LMUL; REAL_OF_NUM_EQ;
4377                  DIMINDEX_NONZERO; REAL_LE_REFL; REAL_LT_LDIV_EQ; ARITH;
4378                  REAL_OF_NUM_LT; REAL_ARITH `x < x * &2 <=> &0 < x`]]);;
4379
4380 (* ------------------------------------------------------------------------- *)
4381 (* Completeness.                                                             *)
4382 (* ------------------------------------------------------------------------- *)
4383
4384 let cauchy = new_definition
4385   `cauchy (s:num->real^N) <=>
4386      !e. &0 < e ==> ?N. !m n. m >= N /\ n >= N ==> dist(s m,s n) < e`;;
4387
4388 let complete = new_definition
4389   `complete s <=>
4390      !f:num->real^N. (!n. f n IN s) /\ cauchy f
4391                       ==> ?l. l IN s /\ (f --> l) sequentially`;;
4392
4393 let CAUCHY = prove
4394  (`!s:num->real^N.
4395       cauchy s <=> !e. &0 < e ==> ?N. !n. n >= N ==> dist(s n,s N) < e`,
4396   REPEAT GEN_TAC THEN REWRITE_TAC[cauchy; GE] THEN EQ_TAC THENL
4397    [MESON_TAC[LE_REFL]; DISCH_TAC] THEN
4398   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
4399   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
4400   MESON_TAC[DIST_TRIANGLE_HALF_L]);;
4401
4402 let CONVERGENT_IMP_CAUCHY = prove
4403  (`!s l. (s --> l) sequentially ==> cauchy s`,
4404   REWRITE_TAC[LIM_SEQUENTIALLY; cauchy] THEN
4405   REPEAT GEN_TAC THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
4406   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
4407   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
4408   ASM_MESON_TAC[GE; LE_REFL; DIST_TRIANGLE_HALF_L]);;
4409
4410 let CAUCHY_IMP_BOUNDED = prove
4411  (`!s:num->real^N. cauchy s ==> bounded {y | ?n. y = s n}`,
4412   REWRITE_TAC[cauchy; bounded; IN_ELIM_THM] THEN GEN_TAC THEN
4413   DISCH_THEN(MP_TAC o SPEC `&1`) THEN REWRITE_TAC[REAL_LT_01] THEN
4414   DISCH_THEN(X_CHOOSE_THEN `N:num` (MP_TAC o SPEC `N:num`)) THEN
4415   REWRITE_TAC[GE_REFL] THEN DISCH_TAC THEN
4416   SUBGOAL_THEN `!n:num. N <= n ==> norm(s n :real^N) <= norm(s N) + &1`
4417   ASSUME_TAC THENL
4418    [ASM_MESON_TAC[GE; dist; DIST_SYM; NORM_TRIANGLE_SUB;
4419                   REAL_ARITH `a <= b + c /\ c < &1 ==> a <= b + &1`];
4420     MP_TAC(ISPECL [`\n:num. norm(s n :real^N)`; `0..N`]
4421                   UPPER_BOUND_FINITE_SET_REAL) THEN
4422     SIMP_TAC[FINITE_NUMSEG; IN_NUMSEG; LE_0; LEFT_IMP_EXISTS_THM] THEN
4423     ASM_MESON_TAC[LE_CASES;
4424                   REAL_ARITH `x <= a \/ x <= b ==> x <= abs a + abs b`]]);;
4425
4426 let COMPACT_IMP_COMPLETE = prove
4427  (`!s:real^N->bool. compact s ==> complete s`,
4428   GEN_TAC THEN REWRITE_TAC[complete; compact] THEN
4429   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `f:num->real^N` THEN
4430   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
4431   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
4432   DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN
4433   FIRST_X_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] LIM_ADD)) THEN
4434   DISCH_THEN(MP_TAC o SPEC `\n. (f:num->real^N)(n) - f(r n)`) THEN
4435   DISCH_THEN(MP_TAC o SPEC `vec 0: real^N`) THEN ASM_REWRITE_TAC[o_THM] THEN
4436   REWRITE_TAC[VECTOR_ADD_RID; VECTOR_SUB_ADD2; ETA_AX] THEN
4437   DISCH_THEN MATCH_MP_TAC THEN
4438   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [cauchy]) THEN
4439   REWRITE_TAC[GE; LIM; SEQUENTIALLY; dist; VECTOR_SUB_RZERO] THEN
4440   SUBGOAL_THEN `!n:num. n <= r(n)` MP_TAC THENL [INDUCT_TAC; ALL_TAC] THEN
4441   ASM_MESON_TAC[ LE_TRANS; LE_REFL; LT; LET_TRANS; LE_0; LE_SUC_LT]);;
4442
4443 let COMPLETE_UNIV = prove
4444  (`complete(:real^N)`,
4445   REWRITE_TAC[complete; IN_UNIV] THEN X_GEN_TAC `x:num->real^N` THEN
4446   DISCH_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP CAUCHY_IMP_BOUNDED) THEN
4447   DISCH_THEN(ASSUME_TAC o MATCH_MP BOUNDED_CLOSURE) THEN
4448   MP_TAC(ISPEC `closure {y:real^N | ?n:num. y = x n}`
4449                COMPACT_IMP_COMPLETE) THEN
4450   ASM_SIMP_TAC[BOUNDED_CLOSED_IMP_COMPACT; CLOSED_CLOSURE; complete] THEN
4451   DISCH_THEN(MP_TAC o SPEC `x:num->real^N`) THEN
4452   ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
4453   ASM_REWRITE_TAC[closure; IN_ELIM_THM; IN_UNION] THEN MESON_TAC[]);;
4454
4455 let COMPLETE_EQ_CLOSED = prove
4456  (`!s:real^N->bool. complete s <=> closed s`,
4457   GEN_TAC THEN EQ_TAC THENL
4458    [REWRITE_TAC[complete; CLOSED_LIMPT; LIMPT_SEQUENTIAL] THEN
4459     REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN GEN_TAC THEN
4460     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MATCH_MP_TAC MONO_FORALL THEN
4461     MESON_TAC[CONVERGENT_IMP_CAUCHY; IN_DELETE; LIM_UNIQUE;
4462               TRIVIAL_LIMIT_SEQUENTIALLY];
4463     REWRITE_TAC[complete; CLOSED_SEQUENTIAL_LIMITS] THEN DISCH_TAC THEN
4464     X_GEN_TAC `f:num->real^N` THEN STRIP_TAC THEN
4465     MP_TAC(REWRITE_RULE[complete] COMPLETE_UNIV) THEN
4466     DISCH_THEN(MP_TAC o SPEC `f:num->real^N`) THEN
4467     ASM_REWRITE_TAC[IN_UNIV] THEN ASM_MESON_TAC[]]);;
4468
4469 let CONVERGENT_EQ_CAUCHY = prove
4470  (`!s. (?l. (s --> l) sequentially) <=> cauchy s`,
4471   GEN_TAC THEN EQ_TAC THENL
4472    [REWRITE_TAC[LEFT_IMP_EXISTS_THM; CONVERGENT_IMP_CAUCHY];
4473     REWRITE_TAC[REWRITE_RULE[complete; IN_UNIV] COMPLETE_UNIV]]);;
4474
4475 let CONVERGENT_IMP_BOUNDED = prove
4476  (`!s l. (s --> l) sequentially ==> bounded (IMAGE s (:num))`,
4477   REWRITE_TAC[LEFT_FORALL_IMP_THM; CONVERGENT_EQ_CAUCHY] THEN
4478   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CAUCHY_IMP_BOUNDED) THEN
4479   REWRITE_TAC[IMAGE; IN_UNIV]);;
4480
4481 (* ------------------------------------------------------------------------- *)
4482 (* Total boundedness.                                                        *)
4483 (* ------------------------------------------------------------------------- *)
4484
4485 let COMPACT_IMP_TOTALLY_BOUNDED = prove
4486  (`!s:real^N->bool.
4487         compact s
4488         ==> !e. &0 < e ==> ?k. FINITE k /\ k SUBSET s /\
4489                                s SUBSET (UNIONS(IMAGE (\x. ball(x,e)) k))`,
4490   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4491   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
4492   REWRITE_TAC[TAUT `~(a /\ b /\ c) <=> a /\ b ==> ~c`; SUBSET] THEN
4493   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
4494   SUBGOAL_THEN
4495    `?x:num->real^N. !n. x(n) IN s /\ !m. m < n ==> ~(dist(x(m),x(n)) < e)`
4496   MP_TAC THENL
4497    [SUBGOAL_THEN
4498      `?x:num->real^N.
4499           !n. x(n) = @y. y IN s /\ !m. m < n ==> ~(dist(x(m),y) < e)`
4500     MP_TAC THENL
4501      [MATCH_MP_TAC(MATCH_MP WF_REC WF_num) THEN SIMP_TAC[]; ALL_TAC] THEN
4502     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:num->real^N` THEN
4503     DISCH_TAC THEN MATCH_MP_TAC num_WF THEN X_GEN_TAC `n:num` THEN
4504     FIRST_X_ASSUM(SUBST1_TAC o SPEC `n:num`) THEN STRIP_TAC THEN
4505     CONV_TAC SELECT_CONV THEN
4506     FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (x:num->real^N) {m | m < n}`) THEN
4507     SIMP_TAC[FINITE_IMAGE; FINITE_NUMSEG_LT; NOT_FORALL_THM; NOT_IMP] THEN
4508     REWRITE_TAC[IN_UNIONS; IN_IMAGE; IN_ELIM_THM] THEN ASM_MESON_TAC[IN_BALL];
4509     ALL_TAC] THEN
4510   REWRITE_TAC[compact; NOT_FORALL_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
4511   X_GEN_TAC `x:num->real^N` THEN  REWRITE_TAC[NOT_IMP; FORALL_AND_THM] THEN
4512   STRIP_TAC THEN ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN REPEAT STRIP_TAC THEN
4513   FIRST_X_ASSUM(MP_TAC o MATCH_MP CONVERGENT_IMP_CAUCHY) THEN
4514   REWRITE_TAC[cauchy] THEN DISCH_THEN(MP_TAC o SPEC `e:real`) THEN
4515   ASM_REWRITE_TAC[o_THM; NOT_EXISTS_THM; NOT_IMP; NOT_FORALL_THM; NOT_IMP] THEN
4516   X_GEN_TAC `N:num` THEN MAP_EVERY EXISTS_TAC [`N:num`; `SUC N`] THEN
4517   CONJ_TAC THENL [ARITH_TAC; ASM_MESON_TAC[LT]]);;
4518
4519 (* ------------------------------------------------------------------------- *)
4520 (* Heine-Borel theorem (following Burkill & Burkill vol. 2)                  *)
4521 (* ------------------------------------------------------------------------- *)
4522
4523 let HEINE_BOREL_LEMMA = prove
4524  (`!s:real^N->bool.
4525       compact s
4526       ==> !t. s SUBSET (UNIONS t) /\ (!b. b IN t ==> open b)
4527               ==> ?e. &0 < e /\
4528                       !x. x IN s ==> ?b. b IN t /\ ball(x,e) SUBSET b`,
4529   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4530   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
4531   DISCH_THEN(CHOOSE_THEN (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
4532   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC `&1 / (&n + &1)`) THEN
4533   SIMP_TAC[REAL_LT_DIV; REAL_LT_01; REAL_ARITH `x <= y ==> x < y + &1`;
4534    FORALL_AND_THM; REAL_POS; NOT_FORALL_THM; NOT_IMP; SKOLEM_THM; compact] THEN
4535   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN REWRITE_TAC[NOT_EXISTS_THM] THEN
4536   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN ASM_REWRITE_TAC[] THEN
4537   DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`l:real^N`; `r:num->num`] THEN
4538   STRIP_TAC THEN
4539   SUBGOAL_THEN `?b:real^N->bool. l IN b /\ b IN t` STRIP_ASSUME_TAC THENL
4540    [ASM_MESON_TAC[SUBSET; IN_UNIONS]; ALL_TAC] THEN
4541   SUBGOAL_THEN `?e. &0 < e /\ !z:real^N. dist(z,l) < e ==> z IN b`
4542   STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[open_def]; ALL_TAC] THEN
4543   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
4544   DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN
4545   SUBGOAL_THEN `&0 < e / &2` (fun th ->
4546     REWRITE_TAC[th; o_THM] THEN MP_TAC(GEN_REWRITE_RULE I [REAL_ARCH_INV] th))
4547   THENL [ASM_REWRITE_TAC[REAL_HALF]; ALL_TAC] THEN
4548   DISCH_THEN(X_CHOOSE_THEN `N1:num` STRIP_ASSUME_TAC) THEN
4549   DISCH_THEN(X_CHOOSE_THEN `N2:num` STRIP_ASSUME_TAC) THEN
4550   FIRST_X_ASSUM(MP_TAC o SPECL
4551    [`(r:num->num)(N1 + N2)`; `b:real^N->bool`]) THEN
4552   ASM_REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4553   FIRST_X_ASSUM MATCH_MP_TAC THEN MATCH_MP_TAC DIST_TRIANGLE_HALF_R THEN
4554   EXISTS_TAC `(f:num->real^N)(r(N1 + N2:num))` THEN CONJ_TAC THENL
4555    [ALL_TAC; FIRST_X_ASSUM MATCH_MP_TAC THEN ARITH_TAC] THEN
4556   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_BALL]) THEN
4557   MATCH_MP_TAC(REAL_ARITH `a <= b ==> x < a ==> x < b`) THEN
4558   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&N1)` THEN
4559   ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN REWRITE_TAC[real_div; REAL_MUL_LID] THEN
4560   MATCH_MP_TAC REAL_LE_INV2 THEN
4561   REWRITE_TAC[REAL_OF_NUM_ADD; REAL_OF_NUM_LE; REAL_OF_NUM_LT] THEN
4562   ASM_MESON_TAC[ARITH_RULE `(~(n = 0) ==> 0 < n)`; LE_ADD; MONOTONE_BIGGER;
4563                 LT_IMP_LE; LE_TRANS]);;
4564
4565 let COMPACT_IMP_HEINE_BOREL = prove
4566  (`!s. compact (s:real^N->bool)
4567        ==> !f. (!t. t IN f ==> open t) /\ s SUBSET (UNIONS f)
4568                ==> ?f'. f' SUBSET f /\ FINITE f' /\ s SUBSET (UNIONS f')`,
4569   REPEAT STRIP_TAC THEN
4570   FIRST_ASSUM(MP_TAC o SPEC `f:(real^N->bool)->bool` o
4571     MATCH_MP HEINE_BOREL_LEMMA) THEN ASM_REWRITE_TAC[] THEN
4572   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
4573   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4574   REWRITE_TAC[SKOLEM_THM; SUBSET; IN_BALL] THEN
4575   DISCH_THEN(X_CHOOSE_TAC `B:real^N->real^N->bool`) THEN
4576   FIRST_ASSUM(MP_TAC o SPEC `e:real` o
4577     MATCH_MP COMPACT_IMP_TOTALLY_BOUNDED) THEN
4578   ASM_REWRITE_TAC[UNIONS_IMAGE; SUBSET; IN_ELIM_THM] THEN
4579   REWRITE_TAC[IN_UNIONS; IN_BALL] THEN
4580   DISCH_THEN(X_CHOOSE_THEN `k:real^N->bool` STRIP_ASSUME_TAC) THEN
4581   EXISTS_TAC `IMAGE (B:real^N->real^N->bool) k` THEN
4582   ASM_SIMP_TAC[FINITE_IMAGE; SUBSET; IN_IMAGE; LEFT_IMP_EXISTS_THM] THEN
4583   ASM_MESON_TAC[IN_BALL]);;
4584
4585 (* ------------------------------------------------------------------------- *)
4586 (* Bolzano-Weierstrass property.                                             *)
4587 (* ------------------------------------------------------------------------- *)
4588
4589 let HEINE_BOREL_IMP_BOLZANO_WEIERSTRASS = prove
4590  (`!s:real^N->bool.
4591         (!f. (!t. t IN f ==> open t) /\ s SUBSET (UNIONS f)
4592              ==> ?f'. f' SUBSET f /\ FINITE f' /\ s SUBSET (UNIONS f'))
4593         ==> !t. INFINITE t /\ t SUBSET s ==> ?x. x IN s /\ x limit_point_of t`,
4594   REWRITE_TAC[RIGHT_IMP_FORALL_THM; limit_point_of] THEN REPEAT GEN_TAC THEN
4595   ONCE_REWRITE_TAC[TAUT `a ==> b /\ c ==> d <=> c ==> ~d ==> a ==> ~b`] THEN
4596   REWRITE_TAC[NOT_FORALL_THM; NOT_EXISTS_THM; RIGHT_AND_FORALL_THM] THEN
4597   DISCH_TAC THEN REWRITE_TAC[SKOLEM_THM] THEN
4598   DISCH_THEN(X_CHOOSE_TAC `f:real^N->real^N->bool`) THEN
4599   DISCH_THEN(MP_TAC o SPEC
4600    `{t:real^N->bool | ?x:real^N. x IN s /\ (t = f x)}`) THEN
4601   REWRITE_TAC[INFINITE; SUBSET; IN_ELIM_THM; IN_UNIONS; NOT_IMP] THEN
4602   ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
4603   DISCH_THEN(X_CHOOSE_THEN `g:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
4604   MATCH_MP_TAC FINITE_SUBSET THEN
4605   EXISTS_TAC `{x:real^N | x IN t /\ (f(x):real^N->bool) IN g}` THEN
4606   CONJ_TAC THENL
4607    [MATCH_MP_TAC FINITE_IMAGE_INJ_GENERAL THEN ASM_MESON_TAC[SUBSET];
4608     SIMP_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `u:real^N` THEN
4609     DISCH_TAC THEN SUBGOAL_THEN `(u:real^N) IN s` ASSUME_TAC THEN
4610     ASM_MESON_TAC[SUBSET]]);;
4611
4612 (* ------------------------------------------------------------------------- *)
4613 (* Complete the chain of compactness variants.                               *)
4614 (* ------------------------------------------------------------------------- *)
4615
4616 let BOLZANO_WEIERSTRASS_IMP_BOUNDED = prove
4617  (`!s:real^N->bool.
4618         (!t. INFINITE t /\ t SUBSET s ==> ?x. x limit_point_of t)
4619         ==> bounded s`,
4620   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4621   SIMP_TAC[compact; bounded] THEN
4622   REWRITE_TAC[NOT_FORALL_THM; NOT_EXISTS_THM; SKOLEM_THM; NOT_IMP] THEN
4623   REWRITE_TAC[REAL_NOT_LE] THEN
4624   DISCH_THEN(X_CHOOSE_TAC `beyond:real->real^N`) THEN
4625   (MP_TAC o prove_recursive_functions_exist num_RECURSION)
4626    `(f(0) = beyond(&0)) /\
4627     (!n. f(SUC n) = beyond(norm(f n) + &1):real^N)` THEN
4628   DISCH_THEN(X_CHOOSE_THEN `x:num->real^N` STRIP_ASSUME_TAC) THEN
4629   EXISTS_TAC `IMAGE (x:num->real^N) UNIV` THEN
4630   SUBGOAL_THEN
4631    `!m n. m < n ==> norm((x:num->real^N) m) + &1 < norm(x n)`
4632   ASSUME_TAC THENL
4633    [GEN_TAC THEN INDUCT_TAC THEN ASM_REWRITE_TAC[LT] THEN
4634     ASM_MESON_TAC[REAL_LT_TRANS; REAL_ARITH `b < b + &1`];
4635     ALL_TAC] THEN
4636   SUBGOAL_THEN `!m n. ~(m = n) ==> &1 < dist((x:num->real^N) m,x n)`
4637   ASSUME_TAC THENL
4638    [REPEAT GEN_TAC THEN REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC
4639      (SPECL [`m:num`; `n:num`] LT_CASES) THEN
4640     ASM_MESON_TAC[dist; LT_CASES; NORM_TRIANGLE_SUB; NORM_SUB;
4641                   REAL_ARITH `x + &1 < y /\ y <= x + d ==> &1 < d`];
4642     ALL_TAC] THEN
4643   REPEAT CONJ_TAC THENL
4644    [ASM_MESON_TAC[INFINITE_IMAGE_INJ; num_INFINITE; DIST_REFL;
4645                   REAL_ARITH `~(&1 < &0)`];
4646     REWRITE_TAC[SUBSET; IN_IMAGE; IN_UNIV; LEFT_IMP_EXISTS_THM] THEN
4647     GEN_TAC THEN INDUCT_TAC THEN ASM_MESON_TAC[];
4648     ALL_TAC] THEN
4649   X_GEN_TAC `l:real^N` THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN
4650   REWRITE_TAC[IN_IMAGE; IN_UNIV; LEFT_AND_EXISTS_THM] THEN
4651   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[UNWIND_THM2] THEN
4652   STRIP_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `&1 / &2`) THEN
4653   CONV_TAC REAL_RAT_REDUCE_CONV THEN
4654   DISCH_THEN(X_CHOOSE_THEN `k:num` STRIP_ASSUME_TAC) THEN
4655   FIRST_X_ASSUM(MP_TAC o SPEC `dist((x:num->real^N) k,l)`) THEN
4656   ASM_SIMP_TAC[DIST_POS_LT] THEN
4657   DISCH_THEN(X_CHOOSE_THEN `m:num` STRIP_ASSUME_TAC) THEN
4658   ASM_CASES_TAC `m:num = k` THEN
4659   ASM_MESON_TAC[DIST_TRIANGLE_HALF_L; REAL_LT_TRANS; REAL_LT_REFL]);;
4660
4661 let SEQUENCE_INFINITE_LEMMA = prove
4662  (`!f l. (!n. ~(f(n) = l)) /\ (f --> l) sequentially
4663          ==> INFINITE {y:real^N | ?n. y = f n}`,
4664   REWRITE_TAC[INFINITE] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPEC
4665    `IMAGE (\y:real^N. dist(y,l)) {y | ?n:num. y = f n}` INF_FINITE) THEN
4666   ASM_SIMP_TAC[GSYM MEMBER_NOT_EMPTY; IN_IMAGE; FINITE_IMAGE; IN_ELIM_THM] THEN
4667   ASM_MESON_TAC[LIM_SEQUENTIALLY; LE_REFL; REAL_NOT_LE; DIST_POS_LT]);;
4668
4669 let LIMPT_OF_SEQUENCE_SUBSEQUENCE = prove
4670  (`!f:num->real^N l.
4671         l limit_point_of (IMAGE f (:num))
4672         ==> ?r. (!m n. m < n ==> r(m) < r(n)) /\ ((f o r) --> l) sequentially`,
4673   REPEAT STRIP_TAC THEN
4674   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIMPT_APPROACHABLE]) THEN
4675   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC
4676    `inf((inv(&n + &1)) INSERT
4677     IMAGE (\k. dist((f:num->real^N) k,l))
4678           {k | k IN 0..n /\ ~(f k = l)})`) THEN
4679   SIMP_TAC[REAL_LT_INF_FINITE; FINITE_INSERT; NOT_INSERT_EMPTY;
4680            FINITE_RESTRICT; FINITE_NUMSEG; FINITE_IMAGE] THEN
4681   REWRITE_TAC[FORALL_IN_INSERT; EXISTS_IN_IMAGE; FORALL_IN_IMAGE; IN_UNIV] THEN
4682   REWRITE_TAC[REAL_LT_INV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
4683   SIMP_TAC[FORALL_AND_THM; FORALL_IN_GSPEC; GSYM DIST_NZ; SKOLEM_THM] THEN
4684   DISCH_THEN(X_CHOOSE_THEN `nn:num->num` STRIP_ASSUME_TAC) THEN
4685   (MP_TAC o prove_recursive_functions_exist num_RECURSION)
4686    `r 0 = nn 0 /\ (!n. r (SUC n) = nn(r n))` THEN
4687   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `r:num->num` THEN
4688   STRIP_TAC THEN
4689   MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
4690    [MATCH_MP_TAC TRANSITIVE_STEPWISE_LT THEN REWRITE_TAC[LT_TRANS] THEN
4691     X_GEN_TAC `n:num` THEN ASM_REWRITE_TAC[] THEN
4692     FIRST_X_ASSUM(MP_TAC o SPECL
4693      [`(r:num->num) n`; `(nn:num->num)(r(n:num))`]) THEN
4694     ASM_REWRITE_TAC[IN_NUMSEG; LE_0; REAL_LT_REFL] THEN ARITH_TAC;
4695     DISCH_THEN(ASSUME_TAC o MATCH_MP MONOTONE_BIGGER)] THEN
4696   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
4697   X_GEN_TAC `e:real` THEN GEN_REWRITE_TAC LAND_CONV [REAL_ARCH_INV] THEN
4698   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN STRIP_TAC THEN
4699   MATCH_MP_TAC num_INDUCTION THEN ASM_REWRITE_TAC[CONJUNCT1 LE] THEN
4700   X_GEN_TAC `n:num` THEN DISCH_THEN(K ALL_TAC) THEN DISCH_TAC THEN
4701   ASM_REWRITE_TAC[o_THM] THEN MATCH_MP_TAC REAL_LT_TRANS THEN
4702   EXISTS_TAC `inv(&((r:num->num) n) + &1)` THEN ASM_REWRITE_TAC[] THEN
4703   MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&N)` THEN
4704   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
4705   ASM_SIMP_TAC[REAL_OF_NUM_LE; REAL_OF_NUM_LT; LE_1; REAL_OF_NUM_ADD] THEN
4706   MATCH_MP_TAC(ARITH_RULE `N <= SUC n /\ n <= r n ==> N <= r n + 1`) THEN
4707   ASM_REWRITE_TAC[]);;
4708
4709 let SEQUENCE_UNIQUE_LIMPT = prove
4710  (`!f l l':real^N.
4711         (f --> l) sequentially /\ l' limit_point_of {y | ?n. y = f n}
4712         ==> l' = l`,
4713   REWRITE_TAC[SET_RULE `{y | ?n. y = f n} = IMAGE f (:num)`] THEN
4714   REPEAT STRIP_TAC THEN
4715   FIRST_X_ASSUM(MP_TAC o MATCH_MP LIMPT_OF_SEQUENCE_SUBSEQUENCE) THEN
4716   DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN
4717   MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
4718   EXISTS_TAC `(f:num->real^N) o (r:num->num)` THEN
4719   ASM_SIMP_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; LIM_SUBSEQUENCE]);;
4720
4721 let BOLZANO_WEIERSTRASS_IMP_CLOSED = prove
4722  (`!s:real^N->bool.
4723         (!t. INFINITE t /\ t SUBSET s ==> ?x. x IN s /\ x limit_point_of t)
4724         ==> closed s`,
4725   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSED_SEQUENTIAL_LIMITS] THEN
4726   MAP_EVERY X_GEN_TAC [`f:num->real^N`; `l:real^N`] THEN
4727   DISCH_TAC THEN
4728   MAP_EVERY (MP_TAC o ISPECL [`f:num->real^N`; `l:real^N`])
4729    [SEQUENCE_UNIQUE_LIMPT; SEQUENCE_INFINITE_LEMMA] THEN
4730   MATCH_MP_TAC(TAUT
4731    `(~d ==> a /\ ~(b /\ c)) ==> (a ==> b) ==> c ==> d`) THEN
4732   DISCH_TAC THEN CONJ_TAC THENL [ASM_MESON_TAC[]; STRIP_TAC] THEN
4733   FIRST_X_ASSUM(MP_TAC o SPEC `{y:real^N | ?n:num. y = f n}`) THEN
4734   ASM_REWRITE_TAC[NOT_IMP] THEN CONJ_TAC THENL
4735    [REWRITE_TAC[SUBSET; IN_ELIM_THM];
4736     ABBREV_TAC `t = {y:real^N | ?n:num. y = f n}`] THEN
4737   ASM_MESON_TAC[]);;
4738
4739 (* ------------------------------------------------------------------------- *)
4740 (* Hence express everything as an equivalence.                               *)
4741 (* ------------------------------------------------------------------------- *)
4742
4743 let COMPACT_EQ_HEINE_BOREL = prove
4744  (`!s:real^N->bool.
4745         compact s <=>
4746            !f. (!t. t IN f ==> open t) /\ s SUBSET (UNIONS f)
4747                ==> ?f'. f' SUBSET f /\ FINITE f' /\ s SUBSET (UNIONS f')`,
4748   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[COMPACT_IMP_HEINE_BOREL] THEN
4749   DISCH_THEN(MP_TAC o MATCH_MP HEINE_BOREL_IMP_BOLZANO_WEIERSTRASS) THEN
4750   DISCH_TAC THEN MATCH_MP_TAC BOUNDED_CLOSED_IMP_COMPACT THEN
4751   ASM_MESON_TAC[BOLZANO_WEIERSTRASS_IMP_BOUNDED;
4752                 BOLZANO_WEIERSTRASS_IMP_CLOSED]);;
4753
4754 let COMPACT_EQ_BOLZANO_WEIERSTRASS = prove
4755  (`!s:real^N->bool.
4756         compact s <=>
4757            !t. INFINITE t /\ t SUBSET s ==> ?x. x IN s /\ x limit_point_of t`,
4758   GEN_TAC THEN EQ_TAC THENL
4759    [SIMP_TAC[COMPACT_EQ_HEINE_BOREL; HEINE_BOREL_IMP_BOLZANO_WEIERSTRASS];
4760     MESON_TAC[BOLZANO_WEIERSTRASS_IMP_BOUNDED; BOLZANO_WEIERSTRASS_IMP_CLOSED;
4761               BOUNDED_CLOSED_IMP_COMPACT]]);;
4762
4763 let COMPACT_EQ_BOUNDED_CLOSED = prove
4764  (`!s:real^N->bool. compact s <=> bounded s /\ closed s`,
4765   GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[BOUNDED_CLOSED_IMP_COMPACT] THEN
4766   MESON_TAC[COMPACT_EQ_BOLZANO_WEIERSTRASS; BOLZANO_WEIERSTRASS_IMP_BOUNDED;
4767             BOLZANO_WEIERSTRASS_IMP_CLOSED]);;
4768
4769 let COMPACT_IMP_BOUNDED = prove
4770  (`!s. compact s ==> bounded s`,
4771   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED]);;
4772
4773 let COMPACT_IMP_CLOSED = prove
4774  (`!s. compact s ==> closed s`,
4775   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED]);;
4776
4777 let COMPACT_SEQUENCE_WITH_LIMIT = prove
4778  (`!f l:real^N.
4779         (f --> l) sequentially ==> compact (l INSERT IMAGE f (:num))`,
4780   REPEAT STRIP_TAC THEN REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4781   REWRITE_TAC[BOUNDED_INSERT] THEN CONJ_TAC THENL
4782    [ASM_MESON_TAC[CONVERGENT_IMP_BOUNDED];
4783     SIMP_TAC[CLOSED_LIMPT; LIMPT_INSERT; IN_INSERT] THEN
4784     REWRITE_TAC[IMAGE; IN_UNIV] THEN REPEAT STRIP_TAC THEN DISJ1_TAC THEN
4785     MATCH_MP_TAC SEQUENCE_UNIQUE_LIMPT THEN ASM_MESON_TAC[]]);;
4786
4787 let CLOSED_IN_COMPACT = prove
4788  (`!s t:real^N->bool.
4789         compact s /\ closed_in (subtopology euclidean s) t
4790         ==> compact t`,
4791   SIMP_TAC[IMP_CONJ; COMPACT_EQ_BOUNDED_CLOSED; CLOSED_IN_CLOSED_EQ] THEN
4792   MESON_TAC[BOUNDED_SUBSET]);;
4793
4794 let CLOSED_IN_COMPACT_EQ = prove
4795  (`!s t. compact s
4796          ==> (closed_in (subtopology euclidean s) t <=>
4797               compact t /\ t SUBSET s)`,
4798   MESON_TAC[CLOSED_IN_CLOSED_EQ; COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_SUBSET]);;
4799
4800 (* ------------------------------------------------------------------------- *)
4801 (* A version of Heine-Borel for subtopology.                                 *)
4802 (* ------------------------------------------------------------------------- *)
4803
4804 let COMPACT_EQ_HEINE_BOREL_SUBTOPOLOGY = prove
4805  (`!s:real^N->bool.
4806         compact s <=>
4807         (!f. (!t. t IN f ==> open_in(subtopology euclidean s) t) /\
4808              s SUBSET UNIONS f
4809              ==> ?f'. f' SUBSET f /\ FINITE f' /\ s SUBSET UNIONS f')`,
4810   GEN_TAC THEN REWRITE_TAC[COMPACT_EQ_HEINE_BOREL] THEN EQ_TAC THEN
4811   DISCH_TAC THEN X_GEN_TAC `f:(real^N->bool)->bool` THENL
4812    [REWRITE_TAC[OPEN_IN_OPEN] THEN
4813     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4814     REWRITE_TAC[SKOLEM_THM] THEN
4815     DISCH_THEN(CONJUNCTS_THEN2
4816      (X_CHOOSE_TAC `m:(real^N->bool)->(real^N->bool)`) ASSUME_TAC) THEN
4817     FIRST_X_ASSUM(MP_TAC o SPEC
4818      `IMAGE (m:(real^N->bool)->(real^N->bool)) f`) THEN
4819     ASM_SIMP_TAC[FORALL_IN_IMAGE] THEN
4820     ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4821     DISCH_THEN(X_CHOOSE_THEN `f':(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
4822     EXISTS_TAC `IMAGE (\t:real^N->bool. s INTER t) f'` THEN
4823     ASM_SIMP_TAC[FINITE_IMAGE; UNIONS_IMAGE; SUBSET; FORALL_IN_IMAGE] THEN
4824     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
4825     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET_IMAGE]) THEN
4826     STRIP_TAC THEN ASM_REWRITE_TAC[FORALL_IN_IMAGE] THEN ASM_MESON_TAC[SUBSET];
4827     DISCH_TAC THEN
4828     FIRST_X_ASSUM(MP_TAC o SPEC `{s INTER t:real^N->bool | t IN f}`) THEN
4829     REWRITE_TAC[SIMPLE_IMAGE; FORALL_IN_IMAGE; OPEN_IN_OPEN; UNIONS_IMAGE] THEN
4830     ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4831     ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`] THEN
4832     REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE; UNIONS_IMAGE] THEN
4833     MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]]);;
4834
4835 (* ------------------------------------------------------------------------- *)
4836 (* More easy lemmas.                                                         *)
4837 (* ------------------------------------------------------------------------- *)
4838
4839 let COMPACT_CLOSURE = prove
4840  (`!s. compact(closure s) <=> bounded s`,
4841   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_CLOSURE; BOUNDED_CLOSURE_EQ]);;
4842
4843 let BOLZANO_WEIERSTRASS_CONTRAPOS = prove
4844  (`!s t:real^N->bool.
4845         compact s /\ t SUBSET s /\
4846         (!x. x IN s ==> ~(x limit_point_of t))
4847         ==> FINITE t`,
4848   REWRITE_TAC[COMPACT_EQ_BOLZANO_WEIERSTRASS; INFINITE] THEN MESON_TAC[]);;
4849
4850 let DISCRETE_BOUNDED_IMP_FINITE = prove
4851  (`!s:real^N->bool e.
4852         &0 < e /\
4853         (!x y. x IN s /\ y IN s /\ norm(y - x) < e ==> y = x) /\
4854         bounded s
4855         ==> FINITE s`,
4856   REPEAT STRIP_TAC THEN
4857   SUBGOAL_THEN `compact(s:real^N->bool)` MP_TAC THENL
4858    [ASM_REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4859     ASM_MESON_TAC[DISCRETE_IMP_CLOSED];
4860     DISCH_THEN(MP_TAC o MATCH_MP COMPACT_IMP_HEINE_BOREL)] THEN
4861   DISCH_THEN(MP_TAC o SPEC `IMAGE (\x:real^N. ball(x,e)) s`) THEN
4862   REWRITE_TAC[FORALL_IN_IMAGE; OPEN_BALL; UNIONS_IMAGE; IN_ELIM_THM] THEN
4863   ANTS_TAC THENL
4864    [REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN ASM_MESON_TAC[CENTRE_IN_BALL];
4865     ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`]] THEN
4866   REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE] THEN
4867   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
4868   SUBGOAL_THEN `s:real^N->bool = t` (fun th -> ASM_REWRITE_TAC[th]) THEN
4869   MATCH_MP_TAC SUBSET_ANTISYM THEN ASM_REWRITE_TAC[] THEN
4870   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4871   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [UNIONS_IMAGE]) THEN
4872   DISCH_THEN(MP_TAC o SPEC `x:real^N` o GEN_REWRITE_RULE I [SUBSET]) THEN
4873   ASM_REWRITE_TAC[IN_ELIM_THM; IN_BALL; dist] THEN ASM_MESON_TAC[SUBSET]);;
4874
4875 let BOLZANO_WEIERSTRASS = prove
4876  (`!s:real^N->bool. bounded s /\ INFINITE s ==> ?x. x limit_point_of s`,
4877   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
4878   FIRST_ASSUM(ASSUME_TAC o MATCH_MP NO_LIMIT_POINT_IMP_CLOSED) THEN
4879   STRIP_TAC THEN
4880   MP_TAC(ISPEC `s:real^N->bool` COMPACT_EQ_BOLZANO_WEIERSTRASS) THEN
4881   ASM_REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4882   DISCH_THEN(MP_TAC o SPEC `s:real^N->bool`) THEN
4883   ASM_REWRITE_TAC[SUBSET_REFL] THEN ASM_MESON_TAC[]);;
4884
4885 let BOUNDED_EQ_BOLZANO_WEIERSTRASS = prove
4886  (`!s:real^N->bool.
4887         bounded s <=> !t. t SUBSET s /\ INFINITE t ==> ?x. x limit_point_of t`,
4888   MESON_TAC[BOLZANO_WEIERSTRASS_IMP_BOUNDED; BOLZANO_WEIERSTRASS;
4889             BOUNDED_SUBSET]);;
4890
4891 (* ------------------------------------------------------------------------- *)
4892 (* In particular, some common special cases.                                 *)
4893 (* ------------------------------------------------------------------------- *)
4894
4895 let COMPACT_EMPTY = prove
4896  (`compact {}`,
4897   REWRITE_TAC[compact; NOT_IN_EMPTY]);;
4898
4899 let COMPACT_UNION = prove
4900  (`!s t. compact s /\ compact t ==> compact (s UNION t)`,
4901   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_UNION; CLOSED_UNION]);;
4902
4903 let COMPACT_INTER = prove
4904  (`!s t. compact s /\ compact t ==> compact (s INTER t)`,
4905   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_INTER; CLOSED_INTER]);;
4906
4907 let COMPACT_INTER_CLOSED = prove
4908  (`!s t. compact s /\ closed t ==> compact (s INTER t)`,
4909   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_INTER] THEN
4910   MESON_TAC[BOUNDED_SUBSET; INTER_SUBSET]);;
4911
4912 let CLOSED_INTER_COMPACT = prove
4913  (`!s t. closed s /\ compact t ==> compact (s INTER t)`,
4914   MESON_TAC[COMPACT_INTER_CLOSED; INTER_COMM]);;
4915
4916 let COMPACT_INTERS = prove
4917  (`!f:(real^N->bool)->bool.
4918         (!s. s IN f ==> compact s) /\ ~(f = {})
4919         ==> compact(INTERS f)`,
4920   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_INTERS] THEN
4921   REPEAT STRIP_TAC THEN MATCH_MP_TAC BOUNDED_INTERS THEN ASM SET_TAC[]);;
4922
4923 let FINITE_IMP_CLOSED = prove
4924  (`!s. FINITE s ==> closed s`,
4925   MESON_TAC[BOLZANO_WEIERSTRASS_IMP_CLOSED; INFINITE; FINITE_SUBSET]);;
4926
4927 let FINITE_IMP_CLOSED_IN = prove
4928  (`!s t. FINITE s /\ s SUBSET t ==> closed_in (subtopology euclidean t) s`,
4929   SIMP_TAC[CLOSED_SUBSET_EQ; FINITE_IMP_CLOSED]);;
4930
4931 let FINITE_IMP_COMPACT = prove
4932  (`!s. FINITE s ==> compact s`,
4933   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; FINITE_IMP_CLOSED; FINITE_IMP_BOUNDED]);;
4934
4935 let COMPACT_SING = prove
4936  (`!a. compact {a}`,
4937   SIMP_TAC[FINITE_IMP_COMPACT; FINITE_RULES]);;
4938
4939 let COMPACT_INSERT = prove
4940  (`!a s. compact s ==> compact(a INSERT s)`,
4941   ONCE_REWRITE_TAC[SET_RULE `a INSERT s = {a} UNION s`] THEN
4942   SIMP_TAC[COMPACT_UNION; COMPACT_SING]);;
4943
4944 let CLOSED_SING = prove
4945  (`!a. closed {a}`,
4946   MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; COMPACT_SING]);;
4947
4948 let CLOSED_IN_SING = prove
4949  (`!u x:real^N. closed_in (subtopology euclidean u) {x} <=> x IN u`,
4950   SIMP_TAC[CLOSED_SUBSET_EQ; CLOSED_SING] THEN SET_TAC[]);;
4951
4952 let CLOSURE_SING = prove
4953  (`!x:real^N. closure {x} = {x}`,
4954   SIMP_TAC[CLOSURE_CLOSED; CLOSED_SING]);;
4955
4956 let CLOSED_INSERT = prove
4957  (`!a s. closed s ==> closed(a INSERT s)`,
4958   ONCE_REWRITE_TAC[SET_RULE `a INSERT s = {a} UNION s`] THEN
4959   SIMP_TAC[CLOSED_UNION; CLOSED_SING]);;
4960
4961 let COMPACT_CBALL = prove
4962  (`!x e. compact(cball(x,e))`,
4963   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_CBALL; CLOSED_CBALL]);;
4964
4965 let COMPACT_FRONTIER_BOUNDED = prove
4966  (`!s. bounded s ==> compact(frontier s)`,
4967   SIMP_TAC[frontier; COMPACT_EQ_BOUNDED_CLOSED;
4968            CLOSED_DIFF; OPEN_INTERIOR; CLOSED_CLOSURE] THEN
4969   MESON_TAC[SUBSET_DIFF; BOUNDED_SUBSET; BOUNDED_CLOSURE]);;
4970
4971 let COMPACT_FRONTIER = prove
4972  (`!s. compact s ==> compact (frontier s)`,
4973   MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; COMPACT_FRONTIER_BOUNDED]);;
4974
4975 let BOUNDED_FRONTIER = prove
4976  (`!s:real^N->bool. bounded s ==> bounded(frontier s)`,
4977   MESON_TAC[COMPACT_FRONTIER_BOUNDED; COMPACT_IMP_BOUNDED]);;
4978
4979 let FRONTIER_SUBSET_COMPACT = prove
4980  (`!s. compact s ==> frontier s SUBSET s`,
4981   MESON_TAC[FRONTIER_SUBSET_CLOSED; COMPACT_EQ_BOUNDED_CLOSED]);;
4982
4983 let OPEN_DELETE = prove
4984  (`!s x. open s ==> open(s DELETE x)`,
4985   let lemma = prove(`s DELETE x = s DIFF {x}`,SET_TAC[]) in
4986   SIMP_TAC[lemma; OPEN_DIFF; CLOSED_SING]);;
4987
4988 let OPEN_IN_DELETE = prove
4989  (`!u s a:real^N.
4990         open_in (subtopology euclidean u) s
4991         ==> open_in (subtopology euclidean u) (s DELETE a)`,
4992   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(a:real^N) IN s` THENL
4993    [ONCE_REWRITE_TAC[SET_RULE `s DELETE a = s DIFF {a}`] THEN
4994     MATCH_MP_TAC OPEN_IN_DIFF THEN ASM_REWRITE_TAC[CLOSED_IN_SING] THEN
4995     FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN ASM SET_TAC[];
4996     ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> s DELETE a = s`]]);;
4997
4998 let CLOSED_INTERS_COMPACT = prove
4999  (`!s:real^N->bool.
5000         closed s <=> !e. compact(cball(vec 0,e) INTER s)`,
5001   GEN_TAC THEN EQ_TAC THENL
5002    [SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_INTER; CLOSED_CBALL;
5003              BOUNDED_INTER; BOUNDED_CBALL];
5004     ALL_TAC] THEN
5005   STRIP_TAC THEN REWRITE_TAC[CLOSED_LIMPT] THEN
5006   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
5007   FIRST_X_ASSUM(MP_TAC o SPEC `norm(x:real^N) + &1`) THEN
5008   DISCH_THEN(MP_TAC o MATCH_MP COMPACT_IMP_CLOSED) THEN
5009   REWRITE_TAC[CLOSED_LIMPT] THEN DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
5010   REWRITE_TAC[IN_INTER] THEN ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
5011   POP_ASSUM MP_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN
5012   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5013   FIRST_X_ASSUM(MP_TAC o SPEC `min e (&1 / &2)`) THEN
5014   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
5015   X_GEN_TAC `y:real^N` THEN SIMP_TAC[IN_INTER; IN_CBALL] THEN NORM_ARITH_TAC);;
5016
5017 let COMPACT_UNIONS = prove
5018  (`!s. FINITE s /\ (!t. t IN s ==> compact t) ==> compact(UNIONS s)`,
5019   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_UNIONS; BOUNDED_UNIONS]);;
5020
5021 let COMPACT_DIFF = prove
5022  (`!s t. compact s /\ open t ==> compact(s DIFF t)`,
5023   ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
5024   SIMP_TAC[COMPACT_INTER_CLOSED; GSYM OPEN_CLOSED]);;
5025
5026 let COMPACT_SPHERE = prove
5027  (`!a:real^N r. compact(sphere(a,r))`,
5028   REPEAT GEN_TAC THEN
5029   REWRITE_TAC[GSYM FRONTIER_CBALL] THEN MATCH_MP_TAC COMPACT_FRONTIER THEN
5030   REWRITE_TAC[COMPACT_CBALL]);;
5031
5032 let BOUNDED_SPHERE = prove
5033  (`!a:real^N r. bounded(sphere(a,r))`,
5034   SIMP_TAC[COMPACT_SPHERE; COMPACT_IMP_BOUNDED]);;
5035
5036 let CLOSED_SPHERE = prove
5037  (`!a r. closed(sphere(a,r))`,
5038   SIMP_TAC[COMPACT_SPHERE; COMPACT_IMP_CLOSED]);;
5039
5040 let FRONTIER_SING = prove
5041  (`!a:real^N. frontier {a} = {a}`,
5042   REWRITE_TAC[frontier; CLOSURE_SING; INTERIOR_SING; DIFF_EMPTY]);;
5043
5044 (* ------------------------------------------------------------------------- *)
5045 (* Finite intersection property. I could make it an equivalence in fact.     *)
5046 (* ------------------------------------------------------------------------- *)
5047
5048 let COMPACT_IMP_FIP = prove
5049  (`!s:real^N->bool f.
5050         compact s /\
5051         (!t. t IN f ==> closed t) /\
5052         (!f'. FINITE f' /\ f' SUBSET f ==> ~(s INTER (INTERS f') = {}))
5053         ==> ~(s INTER (INTERS f) = {})`,
5054   let lemma = prove(`(s = UNIV DIFF t) <=> (UNIV DIFF s = t)`,SET_TAC[]) in
5055   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5056   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL]) THEN
5057   DISCH_THEN(MP_TAC o SPEC `IMAGE (\t:real^N->bool. UNIV DIFF t) f`) THEN
5058   ASM_SIMP_TAC[FORALL_IN_IMAGE] THEN
5059   DISCH_THEN(fun th -> REPEAT STRIP_TAC THEN MP_TAC th) THEN
5060   ASM_SIMP_TAC[OPEN_DIFF; CLOSED_DIFF; OPEN_UNIV; CLOSED_UNIV; NOT_IMP] THEN
5061   CONJ_TAC THENL
5062    [UNDISCH_TAC `(s:real^N->bool) INTER INTERS f = {}` THEN
5063     ONCE_REWRITE_TAC[SUBSET; EXTENSION] THEN
5064     REWRITE_TAC[IN_UNIONS; EXISTS_IN_IMAGE] THEN SET_TAC[];
5065     DISCH_THEN(X_CHOOSE_THEN `g:(real^N->bool)->bool` MP_TAC) THEN
5066     FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (\t:real^N->bool. UNIV DIFF t) g`) THEN
5067     ASM_CASES_TAC `FINITE(g:(real^N->bool)->bool)` THEN
5068     ASM_SIMP_TAC[FINITE_IMAGE] THEN ONCE_REWRITE_TAC[SUBSET; EXTENSION] THEN
5069     REWRITE_TAC[FORALL_IN_IMAGE; IN_INTER; IN_INTERS; IN_IMAGE; IN_DIFF;
5070                 IN_UNIV; NOT_IN_EMPTY; lemma; UNWIND_THM1; IN_UNIONS] THEN
5071     SET_TAC[]]);;
5072
5073 let CLOSED_IMP_FIP = prove
5074  (`!s:real^N->bool f.
5075         closed s /\
5076         (!t. t IN f ==> closed t) /\ (?t. t IN f /\ bounded t) /\
5077         (!f'. FINITE f' /\ f' SUBSET f ==> ~(s INTER (INTERS f') = {}))
5078         ==> ~(s INTER (INTERS f) = {})`,
5079   REPEAT GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC(SET_RULE
5080    `~((s INTER t) INTER u = {}) ==> ~(s INTER u = {})`) THEN
5081   MATCH_MP_TAC COMPACT_IMP_FIP THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
5082    [ASM_MESON_TAC[CLOSED_INTER_COMPACT; COMPACT_EQ_BOUNDED_CLOSED];
5083     REWRITE_TAC[INTER_ASSOC] THEN ONCE_REWRITE_TAC[GSYM INTERS_INSERT]] THEN
5084   GEN_TAC THEN STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
5085   ASM_SIMP_TAC[FINITE_INSERT; INSERT_SUBSET]);;
5086
5087 let CLOSED_IMP_FIP_COMPACT = prove
5088  (`!s:real^N->bool f.
5089         closed s /\ (!t. t IN f ==> compact t) /\
5090         (!f'. FINITE f' /\ f' SUBSET f ==> ~(s INTER (INTERS f') = {}))
5091         ==> ~(s INTER (INTERS f) = {})`,
5092   REPEAT GEN_TAC THEN
5093   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
5094   ASM_SIMP_TAC[SUBSET_EMPTY; INTERS_0; INTER_UNIV] THENL
5095    [MESON_TAC[FINITE_EMPTY]; ALL_TAC] THEN
5096   STRIP_TAC THEN MATCH_MP_TAC CLOSED_IMP_FIP THEN
5097   ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; MEMBER_NOT_EMPTY]);;
5098
5099 let CLOSED_FIP = prove
5100  (`!f. (!t:real^N->bool. t IN f ==> closed t) /\ (?t. t IN f /\ bounded t) /\
5101        (!f'. FINITE f' /\ f' SUBSET f ==> ~(INTERS f' = {}))
5102        ==> ~(INTERS f = {})`,
5103   GEN_TAC THEN DISCH_TAC THEN
5104   ONCE_REWRITE_TAC[SET_RULE `s = {} <=> UNIV INTER s = {}`] THEN
5105   MATCH_MP_TAC CLOSED_IMP_FIP THEN ASM_REWRITE_TAC[CLOSED_UNIV; INTER_UNIV]);;
5106
5107 let COMPACT_FIP = prove
5108  (`!f. (!t:real^N->bool. t IN f ==> compact t) /\
5109        (!f'. FINITE f' /\ f' SUBSET f ==> ~(INTERS f' = {}))
5110        ==> ~(INTERS f = {})`,
5111   GEN_TAC THEN DISCH_TAC THEN
5112   ONCE_REWRITE_TAC[SET_RULE `s = {} <=> UNIV INTER s = {}`] THEN
5113   MATCH_MP_TAC CLOSED_IMP_FIP_COMPACT THEN
5114   ASM_REWRITE_TAC[CLOSED_UNIV; INTER_UNIV]);;
5115
5116 (* ------------------------------------------------------------------------- *)
5117 (* Bounded closed nest property (proof does not use Heine-Borel).            *)
5118 (* ------------------------------------------------------------------------- *)
5119
5120 let BOUNDED_CLOSED_NEST = prove
5121  (`!s. (!n. closed(s n)) /\ (!n. ~(s n = {})) /\
5122        (!m n. m <= n ==> s(n) SUBSET s(m)) /\
5123        bounded(s 0)
5124        ==> ?a:real^N. !n:num. a IN s(n)`,
5125   GEN_TAC THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; SKOLEM_THM] THEN
5126   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5127   DISCH_THEN(CONJUNCTS_THEN2
5128      (X_CHOOSE_TAC `a:num->real^N`) STRIP_ASSUME_TAC) THEN
5129   SUBGOAL_THEN `compact(s 0:real^N->bool)` MP_TAC THENL
5130    [ASM_MESON_TAC[BOUNDED_CLOSED_IMP_COMPACT]; ALL_TAC] THEN
5131   REWRITE_TAC[compact] THEN
5132   DISCH_THEN(MP_TAC o SPEC `a:num->real^N`) THEN
5133   ANTS_TAC THENL [ASM_MESON_TAC[SUBSET; LE_0]; ALL_TAC] THEN
5134   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real^N` THEN
5135   REWRITE_TAC[LIM_SEQUENTIALLY; o_THM] THEN
5136   DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN
5137   GEN_REWRITE_TAC I [TAUT `p <=> ~(~p)`] THEN
5138   GEN_REWRITE_TAC RAND_CONV [NOT_FORALL_THM] THEN
5139   DISCH_THEN(X_CHOOSE_THEN `N:num` MP_TAC) THEN
5140   MP_TAC(ISPECL [`l:real^N`; `(s:num->real^N->bool) N`]
5141                 CLOSED_APPROACHABLE) THEN
5142   ASM_MESON_TAC[SUBSET; LE_REFL; LE_TRANS; LE_CASES; MONOTONE_BIGGER]);;
5143
5144 (* ------------------------------------------------------------------------- *)
5145 (* Decreasing case does not even need compactness, just completeness.        *)
5146 (* ------------------------------------------------------------------------- *)
5147
5148 let DECREASING_CLOSED_NEST = prove
5149  (`!s. (!n. closed(s n)) /\ (!n. ~(s n = {})) /\
5150        (!m n. m <= n ==> s(n) SUBSET s(m)) /\
5151        (!e. &0 < e ==> ?n. !x y. x IN s(n) /\ y IN s(n) ==> dist(x,y) < e)
5152        ==> ?a:real^N. !n:num. a IN s(n)`,
5153   GEN_TAC THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; SKOLEM_THM] THEN
5154   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5155   DISCH_THEN(CONJUNCTS_THEN2
5156      (X_CHOOSE_TAC `a:num->real^N`) STRIP_ASSUME_TAC) THEN
5157   SUBGOAL_THEN `?l:real^N. (a --> l) sequentially` MP_TAC THENL
5158    [ASM_MESON_TAC[cauchy; GE; SUBSET; LE_TRANS; LE_REFL;
5159                   complete; COMPLETE_UNIV; IN_UNIV];
5160     ASM_MESON_TAC[LIM_SEQUENTIALLY; CLOSED_APPROACHABLE;
5161                   SUBSET; LE_REFL; LE_TRANS; LE_CASES]]);;
5162
5163 (* ------------------------------------------------------------------------- *)
5164 (* Strengthen it to the intersection actually being a singleton.             *)
5165 (* ------------------------------------------------------------------------- *)
5166
5167 let DECREASING_CLOSED_NEST_SING = prove
5168  (`!s. (!n. closed(s n)) /\ (!n. ~(s n = {})) /\
5169        (!m n. m <= n ==> s(n) SUBSET s(m)) /\
5170        (!e. &0 < e ==> ?n. !x y. x IN s(n) /\ y IN s(n) ==> dist(x,y) < e)
5171        ==> ?a:real^N. INTERS {t | ?n:num. t = s n} = {a}`,
5172   GEN_TAC THEN DISCH_TAC THEN
5173   FIRST_ASSUM(MP_TAC o MATCH_MP DECREASING_CLOSED_NEST) THEN
5174   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
5175   DISCH_TAC THEN REWRITE_TAC[EXTENSION; IN_INTERS; IN_SING; IN_ELIM_THM] THEN
5176   ASM_MESON_TAC[DIST_POS_LT; REAL_LT_REFL; SUBSET; LE_CASES]);;
5177
5178 (* ------------------------------------------------------------------------- *)
5179 (* A version for a more general chain, not indexed by N.                     *)
5180 (* ------------------------------------------------------------------------- *)
5181
5182 let BOUNDED_CLOSED_CHAIN = prove
5183  (`!f b:real^N->bool.
5184         (!s. s IN f ==> closed s /\ ~(s = {})) /\
5185         (!s t. s IN f /\ t IN f ==> s SUBSET t \/ t SUBSET s) /\
5186          b IN f /\ bounded b
5187          ==> ~(INTERS f = {})`,
5188   REPEAT GEN_TAC THEN STRIP_TAC THEN
5189   SUBGOAL_THEN `~(b INTER (INTERS f):real^N->bool = {})` MP_TAC THENL
5190    [ALL_TAC; SET_TAC[]] THEN
5191   MATCH_MP_TAC COMPACT_IMP_FIP THEN
5192   ASM_SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
5193   X_GEN_TAC `u:(real^N->bool)->bool` THEN STRIP_TAC THEN
5194   SUBGOAL_THEN `?s:real^N->bool. s IN f /\ !t. t IN u ==> s SUBSET t`
5195   MP_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
5196   UNDISCH_TAC `(u:(real^N->bool)->bool) SUBSET f` THEN
5197   UNDISCH_TAC `FINITE(u:(real^N->bool)->bool)` THEN
5198   SPEC_TAC(`u:(real^N->bool)->bool`,`u:(real^N->bool)->bool`) THEN
5199   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5200   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5201   MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `u:(real^N->bool)->bool`] THEN
5202   REWRITE_TAC[INSERT_SUBSET] THEN
5203   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
5204   ASM_REWRITE_TAC[] THEN
5205   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
5206   DISCH_THEN(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
5207   FIRST_X_ASSUM(MP_TAC o SPECL [`s:real^N->bool`; `t:real^N->bool`]) THEN
5208   ASM SET_TAC[]);;
5209
5210 (* ------------------------------------------------------------------------- *)
5211 (* Analogous things directly for compactness.                                *)
5212 (* ------------------------------------------------------------------------- *)
5213
5214 let COMPACT_CHAIN = prove
5215  (`!f:(real^N->bool)->bool.
5216         (!s. s IN f ==> compact s /\ ~(s = {})) /\
5217         (!s t. s IN f /\ t IN f ==> s SUBSET t \/ t SUBSET s)
5218         ==> ~(INTERS f = {})`,
5219   GEN_TAC THEN REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN STRIP_TAC THEN
5220   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
5221    [ASM_REWRITE_TAC[INTERS_0] THEN SET_TAC[];
5222     MATCH_MP_TAC BOUNDED_CLOSED_CHAIN THEN ASM SET_TAC[]]);;
5223
5224 let COMPACT_NEST = prove
5225  (`!s. (!n. compact(s n) /\ ~(s n = {})) /\
5226        (!m n. m <= n ==> s n SUBSET s m)
5227        ==> ~(INTERS {s n | n IN (:num)} = {})`,
5228   GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC COMPACT_CHAIN THEN
5229   ASM_SIMP_TAC[FORALL_IN_GSPEC; IN_UNIV; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
5230   MATCH_MP_TAC WLOG_LE THEN ASM_MESON_TAC[]);;
5231
5232 (* ------------------------------------------------------------------------- *)
5233 (* Cauchy-type criteria for *uniform* convergence.                           *)
5234 (* ------------------------------------------------------------------------- *)
5235
5236 let UNIFORMLY_CONVERGENT_EQ_CAUCHY = prove
5237  (`!P s:num->A->real^N.
5238          (?l. !e. &0 < e
5239                   ==> ?N. !n x. N <= n /\ P x ==> dist(s n x,l x) < e) <=>
5240          (!e. &0 < e
5241               ==> ?N. !m n x. N <= m /\ N <= n /\ P x
5242                               ==> dist(s m x,s n x) < e)`,
5243   REPEAT GEN_TAC THEN EQ_TAC THENL
5244    [DISCH_THEN(X_CHOOSE_TAC `l:A->real^N`) THEN X_GEN_TAC `e:real` THEN
5245     DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
5246     ASM_REWRITE_TAC[REAL_HALF] THEN MESON_TAC[DIST_TRIANGLE_HALF_L];
5247     ALL_TAC] THEN
5248   DISCH_TAC THEN
5249   SUBGOAL_THEN `!x:A. P x ==> cauchy (\n. s n x :real^N)` MP_TAC THENL
5250    [REWRITE_TAC[cauchy; GE] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
5251   REWRITE_TAC[GSYM CONVERGENT_EQ_CAUCHY; LIM_SEQUENTIALLY] THEN
5252   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
5253   REWRITE_TAC[SKOLEM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
5254   X_GEN_TAC `l:A->real^N` THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN
5255   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
5256   ASM_REWRITE_TAC[REAL_HALF] THEN MATCH_MP_TAC MONO_EXISTS THEN
5257   X_GEN_TAC `N:num` THEN STRIP_TAC THEN
5258   MAP_EVERY X_GEN_TAC [`n:num`; `x:A`] THEN STRIP_TAC THEN
5259   FIRST_X_ASSUM(MP_TAC o SPEC `x:A`) THEN ASM_REWRITE_TAC[] THEN
5260   DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
5261   DISCH_THEN(X_CHOOSE_TAC `M:num`) THEN
5262   FIRST_X_ASSUM(MP_TAC o SPECL [`n:num`; `N + M:num`; `x:A`]) THEN
5263   ASM_REWRITE_TAC[LE_ADD] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN
5264   FIRST_X_ASSUM(MP_TAC o SPEC `M + N:num`) THEN REWRITE_TAC[LE_ADD] THEN
5265   ASM_MESON_TAC[DIST_TRIANGLE_HALF_L; DIST_SYM]);;
5266
5267 let UNIFORMLY_CONVERGENT_EQ_CAUCHY_ALT = prove
5268  (`!P s:num->A->real^N.
5269          (?l. !e. &0 < e
5270                   ==> ?N. !n x. N <= n /\ P x ==> dist(s n x,l x) < e) <=>
5271          (!e. &0 < e
5272               ==> ?N. !m n x. N <= m /\ N <= n /\ m < n /\ P x
5273                               ==> dist(s m x,s n x) < e)`,
5274   REPEAT GEN_TAC THEN REWRITE_TAC[UNIFORMLY_CONVERGENT_EQ_CAUCHY] THEN
5275   EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5276   FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
5277   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN DISCH_TAC THEN
5278   ASM_SIMP_TAC[] THEN MATCH_MP_TAC WLOG_LT THEN
5279   ASM_SIMP_TAC[DIST_REFL] THEN MESON_TAC[DIST_SYM]);;
5280
5281 let UNIFORMLY_CAUCHY_IMP_UNIFORMLY_CONVERGENT = prove
5282  (`!P (s:num->A->real^N) l.
5283     (!e. &0 < e
5284          ==> ?N. !m n x. N <= m /\ N <= n /\ P x ==> dist(s m x,s n x) < e) /\
5285     (!x. P x ==> !e. &0 < e ==> ?N. !n. N <= n ==> dist(s n x,l x) < e)
5286     ==> (!e. &0 < e ==> ?N. !n x. N <= n /\ P x ==> dist(s n x,l x) < e)`,
5287   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM UNIFORMLY_CONVERGENT_EQ_CAUCHY] THEN
5288   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `l':A->real^N`) ASSUME_TAC) THEN
5289   SUBGOAL_THEN `!x. P x ==> (l:A->real^N) x = l' x` MP_TAC THENL
5290    [ALL_TAC; ASM_MESON_TAC[]] THEN
5291   REPEAT STRIP_TAC THEN MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
5292   EXISTS_TAC `\n. (s:num->A->real^N) n x` THEN
5293   REWRITE_TAC[LIM_SEQUENTIALLY; TRIVIAL_LIMIT_SEQUENTIALLY] THEN
5294   ASM_MESON_TAC[]);;
5295
5296 (* ------------------------------------------------------------------------- *)
5297 (* Define continuity over a net to take in restrictions of the set.          *)
5298 (* ------------------------------------------------------------------------- *)
5299
5300 parse_as_infix ("continuous",(12,"right"));;
5301
5302 let continuous = new_definition
5303   `f continuous net <=> (f --> f(netlimit net)) net`;;
5304
5305 let CONTINUOUS_TRIVIAL_LIMIT = prove
5306  (`!f net. trivial_limit net ==> f continuous net`,
5307   SIMP_TAC[continuous; LIM]);;
5308
5309 let CONTINUOUS_WITHIN = prove
5310  (`!f x:real^M. f continuous (at x within s) <=> (f --> f(x)) (at x within s)`,
5311   REPEAT GEN_TAC THEN REWRITE_TAC[continuous] THEN
5312   ASM_CASES_TAC `trivial_limit(at (x:real^M) within s)` THENL
5313    [ASM_REWRITE_TAC[LIM]; ASM_SIMP_TAC[NETLIMIT_WITHIN]]);;
5314
5315 let CONTINUOUS_AT = prove
5316  (`!f (x:real^N). f continuous (at x) <=> (f --> f(x)) (at x)`,
5317   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
5318   REWRITE_TAC[CONTINUOUS_WITHIN; IN_UNIV]);;
5319
5320 let CONTINUOUS_AT_WITHIN = prove
5321  (`!f:real^M->real^N x s.
5322         f continuous (at x) ==> f continuous (at x within s)`,
5323   SIMP_TAC[LIM_AT_WITHIN; CONTINUOUS_AT; CONTINUOUS_WITHIN]);;
5324
5325 let CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL = prove
5326  (`!a s. closed s /\ ~(a IN s) ==> f continuous (at a within s)`,
5327   ASM_SIMP_TAC[continuous; LIM; LIM_WITHIN_CLOSED_TRIVIAL]);;
5328
5329 let CONTINUOUS_TRANSFORM_WITHIN = prove
5330  (`!f g:real^M->real^N s x d.
5331         &0 < d /\ x IN s /\
5332         (!x'. x' IN s /\ dist(x',x) < d ==> f(x') = g(x')) /\
5333         f continuous (at x within s)
5334         ==> g continuous (at x within s)`,
5335   REWRITE_TAC[CONTINUOUS_WITHIN] THEN
5336   MESON_TAC[LIM_TRANSFORM_WITHIN; DIST_REFL]);;
5337
5338 let CONTINUOUS_TRANSFORM_AT = prove
5339  (`!f g:real^M->real^N x d.
5340         &0 < d /\ (!x'. dist(x',x) < d ==> f(x') = g(x')) /\
5341         f continuous (at x)
5342         ==> g continuous (at x)`,
5343   REWRITE_TAC[CONTINUOUS_AT] THEN
5344   MESON_TAC[LIM_TRANSFORM_AT; DIST_REFL]);;
5345
5346 let CONTINUOUS_TRANSFORM_WITHIN_OPEN = prove
5347  (`!f g:real^M->real^N s a.
5348         open s /\ a IN s /\
5349         (!x. x IN s ==> f x = g x) /\
5350         f continuous at a
5351         ==> g continuous at a`,
5352   MESON_TAC[CONTINUOUS_AT; LIM_TRANSFORM_WITHIN_OPEN]);;
5353
5354 let CONTINUOUS_TRANSFORM_WITHIN_OPEN_IN = prove
5355  (`!f g:real^M->real^N s t a.
5356         open_in (subtopology euclidean t) s /\ a IN s /\
5357         (!x. x IN s ==> f x = g x) /\
5358         f continuous (at a within t)
5359         ==> g continuous (at a within t)`,
5360   MESON_TAC[CONTINUOUS_WITHIN; LIM_TRANSFORM_WITHIN_OPEN_IN]);;
5361
5362 (* ------------------------------------------------------------------------- *)
5363 (* Derive the epsilon-delta forms, which we often use as "definitions"       *)
5364 (* ------------------------------------------------------------------------- *)
5365
5366 let continuous_within = prove
5367  (`f continuous (at x within s) <=>
5368         !e. &0 < e
5369             ==> ?d. &0 < d /\
5370                     !x'. x' IN s /\ dist(x',x) < d ==> dist(f(x'),f(x)) < e`,
5371   REWRITE_TAC[CONTINUOUS_WITHIN; LIM_WITHIN] THEN
5372   REWRITE_TAC[GSYM DIST_NZ] THEN MESON_TAC[DIST_REFL]);;
5373
5374 let continuous_at = prove
5375  (`f continuous (at x) <=>
5376         !e. &0 < e ==> ?d. &0 < d /\
5377                            !x'. dist(x',x) < d ==> dist(f(x'),f(x)) < e`,
5378   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
5379   REWRITE_TAC[continuous_within; IN_UNIV]);;
5380
5381 (* ------------------------------------------------------------------------- *)
5382 (* Versions in terms of open balls.                                          *)
5383 (* ------------------------------------------------------------------------- *)
5384
5385 let CONTINUOUS_WITHIN_BALL = prove
5386  (`!f s x. f continuous (at x within s) <=>
5387                 !e. &0 < e
5388                     ==> ?d. &0 < d /\
5389                             IMAGE f (ball(x,d) INTER s) SUBSET ball(f x,e)`,
5390   SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_BALL; continuous_within; IN_INTER] THEN
5391   MESON_TAC[DIST_SYM]);;
5392
5393 let CONTINUOUS_AT_BALL = prove
5394  (`!f x. f continuous (at x) <=>
5395                 !e. &0 < e
5396                     ==> ?d. &0 < d /\
5397                             IMAGE f (ball(x,d)) SUBSET ball(f x,e)`,
5398   SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_BALL; continuous_at] THEN
5399   MESON_TAC[DIST_SYM]);;
5400
5401 (* ------------------------------------------------------------------------- *)
5402 (* For setwise continuity, just start from the epsilon-delta definitions.    *)
5403 (* ------------------------------------------------------------------------- *)
5404
5405 parse_as_infix ("continuous_on",(12,"right"));;
5406 parse_as_infix ("uniformly_continuous_on",(12,"right"));;
5407
5408 let continuous_on = new_definition
5409   `f continuous_on s <=>
5410         !x. x IN s ==> !e. &0 < e
5411                            ==> ?d. &0 < d /\
5412                                    !x'. x' IN s /\ dist(x',x) < d
5413                                         ==> dist(f(x'),f(x)) < e`;;
5414
5415 let uniformly_continuous_on = new_definition
5416   `f uniformly_continuous_on s <=>
5417         !e. &0 < e
5418             ==> ?d. &0 < d /\
5419                     !x x'. x IN s /\ x' IN s /\ dist(x',x) < d
5420                            ==> dist(f(x'),f(x)) < e`;;
5421
5422 (* ------------------------------------------------------------------------- *)
5423 (* Some simple consequential lemmas.                                         *)
5424 (* ------------------------------------------------------------------------- *)
5425
5426 let UNIFORMLY_CONTINUOUS_IMP_CONTINUOUS = prove
5427  (`!f s. f uniformly_continuous_on s ==> f continuous_on s`,
5428   REWRITE_TAC[uniformly_continuous_on; continuous_on] THEN MESON_TAC[]);;
5429
5430 let CONTINUOUS_AT_IMP_CONTINUOUS_ON = prove
5431  (`!f s. (!x. x IN s ==> f continuous (at x)) ==> f continuous_on s`,
5432   REWRITE_TAC[continuous_at; continuous_on] THEN MESON_TAC[]);;
5433
5434 let CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN = prove
5435  (`!f s. f continuous_on s <=> !x. x IN s ==> f continuous (at x within s)`,
5436   REWRITE_TAC[continuous_on; continuous_within]);;
5437
5438 let CONTINUOUS_ON = prove
5439  (`!f (s:real^N->bool).
5440         f continuous_on s <=> !x. x IN s ==> (f --> f(x)) (at x within s)`,
5441   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_WITHIN]);;
5442
5443 let CONTINUOUS_ON_EQ_CONTINUOUS_AT = prove
5444  (`!f:real^M->real^N s.
5445       open s ==> (f continuous_on s <=> (!x. x IN s ==> f continuous (at x)))`,
5446   SIMP_TAC[CONTINUOUS_ON; CONTINUOUS_AT; LIM_WITHIN_OPEN]);;
5447
5448 let CONTINUOUS_WITHIN_SUBSET = prove
5449  (`!f s t x. f continuous (at x within s) /\ t SUBSET s
5450              ==> f continuous (at x within t)`,
5451    REWRITE_TAC[CONTINUOUS_WITHIN] THEN MESON_TAC[LIM_WITHIN_SUBSET]);;
5452
5453 let CONTINUOUS_ON_SUBSET = prove
5454  (`!f s t. f continuous_on s /\ t SUBSET s ==> f continuous_on t`,
5455   REWRITE_TAC[CONTINUOUS_ON] THEN MESON_TAC[SUBSET; LIM_WITHIN_SUBSET]);;
5456
5457 let UNIFORMLY_CONTINUOUS_ON_SUBSET = prove
5458  (`!f s t. f uniformly_continuous_on s /\ t SUBSET s
5459            ==> f uniformly_continuous_on t`,
5460   REWRITE_TAC[uniformly_continuous_on] THEN
5461   MESON_TAC[SUBSET; LIM_WITHIN_SUBSET]);;
5462
5463 let CONTINUOUS_ON_INTERIOR = prove
5464  (`!f:real^M->real^N s x.
5465         f continuous_on s /\ x IN interior(s) ==> f continuous at x`,
5466   REWRITE_TAC[interior; IN_ELIM_THM] THEN
5467   MESON_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT; CONTINUOUS_ON_SUBSET]);;
5468
5469 let CONTINUOUS_ON_EQ = prove
5470  (`!f g s. (!x. x IN s ==> f(x) = g(x)) /\ f continuous_on s
5471            ==> g continuous_on s`,
5472   SIMP_TAC[continuous_on; IMP_CONJ]);;
5473
5474 let UNIFORMLY_CONTINUOUS_ON_EQ = prove
5475  (`!f g s.
5476         (!x. x IN s ==> f x = g x) /\ f uniformly_continuous_on s
5477         ==> g uniformly_continuous_on s`,
5478   SIMP_TAC[uniformly_continuous_on; IMP_CONJ]);;
5479
5480 let CONTINUOUS_ON_SING = prove
5481  (`!f:real^M->real^N a. f continuous_on {a}`,
5482   SIMP_TAC[continuous_on; IN_SING; FORALL_UNWIND_THM2; DIST_REFL] THEN
5483   MESON_TAC[]);;
5484
5485 let CONTINUOUS_ON_EMPTY = prove
5486  (`!f:real^M->real^N. f continuous_on {}`,
5487   MESON_TAC[CONTINUOUS_ON_SING; EMPTY_SUBSET; CONTINUOUS_ON_SUBSET]);;
5488
5489 let CONTINUOUS_ON_NO_LIMPT = prove
5490  (`!f:real^M->real^N s.
5491      ~(?x. x limit_point_of s) ==> f continuous_on s`,
5492   REWRITE_TAC[continuous_on; LIMPT_APPROACHABLE] THEN MESON_TAC[DIST_REFL]);;
5493
5494 let CONTINUOUS_ON_FINITE = prove
5495  (`!f:real^M->real^N s. FINITE s ==> f continuous_on s`,
5496   MESON_TAC[CONTINUOUS_ON_NO_LIMPT; LIMIT_POINT_FINITE]);;
5497
5498 let CONTRACTION_IMP_CONTINUOUS_ON = prove
5499  (`!f:real^M->real^N.
5500         (!x y. x IN s /\ y IN s ==> dist(f x,f y) <= dist(x,y))
5501         ==> f continuous_on s`,
5502   SIMP_TAC[continuous_on] THEN MESON_TAC[REAL_LET_TRANS]);;
5503
5504 let ISOMETRY_ON_IMP_CONTINUOUS_ON = prove
5505  (`!f:real^M->real^N.
5506         (!x y. x IN s /\ y IN s ==> dist(f x,f y) = dist(x,y))
5507         ==> f continuous_on s`,
5508   SIMP_TAC[CONTRACTION_IMP_CONTINUOUS_ON; REAL_LE_REFL]);;
5509
5510 (* ------------------------------------------------------------------------- *)
5511 (* Characterization of various kinds of continuity in terms of sequences.    *)
5512 (* ------------------------------------------------------------------------- *)
5513
5514 let CONTINUOUS_WITHIN_SEQUENTIALLY = prove
5515  (`!f a:real^N.
5516         f continuous (at a within s) <=>
5517                 !x. (!n. x(n) IN s) /\ (x --> a) sequentially
5518                      ==> ((f o x) --> f(a)) sequentially`,
5519   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_within] THEN EQ_TAC THENL
5520    [REWRITE_TAC[LIM_SEQUENTIALLY; o_THM] THEN MESON_TAC[]; ALL_TAC] THEN
5521   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
5522   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
5523   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5524   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC `&1 / (&n + &1)`) THEN
5525   SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; REAL_OF_NUM_LE; REAL_POS; ARITH;
5526        REAL_ARITH `&0 <= n ==> &0 < n + &1`; NOT_FORALL_THM; SKOLEM_THM] THEN
5527   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[NOT_IMP; FORALL_AND_THM] THEN
5528   X_GEN_TAC `y:num->real^N` THEN REWRITE_TAC[LIM_SEQUENTIALLY; o_THM] THEN
5529   STRIP_TAC THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[LE_REFL]] THEN
5530   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC FORALL_POS_MONO_1 THEN
5531   CONJ_TAC THENL [ASM_MESON_TAC[REAL_LT_TRANS]; ALL_TAC] THEN
5532   X_GEN_TAC `n:num` THEN EXISTS_TAC `n:num` THEN X_GEN_TAC `m:num` THEN
5533   DISCH_TAC THEN MATCH_MP_TAC REAL_LTE_TRANS THEN
5534   EXISTS_TAC `&1 / (&m + &1)` THEN ASM_REWRITE_TAC[] THEN
5535   ASM_SIMP_TAC[REAL_LE_INV2; real_div; REAL_ARITH `&0 <= x ==> &0 < x + &1`;
5536                REAL_POS; REAL_MUL_LID; REAL_LE_RADD; REAL_OF_NUM_LE]);;
5537
5538 let CONTINUOUS_AT_SEQUENTIALLY = prove
5539  (`!f a:real^N.
5540         f continuous (at a) <=>
5541               !x. (x --> a) sequentially
5542                   ==> ((f o x) --> f(a)) sequentially`,
5543   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
5544   REWRITE_TAC[CONTINUOUS_WITHIN_SEQUENTIALLY; IN_UNIV]);;
5545
5546 let CONTINUOUS_ON_SEQUENTIALLY = prove
5547  (`!f s:real^N->bool.
5548         f continuous_on s <=>
5549               !x a. a IN s /\ (!n. x(n) IN s) /\ (x --> a) sequentially
5550                     ==> ((f o x) --> f(a)) sequentially`,
5551   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
5552               CONTINUOUS_WITHIN_SEQUENTIALLY] THEN MESON_TAC[]);;
5553
5554 let UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY = prove
5555  (`!f s:real^N->bool.
5556         f uniformly_continuous_on s <=>
5557               !x y. (!n. x(n) IN s) /\ (!n. y(n) IN s) /\
5558                     ((\n. x(n) - y(n)) --> vec 0) sequentially
5559                     ==> ((\n. f(x(n)) - f(y(n))) --> vec 0) sequentially`,
5560   REPEAT GEN_TAC THEN REWRITE_TAC[uniformly_continuous_on] THEN
5561   REWRITE_TAC[LIM_SEQUENTIALLY; dist; VECTOR_SUB_RZERO] THEN
5562   EQ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
5563   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
5564   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
5565   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5566   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC `&1 / (&n + &1)`) THEN
5567   SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; REAL_OF_NUM_LE; REAL_POS; ARITH;
5568        REAL_ARITH `&0 <= n ==> &0 < n + &1`; NOT_FORALL_THM; SKOLEM_THM] THEN
5569   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:num->real^N` THEN
5570   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:num->real^N` THEN
5571   REWRITE_TAC[NOT_IMP; FORALL_AND_THM] THEN STRIP_TAC THEN
5572   ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN CONJ_TAC THENL
5573    [MATCH_MP_TAC FORALL_POS_MONO_1 THEN
5574     CONJ_TAC THENL [ASM_MESON_TAC[REAL_LT_TRANS]; ALL_TAC] THEN
5575     X_GEN_TAC `n:num` THEN EXISTS_TAC `n:num` THEN X_GEN_TAC `m:num` THEN
5576     DISCH_TAC THEN MATCH_MP_TAC REAL_LTE_TRANS THEN
5577     EXISTS_TAC `&1 / (&m + &1)` THEN ASM_REWRITE_TAC[] THEN
5578     ASM_SIMP_TAC[REAL_LE_INV2; real_div; REAL_ARITH `&0 <= x ==> &0 < x + &1`;
5579                  REAL_POS; REAL_MUL_LID; REAL_LE_RADD; REAL_OF_NUM_LE];
5580     EXISTS_TAC `e:real` THEN ASM_REWRITE_TAC[] THEN
5581     EXISTS_TAC `\x:num. x` THEN ASM_REWRITE_TAC[LE_REFL]]);;
5582
5583 let LIM_CONTINUOUS_FUNCTION = prove
5584  (`!f net g l.
5585         f continuous (at l) /\ (g --> l) net ==> ((\x. f(g x)) --> f l) net`,
5586   REWRITE_TAC[tendsto; continuous_at; eventually] THEN MESON_TAC[]);;
5587
5588 (* ------------------------------------------------------------------------- *)
5589 (* Combination results for pointwise continuity.                             *)
5590 (* ------------------------------------------------------------------------- *)
5591
5592 let CONTINUOUS_CONST = prove
5593  (`!net c. (\x. c) continuous net`,
5594   REWRITE_TAC[continuous; LIM_CONST]);;
5595
5596 let CONTINUOUS_CMUL = prove
5597  (`!f c net. f continuous net ==> (\x. c % f(x)) continuous net`,
5598   REWRITE_TAC[continuous; LIM_CMUL]);;
5599
5600 let CONTINUOUS_NEG = prove
5601  (`!f net. f continuous net ==> (\x. --(f x)) continuous net`,
5602   REWRITE_TAC[continuous; LIM_NEG]);;
5603
5604 let CONTINUOUS_ADD = prove
5605  (`!f g net. f continuous net /\ g continuous net
5606            ==> (\x. f(x) + g(x)) continuous net`,
5607   REWRITE_TAC[continuous; LIM_ADD]);;
5608
5609 let CONTINUOUS_SUB = prove
5610  (`!f g net. f continuous net /\ g continuous net
5611            ==> (\x. f(x) - g(x)) continuous net`,
5612   REWRITE_TAC[continuous; LIM_SUB]);;
5613
5614 let CONTINUOUS_ABS = prove
5615  (`!(f:A->real^N) net.
5616         f continuous net
5617         ==> (\x. (lambda i. abs(f(x)$i)):real^N) continuous net`,
5618   REWRITE_TAC[continuous; LIM_ABS]);;
5619
5620 let CONTINUOUS_MAX = prove
5621  (`!(f:A->real^N) (g:A->real^N) net.
5622         f continuous net /\ g continuous net
5623         ==> (\x. (lambda i. max (f(x)$i) (g(x)$i)):real^N) continuous net`,
5624   REWRITE_TAC[continuous; LIM_MAX]);;
5625
5626 let CONTINUOUS_MIN = prove
5627  (`!(f:A->real^N) (g:A->real^N) net.
5628         f continuous net /\ g continuous net
5629         ==> (\x. (lambda i. min (f(x)$i) (g(x)$i)):real^N) continuous net`,
5630   REWRITE_TAC[continuous; LIM_MIN]);;
5631
5632 let CONTINUOUS_VSUM = prove
5633  (`!net f s. FINITE s /\ (!a. a IN s ==> (f a) continuous net)
5634              ==> (\x. vsum s (\a. f a x)) continuous net`,
5635   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
5636   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5637   SIMP_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY; VSUM_CLAUSES;
5638            CONTINUOUS_CONST; CONTINUOUS_ADD; ETA_AX]);;
5639
5640 (* ------------------------------------------------------------------------- *)
5641 (* Same thing for setwise continuity.                                        *)
5642 (* ------------------------------------------------------------------------- *)
5643
5644 let CONTINUOUS_ON_CONST = prove
5645  (`!s c. (\x. c) continuous_on s`,
5646   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_CONST]);;
5647
5648 let CONTINUOUS_ON_CMUL = prove
5649  (`!f c s. f continuous_on s ==> (\x. c % f(x)) continuous_on s`,
5650   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_CMUL]);;
5651
5652 let CONTINUOUS_ON_NEG = prove
5653  (`!f s. f continuous_on s
5654          ==> (\x. --(f x)) continuous_on s`,
5655   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_NEG]);;
5656
5657 let CONTINUOUS_ON_ADD = prove
5658  (`!f g s. f continuous_on s /\ g continuous_on s
5659            ==> (\x. f(x) + g(x)) continuous_on s`,
5660   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_ADD]);;
5661
5662 let CONTINUOUS_ON_SUB = prove
5663  (`!f g s. f continuous_on s /\ g continuous_on s
5664            ==> (\x. f(x) - g(x)) continuous_on s`,
5665   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_SUB]);;
5666
5667 let CONTINUOUS_ON_ABS = prove
5668  (`!f:real^M->real^N s.
5669         f continuous_on s
5670         ==> (\x. (lambda i. abs(f(x)$i)):real^N) continuous_on s`,
5671   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_ABS]);;
5672
5673 let CONTINUOUS_ON_MAX = prove
5674  (`!f:real^M->real^N g:real^M->real^N s.
5675         f continuous_on s /\ g continuous_on s
5676         ==> (\x. (lambda i. max (f(x)$i) (g(x)$i)):real^N)
5677             continuous_on s`,
5678   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_MAX]);;
5679
5680 let CONTINUOUS_ON_MIN = prove
5681  (`!f:real^M->real^N g:real^M->real^N s.
5682         f continuous_on s /\ g continuous_on s
5683         ==> (\x. (lambda i. min (f(x)$i) (g(x)$i)):real^N)
5684             continuous_on s`,
5685   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_MIN]);;
5686
5687 let CONTINUOUS_ON_VSUM = prove
5688  (`!t f s. FINITE s /\ (!a. a IN s ==> (f a) continuous_on t)
5689              ==> (\x. vsum s (\a. f a x)) continuous_on t`,
5690   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_VSUM]);;
5691
5692 (* ------------------------------------------------------------------------- *)
5693 (* Same thing for uniform continuity, using sequential formulations.         *)
5694 (* ------------------------------------------------------------------------- *)
5695
5696 let UNIFORMLY_CONTINUOUS_ON_CONST = prove
5697  (`!s c. (\x. c) uniformly_continuous_on s`,
5698   REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY; o_DEF;
5699               VECTOR_SUB_REFL; LIM_CONST]);;
5700
5701 let LINEAR_UNIFORMLY_CONTINUOUS_ON = prove
5702  (`!f:real^M->real^N s. linear f ==> f uniformly_continuous_on s`,
5703   REPEAT STRIP_TAC THEN
5704   ASM_SIMP_TAC[uniformly_continuous_on; dist; GSYM LINEAR_SUB] THEN
5705   FIRST_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o
5706         MATCH_MP LINEAR_BOUNDED_POS) THEN
5707   X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `e / B:real` THEN
5708   ASM_SIMP_TAC[REAL_LT_DIV] THEN
5709   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^M`] THEN STRIP_TAC THEN
5710   MATCH_MP_TAC REAL_LET_TRANS THEN
5711   EXISTS_TAC `B * norm(y - x:real^M)` THEN ASM_REWRITE_TAC[] THEN
5712   ASM_MESON_TAC[REAL_LT_RDIV_EQ; REAL_MUL_SYM]);;
5713
5714 let UNIFORMLY_CONTINUOUS_ON_COMPOSE = prove
5715  (`!f g s. f uniformly_continuous_on s /\
5716            g uniformly_continuous_on (IMAGE f s)
5717            ==> (g o f) uniformly_continuous_on s`,
5718   let lemma = prove
5719    (`(!y. ((?x. (y = f x) /\ P x) /\ Q y ==> R y)) <=>
5720      (!x. P x /\ Q (f x) ==> R (f x))`,
5721     MESON_TAC[]) in
5722   REPEAT GEN_TAC THEN
5723   REWRITE_TAC[uniformly_continuous_on; o_THM; IN_IMAGE] THEN
5724   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN REWRITE_TAC[lemma] THEN
5725   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`] THEN
5726   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN REWRITE_TAC[lemma] THEN
5727   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5728   MATCH_MP_TAC MONO_FORALL THEN
5729   X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
5730   ASM_MESON_TAC[]);;
5731
5732 let BILINEAR_UNIFORMLY_CONTINUOUS_ON_COMPOSE = prove
5733  (`!f:real^M->real^N g (h:real^N->real^P->real^Q) s.
5734            f uniformly_continuous_on s /\ g uniformly_continuous_on s /\
5735            bilinear h /\ bounded(IMAGE f s) /\ bounded(IMAGE g s)
5736            ==> (\x. h (f x) (g x)) uniformly_continuous_on s`,
5737   REPEAT STRIP_TAC THEN REWRITE_TAC[uniformly_continuous_on; dist] THEN
5738   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5739   SUBGOAL_THEN
5740    `!a b c d. (h:real^N->real^P->real^Q) a b - h c d =
5741               h (a - c) b + h c (b - d)`
5742    (fun th -> ONCE_REWRITE_TAC[th])
5743   THENL
5744    [FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP BILINEAR_LSUB th]) THEN
5745     FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP BILINEAR_RSUB th]) THEN
5746     VECTOR_ARITH_TAC;
5747     ALL_TAC] THEN
5748   FIRST_X_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o
5749     MATCH_MP BILINEAR_BOUNDED_POS) THEN
5750   UNDISCH_TAC `bounded(IMAGE (g:real^M->real^P) s)` THEN
5751   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
5752   REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE] THEN
5753   DISCH_THEN(X_CHOOSE_THEN `B1:real` STRIP_ASSUME_TAC) THEN
5754   DISCH_THEN(X_CHOOSE_THEN `B2:real` STRIP_ASSUME_TAC) THEN
5755   UNDISCH_TAC `(g:real^M->real^P) uniformly_continuous_on s` THEN
5756   UNDISCH_TAC `(f:real^M->real^N) uniformly_continuous_on s` THEN
5757   REWRITE_TAC[uniformly_continuous_on] THEN
5758   DISCH_THEN(MP_TAC o SPEC `e / &2 / &2 / B / B2`) THEN
5759   ASM_SIMP_TAC[REAL_LT_DIV; REAL_HALF; dist] THEN
5760   DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN
5761   DISCH_THEN(MP_TAC o SPEC `e / &2 / &2 / B / B1`) THEN
5762   ASM_SIMP_TAC[REAL_LT_DIV; REAL_HALF; dist] THEN
5763   DISCH_THEN(X_CHOOSE_THEN `d2:real` STRIP_ASSUME_TAC) THEN
5764   EXISTS_TAC `min d1 d2` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
5765   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^M`] THEN STRIP_TAC THEN
5766   REPEAT(FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^M`; `y:real^M`])) THEN
5767   ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
5768   MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC
5769    `B * e / &2 / &2 / B / B2 * B2 + B * B1 * e / &2 / &2 / B / B1` THEN
5770   CONJ_TAC THENL
5771    [MATCH_MP_TAC(NORM_ARITH
5772      `norm(x) <= a /\ norm(y) <= b ==> norm(x + y:real^N) <= a + b`) THEN
5773     CONJ_TAC THEN
5774     FIRST_X_ASSUM(fun th -> W(MP_TAC o PART_MATCH lhand th o lhand o snd)) THEN
5775     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
5776     MATCH_MP_TAC REAL_LE_LMUL THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN
5777     MATCH_MP_TAC REAL_LE_MUL2 THEN
5778     ASM_SIMP_TAC[REAL_LT_IMP_LE; NORM_POS_LE];
5779     ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
5780     ASM_REAL_ARITH_TAC]);;
5781
5782 let UNIFORMLY_CONTINUOUS_ON_MUL = prove
5783  (`!f g:real^M->real^N s.
5784         (lift o f) uniformly_continuous_on s /\ g uniformly_continuous_on s /\
5785         bounded(IMAGE (lift o f) s) /\ bounded(IMAGE g s)
5786         ==>  (\x. f x % g x) uniformly_continuous_on s`,
5787   REPEAT STRIP_TAC THEN
5788   MP_TAC(ISPECL
5789    [`lift o (f:real^M->real)`; `g:real^M->real^N`;
5790     `\c (v:real^N). drop c % v`; `s:real^M->bool`]
5791         BILINEAR_UNIFORMLY_CONTINUOUS_ON_COMPOSE) THEN
5792   ASM_REWRITE_TAC[o_THM; LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN
5793   REWRITE_TAC[bilinear; linear; DROP_ADD; DROP_CMUL] THEN VECTOR_ARITH_TAC);;
5794
5795 let UNIFORMLY_CONTINUOUS_ON_CMUL = prove
5796  (`!f c s. f uniformly_continuous_on s
5797            ==> (\x. c % f(x)) uniformly_continuous_on s`,
5798   REPEAT GEN_TAC THEN REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY] THEN
5799   REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
5800   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
5801   ASM_REWRITE_TAC[] THEN
5802   DISCH_THEN(MP_TAC o MATCH_MP LIM_CMUL) THEN
5803   ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; VECTOR_MUL_RZERO]);;
5804
5805 let UNIFORMLY_CONTINUOUS_ON_VMUL = prove
5806  (`!s:real^M->bool c v:real^N.
5807       (lift o c) uniformly_continuous_on s
5808       ==> (\x. c x % v) uniformly_continuous_on s`,
5809   REPEAT GEN_TAC THEN
5810   DISCH_THEN(MP_TAC o ISPEC `\x. (drop x % v:real^N)` o MATCH_MP
5811    (REWRITE_RULE[IMP_CONJ] UNIFORMLY_CONTINUOUS_ON_COMPOSE)) THEN
5812   REWRITE_TAC[o_DEF; LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN
5813   MATCH_MP_TAC LINEAR_UNIFORMLY_CONTINUOUS_ON THEN
5814   MATCH_MP_TAC LINEAR_VMUL_DROP THEN REWRITE_TAC[LINEAR_ID]);;
5815
5816 let UNIFORMLY_CONTINUOUS_ON_NEG = prove
5817  (`!f s. f uniformly_continuous_on s
5818          ==> (\x. --(f x)) uniformly_continuous_on s`,
5819   ONCE_REWRITE_TAC[VECTOR_NEG_MINUS1] THEN
5820   REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_CMUL]);;
5821
5822 let UNIFORMLY_CONTINUOUS_ON_ADD = prove
5823  (`!f g s. f uniformly_continuous_on s /\ g uniformly_continuous_on s
5824            ==> (\x. f(x) + g(x)) uniformly_continuous_on s`,
5825   REPEAT GEN_TAC THEN REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY] THEN
5826   REWRITE_TAC[AND_FORALL_THM] THEN
5827   REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
5828   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
5829   ASM_REWRITE_TAC[o_DEF] THEN DISCH_THEN(MP_TAC o MATCH_MP LIM_ADD) THEN
5830   MATCH_MP_TAC EQ_IMP THEN
5831   REWRITE_TAC[VECTOR_ADD_LID] THEN AP_THM_TAC THEN BINOP_TAC THEN
5832   REWRITE_TAC[FUN_EQ_THM] THEN VECTOR_ARITH_TAC);;
5833
5834 let UNIFORMLY_CONTINUOUS_ON_SUB = prove
5835  (`!f g s. f uniformly_continuous_on s /\ g uniformly_continuous_on s
5836            ==> (\x. f(x) - g(x)) uniformly_continuous_on s`,
5837   REWRITE_TAC[VECTOR_SUB] THEN
5838   SIMP_TAC[UNIFORMLY_CONTINUOUS_ON_NEG; UNIFORMLY_CONTINUOUS_ON_ADD]);;
5839
5840 let UNIFORMLY_CONTINUOUS_ON_VSUM = prove
5841  (`!t f s. FINITE s /\ (!a. a IN s ==> (f a) uniformly_continuous_on t)
5842              ==> (\x. vsum s (\a. f a x)) uniformly_continuous_on t`,
5843   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
5844   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5845   SIMP_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY; VSUM_CLAUSES;
5846        UNIFORMLY_CONTINUOUS_ON_CONST; UNIFORMLY_CONTINUOUS_ON_ADD; ETA_AX]);;
5847
5848 (* ------------------------------------------------------------------------- *)
5849 (* Identity function is continuous in every sense.                           *)
5850 (* ------------------------------------------------------------------------- *)
5851
5852 let CONTINUOUS_WITHIN_ID = prove
5853  (`!a s. (\x. x) continuous (at a within s)`,
5854   REWRITE_TAC[continuous_within] THEN MESON_TAC[]);;
5855
5856 let CONTINUOUS_AT_ID = prove
5857  (`!a. (\x. x) continuous (at a)`,
5858   REWRITE_TAC[continuous_at] THEN MESON_TAC[]);;
5859
5860 let CONTINUOUS_ON_ID = prove
5861  (`!s. (\x. x) continuous_on s`,
5862   REWRITE_TAC[continuous_on] THEN MESON_TAC[]);;
5863
5864 let UNIFORMLY_CONTINUOUS_ON_ID = prove
5865  (`!s. (\x. x) uniformly_continuous_on s`,
5866   REWRITE_TAC[uniformly_continuous_on] THEN MESON_TAC[]);;
5867
5868 (* ------------------------------------------------------------------------- *)
5869 (* Continuity of all kinds is preserved under composition.                   *)
5870 (* ------------------------------------------------------------------------- *)
5871
5872 let CONTINUOUS_WITHIN_COMPOSE = prove
5873  (`!f g x s. f continuous (at x within s) /\
5874              g continuous (at (f x) within IMAGE f s)
5875              ==> (g o f) continuous (at x within s)`,
5876   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_within; o_THM; IN_IMAGE] THEN
5877   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5878   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
5879   ASM_MESON_TAC[]);;
5880
5881 let CONTINUOUS_AT_COMPOSE = prove
5882  (`!f g x. f continuous (at x) /\ g continuous (at (f x))
5883            ==> (g o f) continuous (at x)`,
5884   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
5885   MESON_TAC[CONTINUOUS_WITHIN_COMPOSE; IN_IMAGE; CONTINUOUS_WITHIN_SUBSET;
5886             SUBSET_UNIV; IN_UNIV]);;
5887
5888 let CONTINUOUS_ON_COMPOSE = prove
5889  (`!f g s. f continuous_on s /\ g continuous_on (IMAGE f s)
5890            ==> (g o f) continuous_on s`,
5891   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
5892   MESON_TAC[IN_IMAGE; CONTINUOUS_WITHIN_COMPOSE]);;
5893
5894 (* ------------------------------------------------------------------------- *)
5895 (* Continuity in terms of open preimages.                                    *)
5896 (* ------------------------------------------------------------------------- *)
5897
5898 let CONTINUOUS_WITHIN_OPEN = prove
5899  (`!f:real^M->real^N x u.
5900      f continuous (at x within u) <=>
5901         !t. open t /\ f(x) IN t
5902             ==> ?s. open s /\ x IN s /\
5903                     !x'. x' IN s /\ x' IN u ==> f(x') IN t`,
5904   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_within] THEN EQ_TAC THENL
5905    [DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN
5906     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
5907     GEN_REWRITE_TAC LAND_CONV [open_def] THEN
5908     DISCH_THEN(MP_TAC o SPEC `(f:real^M->real^N) x`) THEN
5909     ASM_MESON_TAC[IN_BALL; DIST_SYM; OPEN_BALL; CENTRE_IN_BALL; DIST_SYM];
5910     DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5911     FIRST_X_ASSUM(MP_TAC o SPEC `ball((f:real^M->real^N) x,e)`) THEN
5912     ASM_SIMP_TAC[OPEN_BALL; CENTRE_IN_BALL] THEN
5913     MESON_TAC[open_def; IN_BALL; REAL_LT_TRANS; DIST_SYM]]);;
5914
5915 let CONTINUOUS_AT_OPEN = prove
5916  (`!f:real^M->real^N x.
5917      f continuous (at x) <=>
5918         !t. open t /\ f(x) IN t
5919             ==> ?s. open s /\ x IN s /\
5920                     !x'. x' IN s ==> f(x') IN t`,
5921   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_at] THEN EQ_TAC THENL
5922    [DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN
5923     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
5924     GEN_REWRITE_TAC LAND_CONV [open_def] THEN
5925     DISCH_THEN(MP_TAC o SPEC `(f:real^M->real^N) x`) THEN
5926     ASM_MESON_TAC[IN_BALL; DIST_SYM; OPEN_BALL; CENTRE_IN_BALL];
5927     DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5928     FIRST_X_ASSUM(MP_TAC o SPEC `ball((f:real^M->real^N) x,e)`) THEN
5929     ASM_SIMP_TAC[OPEN_BALL; CENTRE_IN_BALL] THEN
5930     MESON_TAC[open_def; IN_BALL; REAL_LT_TRANS; DIST_SYM]]);;
5931
5932 let CONTINUOUS_ON_OPEN_GEN = prove
5933  (`!f:real^M->real^N s t.
5934     IMAGE f s SUBSET t
5935     ==> (f continuous_on s <=>
5936          !u. open_in (subtopology euclidean t) u
5937              ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN u})`,
5938   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_on] THEN EQ_TAC THENL
5939    [REWRITE_TAC[open_in; SUBSET; IN_ELIM_THM] THEN
5940     DISCH_TAC THEN X_GEN_TAC `u:real^N->bool` THEN STRIP_TAC THEN
5941     CONJ_TAC THENL [ASM_MESON_TAC[DIST_REFL]; ALL_TAC] THEN
5942     X_GEN_TAC `x:real^M` THEN STRIP_TAC THEN
5943     FIRST_X_ASSUM(MP_TAC o SPEC `(f:real^M->real^N) x`) THEN ASM SET_TAC[];
5944     DISCH_TAC THEN X_GEN_TAC `x:real^M` THEN
5945     DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5946     FIRST_X_ASSUM(MP_TAC o
5947       SPEC `ball((f:real^M->real^N) x,e) INTER t`) THEN
5948     ANTS_TAC THENL
5949      [ASM_MESON_TAC[OPEN_IN_OPEN; INTER_COMM; OPEN_BALL]; ALL_TAC] THEN
5950     REWRITE_TAC[open_in; SUBSET; IN_INTER; IN_ELIM_THM; IN_BALL; IN_IMAGE] THEN
5951     REWRITE_TAC[AND_FORALL_THM] THEN DISCH_THEN(MP_TAC o SPEC `x:real^M`) THEN
5952     RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; FORALL_IN_IMAGE]) THEN
5953     ASM_MESON_TAC[DIST_REFL; DIST_SYM]]);;
5954
5955 let CONTINUOUS_ON_OPEN = prove
5956  (`!f:real^M->real^N s.
5957       f continuous_on s <=>
5958         !t. open_in (subtopology euclidean (IMAGE f s)) t
5959             ==> open_in (subtopology euclidean s) {x | x IN s /\ f(x) IN t}`,
5960   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_OPEN_GEN THEN
5961   REWRITE_TAC[SUBSET_REFL]);;
5962
5963 let CONTINUOUS_OPEN_IN_PREIMAGE_GEN = prove
5964  (`!f:real^M->real^N s t u.
5965         f continuous_on s /\ IMAGE f s SUBSET t /\
5966         open_in (subtopology euclidean t) u
5967         ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN u}`,
5968   MESON_TAC[CONTINUOUS_ON_OPEN_GEN]);;
5969
5970 let CONTINUOUS_ON_IMP_OPEN_IN = prove
5971  (`!f:real^M->real^N s t.
5972         f continuous_on s /\
5973         open_in (subtopology euclidean (IMAGE f s)) t
5974         ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
5975   MESON_TAC[CONTINUOUS_ON_OPEN]);;
5976
5977 (* ------------------------------------------------------------------------- *)
5978 (* Similarly in terms of closed sets.                                        *)
5979 (* ------------------------------------------------------------------------- *)
5980
5981 let CONTINUOUS_ON_CLOSED_GEN = prove
5982  (`!f:real^M->real^N s t.
5983     IMAGE f s SUBSET t
5984     ==> (f continuous_on s <=>
5985          !u. closed_in (subtopology euclidean t) u
5986              ==> closed_in (subtopology euclidean s)
5987                            {x | x IN s /\ f x IN u})`,
5988   REPEAT STRIP_TAC THEN FIRST_ASSUM(fun th ->
5989     ONCE_REWRITE_TAC[MATCH_MP CONTINUOUS_ON_OPEN_GEN th]) THEN
5990   EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `u:real^N->bool` THEN
5991   FIRST_X_ASSUM(MP_TAC o SPEC `t DIFF u:real^N->bool`) THENL
5992    [REWRITE_TAC[closed_in]; REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ]] THEN
5993   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
5994   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
5995   ASM_REWRITE_TAC[SUBSET_RESTRICT] THEN
5996   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
5997
5998 let CONTINUOUS_ON_CLOSED = prove
5999  (`!f:real^M->real^N s.
6000       f continuous_on s <=>
6001         !t. closed_in (subtopology euclidean (IMAGE f s)) t
6002             ==> closed_in (subtopology euclidean s) {x | x IN s /\ f(x) IN t}`,
6003   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_CLOSED_GEN THEN
6004   REWRITE_TAC[SUBSET_REFL]);;
6005
6006 let CONTINUOUS_CLOSED_IN_PREIMAGE_GEN = prove
6007  (`!f:real^M->real^N s t u.
6008         f continuous_on s /\ IMAGE f s SUBSET t /\
6009         closed_in (subtopology euclidean t) u
6010         ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x IN u}`,
6011   MESON_TAC[CONTINUOUS_ON_CLOSED_GEN]);;
6012
6013 let CONTINUOUS_ON_IMP_CLOSED_IN = prove
6014  (`!f:real^M->real^N s t.
6015         f continuous_on s /\
6016         closed_in (subtopology euclidean (IMAGE f s)) t
6017         ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
6018   MESON_TAC[CONTINUOUS_ON_CLOSED]);;
6019
6020 (* ------------------------------------------------------------------------- *)
6021 (* Half-global and completely global cases.                                  *)
6022 (* ------------------------------------------------------------------------- *)
6023
6024 let CONTINUOUS_OPEN_IN_PREIMAGE = prove
6025  (`!f s t.
6026          f continuous_on s /\ open t
6027          ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
6028   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[SET_RULE
6029    `x IN s /\ f x IN t <=> x IN s /\ f x IN (t INTER IMAGE f s)`] THEN
6030   FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[CONTINUOUS_ON_OPEN]) THEN
6031   ONCE_REWRITE_TAC[INTER_COMM] THEN MATCH_MP_TAC OPEN_IN_OPEN_INTER THEN
6032   ASM_REWRITE_TAC[]);;
6033
6034 let CONTINUOUS_CLOSED_IN_PREIMAGE = prove
6035  (`!f s t.
6036          f continuous_on s /\ closed t
6037          ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
6038   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[SET_RULE
6039    `x IN s /\ f x IN t <=> x IN s /\ f x IN (t INTER IMAGE f s)`] THEN
6040   FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[CONTINUOUS_ON_CLOSED]) THEN
6041   ONCE_REWRITE_TAC[INTER_COMM] THEN MATCH_MP_TAC CLOSED_IN_CLOSED_INTER THEN
6042   ASM_REWRITE_TAC[]);;
6043
6044 let CONTINUOUS_OPEN_PREIMAGE = prove
6045  (`!f:real^M->real^N s t.
6046      f continuous_on s /\ open s /\ open t
6047      ==> open {x | x IN s /\ f(x) IN t}`,
6048   REPEAT STRIP_TAC THEN
6049   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONTINUOUS_ON_OPEN]) THEN
6050   REWRITE_TAC [OPEN_IN_OPEN] THEN
6051   DISCH_THEN(MP_TAC o SPEC `IMAGE (f:real^M->real^N) s INTER t`) THEN
6052   ANTS_TAC THENL
6053    [EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC [];
6054     STRIP_TAC THEN
6055     SUBGOAL_THEN `{x | x IN s /\ (f:real^M->real^N) x IN t} =
6056                  s INTER t'` SUBST1_TAC THENL
6057     [ASM SET_TAC []; ASM_MESON_TAC [OPEN_INTER]]]);;
6058
6059 let CONTINUOUS_CLOSED_PREIMAGE = prove
6060  (`!f:real^M->real^N s t.
6061      f continuous_on s /\ closed s /\ closed t
6062      ==> closed {x | x IN s /\ f(x) IN t}`,
6063   REPEAT STRIP_TAC THEN
6064   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONTINUOUS_ON_CLOSED]) THEN
6065   REWRITE_TAC [CLOSED_IN_CLOSED] THEN
6066   DISCH_THEN(MP_TAC o SPEC `IMAGE (f:real^M->real^N) s INTER t`) THEN
6067   ANTS_TAC THENL
6068    [EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC [];
6069     STRIP_TAC THEN
6070     SUBGOAL_THEN `{x | x IN s /\ (f:real^M->real^N) x IN t} =
6071                  s INTER t'` SUBST1_TAC THENL
6072     [ASM SET_TAC []; ASM_MESON_TAC [CLOSED_INTER]]]);;
6073
6074 let CONTINUOUS_OPEN_PREIMAGE_UNIV = prove
6075  (`!f:real^M->real^N s.
6076         (!x. f continuous (at x)) /\ open s ==> open {x | f(x) IN s}`,
6077   REPEAT STRIP_TAC THEN
6078   MP_TAC(SPECL [`f:real^M->real^N`; `(:real^M)`; `s:real^N->bool`]
6079     CONTINUOUS_OPEN_PREIMAGE) THEN
6080   ASM_SIMP_TAC[OPEN_UNIV; IN_UNIV; CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
6081
6082 let CONTINUOUS_CLOSED_PREIMAGE_UNIV = prove
6083  (`!f:real^M->real^N s.
6084         (!x. f continuous (at x)) /\ closed s ==> closed {x | f(x) IN s}`,
6085   REPEAT STRIP_TAC THEN
6086   MP_TAC(SPECL [`f:real^M->real^N`; `(:real^M)`; `s:real^N->bool`]
6087     CONTINUOUS_CLOSED_PREIMAGE) THEN
6088   ASM_SIMP_TAC[CLOSED_UNIV; IN_UNIV; CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
6089
6090 let CONTINUOUS_OPEN_IN_PREIMAGE_EQ = prove
6091  (`!f:real^M->real^N s.
6092     f continuous_on s <=>
6093     !t. open t ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
6094   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CONTINUOUS_OPEN_IN_PREIMAGE] THEN
6095   REWRITE_TAC[CONTINUOUS_ON_OPEN] THEN DISCH_TAC THEN
6096   X_GEN_TAC `t:real^N->bool` THEN GEN_REWRITE_TAC LAND_CONV [OPEN_IN_OPEN] THEN
6097   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
6098   FIRST_X_ASSUM(MP_TAC o SPEC `u:real^N->bool`) THEN
6099   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN SET_TAC[]);;
6100
6101 let CONTINUOUS_CLOSED_IN_PREIMAGE_EQ = prove
6102  (`!f:real^M->real^N s.
6103     f continuous_on s <=>
6104     !t. closed t
6105         ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
6106   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE] THEN
6107   REWRITE_TAC[CONTINUOUS_ON_CLOSED] THEN DISCH_TAC THEN
6108   X_GEN_TAC `t:real^N->bool` THEN
6109   GEN_REWRITE_TAC LAND_CONV [CLOSED_IN_CLOSED] THEN
6110   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
6111   FIRST_X_ASSUM(MP_TAC o SPEC `u:real^N->bool`) THEN
6112   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN SET_TAC[]);;
6113
6114 (* ------------------------------------------------------------------------- *)
6115 (* Linear functions are (uniformly) continuous on any set.                   *)
6116 (* ------------------------------------------------------------------------- *)
6117
6118 let LINEAR_LIM_0 = prove
6119  (`!f. linear f ==> (f --> vec 0) (at (vec 0))`,
6120   REPEAT STRIP_TAC THEN REWRITE_TAC[LIM_AT] THEN
6121   FIRST_X_ASSUM(MP_TAC o MATCH_MP LINEAR_BOUNDED_POS) THEN
6122   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
6123   X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `e / B` THEN
6124   ASM_SIMP_TAC[REAL_LT_DIV] THEN REWRITE_TAC[dist; VECTOR_SUB_RZERO] THEN
6125   ASM_MESON_TAC[REAL_MUL_SYM; REAL_LET_TRANS; REAL_LT_RDIV_EQ]);;
6126
6127 let LINEAR_CONTINUOUS_AT = prove
6128  (`!f:real^M->real^N a. linear f ==> f continuous (at a)`,
6129   REPEAT STRIP_TAC THEN
6130   MP_TAC(ISPEC `\x. (f:real^M->real^N) (a + x) - f(a)` LINEAR_LIM_0) THEN
6131   ANTS_TAC THENL
6132    [POP_ASSUM MP_TAC THEN SIMP_TAC[linear] THEN
6133     REPEAT STRIP_TAC THEN VECTOR_ARITH_TAC;
6134     ALL_TAC] THEN
6135   REWRITE_TAC[GSYM LIM_NULL; CONTINUOUS_AT] THEN
6136   GEN_REWRITE_TAC RAND_CONV [LIM_AT_ZERO] THEN SIMP_TAC[]);;
6137
6138 let LINEAR_CONTINUOUS_WITHIN = prove
6139  (`!f:real^M->real^N s x. linear f ==> f continuous (at x within s)`,
6140   SIMP_TAC[CONTINUOUS_AT_WITHIN; LINEAR_CONTINUOUS_AT]);;
6141
6142 let LINEAR_CONTINUOUS_ON = prove
6143  (`!f:real^M->real^N s. linear f ==> f continuous_on s`,
6144   MESON_TAC[LINEAR_CONTINUOUS_AT; CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
6145
6146 let LINEAR_CONTINUOUS_COMPOSE = prove
6147  (`!net f:A->real^N g:real^N->real^P.
6148         f continuous net /\ linear g ==> (\x. g(f x)) continuous net`,
6149   REWRITE_TAC[continuous; LIM_LINEAR]);;
6150
6151 let LINEAR_CONTINUOUS_ON_COMPOSE = prove
6152  (`!f:real^M->real^N g:real^N->real^P s.
6153         f continuous_on s /\ linear g ==> (\x. g(f x)) continuous_on s`,
6154   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
6155            LINEAR_CONTINUOUS_COMPOSE]);;
6156
6157 let CONTINUOUS_LIFT_COMPONENT_COMPOSE = prove
6158  (`!net f:A->real^N i. f continuous net ==> (\x. lift(f x$i)) continuous net`,
6159   REPEAT GEN_TAC THEN
6160   SUBGOAL_THEN `linear(\x:real^N. lift (x$i))` MP_TAC THENL
6161    [REWRITE_TAC[LINEAR_LIFT_COMPONENT]; REWRITE_TAC[GSYM IMP_CONJ_ALT]] THEN
6162   REWRITE_TAC[LINEAR_CONTINUOUS_COMPOSE]);;
6163
6164 let CONTINUOUS_ON_LIFT_COMPONENT_COMPOSE = prove
6165  (`!f:real^M->real^N s.
6166         f continuous_on s
6167         ==> (\x. lift (f x$i)) continuous_on s`,
6168   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
6169            CONTINUOUS_LIFT_COMPONENT_COMPOSE]);;
6170
6171 (* ------------------------------------------------------------------------- *)
6172 (* Also bilinear functions, in composition form.                             *)
6173 (* ------------------------------------------------------------------------- *)
6174
6175 let BILINEAR_CONTINUOUS_COMPOSE = prove
6176  (`!net f:A->real^M g:A->real^N h:real^M->real^N->real^P.
6177         f continuous net /\ g continuous net /\ bilinear h
6178         ==> (\x. h (f x) (g x)) continuous net`,
6179   REWRITE_TAC[continuous; LIM_BILINEAR]);;
6180
6181 let BILINEAR_CONTINUOUS_ON_COMPOSE = prove
6182  (`!f g h s. f continuous_on s /\ g continuous_on s /\ bilinear h
6183              ==> (\x. h (f x) (g x)) continuous_on s`,
6184   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
6185            BILINEAR_CONTINUOUS_COMPOSE]);;
6186
6187 let BILINEAR_DOT = prove
6188  (`bilinear (\x y:real^N. lift(x dot y))`,
6189   REWRITE_TAC[bilinear; linear; DOT_LADD; DOT_RADD; DOT_LMUL; DOT_RMUL] THEN
6190   REWRITE_TAC[LIFT_ADD; LIFT_CMUL]);;
6191
6192 let CONTINUOUS_LIFT_DOT2 = prove
6193  (`!net f g:A->real^N.
6194         f continuous net /\ g continuous net
6195         ==> (\x. lift(f x dot g x)) continuous net`,
6196   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP (MATCH_MP (REWRITE_RULE
6197    [TAUT `p /\ q /\ r ==> s <=> r ==> p /\ q ==> s`]
6198   BILINEAR_CONTINUOUS_COMPOSE) BILINEAR_DOT)) THEN REWRITE_TAC[]);;
6199
6200 let CONTINUOUS_ON_LIFT_DOT2 = prove
6201  (`!f:real^M->real^N g s.
6202         f continuous_on s /\ g continuous_on s
6203         ==> (\x. lift(f x dot g x)) continuous_on s`,
6204   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP (MATCH_MP (REWRITE_RULE
6205    [TAUT `p /\ q /\ r ==> s <=> r ==> p /\ q ==> s`]
6206   BILINEAR_CONTINUOUS_ON_COMPOSE) BILINEAR_DOT)) THEN REWRITE_TAC[]);;
6207
6208 (* ------------------------------------------------------------------------- *)
6209 (* Preservation of compactness and connectedness under continuous function.  *)
6210 (* ------------------------------------------------------------------------- *)
6211
6212 let COMPACT_CONTINUOUS_IMAGE = prove
6213  (`!f:real^M->real^N s.
6214         f continuous_on s /\ compact s ==> compact(IMAGE f s)`,
6215   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_on; compact] THEN
6216   STRIP_TAC THEN X_GEN_TAC `y:num->real^N` THEN
6217   REWRITE_TAC[IN_IMAGE; SKOLEM_THM; FORALL_AND_THM] THEN
6218   DISCH_THEN(X_CHOOSE_THEN `x:num->real^M` STRIP_ASSUME_TAC) THEN
6219   FIRST_X_ASSUM(MP_TAC o SPEC `x:num->real^M`) THEN ASM_REWRITE_TAC[] THEN
6220   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
6221   X_GEN_TAC `r:num->num` THEN
6222   DISCH_THEN(X_CHOOSE_THEN `l:real^M` STRIP_ASSUME_TAC) THEN
6223   EXISTS_TAC `(f:real^M->real^N) l` THEN ASM_REWRITE_TAC[] THEN
6224   CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
6225   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
6226   FIRST_X_ASSUM(MP_TAC o SPEC `l:real^M`) THEN
6227   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
6228   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
6229   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
6230   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
6231   DISCH_THEN(MP_TAC o SPEC `d:real`) THEN ASM_REWRITE_TAC[o_THM] THEN
6232   ASM_MESON_TAC[]);;
6233
6234 let COMPACT_TRANSLATION = prove
6235  (`!s a:real^N. compact s ==> compact (IMAGE (\x. a + x) s)`,
6236   SIMP_TAC[COMPACT_CONTINUOUS_IMAGE; CONTINUOUS_ON_ADD;
6237            CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID]);;
6238
6239 let COMPACT_TRANSLATION_EQ = prove
6240  (`!a s. compact (IMAGE (\x:real^N. a + x) s) <=> compact s`,
6241   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[COMPACT_TRANSLATION] THEN
6242   DISCH_THEN(MP_TAC o ISPEC `--a:real^N` o MATCH_MP COMPACT_TRANSLATION) THEN
6243   REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID;
6244               VECTOR_ARITH `--a + a + x:real^N = x`]);;
6245
6246 add_translation_invariants [COMPACT_TRANSLATION_EQ];;
6247
6248 let COMPACT_LINEAR_IMAGE = prove
6249  (`!f:real^M->real^N s. compact s /\ linear f ==> compact(IMAGE f s)`,
6250   SIMP_TAC[LINEAR_CONTINUOUS_ON; COMPACT_CONTINUOUS_IMAGE]);;
6251
6252 let COMPACT_LINEAR_IMAGE_EQ = prove
6253  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
6254          ==> (compact (IMAGE f s) <=> compact s)`,
6255   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE COMPACT_LINEAR_IMAGE));;
6256
6257 add_linear_invariants [COMPACT_LINEAR_IMAGE_EQ];;
6258
6259 let CONNECTED_CONTINUOUS_IMAGE = prove
6260  (`!f:real^M->real^N s.
6261         f continuous_on s /\ connected s ==> connected(IMAGE f s)`,
6262   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_ON_OPEN] THEN
6263   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6264   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
6265   REWRITE_TAC[CONNECTED_CLOPEN; NOT_FORALL_THM; NOT_IMP; DE_MORGAN_THM] THEN
6266   REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
6267   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
6268   FIRST_X_ASSUM(fun th -> MP_TAC(SPEC `t:real^N->bool` th) THEN
6269     MP_TAC(SPEC `IMAGE (f:real^M->real^N) s DIFF t` th)) THEN
6270   ASM_REWRITE_TAC[] THEN
6271   SUBGOAL_THEN `{x | x IN s /\ (f:real^M->real^N) x IN IMAGE f s DIFF t} =
6272                 s DIFF {x | x IN s /\ f x IN t}`
6273   SUBST1_TAC THENL
6274    [UNDISCH_TAC `t SUBSET IMAGE (f:real^M->real^N) s` THEN
6275     REWRITE_TAC[EXTENSION; IN_IMAGE; IN_DIFF; IN_ELIM_THM; SUBSET] THEN
6276     MESON_TAC[];
6277     REPEAT STRIP_TAC THEN
6278     EXISTS_TAC `{x | x IN s /\ (f:real^M->real^N) x IN t}` THEN
6279     ASM_REWRITE_TAC[] THEN POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN
6280     REWRITE_TAC[IN_IMAGE; SUBSET; IN_ELIM_THM; NOT_IN_EMPTY; EXTENSION] THEN
6281     MESON_TAC[]]);;
6282
6283 let CONNECTED_TRANSLATION = prove
6284  (`!a s. connected s ==> connected (IMAGE (\x:real^N. a + x) s)`,
6285   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN
6286   ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST]);;
6287
6288 let CONNECTED_TRANSLATION_EQ = prove
6289  (`!a s. connected (IMAGE (\x:real^N. a + x) s) <=> connected s`,
6290   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[CONNECTED_TRANSLATION] THEN
6291   DISCH_THEN(MP_TAC o ISPEC `--a:real^N` o MATCH_MP CONNECTED_TRANSLATION) THEN
6292   REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID;
6293               VECTOR_ARITH `--a + a + x:real^N = x`]);;
6294
6295 add_translation_invariants [CONNECTED_TRANSLATION_EQ];;
6296
6297 let CONNECTED_LINEAR_IMAGE = prove
6298  (`!f:real^M->real^N s. connected s /\ linear f ==> connected(IMAGE f s)`,
6299   SIMP_TAC[LINEAR_CONTINUOUS_ON; CONNECTED_CONTINUOUS_IMAGE]);;
6300
6301 let CONNECTED_LINEAR_IMAGE_EQ = prove
6302  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
6303          ==> (connected (IMAGE f s) <=> connected s)`,
6304   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE CONNECTED_LINEAR_IMAGE));;
6305
6306 add_linear_invariants [CONNECTED_LINEAR_IMAGE_EQ];;
6307
6308 (* ------------------------------------------------------------------------- *)
6309 (* Preservation properties for pasted sets (Cartesian products).             *)
6310 (* ------------------------------------------------------------------------- *)
6311
6312 let BOUNDED_PCROSS_EQ = prove
6313  (`!s:real^M->bool t:real^N->bool.
6314         bounded (s PCROSS t) <=>
6315         s = {} \/ t = {} \/ bounded s /\ bounded t`,
6316   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN
6317   ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
6318   ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
6319   REWRITE_TAC[SET_RULE `{f x y |x,y| F} = {}`; BOUNDED_EMPTY] THEN
6320   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
6321   REWRITE_TAC[bounded; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
6322   ASM_MESON_TAC[NORM_LE_PASTECART; REAL_LE_TRANS; NORM_PASTECART_LE;
6323                 REAL_LE_ADD2]);;
6324
6325 let BOUNDED_PCROSS = prove
6326  (`!s:real^M->bool t:real^N->bool.
6327      bounded s /\ bounded t ==> bounded (s PCROSS t)`,
6328   SIMP_TAC[BOUNDED_PCROSS_EQ]);;
6329
6330 let CLOSED_PCROSS_EQ = prove
6331  (`!s:real^M->bool t:real^N->bool.
6332         closed (s PCROSS t) <=>
6333         s = {} \/ t = {} \/ closed s /\ closed t`,
6334   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN MAP_EVERY ASM_CASES_TAC
6335    [`s:real^M->bool = {}`; `t:real^N->bool = {}`] THEN
6336   ASM_REWRITE_TAC[NOT_IN_EMPTY; CLOSED_EMPTY; SET_RULE
6337    `{f x y |x,y| F} = {}`] THEN
6338   REWRITE_TAC[CLOSED_SEQUENTIAL_LIMITS; LIM_SEQUENTIALLY] THEN
6339   REWRITE_TAC[FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
6340   REWRITE_TAC[IN_ELIM_THM; SKOLEM_THM; FORALL_AND_THM] THEN
6341   ONCE_REWRITE_TAC[GSYM FUN_EQ_THM] THEN
6342   REWRITE_TAC[LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
6343   SIMP_TAC[TAUT `((p /\ q) /\ r) /\ s ==> t <=> r ==> p /\ q /\ s ==> t`] THEN
6344   ONCE_REWRITE_TAC[MESON[]
6345    `(!a b c d e. P a b c d e) <=> (!d e b c a. P a b c d e)`] THEN
6346   REWRITE_TAC[FORALL_UNWIND_THM2] THEN
6347   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN EQ_TAC THENL
6348    [GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
6349      [TAUT `p ==> q /\ r <=> (p ==> q) /\ (p ==> r)`; FORALL_AND_THM] THEN
6350     MATCH_MP_TAC MONO_AND THEN CONJ_TAC THENL
6351      [ALL_TAC; GEN_REWRITE_TAC LAND_CONV [SWAP_FORALL_THM]] THEN
6352     MATCH_MP_TAC MONO_FORALL THEN REPEAT STRIP_TAC THEN
6353     FIRST_X_ASSUM MATCH_MP_TAC THEN MATCH_MP_TAC(MESON[]
6354      `(?x. P x (\n. x)) ==> (?s x. P x s)`) THEN
6355     ASM_MESON_TAC[DIST_PASTECART_CANCEL];
6356     ONCE_REWRITE_TAC[MESON[]
6357      `(!x l. P x l) /\ (!y m. Q y m) <=> (!x y l m. P x l /\ Q y m)`] THEN
6358     REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
6359     REWRITE_TAC[dist; PASTECART_SUB] THEN
6360     ASM_MESON_TAC[NORM_LE_PASTECART; REAL_LET_TRANS]]);;
6361
6362 let CLOSED_PCROSS = prove
6363  (`!s:real^M->bool t:real^N->bool.
6364      closed s /\ closed t ==> closed (s PCROSS t)`,
6365   SIMP_TAC[CLOSED_PCROSS_EQ]);;
6366
6367 let COMPACT_PCROSS_EQ = prove
6368  (`!s:real^M->bool t:real^N->bool.
6369         compact (s PCROSS t) <=>
6370         s = {} \/ t = {} \/ compact s /\ compact t`,
6371   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_PCROSS_EQ;
6372               BOUNDED_PCROSS_EQ] THEN
6373   MESON_TAC[]);;
6374
6375 let COMPACT_PCROSS = prove
6376  (`!s:real^M->bool t:real^N->bool.
6377      compact s /\ compact t ==> compact (s PCROSS t)`,
6378   SIMP_TAC[COMPACT_PCROSS_EQ]);;
6379
6380 let OPEN_PCROSS_EQ = prove
6381  (`!s:real^M->bool t:real^N->bool.
6382         open (s PCROSS t) <=>
6383         s = {} \/ t = {} \/ open s /\ open t`,
6384   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN
6385   ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
6386   ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
6387   REWRITE_TAC[SET_RULE `{f x y |x,y| F} = {}`; OPEN_EMPTY] THEN
6388   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
6389   EQ_TAC THENL
6390    [REWRITE_TAC[open_def; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
6391     ASM_MESON_TAC[DIST_PASTECART_CANCEL];
6392     REWRITE_TAC[OPEN_CLOSED] THEN STRIP_TAC THEN
6393     SUBGOAL_THEN
6394      `UNIV DIFF {pastecart x y | x IN s /\ y IN t} =
6395       {pastecart x y | x IN ((:real^M) DIFF s) /\ y IN (:real^N)} UNION
6396       {pastecart x y | x IN (:real^M) /\ y IN ((:real^N) DIFF t)}`
6397     SUBST1_TAC THENL
6398      [REWRITE_TAC[EXTENSION; IN_DIFF; IN_UNION; FORALL_PASTECART; IN_UNIV] THEN
6399       REWRITE_TAC[IN_ELIM_THM; PASTECART_EQ; FSTCART_PASTECART;
6400                   SNDCART_PASTECART] THEN MESON_TAC[];
6401       SIMP_TAC[GSYM PCROSS] THEN MATCH_MP_TAC CLOSED_UNION THEN CONJ_TAC THEN
6402       MATCH_MP_TAC CLOSED_PCROSS THEN ASM_REWRITE_TAC[CLOSED_UNIV]]]);;
6403
6404 let OPEN_PCROSS = prove
6405  (`!s:real^M->bool t:real^N->bool.
6406         open s /\ open t ==> open (s PCROSS t)`,
6407   SIMP_TAC[OPEN_PCROSS_EQ]);;
6408
6409 let OPEN_IN_PCROSS = prove
6410  (`!s s':real^M->bool t t':real^N->bool.
6411         open_in (subtopology euclidean s) s' /\
6412         open_in (subtopology euclidean t) t'
6413         ==> open_in (subtopology euclidean (s PCROSS t)) (s' PCROSS t')`,
6414   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN] THEN DISCH_THEN(CONJUNCTS_THEN2
6415    (X_CHOOSE_THEN `s'':real^M->bool` STRIP_ASSUME_TAC)
6416    (X_CHOOSE_THEN `t'':real^N->bool` STRIP_ASSUME_TAC)) THEN
6417   EXISTS_TAC `(s'':real^M->bool) PCROSS (t'':real^N->bool)` THEN
6418   ASM_SIMP_TAC[OPEN_PCROSS; EXTENSION; FORALL_PASTECART] THEN
6419   REWRITE_TAC[IN_INTER; PASTECART_IN_PCROSS] THEN ASM SET_TAC[]);;
6420
6421 let PASTECART_IN_INTERIOR_SUBTOPOLOGY = prove
6422  (`!s t u x:real^M y:real^N.
6423      pastecart x y IN u /\ open_in (subtopology euclidean (s PCROSS t)) u
6424      ==> ?v w. open_in (subtopology euclidean s) v /\ x IN v /\
6425                open_in (subtopology euclidean t) w /\ y IN w /\
6426                (v PCROSS w) SUBSET u`,
6427   REWRITE_TAC[open_in; FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
6428   REPEAT STRIP_TAC THEN
6429   FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^M`; `y:real^N`]) THEN
6430   ASM_REWRITE_TAC[] THEN
6431   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
6432   EXISTS_TAC `ball(x:real^M,e / &2) INTER s` THEN
6433   EXISTS_TAC `ball(y:real^N,e / &2) INTER t` THEN
6434   SUBGOAL_THEN `(x:real^M) IN s /\ (y:real^N) IN t` STRIP_ASSUME_TAC THENL
6435    [ASM_MESON_TAC[SUBSET; PASTECART_IN_PCROSS]; ALL_TAC] THEN
6436   ASM_SIMP_TAC[INTER_SUBSET; IN_INTER; CENTRE_IN_BALL; REAL_HALF] THEN
6437   REWRITE_TAC[IN_BALL] THEN REPEAT(CONJ_TAC THENL
6438    [MESON_TAC[REAL_SUB_LT; NORM_ARITH
6439      `dist(x,y) < e /\ dist(z,y) < e - dist(x,y)
6440       ==> dist(x:real^N,z) < e`];
6441     ALL_TAC]) THEN
6442   REWRITE_TAC[SUBSET; FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
6443   REWRITE_TAC[IN_BALL; IN_INTER] THEN REPEAT STRIP_TAC THEN
6444   FIRST_X_ASSUM MATCH_MP_TAC THEN
6445   ASM_REWRITE_TAC[dist; PASTECART_SUB] THEN
6446   W(MP_TAC o PART_MATCH lhand NORM_PASTECART_LE o lhand o snd) THEN
6447   REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[DIST_SYM] dist)] THEN
6448   ASM_REAL_ARITH_TAC);;
6449
6450 let OPEN_IN_PCROSS_EQ = prove
6451  (`!s s':real^M->bool t t':real^N->bool.
6452         open_in (subtopology euclidean (s PCROSS t)) (s' PCROSS t') <=>
6453         s' = {} \/ t' = {} \/
6454         open_in (subtopology euclidean s) s' /\
6455         open_in (subtopology euclidean t) t'`,
6456   REPEAT GEN_TAC THEN
6457   ASM_CASES_TAC `s':real^M->bool = {}` THEN
6458   ASM_REWRITE_TAC[PCROSS_EMPTY; OPEN_IN_EMPTY] THEN
6459   ASM_CASES_TAC `t':real^N->bool = {}` THEN
6460   ASM_REWRITE_TAC[PCROSS_EMPTY; OPEN_IN_EMPTY] THEN
6461   EQ_TAC THEN REWRITE_TAC[OPEN_IN_PCROSS] THEN REPEAT STRIP_TAC THENL
6462    [ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN
6463     X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
6464     UNDISCH_TAC `~(t':real^N->bool = {})` THEN
6465     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
6466     DISCH_THEN(X_CHOOSE_TAC `y:real^N`);
6467     ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN
6468     X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
6469     UNDISCH_TAC `~(s':real^M->bool = {})` THEN
6470     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
6471     DISCH_THEN(X_CHOOSE_TAC `x:real^M`)] THEN
6472    MP_TAC(ISPECL
6473      [`s:real^M->bool`; `t:real^N->bool`;
6474       `(s':real^M->bool) PCROSS (t':real^N->bool)`;
6475       `x:real^M`; `y:real^N`] PASTECART_IN_INTERIOR_SUBTOPOLOGY) THEN
6476   ASM_REWRITE_TAC[SUBSET; FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
6477   MESON_TAC[]);;
6478
6479 let INTERIOR_PCROSS = prove
6480  (`!s:real^M->bool t:real^N->bool.
6481         interior (s PCROSS t) = (interior s) PCROSS (interior t)`,
6482   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
6483    [REWRITE_TAC[SUBSET; FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
6484     MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^N`] THEN DISCH_TAC THEN
6485     MP_TAC(ISPECL [`(:real^M)`; `(:real^N)`;
6486          `interior((s:real^M->bool) PCROSS (t:real^N->bool))`;
6487          `x:real^M`; `y:real^N`] PASTECART_IN_INTERIOR_SUBTOPOLOGY) THEN
6488     REWRITE_TAC[UNIV_PCROSS_UNIV; SUBTOPOLOGY_UNIV; GSYM OPEN_IN] THEN
6489     ASM_REWRITE_TAC[OPEN_INTERIOR] THEN STRIP_TAC THEN
6490     FIRST_ASSUM(MP_TAC o MATCH_MP (MESON[INTERIOR_SUBSET; SUBSET_TRANS]
6491       `s SUBSET interior t ==> s SUBSET t`)) THEN
6492     REWRITE_TAC[SUBSET_PCROSS] THEN
6493     ASM_MESON_TAC[NOT_IN_EMPTY; INTERIOR_MAXIMAL; SUBSET];
6494     MATCH_MP_TAC INTERIOR_MAXIMAL THEN
6495     SIMP_TAC[OPEN_PCROSS; OPEN_INTERIOR; PCROSS_MONO; INTERIOR_SUBSET]]);;
6496
6497 (* ------------------------------------------------------------------------- *)
6498 (* Quotient maps are occasionally useful.                                    *)
6499 (* ------------------------------------------------------------------------- *)
6500
6501 let QUASICOMPACT_OPEN_CLOSED = prove
6502  (`!f:real^M->real^N s t.
6503     IMAGE f s SUBSET t
6504     ==> ((!u. u SUBSET t
6505               ==> (open_in (subtopology euclidean s)
6506                            {x | x IN s /\ f x IN u}
6507                    ==> open_in (subtopology euclidean t) u)) <=>
6508          (!u. u SUBSET t
6509               ==> (closed_in (subtopology euclidean s)
6510                              {x | x IN s /\ f x IN u}
6511                    ==> closed_in (subtopology euclidean t) u)))`,
6512   SIMP_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
6513   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN
6514   X_GEN_TAC `u:real^N->bool` THEN
6515   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `t DIFF u:real^N->bool`) THEN
6516   ASM_SIMP_TAC[SET_RULE `u SUBSET t ==> t DIFF (t DIFF u) = u`] THEN
6517   (ANTS_TAC THENL [SET_TAC[]; REPEAT STRIP_TAC]) THEN
6518   FIRST_X_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[SUBSET_RESTRICT] THEN
6519   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
6520    `open_in top x ==> x = y ==> open_in top y`)) THEN
6521   ASM SET_TAC[]);;
6522
6523 let QUOTIENT_MAP_IMP_CONTINUOUS_OPEN = prove
6524  (`!f:real^M->real^N s t.
6525      IMAGE f s SUBSET t /\
6526      (!u. u SUBSET t
6527           ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6528                open_in (subtopology euclidean t) u))
6529      ==> f continuous_on s`,
6530   MESON_TAC[OPEN_IN_IMP_SUBSET; CONTINUOUS_ON_OPEN_GEN]);;
6531
6532 let QUOTIENT_MAP_IMP_CONTINUOUS_CLOSED = prove
6533  (`!f:real^M->real^N s t.
6534      IMAGE f s SUBSET t /\
6535      (!u. u SUBSET t
6536           ==> (closed_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6537                closed_in (subtopology euclidean t) u))
6538      ==> f continuous_on s`,
6539   MESON_TAC[CLOSED_IN_IMP_SUBSET; CONTINUOUS_ON_CLOSED_GEN]);;
6540
6541 let OPEN_MAP_IMP_QUOTIENT_MAP = prove
6542  (`!f:real^M->real^N s.
6543     f continuous_on s /\
6544     (!t. open_in (subtopology euclidean s) t
6545          ==> open_in (subtopology euclidean (IMAGE f s)) (IMAGE f t))
6546     ==> !t. t SUBSET IMAGE f s
6547             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN t} <=>
6548                  open_in (subtopology euclidean (IMAGE f s)) t)`,
6549   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
6550    [SUBGOAL_THEN
6551      `t = IMAGE f {x | x IN s /\ (f:real^M->real^N) x IN t}`
6552     SUBST1_TAC THENL [ASM SET_TAC[]; ASM_SIMP_TAC[]];
6553     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONTINUOUS_ON_OPEN]) THEN
6554     ASM_SIMP_TAC[]]);;
6555
6556 let CLOSED_MAP_IMP_QUOTIENT_MAP = prove
6557  (`!f:real^M->real^N s.
6558     f continuous_on s /\
6559     (!t. closed_in (subtopology euclidean s) t
6560          ==> closed_in (subtopology euclidean (IMAGE f s)) (IMAGE f t))
6561     ==> !t. t SUBSET IMAGE f s
6562             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN t} <=>
6563                  open_in (subtopology euclidean (IMAGE f s)) t)`,
6564   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
6565    [FIRST_X_ASSUM(MP_TAC o SPEC
6566      `s DIFF {x | x IN s /\ (f:real^M->real^N) x IN t}`) THEN
6567     ANTS_TAC THENL
6568      [MATCH_MP_TAC CLOSED_IN_DIFF THEN
6569       ASM_SIMP_TAC[CLOSED_IN_SUBTOPOLOGY_REFL;
6570                    TOPSPACE_EUCLIDEAN; SUBSET_UNIV];
6571       REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
6572       DISCH_THEN(MP_TAC o CONJUNCT2) THEN MATCH_MP_TAC EQ_IMP THEN
6573       AP_TERM_TAC THEN ASM SET_TAC[]];
6574     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONTINUOUS_ON_OPEN]) THEN
6575     ASM_SIMP_TAC[]]);;
6576
6577 let CONTINUOUS_RIGHT_INVERSE_IMP_QUOTIENT_MAP = prove
6578  (`!f:real^M->real^N g s t.
6579         f continuous_on s /\ IMAGE f s SUBSET t /\
6580         g continuous_on t /\ IMAGE g t SUBSET s /\
6581         (!y. y IN t ==> f(g y) = y)
6582         ==> (!u. u SUBSET t
6583             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6584                  open_in (subtopology euclidean t) u))`,
6585   REWRITE_TAC[CONTINUOUS_ON_OPEN] THEN REPEAT STRIP_TAC THEN EQ_TAC THENL
6586    [DISCH_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `(IMAGE (g:real^N->real^M) t)
6587        INTER
6588        {x | x IN s /\ (f:real^M->real^N) x IN u}`) THEN
6589     ANTS_TAC THENL
6590      [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
6591       REWRITE_TAC[OPEN_IN_OPEN] THEN MATCH_MP_TAC MONO_EXISTS THEN
6592       ASM SET_TAC[];
6593       MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]];
6594     DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
6595     SUBGOAL_THEN `IMAGE (f:real^M->real^N) s = t`
6596      (fun th -> ASM_REWRITE_TAC[th]) THEN
6597     ASM SET_TAC[]]);;
6598
6599 let CONTINUOUS_LEFT_INVERSE_IMP_QUOTIENT_MAP = prove
6600  (`!f:real^M->real^N g s.
6601         f continuous_on s /\ g continuous_on (IMAGE f s) /\
6602         (!x. x IN s ==> g(f x) = x)
6603         ==> (!u. u SUBSET (IMAGE f s)
6604             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6605                  open_in (subtopology euclidean (IMAGE f s)) u))`,
6606   REPEAT GEN_TAC THEN STRIP_TAC THEN
6607   MATCH_MP_TAC CONTINUOUS_RIGHT_INVERSE_IMP_QUOTIENT_MAP THEN
6608   EXISTS_TAC `g:real^N->real^M` THEN
6609   ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;
6610
6611 let QUOTIENT_MAP_OPEN_CLOSED = prove
6612  (`!f:real^M->real^N s t.
6613     IMAGE f s SUBSET t
6614     ==> ((!u. u SUBSET t
6615               ==> (open_in (subtopology euclidean s)
6616                            {x | x IN s /\ f x IN u} <=>
6617                    open_in (subtopology euclidean t) u)) <=>
6618          (!u. u SUBSET t
6619               ==> (closed_in (subtopology euclidean s)
6620                              {x | x IN s /\ f x IN u} <=>
6621                    closed_in (subtopology euclidean t) u)))`,
6622   SIMP_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
6623   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN
6624   X_GEN_TAC `u:real^N->bool` THEN
6625   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `t DIFF u:real^N->bool`) THEN
6626   ASM_SIMP_TAC[SET_RULE `u SUBSET t ==> t DIFF (t DIFF u) = u`] THEN
6627   (ANTS_TAC THENL [SET_TAC[]; DISCH_THEN(SUBST1_TAC o SYM)]) THEN
6628   REWRITE_TAC[SUBSET_RESTRICT] THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
6629
6630 let CONTINUOUS_ON_COMPOSE_QUOTIENT = prove
6631  (`!f:real^M->real^N g:real^N->real^P s t u.
6632       IMAGE f s SUBSET t /\ IMAGE g t SUBSET u /\
6633       (!v. v SUBSET t
6634            ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN v} <=>
6635                 open_in (subtopology euclidean t) v)) /\
6636       (g o f) continuous_on s
6637       ==> g continuous_on t`,
6638   REPEAT GEN_TAC THEN
6639   REPLICATE_TAC 3 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6640   FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP CONTINUOUS_ON_OPEN_GEN th]) THEN
6641   SUBGOAL_THEN
6642    `IMAGE ((g:real^N->real^P) o (f:real^M->real^N)) s SUBSET u`
6643    (fun th -> REWRITE_TAC[MATCH_MP CONTINUOUS_ON_OPEN_GEN th])
6644   THENL [REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[]; DISCH_TAC] THEN
6645   X_GEN_TAC `v:real^P->bool` THEN DISCH_TAC THEN
6646   FIRST_X_ASSUM(MP_TAC o SPEC `v:real^P->bool`) THEN
6647   ASM_REWRITE_TAC[o_THM] THEN DISCH_TAC THEN
6648   FIRST_X_ASSUM(MP_TAC o SPEC `{x | x IN t /\ (g:real^N->real^P) x IN v}`) THEN
6649   ASM_REWRITE_TAC[SUBSET_RESTRICT] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
6650   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
6651    `open_in top s ==> s = t ==> open_in top t`)) THEN
6652   ASM SET_TAC[]);;
6653
6654 let LIFT_TO_QUOTIENT_SPACE = prove
6655  (`!f:real^M->real^N h:real^M->real^P s t u.
6656         IMAGE f s = t /\
6657         (!v. v SUBSET t
6658            ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN v} <=>
6659                 open_in (subtopology euclidean t) v)) /\
6660         h continuous_on s /\ IMAGE h s = u /\
6661         (!x y. x IN s /\ y IN s /\ f x = f y ==> h x = h y)
6662         ==> ?g. g continuous_on t /\ IMAGE g t = u /\
6663                 !x. x IN s ==> h(x) = g(f x)`,
6664   REPEAT GEN_TAC THEN
6665   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6666   REWRITE_TAC[FUNCTION_FACTORS_LEFT_GEN] THEN
6667   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^P` THEN
6668   DISCH_TAC THEN CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
6669   MATCH_MP_TAC CONTINUOUS_ON_COMPOSE_QUOTIENT THEN MAP_EVERY EXISTS_TAC
6670    [`f:real^M->real^N`; `s:real^M->bool`; `u:real^P->bool`] THEN
6671   ASM_SIMP_TAC[SUBSET_REFL] THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
6672   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
6673     CONTINUOUS_ON_EQ)) THEN
6674   ASM_REWRITE_TAC[o_THM]);;
6675
6676 let QUOTIENT_MAP_COMPOSE = prove
6677  (`!f:real^M->real^N g:real^N->real^P s t u.
6678         IMAGE f s SUBSET t /\
6679         (!v. v SUBSET t
6680            ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN v} <=>
6681                 open_in (subtopology euclidean t) v)) /\
6682         (!v. v SUBSET u
6683            ==> (open_in (subtopology euclidean t) {x | x IN t /\ g x IN v} <=>
6684                 open_in (subtopology euclidean u) v))
6685         ==> !v. v SUBSET u
6686                 ==> (open_in (subtopology euclidean s)
6687                              {x | x IN s /\ (g o f) x IN v} <=>
6688                      open_in (subtopology euclidean u) v)`,
6689   REPEAT STRIP_TAC THEN REWRITE_TAC[o_THM] THEN
6690   SUBGOAL_THEN
6691    `{x | x IN s /\ (g:real^N->real^P) ((f:real^M->real^N) x) IN v} =
6692     {x | x IN s /\ f x IN {x | x IN t /\ g x IN v}}`
6693   SUBST1_TAC THENL [ASM SET_TAC[]; ASM_SIMP_TAC[SUBSET_RESTRICT]]);;
6694
6695 let QUOTIENT_MAP_FROM_COMPOSITION = prove
6696  (`!f:real^M->real^N g:real^N->real^P s t u.
6697         f continuous_on s /\ IMAGE f s SUBSET t /\
6698         g continuous_on t /\ IMAGE g t SUBSET u /\
6699         (!v. v SUBSET u
6700              ==> (open_in (subtopology euclidean s)
6701                           {x | x IN s /\ (g o f) x IN v} <=>
6702                   open_in (subtopology euclidean u) v))
6703         ==> !v. v SUBSET u
6704                 ==> (open_in (subtopology euclidean t)
6705                               {x | x IN t /\ g x IN v} <=>
6706                      open_in (subtopology euclidean u) v)`,
6707   REPEAT STRIP_TAC THEN EQ_TAC THEN STRIP_TAC THENL
6708    [FIRST_X_ASSUM(MP_TAC o SPEC `v:real^P->bool`) THEN
6709     ASM_REWRITE_TAC[o_THM] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
6710     SUBGOAL_THEN
6711      `{x | x IN s /\ (g:real^N->real^P) ((f:real^M->real^N) x) IN v} =
6712       {x | x IN s /\ f x IN {x | x IN t /\ g x IN v}}`
6713     SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
6714     MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE_GEN THEN
6715     EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[];
6716     MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE_GEN THEN
6717     EXISTS_TAC `u:real^P->bool` THEN ASM_REWRITE_TAC[]]);;
6718
6719 let QUOTIENT_MAP_FROM_SUBSET = prove
6720  (`!f:real^M->real^N s t u.
6721         f continuous_on t /\ IMAGE f t SUBSET u /\
6722         s SUBSET t /\ IMAGE f s = u /\
6723         (!v. v SUBSET u
6724              ==> (open_in (subtopology euclidean s)
6725                           {x | x IN s /\ f x IN v} <=>
6726                   open_in (subtopology euclidean u) v))
6727         ==> !v. v SUBSET u
6728                 ==> (open_in (subtopology euclidean t)
6729                              {x | x IN t /\ f x IN v} <=>
6730                      open_in (subtopology euclidean u) v)`,
6731   REPEAT GEN_TAC THEN STRIP_TAC THEN
6732   MATCH_MP_TAC QUOTIENT_MAP_FROM_COMPOSITION THEN
6733   MAP_EVERY EXISTS_TAC [`\x:real^M. x`; `s:real^M->bool`] THEN
6734   ASM_REWRITE_TAC[CONTINUOUS_ON_ID; IMAGE_ID; o_THM]);;
6735
6736 let QUOTIENT_MAP_RESTRICT = prove
6737  (`!f:real^M->real^N s t c.
6738      IMAGE f s SUBSET t /\
6739      (!u. u SUBSET t
6740         ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6741              open_in (subtopology euclidean t) u)) /\
6742      (open_in (subtopology euclidean t) c \/
6743       closed_in (subtopology euclidean t) c)
6744      ==> !u. u SUBSET c
6745              ==> (open_in (subtopology euclidean {x | x IN s /\ f x IN c})
6746                           {x | x IN {x | x IN s /\ f x IN c} /\ f x IN u} <=>
6747                   open_in (subtopology euclidean c) u)`,
6748   REPEAT GEN_TAC THEN
6749   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6750   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
6751   DISCH_THEN(fun th -> MP_TAC th THEN MP_TAC (MATCH_MP
6752    (REWRITE_RULE[IMP_CONJ_ALT] QUOTIENT_MAP_IMP_CONTINUOUS_OPEN) th)) THEN
6753   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
6754   SUBGOAL_THEN `IMAGE (f:real^M->real^N) {x | x IN s /\ f x IN c} SUBSET c`
6755   ASSUME_TAC THENL [SET_TAC[]; ALL_TAC] THEN
6756   FIRST_X_ASSUM DISJ_CASES_TAC THENL
6757    [FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET);
6758     ASM_SIMP_TAC[QUOTIENT_MAP_OPEN_CLOSED] THEN
6759     FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET)] THEN
6760   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `u:real^N->bool` THEN
6761   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
6762   (ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
6763   (MATCH_MP_TAC EQ_IMP THEN BINOP_TAC THENL
6764     [MATCH_MP_TAC(MESON[] `t = s /\ (P s <=> Q s) ==> (P s <=> Q t)`) THEN
6765      CONJ_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[IN_ELIM_THM]];
6766      ALL_TAC]) THEN
6767   (EQ_TAC THENL
6768     [MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ_ALT] OPEN_IN_SUBSET_TRANS) ORELSE
6769      MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ_ALT] CLOSED_IN_SUBSET_TRANS);
6770      MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] OPEN_IN_TRANS) ORELSE
6771      MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] CLOSED_IN_TRANS)]) THEN
6772   (MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE_GEN ORELSE
6773    MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE_GEN ORELSE ASM_SIMP_TAC[]) THEN
6774   ASM SET_TAC[]);;
6775
6776 let CONNECTED_MONOTONE_QUOTIENT_PREIMAGE = prove
6777  (`!f:real^M->real^N s t.
6778       f continuous_on s /\ IMAGE f s = t /\
6779       (!u. u SUBSET t
6780            ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6781                 open_in (subtopology euclidean t) u)) /\
6782       (!y. y IN t ==> connected {x | x IN s /\ f x = y}) /\
6783       connected t
6784       ==> connected s`,
6785   REPEAT STRIP_TAC THEN REWRITE_TAC[connected; NOT_EXISTS_THM] THEN
6786   MAP_EVERY X_GEN_TAC [`u:real^M->bool`; `v:real^M->bool`] THEN STRIP_TAC THEN
6787   UNDISCH_TAC `connected(t:real^N->bool)` THEN SIMP_TAC[CONNECTED_OPEN_IN] THEN
6788   MAP_EVERY EXISTS_TAC
6789    [`IMAGE (f:real^M->real^N) (s INTER u)`;
6790     `IMAGE (f:real^M->real^N) (s INTER v)`] THEN
6791   ASM_REWRITE_TAC[IMAGE_EQ_EMPTY] THEN
6792   SUBGOAL_THEN
6793    `IMAGE (f:real^M->real^N) (s INTER u) INTER IMAGE f (s INTER v) = {}`
6794   ASSUME_TAC THENL
6795    [REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN
6796     X_GEN_TAC `y:real^N` THEN STRIP_TAC  THEN
6797     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN
6798     ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[connected]] THEN
6799     MAP_EVERY EXISTS_TAC [`u:real^M->bool`; `v:real^M->bool`] THEN
6800     ASM SET_TAC[];
6801     ALL_TAC] THEN
6802   ONCE_REWRITE_TAC[CONJ_ASSOC] THEN
6803   CONJ_TAC THENL [CONJ_TAC; ASM SET_TAC[]] THEN
6804   FIRST_X_ASSUM(fun th ->
6805    W(MP_TAC o PART_MATCH (rand o rand) th o snd)) THEN
6806   (ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN(SUBST1_TAC o SYM)]) THEN
6807   MATCH_MP_TAC(MESON[]
6808    `{x | x IN s /\ f x IN IMAGE f u} = u /\ open_in top u
6809     ==> open_in top {x | x IN s /\ f x IN IMAGE f u}`) THEN
6810   ASM_SIMP_TAC[OPEN_IN_OPEN_INTER] THEN ASM SET_TAC[]);;
6811
6812 let CONNECTED_MONOTONE_QUOTIENT_PREIMAGE_GEN = prove
6813  (`!f:real^M->real^N s t c.
6814       IMAGE f s = t /\
6815       (!u. u SUBSET t
6816            ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6817                 open_in (subtopology euclidean t) u)) /\
6818       (!y. y IN t ==> connected {x | x IN s /\ f x = y}) /\
6819       (open_in (subtopology euclidean t) c \/
6820        closed_in (subtopology euclidean t) c) /\
6821       connected c
6822       ==> connected {x | x IN s /\ f x IN c}`,
6823   REPEAT GEN_TAC THEN
6824   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6825   MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ]
6826    (REWRITE_RULE[CONJ_ASSOC] CONNECTED_MONOTONE_QUOTIENT_PREIMAGE)) THEN
6827   SUBGOAL_THEN `(c:real^N->bool) SUBSET t` ASSUME_TAC THENL
6828    [ASM_MESON_TAC[OPEN_IN_IMP_SUBSET; CLOSED_IN_IMP_SUBSET]; ALL_TAC] THEN
6829   EXISTS_TAC `f:real^M->real^N` THEN REPEAT CONJ_TAC THENL
6830    [FIRST_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
6831       QUOTIENT_MAP_IMP_CONTINUOUS_OPEN)) THEN
6832     ASM_REWRITE_TAC[SUBSET_REFL] THEN
6833     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] CONTINUOUS_ON_SUBSET) THEN
6834     REWRITE_TAC[SUBSET_RESTRICT];
6835     ASM SET_TAC[];
6836     MATCH_MP_TAC QUOTIENT_MAP_RESTRICT THEN
6837     ASM_MESON_TAC[SUBSET_REFL];
6838     X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
6839     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN
6840     ANTS_TAC THENL [ASM SET_TAC[]; MATCH_MP_TAC EQ_IMP] THEN
6841     AP_TERM_TAC THEN ASM SET_TAC[]]);;
6842
6843 (* ------------------------------------------------------------------------- *)
6844 (* More properties of open and closed maps.                                  *)
6845 (* ------------------------------------------------------------------------- *)
6846
6847 let OPEN_MAP_RESTRICT = prove
6848  (`!f:real^M->real^N s t t'.
6849         (!u. open_in (subtopology euclidean s) u
6850              ==> open_in (subtopology euclidean t) (IMAGE f u)) /\
6851         t' SUBSET t
6852         ==> !u. open_in (subtopology euclidean {x | x IN s /\ f x IN t'}) u
6853                 ==> open_in (subtopology euclidean t') (IMAGE f u)`,
6854   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN] THEN
6855   REWRITE_TAC[LEFT_IMP_EXISTS_THM; IMP_CONJ] THEN
6856   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
6857   REWRITE_TAC[RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2] THEN
6858   REPEAT DISCH_TAC THEN X_GEN_TAC `c:real^M->bool` THEN
6859   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `c:real^M->bool`) THEN
6860   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[]);;
6861
6862 let CLOSED_MAP_RESTRICT = prove
6863  (`!f:real^M->real^N s t t'.
6864         (!u. closed_in (subtopology euclidean s) u
6865              ==> closed_in (subtopology euclidean t) (IMAGE f u)) /\
6866         t' SUBSET t
6867         ==> !u. closed_in (subtopology euclidean {x | x IN s /\ f x IN t'}) u
6868                 ==> closed_in (subtopology euclidean t') (IMAGE f u)`,
6869   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN_CLOSED] THEN
6870   REWRITE_TAC[LEFT_IMP_EXISTS_THM; IMP_CONJ] THEN
6871   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
6872   REWRITE_TAC[RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2] THEN
6873   REPEAT DISCH_TAC THEN X_GEN_TAC `c:real^M->bool` THEN
6874   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `c:real^M->bool`) THEN
6875   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[]);;
6876
6877 let QUOTIENT_MAP_OPEN_MAP_EQ = prove
6878  (`!f:real^M->real^N s t.
6879        IMAGE f s SUBSET t /\
6880        (!u. u SUBSET t
6881             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6882                  open_in (subtopology euclidean t) u))
6883        ==> ((!k. open_in (subtopology euclidean s) k
6884                  ==> open_in (subtopology euclidean t) (IMAGE f k)) <=>
6885             (!k. open_in (subtopology euclidean s) k
6886                  ==> open_in (subtopology euclidean s)
6887                                {x | x IN s /\ f x IN IMAGE f k}))`,
6888   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN
6889   X_GEN_TAC `k:real^M->bool` THEN STRIP_TAC THEN
6890   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
6891   FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (f:real^M->real^N) k`) THEN
6892   ASM_SIMP_TAC[IMAGE_SUBSET] THEN DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]);;
6893
6894 let QUOTIENT_MAP_CLOSED_MAP_EQ = prove
6895  (`!f:real^M->real^N s t.
6896        IMAGE f s SUBSET t /\
6897        (!u. u SUBSET t
6898             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
6899                  open_in (subtopology euclidean t) u))
6900        ==> ((!k. closed_in (subtopology euclidean s) k
6901                  ==> closed_in (subtopology euclidean t) (IMAGE f k)) <=>
6902             (!k. closed_in (subtopology euclidean s) k
6903                  ==> closed_in (subtopology euclidean s)
6904                                {x | x IN s /\ f x IN IMAGE f k}))`,
6905   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
6906   ASM_SIMP_TAC[QUOTIENT_MAP_OPEN_CLOSED] THEN
6907   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN
6908   X_GEN_TAC `k:real^M->bool` THEN STRIP_TAC THEN
6909   FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
6910   FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (f:real^M->real^N) k`) THEN
6911   ASM_SIMP_TAC[IMAGE_SUBSET] THEN DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]);;
6912
6913 let CLOSED_MAP_IMP_OPEN_MAP = prove
6914  (`!f:real^M->real^N s t.
6915         IMAGE f s = t /\
6916         (!u. closed_in (subtopology euclidean s) u
6917                 ==> closed_in (subtopology euclidean t) (IMAGE f u)) /\
6918         (!u. open_in (subtopology euclidean s) u
6919              ==> open_in (subtopology euclidean s)
6920                          {x | x IN s /\ f x IN IMAGE f u})
6921         ==> (!u. open_in (subtopology euclidean s) u
6922                  ==> open_in (subtopology euclidean t) (IMAGE f u))`,
6923   REPEAT STRIP_TAC THEN
6924   SUBGOAL_THEN
6925     `IMAGE (f:real^M->real^N) u =
6926      t DIFF IMAGE f (s DIFF {x | x IN s /\ f x IN IMAGE f u})`
6927   SUBST1_TAC THENL
6928    [FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN ASM SET_TAC[];
6929     MATCH_MP_TAC OPEN_IN_DIFF THEN REWRITE_TAC[OPEN_IN_REFL] THEN
6930     FIRST_X_ASSUM MATCH_MP_TAC THEN
6931     MATCH_MP_TAC CLOSED_IN_DIFF THEN REWRITE_TAC[OPEN_IN_REFL] THEN
6932     ASM_SIMP_TAC[CLOSED_IN_REFL]]);;
6933
6934 let OPEN_MAP_IMP_CLOSED_MAP = prove
6935  (`!f:real^M->real^N s t.
6936         IMAGE f s = t /\
6937         (!u. open_in (subtopology euclidean s) u
6938                 ==> open_in (subtopology euclidean t) (IMAGE f u)) /\
6939         (!u. closed_in (subtopology euclidean s) u
6940              ==> closed_in (subtopology euclidean s)
6941                          {x | x IN s /\ f x IN IMAGE f u})
6942         ==> (!u. closed_in (subtopology euclidean s) u
6943                  ==> closed_in (subtopology euclidean t) (IMAGE f u))`,
6944   REPEAT STRIP_TAC THEN
6945   SUBGOAL_THEN
6946     `IMAGE (f:real^M->real^N) u =
6947      t DIFF IMAGE f (s DIFF {x | x IN s /\ f x IN IMAGE f u})`
6948   SUBST1_TAC THENL
6949    [FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN ASM SET_TAC[];
6950     MATCH_MP_TAC CLOSED_IN_DIFF THEN REWRITE_TAC[CLOSED_IN_REFL] THEN
6951     FIRST_X_ASSUM MATCH_MP_TAC THEN
6952     MATCH_MP_TAC OPEN_IN_DIFF THEN REWRITE_TAC[CLOSED_IN_REFL] THEN
6953     ASM_SIMP_TAC[OPEN_IN_REFL]]);;
6954
6955 let OPEN_MAP_FROM_COMPOSITION_SURJECTIVE = prove
6956  (`!f:real^M->real^N g:real^N->real^P s t u.
6957         f continuous_on s /\ IMAGE f s = t /\ IMAGE g t SUBSET u /\
6958         (!k. open_in (subtopology euclidean s) k
6959              ==> open_in (subtopology euclidean u) (IMAGE (g o f) k))
6960         ==> (!k. open_in (subtopology euclidean t) k
6961                  ==> open_in (subtopology euclidean u) (IMAGE g k))`,
6962   REPEAT STRIP_TAC THEN SUBGOAL_THEN
6963    `IMAGE g k = IMAGE ((g:real^N->real^P) o (f:real^M->real^N))
6964                       {x | x IN s /\ f(x) IN k}`
6965   SUBST1_TAC THENL
6966    [FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
6967     REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[];
6968     FIRST_X_ASSUM MATCH_MP_TAC THEN
6969     MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE_GEN THEN
6970     EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[SUBSET_REFL]]);;
6971
6972 let CLOSED_MAP_FROM_COMPOSITION_SURJECTIVE = prove
6973  (`!f:real^M->real^N g:real^N->real^P s t u.
6974         f continuous_on s /\ IMAGE f s = t /\ IMAGE g t SUBSET u /\
6975         (!k. closed_in (subtopology euclidean s) k
6976              ==> closed_in (subtopology euclidean u) (IMAGE (g o f) k))
6977         ==> (!k. closed_in (subtopology euclidean t) k
6978                  ==> closed_in (subtopology euclidean u) (IMAGE g k))`,
6979   REPEAT STRIP_TAC THEN SUBGOAL_THEN
6980    `IMAGE g k = IMAGE ((g:real^N->real^P) o (f:real^M->real^N))
6981                       {x | x IN s /\ f(x) IN k}`
6982   SUBST1_TAC THENL
6983    [FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
6984     REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[];
6985     FIRST_X_ASSUM MATCH_MP_TAC THEN
6986     MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE_GEN THEN
6987     EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[SUBSET_REFL]]);;
6988
6989 let OPEN_MAP_FROM_COMPOSITION_INJECTIVE = prove
6990  (`!f:real^M->real^N g:real^N->real^P s t u.
6991         IMAGE f s SUBSET t /\ IMAGE g t SUBSET u /\
6992         g continuous_on t /\ (!x y. x IN t /\ y IN t /\ g x = g y ==> x = y) /\
6993         (!k. open_in (subtopology euclidean s) k
6994              ==> open_in (subtopology euclidean u) (IMAGE (g o f) k))
6995         ==> (!k. open_in (subtopology euclidean s) k
6996                  ==> open_in (subtopology euclidean t) (IMAGE f k))`,
6997   REPEAT STRIP_TAC THEN SUBGOAL_THEN
6998    `IMAGE f k = {x | x IN t /\
6999                     g(x) IN IMAGE ((g:real^N->real^P) o (f:real^M->real^N)) k}`
7000   SUBST1_TAC THENL
7001    [FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
7002     REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[];
7003     MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE_GEN THEN
7004     EXISTS_TAC `u:real^P->bool` THEN ASM_SIMP_TAC[]]);;
7005
7006 let CLOSED_MAP_FROM_COMPOSITION_INJECTIVE = prove
7007  (`!f:real^M->real^N g:real^N->real^P s t u.
7008         IMAGE f s SUBSET t /\ IMAGE g t SUBSET u /\
7009         g continuous_on t /\ (!x y. x IN t /\ y IN t /\ g x = g y ==> x = y) /\
7010         (!k. closed_in (subtopology euclidean s) k
7011              ==> closed_in (subtopology euclidean u) (IMAGE (g o f) k))
7012         ==> (!k. closed_in (subtopology euclidean s) k
7013                  ==> closed_in (subtopology euclidean t) (IMAGE f k))`,
7014   REPEAT STRIP_TAC THEN SUBGOAL_THEN
7015    `IMAGE f k = {x | x IN t /\
7016                     g(x) IN IMAGE ((g:real^N->real^P) o (f:real^M->real^N)) k}`
7017   SUBST1_TAC THENL
7018    [FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
7019     REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[];
7020     MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE_GEN THEN
7021     EXISTS_TAC `u:real^P->bool` THEN ASM_SIMP_TAC[]]);;
7022
7023 let OPEN_MAP_CLOSED_SUPERSET_PREIMAGE = prove
7024  (`!f:real^M->real^N s t u w.
7025         (!k. open_in (subtopology euclidean s) k
7026              ==> open_in (subtopology euclidean t) (IMAGE f k)) /\
7027         closed_in (subtopology euclidean s) u /\
7028         w SUBSET t /\ {x | x IN s /\ f(x) IN w} SUBSET u
7029         ==> ?v. closed_in (subtopology euclidean t) v /\
7030                 w SUBSET v /\
7031                 {x | x IN s /\ f(x) IN v} SUBSET u`,
7032   REPEAT STRIP_TAC THEN
7033   EXISTS_TAC `t DIFF IMAGE (f:real^M->real^N) (s DIFF u)` THEN
7034   CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
7035   MATCH_MP_TAC CLOSED_IN_DIFF THEN REWRITE_TAC[CLOSED_IN_REFL] THEN
7036   FIRST_X_ASSUM MATCH_MP_TAC THEN
7037   ASM_SIMP_TAC[OPEN_IN_DIFF; OPEN_IN_REFL]);;
7038
7039 let OPEN_MAP_CLOSED_SUPERSET_PREIMAGE_EQ = prove
7040  (`!f:real^M->real^N s t.
7041        IMAGE f s SUBSET t
7042        ==> ((!k. open_in (subtopology euclidean s) k
7043                  ==> open_in (subtopology euclidean t) (IMAGE f k)) <=>
7044             (!u w. closed_in (subtopology euclidean s) u /\
7045                    w SUBSET t /\ {x | x IN s /\ f(x) IN w} SUBSET u
7046                    ==> ?v. closed_in (subtopology euclidean t) v /\
7047                            w SUBSET v /\ {x | x IN s /\ f(x) IN v} SUBSET u))`,
7048   REPEAT(STRIP_TAC ORELSE EQ_TAC) THEN
7049   ASM_SIMP_TAC[OPEN_MAP_CLOSED_SUPERSET_PREIMAGE] THEN
7050   FIRST_X_ASSUM(MP_TAC o SPECL
7051    [`s DIFF k:real^M->bool`; `t DIFF IMAGE (f:real^M->real^N) k`]) THEN
7052   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
7053   ASM_SIMP_TAC[CLOSED_IN_DIFF; CLOSED_IN_REFL] THEN
7054   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7055   DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool` STRIP_ASSUME_TAC) THEN
7056   SUBGOAL_THEN `IMAGE (f:real^M->real^N) k = t DIFF v` SUBST1_TAC THENL
7057    [ASM SET_TAC[]; ASM_SIMP_TAC[OPEN_IN_DIFF; OPEN_IN_REFL]]);;
7058
7059 let CLOSED_MAP_OPEN_SUPERSET_PREIMAGE = prove
7060  (`!f:real^M->real^N s t u w.
7061         (!k. closed_in (subtopology euclidean s) k
7062              ==> closed_in (subtopology euclidean t) (IMAGE f k)) /\
7063         open_in (subtopology euclidean s) u /\
7064         w SUBSET t /\ {x | x IN s /\ f(x) IN w} SUBSET u
7065         ==> ?v. open_in (subtopology euclidean t) v /\
7066                 w SUBSET v /\
7067                 {x | x IN s /\ f(x) IN v} SUBSET u`,
7068   REPEAT STRIP_TAC THEN
7069   EXISTS_TAC `t DIFF IMAGE (f:real^M->real^N) (s DIFF u)` THEN
7070   CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
7071   MATCH_MP_TAC OPEN_IN_DIFF THEN REWRITE_TAC[OPEN_IN_REFL] THEN
7072   FIRST_X_ASSUM MATCH_MP_TAC THEN
7073   ASM_SIMP_TAC[CLOSED_IN_DIFF; CLOSED_IN_REFL]);;
7074
7075 let CLOSED_MAP_OPEN_SUPERSET_PREIMAGE_EQ = prove
7076  (`!f:real^M->real^N s t.
7077        IMAGE f s SUBSET t
7078        ==> ((!k. closed_in (subtopology euclidean s) k
7079                  ==> closed_in (subtopology euclidean t) (IMAGE f k)) <=>
7080             (!u w. open_in (subtopology euclidean s) u /\
7081                    w SUBSET t /\ {x | x IN s /\ f(x) IN w} SUBSET u
7082                    ==> ?v. open_in (subtopology euclidean t) v /\
7083                            w SUBSET v /\ {x | x IN s /\ f(x) IN v} SUBSET u))`,
7084   REPEAT(STRIP_TAC ORELSE EQ_TAC) THEN
7085   ASM_SIMP_TAC[CLOSED_MAP_OPEN_SUPERSET_PREIMAGE] THEN
7086   FIRST_X_ASSUM(MP_TAC o SPECL
7087    [`s DIFF k:real^M->bool`; `t DIFF IMAGE (f:real^M->real^N) k`]) THEN
7088   FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
7089   ASM_SIMP_TAC[OPEN_IN_DIFF; OPEN_IN_REFL] THEN
7090   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7091   DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool` STRIP_ASSUME_TAC) THEN
7092   SUBGOAL_THEN `IMAGE (f:real^M->real^N) k = t DIFF v` SUBST1_TAC THENL
7093    [ASM SET_TAC[]; ASM_SIMP_TAC[CLOSED_IN_DIFF; CLOSED_IN_REFL]]);;
7094
7095 let CLOSED_MAP_OPEN_SUPERSET_PREIMAGE_POINT = prove
7096  (`!f:real^M->real^N s t.
7097        IMAGE f s SUBSET t
7098        ==> ((!k. closed_in (subtopology euclidean s) k
7099                  ==> closed_in (subtopology euclidean t) (IMAGE f k)) <=>
7100             (!u y. open_in (subtopology euclidean s) u /\
7101                    y IN t /\ {x | x IN s /\ f(x) = y} SUBSET u
7102                    ==> ?v. open_in (subtopology euclidean t) v /\
7103                            y IN v /\ {x | x IN s /\ f(x) IN v} SUBSET u))`,
7104   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[CLOSED_MAP_OPEN_SUPERSET_PREIMAGE_EQ] THEN
7105   EQ_TAC THEN DISCH_TAC THENL
7106    [MAP_EVERY X_GEN_TAC [`u:real^M->bool`; `y:real^N`] THEN
7107     STRIP_TAC THEN
7108     FIRST_X_ASSUM(MP_TAC o SPECL  [`u:real^M->bool`; `{y:real^N}`]) THEN
7109     ASM_REWRITE_TAC[SING_SUBSET; IN_SING];
7110     MAP_EVERY X_GEN_TAC [`u:real^M->bool`; `w:real^N->bool`] THEN
7111     STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `u:real^M->bool`) THEN
7112     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
7113     REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
7114     X_GEN_TAC `vv:real^N->real^N->bool` THEN DISCH_TAC THEN
7115     EXISTS_TAC `UNIONS {(vv:real^N->real^N->bool) y | y IN w}` THEN
7116     CONJ_TAC THENL
7117      [MATCH_MP_TAC OPEN_IN_UNIONS THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
7118       ASM SET_TAC[];
7119       REWRITE_TAC[UNIONS_GSPEC] THEN
7120       CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7121       REWRITE_TAC[SUBSET; IN_ELIM_THM; RIGHT_AND_EXISTS_THM;
7122                   LEFT_IMP_EXISTS_THM] THEN
7123       MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^N`] THEN STRIP_TAC THEN
7124       FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ASM SET_TAC[]]]);;
7125
7126 let CONNECTED_OPEN_MONOTONE_PREIMAGE = prove
7127  (`!f:real^M->real^N s t.
7128         f continuous_on s /\ IMAGE f s = t /\
7129         (!c. open_in (subtopology euclidean s) c
7130              ==> open_in (subtopology euclidean t) (IMAGE f c)) /\
7131         (!y. y IN t ==> connected {x | x IN s /\ f x = y})
7132         ==> !c. connected c /\ c SUBSET t
7133                 ==> connected {x | x IN s /\ f x IN c}`,
7134   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `c:real^N->bool` o MATCH_MP
7135    (ONCE_REWRITE_RULE[IMP_CONJ] OPEN_MAP_RESTRICT)) THEN
7136   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN MP_TAC(ISPECL
7137    [`f:real^M->real^N`; `{x | x IN s /\ (f:real^M->real^N) x IN c}`]
7138    OPEN_MAP_IMP_QUOTIENT_MAP) THEN
7139   SUBGOAL_THEN `IMAGE f {x | x IN s /\ (f:real^M->real^N) x IN c} = c`
7140   ASSUME_TAC THENL [ASM SET_TAC[]; ASM_REWRITE_TAC[]] THEN ANTS_TAC THENL
7141    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
7142       CONTINUOUS_ON_SUBSET)) THEN SET_TAC[];
7143     DISCH_TAC] THEN
7144   MATCH_MP_TAC CONNECTED_MONOTONE_QUOTIENT_PREIMAGE THEN
7145   MAP_EVERY EXISTS_TAC [`f:real^M->real^N`; `c:real^N->bool`] THEN
7146   ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
7147    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
7148       CONTINUOUS_ON_SUBSET)) THEN SET_TAC[];
7149     SIMP_TAC[SET_RULE
7150      `y IN c ==> {x | x IN {x | x IN s /\ f x IN c} /\ f x = y} =
7151                  {x | x IN s /\ f x = y}`] THEN
7152    ASM SET_TAC[]]);;
7153
7154 let CONNECTED_CLOSED_MONOTONE_PREIMAGE = prove
7155  (`!f:real^M->real^N s t.
7156         f continuous_on s /\ IMAGE f s = t /\
7157         (!c. closed_in (subtopology euclidean s) c
7158              ==> closed_in (subtopology euclidean t) (IMAGE f c)) /\
7159         (!y. y IN t ==> connected {x | x IN s /\ f x = y})
7160         ==> !c. connected c /\ c SUBSET t
7161                 ==> connected {x | x IN s /\ f x IN c}`,
7162   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `c:real^N->bool` o MATCH_MP
7163    (ONCE_REWRITE_RULE[IMP_CONJ] CLOSED_MAP_RESTRICT)) THEN
7164   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN MP_TAC(ISPECL
7165    [`f:real^M->real^N`; `{x | x IN s /\ (f:real^M->real^N) x IN c}`]
7166    CLOSED_MAP_IMP_QUOTIENT_MAP) THEN
7167   SUBGOAL_THEN `IMAGE f {x | x IN s /\ (f:real^M->real^N) x IN c} = c`
7168   ASSUME_TAC THENL [ASM SET_TAC[]; ASM_REWRITE_TAC[]] THEN ANTS_TAC THENL
7169    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
7170       CONTINUOUS_ON_SUBSET)) THEN SET_TAC[];
7171     DISCH_TAC] THEN
7172   MATCH_MP_TAC CONNECTED_MONOTONE_QUOTIENT_PREIMAGE THEN
7173   MAP_EVERY EXISTS_TAC [`f:real^M->real^N`; `c:real^N->bool`] THEN
7174   ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
7175    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
7176       CONTINUOUS_ON_SUBSET)) THEN SET_TAC[];
7177     SIMP_TAC[SET_RULE
7178      `y IN c ==> {x | x IN {x | x IN s /\ f x IN c} /\ f x = y} =
7179                  {x | x IN s /\ f x = y}`] THEN
7180    ASM SET_TAC[]]);;
7181
7182 (* ------------------------------------------------------------------------- *)
7183 (* Proper maps, including projections out of compact sets.                   *)
7184 (* ------------------------------------------------------------------------- *)
7185
7186 let PROPER_MAP = prove
7187  (`!f:real^M->real^N s t.
7188     IMAGE f s SUBSET t
7189     ==> ((!k. k SUBSET t /\ compact k ==> compact {x | x IN s /\ f x IN k}) <=>
7190          (!k. closed_in (subtopology euclidean s) k
7191               ==> closed_in (subtopology euclidean t) (IMAGE f k)) /\
7192          (!a. a IN t ==> compact {x | x IN s /\ f x = a}))`,
7193   REPEAT STRIP_TAC THEN EQ_TAC THENL
7194    [REPEAT STRIP_TAC THENL
7195      [ALL_TAC;
7196       ONCE_REWRITE_TAC[SET_RULE `x = a <=> x IN {a}`] THEN
7197       FIRST_X_ASSUM MATCH_MP_TAC THEN
7198       ASM_REWRITE_TAC[SING_SUBSET; COMPACT_SING]] THEN
7199     FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
7200     REWRITE_TAC[CLOSED_IN_LIMPT] THEN
7201     CONJ_TAC THENL [ASM SET_TAC[]; X_GEN_TAC `y:real^N`] THEN
7202     REWRITE_TAC[LIMPT_SEQUENTIAL_INJ; IN_DELETE] THEN
7203     REWRITE_TAC[IN_IMAGE; LEFT_AND_EXISTS_THM; SKOLEM_THM] THEN
7204     ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
7205     REWRITE_TAC[GSYM CONJ_ASSOC; FORALL_AND_THM] THEN
7206     ONCE_REWRITE_TAC[GSYM FUN_EQ_THM] THEN
7207     REWRITE_TAC[UNWIND_THM2; FUN_EQ_THM] THEN
7208     DISCH_THEN(X_CHOOSE_THEN `x:num->real^M` STRIP_ASSUME_TAC) THEN
7209     SUBGOAL_THEN
7210      `~(INTERS {{a | a IN k /\
7211                      (f:real^M->real^N) a IN
7212                      (y INSERT IMAGE (\i. f(x(n + i))) (:num))} |
7213                 n IN (:num)} = {})`
7214     MP_TAC THENL
7215      [MATCH_MP_TAC COMPACT_FIP THEN CONJ_TAC THENL
7216        [REWRITE_TAC[FORALL_IN_GSPEC; IN_UNIV] THEN X_GEN_TAC `n:num` THEN
7217         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CLOSED_IN_CLOSED]) THEN
7218         DISCH_THEN(X_CHOOSE_THEN `c:real^M->bool` STRIP_ASSUME_TAC) THEN
7219         ASM_REWRITE_TAC[SET_RULE
7220          `{x | x IN s INTER k /\ P x} = k INTER {x | x IN s /\ P x}`] THEN
7221         MATCH_MP_TAC CLOSED_INTER_COMPACT THEN ASM_REWRITE_TAC[] THEN
7222         FIRST_X_ASSUM MATCH_MP_TAC THEN
7223         CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7224         MATCH_MP_TAC COMPACT_SEQUENCE_WITH_LIMIT THEN
7225         FIRST_ASSUM(MP_TAC o SPEC `n:num` o MATCH_MP SEQ_OFFSET) THEN
7226         REWRITE_TAC[ADD_SYM];
7227         REWRITE_TAC[SIMPLE_IMAGE; FORALL_FINITE_SUBSET_IMAGE] THEN
7228         X_GEN_TAC `i:num->bool` THEN STRIP_TAC THEN
7229         FIRST_ASSUM(MP_TAC o ISPEC `\n:num. n` o MATCH_MP
7230           UPPER_BOUND_FINITE_SET) THEN
7231         REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_TAC `m:num`) THEN
7232         REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; INTERS_IMAGE; IN_ELIM_THM] THEN
7233         EXISTS_TAC `(x:num->real^M) m` THEN
7234         X_GEN_TAC `p:num` THEN DISCH_TAC THEN
7235         CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7236         REWRITE_TAC[IN_INSERT; IN_IMAGE; IN_UNIV] THEN DISJ2_TAC THEN
7237         EXISTS_TAC `m - p:num` THEN
7238         ASM_MESON_TAC[ARITH_RULE `p <= m ==> p + m - p:num = m`]];
7239       REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN MATCH_MP_TAC MONO_EXISTS THEN
7240       X_GEN_TAC `x:real^M` THEN
7241       REWRITE_TAC[INTERS_GSPEC; IN_ELIM_THM; IN_UNIV] THEN
7242       DISCH_THEN(fun th -> LABEL_TAC "*" th THEN MP_TAC(SPEC `0` th)) THEN
7243       REWRITE_TAC[ADD_CLAUSES; IN_INSERT; IN_IMAGE; IN_UNIV] THEN
7244       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (DISJ_CASES_THEN MP_TAC)) THEN
7245       ASM_SIMP_TAC[] THEN DISCH_THEN(X_CHOOSE_TAC `i:num`) THEN
7246       REMOVE_THEN "*" (MP_TAC o SPEC `i + 1`) THEN
7247       ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
7248       ASM_REWRITE_TAC[IN_INSERT; IN_IMAGE; IN_UNIV] THEN ARITH_TAC];
7249     STRIP_TAC THEN X_GEN_TAC `k:real^N->bool` THEN STRIP_TAC THEN
7250     REWRITE_TAC[COMPACT_EQ_HEINE_BOREL] THEN
7251     X_GEN_TAC `c:(real^M->bool)->bool` THEN STRIP_TAC THEN
7252     SUBGOAL_THEN
7253      `!a. a IN k
7254           ==> ?g. g SUBSET c /\ FINITE g /\
7255                   {x | x IN s /\ (f:real^M->real^N) x = a} SUBSET UNIONS g`
7256     MP_TAC THENL
7257      [X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN UNDISCH_THEN
7258        `!a. a IN t ==> compact {x | x IN s /\ (f:real^M->real^N) x = a}`
7259        (MP_TAC o SPEC `a:real^N`) THEN
7260       ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[COMPACT_EQ_HEINE_BOREL]] THEN
7261       DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
7262       GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
7263       REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
7264       X_GEN_TAC `uu:real^N->(real^M->bool)->bool` THEN
7265       DISCH_THEN(LABEL_TAC "*")] THEN
7266     SUBGOAL_THEN
7267      `!a. a IN k
7268           ==> ?v. open v /\ a IN v /\
7269                  {x | x IN s /\ (f:real^M->real^N) x IN v} SUBSET UNIONS(uu a)`
7270     MP_TAC THENL
7271      [REPEAT STRIP_TAC THEN
7272       UNDISCH_THEN
7273        `!k. closed_in (subtopology euclidean s) k
7274             ==> closed_in (subtopology euclidean t)
7275                           (IMAGE (f:real^M->real^N) k)`
7276        (MP_TAC o SPEC `(s:real^M->bool) DIFF UNIONS(uu(a:real^N))`) THEN
7277       SIMP_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN ANTS_TAC THENL
7278        [CONJ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
7279         REWRITE_TAC[SET_RULE `s DIFF (s DIFF t) = s INTER t`] THEN
7280         MATCH_MP_TAC OPEN_IN_OPEN_INTER THEN
7281         MATCH_MP_TAC OPEN_UNIONS THEN ASM SET_TAC[];
7282         DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
7283         REWRITE_TAC[OPEN_IN_OPEN] THEN MATCH_MP_TAC MONO_EXISTS THEN
7284         X_GEN_TAC `v:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
7285         REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N`)) THEN
7286         ASM_REWRITE_TAC[] THEN REPEAT
7287          ((ANTS_TAC THENL [ASM SET_TAC[]; DISCH_TAC]) ORELSE STRIP_TAC)
7288         THENL [ALL_TAC; ASM SET_TAC[]] THEN
7289         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
7290         DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN ASM SET_TAC[]];
7291       GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
7292       REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
7293       X_GEN_TAC `vv:real^N->(real^N->bool)` THEN
7294       DISCH_THEN(LABEL_TAC "+")] THEN
7295     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL]) THEN
7296     DISCH_THEN(MP_TAC o SPEC `IMAGE (vv:real^N->(real^N->bool)) k`) THEN
7297     ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN
7298     ONCE_REWRITE_TAC[TAUT `p /\ q /\ r ==> s <=> q /\ p ==> r ==> s`] THEN
7299     REWRITE_TAC[FORALL_FINITE_SUBSET_IMAGE] THEN
7300     X_GEN_TAC `j:real^N->bool` THEN REPEAT STRIP_TAC THEN
7301     EXISTS_TAC `UNIONS(IMAGE (uu:real^N->(real^M->bool)->bool) j)` THEN
7302     REPEAT CONJ_TAC THENL
7303      [ASM SET_TAC[];
7304       ASM_SIMP_TAC[FINITE_UNIONS; FORALL_IN_IMAGE; FINITE_IMAGE] THEN
7305       ASM SET_TAC[];
7306       REWRITE_TAC[UNIONS_IMAGE; SUBSET; IN_UNIONS; IN_ELIM_THM] THEN
7307       ASM SET_TAC[]]]);;
7308
7309 let COMPACT_CONTINUOUS_IMAGE_EQ = prove
7310  (`!f:real^M->real^N s.
7311         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
7312         ==> (f continuous_on s <=>
7313              !t. compact t /\ t SUBSET s ==> compact(IMAGE f t))`,
7314   REPEAT STRIP_TAC THEN EQ_TAC THENL
7315    [MESON_TAC[COMPACT_CONTINUOUS_IMAGE; CONTINUOUS_ON_SUBSET]; DISCH_TAC] THEN
7316   FIRST_X_ASSUM(X_CHOOSE_TAC `g:real^N->real^M` o
7317     GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
7318   REWRITE_TAC[CONTINUOUS_ON_CLOSED] THEN
7319   X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
7320   MP_TAC(ISPECL [`g:real^N->real^M`; `IMAGE (f:real^M->real^N) s`;
7321                  `s:real^M->bool`] PROPER_MAP) THEN
7322   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7323   MATCH_MP_TAC(TAUT `(q ==> s) /\ p ==> (p <=> q /\ r) ==> s`) THEN
7324   REPEAT STRIP_TAC THENL
7325    [SUBGOAL_THEN
7326      `{x | x IN s /\ (f:real^M->real^N) x IN u} = IMAGE g u`
7327      (fun th -> ASM_MESON_TAC[th]);
7328     SUBGOAL_THEN
7329      `{x | x IN IMAGE f s /\ (g:real^N->real^M) x IN k} = IMAGE f k`
7330      (fun th -> ASM_SIMP_TAC[th])] THEN
7331   FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN ASM SET_TAC[]);;
7332
7333 let PROPER_MAP_FROM_COMPACT = prove
7334  (`!f:real^M->real^N s k.
7335         f continuous_on s /\ IMAGE f s SUBSET t /\ compact s /\
7336         closed_in (subtopology euclidean t) k
7337         ==> compact {x | x IN s /\ f x IN k}`,
7338   REPEAT STRIP_TAC THEN
7339   MATCH_MP_TAC CLOSED_IN_COMPACT THEN EXISTS_TAC `s:real^M->bool` THEN
7340   ASM_MESON_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE_GEN]);;
7341
7342 let PROPER_MAP_COMPOSE = prove
7343  (`!f:real^M->real^N g:real^N->real^P s t u.
7344         IMAGE f s SUBSET t /\
7345         (!k. k SUBSET t /\ compact k ==> compact {x | x IN s /\ f x IN k}) /\
7346         (!k. k SUBSET u /\ compact k ==> compact {x | x IN t /\ g x IN k})
7347         ==> !k. k SUBSET u /\ compact k
7348                 ==> compact {x | x IN s /\ (g o f) x IN k}`,
7349   REPEAT STRIP_TAC THEN REWRITE_TAC[o_THM] THEN
7350   FIRST_X_ASSUM(MP_TAC o SPEC `k:real^P->bool`) THEN
7351   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
7352   FIRST_X_ASSUM(MP_TAC o SPEC `{x | x IN t /\ (g:real^N->real^P) x IN k}`) THEN
7353   ANTS_TAC THENL [ASM SET_TAC[]; MATCH_MP_TAC EQ_IMP] THEN
7354   AP_TERM_TAC THEN ASM SET_TAC[]);;
7355
7356 let PROPER_MAP_FROM_COMPOSITION_LEFT = prove
7357  (`!f:real^M->real^N g:real^N->real^P s t u.
7358         f continuous_on s /\ IMAGE f s = t /\
7359         g continuous_on t /\ IMAGE g t SUBSET u /\
7360         (!k. k SUBSET u /\ compact k
7361              ==> compact {x | x IN s /\ (g o f) x IN k})
7362         ==> !k. k SUBSET u /\ compact k ==> compact {x | x IN t /\ g x IN k}`,
7363   REWRITE_TAC[o_THM] THEN REPEAT STRIP_TAC THEN
7364   FIRST_X_ASSUM(MP_TAC o SPEC `k:real^P->bool`) THEN ASM_REWRITE_TAC[] THEN
7365   DISCH_THEN(MP_TAC o ISPEC `f:real^M->real^N` o MATCH_MP
7366    (REWRITE_RULE[IMP_CONJ_ALT] COMPACT_CONTINUOUS_IMAGE)) THEN
7367   ANTS_TAC THENL
7368    [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
7369         CONTINUOUS_ON_SUBSET)) THEN SET_TAC[];
7370     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]]);;
7371
7372 let PROPER_MAP_FROM_COMPOSITION_RIGHT = prove
7373  (`!f:real^M->real^N g:real^N->real^P s t u.
7374         f continuous_on s /\ IMAGE f s SUBSET t /\
7375         g continuous_on t /\ IMAGE g t SUBSET u /\
7376         (!k. k SUBSET u /\ compact k
7377              ==> compact {x | x IN s /\ (g o f) x IN k})
7378         ==> !k. k SUBSET t /\ compact k ==> compact {x | x IN s /\ f x IN k}`,
7379   let lemma = prove
7380    (`!s t. closed_in (subtopology euclidean s) t ==> compact s ==> compact t`,
7381     MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_SUBSET;
7382               CLOSED_IN_CLOSED_EQ]) in
7383   REWRITE_TAC[o_THM] THEN REPEAT STRIP_TAC THEN
7384   FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (g:real^N->real^P) k`) THEN
7385   ANTS_TAC THENL
7386    [CONJ_TAC THENL [ASM SET_TAC[]; MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE] THEN
7387     ASM_MESON_TAC[CONTINUOUS_ON_SUBSET];
7388     MATCH_MP_TAC lemma THEN
7389     MATCH_MP_TAC CLOSED_IN_SUBSET_TRANS THEN
7390     EXISTS_TAC `s:real^M->bool` THEN
7391     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
7392     MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE_GEN THEN
7393     EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
7394     MATCH_MP_TAC CLOSED_SUBSET THEN ASM_SIMP_TAC[COMPACT_IMP_CLOSED]]);;
7395
7396 let PROPER_MAP_FSTCART = prove
7397  (`!s:real^M->bool t:real^N->bool k.
7398         compact t /\ k SUBSET s /\ compact k
7399         ==> compact {z | z IN s PCROSS t /\ fstcart z IN k}`,
7400   REPEAT STRIP_TAC THEN SUBGOAL_THEN
7401    `{z | z IN s PCROSS t /\ fstcart z IN k} =
7402     (k:real^M->bool) PCROSS (t:real^N->bool)`
7403    (fun th -> ASM_SIMP_TAC[th; COMPACT_PCROSS]) THEN
7404   REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_THM;
7405               PASTECART_IN_PCROSS; FSTCART_PASTECART] THEN
7406   ASM SET_TAC[]);;
7407
7408 let CLOSED_MAP_FSTCART = prove
7409  (`!s:real^M->bool t:real^N->bool c.
7410         compact t /\ closed_in (subtopology euclidean (s PCROSS t)) c
7411         ==> closed_in (subtopology euclidean s) (IMAGE fstcart c)`,
7412   REPEAT STRIP_TAC THEN
7413   MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`;
7414                  `(s:real^M->bool) PCROSS (t:real^N->bool)`;
7415                  `s:real^M->bool`]
7416         PROPER_MAP) THEN
7417   ASM_SIMP_TAC[PROPER_MAP_FSTCART; IMAGE_FSTCART_PCROSS] THEN
7418   ASM SET_TAC[]);;
7419
7420 let PROPER_MAP_SNDCART = prove
7421  (`!s:real^M->bool t:real^N->bool k.
7422         compact s /\ k SUBSET t /\ compact k
7423         ==> compact {z | z IN s PCROSS t /\ sndcart z IN k}`,
7424   REPEAT STRIP_TAC THEN SUBGOAL_THEN
7425    `{z | z IN s PCROSS t /\ sndcart z IN k} =
7426     (s:real^M->bool) PCROSS (k:real^N->bool)`
7427    (fun th -> ASM_SIMP_TAC[th; COMPACT_PCROSS]) THEN
7428   REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_THM;
7429               PASTECART_IN_PCROSS; SNDCART_PASTECART] THEN
7430   ASM SET_TAC[]);;
7431
7432 let CLOSED_MAP_SNDCART = prove
7433  (`!s:real^M->bool t:real^N->bool c.
7434         compact s /\ closed_in (subtopology euclidean (s PCROSS t)) c
7435         ==> closed_in (subtopology euclidean t) (IMAGE sndcart c)`,
7436   REPEAT STRIP_TAC THEN
7437   MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`;
7438                  `(s:real^M->bool) PCROSS (t:real^N->bool)`;
7439                  `t:real^N->bool`]
7440         PROPER_MAP) THEN
7441   ASM_SIMP_TAC[PROPER_MAP_SNDCART; IMAGE_SNDCART_PCROSS] THEN
7442   ASM SET_TAC[]);;
7443
7444 let CLOSED_IN_COMPACT_PROJECTION = prove
7445  (`!s:real^M->bool t:real^N->bool u.
7446     compact s /\ closed_in (subtopology euclidean (s PCROSS t)) u
7447     ==> closed_in (subtopology euclidean t)
7448                   {y | ?x. x IN s /\ pastecart x y IN u}`,
7449   REPEAT GEN_TAC THEN DISCH_TAC THEN
7450   FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_MAP_SNDCART) THEN
7451   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
7452   FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET o CONJUNCT2) THEN
7453   REWRITE_TAC[EXTENSION; SUBSET; IN_IMAGE; FORALL_PASTECART; EXISTS_PASTECART;
7454               PASTECART_IN_PCROSS; IN_ELIM_THM; SNDCART_PASTECART] THEN
7455   SET_TAC[]);;
7456
7457 let CLOSED_COMPACT_PROJECTION = prove
7458  (`!s:real^M->bool t:real^(M,N)finite_sum->bool.
7459       compact s /\ closed t ==> closed {y | ?x. x IN s /\ pastecart x y IN t}`,
7460   REPEAT STRIP_TAC THEN
7461   SUBGOAL_THEN
7462    `{y | ?x:real^M. x IN s /\ pastecart x y IN t} =
7463     {y | ?x. x IN s /\ pastecart x y IN ((s PCROSS (:real^N)) INTER t)}`
7464   SUBST1_TAC THENL
7465    [REWRITE_TAC[PASTECART_IN_PCROSS; IN_UNIV; IN_INTER] THEN SET_TAC[];
7466     MATCH_MP_TAC CLOSED_IN_CLOSED_TRANS THEN
7467     EXISTS_TAC `(:real^N)` THEN REWRITE_TAC[CLOSED_UNIV] THEN
7468     MATCH_MP_TAC CLOSED_IN_COMPACT_PROJECTION THEN
7469     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CLOSED_SUBSET THEN
7470     ASM_SIMP_TAC[CLOSED_INTER; CLOSED_UNIV; CLOSED_PCROSS; COMPACT_IMP_CLOSED;
7471                  INTER_SUBSET]]);;
7472
7473 let TUBE_LEMMA = prove
7474  (`!s:real^M->bool t:real^N->bool u a.
7475         compact s /\ ~(s = {}) /\ {pastecart x a | x IN s} SUBSET u /\
7476         open_in(subtopology euclidean (s PCROSS t)) u
7477         ==> ?v. open_in (subtopology euclidean t) v /\ a IN v /\
7478                 (s PCROSS v) SUBSET u`,
7479   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN
7480   REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ] THEN
7481   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
7482   REPEAT STRIP_TAC THEN
7483   FIRST_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT; PCROSS]
7484         CLOSED_IN_COMPACT_PROJECTION)) THEN
7485   ASM_REWRITE_TAC[IN_ELIM_PASTECART_THM; IN_DIFF] THEN
7486   REWRITE_TAC[GSYM CONJ_ASSOC] THEN MATCH_MP_TAC(MESON[]
7487    `(closed_in top t ==> s DIFF (s DIFF t) = t) /\
7488     s DIFF t SUBSET s /\ P(s DIFF t)
7489     ==> closed_in top t
7490         ==> ?v. v SUBSET s /\ closed_in top (s DIFF v) /\ P v`) THEN
7491   REWRITE_TAC[SET_RULE `s DIFF (s DIFF t) = t <=> t SUBSET s`] THEN
7492   REWRITE_TAC[SUBSET_DIFF] THEN
7493   SIMP_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
7494   REWRITE_TAC[IN_DIFF; IN_ELIM_THM] THEN
7495   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
7496   CONJ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
7497   REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET])) THEN
7498   REWRITE_TAC[FORALL_IN_GSPEC; IN_SING; FORALL_PASTECART] THEN
7499   REWRITE_TAC[IN_ELIM_PASTECART_THM] THEN ASM_MESON_TAC[MEMBER_NOT_EMPTY]);;
7500
7501 let TUBE_LEMMA_GEN = prove
7502  (`!s t t' u:real^(M,N)finite_sum->bool.
7503         compact s /\ ~(s = {}) /\ t SUBSET t' /\
7504         s PCROSS t SUBSET u /\
7505         open_in (subtopology euclidean (s PCROSS t')) u
7506         ==> ?v. open_in (subtopology euclidean t') v /\
7507                 t SUBSET v /\
7508                 s PCROSS v SUBSET u`,
7509   REPEAT STRIP_TAC THEN
7510   SUBGOAL_THEN
7511    `!a. a IN t ==> ?v. open_in (subtopology euclidean t') v /\ a IN v /\
7512                        (s:real^M->bool) PCROSS (v:real^N->bool) SUBSET u`
7513   MP_TAC THENL
7514    [REPEAT STRIP_TAC THEN MATCH_MP_TAC TUBE_LEMMA THEN
7515     ASM_REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN REPEAT STRIP_TAC THEN
7516     REPEAT STRIP_TAC THEN
7517     FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[SUBSET]) THEN
7518     ASM_REWRITE_TAC[PASTECART_IN_PCROSS];
7519     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
7520     REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
7521     X_GEN_TAC `vv:real^N->real^N->bool` THEN DISCH_TAC THEN
7522     EXISTS_TAC `UNIONS (IMAGE (vv:real^N->real^N->bool) t)` THEN
7523     ASM_SIMP_TAC[OPEN_IN_UNIONS; FORALL_IN_IMAGE] THEN
7524     REWRITE_TAC[SUBSET; UNIONS_IMAGE; IN_ELIM_THM; FORALL_IN_PCROSS] THEN
7525     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7526     MAP_EVERY X_GEN_TAC [`a:real^M`; `b:real^N`] THEN
7527     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (X_CHOOSE_TAC `c:real^N`)) THEN
7528     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N`) THEN
7529     ASM_REWRITE_TAC[SUBSET; FORALL_IN_PCROSS] THEN ASM SET_TAC[]]);;
7530
7531 (* ------------------------------------------------------------------------- *)
7532 (* Pasting functions together on open sets.                                  *)
7533 (* ------------------------------------------------------------------------- *)
7534
7535 let PASTING_LEMMA = prove
7536  (`!f:A->real^M->real^N g t s k.
7537         (!i. i IN k
7538              ==> open_in (subtopology euclidean s) (t i) /\
7539                  (f i) continuous_on (t i)) /\
7540         (!i j x. i IN k /\ j IN k /\ x IN s INTER t i INTER t j
7541                  ==> f i x = f j x) /\
7542         (!x. x IN s ==> ?j. j IN k /\ x IN t j /\ g x = f j x)
7543         ==> g continuous_on s`,
7544   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_OPEN_IN_PREIMAGE_EQ] THEN
7545   STRIP_TAC THEN X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
7546   SUBGOAL_THEN
7547    `{x | x IN s /\ g x IN u} =
7548     UNIONS {{x | x IN (t i) /\ ((f:A->real^M->real^N) i x) IN u} |
7549             i IN k}`
7550   SUBST1_TAC THENL
7551    [SUBGOAL_THEN `!i. i IN k ==> ((t:A->real^M->bool) i) SUBSET s`
7552     ASSUME_TAC THENL
7553      [ASM_MESON_TAC[OPEN_IN_SUBSET; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY];
7554       REWRITE_TAC[UNIONS_GSPEC] THEN ASM SET_TAC[]];
7555     MATCH_MP_TAC OPEN_IN_UNIONS THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
7556     ASM_MESON_TAC[OPEN_IN_TRANS]]);;
7557
7558 let PASTING_LEMMA_EXISTS = prove
7559  (`!f:A->real^M->real^N t s k.
7560         s SUBSET UNIONS {t i | i IN k} /\
7561         (!i. i IN k
7562              ==> open_in (subtopology euclidean s) (t i) /\
7563                  (f i) continuous_on (t i)) /\
7564         (!i j x. i IN k /\ j IN k /\ x IN s INTER t i INTER t j
7565                  ==> f i x = f j x)
7566         ==> ?g. g continuous_on s /\
7567                 (!x i. i IN k /\ x IN s INTER t i ==> g x = f i x)`,
7568   REPEAT STRIP_TAC THEN
7569   EXISTS_TAC `\x. (f:A->real^M->real^N)(@i. i IN k /\ x IN t i) x` THEN
7570   CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN MATCH_MP_TAC PASTING_LEMMA THEN
7571   MAP_EVERY EXISTS_TAC
7572    [`f:A->real^M->real^N`; `t:A->real^M->bool`; `k:A->bool`] THEN
7573   ASM SET_TAC[]);;
7574
7575 let CONTINUOUS_ON_UNION_LOCAL_OPEN = prove
7576  (`!f:real^M->real^N s.
7577         open_in (subtopology euclidean (s UNION t)) s /\
7578         open_in (subtopology euclidean (s UNION t)) t /\
7579         f continuous_on s /\ f continuous_on t
7580         ==> f continuous_on (s UNION t)`,
7581   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
7582    [`\i:(real^M->bool). (f:real^M->real^N)`; `f:real^M->real^N`;
7583     `\i:(real^M->bool). i`; `s UNION t:real^M->bool`; `{s:real^M->bool,t}`]
7584    PASTING_LEMMA) THEN DISCH_THEN MATCH_MP_TAC THEN
7585   ASM_REWRITE_TAC[FORALL_IN_INSERT; EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN
7586   REWRITE_TAC[IN_UNION]);;
7587
7588 let CONTINUOUS_ON_UNION_OPEN = prove
7589  (`!f s t. open s /\ open t /\ f continuous_on s /\ f continuous_on t
7590            ==> f continuous_on (s UNION t)`,
7591   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_UNION_LOCAL_OPEN THEN
7592   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC OPEN_OPEN_IN_TRANS THEN
7593   ASM_SIMP_TAC[OPEN_UNION] THEN SET_TAC[]);;
7594
7595 let CONTINUOUS_ON_CASES_LOCAL_OPEN = prove
7596  (`!P f g:real^M->real^N s t.
7597         open_in (subtopology euclidean (s UNION t)) s /\
7598         open_in (subtopology euclidean (s UNION t)) t /\
7599         f continuous_on s /\ g continuous_on t /\
7600         (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x)
7601         ==> (\x. if P x then f x else g x) continuous_on (s UNION t)`,
7602   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_UNION_LOCAL_OPEN THEN
7603   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THENL
7604    [EXISTS_TAC `f:real^M->real^N`; EXISTS_TAC `g:real^M->real^N`] THEN
7605   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
7606
7607 let CONTINUOUS_ON_CASES_OPEN = prove
7608  (`!P f g s t.
7609            open s /\
7610            open t /\
7611            f continuous_on s /\
7612            g continuous_on t /\
7613            (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x)
7614            ==> (\x. if P x then f x else g x) continuous_on s UNION t`,
7615   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL_OPEN THEN
7616   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC OPEN_OPEN_IN_TRANS THEN
7617   ASM_SIMP_TAC[OPEN_UNION] THEN SET_TAC[]);;
7618
7619 (* ------------------------------------------------------------------------- *)
7620 (* Likewise on closed sets, with a finiteness assumption.                    *)
7621 (* ------------------------------------------------------------------------- *)
7622
7623 let PASTING_LEMMA_CLOSED = prove
7624  (`!f:A->real^M->real^N g t s k.
7625         FINITE k /\
7626         (!i. i IN k
7627              ==> closed_in (subtopology euclidean s) (t i) /\
7628                  (f i) continuous_on (t i)) /\
7629         (!i j x. i IN k /\ j IN k /\ x IN s INTER t i INTER t j
7630                  ==> f i x = f j x) /\
7631         (!x. x IN s ==> ?j. j IN k /\ x IN t j /\ g x = f j x)
7632         ==> g continuous_on s`,
7633   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE_EQ] THEN
7634   STRIP_TAC THEN X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
7635   SUBGOAL_THEN
7636    `{x | x IN s /\ g x IN u} =
7637     UNIONS {{x | x IN (t i) /\ ((f:A->real^M->real^N) i x) IN u} |
7638             i IN k}`
7639   SUBST1_TAC THENL
7640    [SUBGOAL_THEN `!i. i IN k ==> ((t:A->real^M->bool) i) SUBSET s`
7641     ASSUME_TAC THENL
7642      [ASM_MESON_TAC[CLOSED_IN_SUBSET; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY];
7643       REWRITE_TAC[UNIONS_GSPEC] THEN ASM SET_TAC[]];
7644     MATCH_MP_TAC CLOSED_IN_UNIONS THEN
7645     ASM_SIMP_TAC[SIMPLE_IMAGE; FINITE_IMAGE; FORALL_IN_IMAGE] THEN
7646     ASM_MESON_TAC[CLOSED_IN_TRANS]]);;
7647
7648 let PASTING_LEMMA_EXISTS_CLOSED = prove
7649  (`!f:A->real^M->real^N t s k.
7650         FINITE k /\
7651         s SUBSET UNIONS {t i | i IN k} /\
7652         (!i. i IN k
7653              ==> closed_in (subtopology euclidean s) (t i) /\
7654                  (f i) continuous_on (t i)) /\
7655         (!i j x. i IN k /\ j IN k /\ x IN s INTER t i INTER t j
7656                  ==> f i x = f j x)
7657         ==> ?g. g continuous_on s /\
7658                 (!x i. i IN k /\ x IN s INTER t i ==> g x = f i x)`,
7659   REPEAT STRIP_TAC THEN
7660   EXISTS_TAC `\x. (f:A->real^M->real^N)(@i. i IN k /\ x IN t i) x` THEN
7661   CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
7662   MATCH_MP_TAC PASTING_LEMMA_CLOSED THEN
7663   MAP_EVERY EXISTS_TAC
7664    [`f:A->real^M->real^N`; `t:A->real^M->bool`; `k:A->bool`] THEN
7665   ASM SET_TAC[]);;
7666
7667 (* ------------------------------------------------------------------------- *)
7668 (* Closure of halflines, halfspaces and hyperplanes.                         *)
7669 (* ------------------------------------------------------------------------- *)
7670
7671 let LIM_LIFT_DOT = prove
7672  (`!f:real^M->real^N a.
7673         (f --> l) net ==> ((lift o (\y. a dot f(y))) --> lift(a dot l)) net`,
7674   REPEAT GEN_TAC THEN ASM_CASES_TAC `a = vec 0:real^N` THENL
7675    [ASM_REWRITE_TAC[DOT_LZERO; LIFT_NUM; o_DEF; LIM_CONST]; ALL_TAC] THEN
7676   REWRITE_TAC[LIM] THEN MATCH_MP_TAC MONO_OR THEN REWRITE_TAC[] THEN
7677   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
7678   FIRST_X_ASSUM(MP_TAC o SPEC `e / norm(a:real^N)`) THEN
7679   ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; REAL_LT_RDIV_EQ] THEN
7680   REWRITE_TAC[dist; o_THM; GSYM LIFT_SUB; GSYM DOT_RSUB; NORM_LIFT] THEN
7681   ONCE_REWRITE_TAC[DOT_SYM] THEN
7682   MESON_TAC[NORM_CAUCHY_SCHWARZ_ABS; REAL_MUL_SYM; REAL_LET_TRANS]);;
7683
7684 let CONTINUOUS_AT_LIFT_DOT = prove
7685  (`!a:real^N x. (lift o (\y. a dot y)) continuous at x`,
7686   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_AT; o_THM] THEN
7687   MATCH_MP_TAC LIM_LIFT_DOT THEN REWRITE_TAC[LIM_AT] THEN MESON_TAC[]);;
7688
7689 let CONTINUOUS_ON_LIFT_DOT = prove
7690  (`!s. (lift o (\y. a dot y)) continuous_on s`,
7691   SIMP_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_LIFT_DOT]);;
7692
7693 let CLOSED_INTERVAL_LEFT = prove
7694  (`!b:real^N.
7695      closed {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> x$i <= b$i}`,
7696   REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE; IN_ELIM_THM] THEN
7697   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
7698   FIRST_X_ASSUM(MP_TAC o SPEC `(x:real^N)$i - (b:real^N)$i`) THEN
7699   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
7700   DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
7701   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
7702   REWRITE_TAC[dist; REAL_NOT_LT] THEN
7703   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs((z - x :real^N)$i)` THEN
7704   ASM_SIMP_TAC[COMPONENT_LE_NORM] THEN
7705   ASM_SIMP_TAC[VECTOR_SUB_COMPONENT] THEN
7706   ASM_SIMP_TAC[REAL_ARITH `z <= b /\ b < x ==> x - b <= abs(z - x)`]);;
7707
7708 let CLOSED_INTERVAL_RIGHT = prove
7709  (`!a:real^N.
7710      closed {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= x$i}`,
7711   REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE; IN_ELIM_THM] THEN
7712   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
7713   FIRST_X_ASSUM(MP_TAC o SPEC `(a:real^N)$i - (x:real^N)$i`) THEN
7714   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
7715   DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
7716   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
7717   REWRITE_TAC[dist; REAL_NOT_LT] THEN
7718   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs((z - x :real^N)$i)` THEN
7719   ASM_SIMP_TAC[COMPONENT_LE_NORM] THEN
7720   ASM_SIMP_TAC[VECTOR_SUB_COMPONENT] THEN
7721   ASM_SIMP_TAC[REAL_ARITH `x < a /\ a <= z ==> a - x <= abs(z - x)`]);;
7722
7723 let CLOSED_HALFSPACE_LE = prove
7724  (`!a:real^N b. closed {x | a dot x <= b}`,
7725   REPEAT GEN_TAC THEN
7726   MP_TAC(ISPEC `(:real^N)` CONTINUOUS_ON_LIFT_DOT) THEN
7727   REWRITE_TAC[CONTINUOUS_ON_CLOSED; GSYM CLOSED_IN; SUBTOPOLOGY_UNIV] THEN
7728   DISCH_THEN(MP_TAC o SPEC
7729    `IMAGE lift {r | ?x:real^N. (a dot x = r) /\ r <= b}`) THEN
7730   ANTS_TAC THENL
7731    [ALL_TAC;
7732     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
7733     REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; IN_UNIV] THEN
7734     REWRITE_TAC[o_DEF] THEN MESON_TAC[LIFT_DROP]] THEN
7735   REWRITE_TAC[CLOSED_IN_CLOSED] THEN
7736   EXISTS_TAC `{x | !i. 1 <= i /\ i <= dimindex(:1)
7737                        ==> (x:real^1)$i <= (lift b)$i}` THEN
7738   REWRITE_TAC[CLOSED_INTERVAL_LEFT] THEN
7739   SIMP_TAC[EXTENSION; IN_IMAGE; IN_UNIV; IN_ELIM_THM; IN_INTER;
7740     VEC_COMPONENT; DIMINDEX_1; LAMBDA_BETA; o_THM] THEN
7741   SIMP_TAC[ARITH_RULE `1 <= i /\ i <= 1 <=> (i = 1)`] THEN
7742   REWRITE_TAC[GSYM drop; LEFT_FORALL_IMP_THM; EXISTS_REFL] THEN
7743   MESON_TAC[LIFT_DROP]);;
7744
7745 let CLOSED_HALFSPACE_GE = prove
7746  (`!a:real^N b. closed {x | a dot x >= b}`,
7747   REWRITE_TAC[REAL_ARITH `a >= b <=> --a <= --b`] THEN
7748   REWRITE_TAC[GSYM DOT_LNEG; CLOSED_HALFSPACE_LE]);;
7749
7750 let CLOSED_HYPERPLANE = prove
7751  (`!a b. closed {x | a dot x = b}`,
7752   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
7753   REWRITE_TAC[REAL_ARITH `b <= a dot x <=> a dot x >= b`] THEN
7754   REWRITE_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
7755   SIMP_TAC[CLOSED_INTER; CLOSED_HALFSPACE_LE; CLOSED_HALFSPACE_GE]);;
7756
7757 let CLOSED_STANDARD_HYPERPLANE = prove
7758  (`!k a. closed {x:real^N | x$k = a}`,
7759   REPEAT GEN_TAC THEN
7760   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7761   CHOOSE_TAC THENL
7762    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7763   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSED_HYPERPLANE) THEN
7764   ASM_SIMP_TAC[DOT_BASIS]);;
7765
7766 let CLOSED_HALFSPACE_COMPONENT_LE = prove
7767  (`!a k. closed {x:real^N | x$k <= a}`,
7768   REPEAT GEN_TAC THEN
7769   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7770   CHOOSE_TAC THENL
7771    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7772   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSED_HALFSPACE_LE) THEN
7773   ASM_SIMP_TAC[DOT_BASIS]);;
7774
7775 let CLOSED_HALFSPACE_COMPONENT_GE = prove
7776  (`!a k. closed {x:real^N | x$k >= a}`,
7777   REPEAT GEN_TAC THEN
7778   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7779   CHOOSE_TAC THENL
7780    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7781   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSED_HALFSPACE_GE) THEN
7782   ASM_SIMP_TAC[DOT_BASIS]);;
7783
7784 (* ------------------------------------------------------------------------- *)
7785 (* Openness of halfspaces.                                                   *)
7786 (* ------------------------------------------------------------------------- *)
7787
7788 let OPEN_HALFSPACE_LT = prove
7789  (`!a b. open {x | a dot x < b}`,
7790   REWRITE_TAC[GSYM REAL_NOT_LE] THEN
7791   REWRITE_TAC[SET_RULE `{x | ~p x} = UNIV DIFF {x | p x}`] THEN
7792   REWRITE_TAC[GSYM closed; GSYM real_ge; CLOSED_HALFSPACE_GE]);;
7793
7794 let OPEN_HALFSPACE_COMPONENT_LT = prove
7795  (`!a k. open {x:real^N | x$k < a}`,
7796   REPEAT GEN_TAC THEN
7797   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7798   CHOOSE_TAC THENL
7799    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7800   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] OPEN_HALFSPACE_LT) THEN
7801   ASM_SIMP_TAC[DOT_BASIS]);;
7802
7803 let OPEN_HALFSPACE_GT = prove
7804  (`!a b. open {x | a dot x > b}`,
7805   REWRITE_TAC[REAL_ARITH `x > y <=> ~(x <= y)`] THEN
7806   REWRITE_TAC[SET_RULE `{x | ~p x} = UNIV DIFF {x | p x}`] THEN
7807   REWRITE_TAC[GSYM closed; CLOSED_HALFSPACE_LE]);;
7808
7809 let OPEN_HALFSPACE_COMPONENT_GT = prove
7810  (`!a k. open {x:real^N | x$k > a}`,
7811   REPEAT GEN_TAC THEN
7812   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7813   CHOOSE_TAC THENL
7814    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7815   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] OPEN_HALFSPACE_GT) THEN
7816   ASM_SIMP_TAC[DOT_BASIS]);;
7817
7818 let OPEN_POSITIVE_MULTIPLES = prove
7819  (`!s:real^N->bool. open s ==> open {c % x | &0 < c /\ x IN s}`,
7820   REWRITE_TAC[open_def; FORALL_IN_GSPEC] THEN GEN_TAC THEN DISCH_TAC THEN
7821   MAP_EVERY X_GEN_TAC [`c:real`; `x:real^N`] THEN STRIP_TAC THEN
7822   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
7823   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
7824   EXISTS_TAC `c * e:real` THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
7825   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
7826   FIRST_X_ASSUM(MP_TAC o SPEC `inv(c) % y:real^N`) THEN ANTS_TAC THENL
7827    [SUBGOAL_THEN `x:real^N = inv c % c % x` SUBST1_TAC THENL
7828      [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID;
7829                    REAL_LT_IMP_NZ];
7830       ASM_SIMP_TAC[DIST_MUL; real_abs; REAL_LT_INV_EQ; REAL_LT_IMP_LE] THEN
7831       ONCE_REWRITE_TAC[REAL_ARITH `inv c * x:real = x / c`] THEN
7832       ASM_MESON_TAC[REAL_LT_LDIV_EQ; REAL_MUL_SYM]];
7833     DISCH_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN
7834     EXISTS_TAC `c:real` THEN EXISTS_TAC `inv(c) % y:real^N` THEN
7835     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; REAL_LT_IMP_NZ] THEN
7836     VECTOR_ARITH_TAC]);;
7837
7838 let OPEN_INTERVAL_LEFT = prove
7839  (`!b:real^N. open {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> x$i < b$i}`,
7840   GEN_TAC THEN
7841   SUBGOAL_THEN
7842    `{x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> x$i < b$i} =
7843     INTERS{{x | x$i < (b:real^N)$i} | i IN 1..dimindex(:N)}`
7844   SUBST1_TAC THENL
7845    [REWRITE_TAC[INTERS_GSPEC; IN_NUMSEG] THEN SET_TAC[];
7846     MATCH_MP_TAC OPEN_INTERS THEN
7847     SIMP_TAC[SIMPLE_IMAGE; FINITE_IMAGE; FINITE_NUMSEG] THEN
7848     REWRITE_TAC[FORALL_IN_IMAGE; OPEN_HALFSPACE_COMPONENT_LT]]);;
7849
7850 let OPEN_INTERVAL_RIGHT = prove
7851  (`!a:real^N. open {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> a$i < x$i}`,
7852   GEN_TAC THEN
7853   SUBGOAL_THEN
7854    `{x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> a$i < x$i} =
7855     INTERS{{x | (a:real^N)$i < x$i} | i IN 1..dimindex(:N)}`
7856   SUBST1_TAC THENL
7857    [REWRITE_TAC[INTERS_GSPEC; IN_NUMSEG] THEN SET_TAC[];
7858     MATCH_MP_TAC OPEN_INTERS THEN
7859     SIMP_TAC[SIMPLE_IMAGE; FINITE_IMAGE; FINITE_NUMSEG] THEN
7860     REWRITE_TAC[FORALL_IN_IMAGE; GSYM real_gt; OPEN_HALFSPACE_COMPONENT_GT]]);;
7861
7862 let OPEN_POSITIVE_ORTHANT = prove
7863  (`open {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> &0 < x$i}`,
7864   MP_TAC(ISPEC `vec 0:real^N` OPEN_INTERVAL_RIGHT) THEN
7865   REWRITE_TAC[VEC_COMPONENT]);;
7866
7867 (* ------------------------------------------------------------------------- *)
7868 (* Closures and interiors of halfspaces.                                     *)
7869 (* ------------------------------------------------------------------------- *)
7870
7871 let INTERIOR_HALFSPACE_LE = prove
7872  (`!a:real^N b.
7873         ~(a = vec 0) ==> interior {x | a dot x <= b} = {x | a dot x < b}`,
7874   REPEAT STRIP_TAC THEN MATCH_MP_TAC INTERIOR_UNIQUE THEN
7875   SIMP_TAC[OPEN_HALFSPACE_LT; SUBSET; IN_ELIM_THM; REAL_LT_IMP_LE] THEN
7876   X_GEN_TAC `s:real^N->bool` THEN STRIP_TAC THEN
7877   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN ASM_SIMP_TAC[REAL_LT_LE] THEN
7878   DISCH_TAC THEN
7879   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
7880   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
7881   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
7882   REWRITE_TAC[SUBSET; IN_CBALL] THEN
7883   DISCH_THEN(MP_TAC o SPEC `x + e / norm(a) % a:real^N`) THEN
7884   REWRITE_TAC[NORM_ARITH `dist(x:real^N,x + y) = norm y`] THEN
7885   ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL;
7886                NORM_EQ_0; REAL_ARITH `&0 < x ==> abs x <= x`] THEN
7887   DISCH_TAC THEN
7888   FIRST_X_ASSUM(MP_TAC o SPEC  `x + e / norm(a) % a:real^N`) THEN
7889   ASM_REWRITE_TAC[DOT_RADD; DOT_RMUL] THEN
7890   MATCH_MP_TAC(REAL_ARITH `&0 < e ==> ~(b + e <= b)`) THEN
7891   ASM_SIMP_TAC[REAL_LT_MUL; REAL_LT_DIV; NORM_POS_LT; DOT_POS_LT]);;
7892
7893 let INTERIOR_HALFSPACE_GE = prove
7894  (`!a:real^N b.
7895         ~(a = vec 0) ==> interior {x | a dot x >= b} = {x | a dot x > b}`,
7896   REPEAT STRIP_TAC THEN
7897   ONCE_REWRITE_TAC[REAL_ARITH `a >= b <=> --a <= --b`;
7898                    REAL_ARITH `a > b <=> --a < --b`] THEN
7899   ASM_SIMP_TAC[GSYM DOT_LNEG; INTERIOR_HALFSPACE_LE; VECTOR_NEG_EQ_0]);;
7900
7901 let INTERIOR_HALFSPACE_COMPONENT_LE = prove
7902  (`!a k. interior {x:real^N | x$k <= a} = {x | x$k < a}`,
7903   REPEAT GEN_TAC THEN
7904   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7905   CHOOSE_TAC THENL
7906    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7907   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] INTERIOR_HALFSPACE_LE) THEN
7908   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
7909
7910 let INTERIOR_HALFSPACE_COMPONENT_GE = prove
7911  (`!a k. interior {x:real^N | x$k >= a} = {x | x$k > a}`,
7912   REPEAT GEN_TAC THEN
7913   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7914   CHOOSE_TAC THENL
7915    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7916   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] INTERIOR_HALFSPACE_GE) THEN
7917   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
7918
7919 let CLOSURE_HALFSPACE_LT = prove
7920  (`!a:real^N b.
7921         ~(a = vec 0) ==> closure {x | a dot x < b} = {x | a dot x <= b}`,
7922   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSURE_INTERIOR] THEN
7923   REWRITE_TAC[SET_RULE `UNIV DIFF {x | P x} = {x | ~P x}`] THEN
7924   ASM_SIMP_TAC[REAL_ARITH `~(x < b) <=> x >= b`; INTERIOR_HALFSPACE_GE] THEN
7925   REWRITE_TAC[EXTENSION; IN_DIFF; IN_UNIV; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
7926
7927 let CLOSURE_HALFSPACE_GT = prove
7928  (`!a:real^N b.
7929         ~(a = vec 0) ==> closure {x | a dot x > b} = {x | a dot x >= b}`,
7930   REPEAT STRIP_TAC THEN
7931   ONCE_REWRITE_TAC[REAL_ARITH `a >= b <=> --a <= --b`;
7932                    REAL_ARITH `a > b <=> --a < --b`] THEN
7933   ASM_SIMP_TAC[GSYM DOT_LNEG; CLOSURE_HALFSPACE_LT; VECTOR_NEG_EQ_0]);;
7934
7935 let CLOSURE_HALFSPACE_COMPONENT_LT = prove
7936  (`!a k. closure {x:real^N | x$k < a} = {x | x$k <= a}`,
7937   REPEAT GEN_TAC THEN
7938   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7939   CHOOSE_TAC THENL
7940    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7941   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSURE_HALFSPACE_LT) THEN
7942   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
7943
7944 let CLOSURE_HALFSPACE_COMPONENT_GT = prove
7945  (`!a k. closure {x:real^N | x$k > a} = {x | x$k >= a}`,
7946   REPEAT GEN_TAC THEN
7947   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
7948   CHOOSE_TAC THENL
7949    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
7950   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSURE_HALFSPACE_GT) THEN
7951   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
7952
7953 let INTERIOR_HYPERPLANE = prove
7954  (`!a b. ~(a = vec 0) ==> interior {x | a dot x = b} = {}`,
7955   REWRITE_TAC[REAL_ARITH `x = y <=> x <= y /\ x >= y`] THEN
7956   REWRITE_TAC[SET_RULE `{x | p x /\ q x} = {x | p x} INTER {x | q x}`] THEN
7957   REWRITE_TAC[INTERIOR_INTER] THEN
7958   ASM_SIMP_TAC[INTERIOR_HALFSPACE_LE; INTERIOR_HALFSPACE_GE] THEN
7959   REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM; NOT_IN_EMPTY] THEN
7960   REAL_ARITH_TAC);;
7961
7962 let FRONTIER_HALFSPACE_LE = prove
7963  (`!a:real^N b. ~(a = vec 0 /\ b = &0)
7964                 ==> frontier {x | a dot x <= b} = {x | a dot x = b}`,
7965   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
7966   ASM_SIMP_TAC[DOT_LZERO] THENL
7967    [ASM_CASES_TAC `&0 <= b` THEN
7968     ASM_REWRITE_TAC[UNIV_GSPEC; FRONTIER_UNIV; EMPTY_GSPEC; FRONTIER_EMPTY];
7969     ASM_SIMP_TAC[frontier; INTERIOR_HALFSPACE_LE; CLOSURE_CLOSED;
7970                  CLOSED_HALFSPACE_LE] THEN
7971     REWRITE_TAC[EXTENSION; IN_DIFF; IN_ELIM_THM] THEN REAL_ARITH_TAC]);;
7972
7973 let FRONTIER_HALFSPACE_GE = prove
7974  (`!a:real^N b. ~(a = vec 0 /\ b = &0)
7975                 ==> frontier {x | a dot x >= b} = {x | a dot x = b}`,
7976   REPEAT STRIP_TAC THEN
7977   MP_TAC(ISPECL [`--a:real^N`; `--b:real`] FRONTIER_HALFSPACE_LE) THEN
7978   ASM_REWRITE_TAC[VECTOR_NEG_EQ_0; REAL_NEG_EQ_0; DOT_LNEG] THEN
7979   REWRITE_TAC[REAL_LE_NEG2; REAL_EQ_NEG2; real_ge]);;
7980
7981 let FRONTIER_HALFSPACE_LT = prove
7982  (`!a:real^N b. ~(a = vec 0 /\ b = &0)
7983                 ==> frontier {x | a dot x < b} = {x | a dot x = b}`,
7984   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
7985   ASM_SIMP_TAC[DOT_LZERO] THENL
7986    [ASM_CASES_TAC `&0 < b` THEN
7987     ASM_REWRITE_TAC[UNIV_GSPEC; FRONTIER_UNIV; EMPTY_GSPEC; FRONTIER_EMPTY];
7988     ASM_SIMP_TAC[frontier; CLOSURE_HALFSPACE_LT; INTERIOR_OPEN;
7989                  OPEN_HALFSPACE_LT] THEN
7990     REWRITE_TAC[EXTENSION; IN_DIFF; IN_ELIM_THM] THEN REAL_ARITH_TAC]);;
7991
7992 let FRONTIER_HALFSPACE_GT = prove
7993  (`!a:real^N b. ~(a = vec 0 /\ b = &0)
7994                 ==> frontier {x | a dot x > b} = {x | a dot x = b}`,
7995   REPEAT STRIP_TAC THEN
7996   MP_TAC(ISPECL [`--a:real^N`; `--b:real`] FRONTIER_HALFSPACE_LT) THEN
7997   ASM_REWRITE_TAC[VECTOR_NEG_EQ_0; REAL_NEG_EQ_0; DOT_LNEG] THEN
7998   REWRITE_TAC[REAL_LT_NEG2; REAL_EQ_NEG2; real_gt]);;
7999
8000 let INTERIOR_STANDARD_HYPERPLANE = prove
8001  (`!k a. interior {x:real^N | x$k = a} = {}`,
8002   REPEAT GEN_TAC THEN
8003   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
8004   CHOOSE_TAC THENL
8005    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
8006   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] INTERIOR_HYPERPLANE) THEN
8007   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
8008
8009 let EMPTY_INTERIOR_LOWDIM = prove
8010  (`!s:real^N->bool. dim(s) < dimindex(:N) ==> interior s = {}`,
8011   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP LOWDIM_SUBSET_HYPERPLANE) THEN
8012   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
8013   MATCH_MP_TAC(SET_RULE
8014    `!t u. s SUBSET t /\ t SUBSET u /\ u = {} ==> s = {}`) THEN
8015   MAP_EVERY EXISTS_TAC
8016    [`interior(span(s):real^N->bool)`;
8017     `interior({x:real^N | a dot x = &0})`] THEN
8018   ASM_SIMP_TAC[SUBSET_INTERIOR; SPAN_INC; INTERIOR_HYPERPLANE]);;
8019
8020 (* ------------------------------------------------------------------------- *)
8021 (* Unboundedness of halfspaces.                                              *)
8022 (* ------------------------------------------------------------------------- *)
8023
8024 let UNBOUNDED_HALFSPACE_COMPONENT_LE = prove
8025  (`!a k. ~bounded {x:real^N | x$k <= a}`,
8026   REPEAT GEN_TAC THEN
8027   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !z:real^N. z$k = z$i`
8028   CHOOSE_TAC THENL [REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
8029   ASM_REWRITE_TAC[bounded; FORALL_IN_GSPEC] THEN
8030   DISCH_THEN(X_CHOOSE_THEN `B:real` MP_TAC) THEN
8031   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP] THEN
8032   EXISTS_TAC `--(&1 + max (abs B) (abs a)) % basis i:real^N` THEN
8033   ASM_SIMP_TAC[NORM_MUL; NORM_BASIS; BASIS_COMPONENT;
8034                VECTOR_MUL_COMPONENT] THEN
8035   REAL_ARITH_TAC);;
8036
8037 let UNBOUNDED_HALFSPACE_COMPONENT_GE = prove
8038  (`!a k. ~bounded {x:real^N | x$k >= a}`,
8039   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP BOUNDED_NEGATIONS) THEN
8040   MP_TAC(SPECL [`--a:real`; `k:num`] UNBOUNDED_HALFSPACE_COMPONENT_LE) THEN
8041   REWRITE_TAC[CONTRAPOS_THM] THEN MATCH_MP_TAC EQ_IMP THEN
8042   AP_TERM_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN CONJ_TAC THENL
8043    [MESON_TAC[VECTOR_NEG_NEG];
8044     REWRITE_TAC[IN_ELIM_THM; VECTOR_NEG_COMPONENT] THEN REAL_ARITH_TAC]);;
8045
8046 let UNBOUNDED_HALFSPACE_COMPONENT_LT = prove
8047  (`!a k. ~bounded {x:real^N | x$k < a}`,
8048   ONCE_REWRITE_TAC[GSYM BOUNDED_CLOSURE_EQ] THEN
8049   REWRITE_TAC[CLOSURE_HALFSPACE_COMPONENT_LT;
8050               UNBOUNDED_HALFSPACE_COMPONENT_LE]);;
8051
8052 let UNBOUNDED_HALFSPACE_COMPONENT_GT = prove
8053  (`!a k. ~bounded {x:real^N | x$k > a}`,
8054   ONCE_REWRITE_TAC[GSYM BOUNDED_CLOSURE_EQ] THEN
8055   REWRITE_TAC[CLOSURE_HALFSPACE_COMPONENT_GT;
8056               UNBOUNDED_HALFSPACE_COMPONENT_GE]);;
8057
8058 let BOUNDED_HALFSPACE_LE = prove
8059  (`!a:real^N b. bounded {x | a dot x <= b} <=> a = vec 0 /\ b < &0`,
8060   GEOM_BASIS_MULTIPLE_TAC 1 `a:real^N` THEN
8061   SIMP_TAC[DOT_LMUL; DOT_BASIS; VECTOR_MUL_EQ_0; DIMINDEX_GE_1; LE_REFL;
8062            BASIS_NONZERO] THEN
8063   X_GEN_TAC `a:real` THEN ASM_CASES_TAC `a = &0` THEN ASM_REWRITE_TAC[] THEN
8064   DISCH_TAC THEN X_GEN_TAC `b:real` THENL
8065    [REWRITE_TAC[REAL_MUL_LZERO; DOT_LZERO; GSYM REAL_NOT_LE] THEN
8066     ASM_CASES_TAC `&0 <= b` THEN
8067     ASM_REWRITE_TAC[BOUNDED_EMPTY; NOT_BOUNDED_UNIV;
8068                     SET_RULE `{x | T} = UNIV`; EMPTY_GSPEC];
8069     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8070     ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; REAL_LT_LE;
8071                  UNBOUNDED_HALFSPACE_COMPONENT_LE]]);;
8072
8073 let BOUNDED_HALFSPACE_GE = prove
8074  (`!a:real^N b. bounded {x | a dot x >= b} <=> a = vec 0 /\ &0 < b`,
8075   REWRITE_TAC[REAL_ARITH `a >= b <=> --a <= --b`] THEN
8076   REWRITE_TAC[GSYM DOT_LNEG; BOUNDED_HALFSPACE_LE] THEN
8077   REWRITE_TAC[VECTOR_NEG_EQ_0; REAL_ARITH `--b < &0 <=> &0 < b`]);;
8078
8079 let BOUNDED_HALFSPACE_LT = prove
8080  (`!a:real^N b. bounded {x | a dot x < b} <=> a = vec 0 /\ b <= &0`,
8081   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
8082   ASM_REWRITE_TAC[] THENL
8083    [REWRITE_TAC[DOT_LZERO; GSYM REAL_NOT_LE] THEN ASM_CASES_TAC `b <= &0` THEN
8084     ASM_REWRITE_TAC[BOUNDED_EMPTY; NOT_BOUNDED_UNIV;
8085                     SET_RULE `{x | T} = UNIV`; EMPTY_GSPEC];
8086     ONCE_REWRITE_TAC[GSYM BOUNDED_CLOSURE_EQ] THEN
8087     ASM_SIMP_TAC[CLOSURE_HALFSPACE_LT; BOUNDED_HALFSPACE_LE]]);;
8088
8089 let BOUNDED_HALFSPACE_GT = prove
8090  (`!a:real^N b. bounded {x | a dot x > b} <=> a = vec 0 /\ &0 <= b`,
8091   REWRITE_TAC[REAL_ARITH `a > b <=> --a < --b`] THEN
8092   REWRITE_TAC[GSYM DOT_LNEG; BOUNDED_HALFSPACE_LT] THEN
8093   REWRITE_TAC[VECTOR_NEG_EQ_0; REAL_ARITH `--b <= &0 <=> &0 <= b`]);;
8094
8095 (* ------------------------------------------------------------------------- *)
8096 (* Equality of continuous functions on closure and related results.          *)
8097 (* ------------------------------------------------------------------------- *)
8098
8099 let FORALL_IN_CLOSURE = prove
8100  (`!f:real^M->real^N s t.
8101         closed t /\ f continuous_on (closure s) /\
8102         (!x. x IN s ==> f x IN t)
8103         ==> (!x. x IN closure s ==> f x IN t)`,
8104   REWRITE_TAC[SET_RULE `(!x. x IN s ==> f x IN t) <=>
8105                         s SUBSET {x | x IN s /\ f x IN t}`] THEN
8106   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_MINIMAL THEN
8107   ASM_REWRITE_TAC[CLOSED_CLOSURE] THEN CONJ_TAC THENL
8108    [MP_TAC(ISPEC `s:real^M->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
8109     MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE THEN
8110     ASM_REWRITE_TAC[CLOSED_CLOSURE]]);;
8111
8112 let FORALL_IN_CLOSURE_EQ = prove
8113  (`!f s t.
8114          closed t /\ f continuous_on closure s
8115          ==> ((!x. x IN closure s ==> f x IN t) <=>
8116               (!x. x IN s ==> f x IN t))`,
8117   MESON_TAC[FORALL_IN_CLOSURE; CLOSURE_SUBSET; SUBSET]);;
8118
8119 let SUP_CLOSURE = prove
8120  (`!s. sup(IMAGE drop (closure s)) = sup(IMAGE drop s)`,
8121   GEN_TAC THEN MATCH_MP_TAC SUP_EQ THEN
8122   REWRITE_TAC[FORALL_IN_IMAGE] THEN GEN_TAC THEN
8123   ONCE_REWRITE_TAC[SET_RULE `drop x <= b <=> x IN {x | drop x <= b}`] THEN
8124   MATCH_MP_TAC FORALL_IN_CLOSURE_EQ THEN
8125   REWRITE_TAC[CONTINUOUS_ON_ID; drop; CLOSED_HALFSPACE_COMPONENT_LE]);;
8126
8127 let INF_CLOSURE = prove
8128  (`!s. inf(IMAGE drop (closure s)) = inf(IMAGE drop s)`,
8129   GEN_TAC THEN MATCH_MP_TAC INF_EQ THEN
8130   REWRITE_TAC[FORALL_IN_IMAGE] THEN GEN_TAC THEN
8131   ONCE_REWRITE_TAC[SET_RULE `b <= drop x <=> x IN {x | b <= drop x}`] THEN
8132   MATCH_MP_TAC FORALL_IN_CLOSURE_EQ THEN
8133   REWRITE_TAC[CONTINUOUS_ON_ID; drop; CLOSED_HALFSPACE_COMPONENT_GE;
8134               GSYM real_ge]);;
8135
8136 let CONTINUOUS_LE_ON_CLOSURE = prove
8137  (`!f:real^M->real s a.
8138         (lift o f) continuous_on closure(s) /\ (!x. x IN s ==> f(x) <= a)
8139         ==> !x. x IN closure(s) ==> f(x) <= a`,
8140   let lemma = prove
8141    (`x IN s ==> f x <= a <=> x IN s ==> (lift o f) x IN {y | y$1 <= a}`,
8142     REWRITE_TAC[IN_ELIM_THM; o_THM; GSYM drop; LIFT_DROP]) in
8143   REWRITE_TAC[lemma] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
8144   MATCH_MP_TAC FORALL_IN_CLOSURE THEN
8145   ASM_REWRITE_TAC[ETA_AX; CLOSED_HALFSPACE_COMPONENT_LE]);;
8146
8147 let CONTINUOUS_GE_ON_CLOSURE = prove
8148  (`!f:real^M->real s a.
8149         (lift o f) continuous_on closure(s) /\ (!x. x IN s ==> a <= f(x))
8150         ==> !x. x IN closure(s) ==> a <= f(x)`,
8151   let lemma = prove
8152    (`x IN s ==> a <= f x <=> x IN s ==> (lift o f) x IN {y | y$1 >= a}`,
8153     REWRITE_TAC[IN_ELIM_THM; o_THM; GSYM drop; real_ge; LIFT_DROP]) in
8154   REWRITE_TAC[lemma] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
8155   MATCH_MP_TAC FORALL_IN_CLOSURE THEN
8156   ASM_REWRITE_TAC[ETA_AX; CLOSED_HALFSPACE_COMPONENT_GE]);;
8157
8158 let CONTINUOUS_CONSTANT_ON_CLOSURE = prove
8159  (`!f:real^M->real^N s a.
8160         f continuous_on closure(s) /\ (!x. x IN s ==> f(x) = a)
8161         ==> !x. x IN closure(s) ==> f(x) = a`,
8162   REWRITE_TAC[SET_RULE
8163    `x IN s ==> f x = a <=> x IN s ==> f x IN {a}`] THEN
8164   REPEAT GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC FORALL_IN_CLOSURE THEN
8165   ASM_REWRITE_TAC[CLOSED_SING]);;
8166
8167 let CONTINUOUS_AGREE_ON_CLOSURE = prove
8168  (`!g h:real^M->real^N.
8169         g continuous_on closure s /\ h continuous_on closure s /\
8170         (!x. x IN s ==> g x = h x)
8171         ==> !x. x IN closure s ==> g x = h x`,
8172   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN STRIP_TAC THEN
8173   MATCH_MP_TAC CONTINUOUS_CONSTANT_ON_CLOSURE THEN
8174   ASM_SIMP_TAC[CONTINUOUS_ON_SUB]);;
8175
8176 let CONTINUOUS_CLOSED_IN_PREIMAGE_CONSTANT = prove
8177  (`!f:real^M->real^N s a.
8178         f continuous_on s
8179         ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x = a}`,
8180   REPEAT STRIP_TAC THEN
8181   ONCE_REWRITE_TAC[SET_RULE
8182    `{x | x IN s /\ f(x) = a} = {x | x IN s /\ f(x) IN {a}}`] THEN
8183   MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
8184   ASM_REWRITE_TAC[CLOSED_SING]);;
8185
8186 let CONTINUOUS_CLOSED_PREIMAGE_CONSTANT = prove
8187  (`!f:real^M->real^N s.
8188       f continuous_on s /\ closed s ==> closed {x | x IN s /\ f(x) = a}`,
8189   REPEAT STRIP_TAC THEN
8190   ASM_CASES_TAC `{x | x IN s /\ (f:real^M->real^N)(x) = a} = {}` THEN
8191   ASM_REWRITE_TAC[CLOSED_EMPTY] THEN ONCE_REWRITE_TAC[SET_RULE
8192    `{x | x IN s /\ f(x) = a} = {x | x IN s /\ f(x) IN {a}}`] THEN
8193   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE THEN
8194   ASM_REWRITE_TAC[CLOSED_SING] THEN ASM SET_TAC[]);;
8195
8196 (* ------------------------------------------------------------------------- *)
8197 (* Theorems relating continuity and uniform continuity to closures.          *)
8198 (* ------------------------------------------------------------------------- *)
8199
8200 let CONTINUOUS_ON_CLOSURE = prove
8201  (`!f:real^M->real^N s.
8202         f continuous_on closure s <=>
8203         !x e. x IN closure s /\ &0 < e
8204               ==> ?d. &0 < d /\
8205                       !y. y IN s /\ dist(y,x) < d ==> dist(f y,f x) < e`,
8206   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_on] THEN
8207   EQ_TAC THENL [MESON_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET]; ALL_TAC] THEN
8208   DISCH_TAC THEN X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
8209   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8210   FIRST_ASSUM(MP_TAC o SPECL [`x:real^M`; `e / &2`]) THEN
8211   ANTS_TAC THENL [ASM_REWRITE_TAC[REAL_HALF]; ALL_TAC] THEN
8212   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
8213   EXISTS_TAC `d / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
8214   X_GEN_TAC `y:real^M` THEN STRIP_TAC THEN
8215   FIRST_X_ASSUM(MP_TAC o SPECL [`y:real^M`; `e / &2`]) THEN
8216   ASM_REWRITE_TAC[REAL_HALF] THEN
8217   DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
8218   MP_TAC(ISPECL [`y:real^M`; `s:real^M->bool`] CLOSURE_APPROACHABLE) THEN
8219   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `min k (d / &2)`) THEN
8220   ASM_REWRITE_TAC[REAL_HALF; REAL_LT_MIN] THEN
8221   ASM_MESON_TAC[DIST_SYM; NORM_ARITH
8222     `dist(a,b) < e / &2 /\ dist(b,c) < e / &2 ==> dist(a,c) < e`]);;
8223
8224 let CONTINUOUS_ON_CLOSURE_SEQUENTIALLY = prove
8225  (`!f:real^M->real^N s.
8226         f continuous_on closure s <=>
8227         !x a. a IN closure s /\ (!n. x n IN s) /\ (x --> a) sequentially
8228               ==> ((f o x) --> f a) sequentially`,
8229   REWRITE_TAC[CONTINUOUS_ON_CLOSURE] THEN
8230   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
8231   REWRITE_TAC[IMP_IMP; GSYM continuous_within] THEN
8232   REWRITE_TAC[CONTINUOUS_WITHIN_SEQUENTIALLY] THEN MESON_TAC[]);;
8233
8234 let UNIFORMLY_CONTINUOUS_ON_CLOSURE = prove
8235  (`!f:real^M->real^N s.
8236         f uniformly_continuous_on s /\ f continuous_on closure s
8237         ==> f uniformly_continuous_on closure s`,
8238   REPEAT GEN_TAC THEN
8239   REWRITE_TAC[uniformly_continuous_on] THEN STRIP_TAC THEN
8240   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8241   FIRST_X_ASSUM(MP_TAC o SPEC `e / &3`) THEN
8242   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
8243   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
8244   EXISTS_TAC `d / &3` THEN CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
8245   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^M`] THEN STRIP_TAC THEN
8246   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [continuous_on]) THEN
8247   DISCH_THEN(fun th ->
8248     MP_TAC(SPEC `y:real^M` th) THEN MP_TAC(SPEC `x:real^M` th)) THEN
8249   ASM_REWRITE_TAC[] THEN
8250   DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
8251   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
8252   DISCH_THEN(X_CHOOSE_THEN `d1:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
8253   MP_TAC(ISPECL [`x:real^M`; `s:real^M->bool`] CLOSURE_APPROACHABLE) THEN
8254   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `min d1 (d / &3)`) THEN
8255   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[REAL_LT_MIN]] THEN
8256   DISCH_THEN(X_CHOOSE_THEN `x':real^M` STRIP_ASSUME_TAC) THEN
8257   DISCH_THEN(MP_TAC o SPEC `x':real^M`) THEN
8258   ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN DISCH_TAC THEN
8259   DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
8260   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
8261   DISCH_THEN(X_CHOOSE_THEN `d2:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
8262   MP_TAC(ISPECL [`y:real^M`; `s:real^M->bool`] CLOSURE_APPROACHABLE) THEN
8263   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `min d2 (d / &3)`) THEN
8264   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[REAL_LT_MIN]] THEN
8265   DISCH_THEN(X_CHOOSE_THEN `y':real^M` STRIP_ASSUME_TAC) THEN
8266   DISCH_THEN(MP_TAC o SPEC `y':real^M`) THEN
8267   ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN DISCH_TAC THEN
8268   FIRST_X_ASSUM(MP_TAC o SPECL [`x':real^M`; `y':real^M`]) THEN
8269   ASM_MESON_TAC[DIST_SYM; NORM_ARITH
8270    `dist(y,x) < d / &3 /\ dist(x',x) < d / &3 /\ dist(y',y) < d / &3
8271     ==> dist(y',x') < d`]);;
8272
8273 (* ------------------------------------------------------------------------- *)
8274 (* Continuity properties for square roots. We get other forms of this        *)
8275 (* later (transcendentals.ml and realanalysis.ml) but it's nice to have      *)
8276 (* them around earlier.                                                      *)
8277 (* ------------------------------------------------------------------------- *)
8278
8279 let CONTINUOUS_AT_SQRT = prove
8280  (`!a s. &0 < drop a ==>  (lift o sqrt o drop) continuous (at a)`,
8281   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_at; o_THM; DIST_LIFT] THEN
8282   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8283   EXISTS_TAC `min (drop a) (e * sqrt(drop a))` THEN
8284   ASM_SIMP_TAC[REAL_LT_MIN; SQRT_POS_LT; REAL_LT_MUL; DIST_REAL] THEN
8285   X_GEN_TAC `b:real^1` THEN REWRITE_TAC[GSYM drop] THEN STRIP_TAC THEN
8286   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REAL_ARITH
8287    `abs(b - a) < a ==> &0 < b`)) THEN
8288   SUBGOAL_THEN
8289    `sqrt(drop b) - sqrt(drop a) =
8290     (drop b - drop a) / (sqrt(drop a) + sqrt(drop b))`
8291   SUBST1_TAC THENL
8292    [MATCH_MP_TAC(REAL_FIELD
8293      `sa pow 2 = a /\ sb pow 2 = b /\ &0 < sa /\ &0 < sb
8294       ==> sb - sa = (b - a) / (sa + sb)`) THEN
8295     ASM_SIMP_TAC[SQRT_POS_LT; SQRT_POW_2; REAL_LT_IMP_LE];
8296     ASM_SIMP_TAC[REAL_ABS_DIV; SQRT_POS_LT; REAL_LT_ADD; REAL_LT_LDIV_EQ;
8297                  REAL_ARITH `&0 < x ==> abs x = x`] THEN
8298     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
8299         REAL_LTE_TRANS)) THEN
8300     ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_LE_ADDR; SQRT_POS_LE;
8301                  REAL_LT_IMP_LE]]);;
8302
8303 let CONTINUOUS_WITHIN_LIFT_SQRT = prove
8304  (`!a s. (!x. x IN s ==> &0 <= drop x)
8305          ==> (lift o sqrt o drop) continuous (at a within s)`,
8306   REPEAT STRIP_TAC THEN
8307   REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC
8308    (REAL_ARITH `drop a < &0 \/ drop a = &0 \/ &0 < drop a`)
8309   THENL
8310    [MATCH_MP_TAC CONTINUOUS_WITHIN_SUBSET THEN
8311     EXISTS_TAC `{x | &0 <= drop x}` THEN
8312     ASM_SIMP_TAC[SUBSET; IN_ELIM_THM] THEN
8313     MATCH_MP_TAC CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL THEN
8314     ASM_REWRITE_TAC[IN_ELIM_THM; REAL_NOT_LE] THEN
8315     REWRITE_TAC[drop; REWRITE_RULE[real_ge] CLOSED_HALFSPACE_COMPONENT_GE];
8316     RULE_ASSUM_TAC(REWRITE_RULE[GSYM LIFT_EQ; LIFT_DROP; LIFT_NUM]) THEN
8317     ASM_REWRITE_TAC[continuous_within; o_THM; DROP_VEC; SQRT_0; LIFT_NUM] THEN
8318     REWRITE_TAC[DIST_0; NORM_LIFT; NORM_REAL; GSYM drop] THEN
8319     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8320     EXISTS_TAC `(e:real) pow 2` THEN ASM_SIMP_TAC[REAL_POW_LT] THEN
8321     X_GEN_TAC `x:real^1` THEN STRIP_TAC THEN
8322     ASM_SIMP_TAC[real_abs; SQRT_POS_LE] THEN
8323     SUBGOAL_THEN `e = sqrt(e pow 2)` SUBST1_TAC THENL
8324      [ASM_SIMP_TAC[POW_2_SQRT; REAL_LT_IMP_LE];
8325       MATCH_MP_TAC SQRT_MONO_LT THEN ASM_SIMP_TAC[] THEN ASM_REAL_ARITH_TAC];
8326     MATCH_MP_TAC CONTINUOUS_AT_WITHIN THEN
8327     MATCH_MP_TAC CONTINUOUS_AT_SQRT THEN ASM_REWRITE_TAC[]]);;
8328
8329 let CONTINUOUS_WITHIN_SQRT_COMPOSE = prove
8330  (`!f s a:real^N.
8331         (\x. lift(f x)) continuous (at a within s) /\
8332         (&0 < f a \/ !x. x IN s ==> &0 <= f x)
8333         ==> (\x. lift(sqrt(f x))) continuous (at a within s)`,
8334   REPEAT GEN_TAC THEN
8335   SUBGOAL_THEN
8336    `(\x:real^N. lift(sqrt(f x))) = (lift o sqrt o drop) o (lift o f)`
8337   SUBST1_TAC THENL [REWRITE_TAC[o_DEF; LIFT_DROP]; ALL_TAC] THEN
8338   REPEAT STRIP_TAC THEN
8339   (MATCH_MP_TAC CONTINUOUS_WITHIN_COMPOSE THEN
8340    CONJ_TAC THENL [ASM_REWRITE_TAC[o_DEF]; ALL_TAC])
8341   THENL
8342    [MATCH_MP_TAC CONTINUOUS_AT_WITHIN THEN
8343     MATCH_MP_TAC CONTINUOUS_AT_SQRT THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP];
8344     MATCH_MP_TAC CONTINUOUS_WITHIN_LIFT_SQRT THEN
8345     ASM_REWRITE_TAC[FORALL_IN_IMAGE; o_DEF; LIFT_DROP]]);;
8346
8347 let CONTINUOUS_AT_SQRT_COMPOSE = prove
8348  (`!f a:real^N.
8349         (\x. lift(f x)) continuous (at a) /\ (&0 < f a \/ !x. &0 <= f x)
8350         ==> (\x. lift(sqrt(f x))) continuous (at a)`,
8351   REPEAT GEN_TAC THEN
8352   MP_TAC(ISPECL [`f:real^N->real`; `(:real^N)`; `a:real^N`]
8353         CONTINUOUS_WITHIN_SQRT_COMPOSE) THEN
8354   REWRITE_TAC[WITHIN_UNIV; IN_UNIV]);;
8355
8356 let CONTINUOUS_ON_LIFT_SQRT = prove
8357  (`!s. (!x. x IN s ==> &0 <= drop x)
8358        ==> (lift o sqrt o drop) continuous_on s`,
8359   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_WITHIN_LIFT_SQRT]);;
8360
8361 let CONTINUOUS_ON_LIFT_SQRT_COMPOSE = prove
8362  (`!f:real^N->real s.
8363         (lift o f) continuous_on s /\ (!x. x IN s ==> &0 <= f x)
8364         ==> (\x. lift(sqrt(f x))) continuous_on s`,
8365   REPEAT STRIP_TAC THEN
8366   SUBGOAL_THEN
8367    `(\x:real^N. lift(sqrt(f x))) = (lift o sqrt o drop) o (lift o f)`
8368   SUBST1_TAC THENL
8369    [REWRITE_TAC[o_DEF; LIFT_DROP];
8370     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN
8371     MATCH_MP_TAC CONTINUOUS_ON_LIFT_SQRT THEN
8372     ASM_REWRITE_TAC[FORALL_IN_IMAGE; o_THM; LIFT_DROP]]);;
8373
8374 (* ------------------------------------------------------------------------- *)
8375 (* Cauchy continuity, and the extension of functions to closures.            *)
8376 (* ------------------------------------------------------------------------- *)
8377
8378 let UNIFORMLY_CONTINUOUS_IMP_CAUCHY_CONTINUOUS = prove
8379  (`!f:real^M->real^N s.
8380         f uniformly_continuous_on s
8381         ==> (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))`,
8382   REPEAT GEN_TAC THEN REWRITE_TAC[uniformly_continuous_on; cauchy; o_DEF] THEN
8383   MESON_TAC[]);;
8384
8385 let CONTINUOUS_CLOSED_IMP_CAUCHY_CONTINUOUS = prove
8386  (`!f:real^M->real^N s.
8387         f continuous_on s /\ closed s
8388         ==> (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))`,
8389   REWRITE_TAC[GSYM COMPLETE_EQ_CLOSED; CONTINUOUS_ON_SEQUENTIALLY] THEN
8390   REWRITE_TAC[complete] THEN MESON_TAC[CONVERGENT_IMP_CAUCHY]);;
8391
8392 let CAUCHY_CONTINUOUS_UNIQUENESS_LEMMA = prove
8393  (`!f:real^M->real^N s.
8394         (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))
8395         ==> !a x. (!n. (x n) IN s) /\ (x --> a) sequentially
8396                   ==> ?l. ((f o x) --> l) sequentially /\
8397                           !y. (!n. (y n) IN s) /\ (y --> a) sequentially
8398                               ==> ((f o y) --> l) sequentially`,
8399   REPEAT STRIP_TAC THEN
8400   FIRST_ASSUM(MP_TAC o SPEC `x:num->real^M`) THEN
8401   ANTS_TAC THENL [ASM_MESON_TAC[CONVERGENT_IMP_CAUCHY]; ALL_TAC] THEN
8402   REWRITE_TAC[GSYM CONVERGENT_EQ_CAUCHY] THEN MATCH_MP_TAC MONO_EXISTS THEN
8403   X_GEN_TAC `l:real^N` THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
8404   X_GEN_TAC `y:num->real^M` THEN STRIP_TAC THEN
8405   FIRST_ASSUM(MP_TAC o SPEC `y:num->real^M`) THEN
8406   ANTS_TAC THENL [ASM_MESON_TAC[CONVERGENT_IMP_CAUCHY]; ALL_TAC] THEN
8407   REWRITE_TAC[GSYM CONVERGENT_EQ_CAUCHY] THEN
8408   DISCH_THEN(X_CHOOSE_THEN `m:real^N` STRIP_ASSUME_TAC) THEN
8409   SUBGOAL_THEN `l:real^N = m` (fun th -> ASM_REWRITE_TAC[th]) THEN
8410   ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
8411   MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
8412   EXISTS_TAC `\n:num. (f:real^M->real^N)(x n) - f(y n)` THEN
8413   RULE_ASSUM_TAC(REWRITE_RULE[o_DEF]) THEN
8414   ASM_SIMP_TAC[LIM_SUB; TRIVIAL_LIMIT_SEQUENTIALLY] THEN
8415   FIRST_X_ASSUM(MP_TAC o SPEC
8416    `\n. if EVEN n then x(n DIV 2):real^M else y(n DIV 2)`) THEN
8417   REWRITE_TAC[cauchy; o_THM; LIM_SEQUENTIALLY] THEN ANTS_TAC THENL
8418    [CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
8419     X_GEN_TAC `e:real` THEN DISCH_TAC THEN MAP_EVERY UNDISCH_TAC
8420      [`((y:num->real^M) --> a) sequentially`;
8421       `((x:num->real^M) --> a) sequentially`] THEN
8422     REPEAT(FIRST_X_ASSUM(K ALL_TAC o check (is_forall o concl))) THEN
8423     REWRITE_TAC[LIM_SEQUENTIALLY] THEN
8424     DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
8425     DISCH_THEN(X_CHOOSE_TAC `N1:num`) THEN
8426     DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
8427     DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN
8428     EXISTS_TAC `2 * (N1 + N2)` THEN
8429     MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
8430     REPEAT(FIRST_X_ASSUM(fun th ->
8431       MP_TAC(SPEC `m DIV 2` th) THEN MP_TAC(SPEC `n DIV 2` th))) THEN
8432     REPEAT(ANTS_TAC THENL [ASM_ARITH_TAC; DISCH_TAC]) THEN
8433     REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
8434     REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_NOT_LE])) THEN
8435     CONV_TAC NORM_ARITH;
8436     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
8437     ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
8438     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN DISCH_TAC THEN
8439     X_GEN_TAC `n:num` THEN DISCH_TAC THEN
8440     FIRST_X_ASSUM(MP_TAC o SPECL [`2 * n`; `2 * n + 1`]) THEN
8441     ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
8442     REWRITE_TAC[EVEN_ADD; EVEN_MULT; ARITH_EVEN] THEN
8443     REWRITE_TAC[ARITH_RULE `(2 * n) DIV 2 = n /\ (2 * n + 1) DIV 2 = n`] THEN
8444     REWRITE_TAC[dist; VECTOR_SUB_RZERO]]);;
8445
8446 let CAUCHY_CONTINUOUS_EXTENDS_TO_CLOSURE = prove
8447  (`!f:real^M->real^N s.
8448         (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))
8449         ==> ?g. g continuous_on closure s /\ (!x. x IN s ==> g x = f x)`,
8450   REPEAT STRIP_TAC THEN
8451   SUBGOAL_THEN
8452    `!a:real^M. ?x.
8453        a IN closure s ==> (!n. x n IN s) /\ (x --> a) sequentially`
8454   MP_TAC THENL [MESON_TAC[CLOSURE_SEQUENTIAL]; ALL_TAC] THEN
8455   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
8456   X_GEN_TAC `X:real^M->num->real^M` THEN DISCH_TAC THEN
8457   FIRST_ASSUM(MP_TAC o MATCH_MP CAUCHY_CONTINUOUS_UNIQUENESS_LEMMA) THEN
8458   DISCH_THEN(MP_TAC o GEN `a:real^M` o
8459    SPECL [`a:real^M`; `(X:real^M->num->real^M) a`]) THEN
8460   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
8461    `(!a. P a ==> Q a) ==> ((!a. P a ==> R a) ==> p)
8462     ==> ((!a. Q a ==> R a) ==> p)`)) THEN
8463   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
8464   REWRITE_TAC[SKOLEM_THM] THEN
8465   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^M->real^N` THEN
8466   STRIP_TAC THEN
8467   MATCH_MP_TAC(TAUT `b /\ (b ==> a) ==> a /\ b`) THEN CONJ_TAC THENL
8468    [X_GEN_TAC `a:real^M` THEN DISCH_TAC THEN
8469     FIRST_X_ASSUM(MP_TAC o SPEC `a:real^M`) THEN
8470     ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN
8471     DISCH_THEN(MP_TAC o SPEC `(\n. a):num->real^M` o CONJUNCT2) THEN
8472     ASM_SIMP_TAC[LIM_CONST_EQ; o_DEF; TRIVIAL_LIMIT_SEQUENTIALLY];
8473     STRIP_TAC] THEN
8474   ASM_SIMP_TAC[CONTINUOUS_ON_CLOSURE_SEQUENTIALLY] THEN
8475   MAP_EVERY X_GEN_TAC [`x:num->real^M`; `a:real^M`] THEN STRIP_TAC THEN
8476   MATCH_MP_TAC LIM_TRANSFORM_EVENTUALLY THEN
8477   EXISTS_TAC `(f:real^M->real^N) o (x:num->real^M)` THEN ASM_SIMP_TAC[] THEN
8478   MATCH_MP_TAC ALWAYS_EVENTUALLY THEN ASM_SIMP_TAC[o_THM]);;
8479
8480 let UNIFORMLY_CONTINUOUS_EXTENDS_TO_CLOSURE = prove
8481  (`!f:real^M->real^N s.
8482    f uniformly_continuous_on s
8483    ==> ?g. g uniformly_continuous_on closure s /\ (!x. x IN s ==> g x = f x) /\
8484            !h. h continuous_on closure s /\ (!x. x IN s ==> h x = f x)
8485                ==> !x. x IN closure s ==> h x = g x`,
8486   REPEAT STRIP_TAC THEN
8487   FIRST_ASSUM(MP_TAC o MATCH_MP CAUCHY_CONTINUOUS_EXTENDS_TO_CLOSURE o
8488    MATCH_MP UNIFORMLY_CONTINUOUS_IMP_CAUCHY_CONTINUOUS) THEN
8489   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^M->real^N` THEN
8490   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
8491    [ASM_MESON_TAC[UNIFORMLY_CONTINUOUS_ON_CLOSURE; UNIFORMLY_CONTINUOUS_ON_EQ];
8492     ASM_MESON_TAC[CONTINUOUS_AGREE_ON_CLOSURE]]);;
8493
8494 let CAUCHY_CONTINUOUS_IMP_CONTINUOUS = prove
8495  (`!f:real^M->real^N s.
8496         (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))
8497         ==> f continuous_on s`,
8498   REPEAT STRIP_TAC THEN
8499   FIRST_ASSUM(CHOOSE_TAC o MATCH_MP CAUCHY_CONTINUOUS_EXTENDS_TO_CLOSURE) THEN
8500   ASM_MESON_TAC[CONTINUOUS_ON_SUBSET; CLOSURE_SUBSET; CONTINUOUS_ON_EQ]);;
8501
8502 let BOUNDED_UNIFORMLY_CONTINUOUS_IMAGE = prove
8503  (`!f:real^M->real^N s.
8504         f uniformly_continuous_on s /\ bounded s ==> bounded(IMAGE f s)`,
8505   REPEAT STRIP_TAC THEN FIRST_ASSUM
8506    (MP_TAC o MATCH_MP UNIFORMLY_CONTINUOUS_EXTENDS_TO_CLOSURE) THEN
8507   DISCH_THEN(X_CHOOSE_THEN `g:real^M->real^N` STRIP_ASSUME_TAC) THEN
8508   MATCH_MP_TAC BOUNDED_SUBSET THEN
8509   EXISTS_TAC `IMAGE (g:real^M->real^N) (closure s)` THEN CONJ_TAC THENL
8510    [ASM_MESON_TAC[COMPACT_CLOSURE; UNIFORMLY_CONTINUOUS_IMP_CONTINUOUS;
8511                   COMPACT_IMP_BOUNDED; COMPACT_CONTINUOUS_IMAGE];
8512     MP_TAC(ISPEC `s:real^M->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[]]);;
8513
8514 (* ------------------------------------------------------------------------- *)
8515 (* Occasionally useful invariance properties.                                *)
8516 (* ------------------------------------------------------------------------- *)
8517
8518 let CONTINUOUS_AT_COMPOSE_EQ = prove
8519  (`!f:real^M->real^N g:real^M->real^M h:real^M->real^M.
8520         g continuous at x /\ h continuous at (g x) /\
8521         (!y. g(h y) = y) /\ h(g x) = x
8522         ==> (f continuous at (g x) <=> (\x. f(g x)) continuous at x)`,
8523   REPEAT STRIP_TAC THEN EQ_TAC THEN
8524   ASM_SIMP_TAC[REWRITE_RULE[o_DEF] CONTINUOUS_AT_COMPOSE] THEN
8525   DISCH_TAC THEN
8526   SUBGOAL_THEN
8527    `((f:real^M->real^N) o (g:real^M->real^M) o (h:real^M->real^M))
8528      continuous at (g(x:real^M))`
8529   MP_TAC THENL
8530    [REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
8531     ASM_REWRITE_TAC[o_DEF];
8532
8533     ASM_REWRITE_TAC[o_DEF; ETA_AX]]);;
8534
8535 let CONTINUOUS_AT_TRANSLATION = prove
8536  (`!a z f:real^M->real^N.
8537       f continuous at (a + z) <=> (\x. f(a + x)) continuous at z`,
8538   REPEAT GEN_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE_EQ THEN
8539   EXISTS_TAC `\x:real^M. x - a` THEN
8540   SIMP_TAC[CONTINUOUS_ADD; CONTINUOUS_SUB;
8541            CONTINUOUS_AT_ID; CONTINUOUS_CONST] THEN
8542   VECTOR_ARITH_TAC);;
8543
8544 add_translation_invariants [CONTINUOUS_AT_TRANSLATION];;
8545
8546 let CONTINUOUS_AT_LINEAR_IMAGE = prove
8547  (`!h:real^M->real^M z f:real^M->real^N.
8548         linear h /\ (!x. norm(h x) = norm x)
8549         ==> (f continuous at (h z) <=> (\x. f(h x)) continuous at z)`,
8550   REPEAT GEN_TAC THEN DISCH_TAC THEN
8551   FIRST_ASSUM(ASSUME_TAC o GEN_REWRITE_RULE I
8552    [GSYM ORTHOGONAL_TRANSFORMATION]) THEN
8553   FIRST_ASSUM(X_CHOOSE_TAC `g:real^M->real^M` o MATCH_MP
8554     ORTHOGONAL_TRANSFORMATION_INVERSE) THEN
8555   MATCH_MP_TAC CONTINUOUS_AT_COMPOSE_EQ THEN
8556   EXISTS_TAC `g:real^M->real^M` THEN
8557   RULE_ASSUM_TAC(REWRITE_RULE[ORTHOGONAL_TRANSFORMATION]) THEN
8558   ASM_SIMP_TAC[LINEAR_CONTINUOUS_AT]);;
8559
8560 add_linear_invariants [CONTINUOUS_AT_LINEAR_IMAGE];;
8561
8562 (* ------------------------------------------------------------------------- *)
8563 (* Interior of an injective image.                                           *)
8564 (* ------------------------------------------------------------------------- *)
8565
8566 let INTERIOR_IMAGE_SUBSET = prove
8567  (`!f:real^M->real^N s.
8568        (!x. f continuous at x) /\ (!x y. f x = f y ==> x = y)
8569        ==> interior(IMAGE f s) SUBSET IMAGE f (interior s)`,
8570   REPEAT STRIP_TAC THEN REWRITE_TAC[SUBSET] THEN
8571   REWRITE_TAC[interior; IN_ELIM_THM] THEN
8572   X_GEN_TAC `y:real^N` THEN
8573   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
8574   REWRITE_TAC[IN_IMAGE; IN_ELIM_THM] THEN
8575   SUBGOAL_THEN `y IN IMAGE (f:real^M->real^N) s` MP_TAC THENL
8576    [ASM SET_TAC[]; ALL_TAC] THEN
8577   REWRITE_TAC[IN_IMAGE] THEN
8578   MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN
8579   ASM_REWRITE_TAC[IN_ELIM_THM] THEN FIRST_X_ASSUM SUBST_ALL_TAC THEN
8580   EXISTS_TAC `{x | (f:real^M->real^N)(x) IN t}` THEN
8581   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN CONJ_TAC THENL
8582    [MATCH_MP_TAC CONTINUOUS_OPEN_PREIMAGE_UNIV THEN ASM_MESON_TAC[];
8583     ASM SET_TAC[]]);;
8584
8585 (* ------------------------------------------------------------------------- *)
8586 (* Making a continuous function avoid some value in a neighbourhood.         *)
8587 (* ------------------------------------------------------------------------- *)
8588
8589 let CONTINUOUS_WITHIN_AVOID = prove
8590  (`!f:real^M->real^N x s a.
8591         f continuous (at x within s) /\ x IN s /\  ~(f x = a)
8592         ==> ?e. &0 < e /\ !y. y IN s /\ dist(x,y) < e ==> ~(f y = a)`,
8593   REPEAT STRIP_TAC THEN
8594   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [continuous_within]) THEN
8595   DISCH_THEN(MP_TAC o SPEC `norm((f:real^M->real^N) x - a)`) THEN
8596   ASM_REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
8597   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_AND THEN
8598   REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN
8599   GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN SIMP_TAC[] THEN NORM_ARITH_TAC);;
8600
8601 let CONTINUOUS_AT_AVOID = prove
8602  (`!f:real^M->real^N x a.
8603         f continuous (at x) /\ ~(f x = a)
8604         ==> ?e. &0 < e /\ !y. dist(x,y) < e ==> ~(f y = a)`,
8605   MP_TAC CONTINUOUS_WITHIN_AVOID THEN
8606   REPLICATE_TAC 2 (MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
8607   DISCH_THEN(MP_TAC o SPEC `(:real^M)`) THEN
8608   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
8609   REWRITE_TAC[WITHIN_UNIV; IN_UNIV]);;
8610
8611 let CONTINUOUS_ON_AVOID = prove
8612  (`!f:real^M->real^N x s a.
8613         f continuous_on s /\ x IN s /\ ~(f x = a)
8614         ==> ?e. &0 < e /\ !y. y IN s /\ dist(x,y) < e ==> ~(f y = a)`,
8615   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
8616   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_WITHIN_AVOID THEN
8617   ASM_SIMP_TAC[]);;
8618
8619 let CONTINUOUS_ON_OPEN_AVOID = prove
8620  (`!f:real^M->real^N x s a.
8621         f continuous_on s /\ open s /\ x IN s /\ ~(f x = a)
8622         ==> ?e. &0 < e /\ !y. dist(x,y) < e ==> ~(f y = a)`,
8623   REPEAT GEN_TAC THEN ASM_CASES_TAC `open(s:real^M->bool)` THEN
8624   ASM_SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT] THEN
8625   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_AVOID THEN
8626   ASM_SIMP_TAC[]);;
8627
8628 (* ------------------------------------------------------------------------- *)
8629 (* Proving a function is constant by proving open-ness of level set.         *)
8630 (* ------------------------------------------------------------------------- *)
8631
8632 let CONTINUOUS_LEVELSET_OPEN_IN_CASES = prove
8633  (`!f:real^M->real^N s a.
8634         connected s /\
8635         f continuous_on s /\
8636         open_in (subtopology euclidean s) {x | x IN s /\ f x = a}
8637         ==> (!x. x IN s ==> ~(f x = a)) \/ (!x. x IN s ==> f x = a)`,
8638   REWRITE_TAC[SET_RULE `(!x. x IN s ==> ~(f x = a)) <=>
8639                         {x | x IN s /\ f x = a} = {}`;
8640               SET_RULE `(!x. x IN s ==> f x = a) <=>
8641                         {x | x IN s /\ f x = a} = s`] THEN
8642   REWRITE_TAC[CONNECTED_CLOPEN] THEN REPEAT STRIP_TAC THEN
8643   FIRST_X_ASSUM MATCH_MP_TAC THEN
8644   ASM_SIMP_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE_CONSTANT]);;
8645
8646 let CONTINUOUS_LEVELSET_OPEN_IN = prove
8647  (`!f:real^M->real^N s a.
8648         connected s /\
8649         f continuous_on s /\
8650         open_in (subtopology euclidean s) {x | x IN s /\ f x = a} /\
8651         (?x. x IN s /\ f x = a)
8652         ==> (!x. x IN s ==> f x = a)`,
8653   MESON_TAC[CONTINUOUS_LEVELSET_OPEN_IN_CASES]);;
8654
8655 let CONTINUOUS_LEVELSET_OPEN = prove
8656  (`!f:real^M->real^N s a.
8657         connected s /\
8658         f continuous_on s /\
8659         open {x | x IN s /\ f x = a} /\
8660         (?x. x IN s /\ f x = a)
8661         ==> (!x. x IN s ==> f x = a)`,
8662   REPEAT GEN_TAC THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
8663   MATCH_MP_TAC CONTINUOUS_LEVELSET_OPEN_IN THEN
8664   ASM_REWRITE_TAC[OPEN_IN_OPEN] THEN
8665   EXISTS_TAC `{x | x IN s /\ (f:real^M->real^N) x = a}` THEN
8666   ASM_REWRITE_TAC[] THEN SET_TAC[]);;
8667
8668 (* ------------------------------------------------------------------------- *)
8669 (* Some arithmetical combinations (more to prove).                           *)
8670 (* ------------------------------------------------------------------------- *)
8671
8672 let OPEN_SCALING = prove
8673  (`!s:real^N->bool c. ~(c = &0) /\ open s ==> open(IMAGE (\x. c % x) s)`,
8674   REPEAT GEN_TAC THEN REWRITE_TAC[open_def; FORALL_IN_IMAGE] THEN
8675   STRIP_TAC THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
8676   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
8677   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
8678   EXISTS_TAC `e * abs(c)` THEN ASM_SIMP_TAC[REAL_LT_MUL; GSYM REAL_ABS_NZ] THEN
8679   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_IMAGE] THEN
8680   EXISTS_TAC `inv(c) % y:real^N` THEN
8681   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; VECTOR_MUL_LID] THEN
8682   FIRST_X_ASSUM MATCH_MP_TAC THEN
8683   SUBGOAL_THEN `x = inv(c) % c % x:real^N` SUBST1_TAC THENL
8684    [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID];
8685     REWRITE_TAC[dist; GSYM VECTOR_SUB_LDISTRIB; NORM_MUL] THEN
8686     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REAL_ABS_INV] THEN
8687     ASM_SIMP_TAC[GSYM real_div; REAL_LT_LDIV_EQ; GSYM REAL_ABS_NZ] THEN
8688     ASM_REWRITE_TAC[GSYM dist]]);;
8689
8690 let OPEN_NEGATIONS = prove
8691  (`!s:real^N->bool. open s ==> open (IMAGE (--) s)`,
8692   SUBGOAL_THEN `(--) = \x:real^N. --(&1) % x`
8693    (fun th -> SIMP_TAC[th; OPEN_SCALING; REAL_ARITH `~(--(&1) = &0)`]) THEN
8694   REWRITE_TAC[FUN_EQ_THM] THEN VECTOR_ARITH_TAC);;
8695
8696 let OPEN_TRANSLATION = prove
8697  (`!s a:real^N. open s ==> open(IMAGE (\x. a + x) s)`,
8698   REPEAT STRIP_TAC THEN
8699   MP_TAC(ISPECL [`\x:real^N. x - a`; `s:real^N->bool`]
8700          CONTINUOUS_OPEN_PREIMAGE_UNIV) THEN
8701   ASM_SIMP_TAC[CONTINUOUS_SUB; CONTINUOUS_AT_ID; CONTINUOUS_CONST] THEN
8702   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
8703   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; IN_UNIV] THEN
8704   ASM_MESON_TAC[VECTOR_ARITH `(a + x) - a = x:real^N`;
8705                 VECTOR_ARITH `a + (x - a) = x:real^N`]);;
8706
8707 let OPEN_TRANSLATION_EQ = prove
8708  (`!a s. open (IMAGE (\x:real^N. a + x) s) <=> open s`,
8709   REWRITE_TAC[open_def] THEN GEOM_TRANSLATE_TAC[]);;
8710
8711 add_translation_invariants [OPEN_TRANSLATION_EQ];;
8712
8713 let OPEN_AFFINITY = prove
8714  (`!s a:real^N c.
8715         open s /\ ~(c = &0) ==> open (IMAGE (\x. a + c % x) s)`,
8716   REPEAT STRIP_TAC THEN
8717   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
8718   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
8719   ASM_SIMP_TAC[IMAGE_o; OPEN_TRANSLATION; OPEN_SCALING]);;
8720
8721 let INTERIOR_TRANSLATION = prove
8722  (`!a:real^N s.
8723     interior (IMAGE (\x. a + x) s) = IMAGE (\x. a + x) (interior s)`,
8724   REWRITE_TAC[interior] THEN GEOM_TRANSLATE_TAC[]);;
8725
8726 add_translation_invariants [INTERIOR_TRANSLATION];;
8727
8728 let OPEN_SUMS = prove
8729  (`!s t:real^N->bool.
8730         open s \/ open t ==> open {x + y | x IN s /\ y IN t}`,
8731   REPEAT GEN_TAC THEN REWRITE_TAC[open_def] THEN STRIP_TAC THEN
8732   REWRITE_TAC[FORALL_IN_GSPEC] THEN
8733   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THENL
8734    [FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`);
8735     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`)] THEN
8736   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN
8737   X_GEN_TAC `e:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
8738   X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN
8739   ASM_MESON_TAC[VECTOR_ADD_SYM; VECTOR_ARITH `(z - y) + y:real^N = z`;
8740                 NORM_ARITH `dist(z:real^N,x + y) < e ==> dist(z - y,x) < e`]);;
8741
8742 (* ------------------------------------------------------------------------- *)
8743 (* Upper and lower hemicontinuous functions, relation in the case of         *)
8744 (* preimage map to open and closed maps, and fact that upper and lower       *)
8745 (* hemicontinuity together imply continuity in the sense of the Hausdorff    *)
8746 (* metric (at points where the function gives a bounded and nonempty set).   *)
8747 (* ------------------------------------------------------------------------- *)
8748
8749 let UPPER_HEMICONTINUOUS = prove
8750  (`!f:real^M->real^N->bool t s.
8751         (!x. x IN s ==> f(x) SUBSET t)
8752         ==> ((!u. open_in (subtopology euclidean t) u
8753                   ==> open_in (subtopology euclidean s)
8754                               {x | x IN s /\ f(x) SUBSET u}) <=>
8755              (!u. closed_in (subtopology euclidean t) u
8756                   ==> closed_in (subtopology euclidean s)
8757                                 {x | x IN s /\ ~(f(x) INTER u = {})}))`,
8758   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN GEN_TAC THEN
8759   FIRST_X_ASSUM(MP_TAC o SPEC `t DIFF u:real^N->bool`) THEN
8760   MATCH_MP_TAC MONO_IMP THEN
8761   SIMP_TAC[OPEN_IN_DIFF; CLOSED_IN_DIFF; OPEN_IN_REFL; CLOSED_IN_REFL] THENL
8762    [REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ]; REWRITE_TAC[closed_in]] THEN
8763   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY; SUBSET_RESTRICT] THEN
8764   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
8765
8766 let LOWER_HEMICONTINUOUS = prove
8767  (`!f:real^M->real^N->bool t s.
8768         (!x. x IN s ==> f(x) SUBSET t)
8769         ==> ((!u. closed_in (subtopology euclidean t) u
8770                   ==> closed_in (subtopology euclidean s)
8771                                 {x | x IN s /\ f(x) SUBSET u}) <=>
8772              (!u. open_in (subtopology euclidean t) u
8773                   ==> open_in (subtopology euclidean s)
8774                               {x | x IN s /\ ~(f(x) INTER u = {})}))`,
8775   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN GEN_TAC THEN
8776   FIRST_X_ASSUM(MP_TAC o SPEC `t DIFF u:real^N->bool`) THEN
8777   MATCH_MP_TAC MONO_IMP THEN
8778   SIMP_TAC[OPEN_IN_DIFF; CLOSED_IN_DIFF; OPEN_IN_REFL; CLOSED_IN_REFL] THENL
8779    [REWRITE_TAC[closed_in]; REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ]] THEN
8780   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY; SUBSET_RESTRICT] THEN
8781   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
8782
8783 let OPEN_MAP_IFF_LOWER_HEMICONTINUOUS_PREIMAGE = prove
8784  (`!f:real^M->real^N s t.
8785         IMAGE f s SUBSET t
8786         ==> ((!u. open_in (subtopology euclidean s) u
8787                   ==> open_in (subtopology euclidean t) (IMAGE f u)) <=>
8788              (!u. closed_in (subtopology euclidean s) u
8789                       ==> closed_in (subtopology euclidean t)
8790                                     {y | y IN t /\
8791                                          {x | x IN s /\ f x = y} SUBSET u}))`,
8792   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
8793    [X_GEN_TAC `v:real^M->bool` THEN DISCH_TAC THEN
8794     FIRST_X_ASSUM(MP_TAC o SPEC `s DIFF v:real^M->bool`) THEN
8795     ASM_SIMP_TAC[OPEN_IN_DIFF; OPEN_IN_REFL] THEN
8796     REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
8797     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
8798     FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
8799     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[];
8800     X_GEN_TAC `v:real^M->bool` THEN DISCH_TAC THEN
8801     FIRST_X_ASSUM(MP_TAC o SPEC `s DIFF v:real^M->bool`) THEN
8802     ASM_SIMP_TAC[CLOSED_IN_DIFF; CLOSED_IN_REFL] THEN
8803     FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
8804     REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
8805     DISCH_THEN(fun th -> CONJ_TAC THENL [ASM SET_TAC[]; MP_TAC th]) THEN
8806     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]]);;
8807
8808 let CLOSED_MAP_IFF_UPPER_HEMICONTINUOUS_PREIMAGE = prove
8809  (`!f:real^M->real^N s t.
8810         IMAGE f s SUBSET t
8811         ==> ((!u. closed_in (subtopology euclidean s) u
8812                   ==> closed_in (subtopology euclidean t) (IMAGE f u)) <=>
8813              (!u. open_in (subtopology euclidean s) u
8814                   ==> open_in (subtopology euclidean t)
8815                               {y | y IN t /\
8816                                    {x | x IN s /\ f x = y} SUBSET u}))`,
8817   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
8818    [X_GEN_TAC `v:real^M->bool` THEN DISCH_TAC THEN
8819     FIRST_X_ASSUM(MP_TAC o SPEC `s DIFF v:real^M->bool`) THEN
8820     ASM_SIMP_TAC[CLOSED_IN_DIFF; CLOSED_IN_REFL] THEN
8821     REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
8822     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
8823     FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
8824     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[];
8825     X_GEN_TAC `v:real^M->bool` THEN DISCH_TAC THEN
8826     FIRST_X_ASSUM(MP_TAC o SPEC `s DIFF v:real^M->bool`) THEN
8827     ASM_SIMP_TAC[OPEN_IN_DIFF; OPEN_IN_REFL] THEN
8828     FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
8829     REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
8830     DISCH_THEN(fun th -> CONJ_TAC THENL [ASM SET_TAC[]; MP_TAC th]) THEN
8831     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]]);;
8832
8833 let UPPER_LOWER_HEMICONTINUOUS_EXPLICIT = prove
8834  (`!f:real^M->real^N->bool t s.
8835       (!x. x IN s ==> f(x) SUBSET t) /\
8836       (!u. open_in (subtopology euclidean t) u
8837            ==> open_in (subtopology euclidean s)
8838                        {x | x IN s /\ f(x) SUBSET u}) /\
8839       (!u. closed_in (subtopology euclidean t) u
8840            ==> closed_in (subtopology euclidean s)
8841                          {x | x IN s /\ f(x) SUBSET u})
8842       ==> !x e. x IN s /\ &0 < e /\ bounded(f x) /\ ~(f x = {})
8843                 ==> ?d. &0 < d /\
8844                         !x'. x' IN s /\ dist(x,x') < d
8845                              ==> (!y. y IN f x
8846                                       ==> ?y'. y' IN f x' /\ dist(y,y') < e) /\
8847                                  (!y'. y' IN f x'
8848                                        ==> ?y. y IN f x /\ dist(y',y) < e)`,
8849   REPEAT STRIP_TAC THEN
8850   UNDISCH_TAC
8851    `!u. open_in (subtopology euclidean t) u
8852         ==> open_in (subtopology euclidean s)
8853                     {x | x IN s /\ (f:real^M->real^N->bool)(x) SUBSET u}` THEN
8854   DISCH_THEN(MP_TAC o SPEC
8855    `t INTER
8856     {a + b | a IN (f:real^M->real^N->bool) x /\ b IN ball(vec 0,e)}`) THEN
8857   SIMP_TAC[OPEN_SUMS; OPEN_BALL; OPEN_IN_OPEN_INTER] THEN
8858   REWRITE_TAC[open_in; SUBSET_RESTRICT] THEN
8859   DISCH_THEN(MP_TAC o SPEC `x:real^M`) THEN
8860   ASM_SIMP_TAC[IN_ELIM_THM; SUBSET_INTER] THEN ANTS_TAC THENL
8861    [REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
8862     ASM_MESON_TAC[CENTRE_IN_BALL; VECTOR_ADD_RID];
8863     DISCH_THEN(X_CHOOSE_THEN `d1:real`
8864      (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "1")))] THEN
8865   UNDISCH_TAC
8866    `!u. closed_in (subtopology euclidean t) u
8867         ==> closed_in (subtopology euclidean s)
8868                     {x | x IN s /\ (f:real^M->real^N->bool)(x) SUBSET u}` THEN
8869   ASM_SIMP_TAC[LOWER_HEMICONTINUOUS] THEN DISCH_THEN(MP_TAC o
8870     GEN `a:real^N` o SPEC `t INTER ball(a:real^N,e / &2)`) THEN
8871   SIMP_TAC[OPEN_BALL; OPEN_IN_OPEN_INTER] THEN
8872
8873   MP_TAC(SPEC `closure((f:real^M->real^N->bool) x)`
8874     COMPACT_EQ_HEINE_BOREL) THEN
8875   ASM_REWRITE_TAC[COMPACT_CLOSURE] THEN DISCH_THEN(MP_TAC o SPEC
8876    `{ball(a:real^N,e / &2) | a IN (f:real^M->real^N->bool) x}`) THEN
8877   REWRITE_TAC[SIMPLE_IMAGE; FORALL_IN_IMAGE; OPEN_BALL] THEN
8878   ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN
8879   REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE] THEN ANTS_TAC THENL
8880    [REWRITE_TAC[CLOSURE_APPROACHABLE; SUBSET; UNIONS_IMAGE; IN_ELIM_THM] THEN
8881     REWRITE_TAC[IN_BALL] THEN ASM_SIMP_TAC[REAL_HALF];
8882     ALL_TAC] THEN
8883   DISCH_THEN(X_CHOOSE_THEN `c:real^N->bool` STRIP_ASSUME_TAC) THEN
8884   DISCH_TAC THEN FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP
8885    (MESON[CLOSURE_SUBSET; SUBSET_TRANS]
8886         `closure s SUBSET t ==> s SUBSET t`)) THEN
8887   SUBGOAL_THEN
8888    `open_in (subtopology euclidean s)
8889       (INTERS {{x | x IN s /\
8890           ~((f:real^M->real^N->bool) x INTER t INTER ball(a,e / &2) = {})} |
8891      a IN c})`
8892   MP_TAC THENL
8893    [MATCH_MP_TAC OPEN_IN_INTERS THEN
8894     ASM_SIMP_TAC[SIMPLE_IMAGE; FORALL_IN_IMAGE; FINITE_IMAGE] THEN
8895     ASM_REWRITE_TAC[IMAGE_EQ_EMPTY] THEN ASM SET_TAC[];
8896     ALL_TAC] THEN
8897   REWRITE_TAC[open_in] THEN
8898   DISCH_THEN(MP_TAC o SPEC `x:real^M` o CONJUNCT2) THEN ANTS_TAC THENL
8899    [REWRITE_TAC[INTERS_GSPEC; IN_ELIM_THM] THEN
8900     X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN
8901     ASM_REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
8902     EXISTS_TAC `a:real^N` THEN
8903     ASM_REWRITE_TAC[IN_INTER; CENTRE_IN_BALL; REAL_HALF] THEN
8904     ASM SET_TAC[];
8905     DISCH_THEN(X_CHOOSE_THEN `d2:real`
8906      (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "2")))] THEN
8907   EXISTS_TAC `min d1 d2:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
8908   X_GEN_TAC `x':real^M` THEN STRIP_TAC THEN CONJ_TAC THENL
8909    [ALL_TAC;
8910     REMOVE_THEN "1" (MP_TAC o SPEC `x':real^M`) THEN
8911     ASM_REWRITE_TAC[] THEN
8912     ANTS_TAC THENL [ASM_MESON_TAC[DIST_SYM]; ALL_TAC] THEN
8913     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_BALL] THEN
8914     REWRITE_TAC[VECTOR_ARITH `x:real^N = a + b <=> x - a = b`;
8915                 DIST_0; ONCE_REWRITE_RULE[CONJ_SYM] UNWIND_THM1] THEN
8916     REWRITE_TAC[dist]] THEN
8917   REMOVE_THEN "2" (MP_TAC o SPEC `x':real^M`) THEN
8918   ASM_REWRITE_TAC[INTERS_GSPEC; IN_ELIM_THM] THEN
8919   ANTS_TAC THENL [ASM_MESON_TAC[DIST_SYM]; ALL_TAC] THEN
8920   DISCH_THEN(LABEL_TAC "3") THEN
8921   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
8922   UNDISCH_TAC `(f:real^M->real^N->bool) x SUBSET
8923                UNIONS (IMAGE (\a. ball (a,e / &2)) c)` THEN
8924   REWRITE_TAC[SUBSET] THEN DISCH_THEN(MP_TAC o SPEC `y:real^N`) THEN
8925   ASM_REWRITE_TAC[UNIONS_IMAGE; IN_ELIM_THM; IN_BALL] THEN
8926   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
8927   REMOVE_THEN "3" (MP_TAC o SPEC `a:real^N`) THEN
8928   ASM_REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER; IN_BALL] THEN
8929   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `z:real^N` THEN
8930   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
8931   ASM_MESON_TAC[DIST_TRIANGLE_HALF_L; DIST_SYM]);;
8932
8933 (* ------------------------------------------------------------------------- *)
8934 (* Connected components, considered as a "connectedness" relation or a set.  *)
8935 (* ------------------------------------------------------------------------- *)
8936
8937 let connected_component = new_definition
8938  `connected_component s x y <=>
8939         ?t. connected t /\ t SUBSET s /\ x IN t /\ y IN t`;;
8940
8941 let CONNECTED_COMPONENT_IN = prove
8942  (`!s x y. connected_component s x y ==> x IN s /\ y IN s`,
8943   REWRITE_TAC[connected_component] THEN SET_TAC[]);;
8944
8945 let CONNECTED_COMPONENT_REFL = prove
8946  (`!s x:real^N. x IN s ==> connected_component s x x`,
8947   REWRITE_TAC[connected_component] THEN REPEAT STRIP_TAC THEN
8948   EXISTS_TAC `{x:real^N}` THEN REWRITE_TAC[CONNECTED_SING] THEN
8949   ASM SET_TAC[]);;
8950
8951 let CONNECTED_COMPONENT_REFL_EQ = prove
8952  (`!s x:real^N. connected_component s x x <=> x IN s`,
8953   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[CONNECTED_COMPONENT_REFL] THEN
8954   REWRITE_TAC[connected_component] THEN SET_TAC[]);;
8955
8956 let CONNECTED_COMPONENT_SYM = prove
8957  (`!s x y:real^N. connected_component s x y ==> connected_component s y x`,
8958   REWRITE_TAC[connected_component] THEN MESON_TAC[]);;
8959
8960 let CONNECTED_COMPONENT_TRANS = prove
8961  (`!s x y:real^N.
8962     connected_component s x y /\ connected_component s y z
8963     ==> connected_component s x z`,
8964   REPEAT GEN_TAC THEN REWRITE_TAC[connected_component] THEN
8965   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `t:real^N->bool`)
8966                              (X_CHOOSE_TAC `u:real^N->bool`)) THEN
8967   EXISTS_TAC `t UNION u:real^N->bool` THEN
8968   ASM_REWRITE_TAC[IN_UNION; UNION_SUBSET] THEN
8969   MATCH_MP_TAC CONNECTED_UNION THEN ASM SET_TAC[]);;
8970
8971 let CONNECTED_COMPONENT_OF_SUBSET = prove
8972  (`!s t x. s SUBSET t /\ connected_component s x y
8973            ==> connected_component t x y`,
8974   REWRITE_TAC[connected_component] THEN SET_TAC[]);;
8975
8976 let CONNECTED_COMPONENT_SET = prove
8977  (`!s x. connected_component s x =
8978             { y | ?t. connected t /\ t SUBSET s /\ x IN t /\ y IN t}`,
8979   REWRITE_TAC[IN_ELIM_THM; EXTENSION] THEN
8980   REWRITE_TAC[IN; connected_component] THEN MESON_TAC[]);;
8981
8982 let CONNECTED_COMPONENT_UNIONS = prove
8983  (`!s x. connected_component s x =
8984                 UNIONS {t | connected t /\ x IN t /\ t SUBSET s}`,
8985   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]);;
8986
8987 let CONNECTED_COMPONENT_SUBSET = prove
8988  (`!s x. (connected_component s x) SUBSET s`,
8989   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]);;
8990
8991 let CONNECTED_CONNECTED_COMPONENT_SET = prove
8992  (`!s. connected s <=> !x:real^N. x IN s ==> connected_component s x = s`,
8993   GEN_TAC THEN REWRITE_TAC[CONNECTED_COMPONENT_UNIONS] THEN EQ_TAC THENL
8994    [SET_TAC[]; ALL_TAC] THEN
8995   ASM_CASES_TAC `s:real^N->bool = {}` THEN
8996   ASM_REWRITE_TAC[CONNECTED_EMPTY] THEN
8997   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
8998   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
8999   DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN ASM_REWRITE_TAC[] THEN
9000   DISCH_THEN(SUBST1_TAC o SYM) THEN MATCH_MP_TAC CONNECTED_UNIONS THEN
9001   ASM SET_TAC[]);;
9002
9003 let CONNECTED_COMPONENT_EQ_SELF = prove
9004  (`!s x. connected s /\ x IN s ==> connected_component s x = s`,
9005   MESON_TAC[CONNECTED_CONNECTED_COMPONENT_SET]);;
9006
9007 let CONNECTED_IFF_CONNECTED_COMPONENT = prove
9008  (`!s. connected s <=>
9009           !x y. x IN s /\ y IN s ==> connected_component s x y`,
9010   REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT_SET] THEN
9011   REWRITE_TAC[EXTENSION] THEN MESON_TAC[IN; CONNECTED_COMPONENT_IN]);;
9012
9013 let CONNECTED_COMPONENT_MAXIMAL = prove
9014  (`!s t x:real^N.
9015         x IN t /\ connected t /\ t SUBSET s
9016         ==> t SUBSET (connected_component s x)`,
9017   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]);;
9018
9019 let CONNECTED_COMPONENT_MONO = prove
9020  (`!s t x. s SUBSET t
9021            ==> (connected_component s x) SUBSET (connected_component t x)`,
9022   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]);;
9023
9024 let CONNECTED_CONNECTED_COMPONENT = prove
9025  (`!s x. connected(connected_component s x)`,
9026   REWRITE_TAC[CONNECTED_COMPONENT_UNIONS] THEN
9027   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_UNIONS THEN SET_TAC[]);;
9028
9029 let CONNECTED_COMPONENT_EQ_EMPTY = prove
9030  (`!s x:real^N. connected_component s x = {} <=> ~(x IN s)`,
9031   REPEAT GEN_TAC THEN EQ_TAC THENL
9032    [REWRITE_TAC[EXTENSION; NOT_IN_EMPTY] THEN
9033     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
9034     REWRITE_TAC[IN; CONNECTED_COMPONENT_REFL_EQ];
9035     REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]]);;
9036
9037 let CONNECTED_COMPONENT_EMPTY = prove
9038  (`!x. connected_component {} x = {}`,
9039   REWRITE_TAC[CONNECTED_COMPONENT_EQ_EMPTY; NOT_IN_EMPTY]);;
9040
9041 let CONNECTED_COMPONENT_EQ = prove
9042  (`!s x y. y IN connected_component s x
9043            ==> (connected_component s y = connected_component s x)`,
9044   REWRITE_TAC[EXTENSION; IN] THEN
9045   MESON_TAC[CONNECTED_COMPONENT_SYM; CONNECTED_COMPONENT_TRANS]);;
9046
9047 let CLOSED_CONNECTED_COMPONENT = prove
9048  (`!s x:real^N. closed s ==> closed(connected_component s x)`,
9049   REPEAT STRIP_TAC THEN
9050   ASM_CASES_TAC `(x:real^N) IN s` THENL
9051    [ALL_TAC; ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY; CLOSED_EMPTY]] THEN
9052   REWRITE_TAC[GSYM CLOSURE_EQ] THEN
9053   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[CLOSURE_SUBSET] THEN
9054   MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
9055   SIMP_TAC[CONNECTED_CLOSURE; CONNECTED_CONNECTED_COMPONENT] THEN
9056   CONJ_TAC THENL
9057    [MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN
9058     ASM_REWRITE_TAC[IN; CONNECTED_COMPONENT_REFL_EQ];
9059     MATCH_MP_TAC CLOSURE_MINIMAL THEN
9060     ASM_REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]]);;
9061
9062 let CONNECTED_COMPONENT_DISJOINT = prove
9063  (`!s a b. DISJOINT (connected_component s a) (connected_component s b) <=>
9064              ~(a IN connected_component s b)`,
9065   REWRITE_TAC[DISJOINT; EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN
9066   REWRITE_TAC[IN] THEN
9067   MESON_TAC[CONNECTED_COMPONENT_SYM; CONNECTED_COMPONENT_TRANS]);;
9068
9069 let CONNECTED_COMPONENT_NONOVERLAP = prove
9070  (`!s a b:real^N.
9071         (connected_component s a) INTER (connected_component s b) = {} <=>
9072         ~(a IN s) \/ ~(b IN s) \/
9073         ~(connected_component s a = connected_component s b)`,
9074   REPEAT GEN_TAC THEN
9075   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
9076   RULE_ASSUM_TAC(REWRITE_RULE[GSYM CONNECTED_COMPONENT_EQ_EMPTY]) THEN
9077   ASM_REWRITE_TAC[INTER_EMPTY] THEN
9078   ASM_CASES_TAC `(b:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
9079   RULE_ASSUM_TAC(REWRITE_RULE[GSYM CONNECTED_COMPONENT_EQ_EMPTY]) THEN
9080   ASM_REWRITE_TAC[INTER_EMPTY] THEN ASM_CASES_TAC
9081    `connected_component s (a:real^N) = connected_component s b` THEN
9082   ASM_REWRITE_TAC[INTER_IDEMPOT; CONNECTED_COMPONENT_EQ_EMPTY] THEN
9083   FIRST_X_ASSUM(MP_TAC o check(is_neg o concl)) THEN
9084   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
9085   REWRITE_TAC[] THEN MATCH_MP_TAC CONNECTED_COMPONENT_EQ THEN
9086   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [GSYM DISJOINT]) THEN
9087   REWRITE_TAC[CONNECTED_COMPONENT_DISJOINT]);;
9088
9089 let CONNECTED_COMPONENT_OVERLAP = prove
9090  (`!s a b:real^N.
9091         ~((connected_component s a) INTER (connected_component s b) = {}) <=>
9092         a IN s /\ b IN s /\
9093         connected_component s a = connected_component s b`,
9094   REWRITE_TAC[CONNECTED_COMPONENT_NONOVERLAP; DE_MORGAN_THM]);;
9095
9096 let CONNECTED_COMPONENT_SYM_EQ = prove
9097  (`!s x y. connected_component s x y <=> connected_component s y x`,
9098   MESON_TAC[CONNECTED_COMPONENT_SYM]);;
9099
9100 let CONNECTED_COMPONENT_EQ_EQ = prove
9101  (`!s x y:real^N.
9102         connected_component s x = connected_component s y <=>
9103            ~(x IN s) /\ ~(y IN s) \/
9104            x IN s /\ y IN s /\ connected_component s x y`,
9105   REPEAT GEN_TAC THEN ASM_CASES_TAC `(y:real^N) IN s` THENL
9106    [ASM_CASES_TAC `(x:real^N) IN s` THEN ASM_REWRITE_TAC[] THENL
9107      [REWRITE_TAC[FUN_EQ_THM] THEN
9108       ASM_MESON_TAC[CONNECTED_COMPONENT_TRANS; CONNECTED_COMPONENT_REFL;
9109                     CONNECTED_COMPONENT_SYM];
9110       ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY]];
9111     RULE_ASSUM_TAC(REWRITE_RULE[GSYM CONNECTED_COMPONENT_EQ_EMPTY]) THEN
9112     ASM_REWRITE_TAC[CONNECTED_COMPONENT_EQ_EMPTY] THEN
9113     ONCE_REWRITE_TAC[CONNECTED_COMPONENT_SYM_EQ] THEN
9114     ASM_REWRITE_TAC[EMPTY] THEN ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY]]);;
9115
9116 let CONNECTED_EQ_CONNECTED_COMPONENT_EQ = prove
9117  (`!s. connected s <=>
9118        !x y. x IN s /\ y IN s
9119              ==> connected_component s x = connected_component s y`,
9120   SIMP_TAC[CONNECTED_COMPONENT_EQ_EQ] THEN
9121   REWRITE_TAC[CONNECTED_IFF_CONNECTED_COMPONENT]);;
9122
9123 let CONNECTED_COMPONENT_IDEMP = prove
9124  (`!s x:real^N. connected_component (connected_component s x) x =
9125                 connected_component s x`,
9126   REWRITE_TAC[FUN_EQ_THM; connected_component] THEN
9127   REPEAT GEN_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN EQ_TAC THEN
9128   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
9129   ASM_MESON_TAC[CONNECTED_COMPONENT_MAXIMAL; SUBSET_TRANS;
9130                 CONNECTED_COMPONENT_SUBSET]);;
9131
9132 let CONNECTED_COMPONENT_UNIQUE = prove
9133  (`!s c x:real^N.
9134         x IN c /\ c SUBSET s /\ connected c /\
9135         (!c'. x IN c' /\ c' SUBSET s /\ connected c'
9136               ==> c' SUBSET c)
9137         ==> connected_component s x = c`,
9138   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
9139    [FIRST_X_ASSUM MATCH_MP_TAC THEN
9140     REWRITE_TAC[CONNECTED_COMPONENT_SUBSET; CONNECTED_CONNECTED_COMPONENT] THEN
9141     REWRITE_TAC[IN] THEN ASM_REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ] THEN
9142     ASM SET_TAC[];
9143     MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[]]);;
9144
9145 let JOINABLE_CONNECTED_COMPONENT_EQ = prove
9146  (`!s t x y:real^N.
9147         connected t /\ t SUBSET s /\
9148         ~(connected_component s x INTER t = {}) /\
9149         ~(connected_component s y INTER t = {})
9150         ==> connected_component s x = connected_component s y`,
9151   REPEAT GEN_TAC THEN
9152   REPLICATE_TAC 2 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
9153   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN DISCH_THEN(CONJUNCTS_THEN2
9154    (X_CHOOSE_THEN `w:real^N` STRIP_ASSUME_TAC)
9155    (X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC)) THEN
9156   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_COMPONENT_EQ THEN
9157   REWRITE_TAC[IN] THEN
9158   MATCH_MP_TAC CONNECTED_COMPONENT_TRANS THEN
9159   EXISTS_TAC `z:real^N` THEN CONJ_TAC THENL [ASM_MESON_TAC[IN]; ALL_TAC] THEN
9160   MATCH_MP_TAC CONNECTED_COMPONENT_TRANS THEN
9161   EXISTS_TAC `w:real^N` THEN CONJ_TAC THENL
9162    [REWRITE_TAC[connected_component] THEN
9163     EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[];
9164     ASM_MESON_TAC[IN; CONNECTED_COMPONENT_SYM]]);;
9165
9166 let CONNECTED_COMPONENT_TRANSLATION = prove
9167  (`!a s x. connected_component (IMAGE (\x. a + x) s) (a + x) =
9168                 IMAGE (\x. a + x) (connected_component s x)`,
9169   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN GEOM_TRANSLATE_TAC[]);;
9170
9171 add_translation_invariants [CONNECTED_COMPONENT_TRANSLATION];;
9172
9173 let CONNECTED_COMPONENT_LINEAR_IMAGE = prove
9174  (`!f s x. linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
9175            ==> connected_component (IMAGE f s) (f x) =
9176                IMAGE f (connected_component s x)`,
9177   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN
9178   GEOM_TRANSFORM_TAC[]);;
9179
9180 add_linear_invariants [CONNECTED_COMPONENT_LINEAR_IMAGE];;
9181
9182 let UNIONS_CONNECTED_COMPONENT = prove
9183  (`!s:real^N->bool. UNIONS {connected_component s x |x| x IN s} = s`,
9184   GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9185   REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC; CONNECTED_COMPONENT_SUBSET] THEN
9186   REWRITE_TAC[SUBSET; UNIONS_GSPEC; IN_ELIM_THM] THEN
9187   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN EXISTS_TAC `x:real^N` THEN
9188   ASM_REWRITE_TAC[] THEN REWRITE_TAC[IN] THEN
9189   ASM_REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ]);;
9190
9191 let COMPLEMENT_CONNECTED_COMPONENT_UNIONS = prove
9192  (`!s x:real^N.
9193      s DIFF connected_component s x =
9194      UNIONS({connected_component s y | y | y IN s} DELETE
9195             (connected_component s x))`,
9196   REPEAT GEN_TAC THEN
9197   GEN_REWRITE_TAC (LAND_CONV o LAND_CONV)
9198     [GSYM UNIONS_CONNECTED_COMPONENT] THEN
9199   MATCH_MP_TAC(SET_RULE
9200    `(!x. x IN s DELETE a ==> DISJOINT a x)
9201      ==> UNIONS s DIFF a = UNIONS (s DELETE a)`) THEN
9202   REWRITE_TAC[IMP_CONJ; FORALL_IN_GSPEC; IN_DELETE] THEN
9203   SIMP_TAC[CONNECTED_COMPONENT_DISJOINT; CONNECTED_COMPONENT_EQ_EQ] THEN
9204   MESON_TAC[IN; SUBSET; CONNECTED_COMPONENT_SUBSET]);;
9205
9206 let CLOSED_IN_CONNECTED_COMPONENT = prove
9207  (`!s x:real^N. closed_in (subtopology euclidean s) (connected_component s x)`,
9208   REPEAT GEN_TAC THEN
9209   ASM_CASES_TAC `connected_component s (x:real^N) = {}` THEN
9210   ASM_REWRITE_TAC[CLOSED_IN_EMPTY] THEN
9211   RULE_ASSUM_TAC(REWRITE_RULE[CONNECTED_COMPONENT_EQ_EMPTY]) THEN
9212   REWRITE_TAC[CLOSED_IN_CLOSED] THEN
9213   EXISTS_TAC `closure(connected_component s x):real^N->bool` THEN
9214   REWRITE_TAC[CLOSED_CLOSURE] THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9215   REWRITE_TAC[SUBSET_INTER; CONNECTED_COMPONENT_SUBSET; CLOSURE_SUBSET] THEN
9216   MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN REWRITE_TAC[INTER_SUBSET] THEN
9217   CONJ_TAC THENL
9218    [ASM_REWRITE_TAC[IN_INTER] THEN
9219     MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN
9220     ASM_REWRITE_TAC[IN; CONNECTED_COMPONENT_REFL_EQ];
9221     MATCH_MP_TAC CONNECTED_INTERMEDIATE_CLOSURE THEN
9222     EXISTS_TAC `connected_component s (x:real^N)` THEN
9223     REWRITE_TAC[INTER_SUBSET; CONNECTED_CONNECTED_COMPONENT;
9224                 SUBSET_INTER; CONNECTED_COMPONENT_SUBSET; CLOSURE_SUBSET]]);;
9225
9226 let OPEN_IN_CONNECTED_COMPONENT = prove
9227  (`!s x:real^N.
9228         FINITE {connected_component s x |x| x IN s}
9229         ==> open_in (subtopology euclidean s) (connected_component s x)`,
9230   REPEAT STRIP_TAC THEN
9231   SUBGOAL_THEN
9232    `connected_component s (x:real^N) =
9233         s DIFF (UNIONS {connected_component s y |y| y IN s} DIFF
9234                 connected_component s x)`
9235   SUBST1_TAC THENL
9236    [REWRITE_TAC[UNIONS_CONNECTED_COMPONENT] THEN
9237     MATCH_MP_TAC(SET_RULE `t SUBSET s ==> t = s DIFF (s DIFF t)`) THEN
9238     REWRITE_TAC[CONNECTED_COMPONENT_SUBSET];
9239     MATCH_MP_TAC OPEN_IN_DIFF THEN
9240     REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_REFL; TOPSPACE_EUCLIDEAN; SUBSET_UNIV] THEN
9241     REWRITE_TAC[UNIONS_DIFF] THEN
9242     MATCH_MP_TAC CLOSED_IN_UNIONS THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
9243     ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN ASM_SIMP_TAC[FINITE_IMAGE] THEN
9244     X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
9245     SUBGOAL_THEN
9246      `connected_component s y DIFF connected_component s x =
9247       connected_component s y \/
9248       connected_component s (y:real^N) DIFF connected_component s x = {}`
9249      (DISJ_CASES_THEN SUBST1_TAC)
9250     THENL
9251      [MATCH_MP_TAC(SET_RULE
9252        `(~(s INTER t = {}) ==> s = t) ==> s DIFF t = s \/ s DIFF t = {}`) THEN
9253       SIMP_TAC[CONNECTED_COMPONENT_OVERLAP];
9254       REWRITE_TAC[CLOSED_IN_CONNECTED_COMPONENT];
9255       REWRITE_TAC[CLOSED_IN_EMPTY]]]);;
9256
9257 let CONNECTED_COMPONENT_EQUIVALENCE_RELATION = prove
9258  (`!R s:real^N->bool.
9259         (!x y. R x y ==> R y x) /\
9260         (!x y z. R x y /\ R y z ==> R x z) /\
9261         (!a. a IN s
9262              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
9263                      !x. x IN t ==> R a x)
9264         ==> !a b. connected_component s a b ==> R a b`,
9265   REPEAT STRIP_TAC THEN
9266   MP_TAC(ISPECL [`R:real^N->real^N->bool`; `connected_component s (a:real^N)`]
9267     CONNECTED_EQUIVALENCE_RELATION) THEN
9268   ASM_REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT] THEN ANTS_TAC THENL
9269    [X_GEN_TAC `c:real^N` THEN DISCH_TAC THEN
9270     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N`) THEN ANTS_TAC THENL
9271      [ASM_MESON_TAC[CONNECTED_COMPONENT_SUBSET; SUBSET]; ALL_TAC] THEN
9272     DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
9273     EXISTS_TAC `t INTER connected_component s (a:real^N)` THEN
9274     ASM_SIMP_TAC[IN_INTER; OPEN_IN_OPEN] THEN
9275     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
9276     MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN
9277     MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`]
9278         CONNECTED_COMPONENT_SUBSET) THEN
9279     SET_TAC[];
9280     DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[IN] THEN
9281     REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ] THEN
9282     ASM_MESON_TAC[CONNECTED_COMPONENT_IN]]);;
9283
9284 let CONNECTED_COMPONENT_INTERMEDIATE_SUBSET = prove
9285  (`!t u a:real^N.
9286         connected_component u a SUBSET t /\ t SUBSET u
9287         ==> connected_component t a = connected_component u a`,
9288   REPEAT GEN_TAC THEN ASM_CASES_TAC `(a:real^N) IN u` THENL
9289    [REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_COMPONENT_UNIQUE THEN
9290     ASM_REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT] THEN
9291     CONJ_TAC THENL [ASM_MESON_TAC[CONNECTED_COMPONENT_REFL; IN]; ALL_TAC] THEN
9292     REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
9293     ASM SET_TAC[];
9294     ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY; SUBSET]]);;
9295
9296 (* ------------------------------------------------------------------------- *)
9297 (* The set of connected components of a set.                                 *)
9298 (* ------------------------------------------------------------------------- *)
9299
9300 let components = new_definition
9301   `components s = {connected_component s x | x | x:real^N IN s}`;;
9302
9303 let COMPONENTS_TRANSLATION = prove
9304  (`!a s. components(IMAGE (\x. a + x) s) =
9305    IMAGE (IMAGE (\x. a + x)) (components s)`,
9306   REWRITE_TAC[components] THEN GEOM_TRANSLATE_TAC[] THEN SET_TAC[]);;
9307
9308 add_translation_invariants [COMPONENTS_TRANSLATION];;
9309
9310 let COMPONENTS_LINEAR_IMAGE = prove
9311  (`!f s. linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
9312            ==> components(IMAGE f s) = IMAGE (IMAGE f) (components s)`,
9313   REWRITE_TAC[components] THEN GEOM_TRANSFORM_TAC[] THEN SET_TAC[]);;
9314
9315 add_linear_invariants [COMPONENTS_LINEAR_IMAGE];;
9316
9317 let IN_COMPONENTS = prove
9318  (`!u:real^N->bool s. s IN components u
9319     <=> ?x. x IN u /\ s = connected_component u x`,
9320   REPEAT GEN_TAC THEN REWRITE_TAC[components] THEN EQ_TAC
9321   THENL [SET_TAC[];STRIP_TAC THEN ASM_SIMP_TAC[] THEN
9322   UNDISCH_TAC `x:real^N IN u` THEN SET_TAC[]]);;
9323
9324 let UNIONS_COMPONENTS = prove
9325  (`!u:real^N->bool. u = UNIONS (components u)`,
9326   REWRITE_TAC[EXTENSION] THEN REPEAT GEN_TAC THEN EQ_TAC
9327   THENL[DISCH_TAC THEN REWRITE_TAC[IN_UNIONS] THEN
9328   EXISTS_TAC `connected_component (u:real^N->bool) x` THEN CONJ_TAC THENL
9329   [REWRITE_TAC[components] THEN SET_TAC[ASSUME `x:real^N IN u`];
9330   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SUBGOAL_THEN
9331   `?s:real^N->bool. connected s /\ s SUBSET u /\ x IN s` MP_TAC
9332   THENL[EXISTS_TAC `{x:real^N}` THEN ASM_REWRITE_TAC[CONNECTED_SING] THEN
9333   POP_ASSUM MP_TAC THEN SET_TAC[]; SET_TAC[]]];
9334   REWRITE_TAC[IN_UNIONS] THEN STRIP_TAC THEN
9335   MATCH_MP_TAC (SET_RULE `!x:real^N s u. x IN s /\ s SUBSET u ==> x IN u`) THEN
9336   EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[] THEN STRIP_ASSUME_TAC
9337   (MESON[IN_COMPONENTS;ASSUME `t:real^N->bool IN components u`]
9338   `?y. t:real^N->bool = connected_component u y`) THEN
9339    ASM_REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]]);;
9340
9341 let PAIRWISE_DISJOINT_COMPONENTS = prove
9342  (`!u:real^N->bool. pairwise DISJOINT (components u)`,
9343   GEN_TAC THEN REWRITE_TAC[pairwise;DISJOINT] THEN
9344   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `t:real^N->bool`] THEN STRIP_TAC THEN
9345   ASSERT_TAC `(?a. s:real^N->bool = connected_component u a) /\
9346   ?b. t:real^N->bool = connected_component u b`
9347   THENL [ASM_MESON_TAC[IN_COMPONENTS];
9348   ASM_MESON_TAC[CONNECTED_COMPONENT_NONOVERLAP]]);;
9349
9350 let IN_COMPONENTS_NONEMPTY = prove
9351  (`!s c. c IN components s ==> ~(c = {})`,
9352   REPEAT GEN_TAC THEN REWRITE_TAC[components; IN_ELIM_THM] THEN
9353   STRIP_TAC THEN ASM_REWRITE_TAC[CONNECTED_COMPONENT_EQ_EMPTY]);;
9354
9355 let IN_COMPONENTS_SUBSET = prove
9356  (`!s c. c IN components s ==> c SUBSET s`,
9357   REPEAT GEN_TAC THEN REWRITE_TAC[components; IN_ELIM_THM] THEN
9358   STRIP_TAC THEN ASM_REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]);;
9359
9360 let IN_COMPONENTS_CONNECTED = prove
9361  (`!s c. c IN components s ==> connected c`,
9362   REPEAT GEN_TAC THEN REWRITE_TAC[components; IN_ELIM_THM] THEN
9363   STRIP_TAC THEN ASM_REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT]);;
9364
9365 let IN_COMPONENTS_MAXIMAL = prove
9366  (`!s c:real^N->bool.
9367         c IN components s <=>
9368         ~(c = {}) /\ c SUBSET s /\ connected c /\
9369         !c'. ~(c' = {}) /\ c SUBSET c' /\ c' SUBSET s /\ connected c'
9370              ==> c' = c`,
9371   REPEAT GEN_TAC THEN REWRITE_TAC[components; IN_ELIM_THM] THEN EQ_TAC THENL
9372    [DISCH_THEN(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
9373     ASM_REWRITE_TAC[CONNECTED_COMPONENT_EQ_EMPTY; CONNECTED_COMPONENT_SUBSET;
9374                     CONNECTED_CONNECTED_COMPONENT] THEN
9375     REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9376     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
9377     ASM_MESON_TAC[CONNECTED_COMPONENT_REFL; IN; SUBSET];
9378     STRIP_TAC THEN
9379     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9380     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN
9381     DISCH_TAC THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
9382     MATCH_MP_TAC(GSYM CONNECTED_COMPONENT_UNIQUE) THEN
9383     ASM_REWRITE_TAC[] THEN X_GEN_TAC `c':real^N->bool` THEN STRIP_TAC THEN
9384     REWRITE_TAC[SET_RULE `c' SUBSET c <=> c' UNION c = c`] THEN
9385     FIRST_X_ASSUM MATCH_MP_TAC THEN
9386     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
9387     MATCH_MP_TAC CONNECTED_UNION THEN ASM SET_TAC[]]);;
9388
9389 let JOINABLE_COMPONENTS_EQ = prove
9390  (`!s t c1 c2.
9391         connected t /\ t SUBSET s /\
9392         c1 IN components s /\ c2 IN components s /\
9393         ~(c1 INTER t = {}) /\ ~(c2 INTER t = {})
9394         ==> c1 = c2`,
9395   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; components; FORALL_IN_GSPEC] THEN
9396   MESON_TAC[JOINABLE_CONNECTED_COMPONENT_EQ]);;
9397
9398 let CLOSED_IN_COMPONENT = prove
9399  (`!s c:real^N->bool.
9400         c IN components s ==> closed_in (subtopology euclidean s) c`,
9401   REWRITE_TAC[components; FORALL_IN_GSPEC; CLOSED_IN_CONNECTED_COMPONENT]);;
9402
9403 let CLOSED_COMPONENTS = prove
9404  (`!s c. closed s /\ c IN components s ==> closed c`,
9405   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; components; FORALL_IN_GSPEC] THEN
9406   SIMP_TAC[CLOSED_CONNECTED_COMPONENT]);;
9407
9408 let COMPACT_COMPONENTS = prove
9409  (`!s c:real^N->bool. compact s /\ c IN components s ==> compact c`,
9410   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
9411   MESON_TAC[CLOSED_COMPONENTS; IN_COMPONENTS_SUBSET; BOUNDED_SUBSET]);;
9412
9413 let CONTINUOUS_ON_COMPONENTS_GEN = prove
9414  (`!f:real^M->real^N s.
9415         (!c. c IN components s
9416              ==> open_in (subtopology euclidean s) c /\ f continuous_on c)
9417         ==> f continuous_on s`,
9418   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_OPEN_IN_PREIMAGE_EQ] THEN
9419   DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN DISCH_TAC THEN
9420   SUBGOAL_THEN
9421    `{x | x IN s /\ (f:real^M->real^N) x IN t} =
9422     UNIONS {{x | x IN c /\ f x IN t} | c IN components s}`
9423   SUBST1_TAC THENL
9424    [CONV_TAC(LAND_CONV(SUBS_CONV
9425      [ISPEC `s:real^M->bool` UNIONS_COMPONENTS])) THEN
9426     REWRITE_TAC[UNIONS_GSPEC; IN_UNIONS] THEN SET_TAC[];
9427     MATCH_MP_TAC OPEN_IN_UNIONS THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
9428     ASM_MESON_TAC[OPEN_IN_TRANS]]);;
9429
9430 let CONTINUOUS_ON_COMPONENTS_FINITE = prove
9431  (`!f:real^M->real^N s.
9432         FINITE(components s) /\
9433         (!c. c IN components s ==> f continuous_on c)
9434         ==> f continuous_on s`,
9435   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE_EQ] THEN
9436   DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN DISCH_TAC THEN
9437   SUBGOAL_THEN
9438    `{x | x IN s /\ (f:real^M->real^N) x IN t} =
9439     UNIONS {{x | x IN c /\ f x IN t} | c IN components s}`
9440   SUBST1_TAC THENL
9441    [CONV_TAC(LAND_CONV(SUBS_CONV
9442      [ISPEC `s:real^M->bool` UNIONS_COMPONENTS])) THEN
9443     REWRITE_TAC[UNIONS_GSPEC; IN_UNIONS] THEN SET_TAC[];
9444     MATCH_MP_TAC CLOSED_IN_UNIONS THEN
9445     ASM_SIMP_TAC[SIMPLE_IMAGE; FINITE_IMAGE; FORALL_IN_IMAGE] THEN
9446     ASM_MESON_TAC[CLOSED_IN_TRANS; CLOSED_IN_COMPONENT]]);;
9447
9448 let COMPONENTS_NONOVERLAP = prove
9449  (`!s c c'. c IN components s /\ c' IN components s
9450             ==> (c INTER c' = {} <=> ~(c = c'))`,
9451   REWRITE_TAC[components; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
9452   ASM_SIMP_TAC[CONNECTED_COMPONENT_NONOVERLAP]);;
9453
9454 let COMPONENTS_EQ = prove
9455  (`!s c c'. c IN components s /\ c' IN components s
9456             ==> (c = c' <=> ~(c INTER c' = {}))`,
9457   MESON_TAC[COMPONENTS_NONOVERLAP]);;
9458
9459 let COMPONENTS_EQ_EMPTY = prove
9460  (`!s. components s = {} <=> s = {}`,
9461   GEN_TAC THEN REWRITE_TAC[EXTENSION] THEN
9462   REWRITE_TAC[components; connected_component; IN_ELIM_THM] THEN
9463   SET_TAC[]);;
9464
9465 let COMPONENTS_EMPTY = prove
9466  (`components {} = {}`,
9467   REWRITE_TAC[COMPONENTS_EQ_EMPTY]);;
9468
9469 let CONNECTED_EQ_CONNECTED_COMPONENTS_EQ = prove
9470  (`!s. connected s <=>
9471        !c c'. c IN components s /\ c' IN components s ==> c = c'`,
9472   REWRITE_TAC[components; IN_ELIM_THM] THEN
9473   MESON_TAC[CONNECTED_EQ_CONNECTED_COMPONENT_EQ]);;
9474
9475 let COMPONENTS_EQ_SING,COMPONENTS_EQ_SING_EXISTS = (CONJ_PAIR o prove)
9476  (`(!s:real^N->bool. components s = {s} <=> connected s /\ ~(s = {})) /\
9477    (!s:real^N->bool. (?a. components s = {a}) <=> connected s /\ ~(s = {}))`,
9478   REWRITE_TAC[AND_FORALL_THM] THEN X_GEN_TAC `s:real^N->bool` THEN
9479   MATCH_MP_TAC(TAUT `(p ==> q) /\ (q ==> r) /\ (r ==> p)
9480                      ==> (p <=> r) /\ (q <=> r)`) THEN
9481   REPEAT CONJ_TAC THENL
9482    [MESON_TAC[];
9483     STRIP_TAC THEN ASM_REWRITE_TAC[CONNECTED_EQ_CONNECTED_COMPONENTS_EQ] THEN
9484     ASM_MESON_TAC[IN_SING; COMPONENTS_EQ_EMPTY; NOT_INSERT_EMPTY];
9485     STRIP_TAC THEN ONCE_REWRITE_TAC[EXTENSION] THEN
9486     REWRITE_TAC[IN_SING] THEN
9487     REWRITE_TAC[components; IN_ELIM_THM] THEN
9488     ASM_MESON_TAC[CONNECTED_CONNECTED_COMPONENT_SET; MEMBER_NOT_EMPTY]]);;
9489
9490 let CONNECTED_EQ_COMPONENTS_SUBSET_SING = prove
9491  (`!s:real^N->bool. connected s <=> components s SUBSET {s}`,
9492   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9493   ASM_REWRITE_TAC[COMPONENTS_EMPTY; CONNECTED_EMPTY; EMPTY_SUBSET] THEN
9494   REWRITE_TAC[SET_RULE `s SUBSET {a} <=> s = {} \/ s = {a}`] THEN
9495   ASM_REWRITE_TAC[COMPONENTS_EQ_EMPTY; COMPONENTS_EQ_SING]);;
9496
9497 let CONNECTED_EQ_COMPONENTS_SUBSET_SING_EXISTS = prove
9498  (`!s:real^N->bool. connected s <=> ?a. components s SUBSET {a}`,
9499   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
9500   ASM_REWRITE_TAC[COMPONENTS_EMPTY; CONNECTED_EMPTY; EMPTY_SUBSET] THEN
9501   REWRITE_TAC[SET_RULE `s SUBSET {a} <=> s = {} \/ s = {a}`] THEN
9502   ASM_REWRITE_TAC[COMPONENTS_EQ_EMPTY; COMPONENTS_EQ_SING_EXISTS]);;
9503
9504 let IN_COMPONENTS_SELF = prove
9505  (`!s:real^N->bool. s IN components s <=> connected s /\ ~(s = {})`,
9506   GEN_TAC THEN EQ_TAC THENL
9507    [MESON_TAC[IN_COMPONENTS_NONEMPTY; IN_COMPONENTS_CONNECTED];
9508     SIMP_TAC[GSYM COMPONENTS_EQ_SING; IN_SING]]);;
9509
9510 let COMPONENTS_MAXIMAL = prove
9511  (`!s t c:real^N->bool.
9512      c IN components s /\ connected t /\ t SUBSET s /\ ~(c INTER t = {})
9513      ==> t SUBSET c`,
9514   REWRITE_TAC[IMP_CONJ; components; FORALL_IN_GSPEC] THEN
9515   REPEAT STRIP_TAC THEN
9516   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9517   REWRITE_TAC[IN_INTER; LEFT_IMP_EXISTS_THM] THEN
9518   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
9519   FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP CONNECTED_COMPONENT_EQ) THEN
9520   MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[]);;
9521
9522 let COMPONENTS_UNIQUE = prove
9523  (`!s:real^N->bool k.
9524         UNIONS k = s /\
9525         (!c. c IN k
9526              ==> connected c /\ ~(c = {}) /\
9527                  !c'. connected c' /\ c SUBSET c' /\ c' SUBSET s ==> c' = c)
9528         ==> components s = k`,
9529   REPEAT STRIP_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
9530   X_GEN_TAC `c:real^N->bool` THEN REWRITE_TAC[IN_COMPONENTS] THEN
9531   EQ_TAC THENL
9532    [DISCH_THEN(X_CHOOSE_THEN `x:real^N`
9533      (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN
9534     FIRST_ASSUM(MP_TAC o SPEC `x:real^N` o GEN_REWRITE_RULE I [EXTENSION]) THEN
9535     REWRITE_TAC[IN_UNIONS] THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
9536     X_GEN_TAC `c:real^N->bool` THEN STRIP_TAC THEN
9537     SUBGOAL_THEN `connected_component s (x:real^N) = c`
9538      (fun th -> ASM_REWRITE_TAC[th]) THEN
9539     MATCH_MP_TAC CONNECTED_COMPONENT_UNIQUE THEN
9540     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN
9541     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
9542     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
9543     X_GEN_TAC `c':real^N->bool` THEN STRIP_TAC THEN
9544     REWRITE_TAC[SET_RULE `c' SUBSET c <=> c' UNION c = c`] THEN
9545     FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
9546      [MATCH_MP_TAC CONNECTED_UNION; ASM SET_TAC[]] THEN
9547     ASM SET_TAC[];
9548     DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN
9549     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
9550     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9551     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
9552     CONJ_TAC THENL [ASM SET_TAC[]; CONV_TAC SYM_CONV] THEN
9553     FIRST_X_ASSUM MATCH_MP_TAC THEN
9554     REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT; CONNECTED_COMPONENT_SUBSET] THEN
9555     MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
9556     ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;
9557
9558 let COMPONENTS_UNIQUE_EQ = prove
9559  (`!s:real^N->bool k.
9560         components s = k <=>
9561         UNIONS k = s /\
9562         (!c. c IN k
9563              ==> connected c /\ ~(c = {}) /\
9564                  !c'. connected c' /\ c SUBSET c' /\ c' SUBSET s ==> c' = c)`,
9565   REPEAT GEN_TAC THEN EQ_TAC THENL
9566    [DISCH_THEN(SUBST1_TAC o SYM); REWRITE_TAC[COMPONENTS_UNIQUE]] THEN
9567   REWRITE_TAC[GSYM UNIONS_COMPONENTS] THEN
9568   X_GEN_TAC `c:real^N->bool` THEN DISCH_TAC THEN REPEAT CONJ_TAC THENL
9569    [ASM_MESON_TAC[IN_COMPONENTS_CONNECTED];
9570     ASM_MESON_TAC[IN_COMPONENTS_NONEMPTY];
9571     RULE_ASSUM_TAC(REWRITE_RULE[IN_COMPONENTS_MAXIMAL]) THEN
9572     ASM_MESON_TAC[SUBSET_EMPTY]]);;
9573
9574 let EXISTS_COMPONENT_SUPERSET = prove
9575  (`!s t:real^N->bool.
9576         t SUBSET s /\ ~(s = {}) /\ connected t
9577         ==> ?c. c IN components s /\ t SUBSET c`,
9578   REPEAT STRIP_TAC THEN ASM_CASES_TAC `t:real^N->bool = {}` THENL
9579    [ASM_REWRITE_TAC[EMPTY_SUBSET] THEN
9580     ASM_MESON_TAC[COMPONENTS_EQ_EMPTY; MEMBER_NOT_EMPTY];
9581     FIRST_X_ASSUM(X_CHOOSE_TAC `a:real^N` o
9582       GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9583     EXISTS_TAC `connected_component s (a:real^N)` THEN
9584     REWRITE_TAC[IN_COMPONENTS] THEN CONJ_TAC THENL
9585      [ASM SET_TAC[]; ASM_MESON_TAC[CONNECTED_COMPONENT_MAXIMAL]]]);;
9586
9587 let COMPONENTS_INTERMEDIATE_SUBSET = prove
9588  (`!s t u:real^N->bool.
9589         s IN components u /\ s SUBSET t /\ t SUBSET u
9590         ==> s IN components t`,
9591   REPEAT GEN_TAC THEN REWRITE_TAC[IN_COMPONENTS; LEFT_AND_EXISTS_THM] THEN
9592   MESON_TAC[CONNECTED_COMPONENT_INTERMEDIATE_SUBSET; SUBSET;
9593             CONNECTED_COMPONENT_REFL; IN; CONNECTED_COMPONENT_SUBSET]);;
9594
9595 let IN_COMPONENTS_UNIONS_COMPLEMENT = prove
9596  (`!s c:real^N->bool.
9597         c IN components s
9598         ==> s DIFF c = UNIONS(components s DELETE c)`,
9599   REWRITE_TAC[components; FORALL_IN_GSPEC;
9600               COMPLEMENT_CONNECTED_COMPONENT_UNIONS]);;
9601
9602 let CONNECTED_SUBSET_CLOPEN = prove
9603  (`!u s c:real^N->bool.
9604         closed_in (subtopology euclidean u) s /\
9605         open_in (subtopology euclidean u) s /\
9606         connected c /\ c SUBSET u /\ ~(c INTER s = {})
9607         ==> c SUBSET s`,
9608   REPEAT STRIP_TAC THEN
9609   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONNECTED_CLOSED_IN]) THEN
9610   REWRITE_TAC[NOT_EXISTS_THM] THEN DISCH_THEN(MP_TAC o
9611     SPECL [`c INTER s:real^N->bool`; `c DIFF s:real^N->bool`]) THEN
9612   ASM_REWRITE_TAC[CONJ_ASSOC; SET_RULE `c DIFF s = {} <=> c SUBSET s`] THEN
9613   MATCH_MP_TAC(TAUT `p ==> ~(p /\ ~q) ==> q`) THEN
9614   REPLICATE_TAC 2 (CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]]) THEN
9615   CONJ_TAC THENL
9616    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CLOSED_IN_CLOSED]);
9617     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN])] THEN
9618   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
9619   REWRITE_TAC[OPEN_IN_OPEN; CLOSED_IN_CLOSED] THENL
9620    [EXISTS_TAC `t:real^N->bool`; EXISTS_TAC `(:real^N) DIFF t`] THEN
9621   ASM_REWRITE_TAC[GSYM OPEN_CLOSED] THEN ASM SET_TAC[]);;
9622
9623 let CLOPEN_UNIONS_COMPONENTS = prove
9624  (`!u s:real^N->bool.
9625         closed_in (subtopology euclidean u) s /\
9626         open_in (subtopology euclidean u) s
9627         ==> ?k. k SUBSET components u /\ s = UNIONS k`,
9628   REPEAT STRIP_TAC THEN
9629   EXISTS_TAC `{c:real^N->bool | c IN components u /\ ~(c INTER s = {})}` THEN
9630   REWRITE_TAC[SUBSET_RESTRICT] THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9631   CONJ_TAC THENL
9632    [MP_TAC(ISPEC `u:real^N->bool` UNIONS_COMPONENTS) THEN
9633     FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN SET_TAC[];
9634     REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC] THEN
9635     REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_SUBSET_CLOPEN THEN
9636     EXISTS_TAC `u:real^N->bool` THEN
9637     ASM_MESON_TAC[IN_COMPONENTS_CONNECTED; IN_COMPONENTS_SUBSET]]);;
9638
9639 let CLOPEN_IN_COMPONENTS = prove
9640  (`!u s:real^N->bool.
9641         closed_in (subtopology euclidean u) s /\
9642         open_in (subtopology euclidean u) s /\
9643         connected s /\ ~(s = {})
9644         ==> s IN components u`,
9645   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[CONJ_ASSOC] THEN
9646   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9647   FIRST_ASSUM(MP_TAC o MATCH_MP CLOPEN_UNIONS_COMPONENTS) THEN
9648   DISCH_THEN(X_CHOOSE_THEN `k:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
9649   ASM_CASES_TAC `k:(real^N->bool)->bool = {}` THEN
9650   ASM_REWRITE_TAC[UNIONS_0] THEN
9651   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9652   DISCH_THEN(X_CHOOSE_TAC `c:real^N->bool`) THEN
9653   ASM_CASES_TAC `k = {c:real^N->bool}` THENL
9654    [ASM_MESON_TAC[UNIONS_1; GSYM SING_SUBSET]; ALL_TAC] THEN
9655   MATCH_MP_TAC(TAUT `~p ==> p /\ q ==> r`) THEN
9656   SUBGOAL_THEN `?c':real^N->bool. c' IN k /\ ~(c = c')` STRIP_ASSUME_TAC THENL
9657    [ASM_MESON_TAC[SET_RULE
9658      `a IN s /\ ~(s = {a}) ==> ?b. b IN s /\ ~(b = a)`];
9659     REWRITE_TAC[CONNECTED_EQ_CONNECTED_COMPONENTS_EQ] THEN
9660     DISCH_THEN(MP_TAC o SPECL [`c:real^N->bool`; `c':real^N->bool`]) THEN
9661     ASM_REWRITE_TAC[NOT_IMP] THEN CONJ_TAC THEN
9662     MATCH_MP_TAC COMPONENTS_INTERMEDIATE_SUBSET THEN
9663     EXISTS_TAC `u:real^N->bool` THEN
9664     MP_TAC(ISPEC `u:real^N->bool` UNIONS_COMPONENTS) THEN ASM SET_TAC[]]);;
9665
9666 (* ------------------------------------------------------------------------- *)
9667 (* Continuity implies uniform continuity on a compact domain.                *)
9668 (* ------------------------------------------------------------------------- *)
9669
9670 let COMPACT_UNIFORMLY_EQUICONTINUOUS = prove
9671  (`!(fs:(real^M->real^N)->bool) s.
9672      (!x e. x IN s /\ &0 < e
9673             ==> ?d. &0 < d /\
9674                     (!f x'. f IN fs /\ x' IN s /\ dist (x',x) < d
9675                             ==> dist (f x',f x) < e)) /\
9676      compact s
9677      ==> !e. &0 < e
9678              ==> ?d. &0 < d /\
9679                      !f x x'. f IN fs /\ x IN s /\ x' IN s /\ dist (x',x) < d
9680                               ==> dist(f x',f x) < e`,
9681   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
9682   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
9683   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
9684   X_GEN_TAC `d:real^M->real->real` THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN
9685   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP HEINE_BOREL_LEMMA) THEN
9686   DISCH_THEN(MP_TAC o SPEC
9687     `{ ball(x:real^M,d x (e / &2)) | x IN s}`) THEN
9688   SIMP_TAC[FORALL_IN_GSPEC; OPEN_BALL; UNIONS_GSPEC; SUBSET; IN_ELIM_THM] THEN
9689   ANTS_TAC THENL [ASM_MESON_TAC[CENTRE_IN_BALL; REAL_HALF]; ALL_TAC] THEN
9690   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `k:real` THEN STRIP_TAC THEN
9691   ASM_REWRITE_TAC[] THEN
9692   MAP_EVERY X_GEN_TAC [`f:real^M->real^N`; `u:real^M`; `v:real^M`] THEN
9693   STRIP_TAC THEN FIRST_X_ASSUM(fun th -> MP_TAC(SPEC `v:real^M` th) THEN
9694     ASM_REWRITE_TAC[] THEN DISCH_THEN(CHOOSE_THEN MP_TAC)) THEN
9695   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9696   DISCH_THEN(fun th ->
9697     MP_TAC(SPEC `u:real^M` th) THEN MP_TAC(SPEC `v:real^M` th)) THEN
9698   ASM_REWRITE_TAC[DIST_REFL] THEN
9699   FIRST_X_ASSUM(X_CHOOSE_THEN `w:real^M` (CONJUNCTS_THEN2 ASSUME_TAC
9700     SUBST_ALL_TAC)) THEN
9701   ASM_REWRITE_TAC[CENTRE_IN_BALL] THEN ASM_REWRITE_TAC[IN_BALL] THEN
9702   ONCE_REWRITE_TAC[DIST_SYM] THEN REPEAT STRIP_TAC THEN
9703   FIRST_X_ASSUM(MP_TAC o SPECL [`w:real^M`; `e / &2`]) THEN
9704   ASM_REWRITE_TAC[REAL_HALF] THEN
9705   DISCH_THEN(MP_TAC o SPEC `f:real^M->real^N` o CONJUNCT2) THEN
9706   DISCH_THEN(fun th -> MP_TAC(SPEC `u:real^M` th) THEN
9707                         MP_TAC(SPEC `v:real^M` th)) THEN
9708   ASM_REWRITE_TAC[] THEN CONV_TAC NORM_ARITH);;
9709
9710 let COMPACT_UNIFORMLY_CONTINUOUS = prove
9711  (`!f:real^M->real^N s.
9712         f continuous_on s /\ compact s ==> f uniformly_continuous_on s`,
9713   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_on; uniformly_continuous_on] THEN
9714   STRIP_TAC THEN
9715   MP_TAC(ISPECL [`{f:real^M->real^N}`; `s:real^M->bool`]
9716         COMPACT_UNIFORMLY_EQUICONTINUOUS) THEN
9717   REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ; IN_SING; FORALL_UNWIND_THM2] THEN
9718   ASM_MESON_TAC[]);;
9719
9720 (* ------------------------------------------------------------------------- *)
9721 (* A uniformly convergent limit of continuous functions is continuous.       *)
9722 (* ------------------------------------------------------------------------- *)
9723
9724 let CONTINUOUS_UNIFORM_LIMIT = prove
9725  (`!net f:A->real^M->real^N g s.
9726         ~(trivial_limit net) /\
9727         eventually (\n. (f n) continuous_on s) net /\
9728         (!e. &0 < e
9729              ==> eventually (\n. !x. x IN s ==> norm(f n x - g x) < e) net)
9730         ==> g continuous_on s`,
9731   REWRITE_TAC[continuous_on] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
9732   X_GEN_TAC `x:real^M` THEN STRIP_TAC THEN
9733   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
9734   FIRST_X_ASSUM(MP_TAC o SPEC `e / &3`) THEN
9735   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
9736   FIRST_X_ASSUM(fun th -> MP_TAC th THEN REWRITE_TAC[IMP_IMP] THEN
9737         GEN_REWRITE_TAC LAND_CONV [GSYM EVENTUALLY_AND]) THEN
9738   DISCH_THEN(MP_TAC o MATCH_MP EVENTUALLY_HAPPENS) THEN
9739   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `a:A` THEN
9740   DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o SPEC `x:real^M`) ASSUME_TAC) THEN
9741   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
9742   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
9743   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN
9744   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
9745   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `y:real^M` THEN
9746   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
9747   FIRST_X_ASSUM(fun th ->
9748    MP_TAC(SPEC `x:real^M` th) THEN MP_TAC(SPEC `y:real^M` th)) THEN
9749   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(REAL_ARITH
9750    `w <= x + y + z
9751     ==> x < e / &3 ==> y < e / &3 ==> z < e / &3 ==> w < e`) THEN
9752   REWRITE_TAC[dist] THEN
9753   SUBST1_TAC(VECTOR_ARITH
9754    `(g:real^M->real^N) y - g x =
9755     --(f (a:A) y - g y) + (f a x - g x) + (f a y - f a x)`) THEN
9756   MATCH_MP_TAC NORM_TRIANGLE_LE THEN REWRITE_TAC[NORM_NEG; REAL_LE_LADD] THEN
9757   MATCH_MP_TAC NORM_TRIANGLE_LE THEN REWRITE_TAC[NORM_NEG; REAL_LE_REFL]);;
9758
9759 (* ------------------------------------------------------------------------- *)
9760 (* Topological stuff lifted from and dropped to R                            *)
9761 (* ------------------------------------------------------------------------- *)
9762
9763 let OPEN_LIFT = prove
9764  (`!s. open(IMAGE lift s) <=>
9765         !x. x IN s ==> ?e. &0 < e /\ !x'. abs(x' - x) < e ==> x' IN s`,
9766   REWRITE_TAC[open_def; FORALL_LIFT; LIFT_IN_IMAGE_LIFT; DIST_LIFT]);;
9767
9768 let LIMPT_APPROACHABLE_LIFT = prove
9769  (`!x s. (lift x) limit_point_of (IMAGE lift s) <=>
9770          !e. &0 < e ==> ?x'. x' IN s /\ ~(x' = x) /\ abs(x' - x) < e`,
9771   REWRITE_TAC[LIMPT_APPROACHABLE; EXISTS_LIFT; LIFT_IN_IMAGE_LIFT;
9772               LIFT_EQ; DIST_LIFT]);;
9773
9774 let CLOSED_LIFT = prove
9775  (`!s. closed (IMAGE lift s) <=>
9776         !x. (!e. &0 < e ==> ?x'. x' IN s /\ ~(x' = x) /\ abs(x' - x) < e)
9777             ==> x IN s`,
9778   GEN_TAC THEN REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE] THEN
9779   ONCE_REWRITE_TAC[FORALL_LIFT] THEN
9780   REWRITE_TAC[LIMPT_APPROACHABLE_LIFT; LIFT_EQ; DIST_LIFT;
9781               EXISTS_LIFT; LIFT_IN_IMAGE_LIFT]);;
9782
9783 let CONTINUOUS_AT_LIFT_RANGE = prove
9784  (`!f x. (lift o f) continuous (at x) <=>
9785                 !e. &0 < e
9786                     ==> ?d. &0 < d /\
9787                             (!x'. norm(x' - x) < d
9788                                   ==> abs(f x' - f x) < e)`,
9789   REWRITE_TAC[continuous_at; o_THM; DIST_LIFT] THEN REWRITE_TAC[dist]);;
9790
9791 let CONTINUOUS_ON_LIFT_RANGE = prove
9792  (`!f s. (lift o f) continuous_on s <=>
9793          !x. x IN s
9794              ==> !e. &0 < e
9795                      ==> ?d. &0 < d /\
9796                              (!x'. x' IN s /\ norm(x' - x) < d
9797                                    ==> abs(f x' - f x) < e)`,
9798   REWRITE_TAC[continuous_on; o_THM; DIST_LIFT] THEN REWRITE_TAC[dist]);;
9799
9800 let CONTINUOUS_LIFT_NORM_COMPOSE = prove
9801  (`!net f:A->real^N.
9802         f continuous net
9803         ==> (\x. lift(norm(f x))) continuous net`,
9804   REPEAT GEN_TAC THEN REWRITE_TAC[continuous; tendsto] THEN
9805   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
9806   REWRITE_TAC[] THEN
9807   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
9808   REWRITE_TAC[DIST_REAL; GSYM drop; LIFT_DROP] THEN
9809   NORM_ARITH_TAC);;
9810
9811 let CONTINUOUS_ON_LIFT_NORM_COMPOSE = prove
9812  (`!f:real^M->real^N s.
9813         f continuous_on s
9814         ==> (\x. lift(norm(f x))) continuous_on s`,
9815   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_LIFT_NORM_COMPOSE]);;
9816
9817 let CONTINUOUS_AT_LIFT_NORM = prove
9818  (`!x. (lift o norm) continuous (at x)`,
9819   REWRITE_TAC[CONTINUOUS_AT_LIFT_RANGE; NORM_LIFT] THEN
9820   MESON_TAC[REAL_ABS_SUB_NORM; REAL_LET_TRANS]);;
9821
9822 let CONTINUOUS_ON_LIFT_NORM = prove
9823  (`!s. (lift o norm) continuous_on s`,
9824   REWRITE_TAC[CONTINUOUS_ON_LIFT_RANGE; NORM_LIFT] THEN
9825   MESON_TAC[REAL_ABS_SUB_NORM; REAL_LET_TRANS]);;
9826
9827 let CONTINUOUS_AT_LIFT_COMPONENT = prove
9828  (`!i a. 1 <= i /\ i <= dimindex(:N)
9829          ==> (\x:real^N. lift(x$i)) continuous (at a)`,
9830   SIMP_TAC[continuous_at; DIST_LIFT; GSYM VECTOR_SUB_COMPONENT] THEN
9831   MESON_TAC[dist; REAL_LET_TRANS; COMPONENT_LE_NORM]);;
9832
9833 let CONTINUOUS_ON_LIFT_COMPONENT = prove
9834  (`!i s. 1 <= i /\ i <= dimindex(:N)
9835          ==> (\x:real^N. lift(x$i)) continuous_on s`,
9836   SIMP_TAC[continuous_on; DIST_LIFT; GSYM VECTOR_SUB_COMPONENT] THEN
9837   MESON_TAC[dist; REAL_LET_TRANS; COMPONENT_LE_NORM]);;
9838
9839 let CONTINUOUS_AT_LIFT_INFNORM = prove
9840  (`!x:real^N. (lift o infnorm) continuous (at x)`,
9841   REWRITE_TAC[CONTINUOUS_AT; LIM_AT; o_THM; DIST_LIFT] THEN
9842   MESON_TAC[REAL_LET_TRANS; dist; REAL_ABS_SUB_INFNORM; INFNORM_LE_NORM]);;
9843
9844 let CONTINUOUS_AT_LIFT_DIST = prove
9845  (`!a:real^N x. (lift o (\x. dist(a,x))) continuous (at x)`,
9846   REWRITE_TAC[CONTINUOUS_AT_LIFT_RANGE] THEN
9847   MESON_TAC[NORM_ARITH `abs(dist(a:real^N,x) - dist(a,y)) <= norm(x - y)`;
9848             REAL_LET_TRANS]);;
9849
9850 let CONTINUOUS_ON_LIFT_DIST = prove
9851  (`!a s. (lift o (\x. dist(a,x))) continuous_on s`,
9852   REWRITE_TAC[CONTINUOUS_ON_LIFT_RANGE] THEN
9853   MESON_TAC[NORM_ARITH `abs(dist(a:real^N,x) - dist(a,y)) <= norm(x - y)`;
9854             REAL_LET_TRANS]);;
9855
9856 (* ------------------------------------------------------------------------- *)
9857 (* Hence some handy theorems on distance, diameter etc. of/from a set.       *)
9858 (* ------------------------------------------------------------------------- *)
9859
9860 let COMPACT_ATTAINS_SUP = prove
9861  (`!s. compact (IMAGE lift s) /\ ~(s = {})
9862        ==> ?x. x IN s /\ !y. y IN s ==> y <= x`,
9863   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN REPEAT STRIP_TAC THEN
9864   MP_TAC(SPEC `s:real->bool` BOUNDED_HAS_SUP) THEN ASM_REWRITE_TAC[] THEN
9865   STRIP_TAC THEN EXISTS_TAC `sup s` THEN ASM_REWRITE_TAC[] THEN
9866   ASM_MESON_TAC[CLOSED_LIFT; REAL_ARITH `s <= s - e <=> ~(&0 < e)`;
9867                 REAL_ARITH `x <= s /\ ~(x <= s - e) ==> abs(x - s) < e`]);;
9868
9869 let COMPACT_ATTAINS_INF = prove
9870  (`!s. compact (IMAGE lift s) /\ ~(s = {})
9871        ==> ?x. x IN s /\ !y. y IN s ==> x <= y`,
9872   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN REPEAT STRIP_TAC THEN
9873   MP_TAC(SPEC `s:real->bool` BOUNDED_HAS_INF) THEN ASM_REWRITE_TAC[] THEN
9874   STRIP_TAC THEN EXISTS_TAC `inf s` THEN ASM_REWRITE_TAC[] THEN
9875   ASM_MESON_TAC[CLOSED_LIFT; REAL_ARITH `s + e <= s <=> ~(&0 < e)`;
9876                 REAL_ARITH `s <= x /\ ~(s + e <= x) ==> abs(x - s) < e`]);;
9877
9878 let CONTINUOUS_ATTAINS_SUP = prove
9879  (`!f:real^N->real s.
9880         compact s /\ ~(s = {}) /\ (lift o f) continuous_on s
9881         ==> ?x. x IN s /\ !y. y IN s ==> f(y) <= f(x)`,
9882   REPEAT STRIP_TAC THEN
9883   MP_TAC(SPEC `IMAGE (f:real^N->real) s` COMPACT_ATTAINS_SUP) THEN
9884   ASM_SIMP_TAC[GSYM IMAGE_o; COMPACT_CONTINUOUS_IMAGE; IMAGE_EQ_EMPTY] THEN
9885   MESON_TAC[IN_IMAGE]);;
9886
9887 let CONTINUOUS_ATTAINS_INF = prove
9888  (`!f:real^N->real s.
9889         compact s /\ ~(s = {}) /\ (lift o f) continuous_on s
9890         ==> ?x. x IN s /\ !y. y IN s ==> f(x) <= f(y)`,
9891   REPEAT STRIP_TAC THEN
9892   MP_TAC(SPEC `IMAGE (f:real^N->real) s` COMPACT_ATTAINS_INF) THEN
9893   ASM_SIMP_TAC[GSYM IMAGE_o; COMPACT_CONTINUOUS_IMAGE; IMAGE_EQ_EMPTY] THEN
9894   MESON_TAC[IN_IMAGE]);;
9895
9896 let DISTANCE_ATTAINS_SUP = prove
9897  (`!s a. compact s /\ ~(s = {})
9898          ==> ?x. x IN s /\ !y. y IN s ==> dist(a,y) <= dist(a,x)`,
9899   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ATTAINS_SUP THEN
9900   ASM_REWRITE_TAC[CONTINUOUS_ON_LIFT_RANGE] THEN REWRITE_TAC[dist] THEN
9901   ASM_MESON_TAC[REAL_LET_TRANS; REAL_ABS_SUB_NORM; NORM_NEG;
9902                 VECTOR_ARITH `(a - x) - (a - y) = --(x - y):real^N`]);;
9903
9904 (* ------------------------------------------------------------------------- *)
9905 (* For *minimal* distance, we only need closure, not compactness.            *)
9906 (* ------------------------------------------------------------------------- *)
9907
9908 let DISTANCE_ATTAINS_INF = prove
9909  (`!s a:real^N.
9910         closed s /\ ~(s = {})
9911         ==> ?x. x IN s /\ !y. y IN s ==> dist(a,x) <= dist(a,y)`,
9912   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
9913   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
9914   DISCH_THEN(X_CHOOSE_TAC `b:real^N`) THEN
9915   MP_TAC(ISPECL [`\x:real^N. dist(a,x)`; `cball(a:real^N,dist(b,a)) INTER s`]
9916                 CONTINUOUS_ATTAINS_INF) THEN
9917   ANTS_TAC THENL
9918    [ASM_SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_INTER; BOUNDED_INTER;
9919                  BOUNDED_CBALL; CLOSED_CBALL; GSYM MEMBER_NOT_EMPTY] THEN
9920     REWRITE_TAC[dist; CONTINUOUS_ON_LIFT_RANGE; IN_INTER; IN_CBALL] THEN
9921     ASM_MESON_TAC[REAL_LET_TRANS; REAL_ABS_SUB_NORM; NORM_NEG; REAL_LE_REFL;
9922             NORM_SUB; VECTOR_ARITH `(a - x) - (a - y) = --(x - y):real^N`];
9923     MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[IN_INTER; IN_CBALL] THEN
9924     ASM_MESON_TAC[DIST_SYM; REAL_LE_TOTAL; REAL_LE_TRANS]]);;
9925
9926 (* ------------------------------------------------------------------------- *)
9927 (* We can now extend limit compositions to consider the scalar multiplier.   *)
9928 (* ------------------------------------------------------------------------- *)
9929
9930 let LIM_MUL = prove
9931  (`!net:(A)net f l:real^N c d.
9932         ((lift o c) --> lift d) net /\ (f --> l) net
9933         ==> ((\x. c(x) % f(x)) --> (d % l)) net`,
9934   REPEAT STRIP_TAC THEN
9935   MP_TAC(ISPECL [`net:(A)net`; `\x (y:real^N). drop x % y`;
9936   `lift o (c:A->real)`; `f:A->real^N`; `lift d`; `l:real^N`] LIM_BILINEAR) THEN
9937   ASM_REWRITE_TAC[LIFT_DROP; o_THM] THEN DISCH_THEN MATCH_MP_TAC THEN
9938   REWRITE_TAC[bilinear; linear; DROP_ADD; DROP_CMUL] THEN
9939   REPEAT STRIP_TAC THEN VECTOR_ARITH_TAC);;
9940
9941 let LIM_VMUL = prove
9942  (`!net:(A)net c d v:real^N.
9943         ((lift o c) --> lift d) net ==> ((\x. c(x) % v) --> d % v) net`,
9944   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_MUL THEN ASM_REWRITE_TAC[LIM_CONST]);;
9945
9946 let CONTINUOUS_VMUL = prove
9947  (`!net c v. (lift o c) continuous net ==> (\x. c(x) % v) continuous net`,
9948   REWRITE_TAC[continuous; LIM_VMUL; o_THM]);;
9949
9950 let CONTINUOUS_MUL = prove
9951  (`!net f c. (lift o c) continuous net /\ f continuous net
9952              ==> (\x. c(x) % f(x)) continuous net`,
9953   REWRITE_TAC[continuous; LIM_MUL; o_THM]);;
9954
9955 let CONTINUOUS_ON_VMUL = prove
9956  (`!s c v. (lift o c) continuous_on s ==> (\x. c(x) % v) continuous_on s`,
9957   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
9958   SIMP_TAC[CONTINUOUS_VMUL]);;
9959
9960 let CONTINUOUS_ON_MUL = prove
9961  (`!s c f. (lift o c) continuous_on s /\ f continuous_on s
9962            ==> (\x. c(x) % f(x)) continuous_on s`,
9963   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
9964   SIMP_TAC[CONTINUOUS_MUL]);;
9965
9966 let CONTINUOUS_LIFT_POW = prove
9967  (`!net f:A->real n.
9968         (\x. lift(f x)) continuous net
9969         ==> (\x. lift(f x pow n)) continuous net`,
9970   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN
9971   INDUCT_TAC THEN ASM_REWRITE_TAC[LIFT_CMUL; real_pow; CONTINUOUS_CONST] THEN
9972   MATCH_MP_TAC CONTINUOUS_MUL THEN ASM_REWRITE_TAC[o_DEF]);;
9973
9974 let CONTINUOUS_ON_LIFT_POW = prove
9975  (`!f:real^N->real s n.
9976         (\x. lift(f x)) continuous_on s
9977         ==> (\x. lift(f x pow n)) continuous_on s`,
9978   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN REPEAT GEN_TAC THEN
9979   DISCH_TAC THEN INDUCT_TAC THEN
9980   ASM_REWRITE_TAC[LIFT_CMUL; real_pow; CONTINUOUS_ON_CONST] THEN
9981   MATCH_MP_TAC CONTINUOUS_ON_MUL THEN ASM_REWRITE_TAC[o_DEF]);;
9982
9983 let CONTINUOUS_LIFT_PRODUCT = prove
9984  (`!net:(A)net f (t:B->bool).
9985         FINITE t /\
9986         (!i. i IN t ==> (\x. lift(f x i)) continuous net)
9987         ==> (\x. lift(product t (f x))) continuous net`,
9988   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
9989   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN SIMP_TAC[PRODUCT_CLAUSES] THEN
9990   REWRITE_TAC[CONTINUOUS_CONST; LIFT_CMUL; FORALL_IN_INSERT] THEN
9991   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
9992   ASM_SIMP_TAC[o_DEF]);;
9993
9994 let CONTINUOUS_ON_LIFT_PRODUCT = prove
9995  (`!f:real^N->A->real s t.
9996         FINITE t /\
9997
9998         (!i. i IN t ==> (\x. lift(f x i)) continuous_on s)
9999         ==> (\x. lift(product t (f x))) continuous_on s`,
10000   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_LIFT_PRODUCT]);;
10001
10002 (* ------------------------------------------------------------------------- *)
10003 (* And so we have continuity of inverse.                                     *)
10004 (* ------------------------------------------------------------------------- *)
10005
10006 let LIM_INV = prove
10007  (`!net:(A)net f l.
10008         ((lift o f) --> lift l) net /\ ~(l = &0)
10009         ==> ((lift o inv o f) --> lift(inv l)) net`,
10010   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
10011   ASM_CASES_TAC `trivial_limit(net:(A)net)` THEN ASM_REWRITE_TAC[] THEN
10012   REWRITE_TAC[o_THM; DIST_LIFT] THEN STRIP_TAC THEN
10013   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
10014   FIRST_X_ASSUM(MP_TAC o SPEC `min (abs(l) / &2) ((l pow 2 * e) / &2)`) THEN
10015   REWRITE_TAC[REAL_LT_MIN] THEN ANTS_TAC THENL
10016    [ASM_SIMP_TAC[GSYM REAL_ABS_NZ; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
10017     MATCH_MP_TAC REAL_LT_DIV THEN REWRITE_TAC[REAL_OF_NUM_LT; ARITH] THEN
10018     ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN
10019     ASM_SIMP_TAC[REAL_LT_MUL; GSYM REAL_ABS_NZ; REAL_POW_LT];
10020     ALL_TAC] THEN
10021   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:A` THEN
10022   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
10023   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `b:A` THEN
10024   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
10025   SIMP_TAC[REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN STRIP_TAC THEN
10026   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REAL_ARITH
10027    `abs(x - l) * &2 < abs l ==> ~(x = &0)`)) THEN
10028   ASM_SIMP_TAC[REAL_SUB_INV; REAL_ABS_DIV; REAL_LT_LDIV_EQ;
10029                GSYM REAL_ABS_NZ; REAL_ENTIRE] THEN
10030   FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
10031    `abs(x - y) * &2 < b * c ==> c * b <= d * &2 ==> abs(y - x) < d`)) THEN
10032   ASM_SIMP_TAC[GSYM REAL_MUL_ASSOC; REAL_LE_LMUL_EQ] THEN
10033   ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
10034   ASM_SIMP_TAC[REAL_ABS_MUL; REAL_POW_2; REAL_MUL_ASSOC; GSYM REAL_ABS_NZ;
10035                REAL_LE_RMUL_EQ] THEN
10036   ASM_SIMP_TAC[REAL_ARITH `abs(x - y) * &2 < abs y ==> abs y <= &2 * abs x`]);;
10037
10038 let CONTINUOUS_INV = prove
10039  (`!net f. (lift o f) continuous net /\ ~(f(netlimit net) = &0)
10040            ==> (lift o inv o f) continuous net`,
10041   REWRITE_TAC[continuous; LIM_INV; o_THM]);;
10042
10043 let CONTINUOUS_AT_WITHIN_INV = prove
10044  (`!f s a:real^N.
10045         (lift o f) continuous (at a within s) /\ ~(f a = &0)
10046         ==> (lift o inv o f) continuous (at a within s)`,
10047   REPEAT GEN_TAC THEN
10048   ASM_CASES_TAC `trivial_limit (at (a:real^N) within s)` THENL
10049    [ASM_REWRITE_TAC[continuous; LIM];
10050     ASM_SIMP_TAC[NETLIMIT_WITHIN; CONTINUOUS_INV]]);;
10051
10052 let CONTINUOUS_AT_INV = prove
10053  (`!f a. (lift o f) continuous at a /\ ~(f a = &0)
10054          ==> (lift o inv o f) continuous at a`,
10055   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
10056   REWRITE_TAC[CONTINUOUS_AT_WITHIN_INV]);;
10057
10058 let CONTINUOUS_ON_INV = prove
10059  (`!f s. (lift o f) continuous_on s /\ (!x. x IN s ==> ~(f x = &0))
10060          ==> (lift o inv o f) continuous_on s`,
10061   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_AT_WITHIN_INV]);;
10062
10063 (* ------------------------------------------------------------------------- *)
10064 (* More preservation properties for pasted sets (Cartesian products).        *)
10065 (* ------------------------------------------------------------------------- *)
10066
10067 let LIM_PASTECART = prove
10068  (`!net f:A->real^M g:A->real^N.
10069         (f --> a) net /\ (g --> b) net
10070         ==> ((\x. pastecart (f x) (g x)) --> pastecart a b) net`,
10071   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
10072   ASM_CASES_TAC `trivial_limit(net:(A)net)` THEN ASM_REWRITE_TAC[] THEN
10073   REWRITE_TAC[AND_FORALL_THM] THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN
10074   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
10075   ASM_REWRITE_TAC[REAL_HALF] THEN
10076   DISCH_THEN(MP_TAC o MATCH_MP NET_DILEMMA) THEN
10077   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_AND THEN
10078   REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
10079   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
10080   REWRITE_TAC[dist; PASTECART_SUB] THEN
10081   MATCH_MP_TAC(REAL_ARITH
10082     `z <= x + y ==> x < e / &2 /\ y < e / &2 ==> z < e`) THEN
10083   REWRITE_TAC[NORM_PASTECART_LE]);;
10084
10085 let LIM_PASTECART_EQ = prove
10086  (`!net f:A->real^M g:A->real^N.
10087         ((\x. pastecart (f x) (g x)) --> pastecart a b) net <=>
10088         (f --> a) net /\ (g --> b) net`,
10089   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[LIM_PASTECART] THEN
10090   REPEAT STRIP_TAC THENL
10091    [FIRST_ASSUM(MP_TAC o ISPEC `fstcart:real^(M,N)finite_sum->real^M` o
10092         MATCH_MP (REWRITE_RULE[IMP_CONJ] LIM_LINEAR)) THEN
10093     REWRITE_TAC[LINEAR_FSTCART; FSTCART_PASTECART; ETA_AX];
10094     FIRST_ASSUM(MP_TAC o ISPEC `sndcart:real^(M,N)finite_sum->real^N` o
10095         MATCH_MP (REWRITE_RULE[IMP_CONJ] LIM_LINEAR)) THEN
10096     REWRITE_TAC[LINEAR_SNDCART; SNDCART_PASTECART; ETA_AX]]);;
10097
10098 let CONTINUOUS_PASTECART = prove
10099  (`!net f:A->real^M g:A->real^N.
10100         f continuous net /\ g continuous net
10101         ==> (\x. pastecart (f x) (g x)) continuous net`,
10102   REWRITE_TAC[continuous; LIM_PASTECART]);;
10103
10104 let CONTINUOUS_ON_PASTECART = prove
10105  (`!f:real^M->real^N g:real^M->real^P s.
10106         f continuous_on s /\ g continuous_on s
10107         ==> (\x. pastecart (f x) (g x)) continuous_on s`,
10108   SIMP_TAC[CONTINUOUS_ON; LIM_PASTECART]);;
10109
10110 let CONNECTED_PCROSS = prove
10111  (`!s:real^M->bool t:real^N->bool.
10112         connected s /\ connected t
10113         ==> connected (s PCROSS t)`,
10114   REPEAT GEN_TAC THEN
10115   REWRITE_TAC[PCROSS; CONNECTED_IFF_CONNECTED_COMPONENT] THEN
10116   DISCH_TAC THEN REWRITE_TAC[FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
10117   MAP_EVERY X_GEN_TAC [`x1:real^M`; `y1:real^N`; `x2:real^M`; `y2:real^N`] THEN
10118   STRIP_TAC THEN FIRST_X_ASSUM(CONJUNCTS_THEN2
10119    (MP_TAC o SPECL [`x1:real^M`; `x2:real^M`])
10120    (MP_TAC o SPECL [`y1:real^N`; `y2:real^N`])) THEN
10121   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; connected_component] THEN
10122   X_GEN_TAC `c2:real^N->bool` THEN STRIP_TAC THEN
10123   X_GEN_TAC `c1:real^M->bool` THEN STRIP_TAC THEN
10124   EXISTS_TAC
10125    `IMAGE (\x:real^M. pastecart x y1) c1 UNION
10126     IMAGE (\y:real^N. pastecart x2 y) c2` THEN
10127   REWRITE_TAC[IN_UNION] THEN REPEAT CONJ_TAC THENL
10128    [MATCH_MP_TAC CONNECTED_UNION THEN
10129     ASM_SIMP_TAC[CONNECTED_CONTINUOUS_IMAGE; CONTINUOUS_ON_PASTECART;
10130                  CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN
10131     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER; EXISTS_IN_IMAGE] THEN
10132     EXISTS_TAC `x2:real^M` THEN ASM SET_TAC[];
10133     REWRITE_TAC[SUBSET; IN_UNION; FORALL_AND_THM; FORALL_IN_IMAGE;
10134                 TAUT `a \/ b ==> c <=> (a ==> c) /\ (b ==> c)`] THEN
10135     ASM SET_TAC[];
10136     ASM SET_TAC[];
10137     ASM SET_TAC[]]);;
10138
10139 let CONNECTED_PCROSS_EQ = prove
10140  (`!s:real^M->bool t:real^N->bool.
10141         connected (s PCROSS t) <=>
10142         s = {} \/ t = {} \/ connected s /\ connected t`,
10143   REPEAT GEN_TAC THEN
10144   ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
10145   ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
10146   REWRITE_TAC[PCROSS_EMPTY; CONNECTED_EMPTY] THEN
10147   EQ_TAC THEN SIMP_TAC[CONNECTED_PCROSS] THEN
10148   REWRITE_TAC[PCROSS] THEN REPEAT STRIP_TAC THENL
10149    [SUBGOAL_THEN `connected (IMAGE fstcart
10150                      {pastecart (x:real^M) (y:real^N) | x IN s /\ y IN t})`
10151     MP_TAC THENL [MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE; ALL_TAC];
10152     SUBGOAL_THEN `connected (IMAGE sndcart
10153                      {pastecart (x:real^M) (y:real^N) | x IN s /\ y IN t})`
10154     MP_TAC THENL [MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE; ALL_TAC]] THEN
10155   ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART; LINEAR_SNDCART] THEN
10156   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
10157   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; IN_ELIM_PASTECART_THM;
10158               FSTCART_PASTECART; SNDCART_PASTECART] THEN
10159   ASM SET_TAC[]);;
10160
10161 let CLOSURE_PCROSS = prove
10162  (`!s:real^M->bool t:real^N->bool.
10163         closure (s PCROSS t) = (closure s) PCROSS (closure t)`,
10164   REWRITE_TAC[EXTENSION; PCROSS; FORALL_PASTECART] THEN REPEAT GEN_TAC THEN
10165   REWRITE_TAC[CLOSURE_APPROACHABLE; EXISTS_PASTECART; FORALL_PASTECART] THEN
10166   REWRITE_TAC[IN_ELIM_PASTECART_THM; PASTECART_INJ] THEN
10167   REWRITE_TAC[FSTCART_PASTECART; SNDCART_PASTECART] THEN
10168   REWRITE_TAC[dist; PASTECART_SUB] THEN EQ_TAC THENL
10169    [MESON_TAC[NORM_LE_PASTECART; REAL_LET_TRANS]; DISCH_TAC] THEN
10170   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
10171   FIRST_X_ASSUM(CONJUNCTS_THEN (MP_TAC o SPEC `e / &2`)) THEN
10172   ASM_MESON_TAC[REAL_HALF; NORM_PASTECART_LE; REAL_ARITH
10173     `z <= x + y /\ x < e / &2 /\ y < e / &2 ==> z < e`]);;
10174
10175 let LIMPT_PCROSS = prove
10176  (`!s:real^M->bool t:real^N->bool x y.
10177         x limit_point_of s /\ y limit_point_of t
10178         ==> (pastecart x y) limit_point_of (s PCROSS t)`,
10179   REPEAT GEN_TAC THEN
10180   REWRITE_TAC[PCROSS; LIMPT_APPROACHABLE; EXISTS_PASTECART] THEN
10181   REWRITE_TAC[IN_ELIM_PASTECART_THM; PASTECART_INJ; dist; PASTECART_SUB] THEN
10182   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
10183   FIRST_X_ASSUM(CONJUNCTS_THEN (MP_TAC o SPEC `e / &2`)) THEN
10184   ASM_MESON_TAC[REAL_HALF; NORM_PASTECART_LE; REAL_ARITH
10185     `z <= x + y /\ x < e / &2 /\ y < e / &2 ==> z < e`]);;
10186
10187 let CLOSED_IN_PCROSS = prove
10188  (`!s:real^M->bool s' t:real^N->bool t'.
10189         closed_in (subtopology euclidean s) s' /\
10190         closed_in (subtopology euclidean t) t'
10191         ==> closed_in (subtopology euclidean (s PCROSS t)) (s' PCROSS t')`,
10192   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN_CLOSED] THEN
10193   DISCH_THEN(CONJUNCTS_THEN2
10194    (X_CHOOSE_THEN `s'':real^M->bool` STRIP_ASSUME_TAC)
10195    (X_CHOOSE_THEN `t'':real^N->bool` STRIP_ASSUME_TAC)) THEN
10196   EXISTS_TAC `(s'':real^M->bool) PCROSS (t'':real^N->bool)` THEN
10197   ASM_SIMP_TAC[CLOSED_PCROSS; EXTENSION; FORALL_PASTECART] THEN
10198   REWRITE_TAC[IN_INTER; PASTECART_IN_PCROSS] THEN ASM SET_TAC[]);;
10199
10200 let CLOSED_IN_PCROSS_EQ = prove
10201  (`!s s':real^M->bool t t':real^N->bool.
10202         closed_in (subtopology euclidean (s PCROSS t)) (s' PCROSS t') <=>
10203         s' = {} \/ t' = {} \/
10204         closed_in (subtopology euclidean s) s' /\
10205         closed_in (subtopology euclidean t) t'`,
10206   REPEAT GEN_TAC THEN
10207   ASM_CASES_TAC `s':real^M->bool = {}` THEN
10208   ASM_REWRITE_TAC[PCROSS_EMPTY; CLOSED_IN_EMPTY] THEN
10209   ASM_CASES_TAC `t':real^N->bool = {}` THEN
10210   ASM_REWRITE_TAC[PCROSS_EMPTY; CLOSED_IN_EMPTY] THEN
10211   EQ_TAC THEN REWRITE_TAC[CLOSED_IN_PCROSS] THEN
10212   ASM_REWRITE_TAC[CLOSED_IN_INTER_CLOSURE; CLOSURE_PCROSS; INTER_PCROSS;
10213                   PCROSS_EQ; PCROSS_EQ_EMPTY]);;
10214
10215 let FRONTIER_PCROSS = prove
10216  (`!s:real^M->bool t:real^N->bool.
10217         frontier(s PCROSS t) = frontier s PCROSS closure t UNION
10218                                closure s PCROSS frontier t`,
10219   REPEAT GEN_TAC THEN
10220   REWRITE_TAC[frontier; CLOSURE_PCROSS; INTERIOR_PCROSS; PCROSS_DIFF] THEN
10221   REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_DIFF; IN_UNION;
10222               PASTECART_IN_PCROSS] THEN
10223   ASM SET_TAC[]);;
10224
10225 (* ------------------------------------------------------------------------- *)
10226 (* Hence some useful properties follow quite easily.                         *)
10227 (* ------------------------------------------------------------------------- *)
10228
10229 let CONNECTED_SCALING = prove
10230  (`!s:real^N->bool c. connected s ==> connected (IMAGE (\x. c % x) s)`,
10231   REPEAT STRIP_TAC THEN
10232   MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
10233   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
10234   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
10235   REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
10236
10237 let CONNECTED_NEGATIONS = prove
10238  (`!s:real^N->bool. connected s ==> connected (IMAGE (--) s)`,
10239   REPEAT STRIP_TAC THEN
10240   MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
10241   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
10242   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
10243   REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
10244
10245 let CONNECTED_SUMS = prove
10246  (`!s t:real^N->bool.
10247         connected s /\ connected t ==> connected {x + y | x IN s /\ y IN t}`,
10248   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CONNECTED_PCROSS) THEN
10249   DISCH_THEN(MP_TAC o ISPEC
10250    `\z. (fstcart z + sndcart z:real^N)` o
10251     MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT] CONNECTED_CONTINUOUS_IMAGE)) THEN
10252   SIMP_TAC[CONTINUOUS_ON_ADD; LINEAR_CONTINUOUS_ON; LINEAR_FSTCART;
10253            LINEAR_SNDCART; PCROSS] THEN
10254   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
10255   REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM; EXISTS_PASTECART] THEN
10256   REWRITE_TAC[PASTECART_INJ; FSTCART_PASTECART; SNDCART_PASTECART] THEN
10257   MESON_TAC[]);;
10258
10259 let COMPACT_SCALING = prove
10260  (`!s:real^N->bool c. compact s ==> compact (IMAGE (\x. c % x) s)`,
10261   REPEAT STRIP_TAC THEN
10262   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
10263   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
10264   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
10265   REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
10266
10267 let COMPACT_NEGATIONS = prove
10268  (`!s:real^N->bool. compact s ==> compact (IMAGE (--) s)`,
10269   REPEAT STRIP_TAC THEN
10270   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
10271   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
10272   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
10273   REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
10274
10275 let COMPACT_SUMS = prove
10276  (`!s:real^N->bool t.
10277         compact s /\ compact t ==> compact {x + y | x IN s /\ y IN t}`,
10278   REPEAT STRIP_TAC THEN
10279   SUBGOAL_THEN `{x + y | x IN s /\ y IN t} =
10280                 IMAGE (\z. fstcart z + sndcart z :real^N) (s PCROSS t)`
10281   SUBST1_TAC THENL
10282    [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; PCROSS] THEN
10283     GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
10284     ASM_MESON_TAC[FSTCART_PASTECART; SNDCART_PASTECART; PASTECART_FST_SND];
10285     ALL_TAC] THEN
10286   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
10287   ASM_SIMP_TAC[COMPACT_PCROSS] THEN
10288   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
10289   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
10290   REWRITE_TAC[linear; FSTCART_ADD; FSTCART_CMUL; SNDCART_ADD;
10291               SNDCART_CMUL] THEN
10292   CONJ_TAC THEN VECTOR_ARITH_TAC);;
10293
10294 let COMPACT_DIFFERENCES = prove
10295  (`!s:real^N->bool t.
10296         compact s /\ compact t ==> compact {x - y | x IN s /\ y IN t}`,
10297   REPEAT STRIP_TAC THEN
10298   SUBGOAL_THEN `{x - y | x:real^N IN s /\ y IN t} =
10299                 {x + y | x IN s /\ y IN (IMAGE (--) t)}`
10300     (fun th -> ASM_SIMP_TAC[th; COMPACT_SUMS; COMPACT_NEGATIONS]) THEN
10301   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE] THEN
10302   ONCE_REWRITE_TAC[VECTOR_ARITH `(x:real^N = --y) <=> (y = --x)`] THEN
10303   SIMP_TAC[VECTOR_SUB; GSYM CONJ_ASSOC; UNWIND_THM2] THEN
10304   MESON_TAC[VECTOR_NEG_NEG]);;
10305
10306 let COMPACT_AFFINITY = prove
10307  (`!s a:real^N c.
10308         compact s ==> compact (IMAGE (\x. a + c % x) s)`,
10309   REPEAT STRIP_TAC THEN
10310   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
10311   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
10312   ASM_SIMP_TAC[IMAGE_o; COMPACT_TRANSLATION; COMPACT_SCALING]);;
10313
10314 (* ------------------------------------------------------------------------- *)
10315 (* Hence we get the following.                                               *)
10316 (* ------------------------------------------------------------------------- *)
10317
10318 let COMPACT_SUP_MAXDISTANCE = prove
10319  (`!s:real^N->bool.
10320         compact s /\ ~(s = {})
10321         ==> ?x y. x IN s /\ y IN s /\
10322                   !u v. u IN s /\ v IN s ==> norm(u - v) <= norm(x - y)`,
10323   REPEAT STRIP_TAC THEN
10324   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN s}`; `vec 0:real^N`]
10325                 DISTANCE_ATTAINS_SUP) THEN
10326   ANTS_TAC THENL
10327    [ASM_SIMP_TAC[COMPACT_DIFFERENCES] THEN
10328     REWRITE_TAC[EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY] THEN
10329     ASM_MESON_TAC[MEMBER_NOT_EMPTY];
10330     REWRITE_TAC[IN_ELIM_THM; dist; VECTOR_SUB_RZERO; VECTOR_SUB_LZERO;
10331                 NORM_NEG] THEN
10332     MESON_TAC[]]);;
10333
10334 (* ------------------------------------------------------------------------- *)
10335 (* We can state this in terms of diameter of a set.                          *)
10336 (* ------------------------------------------------------------------------- *)
10337
10338 let diameter = new_definition
10339   `diameter s =
10340         if s = {} then &0
10341         else sup {norm(x - y) | x IN s /\ y IN s}`;;
10342
10343 let DIAMETER_BOUNDED = prove
10344  (`!s. bounded s
10345        ==> (!x:real^N y. x IN s /\ y IN s ==> norm(x - y) <= diameter s) /\
10346            (!d. &0 <= d /\ d < diameter s
10347                 ==> ?x y. x IN s /\ y IN s /\ norm(x - y) > d)`,
10348   GEN_TAC THEN DISCH_TAC THEN
10349   ASM_CASES_TAC `s:real^N->bool = {}` THEN
10350   ASM_REWRITE_TAC[diameter; NOT_IN_EMPTY; REAL_LET_ANTISYM] THEN
10351   MP_TAC(SPEC `{norm(x - y:real^N) | x IN s /\ y IN s}` SUP) THEN
10352   ABBREV_TAC `b = sup {norm(x - y:real^N) | x IN s /\ y IN s}` THEN
10353   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
10354   REWRITE_TAC[NOT_IN_EMPTY; real_gt] THEN ANTS_TAC THENL
10355    [CONJ_TAC THENL [ASM_MESON_TAC[MEMBER_NOT_EMPTY]; ALL_TAC];
10356     MESON_TAC[REAL_NOT_LE]] THEN
10357   SIMP_TAC[VECTOR_SUB; LEFT_IMP_EXISTS_THM] THEN
10358   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [bounded]) THEN
10359   MESON_TAC[REAL_ARITH `x <= y + z /\ y <= b /\ z<= b ==> x <= b + b`;
10360             NORM_TRIANGLE; NORM_NEG]);;
10361
10362 let DIAMETER_BOUNDED_BOUND = prove
10363  (`!s x y. bounded s /\ x IN s /\ y IN s ==> norm(x - y) <= diameter s`,
10364   MESON_TAC[DIAMETER_BOUNDED]);;
10365
10366 let DIAMETER_COMPACT_ATTAINED = prove
10367  (`!s:real^N->bool.
10368         compact s /\ ~(s = {})
10369         ==> ?x y. x IN s /\ y IN s /\ (norm(x - y) = diameter s)`,
10370   GEN_TAC THEN DISCH_TAC THEN
10371   FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_SUP_MAXDISTANCE) THEN
10372   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
10373   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
10374   MP_TAC(SPEC `s:real^N->bool` DIAMETER_BOUNDED) THEN
10375   RULE_ASSUM_TAC(REWRITE_RULE[COMPACT_EQ_BOUNDED_CLOSED]) THEN
10376   ASM_REWRITE_TAC[real_gt] THEN STRIP_TAC THEN
10377   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
10378   ASM_MESON_TAC[NORM_POS_LE; REAL_NOT_LT]);;
10379
10380 let DIAMETER_TRANSLATION = prove
10381  (`!a s. diameter (IMAGE (\x. a + x) s) = diameter s`,
10382   REWRITE_TAC[diameter] THEN GEOM_TRANSLATE_TAC[]);;
10383
10384 add_translation_invariants [DIAMETER_TRANSLATION];;
10385
10386 let DIAMETER_LINEAR_IMAGE = prove
10387  (`!f:real^M->real^N s.
10388         linear f /\ (!x. norm(f x) = norm x)
10389         ==> diameter(IMAGE f s) = diameter s`,
10390   REWRITE_TAC[diameter] THEN
10391   REPEAT STRIP_TAC THEN REWRITE_TAC[diameter; IMAGE_EQ_EMPTY] THEN
10392   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN
10393   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
10394   REWRITE_TAC[GSYM CONJ_ASSOC; RIGHT_EXISTS_AND_THM; EXISTS_IN_IMAGE] THEN
10395   ASM_MESON_TAC[LINEAR_SUB]);;
10396
10397 add_linear_invariants [DIAMETER_LINEAR_IMAGE];;
10398
10399 let DIAMETER_EMPTY = prove
10400  (`diameter {} = &0`,
10401   REWRITE_TAC[diameter]);;
10402
10403 let DIAMETER_SING = prove
10404  (`!a. diameter {a} = &0`,
10405   REWRITE_TAC[diameter; NOT_INSERT_EMPTY; IN_SING] THEN
10406   REWRITE_TAC[SET_RULE `{f x y | x = a /\ y = a} = {f a a }`] THEN
10407   REWRITE_TAC[SUP_SING; VECTOR_SUB_REFL; NORM_0]);;
10408
10409 let DIAMETER_POS_LE = prove
10410  (`!s:real^N->bool. bounded s ==> &0 <= diameter s`,
10411   REPEAT STRIP_TAC THEN REWRITE_TAC[diameter] THEN
10412   COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_LE_REFL] THEN
10413   MP_TAC(SPEC `{norm(x - y:real^N) | x IN s /\ y IN s}` SUP) THEN
10414   REWRITE_TAC[FORALL_IN_GSPEC] THEN ANTS_TAC THENL
10415    [CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10416     FIRST_X_ASSUM(X_CHOOSE_TAC `B:real` o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
10417     EXISTS_TAC `&2 * B` THEN
10418     ASM_SIMP_TAC[NORM_ARITH
10419       `norm x <= B /\ norm y <= B ==> norm(x - y) <= &2 * B`];
10420     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
10421     DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
10422     DISCH_THEN(MP_TAC o SPECL [`a:real^N`; `a:real^N`] o CONJUNCT1) THEN
10423     ASM_REWRITE_TAC[VECTOR_SUB_REFL; NORM_0]]);;
10424
10425 let DIAMETER_SUBSET = prove
10426  (`!s t:real^N->bool. s SUBSET t /\ bounded t ==> diameter s <= diameter t`,
10427   REPEAT STRIP_TAC THEN
10428   ASM_CASES_TAC `s:real^N->bool = {}` THEN
10429   ASM_SIMP_TAC[DIAMETER_EMPTY; DIAMETER_POS_LE] THEN
10430   ASM_REWRITE_TAC[diameter] THEN
10431   COND_CASES_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10432   MATCH_MP_TAC REAL_SUP_LE_SUBSET THEN
10433   REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
10434   REWRITE_TAC[FORALL_IN_GSPEC] THEN
10435   FIRST_X_ASSUM(X_CHOOSE_TAC `B:real` o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
10436   EXISTS_TAC `&2 * B` THEN
10437   ASM_SIMP_TAC[NORM_ARITH
10438     `norm x <= B /\ norm y <= B ==> norm(x - y) <= &2 * B`]);;
10439
10440 let DIAMETER_CLOSURE = prove
10441  (`!s:real^N->bool. bounded s ==> diameter(closure s) = diameter s`,
10442   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN REPEAT STRIP_TAC THEN
10443   ASM_SIMP_TAC[DIAMETER_SUBSET; BOUNDED_CLOSURE; CLOSURE_SUBSET] THEN
10444   REWRITE_TAC[GSYM REAL_NOT_LT] THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
10445   DISCH_TAC THEN MP_TAC(ISPEC `closure s:real^N->bool` DIAMETER_BOUNDED) THEN
10446   ABBREV_TAC `d = diameter(closure s) - diameter(s:real^N->bool)` THEN
10447   ASM_SIMP_TAC[BOUNDED_CLOSURE] THEN DISCH_THEN(MP_TAC o
10448     SPEC `diameter(closure(s:real^N->bool)) - d / &2` o CONJUNCT2) THEN
10449   REWRITE_TAC[NOT_IMP; GSYM CONJ_ASSOC; NOT_EXISTS_THM] THEN
10450   FIRST_ASSUM(ASSUME_TAC o MATCH_MP DIAMETER_POS_LE) THEN
10451   REPEAT(CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
10452   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
10453   REWRITE_TAC[CLOSURE_APPROACHABLE; CONJ_ASSOC; AND_FORALL_THM] THEN
10454   DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o SPEC `d / &4`) ASSUME_TAC) THEN
10455   ASM_REWRITE_TAC[REAL_ARITH `&0 < d / &4 <=> &0 < d`] THEN
10456   DISCH_THEN(CONJUNCTS_THEN2
10457    (X_CHOOSE_THEN `u:real^N` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC))
10458    (X_CHOOSE_THEN `v:real^N` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC))) THEN
10459   FIRST_ASSUM(MP_TAC o MATCH_MP DIAMETER_BOUNDED) THEN
10460   DISCH_THEN(MP_TAC o SPECL [`u:real^N`; `v:real^N`] o CONJUNCT1) THEN
10461   ASM_REWRITE_TAC[] THEN REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
10462
10463 let DIAMETER_SUBSET_CBALL_NONEMPTY = prove
10464  (`!s:real^N->bool.
10465        bounded s /\ ~(s = {}) ==> ?z. z IN s /\ s SUBSET cball(z,diameter s)`,
10466    REPEAT STRIP_TAC THEN
10467    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
10468    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
10469    DISCH_TAC THEN ASM_REWRITE_TAC[SUBSET] THEN X_GEN_TAC `b:real^N` THEN
10470    DISCH_TAC THEN REWRITE_TAC[IN_CBALL; dist] THEN
10471    ASM_MESON_TAC[DIAMETER_BOUNDED]);;
10472
10473 let DIAMETER_SUBSET_CBALL = prove
10474  (`!s:real^N->bool. bounded s ==> ?z. s SUBSET cball(z,diameter s)`,
10475   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
10476   ASM_MESON_TAC[DIAMETER_SUBSET_CBALL_NONEMPTY; EMPTY_SUBSET]);;
10477
10478 let DIAMETER_EQ_0 = prove
10479  (`!s:real^N->bool.
10480         bounded s ==> (diameter s = &0 <=> s = {} \/ ?a. s = {a})`,
10481   REPEAT STRIP_TAC THEN EQ_TAC THEN STRIP_TAC THEN
10482   ASM_REWRITE_TAC[DIAMETER_EMPTY; DIAMETER_SING] THEN
10483   REWRITE_TAC[SET_RULE
10484    `s = {} \/ (?a. s = {a}) <=> !a b. a IN s /\ b IN s ==> a = b`] THEN
10485   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN
10486   MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`; `b:real^N`]
10487         DIAMETER_BOUNDED_BOUND) THEN
10488   ASM_REWRITE_TAC[] THEN NORM_ARITH_TAC);;
10489
10490 let DIAMETER_LE = prove
10491  (`!s:real^N->bool.
10492         (~(s = {}) \/ &0 <= d) /\
10493         (!x y. x IN s /\ y IN s ==> norm(x - y) <= d) ==> diameter s <= d`,
10494   GEN_TAC THEN REWRITE_TAC[diameter] THEN
10495   COND_CASES_TAC THEN ASM_SIMP_TAC[] THEN
10496   STRIP_TAC THEN MATCH_MP_TAC REAL_SUP_LE THEN
10497   CONJ_TAC THENL [ASM SET_TAC[]; ASM_SIMP_TAC[FORALL_IN_GSPEC]]);;
10498
10499 let DIAMETER_CBALL = prove
10500  (`!a:real^N r. diameter(cball(a,r)) = if r < &0 then &0 else &2 * r`,
10501   REPEAT GEN_TAC THEN COND_CASES_TAC THENL
10502    [ASM_MESON_TAC[CBALL_EQ_EMPTY; DIAMETER_EMPTY]; ALL_TAC] THEN
10503   RULE_ASSUM_TAC(REWRITE_RULE[REAL_NOT_LT]) THEN
10504   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN CONJ_TAC THENL
10505    [MATCH_MP_TAC DIAMETER_LE THEN
10506     ASM_SIMP_TAC[CBALL_EQ_EMPTY; REAL_LE_MUL; REAL_POS; REAL_NOT_LT] THEN
10507     REWRITE_TAC[IN_CBALL] THEN NORM_ARITH_TAC;
10508     MATCH_MP_TAC REAL_LE_TRANS THEN
10509     EXISTS_TAC `norm((a + r % basis 1) - (a - r % basis 1):real^N)` THEN
10510     CONJ_TAC THENL
10511      [REWRITE_TAC[VECTOR_ARITH `(a + r % b) - (a - r % b:real^N) =
10512                                 (&2 * r) % b`] THEN
10513       SIMP_TAC[NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
10514       ASM_REAL_ARITH_TAC;
10515       MATCH_MP_TAC DIAMETER_BOUNDED_BOUND THEN
10516       REWRITE_TAC[BOUNDED_CBALL; IN_CBALL] THEN
10517       REWRITE_TAC[NORM_ARITH
10518        `dist(a:real^N,a + b) = norm b /\ dist(a,a - b) = norm b`] THEN
10519       SIMP_TAC[NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
10520       ASM_REAL_ARITH_TAC]]);;
10521
10522 let DIAMETER_BALL = prove
10523  (`!a:real^N r. diameter(ball(a,r)) = if r < &0 then &0 else &2 * r`,
10524   REPEAT GEN_TAC THEN COND_CASES_TAC THENL
10525    [ASM_SIMP_TAC[BALL_EMPTY; REAL_LT_IMP_LE; DIAMETER_EMPTY]; ALL_TAC] THEN
10526   ASM_CASES_TAC `r = &0` THEN
10527   ASM_SIMP_TAC[BALL_EMPTY; REAL_LE_REFL; DIAMETER_EMPTY; REAL_MUL_RZERO] THEN
10528   MATCH_MP_TAC EQ_TRANS THEN
10529   EXISTS_TAC `diameter(cball(a:real^N,r))` THEN CONJ_TAC THENL
10530    [SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
10531     ASM_SIMP_TAC[GSYM CLOSURE_BALL; DIAMETER_CLOSURE; BOUNDED_BALL];
10532     ASM_SIMP_TAC[DIAMETER_CBALL]]);;
10533
10534 let DIAMETER_SUMS = prove
10535  (`!s t:real^N->bool.
10536         bounded s /\ bounded t
10537         ==> diameter {x + y | x IN s /\ y IN t} <= diameter s + diameter t`,
10538   REPEAT STRIP_TAC THEN
10539   ASM_CASES_TAC `s:real^N->bool = {}` THEN
10540   ASM_SIMP_TAC[NOT_IN_EMPTY; SET_RULE `{f x y |x,y| F} = {}`;
10541                DIAMETER_EMPTY; REAL_ADD_LID; DIAMETER_POS_LE] THEN
10542   ASM_CASES_TAC `t:real^N->bool = {}` THEN
10543   ASM_SIMP_TAC[NOT_IN_EMPTY; SET_RULE `{f x y |x,y| F} = {}`;
10544                DIAMETER_EMPTY; REAL_ADD_RID; DIAMETER_POS_LE] THEN
10545   MATCH_MP_TAC DIAMETER_LE THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10546   REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ; FORALL_IN_GSPEC] THEN
10547   REPEAT STRIP_TAC THEN MATCH_MP_TAC(NORM_ARITH
10548    `norm(x - x') <= s /\ norm(y - y') <= t
10549     ==> norm((x + y) - (x' + y'):real^N) <= s + t`) THEN
10550   ASM_SIMP_TAC[DIAMETER_BOUNDED_BOUND]);;
10551
10552 let LEBESGUE_COVERING_LEMMA = prove
10553  (`!s:real^N->bool c.
10554         compact s /\ ~(c = {}) /\ s SUBSET UNIONS c /\ (!b. b IN c ==> open b)
10555         ==> ?d. &0 < d /\
10556                 !t. t SUBSET s /\ diameter t <= d
10557                     ==> ?b. b IN c /\ t SUBSET b`,
10558   REPEAT STRIP_TAC THEN
10559   FIRST_ASSUM(MP_TAC o MATCH_MP HEINE_BOREL_LEMMA) THEN
10560   DISCH_THEN(MP_TAC o SPEC `c:(real^N->bool)->bool`) THEN ASM_SIMP_TAC[] THEN
10561   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `e:real` THEN
10562   STRIP_TAC THEN EXISTS_TAC `e / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
10563   X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
10564   ASM_CASES_TAC `t:real^N->bool = {}` THENL [ASM SET_TAC[]; ALL_TAC] THEN
10565   MP_TAC(ISPEC `t:real^N->bool` DIAMETER_SUBSET_CBALL_NONEMPTY) THEN
10566   ANTS_TAC THENL
10567    [ASM_MESON_TAC[BOUNDED_SUBSET; COMPACT_IMP_BOUNDED]; ALL_TAC] THEN
10568   DISCH_THEN(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
10569   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
10570   ANTS_TAC THENL [ASM SET_TAC[]; MATCH_MP_TAC MONO_EXISTS] THEN
10571   X_GEN_TAC `b:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
10572   MATCH_MP_TAC SUBSET_TRANS THEN
10573   EXISTS_TAC `cball(x:real^N,diameter(t:real^N->bool))` THEN
10574   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUBSET_TRANS THEN
10575   EXISTS_TAC `ball(x:real^N,e)` THEN ASM_REWRITE_TAC[] THEN
10576   REWRITE_TAC[SUBSET; IN_CBALL; IN_BALL] THEN
10577   MAP_EVERY UNDISCH_TAC [`&0 < e`; `diameter(t:real^N->bool) <= e / &2`] THEN
10578   NORM_ARITH_TAC);;
10579
10580 (* ------------------------------------------------------------------------- *)
10581 (* Related results with closure as the conclusion.                           *)
10582 (* ------------------------------------------------------------------------- *)
10583
10584 let CLOSED_SCALING = prove
10585  (`!s:real^N->bool c. closed s ==> closed (IMAGE (\x. c % x) s)`,
10586   REPEAT GEN_TAC THEN
10587   ASM_CASES_TAC `s :real^N->bool = {}` THEN
10588   ASM_REWRITE_TAC[CLOSED_EMPTY; IMAGE_CLAUSES] THEN
10589   ASM_CASES_TAC `c = &0` THENL
10590    [SUBGOAL_THEN `IMAGE (\x:real^N. c % x) s = {(vec 0)}`
10591      (fun th -> REWRITE_TAC[th; CLOSED_SING]) THEN
10592     ASM_REWRITE_TAC[EXTENSION; IN_IMAGE; IN_SING; VECTOR_MUL_LZERO] THEN
10593     ASM_MESON_TAC[MEMBER_NOT_EMPTY];
10594     ALL_TAC] THEN
10595   REWRITE_TAC[CLOSED_SEQUENTIAL_LIMITS; IN_IMAGE; SKOLEM_THM] THEN
10596   STRIP_TAC THEN X_GEN_TAC `x:num->real^N` THEN X_GEN_TAC `l:real^N` THEN
10597   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
10598   DISCH_THEN(X_CHOOSE_THEN `y:num->real^N` MP_TAC) THEN
10599   REWRITE_TAC[FORALL_AND_THM] THEN STRIP_TAC THEN
10600   EXISTS_TAC `inv(c) % l :real^N` THEN
10601   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; VECTOR_MUL_LID] THEN
10602   FIRST_X_ASSUM MATCH_MP_TAC THEN EXISTS_TAC `\n:num. inv(c) % x n:real^N` THEN
10603   ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
10604    [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID];
10605     MATCH_MP_TAC LIM_CMUL THEN
10606     FIRST_ASSUM(fun th -> REWRITE_TAC[SYM(SPEC_ALL th)]) THEN
10607     ASM_REWRITE_TAC[ETA_AX]]);;
10608
10609 let CLOSED_NEGATIONS = prove
10610  (`!s:real^N->bool. closed s ==> closed (IMAGE (--) s)`,
10611   REPEAT GEN_TAC THEN
10612   SUBGOAL_THEN `IMAGE (--) s = IMAGE (\x:real^N. --(&1) % x) s`
10613   SUBST1_TAC THEN SIMP_TAC[CLOSED_SCALING] THEN
10614   REWRITE_TAC[VECTOR_ARITH `--(&1) % x = --x`] THEN REWRITE_TAC[ETA_AX]);;
10615
10616 let COMPACT_CLOSED_SUMS = prove
10617  (`!s:real^N->bool t.
10618         compact s /\ closed t ==> closed {x + y | x IN s /\ y IN t}`,
10619   REPEAT GEN_TAC THEN
10620   REWRITE_TAC[compact; IN_ELIM_THM; CLOSED_SEQUENTIAL_LIMITS] THEN
10621   STRIP_TAC THEN X_GEN_TAC `f:num->real^N` THEN X_GEN_TAC `l:real^N` THEN
10622   REWRITE_TAC[SKOLEM_THM; FORALL_AND_THM] THEN
10623   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
10624   DISCH_THEN(X_CHOOSE_THEN `a:num->real^N` MP_TAC) THEN
10625   DISCH_THEN(X_CHOOSE_THEN `b:num->real^N` STRIP_ASSUME_TAC) THEN
10626   FIRST_X_ASSUM(MP_TAC o check(is_imp o concl) o SPEC `a:num->real^N`) THEN
10627   ASM_REWRITE_TAC[] THEN
10628   DISCH_THEN(X_CHOOSE_THEN `la:real^N` (X_CHOOSE_THEN `sub:num->num`
10629         STRIP_ASSUME_TAC)) THEN
10630   MAP_EVERY EXISTS_TAC [`la:real^N`; `l - la:real^N`] THEN
10631   ASM_REWRITE_TAC[VECTOR_ARITH `a + (b - a) = b:real^N`] THEN
10632   FIRST_X_ASSUM MATCH_MP_TAC THEN
10633   EXISTS_TAC `\n. (f o (sub:num->num)) n - (a o sub) n:real^N` THEN
10634   CONJ_TAC THENL [ASM_REWRITE_TAC[VECTOR_ADD_SUB; o_THM]; ALL_TAC] THEN
10635   MATCH_MP_TAC LIM_SUB THEN ASM_SIMP_TAC[LIM_SUBSEQUENCE; ETA_AX]);;
10636
10637 let CLOSED_COMPACT_SUMS = prove
10638  (`!s:real^N->bool t.
10639         closed s /\ compact t ==> closed {x + y | x IN s /\ y IN t}`,
10640   REPEAT GEN_TAC THEN
10641   SUBGOAL_THEN `{x + y:real^N | x IN s /\ y IN t} = {y + x | y IN t /\ x IN s}`
10642   SUBST1_TAC THEN  SIMP_TAC[COMPACT_CLOSED_SUMS] THEN
10643   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN MESON_TAC[VECTOR_ADD_SYM]);;
10644
10645 let CLOSURE_SUMS = prove
10646  (`!s t:real^N->bool.
10647         bounded s \/ bounded t
10648         ==> closure {x + y | x IN s /\ y IN t} =
10649             {x + y | x IN closure s /\ y IN closure t}`,
10650   REWRITE_TAC[TAUT `p \/ q ==> r <=> (p ==> r) /\ (q ==> r)`] THEN
10651   REWRITE_TAC[FORALL_AND_THM] THEN
10652   GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [SUMS_SYM] THEN
10653   MATCH_MP_TAC(TAUT `(p ==> q) /\ p ==> p /\ q`) THEN
10654   SIMP_TAC[] THEN
10655   REPEAT STRIP_TAC THEN REWRITE_TAC[EXTENSION; CLOSURE_SEQUENTIAL] THEN
10656   X_GEN_TAC `z:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN EQ_TAC THENL
10657    [REWRITE_TAC[IN_ELIM_THM; IN_DELETE; SKOLEM_THM; LEFT_AND_EXISTS_THM] THEN
10658     REWRITE_TAC[FORALL_AND_THM] THEN
10659     ONCE_REWRITE_TAC[TAUT `(p /\ q) /\ r <=> q /\ p /\ r`] THEN
10660     ONCE_REWRITE_TAC[MESON[] `(?f x y. P f x y) <=> (?x y f. P f x y)`] THEN
10661     ONCE_REWRITE_TAC[GSYM FUN_EQ_THM] THEN
10662     REWRITE_TAC[ETA_AX; UNWIND_THM2] THEN
10663     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
10664     MAP_EVERY X_GEN_TAC [`a:num->real^N`; `b:num->real^N`] THEN
10665     STRIP_TAC THEN
10666     MP_TAC(ISPEC `closure s:real^N->bool` compact) THEN
10667     ASM_REWRITE_TAC[COMPACT_CLOSURE] THEN
10668     DISCH_THEN(MP_TAC o SPEC `a:num->real^N`) THEN
10669     ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET; LEFT_IMP_EXISTS_THM] THEN
10670     MAP_EVERY X_GEN_TAC [`u:real^N`; `r:num->num`] THEN STRIP_TAC THEN
10671     EXISTS_TAC `z - u:real^N` THEN
10672     EXISTS_TAC `(a:num->real^N) o (r:num->num)` THEN EXISTS_TAC `u:real^N` THEN
10673     ASM_REWRITE_TAC[o_THM] THEN
10674     CONJ_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN
10675     EXISTS_TAC `(\n. ((\n. a n + b n) o (r:num->num)) n - (a o r) n)
10676                 :num->real^N` THEN
10677     CONJ_TAC THENL
10678      [ASM_REWRITE_TAC[o_DEF; VECTOR_ARITH `(a + b) - a:real^N = b`];
10679       MATCH_MP_TAC LIM_SUB THEN ASM_REWRITE_TAC[ETA_AX] THEN
10680       MATCH_MP_TAC LIM_SUBSEQUENCE THEN ASM_REWRITE_TAC[]];
10681     REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN
10682     REWRITE_TAC[LEFT_IMP_EXISTS_THM; LEFT_AND_EXISTS_THM;
10683                 RIGHT_AND_EXISTS_THM] THEN
10684     MAP_EVERY X_GEN_TAC
10685      [`x:real^N`; `y:real^N`; `a:num->real^N`; `b:num->real^N`] THEN
10686     STRIP_TAC THEN EXISTS_TAC `(\n. a n + b n):num->real^N` THEN
10687     ASM_SIMP_TAC[LIM_ADD] THEN ASM_MESON_TAC[]]);;
10688
10689 let COMPACT_CLOSED_DIFFERENCES = prove
10690  (`!s:real^N->bool t.
10691         compact s /\ closed t ==> closed {x - y | x IN s /\ y IN t}`,
10692   REPEAT STRIP_TAC THEN
10693   SUBGOAL_THEN `{x - y | x:real^N IN s /\ y IN t} =
10694                 {x + y | x IN s /\ y IN (IMAGE (--) t)}`
10695     (fun th -> ASM_SIMP_TAC[th; COMPACT_CLOSED_SUMS; CLOSED_NEGATIONS]) THEN
10696   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE] THEN
10697   ONCE_REWRITE_TAC[VECTOR_ARITH `(x:real^N = --y) <=> (y = --x)`] THEN
10698   SIMP_TAC[VECTOR_SUB; GSYM CONJ_ASSOC; UNWIND_THM2] THEN
10699   MESON_TAC[VECTOR_NEG_NEG]);;
10700
10701 let CLOSED_COMPACT_DIFFERENCES = prove
10702  (`!s:real^N->bool t.
10703         closed s /\ compact t ==> closed {x - y | x IN s /\ y IN t}`,
10704   REPEAT STRIP_TAC THEN
10705   SUBGOAL_THEN `{x - y | x:real^N IN s /\ y IN t} =
10706                 {x + y | x IN s /\ y IN (IMAGE (--) t)}`
10707     (fun th -> ASM_SIMP_TAC[th; CLOSED_COMPACT_SUMS; COMPACT_NEGATIONS]) THEN
10708   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE] THEN
10709   ONCE_REWRITE_TAC[VECTOR_ARITH `(x:real^N = --y) <=> (y = --x)`] THEN
10710   SIMP_TAC[VECTOR_SUB; GSYM CONJ_ASSOC; UNWIND_THM2] THEN
10711   MESON_TAC[VECTOR_NEG_NEG]);;
10712
10713 let CLOSED_TRANSLATION_EQ = prove
10714  (`!a s. closed (IMAGE (\x:real^N. a + x) s) <=> closed s`,
10715   REWRITE_TAC[closed] THEN GEOM_TRANSLATE_TAC[]);;
10716
10717 let CLOSED_TRANSLATION = prove
10718  (`!s a:real^N. closed s ==> closed (IMAGE (\x. a + x) s)`,
10719   REWRITE_TAC[CLOSED_TRANSLATION_EQ]);;
10720
10721 add_translation_invariants [CLOSED_TRANSLATION_EQ];;
10722
10723 let COMPLETE_TRANSLATION_EQ = prove
10724  (`!a s. complete(IMAGE (\x:real^N. a + x) s) <=> complete s`,
10725   REWRITE_TAC[COMPLETE_EQ_CLOSED; CLOSED_TRANSLATION_EQ]);;
10726
10727 add_translation_invariants [COMPLETE_TRANSLATION_EQ];;
10728
10729 let TRANSLATION_UNIV = prove
10730  (`!a. IMAGE (\x. a + x) (:real^N) = (:real^N)`,
10731   CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN GEOM_TRANSLATE_TAC[]);;
10732
10733 let TRANSLATION_DIFF = prove
10734  (`!s t:real^N->bool.
10735         IMAGE (\x. a + x) (s DIFF t) =
10736         (IMAGE (\x. a + x) s) DIFF (IMAGE (\x. a + x) t)`,
10737   REWRITE_TAC[EXTENSION; IN_DIFF; IN_IMAGE] THEN
10738   ONCE_REWRITE_TAC[VECTOR_ARITH `x:real^N = a + y <=> y = x - a`] THEN
10739   REWRITE_TAC[UNWIND_THM2]);;
10740
10741 let CLOSURE_TRANSLATION = prove
10742  (`!a s. closure(IMAGE (\x:real^N. a + x) s) = IMAGE (\x. a + x) (closure s)`,
10743   REWRITE_TAC[CLOSURE_INTERIOR] THEN GEOM_TRANSLATE_TAC[]);;
10744
10745 add_translation_invariants [CLOSURE_TRANSLATION];;
10746
10747 let FRONTIER_TRANSLATION = prove
10748  (`!a s. frontier(IMAGE (\x:real^N. a + x) s) = IMAGE (\x. a + x) (frontier s)`,
10749   REWRITE_TAC[frontier] THEN GEOM_TRANSLATE_TAC[]);;
10750
10751 add_translation_invariants [FRONTIER_TRANSLATION];;
10752
10753 (* ------------------------------------------------------------------------- *)
10754 (* Separation between points and sets.                                       *)
10755 (* ------------------------------------------------------------------------- *)
10756
10757 let SEPARATE_POINT_CLOSED = prove
10758  (`!s a:real^N.
10759         closed s /\ ~(a IN s)
10760         ==> ?d. &0 < d /\ !x. x IN s ==> d <= dist(a,x)`,
10761   REPEAT STRIP_TAC THEN
10762   ASM_CASES_TAC `s:real^N->bool = {}` THENL
10763    [EXISTS_TAC `&1` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY; REAL_LT_01];
10764     ALL_TAC] THEN
10765   MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`] DISTANCE_ATTAINS_INF) THEN
10766   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `b:real^N` THEN
10767   STRIP_TAC THEN EXISTS_TAC `dist(a:real^N,b)` THEN
10768   ASM_MESON_TAC[DIST_POS_LT]);;
10769
10770 let SEPARATE_COMPACT_CLOSED = prove
10771  (`!s t:real^N->bool.
10772         compact s /\ closed t /\ s INTER t = {}
10773         ==> ?d. &0 < d /\ !x y. x IN s /\ y IN t ==> d <= dist(x,y)`,
10774   REPEAT STRIP_TAC THEN
10775   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN t}`; `vec 0:real^N`]
10776                 SEPARATE_POINT_CLOSED) THEN
10777   ASM_SIMP_TAC[COMPACT_CLOSED_DIFFERENCES; IN_ELIM_THM] THEN
10778   REWRITE_TAC[VECTOR_ARITH `vec 0 = x - y <=> x = y`] THEN
10779   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
10780   MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN
10781   MESON_TAC[NORM_ARITH `dist(vec 0,x - y) = dist(x,y)`]);;
10782
10783 let SEPARATE_CLOSED_COMPACT = prove
10784  (`!s t:real^N->bool.
10785         closed s /\ compact t /\ s INTER t = {}
10786         ==> ?d. &0 < d /\ !x y. x IN s /\ y IN t ==> d <= dist(x,y)`,
10787   ONCE_REWRITE_TAC[DIST_SYM; INTER_COMM] THEN
10788   MESON_TAC[SEPARATE_COMPACT_CLOSED]);;
10789
10790 (* ------------------------------------------------------------------------- *)
10791 (* Representing sets as the union of a chain of compact sets.                *)
10792 (* ------------------------------------------------------------------------- *)
10793
10794 let CLOSED_UNION_COMPACT_SUBSETS = prove
10795  (`!s. closed s
10796        ==> ?f:num->real^N->bool.
10797                 (!n. compact(f n)) /\
10798                 (!n. (f n) SUBSET s) /\
10799                 (!n. (f n) SUBSET f(n + 1)) /\
10800                 UNIONS {f n | n IN (:num)} = s /\
10801                 (!k. compact k /\ k SUBSET s
10802                      ==> ?N. !n. n >= N ==> k SUBSET (f n))`,
10803   REPEAT STRIP_TAC THEN
10804   EXISTS_TAC `\n. s INTER cball(vec 0:real^N,&n)` THEN
10805   ASM_SIMP_TAC[INTER_SUBSET; COMPACT_CBALL; CLOSED_INTER_COMPACT] THEN
10806   REPEAT CONJ_TAC THENL
10807    [GEN_TAC THEN MATCH_MP_TAC(SET_RULE
10808      `t SUBSET u ==> s INTER t SUBSET s INTER u`) THEN
10809     REWRITE_TAC[SUBSET_BALLS; DIST_REFL; GSYM REAL_OF_NUM_ADD] THEN
10810     REAL_ARITH_TAC;
10811     REWRITE_TAC[EXTENSION; UNIONS_GSPEC; IN_ELIM_THM; IN_UNIV; IN_INTER] THEN
10812     X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_CBALL_0] THEN
10813     MESON_TAC[REAL_ARCH_SIMPLE];
10814     X_GEN_TAC `k:real^N->bool` THEN SIMP_TAC[SUBSET_INTER] THEN
10815     REPEAT STRIP_TAC THEN
10816     FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN DISCH_THEN
10817      (MP_TAC o SPEC `vec 0:real^N` o MATCH_MP BOUNDED_SUBSET_CBALL) THEN
10818     DISCH_THEN(X_CHOOSE_THEN `r:real` STRIP_ASSUME_TAC) THEN
10819     MP_TAC(ISPEC `r:real` REAL_ARCH_SIMPLE) THEN MATCH_MP_TAC MONO_EXISTS THEN
10820     X_GEN_TAC `N:num` THEN REWRITE_TAC[GSYM REAL_OF_NUM_GE] THEN
10821
10822     REPEAT STRIP_TAC THEN
10823     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10824         SUBSET_TRANS)) THEN
10825     REWRITE_TAC[SUBSET_BALLS; DIST_REFL] THEN ASM_REAL_ARITH_TAC]);;
10826
10827 let OPEN_UNION_COMPACT_SUBSETS = prove
10828  (`!s. open s
10829        ==> ?f:num->real^N->bool.
10830                 (!n. compact(f n)) /\
10831                 (!n. (f n) SUBSET s) /\
10832                 (!n. (f n) SUBSET interior(f(n + 1))) /\
10833                 UNIONS {f n | n IN (:num)} = s /\
10834                 (!k. compact k /\ k SUBSET s
10835                      ==> ?N. !n. n >= N ==> k SUBSET (f n))`,
10836   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
10837    [DISCH_TAC THEN EXISTS_TAC `(\n. {}):num->real^N->bool` THEN
10838     ASM_SIMP_TAC[EMPTY_SUBSET; SUBSET_EMPTY; COMPACT_EMPTY] THEN
10839     REWRITE_TAC[EXTENSION; UNIONS_GSPEC; IN_ELIM_THM; NOT_IN_EMPTY];
10840     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
10841     DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN STRIP_TAC] THEN
10842   MATCH_MP_TAC(MESON[]
10843    `(!f. p1 f /\ p3 f /\ p4 f ==> p5 f) /\
10844     (?f. p1 f /\ p2 f /\ p3 f /\ (p2 f ==> p4 f))
10845     ==> ?f. p1 f /\ p2 f /\ p3 f /\ p4 f /\ p5 f`) THEN
10846   CONJ_TAC THENL
10847    [X_GEN_TAC `f:num->real^N->bool` THEN STRIP_TAC THEN
10848     FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
10849     X_GEN_TAC `k:real^N->bool` THEN STRIP_TAC THEN
10850     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL]) THEN
10851     DISCH_THEN(MP_TAC o SPEC `{interior(f n):real^N->bool | n IN (:num)}`) THEN
10852     REWRITE_TAC[FORALL_IN_GSPEC; OPEN_INTERIOR] THEN ANTS_TAC THENL
10853      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10854         SUBSET_TRANS)) THEN
10855       REWRITE_TAC[SUBSET; UNIONS_GSPEC; IN_ELIM_THM] THEN ASM SET_TAC[];
10856       ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN
10857       REWRITE_TAC[SIMPLE_IMAGE; EXISTS_FINITE_SUBSET_IMAGE] THEN
10858       REWRITE_TAC[SUBSET_UNIV] THEN
10859       DISCH_THEN(X_CHOOSE_THEN `i:num->bool` STRIP_ASSUME_TAC) THEN
10860       FIRST_ASSUM(MP_TAC o SPEC `\n:num. n` o
10861         MATCH_MP UPPER_BOUND_FINITE_SET) THEN
10862       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
10863       REWRITE_TAC[GE] THEN DISCH_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
10864       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
10865         SUBSET_TRANS)) THEN
10866       REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_IMAGE] THEN
10867       X_GEN_TAC `m:num` THEN DISCH_TAC THEN MATCH_MP_TAC SUBSET_TRANS THEN
10868       EXISTS_TAC `(f:num->real^N->bool) m` THEN
10869       REWRITE_TAC[INTERIOR_SUBSET] THEN
10870       SUBGOAL_THEN `!m n. m <= n ==> (f:num->real^N->bool) m SUBSET f n`
10871        (fun th -> ASM_MESON_TAC[th; LE_TRANS]) THEN
10872       MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
10873       ASM_MESON_TAC[SUBSET; ADD1; INTERIOR_SUBSET]];
10874     EXISTS_TAC
10875      `\n. cball(a,&n) DIFF
10876          {x + e | x IN (:real^N) DIFF s /\ e IN ball(vec 0,inv(&n + &1))}` THEN
10877     REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
10878      [X_GEN_TAC `n:num` THEN MATCH_MP_TAC COMPACT_DIFF THEN
10879       SIMP_TAC[COMPACT_CBALL; OPEN_SUMS; OPEN_BALL];
10880       GEN_TAC THEN MATCH_MP_TAC(SET_RULE
10881        `(UNIV DIFF s) SUBSET t ==> c DIFF t SUBSET s`) THEN
10882       REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
10883       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
10884       MAP_EVERY EXISTS_TAC [`x:real^N`; `vec 0:real^N`] THEN
10885       ASM_REWRITE_TAC[VECTOR_ADD_RID; CENTRE_IN_BALL; REAL_LT_INV_EQ] THEN
10886       REAL_ARITH_TAC;
10887       GEN_TAC THEN REWRITE_TAC[INTERIOR_DIFF] THEN MATCH_MP_TAC(SET_RULE
10888        `s SUBSET s' /\ t' SUBSET t ==> (s DIFF t) SUBSET (s' DIFF t')`) THEN
10889       CONJ_TAC THENL
10890        [REWRITE_TAC[INTERIOR_CBALL; SUBSET; IN_BALL; IN_CBALL] THEN
10891         REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN REAL_ARITH_TAC;
10892         MATCH_MP_TAC SUBSET_TRANS THEN
10893         EXISTS_TAC `{x + e | x IN (:real^N) DIFF s /\
10894                              e IN cball(vec 0,inv(&n + &2))}` THEN
10895         CONJ_TAC THENL
10896          [MATCH_MP_TAC CLOSURE_MINIMAL THEN
10897           ASM_SIMP_TAC[CLOSED_COMPACT_SUMS; COMPACT_CBALL;
10898                        GSYM OPEN_CLOSED] THEN
10899           MATCH_MP_TAC(SET_RULE
10900            `t SUBSET t'
10901             ==> {f x y | x IN s /\ y IN t} SUBSET
10902                 {f x y | x IN s /\ y IN t'}`) THEN
10903           REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL; GSYM REAL_OF_NUM_ADD] THEN
10904           REAL_ARITH_TAC;
10905           MATCH_MP_TAC(SET_RULE
10906            `t SUBSET t'
10907             ==> {f x y | x IN s /\ y IN t} SUBSET
10908                 {f x y | x IN s /\ y IN t'}`) THEN
10909           REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL; GSYM REAL_OF_NUM_ADD] THEN
10910           GEN_TAC THEN MATCH_MP_TAC(REAL_ARITH
10911            `a < b ==> x <= a ==> x < b`) THEN
10912           MATCH_MP_TAC REAL_LT_INV2 THEN REAL_ARITH_TAC]];
10913       DISCH_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
10914       ASM_REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC] THEN
10915       REWRITE_TAC[SUBSET; UNIONS_GSPEC; IN_UNIV; IN_ELIM_THM] THEN
10916       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_DIFF] THEN
10917       REWRITE_TAC[IN_ELIM_THM; IN_UNIV; IN_BALL_0] THEN
10918       REWRITE_TAC[VECTOR_ARITH `x:real^N = y + e <=> e = x - y`] THEN
10919       REWRITE_TAC[TAUT `(p /\ q) /\ r <=> r /\ p /\ q`; UNWIND_THM2] THEN
10920       REWRITE_TAC[MESON[] `~(?x. ~P x /\ Q x) <=> !x. Q x ==> P x`] THEN
10921       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
10922       DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
10923       ASM_REWRITE_TAC[SUBSET; IN_BALL; dist] THEN
10924       DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
10925       FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [REAL_ARCH_INV]) THEN
10926       DISCH_THEN(X_CHOOSE_THEN `N1:num` STRIP_ASSUME_TAC) THEN
10927       MP_TAC(ISPEC `norm(x - a:real^N)` REAL_ARCH_SIMPLE) THEN
10928       DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN EXISTS_TAC `N1 + N2:num` THEN
10929       CONJ_TAC THENL
10930        [REWRITE_TAC[IN_CBALL] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
10931         UNDISCH_TAC `norm(x - a:real^N) <= &N2` THEN
10932         REWRITE_TAC[dist; GSYM REAL_OF_NUM_ADD] THEN REAL_ARITH_TAC;
10933         REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
10934         SUBGOAL_THEN `inv(&(N1 + N2) + &1) <= inv(&N1)` MP_TAC THENL
10935          [MATCH_MP_TAC REAL_LE_INV2 THEN
10936           ASM_SIMP_TAC[REAL_OF_NUM_LT; LE_1] THEN
10937           REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN REAL_ARITH_TAC;
10938           ASM_REAL_ARITH_TAC]]]]);;
10939
10940 (* ------------------------------------------------------------------------- *)
10941 (* Closed-graph characterization of continuity.                              *)
10942 (* ------------------------------------------------------------------------- *)
10943
10944 let CONTINUOUS_CLOSED_GRAPH_GEN = prove
10945  (`!f:real^M->real^N s t.
10946         f continuous_on s /\ IMAGE f s SUBSET t
10947         ==> closed_in (subtopology euclidean (s PCROSS t))
10948                       {pastecart x (f x) | x IN s}`,
10949   REPEAT STRIP_TAC THEN
10950   SUBGOAL_THEN
10951    `{pastecart (x:real^M) (f x:real^N) | x IN s} =
10952     {z | z IN s PCROSS t /\ f(fstcart z) - sndcart z IN {vec 0}}`
10953   SUBST1_TAC THENL
10954    [REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_THM; IN_SING;
10955                 PASTECART_IN_PCROSS; FSTCART_PASTECART; SNDCART_PASTECART;
10956                 PASTECART_INJ; VECTOR_SUB_EQ] THEN
10957     ASM SET_TAC[];
10958     MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
10959     REWRITE_TAC[CLOSED_SING] THEN MATCH_MP_TAC CONTINUOUS_ON_SUB THEN
10960     SIMP_TAC[GSYM o_DEF; LINEAR_CONTINUOUS_ON; LINEAR_SNDCART] THEN
10961     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
10962     SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART; IMAGE_FSTCART_PCROSS] THEN
10963     ASM_MESON_TAC[CONTINUOUS_ON_EMPTY]]);;
10964
10965 let CONTINUOUS_CLOSED_GRAPH_EQ = prove
10966  (`!f:real^M->real^N s t.
10967         compact t /\ IMAGE f s SUBSET t
10968         ==> (f continuous_on s <=>
10969              closed_in (subtopology euclidean (s PCROSS t))
10970                        {pastecart x (f x) | x IN s})`,
10971   REPEAT STRIP_TAC THEN EQ_TAC THEN
10972   ASM_SIMP_TAC[CONTINUOUS_CLOSED_GRAPH_GEN] THEN DISCH_TAC THEN
10973   FIRST_ASSUM(fun th ->
10974    REWRITE_TAC[MATCH_MP CONTINUOUS_ON_CLOSED_GEN th]) THEN
10975   X_GEN_TAC `c:real^N->bool` THEN STRIP_TAC THEN
10976   SUBGOAL_THEN
10977    `{x | x IN s /\ (f:real^M->real^N) x IN c} =
10978     IMAGE fstcart ({pastecart x (f x) | x IN s} INTER
10979                    (s PCROSS c))`
10980   SUBST1_TAC THENL
10981    [REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM; EXISTS_PASTECART;
10982                 FSTCART_PASTECART; IN_INTER; IN_ELIM_PASTECART_THM;
10983                 PASTECART_IN_PCROSS; PASTECART_INJ] THEN
10984     ASM SET_TAC[];
10985     MATCH_MP_TAC CLOSED_MAP_FSTCART THEN EXISTS_TAC `t:real^N->bool` THEN
10986     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CLOSED_IN_INTER THEN
10987     ASM_REWRITE_TAC[] THEN  MATCH_MP_TAC CLOSED_IN_PCROSS THEN
10988     ASM_REWRITE_TAC[CLOSED_IN_REFL]]);;
10989
10990 let CONTINUOUS_CLOSED_GRAPH = prove
10991  (`!f:real^M->real^N s.
10992         closed s /\ f continuous_on s ==> closed {pastecart x (f x) | x IN s}`,
10993   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSED_IN_CLOSED_TRANS THEN
10994   EXISTS_TAC `(s:real^M->bool) PCROSS (:real^N)` THEN
10995   ASM_SIMP_TAC[CLOSED_PCROSS; CLOSED_UNIV] THEN
10996   MATCH_MP_TAC CONTINUOUS_CLOSED_GRAPH_GEN THEN
10997   ASM_REWRITE_TAC[SUBSET_UNIV]);;
10998
10999 let CONTINUOUS_FROM_CLOSED_GRAPH = prove
11000  (`!f:real^M->real^N s t.
11001         compact t /\ IMAGE f s SUBSET t /\
11002         closed {pastecart x (f x) | x IN s}
11003         ==> f continuous_on s`,
11004   REPEAT GEN_TAC THEN REWRITE_TAC[CONJ_ASSOC] THEN
11005   DISCH_THEN(CONJUNCTS_THEN ASSUME_TAC) THEN
11006   FIRST_ASSUM(SUBST1_TAC o MATCH_MP CONTINUOUS_CLOSED_GRAPH_EQ) THEN
11007   MATCH_MP_TAC CLOSED_SUBSET THEN ASM_REWRITE_TAC[] THEN
11008   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC; PASTECART_IN_PCROSS] THEN
11009   ASM SET_TAC[]);;
11010
11011 (* ------------------------------------------------------------------------- *)
11012 (* A cute way of denoting open and closed intervals using overloading.       *)
11013 (* ------------------------------------------------------------------------- *)
11014
11015 let open_interval = new_definition
11016   `open_interval(a:real^N,b:real^N) =
11017         {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
11018                         ==> a$i < x$i /\ x$i < b$i}`;;
11019
11020 let closed_interval = new_definition
11021   `closed_interval(l:(real^N#real^N)list) =
11022          {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
11023                          ==> FST(HD l)$i <= x$i /\ x$i <= SND(HD l)$i}`;;
11024
11025 make_overloadable "interval" `:A`;;
11026
11027 overload_interface("interval",`open_interval`);;
11028 overload_interface("interval",`closed_interval`);;
11029
11030 let interval = prove
11031  (`(interval (a,b) = {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
11032                                      ==> a$i < x$i /\ x$i < b$i}) /\
11033    (interval [a,b] = {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
11034                                      ==> a$i <= x$i /\ x$i <= b$i})`,
11035   REWRITE_TAC[open_interval; closed_interval; HD; FST; SND]);;
11036
11037 let IN_INTERVAL = prove
11038  (`(!x:real^N.
11039         x IN interval (a,b) <=>
11040                 !i. 1 <= i /\ i <= dimindex(:N)
11041                     ==> a$i < x$i /\ x$i < b$i) /\
11042    (!x:real^N.
11043         x IN interval [a,b] <=>
11044                 !i. 1 <= i /\ i <= dimindex(:N)
11045                     ==> a$i <= x$i /\ x$i <= b$i)`,
11046   REWRITE_TAC[interval; IN_ELIM_THM]);;
11047
11048 let IN_INTERVAL_REFLECT = prove
11049  (`(!a b x. (--x) IN interval[--b,--a] <=> x IN interval[a,b]) /\
11050    (!a b x. (--x) IN interval(--b,--a) <=> x IN interval(a,b))`,
11051   SIMP_TAC[IN_INTERVAL; REAL_LT_NEG2; REAL_LE_NEG2; VECTOR_NEG_COMPONENT] THEN
11052   MESON_TAC[]);;
11053
11054 let REFLECT_INTERVAL = prove
11055  (`(!a b:real^N. IMAGE (--) (interval[a,b]) = interval[--b,--a]) /\
11056    (!a b:real^N. IMAGE (--) (interval(a,b)) = interval(--b,--a))`,
11057   REPEAT STRIP_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
11058   REWRITE_TAC[IN_INTERVAL_REFLECT] THEN MESON_TAC[VECTOR_NEG_NEG]);;
11059
11060 let INTERVAL_EQ_EMPTY = prove
11061  (`((interval [a:real^N,b] = {}) <=>
11062     ?i. 1 <= i /\ i <= dimindex(:N) /\ b$i < a$i) /\
11063    ((interval (a:real^N,b) = {}) <=>
11064     ?i. 1 <= i /\ i <= dimindex(:N) /\ b$i <= a$i)`,
11065   REWRITE_TAC[EXTENSION; IN_INTERVAL; NOT_IN_EMPTY] THEN
11066   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; GSYM CONJ_ASSOC] THEN
11067   CONJ_TAC THEN EQ_TAC THENL
11068    [MESON_TAC[REAL_LE_REFL; REAL_NOT_LE];
11069     MESON_TAC[REAL_LE_TRANS; REAL_NOT_LE];
11070     ALL_TAC;
11071     MESON_TAC[REAL_LT_TRANS; REAL_NOT_LT]] THEN
11072   SUBGOAL_THEN `!a b. ?c. a < b ==> a < c /\ c < b`
11073   (MP_TAC o REWRITE_RULE[SKOLEM_THM]) THENL
11074    [MESON_TAC[REAL_LT_BETWEEN]; ALL_TAC] THEN
11075   DISCH_THEN(X_CHOOSE_TAC `mid:real->real->real`) THEN
11076   DISCH_THEN(MP_TAC o SPEC
11077    `(lambda i. mid ((a:real^N)$i) ((b:real^N)$i)):real^N`) THEN
11078   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> ~(a /\ b ==> ~c)`] THEN
11079   SIMP_TAC[LAMBDA_BETA] THEN ASM_MESON_TAC[REAL_NOT_LT]);;
11080
11081 let INTERVAL_NE_EMPTY = prove
11082  (`(~(interval [a:real^N,b] = {}) <=>
11083     !i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= b$i) /\
11084    (~(interval (a:real^N,b) = {}) <=>
11085     !i. 1 <= i /\ i <= dimindex(:N) ==> a$i < b$i)`,
11086   REWRITE_TAC[INTERVAL_EQ_EMPTY] THEN MESON_TAC[REAL_NOT_LE]);;
11087
11088 let SUBSET_INTERVAL_IMP = prove
11089  (`((!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)
11090     ==> interval[c,d] SUBSET interval[a:real^N,b]) /\
11091    ((!i. 1 <= i /\ i <= dimindex(:N) ==> a$i < c$i /\ d$i < b$i)
11092     ==> interval[c,d] SUBSET interval(a:real^N,b)) /\
11093    ((!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)
11094     ==> interval(c,d) SUBSET interval[a:real^N,b]) /\
11095    ((!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)
11096     ==> interval(c,d) SUBSET interval(a:real^N,b))`,
11097   REWRITE_TAC[SUBSET; IN_INTERVAL] THEN REPEAT CONJ_TAC THEN
11098   DISCH_TAC THEN GEN_TAC THEN POP_ASSUM MP_TAC THEN
11099   REWRITE_TAC[IMP_IMP; AND_FORALL_THM] THEN MATCH_MP_TAC MONO_FORALL THEN
11100   GEN_TAC THEN DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
11101   ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
11102
11103 let INTERVAL_SING = prove
11104  (`interval[a,a] = {a} /\ interval(a,a) = {}`,
11105   REWRITE_TAC[EXTENSION; IN_SING; NOT_IN_EMPTY; IN_INTERVAL] THEN
11106   REWRITE_TAC[REAL_LE_ANTISYM; REAL_LT_ANTISYM; CART_EQ; EQ_SYM_EQ] THEN
11107   MESON_TAC[DIMINDEX_GE_1; LE_REFL]);;
11108
11109 let SUBSET_INTERVAL = prove
11110  (`(interval[c,d] SUBSET interval[a:real^N,b] <=>
11111         (!i. 1 <= i /\ i <= dimindex(:N) ==> c$i <= d$i)
11112         ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)) /\
11113    (interval[c,d] SUBSET interval(a:real^N,b) <=>
11114         (!i. 1 <= i /\ i <= dimindex(:N) ==> c$i <= d$i)
11115         ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> a$i < c$i /\ d$i < b$i)) /\
11116    (interval(c,d) SUBSET interval[a:real^N,b] <=>
11117         (!i. 1 <= i /\ i <= dimindex(:N) ==> c$i < d$i)
11118         ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)) /\
11119    (interval(c,d) SUBSET interval(a:real^N,b) <=>
11120         (!i. 1 <= i /\ i <= dimindex(:N) ==> c$i < d$i)
11121         ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i))`,
11122   let lemma = prove
11123    (`(!x:real^N. (!i. 1 <= i /\ i <= dimindex(:N) ==> Q i (x$i))
11124                  ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> R i (x$i)))
11125      ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> ?y. Q i y)
11126          ==> !i y. 1 <= i /\ i <= dimindex(:N) /\ Q i y ==> R i y`,
11127     DISCH_TAC THEN REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
11128     DISCH_THEN(X_CHOOSE_THEN `f:num->real` STRIP_ASSUME_TAC) THEN
11129     REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o
11130      SPEC `(lambda j. if j = i then y else f j):real^N`) THEN
11131     SIMP_TAC[LAMBDA_BETA] THEN ASM_MESON_TAC[]) in
11132   REPEAT STRIP_TAC THEN
11133   (MATCH_MP_TAC(TAUT
11134     `(~q ==> p) /\ (q ==> (p <=> r)) ==> (p <=> q ==> r)`) THEN
11135    CONJ_TAC THENL
11136     [DISCH_TAC THEN MATCH_MP_TAC(SET_RULE `s = {} ==> s SUBSET t`) THEN
11137      REWRITE_TAC[INTERVAL_EQ_EMPTY] THEN ASM_MESON_TAC[REAL_NOT_LT];
11138      ALL_TAC] THEN
11139    DISCH_TAC THEN EQ_TAC THEN REWRITE_TAC[SUBSET_INTERVAL_IMP] THEN
11140    REWRITE_TAC[SUBSET; IN_INTERVAL] THEN
11141    DISCH_THEN(MP_TAC o MATCH_MP lemma) THEN ANTS_TAC THENL
11142     [ASM_MESON_TAC[REAL_LT_BETWEEN; REAL_LE_BETWEEN]; ALL_TAC] THEN
11143    MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `i:num` THEN
11144    DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
11145    FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN
11146    ASM_REWRITE_TAC[] THEN POP_ASSUM_LIST(K ALL_TAC) THEN STRIP_TAC)
11147   THENL
11148    [ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_REFL];
11149     ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_REFL];
11150     ALL_TAC; ALL_TAC] THEN
11151   (REPEAT STRIP_TAC THENL
11152     [FIRST_X_ASSUM(MP_TAC o SPEC
11153       `((c:real^N)$i + min ((a:real^N)$i) ((d:real^N)$i)) / &2`) THEN
11154      POP_ASSUM MP_TAC THEN REAL_ARITH_TAC;
11155      FIRST_X_ASSUM(MP_TAC o SPEC
11156       `(max ((b:real^N)$i) ((c:real^N)$i) + (d:real^N)$i) / &2`) THEN
11157      POP_ASSUM MP_TAC THEN REAL_ARITH_TAC]));;
11158
11159 let DISJOINT_INTERVAL = prove
11160  (`!a b c d:real^N.
11161         (interval[a,b] INTER interval[c,d] = {} <=>
11162           ?i. 1 <= i /\ i <= dimindex(:N) /\
11163               (b$i < a$i \/ d$i < c$i \/ b$i < c$i \/ d$i < a$i)) /\
11164         (interval[a,b] INTER interval(c,d) = {} <=>
11165           ?i. 1 <= i /\ i <= dimindex(:N) /\
11166               (b$i < a$i \/ d$i <= c$i \/ b$i <= c$i \/ d$i <= a$i)) /\
11167         (interval(a,b) INTER interval[c,d] = {} <=>
11168           ?i. 1 <= i /\ i <= dimindex(:N) /\
11169               (b$i <= a$i \/ d$i < c$i \/ b$i <= c$i \/ d$i <= a$i)) /\
11170         (interval(a,b) INTER interval(c,d) = {} <=>
11171           ?i. 1 <= i /\ i <= dimindex(:N) /\
11172               (b$i <= a$i \/ d$i <= c$i \/ b$i <= c$i \/ d$i <= a$i))`,
11173   REWRITE_TAC[EXTENSION; IN_INTER; IN_INTERVAL; NOT_IN_EMPTY] THEN
11174   REWRITE_TAC[AND_FORALL_THM; NOT_FORALL_THM] THEN
11175   REWRITE_TAC[TAUT `~((p ==> q) /\ (p ==> r)) <=> p /\ (~q \/ ~r)`] THEN
11176   REWRITE_TAC[DE_MORGAN_THM] THEN REPEAT STRIP_TAC THEN
11177   (EQ_TAC THENL
11178     [DISCH_THEN(MP_TAC o SPEC
11179       `(lambda i. (max ((a:real^N)$i) ((c:real^N)$i) +
11180                    min ((b:real^N)$i) ((d:real^N)$i)) / &2):real^N`) THEN
11181      MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
11182      DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
11183      ASM_SIMP_TAC[LAMBDA_BETA] THEN REAL_ARITH_TAC;
11184      DISCH_THEN(fun th -> GEN_TAC THEN MP_TAC th) THEN
11185      MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN SIMP_TAC[] THEN
11186      REAL_ARITH_TAC]));;
11187
11188 let ENDS_IN_INTERVAL = prove
11189  (`(!a b. a IN interval[a,b] <=> ~(interval[a,b] = {})) /\
11190    (!a b. b IN interval[a,b] <=> ~(interval[a,b] = {})) /\
11191    (!a b. ~(a IN interval(a,b))) /\
11192    (!a b. ~(b IN interval(a,b)))`,
11193   REWRITE_TAC[IN_INTERVAL; INTERVAL_NE_EMPTY] THEN
11194   REWRITE_TAC[REAL_LE_REFL; REAL_LT_REFL] THEN
11195   MESON_TAC[DIMINDEX_GE_1; LE_REFL]);;
11196
11197 let ENDS_IN_UNIT_INTERVAL = prove
11198  (`vec 0 IN interval[vec 0,vec 1] /\
11199    vec 1 IN interval[vec 0,vec 1] /\
11200    ~(vec 0 IN interval(vec 0,vec 1)) /\
11201    ~(vec 1 IN interval(vec 0,vec 1))`,
11202   REWRITE_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY; VEC_COMPONENT] THEN
11203   REWRITE_TAC[REAL_POS]);;
11204
11205 let INTER_INTERVAL = prove
11206  (`interval[a,b] INTER interval[c,d] =
11207         interval[(lambda i. max (a$i) (c$i)),(lambda i. min (b$i) (d$i))]`,
11208   REWRITE_TAC[EXTENSION; IN_INTER; IN_INTERVAL] THEN
11209   SIMP_TAC[LAMBDA_BETA; REAL_MAX_LE; REAL_LE_MIN] THEN MESON_TAC[]);;
11210
11211 let INTERVAL_OPEN_SUBSET_CLOSED = prove
11212  (`!a b. interval(a,b) SUBSET interval[a,b]`,
11213   REWRITE_TAC[SUBSET; IN_INTERVAL] THEN MESON_TAC[REAL_LT_IMP_LE]);;
11214
11215 let OPEN_INTERVAL_LEMMA = prove
11216  (`!a b x. a < x /\ x < b
11217            ==> ?d. &0 < d /\ !x'. abs(x' - x) < d ==> a < x' /\ x' < b`,
11218   REPEAT STRIP_TAC THEN
11219   EXISTS_TAC `min (x - a) (b - x)` THEN REWRITE_TAC[REAL_LT_MIN] THEN
11220   ASM_REAL_ARITH_TAC);;
11221
11222 let OPEN_INTERVAL = prove
11223  (`!a:real^N b. open(interval (a,b))`,
11224   REPEAT GEN_TAC THEN REWRITE_TAC[open_def; interval; IN_ELIM_THM] THEN
11225   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
11226   SUBGOAL_THEN `!i. 1 <= i /\ i <= dimindex(:N)
11227                     ==> ?d. &0 < d /\
11228                             !x'. abs(x' - (x:real^N)$i) < d
11229                                  ==> (a:real^N)$i < x' /\ x' < (b:real^N)$i`
11230   MP_TAC THENL [ASM_SIMP_TAC[OPEN_INTERVAL_LEMMA]; ALL_TAC] THEN
11231   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
11232   REWRITE_TAC[SKOLEM_THM] THEN
11233   DISCH_THEN(X_CHOOSE_THEN `d:num->real` STRIP_ASSUME_TAC) THEN
11234   EXISTS_TAC `inf (IMAGE d (1..dimindex(:N)))` THEN
11235   SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; FINITE_NUMSEG;
11236            IMAGE_EQ_EMPTY; NOT_INSERT_EMPTY; NUMSEG_EMPTY;
11237            ARITH_RULE `n < 1 <=> (n = 0)`; DIMINDEX_NONZERO] THEN
11238   REWRITE_TAC[FORALL_IN_IMAGE; IN_NUMSEG; dist] THEN
11239   ASM_MESON_TAC[COMPONENT_LE_NORM; REAL_LET_TRANS; VECTOR_SUB_COMPONENT]);;
11240
11241 let CLOSED_INTERVAL = prove
11242  (`!a:real^N b. closed(interval [a,b])`,
11243   REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE; IN_INTERVAL] THEN
11244   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THENL
11245    [FIRST_X_ASSUM(MP_TAC o SPEC `(a:real^N)$i - (x:real^N)$i`);
11246     FIRST_X_ASSUM(MP_TAC o SPEC `(x:real^N)$i - (b:real^N)$i`)] THEN
11247   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
11248   DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
11249   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
11250   REWRITE_TAC[dist; REAL_NOT_LT] THEN
11251   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs((z - x :real^N)$i)` THEN
11252   ASM_SIMP_TAC[COMPONENT_LE_NORM] THEN
11253   ASM_SIMP_TAC[VECTOR_SUB_COMPONENT] THEN
11254   ASM_SIMP_TAC[REAL_ARITH `x < a /\ a <= z ==> a - x <= abs(z - x)`;
11255                REAL_ARITH `z <= b /\ b < x ==> x - b <= abs(z - x)`]);;
11256
11257 let INTERIOR_CLOSED_INTERVAL = prove
11258  (`!a:real^N b. interior(interval [a,b]) = interval (a,b)`,
11259   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
11260    [ALL_TAC;
11261     MATCH_MP_TAC INTERIOR_MAXIMAL THEN
11262     REWRITE_TAC[INTERVAL_OPEN_SUBSET_CLOSED; OPEN_INTERVAL]] THEN
11263   REWRITE_TAC[interior; SUBSET; IN_INTERVAL; IN_ELIM_THM] THEN
11264   X_GEN_TAC `x:real^N` THEN
11265   DISCH_THEN(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
11266   X_GEN_TAC `i:num` THEN STRIP_TAC THEN
11267   ASM_SIMP_TAC[REAL_LT_LE] THEN REPEAT STRIP_TAC THEN
11268   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [open_def]) THEN
11269   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
11270   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THENL
11271    [(let t = `x - (e / &2) % basis i :real^N` in
11272      DISCH_THEN(MP_TAC o SPEC t) THEN FIRST_X_ASSUM(MP_TAC o SPEC t));
11273     (let t = `x + (e / &2) % basis i :real^N` in
11274      DISCH_THEN(MP_TAC o SPEC t) THEN FIRST_X_ASSUM(MP_TAC o SPEC t))] THEN
11275   REWRITE_TAC[dist; VECTOR_ADD_SUB; VECTOR_ARITH `x - y - x = --y:real^N`] THEN
11276   ASM_SIMP_TAC[NORM_MUL; NORM_BASIS; NORM_NEG; REAL_MUL_RID;
11277                REAL_ARITH `&0 < e ==> abs(e / &2) < e`] THEN
11278   MATCH_MP_TAC(TAUT `~b ==> (a ==> b) ==> ~a`) THEN
11279   REWRITE_TAC[NOT_FORALL_THM] THEN EXISTS_TAC `i:num` THEN
11280   ASM_SIMP_TAC[DE_MORGAN_THM; VECTOR_SUB_COMPONENT; VECTOR_ADD_COMPONENT] THENL
11281    [DISJ1_TAC THEN REWRITE_TAC[REAL_ARITH `a <= a - b <=> ~(&0 < b)`];
11282     DISJ2_TAC THEN REWRITE_TAC[REAL_ARITH `a + b <= a <=> ~(&0 < b)`]] THEN
11283   ASM_SIMP_TAC[VECTOR_MUL_COMPONENT; basis; LAMBDA_BETA; REAL_MUL_RID] THEN
11284   ASM_REWRITE_TAC[REAL_HALF]);;
11285
11286 let INTERIOR_INTERVAL = prove
11287  (`(!a b. interior(interval[a,b]) = interval(a,b)) /\
11288    (!a b. interior(interval(a,b)) = interval(a,b))`,
11289   SIMP_TAC[INTERIOR_CLOSED_INTERVAL; INTERIOR_OPEN; OPEN_INTERVAL]);;
11290
11291 let BOUNDED_CLOSED_INTERVAL = prove
11292  (`!a b:real^N. bounded (interval [a,b])`,
11293   REPEAT STRIP_TAC THEN REWRITE_TAC[bounded; interval] THEN
11294   EXISTS_TAC `sum(1..dimindex(:N))
11295                  (\i. abs((a:real^N)$i) + abs((b:real^N)$i))` THEN
11296   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
11297   STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN
11298   EXISTS_TAC `sum(1..dimindex(:N)) (\i. abs((x:real^N)$i))` THEN
11299   REWRITE_TAC[NORM_LE_L1] THEN MATCH_MP_TAC SUM_LE THEN
11300   ASM_SIMP_TAC[FINITE_NUMSEG; IN_NUMSEG; REAL_ARITH
11301    `a <= x /\ x <= b ==> abs(x) <= abs(a) + abs(b)`]);;
11302
11303 let BOUNDED_INTERVAL = prove
11304  (`(!a b. bounded (interval [a,b])) /\ (!a b. bounded (interval (a,b)))`,
11305   MESON_TAC[BOUNDED_CLOSED_INTERVAL; BOUNDED_SUBSET;
11306             INTERVAL_OPEN_SUBSET_CLOSED]);;
11307
11308 let NOT_INTERVAL_UNIV = prove
11309  (`(!a b. ~(interval[a,b] = UNIV)) /\
11310    (!a b. ~(interval(a,b) = UNIV))`,
11311   MESON_TAC[BOUNDED_INTERVAL; NOT_BOUNDED_UNIV]);;
11312
11313 let COMPACT_INTERVAL = prove
11314  (`!a b. compact (interval [a,b])`,
11315   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_INTERVAL; CLOSED_INTERVAL]);;
11316
11317 let OPEN_INTERVAL_MIDPOINT = prove
11318  (`!a b:real^N.
11319         ~(interval(a,b) = {}) ==> (inv(&2) % (a + b)) IN interval(a,b)`,
11320   REWRITE_TAC[INTERVAL_NE_EMPTY; IN_INTERVAL] THEN
11321   SIMP_TAC[VECTOR_MUL_COMPONENT; VECTOR_ADD_COMPONENT] THEN
11322   REPEAT GEN_TAC THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
11323   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN REAL_ARITH_TAC);;
11324
11325 let OPEN_CLOSED_INTERVAL_CONVEX = prove
11326  (`!a b x y:real^N e.
11327         x IN interval(a,b) /\ y IN interval[a,b] /\ &0 < e /\ e <= &1
11328         ==> (e % x + (&1 - e) % y) IN interval(a,b)`,
11329   REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
11330    `(c /\ d ==> a /\ b ==> e) ==> a /\ b /\ c /\ d ==> e`) THEN
11331   STRIP_TAC THEN REWRITE_TAC[IN_INTERVAL; AND_FORALL_THM] THEN
11332   SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN
11333   MATCH_MP_TAC MONO_FORALL THEN
11334   GEN_TAC THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
11335   ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
11336   SUBST1_TAC(REAL_ARITH `(a:real^N)$i = e * a$i + (&1 - e) * a$i`) THEN
11337   SUBST1_TAC(REAL_ARITH `(b:real^N)$i = e * b$i + (&1 - e) * b$i`) THEN
11338   CONJ_TAC THEN MATCH_MP_TAC REAL_LTE_ADD2 THEN
11339   ASM_SIMP_TAC[REAL_LT_LMUL_EQ; REAL_LE_LMUL; REAL_SUB_LE]);;
11340
11341 let CLOSURE_OPEN_INTERVAL = prove
11342  (`!a b:real^N.
11343      ~(interval(a,b) = {}) ==> closure(interval(a,b)) = interval[a,b]`,
11344   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
11345    [MATCH_MP_TAC CLOSURE_MINIMAL THEN
11346     REWRITE_TAC[INTERVAL_OPEN_SUBSET_CLOSED; CLOSED_INTERVAL];
11347     ALL_TAC] THEN
11348   REWRITE_TAC[SUBSET; closure; IN_UNION] THEN X_GEN_TAC `x:real^N` THEN
11349   DISCH_TAC THEN MATCH_MP_TAC(TAUT `(~b ==> c) ==> b \/ c`) THEN DISCH_TAC THEN
11350   REWRITE_TAC[IN_ELIM_THM; LIMPT_SEQUENTIAL] THEN
11351   ABBREV_TAC `(c:real^N) = inv(&2) % (a + b)` THEN
11352   EXISTS_TAC `\n. (x:real^N) + inv(&n + &1) % (c - x)` THEN CONJ_TAC THENL
11353    [X_GEN_TAC `n:num` THEN REWRITE_TAC[IN_DELETE] THEN
11354     REWRITE_TAC[VECTOR_ARITH `x + a = x <=> a = vec 0`] THEN
11355     REWRITE_TAC[VECTOR_MUL_EQ_0; REAL_INV_EQ_0] THEN
11356     REWRITE_TAC[VECTOR_SUB_EQ; REAL_ARITH `~(&n + &1 = &0)`] THEN
11357     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[OPEN_INTERVAL_MIDPOINT]] THEN
11358     REWRITE_TAC[VECTOR_ARITH `x + a % (y - x) = a % y + (&1 - a) % x`] THEN
11359     MATCH_MP_TAC OPEN_CLOSED_INTERVAL_CONVEX THEN
11360     CONJ_TAC THENL [ASM_MESON_TAC[OPEN_INTERVAL_MIDPOINT]; ALL_TAC] THEN
11361     ASM_REWRITE_TAC[REAL_LT_INV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
11362     MATCH_MP_TAC REAL_INV_LE_1 THEN REAL_ARITH_TAC;
11363     ALL_TAC] THEN
11364   GEN_REWRITE_TAC LAND_CONV [VECTOR_ARITH `x:real^N = x + &0 % (c - x)`] THEN
11365   MATCH_MP_TAC LIM_ADD THEN REWRITE_TAC[LIM_CONST] THEN
11366   MATCH_MP_TAC LIM_VMUL THEN REWRITE_TAC[LIM_CONST] THEN
11367   REWRITE_TAC[LIM_SEQUENTIALLY; o_THM; DIST_LIFT; REAL_SUB_RZERO] THEN
11368   X_GEN_TAC `e:real` THEN GEN_REWRITE_TAC LAND_CONV [REAL_ARCH_INV] THEN
11369   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
11370   STRIP_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
11371   REWRITE_TAC[REAL_ABS_INV] THEN MATCH_MP_TAC REAL_LET_TRANS THEN
11372   EXISTS_TAC `inv(&N)` THEN ASM_REWRITE_TAC[] THEN
11373   MATCH_MP_TAC REAL_LE_INV2 THEN UNDISCH_TAC `N:num <= n` THEN
11374   UNDISCH_TAC `~(N = 0)` THEN
11375   REWRITE_TAC[GSYM LT_NZ; GSYM REAL_OF_NUM_LE; GSYM REAL_OF_NUM_LT] THEN
11376   REAL_ARITH_TAC);;
11377
11378 let CLOSURE_INTERVAL = prove
11379  (`(!a b. closure(interval[a,b]) = interval[a,b]) /\
11380    (!a b. closure(interval(a,b)) =
11381           if interval(a,b) = {} then {} else interval[a,b])`,
11382   SIMP_TAC[CLOSURE_CLOSED; CLOSED_INTERVAL] THEN REPEAT GEN_TAC THEN
11383   COND_CASES_TAC THEN ASM_SIMP_TAC[CLOSURE_OPEN_INTERVAL; CLOSURE_EMPTY]);;
11384
11385 let BOUNDED_SUBSET_OPEN_INTERVAL_SYMMETRIC = prove
11386  (`!s:real^N->bool. bounded s ==> ?a. s SUBSET interval(--a,a)`,
11387   REWRITE_TAC[BOUNDED_POS; LEFT_IMP_EXISTS_THM] THEN
11388   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `B:real`] THEN STRIP_TAC THEN
11389   EXISTS_TAC `(lambda i. B + &1):real^N` THEN
11390   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
11391   SIMP_TAC[IN_INTERVAL; LAMBDA_BETA; REAL_BOUNDS_LT; VECTOR_NEG_COMPONENT] THEN
11392   ASM_MESON_TAC[COMPONENT_LE_NORM;
11393                 REAL_ARITH `x <= y ==> a <= x ==> a < y + &1`]);;
11394
11395 let BOUNDED_SUBSET_OPEN_INTERVAL = prove
11396  (`!s:real^N->bool. bounded s ==> ?a b. s SUBSET interval(a,b)`,
11397   MESON_TAC[BOUNDED_SUBSET_OPEN_INTERVAL_SYMMETRIC]);;
11398
11399 let BOUNDED_SUBSET_CLOSED_INTERVAL_SYMMETRIC = prove
11400  (`!s:real^N->bool. bounded s ==> ?a. s SUBSET interval[--a,a]`,
11401   GEN_TAC THEN
11402   DISCH_THEN(MP_TAC o MATCH_MP BOUNDED_SUBSET_OPEN_INTERVAL_SYMMETRIC) THEN
11403   MATCH_MP_TAC MONO_EXISTS THEN
11404   SIMP_TAC[IN_BALL; IN_INTERVAL; SUBSET; REAL_LT_IMP_LE]);;
11405
11406 let BOUNDED_SUBSET_CLOSED_INTERVAL = prove
11407  (`!s:real^N->bool. bounded s ==> ?a b. s SUBSET interval[a,b]`,
11408   MESON_TAC[BOUNDED_SUBSET_CLOSED_INTERVAL_SYMMETRIC]);;
11409
11410 let FRONTIER_CLOSED_INTERVAL = prove
11411  (`!a b. frontier(interval[a,b]) = interval[a,b] DIFF interval(a,b)`,
11412   SIMP_TAC[frontier; INTERIOR_CLOSED_INTERVAL; CLOSURE_CLOSED;
11413            CLOSED_INTERVAL]);;
11414
11415 let FRONTIER_OPEN_INTERVAL = prove
11416  (`!a b. frontier(interval(a,b)) =
11417                 if interval(a,b) = {} then {}
11418                 else interval[a,b] DIFF interval(a,b)`,
11419   REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[FRONTIER_EMPTY] THEN
11420   ASM_SIMP_TAC[frontier; CLOSURE_OPEN_INTERVAL; INTERIOR_OPEN;
11421                OPEN_INTERVAL]);;
11422
11423 let INTER_INTERVAL_MIXED_EQ_EMPTY = prove
11424  (`!a b c d:real^N.
11425         ~(interval(c,d) = {})
11426         ==> (interval(a,b) INTER interval[c,d] = {} <=>
11427              interval(a,b) INTER interval(c,d) = {})`,
11428   SIMP_TAC[GSYM CLOSURE_OPEN_INTERVAL; OPEN_INTER_CLOSURE_EQ_EMPTY;
11429            OPEN_INTERVAL]);;
11430
11431 let INTERVAL_TRANSLATION = prove
11432  (`(!c a b. interval[c + a,c + b] = IMAGE (\x. c + x) (interval[a,b])) /\
11433    (!c a b. interval(c + a,c + b) = IMAGE (\x. c + x) (interval(a,b)))`,
11434   REWRITE_TAC[interval] THEN CONJ_TAC THEN GEOM_TRANSLATE_TAC[] THEN
11435   REWRITE_TAC[VECTOR_ADD_COMPONENT; REAL_LT_LADD; REAL_LE_LADD]);;
11436
11437 add_translation_invariants
11438  [CONJUNCT1 INTERVAL_TRANSLATION; CONJUNCT2 INTERVAL_TRANSLATION];;
11439
11440 let EMPTY_AS_INTERVAL = prove
11441  (`{} = interval[vec 1,vec 0]`,
11442   SIMP_TAC[EXTENSION; NOT_IN_EMPTY; IN_INTERVAL; VEC_COMPONENT] THEN
11443   GEN_TAC THEN DISCH_THEN(MP_TAC o SPEC `1`) THEN
11444   REWRITE_TAC[LE_REFL; DIMINDEX_GE_1] THEN REAL_ARITH_TAC);;
11445
11446 let UNIT_INTERVAL_NONEMPTY = prove
11447  (`~(interval[vec 0:real^N,vec 1] = {}) /\
11448    ~(interval(vec 0:real^N,vec 1) = {})`,
11449   SIMP_TAC[INTERVAL_NE_EMPTY; VEC_COMPONENT; REAL_LT_01; REAL_POS]);;
11450
11451 let IMAGE_STRETCH_INTERVAL = prove
11452  (`!a b:real^N m.
11453     IMAGE (\x. lambda k. m(k) * x$k) (interval[a,b]) =
11454         if interval[a,b] = {} then {}
11455         else interval[(lambda k. min (m(k) * a$k) (m(k) * b$k)):real^N,
11456                       (lambda k. max (m(k) * a$k) (m(k) * b$k))]`,
11457   REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_SIMP_TAC[IMAGE_CLAUSES] THEN
11458   ASM_SIMP_TAC[EXTENSION; IN_IMAGE; CART_EQ; IN_INTERVAL; AND_FORALL_THM;
11459                TAUT `(a ==> b) /\ (a ==> c) <=> a ==> b /\ c`;
11460                 LAMBDA_BETA; GSYM LAMBDA_SKOLEM] THEN
11461   X_GEN_TAC `x:real^N` THEN MATCH_MP_TAC(MESON[]
11462    `(!x. p x ==> (q x <=> r x))
11463     ==> ((!x. p x ==> q x) <=> (!x. p x ==> r x))`) THEN
11464   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INTERVAL_NE_EMPTY]) THEN
11465   MATCH_MP_TAC MONO_FORALL THEN
11466   X_GEN_TAC `k:num` THEN ASM_CASES_TAC `1 <= k /\ k <= dimindex(:N)` THEN
11467   ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `(m:num->real) k = &0` THENL
11468    [ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_MAX_ACI; REAL_MIN_ACI] THEN
11469     ASM_MESON_TAC[REAL_LE_ANTISYM; REAL_LE_REFL];
11470     ALL_TAC] THEN
11471   ASM_SIMP_TAC[REAL_FIELD `~(m = &0) ==> (x = m * y <=> y = x / m)`] THEN
11472   REWRITE_TAC[UNWIND_THM2] THEN FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP
11473    (REAL_ARITH `~(z = &0) ==> &0 < z \/ &0 < --z`))
11474   THENL
11475    [ALL_TAC;
11476     ONCE_REWRITE_TAC[GSYM REAL_LE_NEG2] THEN
11477     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
11478     REWRITE_TAC[REAL_ARITH `--(max a b) = min (--a) (--b)`;
11479                 REAL_ARITH `--(min a b) = max (--a) (--b)`; real_div;
11480                 GSYM REAL_MUL_RNEG; GSYM REAL_INV_NEG] THEN
11481     REWRITE_TAC[GSYM real_div]] THEN
11482   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ] THEN
11483   ASM_SIMP_TAC[real_min; real_max; REAL_LE_LMUL_EQ; REAL_LE_RMUL_EQ] THEN
11484   REAL_ARITH_TAC);;
11485
11486 let INTERVAL_IMAGE_STRETCH_INTERVAL = prove
11487  (`!a b:real^N m. ?u v:real^N.
11488      IMAGE (\x. lambda k. m k * x$k) (interval[a,b]) = interval[u,v]`,
11489   REWRITE_TAC[IMAGE_STRETCH_INTERVAL] THEN MESON_TAC[EMPTY_AS_INTERVAL]);;
11490
11491 let CLOSED_INTERVAL_IMAGE_UNIT_INTERVAL = prove
11492  (`!a b:real^N.
11493         ~(interval[a,b] = {})
11494         ==> interval[a,b] = IMAGE (\x:real^N. a + x)
11495                                   (IMAGE (\x. (lambda i. (b$i - a$i) * x$i))
11496                                          (interval[vec 0:real^N,vec 1]))`,
11497   REWRITE_TAC[INTERVAL_NE_EMPTY] THEN REPEAT STRIP_TAC THEN
11498   REWRITE_TAC[IMAGE_STRETCH_INTERVAL; UNIT_INTERVAL_NONEMPTY] THEN
11499   REWRITE_TAC[GSYM INTERVAL_TRANSLATION] THEN
11500   REWRITE_TAC[EXTENSION; IN_INTERVAL] THEN
11501   SIMP_TAC[LAMBDA_BETA; VECTOR_ADD_COMPONENT; VEC_COMPONENT] THEN
11502   GEN_TAC THEN REWRITE_TAC[REAL_MUL_RZERO; REAL_MUL_RID] THEN
11503   MATCH_MP_TAC(MESON[] `(!x. P x <=> Q x) ==> ((!x. P x) <=> (!x. Q x))`) THEN
11504   POP_ASSUM MP_TAC THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `i:num` THEN
11505   ASM_CASES_TAC `1 <= i /\ i <= dimindex(:N)` THEN ASM_REWRITE_TAC[] THEN
11506   REAL_ARITH_TAC);;
11507
11508 let SUMS_INTERVALS = prove
11509  (`(!a b c d:real^N.
11510         ~(interval[a,b] = {}) /\ ~(interval[c,d] = {})
11511         ==> {x + y | x IN interval[a,b] /\ y IN interval[c,d]} =
11512             interval[a+c,b+d]) /\
11513    (!a b c d:real^N.
11514         ~(interval(a,b) = {}) /\ ~(interval(c,d) = {})
11515         ==> {x + y | x IN interval(a,b) /\ y IN interval(c,d)} =
11516             interval(a+c,b+d))`,
11517   CONJ_TAC THEN REPEAT GEN_TAC THEN REWRITE_TAC[INTERVAL_NE_EMPTY] THEN
11518   STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_INTERVAL; IN_ELIM_THM] THEN
11519   REWRITE_TAC[TAUT `(a /\ b) /\ c <=> c /\ a /\ b`] THEN
11520   REWRITE_TAC[VECTOR_ARITH `x:real^N = y + z <=> z = x - y`] THEN
11521   REWRITE_TAC[UNWIND_THM2; VECTOR_ADD_COMPONENT; VECTOR_SUB_COMPONENT] THEN
11522   (X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
11523    [DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC);
11524     DISCH_TAC THEN
11525     REWRITE_TAC[AND_FORALL_THM; GSYM LAMBDA_SKOLEM;
11526                 TAUT `(p ==> q) /\ (p ==> r) <=> p ==> q /\ r`] THEN
11527     REWRITE_TAC[REAL_ARITH
11528      `((a <= y /\ y <= b) /\ c <= x - y /\ x - y <= d <=>
11529        max a (x - d) <= y /\ y <= min b (x - c)) /\
11530       ((a < y /\ y < b) /\ c < x - y /\ x - y < d <=>
11531        max a (x - d) < y /\ y < min b (x - c))`] THEN
11532     REWRITE_TAC[GSYM REAL_LE_BETWEEN; GSYM REAL_LT_BETWEEN]] THEN
11533   X_GEN_TAC `i:num` THEN STRIP_TAC THEN
11534   REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `i:num`)) THEN
11535   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC));;
11536
11537 let PCROSS_INTERVAL = prove
11538  (`!a b:real^M c d:real^N.
11539         interval[a,b] PCROSS interval[c,d] =
11540         interval[pastecart a c,pastecart b d]`,
11541   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN
11542   REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
11543   SIMP_TAC[IN_INTERVAL; pastecart; LAMBDA_BETA; DIMINDEX_FINITE_SUM] THEN
11544   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^N`] THEN EQ_TAC THEN STRIP_TAC THENL
11545    [X_GEN_TAC `i:num` THEN STRIP_TAC THEN
11546     COND_CASES_TAC THEN ASM_SIMP_TAC[] THEN
11547     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC;
11548     CONJ_TAC THEN X_GEN_TAC `i:num` THEN STRIP_TAC THENL
11549      [FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN ASM_REWRITE_TAC[] THEN
11550       DISCH_THEN MATCH_MP_TAC THEN ASM_ARITH_TAC;
11551       FIRST_X_ASSUM(MP_TAC o SPEC `i + dimindex(:M)`) THEN
11552       COND_CASES_TAC THEN ASM_REWRITE_TAC[ADD_SUB] THENL
11553        [ASM_ARITH_TAC;
11554         DISCH_THEN MATCH_MP_TAC THEN ASM_ARITH_TAC]]]);;
11555
11556 let OPEN_CONTAINS_INTERVAL,OPEN_CONTAINS_OPEN_INTERVAL = (CONJ_PAIR o prove)
11557  (`(!s:real^N->bool.
11558         open s <=>
11559         !x. x IN s ==> ?a b. x IN interval(a,b) /\ interval[a,b] SUBSET s) /\
11560    (!s:real^N->bool.
11561         open s <=>
11562         !x. x IN s ==> ?a b. x IN interval(a,b) /\ interval(a,b) SUBSET s)`,
11563   REWRITE_TAC[AND_FORALL_THM] THEN GEN_TAC THEN
11564   MATCH_MP_TAC(TAUT
11565    `(q ==> r) /\ (r ==> p) /\ (p ==> q) ==> (p <=> q) /\ (p <=> r)`) THEN
11566   REPEAT CONJ_TAC THENL
11567    [MESON_TAC[SUBSET_TRANS; INTERVAL_OPEN_SUBSET_CLOSED];
11568     DISCH_TAC THEN REWRITE_TAC[OPEN_CONTAINS_BALL] THEN
11569     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
11570     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
11571     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
11572     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN
11573     MP_TAC(ISPEC `interval(a:real^N,b)` OPEN_CONTAINS_BALL) THEN
11574     REWRITE_TAC[OPEN_INTERVAL] THEN
11575     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
11576     MATCH_MP_TAC MONO_EXISTS THEN
11577     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
11578     ASM_MESON_TAC[SUBSET_TRANS; INTERVAL_OPEN_SUBSET_CLOSED];
11579     DISCH_TAC THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
11580     FIRST_ASSUM(MP_TAC o SPEC `x:real^N` o
11581       GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
11582     ASM_REWRITE_TAC[] THEN
11583     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
11584     EXISTS_TAC `x - e / &(dimindex(:N)) % vec 1:real^N` THEN
11585     EXISTS_TAC `x + e / &(dimindex(:N)) % vec 1:real^N` THEN
11586     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
11587      `b SUBSET s ==> x IN i /\ j SUBSET b ==> x IN i /\ j SUBSET s`)) THEN
11588     SIMP_TAC[IN_INTERVAL; VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT; IN_CBALL;
11589              VEC_COMPONENT; VECTOR_ADD_COMPONENT; SUBSET; REAL_MUL_RID] THEN
11590     REWRITE_TAC[REAL_ARITH `x - e < x /\ x < x + e <=> &0 < e`;
11591                 REAL_ARITH `x - e <= y /\ y <= x + e <=> abs(x - y) <= e`] THEN
11592     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1] THEN
11593     X_GEN_TAC `y:real^N` THEN REWRITE_TAC[GSYM VECTOR_SUB_COMPONENT] THEN
11594     DISCH_TAC THEN REWRITE_TAC[dist] THEN
11595     MATCH_MP_TAC REAL_LE_TRANS THEN
11596     EXISTS_TAC `sum(1..dimindex(:N)) (\i. abs((x - y:real^N)$i))` THEN
11597     REWRITE_TAC[NORM_LE_L1] THEN MATCH_MP_TAC SUM_BOUND_GEN THEN
11598     ASM_SIMP_TAC[CARD_NUMSEG_1; IN_NUMSEG; FINITE_NUMSEG] THEN
11599     REWRITE_TAC[NUMSEG_EMPTY; NOT_LT; DIMINDEX_GE_1]]);;
11600
11601 let DIAMETER_INTERVAL = prove
11602  (`(!a b:real^N.
11603         diameter(interval[a,b]) =
11604         if interval[a,b] = {} then &0 else norm(b - a)) /\
11605    (!a b:real^N.
11606         diameter(interval(a,b)) =
11607         if interval(a,b) = {} then &0 else norm(b - a))`,
11608   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN
11609   ASM_CASES_TAC `interval[a:real^N,b] = {}` THENL
11610    [ASM_MESON_TAC[INTERVAL_OPEN_SUBSET_CLOSED; SUBSET_EMPTY; DIAMETER_EMPTY];
11611     ASM_REWRITE_TAC[]] THEN
11612   MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
11613    [REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
11614     ASM_SIMP_TAC[DIAMETER_BOUNDED_BOUND;
11615                  ENDS_IN_INTERVAL; BOUNDED_INTERVAL] THEN
11616     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
11617      `diameter(cball(inv(&2) % (a + b):real^N,norm(b - a) / &2))` THEN
11618     CONJ_TAC THENL
11619      [MATCH_MP_TAC DIAMETER_SUBSET THEN REWRITE_TAC[BOUNDED_CBALL] THEN
11620       REWRITE_TAC[SUBSET; IN_INTERVAL; IN_CBALL] THEN
11621       GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[dist] THEN
11622       REWRITE_TAC[GSYM NORM_MUL; REAL_ARITH `x / &2 = abs(inv(&2)) * x`] THEN
11623       MATCH_MP_TAC NORM_LE_COMPONENTWISE THEN
11624       X_GEN_TAC `i:num` THEN DISCH_TAC THEN
11625       FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN
11626       ASM_REWRITE_TAC[VECTOR_ADD_COMPONENT; VECTOR_SUB_COMPONENT;
11627                       VECTOR_MUL_COMPONENT] THEN
11628       REAL_ARITH_TAC;
11629       REWRITE_TAC[DIAMETER_CBALL] THEN NORM_ARITH_TAC];
11630     DISCH_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[DIAMETER_EMPTY] THEN
11631     SUBGOAL_THEN `interval[a:real^N,b] = closure(interval(a,b))`
11632     SUBST_ALL_TAC THEN ASM_REWRITE_TAC[CLOSURE_INTERVAL] THEN
11633     ASM_MESON_TAC[DIAMETER_CLOSURE; BOUNDED_INTERVAL]]);;
11634
11635 let IMAGE_TWIZZLE_INTERVAL = prove
11636  (`!p a b. dimindex(:M) = dimindex(:N) /\ p permutes 1..dimindex(:N)
11637            ==> IMAGE ((\x. lambda i. x$(p i)):real^M->real^N) (interval[a,b]) =
11638                interval[(lambda i. a$(p i)),(lambda i. b$(p i))]`,
11639   REPEAT STRIP_TAC THEN
11640   MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
11641   SIMP_TAC[IN_INTERVAL; CART_EQ; LAMBDA_BETA] THEN CONJ_TAC THENL
11642    [X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
11643     EXISTS_TAC `(lambda i. (y:real^N)$(inverse p i)):real^M` THEN
11644     IMP_REWRITE_TAC[LAMBDA_BETA] THEN
11645     ASM_REWRITE_TAC[GSYM IN_NUMSEG] THEN
11646     ASM_MESON_TAC[PERMUTES_INVERSE_EQ; PERMUTES_IN_IMAGE];
11647     REWRITE_TAC[GSYM IN_NUMSEG] THEN
11648     ASM_MESON_TAC[PERMUTES_INVERSES; PERMUTES_IN_IMAGE]]);;
11649
11650 (* ------------------------------------------------------------------------- *)
11651 (* Some special cases for intervals in R^1.                                  *)
11652 (* ------------------------------------------------------------------------- *)
11653
11654 let INTERVAL_CASES_1 = prove
11655  (`!x:real^1. x IN interval[a,b] ==> x IN interval(a,b) \/ (x = a) \/ (x = b)`,
11656   REWRITE_TAC[CART_EQ; IN_INTERVAL; FORALL_DIMINDEX_1] THEN REAL_ARITH_TAC);;
11657
11658 let IN_INTERVAL_1 = prove
11659  (`!a b x:real^1.
11660         (x IN interval[a,b] <=> drop a <= drop x /\ drop x <= drop b) /\
11661         (x IN interval(a,b) <=> drop a < drop x /\ drop x < drop b)`,
11662   REWRITE_TAC[IN_INTERVAL; drop; CONJ_ASSOC; DIMINDEX_1; LE_ANTISYM] THEN
11663   MESON_TAC[]);;
11664
11665 let INTERVAL_EQ_EMPTY_1 = prove
11666  (`!a b:real^1.
11667         (interval[a,b] = {} <=> drop b < drop a) /\
11668         (interval(a,b) = {} <=> drop b <= drop a)`,
11669   REWRITE_TAC[INTERVAL_EQ_EMPTY; drop; CONJ_ASSOC; DIMINDEX_1; LE_ANTISYM] THEN
11670   MESON_TAC[]);;
11671
11672 let INTERVAL_NE_EMPTY_1 = prove
11673  (`(!a b:real^1. ~(interval[a,b] = {}) <=> drop a <= drop b) /\
11674    (!a b:real^1. ~(interval(a,b) = {}) <=> drop a < drop b)`,
11675   REWRITE_TAC[INTERVAL_EQ_EMPTY_1] THEN REAL_ARITH_TAC);;
11676
11677 let SUBSET_INTERVAL_1 = prove
11678  (`!a b c d.
11679         (interval[a,b] SUBSET interval[c,d] <=>
11680                 drop b < drop a \/
11681                 drop c <= drop a /\ drop a <= drop b /\ drop b <= drop d) /\
11682         (interval[a,b] SUBSET interval(c,d) <=>
11683                 drop b < drop a \/
11684                 drop c < drop a /\ drop a <= drop b /\ drop b < drop d) /\
11685         (interval(a,b) SUBSET interval[c,d] <=>
11686                 drop b <= drop a \/
11687                 drop c <= drop a /\ drop a < drop b /\ drop b <= drop d) /\
11688         (interval(a,b) SUBSET interval(c,d) <=>
11689                 drop b <= drop a \/
11690                 drop c <= drop a /\ drop a < drop b /\ drop b <= drop d)`,
11691   REWRITE_TAC[SUBSET_INTERVAL; FORALL_1; DIMINDEX_1; drop] THEN
11692   REAL_ARITH_TAC);;
11693
11694 let EQ_INTERVAL_1 = prove
11695  (`!a b c d:real^1.
11696        (interval[a,b] = interval[c,d] <=>
11697           drop b < drop a /\ drop d < drop c \/
11698           drop a = drop c /\ drop b = drop d)`,
11699   REWRITE_TAC[SET_RULE `s = t <=> s SUBSET t /\ t SUBSET s`] THEN
11700   REWRITE_TAC[SUBSET_INTERVAL_1] THEN REAL_ARITH_TAC);;
11701
11702 let DISJOINT_INTERVAL_1 = prove
11703  (`!a b c d:real^1.
11704         (interval[a,b] INTER interval[c,d] = {} <=>
11705           drop b < drop a \/ drop d < drop c \/
11706           drop b < drop c \/ drop d < drop a) /\
11707         (interval[a,b] INTER interval(c,d) = {} <=>
11708           drop b < drop a \/ drop d <= drop c \/
11709           drop b <= drop c \/ drop d <= drop a) /\
11710         (interval(a,b) INTER interval[c,d] = {} <=>
11711           drop b <= drop a \/ drop d < drop c \/
11712           drop b <= drop c \/ drop d <= drop a) /\
11713         (interval(a,b) INTER interval(c,d) = {} <=>
11714           drop b <= drop a \/ drop d <= drop c \/
11715           drop b <= drop c \/ drop d <= drop a)`,
11716   REWRITE_TAC[DISJOINT_INTERVAL; CONJ_ASSOC; DIMINDEX_1; LE_ANTISYM;
11717               UNWIND_THM1; drop]);;
11718
11719 let OPEN_CLOSED_INTERVAL_1 = prove
11720  (`!a b:real^1. interval(a,b) = interval[a,b] DIFF {a,b}`,
11721   REWRITE_TAC[EXTENSION; IN_INTERVAL_1; IN_DIFF; IN_INSERT; NOT_IN_EMPTY] THEN
11722   REWRITE_TAC[GSYM DROP_EQ] THEN REAL_ARITH_TAC);;
11723
11724 let CLOSED_OPEN_INTERVAL_1 = prove
11725  (`!a b:real^1. drop a <= drop b ==> interval[a,b] = interval(a,b) UNION {a,b}`,
11726   REWRITE_TAC[EXTENSION; IN_INTERVAL_1; IN_UNION; IN_INSERT; NOT_IN_EMPTY] THEN
11727   REWRITE_TAC[GSYM DROP_EQ] THEN REAL_ARITH_TAC);;
11728
11729 let BALL_1 = prove
11730  (`!x:real^1 r. cball(x,r) = interval[x - lift r,x + lift r] /\
11731                 ball(x,r) = interval(x - lift r,x + lift r)`,
11732   REWRITE_TAC[EXTENSION; IN_BALL; IN_CBALL; IN_INTERVAL_1] THEN
11733   REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB; LIFT_DROP; DROP_ADD] THEN
11734   REAL_ARITH_TAC);;
11735
11736 let SPHERE_1 = prove
11737  (`!a:real^1 r. sphere(a,r) = if r < &0 then {} else {a - lift r,a + lift r}`,
11738   REPEAT GEN_TAC THEN REWRITE_TAC[sphere] THEN COND_CASES_TAC THEN
11739   REWRITE_TAC[DIST_REAL; GSYM drop; FORALL_DROP] THEN
11740   REWRITE_TAC[EXTENSION; IN_INSERT; NOT_IN_EMPTY; IN_ELIM_THM] THEN
11741   REWRITE_TAC[GSYM DROP_EQ; DROP_ADD; DROP_SUB; LIFT_DROP] THEN
11742   ASM_REAL_ARITH_TAC);;
11743
11744 let FINITE_SPHERE_1 = prove
11745  (`!a:real^1 r. FINITE(sphere(a,r))`,
11746   REPEAT GEN_TAC THEN REWRITE_TAC[SPHERE_1] THEN
11747   MESON_TAC[FINITE_INSERT; FINITE_EMPTY]);;
11748
11749 let FINITE_INTERVAL_1 = prove
11750  (`(!a b. FINITE(interval[a,b]) <=> drop b <= drop a) /\
11751    (!a b. FINITE(interval(a,b)) <=> drop b <= drop a)`,
11752   REWRITE_TAC[OPEN_CLOSED_INTERVAL_1] THEN
11753   REWRITE_TAC[SET_RULE `s DIFF {a,b} = s DELETE a DELETE b`] THEN
11754   REWRITE_TAC[FINITE_DELETE] THEN REPEAT GEN_TAC THEN
11755   SUBGOAL_THEN `interval[a,b] = IMAGE lift {x | drop a <= x /\ x <= drop b}`
11756   SUBST1_TAC THENL
11757    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
11758     CONJ_TAC THENL [MESON_TAC[LIFT_DROP]; ALL_TAC] THEN
11759     REWRITE_TAC[IN_INTERVAL_1; IN_ELIM_THM; LIFT_DROP];
11760     SIMP_TAC[FINITE_IMAGE_INJ_EQ; LIFT_EQ; FINITE_REAL_INTERVAL]]);;
11761
11762 let BALL_INTERVAL = prove
11763  (`!x:real^1 e. ball(x,e) = interval(x - lift e,x + lift e)`,
11764   REWRITE_TAC[EXTENSION; IN_BALL; IN_INTERVAL_1; DIST_REAL] THEN
11765   REWRITE_TAC[GSYM drop; DROP_SUB; DROP_ADD; LIFT_DROP] THEN REAL_ARITH_TAC);;
11766
11767 let CBALL_INTERVAL = prove
11768  (`!x:real^1 e. cball(x,e) = interval[x - lift e,x + lift e]`,
11769   REWRITE_TAC[EXTENSION; IN_CBALL; IN_INTERVAL_1; DIST_REAL] THEN
11770   REWRITE_TAC[GSYM drop; DROP_SUB; DROP_ADD; LIFT_DROP] THEN REAL_ARITH_TAC);;
11771
11772 let BALL_INTERVAL_0 = prove
11773  (`!e. ball(vec 0:real^1,e) = interval(--lift e,lift e)`,
11774   GEN_TAC THEN REWRITE_TAC[BALL_INTERVAL] THEN AP_TERM_TAC THEN
11775   BINOP_TAC THEN VECTOR_ARITH_TAC);;
11776
11777 let CBALL_INTERVAL_0 = prove
11778  (`!e. cball(vec 0:real^1,e) = interval[--lift e,lift e]`,
11779   GEN_TAC THEN REWRITE_TAC[CBALL_INTERVAL] THEN AP_TERM_TAC THEN
11780   AP_THM_TAC THEN AP_TERM_TAC THEN BINOP_TAC THEN VECTOR_ARITH_TAC);;
11781
11782 let INTER_INTERVAL_1 = prove
11783  (`!a b c d:real^1.
11784         interval[a,b] INTER interval[c,d] =
11785         interval[lift(max (drop a) (drop c)),lift(min (drop b) (drop d))]`,
11786   REWRITE_TAC[EXTENSION; IN_INTER; IN_INTERVAL_1; real_max; real_min] THEN
11787   REPEAT GEN_TAC THEN
11788   REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[LIFT_DROP]) THEN
11789   ASM_REAL_ARITH_TAC);;
11790
11791 let CLOSED_DIFF_OPEN_INTERVAL_1 = prove
11792  (`!a b:real^1.
11793         interval[a,b] DIFF interval(a,b) =
11794         if interval[a,b] = {} then {} else {a,b}`,
11795   REWRITE_TAC[EXTENSION; IN_DIFF; INTERVAL_EQ_EMPTY_1; IN_INTERVAL_1] THEN
11796   REPEAT GEN_TAC THEN COND_CASES_TAC THEN
11797   ASM_REWRITE_TAC[NOT_IN_EMPTY; IN_INSERT; NOT_IN_EMPTY] THEN
11798   REWRITE_TAC[GSYM DROP_EQ] THEN ASM_REAL_ARITH_TAC);;
11799
11800 (* ------------------------------------------------------------------------- *)
11801 (* Intervals in general, including infinite and mixtures of open and closed. *)
11802 (* ------------------------------------------------------------------------- *)
11803
11804 let is_interval = new_definition
11805   `is_interval(s:real^N->bool) <=>
11806         !a b x. a IN s /\ b IN s /\
11807                 (!i. 1 <= i /\ i <= dimindex(:N)
11808                      ==> (a$i <= x$i /\ x$i <= b$i) \/
11809                          (b$i <= x$i /\ x$i <= a$i))
11810                 ==> x IN s`;;
11811
11812 let IS_INTERVAL_INTERVAL = prove
11813  (`!a:real^N b. is_interval(interval (a,b)) /\ is_interval(interval [a,b])`,
11814   REWRITE_TAC[is_interval; IN_INTERVAL] THEN
11815   MESON_TAC[REAL_LT_TRANS; REAL_LE_TRANS; REAL_LET_TRANS; REAL_LTE_TRANS]);;
11816
11817 let IS_INTERVAL_EMPTY = prove
11818  (`is_interval {}`,
11819   REWRITE_TAC[is_interval; NOT_IN_EMPTY]);;
11820
11821 let IS_INTERVAL_UNIV = prove
11822  (`is_interval(UNIV:real^N->bool)`,
11823   REWRITE_TAC[is_interval; IN_UNIV]);;
11824
11825 let IS_INTERVAL_TRANSLATION_EQ = prove
11826  (`!a:real^N s. is_interval(IMAGE (\x. a + x) s) <=> is_interval s`,
11827   REWRITE_TAC[is_interval] THEN GEOM_TRANSLATE_TAC[] THEN
11828   REWRITE_TAC[VECTOR_ADD_COMPONENT; REAL_LT_LADD; REAL_LE_LADD]);;
11829
11830 add_translation_invariants [IS_INTERVAL_TRANSLATION_EQ];;
11831
11832 let IS_INTERVAL_TRANSLATION = prove
11833  (`!s a:real^N. is_interval s ==> is_interval(IMAGE (\x. a + x) s)`,
11834   REWRITE_TAC[IS_INTERVAL_TRANSLATION_EQ]);;
11835
11836 let IS_INTERVAL_POINTWISE = prove
11837  (`!s:real^N->bool x.
11838         is_interval s /\
11839         (!i. 1 <= i /\ i <= dimindex(:N) ==> ?a. a IN s /\ a$i = x$i)
11840         ==> x IN s`,
11841   REWRITE_TAC[is_interval] THEN REPEAT STRIP_TAC THEN
11842   SUBGOAL_THEN
11843     `!n. ?y:real^N. (!i. 1 <= i /\ i <= n ==> y$i = (x:real^N)$i) /\ y IN s`
11844   MP_TAC THENL
11845    [INDUCT_TAC THEN REWRITE_TAC[ARITH_RULE `~(1 <= i /\ i <= 0)`] THENL
11846      [ASM_MESON_TAC[DIMINDEX_GE_1; LE_REFL]; ALL_TAC] THEN
11847     FIRST_X_ASSUM(X_CHOOSE_TAC `y:real^N`) THEN
11848     ASM_CASES_TAC `SUC n <= dimindex(:N)` THENL
11849      [FIRST_X_ASSUM(MP_TAC o SPEC `SUC n`) THEN
11850       ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
11851       DISCH_THEN(X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC) THEN
11852       EXISTS_TAC
11853        `(lambda i. if i <= n then (y:real^N)$i else (z:real^N)$i):real^N` THEN
11854       CONJ_TAC THENL
11855        [X_GEN_TAC `i:num` THEN STRIP_TAC THEN
11856         SUBGOAL_THEN `i <= dimindex(:N)` ASSUME_TAC THENL
11857          [ASM_ARITH_TAC; ASM_SIMP_TAC[LAMBDA_BETA]] THEN
11858         COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
11859         SUBGOAL_THEN `i = SUC n` (fun th -> ASM_REWRITE_TAC[th]) THEN
11860         ASM_ARITH_TAC;
11861         FIRST_X_ASSUM(ASSUME_TAC o CONJUNCT2) THEN
11862         FIRST_X_ASSUM MATCH_MP_TAC THEN
11863         MAP_EVERY EXISTS_TAC [`y:real^N`; `z:real^N`] THEN
11864         ASM_SIMP_TAC[LAMBDA_BETA] THEN REAL_ARITH_TAC];
11865       EXISTS_TAC `y:real^N` THEN ASM_REWRITE_TAC[] THEN
11866       SUBGOAL_THEN `y:real^N = x` (fun th -> REWRITE_TAC[th]) THEN
11867       REWRITE_TAC[CART_EQ] THEN
11868       ASM_MESON_TAC[ARITH_RULE `i <= N /\ ~(SUC n <= N) ==> i <= n`]];
11869     DISCH_THEN(MP_TAC o SPEC `dimindex(:N)`) THEN
11870     REWRITE_TAC[GSYM CART_EQ] THEN MESON_TAC[]]);;
11871
11872 let IS_INTERVAL_COMPACT = prove
11873  (`!s:real^N->bool. is_interval s /\ compact s <=> ?a b. s = interval[a,b]`,
11874   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
11875   ASM_SIMP_TAC[IS_INTERVAL_INTERVAL; COMPACT_INTERVAL] THEN
11876   ASM_CASES_TAC `s:real^N->bool = {}` THENL
11877    [ASM_MESON_TAC[EMPTY_AS_INTERVAL]; ALL_TAC] THEN
11878   EXISTS_TAC `(lambda i. inf { (x:real^N)$i | x IN s}):real^N` THEN
11879   EXISTS_TAC `(lambda i. sup { (x:real^N)$i | x IN s}):real^N` THEN
11880   SIMP_TAC[EXTENSION; IN_INTERVAL; LAMBDA_BETA] THEN X_GEN_TAC `x:real^N` THEN
11881   EQ_TAC THENL
11882    [DISCH_TAC THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
11883     MP_TAC(ISPEC `{ (x:real^N)$i | x IN s}` INF) THEN
11884     MP_TAC(ISPEC `{ (x:real^N)$i | x IN s}` SUP) THEN
11885     ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
11886     ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
11887     FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN
11888     REWRITE_TAC[bounded] THEN
11889     ASM_MESON_TAC[COMPONENT_LE_NORM; REAL_LE_TRANS; MEMBER_NOT_EMPTY;
11890                   REAL_ARITH `abs(x) <= B ==> --B <= x /\ x <= B`];
11891     DISCH_TAC THEN MATCH_MP_TAC IS_INTERVAL_POINTWISE THEN
11892     ASM_REWRITE_TAC[] THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
11893     SUBGOAL_THEN
11894      `?a b:real^N. a IN s /\ b IN s /\ a$i <= (x:real^N)$i /\ x$i <= b$i`
11895     STRIP_ASSUME_TAC THENL
11896      [MP_TAC(ISPECL [`\x:real^N. x$i`; `s:real^N->bool`]
11897         CONTINUOUS_ATTAINS_INF) THEN
11898       ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT; o_DEF] THEN
11899       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN STRIP_TAC THEN
11900       MP_TAC(ISPECL [`\x:real^N. x$i`; `s:real^N->bool`]
11901         CONTINUOUS_ATTAINS_SUP) THEN
11902       ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT; o_DEF] THEN
11903       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
11904       ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THENL
11905        [EXISTS_TAC `inf {(x:real^N)$i | x IN s}` THEN ASM_SIMP_TAC[] THEN
11906         MATCH_MP_TAC REAL_LE_INF THEN ASM SET_TAC[];
11907         EXISTS_TAC `sup {(x:real^N)$i | x IN s}` THEN ASM_SIMP_TAC[] THEN
11908         MATCH_MP_TAC REAL_SUP_LE THEN ASM SET_TAC[]];
11909       EXISTS_TAC
11910        `(lambda j. if j = i then (x:real^N)$i else (a:real^N)$j):real^N` THEN
11911       ASM_SIMP_TAC[LAMBDA_BETA] THEN
11912       FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[is_interval]) THEN
11913       MAP_EVERY EXISTS_TAC
11914        [`a:real^N`;
11915         `(lambda j. if j = i then (b:real^N)$i else (a:real^N)$j):real^N`] THEN
11916       ASM_SIMP_TAC[LAMBDA_BETA] THEN CONJ_TAC THENL
11917        [FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[is_interval]) THEN
11918         MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real^N`] THEN
11919         ASM_SIMP_TAC[LAMBDA_BETA];
11920         ALL_TAC] THEN
11921       GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
11922       ASM_REAL_ARITH_TAC]]);;
11923
11924 let IS_INTERVAL_1 = prove
11925  (`!s:real^1->bool.
11926         is_interval s <=>
11927           !a b x. a IN s /\ b IN s /\ drop a <= drop x /\ drop x <= drop b
11928                   ==> x IN s`,
11929   REWRITE_TAC[is_interval; DIMINDEX_1; FORALL_1; GSYM drop] THEN
11930   REWRITE_TAC[FORALL_LIFT; LIFT_DROP] THEN MESON_TAC[]);;
11931
11932 let IS_INTERVAL_1_CASES = prove
11933  (`!s:real^1->bool.
11934         is_interval s <=>
11935         s = {} \/
11936         s = (:real^1) \/
11937         (?a. s = {x | a < drop x}) \/
11938         (?a. s = {x | a <= drop x}) \/
11939         (?b. s = {x | drop x <= b}) \/
11940         (?b. s = {x | drop x < b}) \/
11941         (?a b. s = {x | a < drop x /\ drop x < b}) \/
11942         (?a b. s = {x | a < drop x /\ drop x <= b}) \/
11943         (?a b. s = {x | a <= drop x /\ drop x < b}) \/
11944         (?a b. s = {x | a <= drop x /\ drop x <= b})`,
11945   GEN_TAC THEN REWRITE_TAC[IS_INTERVAL_1] THEN EQ_TAC THENL
11946    [DISCH_TAC;
11947     STRIP_TAC THEN ASM_REWRITE_TAC[IN_ELIM_THM; IN_UNIV; NOT_IN_EMPTY] THEN
11948     REAL_ARITH_TAC] THEN
11949   ASM_CASES_TAC `s:real^1->bool = {}` THEN ASM_REWRITE_TAC[] THEN
11950   MP_TAC(ISPEC `IMAGE drop s` SUP) THEN
11951   MP_TAC(ISPEC `IMAGE drop s` INF) THEN
11952   ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
11953   ASM_CASES_TAC `?a. !x. x IN s ==> a <= drop x` THEN
11954   ASM_CASES_TAC `?b. !x. x IN s ==> drop x <= b` THEN
11955   ASM_REWRITE_TAC[] THENL
11956    [STRIP_TAC THEN STRIP_TAC THEN
11957     MAP_EVERY ASM_CASES_TAC
11958      [`inf(IMAGE drop s) IN IMAGE drop s`; `sup(IMAGE drop s) IN IMAGE drop s`]
11959     THENL
11960      [REPLICATE_TAC 8 DISJ2_TAC;
11961       REPLICATE_TAC 7 DISJ2_TAC THEN DISJ1_TAC;
11962       REPLICATE_TAC 6 DISJ2_TAC THEN DISJ1_TAC;
11963       REPLICATE_TAC 5 DISJ2_TAC THEN DISJ1_TAC] THEN
11964     MAP_EVERY EXISTS_TAC [`inf(IMAGE drop s)`; `sup(IMAGE drop s)`];
11965     STRIP_TAC THEN ASM_CASES_TAC `inf(IMAGE drop s) IN IMAGE drop s` THENL
11966      [REPLICATE_TAC 2 DISJ2_TAC THEN DISJ1_TAC;
11967       DISJ2_TAC THEN DISJ1_TAC] THEN
11968     EXISTS_TAC `inf(IMAGE drop s)`;
11969     STRIP_TAC THEN ASM_CASES_TAC `sup(IMAGE drop s) IN IMAGE drop s` THENL
11970      [REPLICATE_TAC 3 DISJ2_TAC THEN DISJ1_TAC;
11971       REPLICATE_TAC 4 DISJ2_TAC THEN DISJ1_TAC] THEN
11972     EXISTS_TAC `sup(IMAGE drop s)`;
11973     DISJ1_TAC] THEN
11974   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_UNIV] THEN
11975   RULE_ASSUM_TAC(REWRITE_RULE[IN_IMAGE]) THEN
11976   REWRITE_TAC[GSYM REAL_NOT_LE] THEN
11977   ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_TOTAL; REAL_LE_ANTISYM]);;
11978
11979 let IS_INTERVAL_PCROSS = prove
11980  (`!s:real^M->bool t:real^N->bool.
11981         is_interval s /\ is_interval t ==> is_interval(s PCROSS t)`,
11982   REWRITE_TAC[is_interval; DIMINDEX_FINITE_SUM] THEN
11983   REWRITE_TAC[FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
11984   REPEAT GEN_TAC THEN
11985   MATCH_MP_TAC(MESON[]
11986    `(!a b a' b' x x'. P a b x /\ Q a' b' x' ==> R a b x a' b' x')
11987     ==> (!a b x. P a b x) /\ (!a' b' x'. Q a' b' x')
11988         ==> (!a a' b b' x x'. R a b x a' b' x')`) THEN
11989   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
11990   ASM_REWRITE_TAC[] THEN X_GEN_TAC `i:num` THEN STRIP_TAC THENL
11991    [FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN
11992     ASM_SIMP_TAC[pastecart; LAMBDA_BETA; DIMINDEX_FINITE_SUM;
11993                  ARITH_RULE `x:num <= m ==> x <= m + n`];
11994     FIRST_X_ASSUM(MP_TAC o SPEC `dimindex(:M) + i`) THEN
11995     ASM_SIMP_TAC[pastecart; LAMBDA_BETA; DIMINDEX_FINITE_SUM;
11996                  ARITH_RULE `x:num <= n ==> m + x <= m + n`;
11997                  ARITH_RULE `1 <= x ==> 1 <= m + x`] THEN
11998     COND_CASES_TAC THEN ASM_REWRITE_TAC[ADD_SUB2] THEN ASM_ARITH_TAC]);;
11999
12000 let IS_INTERVAL_PCROSS_EQ = prove
12001  (`!s:real^M->bool t:real^N->bool.
12002         is_interval(s PCROSS t) <=>
12003         s = {} \/ t = {} \/ is_interval s /\ is_interval t`,
12004   REPEAT GEN_TAC THEN
12005   ASM_CASES_TAC `s:real^M->bool = {}` THEN
12006   ASM_REWRITE_TAC[PCROSS_EMPTY; IS_INTERVAL_EMPTY] THEN
12007   ASM_CASES_TAC `t:real^N->bool = {}` THEN
12008   ASM_REWRITE_TAC[PCROSS_EMPTY; IS_INTERVAL_EMPTY] THEN
12009   EQ_TAC THEN REWRITE_TAC[IS_INTERVAL_PCROSS] THEN
12010   REWRITE_TAC[is_interval] THEN
12011   REWRITE_TAC[FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
12012   STRIP_TAC THEN CONJ_TAC THENL
12013    [MAP_EVERY X_GEN_TAC [`a:real^M`; `b:real^M`; `x:real^M`] THEN
12014     STRIP_TAC THEN UNDISCH_TAC `~(t:real^N->bool = {})` THEN
12015     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
12016     DISCH_THEN(X_CHOOSE_TAC `y:real^N`) THEN
12017     FIRST_X_ASSUM(MP_TAC o SPECL
12018      [`a:real^M`; `y:real^N`; `b:real^M`;
12019       `y:real^N`; `x:real^M`; `y:real^N`]);
12020     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`; `x:real^N`] THEN
12021     STRIP_TAC THEN UNDISCH_TAC `~(s:real^M->bool = {})` THEN
12022     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
12023     DISCH_THEN(X_CHOOSE_TAC `w:real^M`) THEN
12024     FIRST_X_ASSUM(MP_TAC o SPECL
12025      [`w:real^M`; `a:real^N`; `w:real^M`;
12026       `b:real^N`; `w:real^M`; `x:real^N`])] THEN
12027   ASM_REWRITE_TAC[] THEN DISCH_THEN MATCH_MP_TAC THEN
12028   SIMP_TAC[pastecart; LAMBDA_BETA] THEN
12029   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_LE_REFL] THEN
12030   ASM_MESON_TAC[DIMINDEX_FINITE_SUM; ARITH_RULE
12031       `1 <= i /\ i <= m + n /\ ~(i <= m) ==> 1 <= i - m /\ i - m <= n`]);;
12032
12033 let IS_INTERVAL_INTER = prove
12034  (`!s t:real^N->bool.
12035         is_interval s /\ is_interval t ==> is_interval(s INTER t)`,
12036   REWRITE_TAC[is_interval; IN_INTER] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
12037   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`; `x:real^N`] THEN
12038   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
12039   MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real^N`] THEN ASM_REWRITE_TAC[]);;
12040
12041 let INTERVAL_SUBSET_IS_INTERVAL = prove
12042  (`!s a b:real^N.
12043      is_interval s
12044      ==> (interval[a,b] SUBSET s <=> interval[a,b] = {} \/ a IN s /\ b IN s)`,
12045   REWRITE_TAC[is_interval] THEN REPEAT STRIP_TAC THEN
12046   ASM_CASES_TAC `interval[a:real^N,b] = {}` THEN
12047   ASM_REWRITE_TAC[EMPTY_SUBSET] THEN
12048   EQ_TAC THENL [ASM_MESON_TAC[ENDS_IN_INTERVAL; SUBSET]; ALL_TAC] THEN
12049   REWRITE_TAC[SUBSET; IN_INTERVAL] THEN ASM_MESON_TAC[]);;
12050
12051 let INTERVAL_CONTAINS_COMPACT_NEIGHBOURHOOD = prove
12052  (`!s x:real^N.
12053         is_interval s /\ x IN s
12054         ==> ?a b d. &0 < d /\ x IN interval[a,b] /\
12055                     interval[a,b] SUBSET s /\
12056                     ball(x,d) INTER s SUBSET interval[a,b]`,
12057   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[INTERVAL_SUBSET_IS_INTERVAL] THEN
12058   SUBGOAL_THEN
12059    `!i. 1 <= i /\ i <= dimindex(:N)
12060         ==> ?a. (?y. y IN s /\ y$i = a) /\
12061                 (a < x$i \/ a = (x:real^N)$i /\
12062                             !y:real^N. y IN s ==> a <= y$i)`
12063   MP_TAC THENL [ASM_MESON_TAC[REAL_NOT_LT]; REWRITE_TAC[LAMBDA_SKOLEM]] THEN
12064   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN STRIP_TAC THEN
12065   SUBGOAL_THEN
12066    `!i. 1 <= i /\ i <= dimindex(:N)
12067         ==> ?b. (?y. y IN s /\ y$i = b) /\
12068                 (x$i < b \/ b = (x:real^N)$i /\
12069                             !y:real^N. y IN s ==> y$i <= b)`
12070   MP_TAC THENL [ASM_MESON_TAC[REAL_NOT_LT]; REWRITE_TAC[LAMBDA_SKOLEM]] THEN
12071   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
12072   EXISTS_TAC `min (inf (IMAGE (\i. if a$i < x$i
12073                                    then (x:real^N)$i - (a:real^N)$i else &1)
12074                               (1..dimindex(:N))))
12075                   (inf (IMAGE (\i. if x$i < b$i
12076                                    then (b:real^N)$i - x$i else &1)
12077                               (1..dimindex(:N))))` THEN
12078   REWRITE_TAC[REAL_LT_MIN; SUBSET; IN_BALL; IN_INTER] THEN
12079   SIMP_TAC[REAL_LT_INF_FINITE; IMAGE_EQ_EMPTY; FINITE_IMAGE;
12080            FINITE_NUMSEG; NUMSEG_EMPTY; GSYM NOT_LE; DIMINDEX_GE_1] THEN
12081   REWRITE_TAC[FORALL_IN_IMAGE; IN_INTERVAL] THEN REPEAT CONJ_TAC THENL
12082    [MESON_TAC[REAL_SUB_LT; REAL_LT_01];
12083     MESON_TAC[REAL_SUB_LT; REAL_LT_01];
12084     ASM_MESON_TAC[REAL_LE_LT];
12085     DISJ2_TAC THEN CONJ_TAC THEN MATCH_MP_TAC IS_INTERVAL_POINTWISE THEN
12086     ASM_MESON_TAC[];
12087     X_GEN_TAC `y:real^N` THEN
12088     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
12089     REWRITE_TAC[AND_FORALL_THM] THEN MATCH_MP_TAC MONO_FORALL THEN
12090     X_GEN_TAC `i:num` THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
12091     ASM_REWRITE_TAC[IN_NUMSEG] THEN MATCH_MP_TAC MONO_AND THEN CONJ_TAC THEN
12092     (COND_CASES_TAC THENL [REWRITE_TAC[dist]; ASM_MESON_TAC[]]) THEN
12093     DISCH_TAC THEN MP_TAC(ISPECL [`x - y:real^N`; `i:num`]
12094       COMPONENT_LE_NORM) THEN
12095     ASM_REWRITE_TAC[VECTOR_SUB_COMPONENT] THEN ASM_REAL_ARITH_TAC]);;
12096
12097 let IS_INTERVAL_SUMS = prove
12098  (`!s t:real^N->bool.
12099         is_interval s /\ is_interval t
12100         ==> is_interval {x + y | x IN s /\ y IN t}`,
12101   REPEAT GEN_TAC THEN REWRITE_TAC[is_interval] THEN
12102   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
12103   REWRITE_TAC[FORALL_IN_GSPEC] THEN
12104   REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN
12105   REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC] THEN
12106   MAP_EVERY X_GEN_TAC
12107    [`a:real^N`; `a':real^N`; `b:real^N`; `b':real^N`; `y:real^N`] THEN
12108   DISCH_THEN(CONJUNCTS_THEN2
12109    (MP_TAC o SPECL [`a:real^N`; `b:real^N`]) MP_TAC) THEN
12110   DISCH_THEN(CONJUNCTS_THEN2
12111    (MP_TAC o SPECL [`a':real^N`; `b':real^N`]) STRIP_ASSUME_TAC) THEN
12112   ASM_REWRITE_TAC[IMP_IMP; IN_ELIM_THM] THEN  ONCE_REWRITE_TAC[CONJ_SYM] THEN
12113   ONCE_REWRITE_TAC[VECTOR_ARITH `z:real^N = x + y <=> y = z - x`] THEN
12114   REWRITE_TAC[UNWIND_THM2] THEN MATCH_MP_TAC(MESON[]
12115    `(?x. P x /\ Q(f x))
12116     ==> (!x. P x ==> x IN s) /\ (!x. Q x ==> x IN t)
12117         ==> ?x. x IN s /\ f x IN t`) THEN
12118   REWRITE_TAC[VECTOR_SUB_COMPONENT; AND_FORALL_THM;
12119               TAUT `(p ==> q) /\ (p ==> r) <=> p ==> q /\ r`] THEN
12120   REWRITE_TAC[GSYM LAMBDA_SKOLEM] THEN
12121   X_GEN_TAC `i:num` THEN STRIP_TAC THEN
12122   FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN
12123   ASM_REWRITE_TAC[VECTOR_ADD_COMPONENT] THEN
12124   REWRITE_TAC[REAL_ARITH
12125    `c <= y - x /\ y - x <= d <=> y - d <= x /\ x <= y - c`] THEN
12126   REWRITE_TAC[REAL_ARITH
12127   `a <= x /\ x <= b \/ b <= x /\ x <= a <=> min a b <= x /\ x <= max a b`] THEN
12128   ONCE_REWRITE_TAC[TAUT `(p /\ q) /\ (r /\ s) <=> (p /\ r) /\ (q /\ s)`] THEN
12129   REWRITE_TAC[GSYM REAL_LE_MIN; GSYM REAL_MAX_LE] THEN
12130   REWRITE_TAC[GSYM REAL_LE_BETWEEN] THEN REAL_ARITH_TAC);;
12131
12132 let IS_INTERVAL_SING = prove
12133  (`!a:real^N. is_interval {a}`,
12134   SIMP_TAC[is_interval; IN_SING; IMP_CONJ; CART_EQ; REAL_LE_ANTISYM]);;
12135
12136 let IS_INTERVAL_SCALING = prove
12137  (`!s:real^N->bool c. is_interval s ==> is_interval(IMAGE (\x. c % x) s)`,
12138   REPEAT GEN_TAC THEN ASM_CASES_TAC `c = &0` THENL
12139    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO] THEN
12140     SUBGOAL_THEN `IMAGE ((\x. vec 0):real^N->real^N) s = {} \/
12141                   IMAGE ((\x. vec 0):real^N->real^N) s = {vec 0}`
12142     STRIP_ASSUME_TAC THENL
12143      [SET_TAC[];
12144       ASM_REWRITE_TAC[IS_INTERVAL_EMPTY];
12145       ASM_REWRITE_TAC[IS_INTERVAL_SING]];
12146     REWRITE_TAC[is_interval; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
12147     REWRITE_TAC[FORALL_IN_IMAGE] THEN
12148     GEN_REWRITE_TAC (BINOP_CONV o REDEPTH_CONV) [RIGHT_IMP_FORALL_THM] THEN
12149     REWRITE_TAC[IMP_IMP; VECTOR_MUL_COMPONENT] THEN
12150     MAP_EVERY (fun t -> MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC t)
12151      [`a:real^N`; `b:real^N`] THEN
12152     DISCH_THEN(fun th -> X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
12153                          MP_TAC(SPEC `inv(c) % x:real^N` th)) THEN
12154     ASM_REWRITE_TAC[VECTOR_MUL_COMPONENT; IN_IMAGE] THEN ANTS_TAC THENL
12155      [X_GEN_TAC `i:num` THEN STRIP_TAC THEN
12156       FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN ASM_REWRITE_TAC[] THEN
12157       ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN
12158       FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
12159        `~(c = &0) ==> &0 < c \/ &0 < --c`)) THEN
12160       ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ] THEN
12161       GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM REAL_LE_NEG2] THEN
12162       ASM_SIMP_TAC[GSYM REAL_MUL_RNEG; GSYM REAL_LE_RDIV_EQ; GSYM
12163                    REAL_LE_LDIV_EQ] THEN
12164       REWRITE_TAC[real_div; REAL_INV_NEG] THEN REAL_ARITH_TAC;
12165       DISCH_TAC THEN EXISTS_TAC `inv c % x:real^N` THEN
12166       ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; VECTOR_MUL_LID]]]);;
12167
12168 let IS_INTERVAL_SCALING_EQ = prove
12169  (`!s:real^N->bool c.
12170         is_interval(IMAGE (\x. c % x) s) <=> c = &0 \/ is_interval s`,
12171   REPEAT GEN_TAC THEN ASM_CASES_TAC `c = &0` THENL
12172    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO] THEN
12173     SUBGOAL_THEN `IMAGE ((\x. vec 0):real^N->real^N) s = {} \/
12174                   IMAGE ((\x. vec 0):real^N->real^N) s = {vec 0}`
12175     STRIP_ASSUME_TAC THENL
12176      [SET_TAC[];
12177       ASM_REWRITE_TAC[IS_INTERVAL_EMPTY];
12178       ASM_REWRITE_TAC[IS_INTERVAL_SING]];
12179     ASM_REWRITE_TAC[] THEN EQ_TAC THEN REWRITE_TAC[IS_INTERVAL_SCALING] THEN
12180     DISCH_THEN(MP_TAC o SPEC `inv c:real` o MATCH_MP IS_INTERVAL_SCALING) THEN
12181     ASM_SIMP_TAC[GSYM IMAGE_o; VECTOR_MUL_ASSOC; o_DEF; REAL_MUL_LINV;
12182                  VECTOR_MUL_LID; IMAGE_ID]]);;
12183
12184 let lemma = prove
12185  (`!c. &0 < c
12186        ==> !s:real^N->bool. is_interval(IMAGE (\x. c % x) s) <=>
12187                             is_interval s`,
12188   SIMP_TAC[IS_INTERVAL_SCALING_EQ; REAL_LT_IMP_NZ]) in
12189 add_scaling_theorems [lemma];;
12190
12191 (* ------------------------------------------------------------------------- *)
12192 (* Line segments, with same open/closed overloading as for intervals.        *)
12193 (* ------------------------------------------------------------------------- *)
12194
12195 let closed_segment = define
12196  `closed_segment[a,b] = {(&1 - u) % a + u % b | &0 <= u /\ u <= &1}`;;
12197
12198 let open_segment = new_definition
12199  `open_segment(a,b) = closed_segment[a,b] DIFF {a,b}`;;
12200
12201 let OPEN_SEGMENT_ALT = prove
12202  (`!a b:real^N.
12203         ~(a = b)
12204         ==> open_segment(a,b) = {(&1 - u) % a + u % b | &0 < u /\ u < &1}`,
12205   REPEAT STRIP_TAC THEN REWRITE_TAC[open_segment; closed_segment] THEN
12206   REWRITE_TAC[EXTENSION; IN_DIFF; IN_INSERT; NOT_IN_EMPTY; IN_ELIM_THM] THEN
12207   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN
12208   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN
12209   X_GEN_TAC `u:real` THEN ASM_CASES_TAC `x:real^N = (&1 - u) % a + u % b` THEN
12210   ASM_REWRITE_TAC[REAL_LE_LT;
12211     VECTOR_ARITH `(&1 - u) % a + u % b = a <=> u % (b - a) = vec 0`;
12212     VECTOR_ARITH `(&1 - u) % a + u % b = b <=> (&1 - u) % (b - a) = vec 0`;
12213     VECTOR_MUL_EQ_0; REAL_SUB_0; VECTOR_SUB_EQ] THEN
12214   REAL_ARITH_TAC);;
12215
12216 make_overloadable "segment" `:A`;;
12217
12218 overload_interface("segment",`open_segment`);;
12219 overload_interface("segment",`closed_segment`);;
12220
12221 let segment = prove
12222  (`segment[a,b] = {(&1 - u) % a + u % b | &0 <= u /\ u <= &1} /\
12223    segment(a,b) = segment[a,b] DIFF {a,b}`,
12224   REWRITE_TAC[open_segment; closed_segment]);;
12225
12226 let SEGMENT_REFL = prove
12227  (`(!a. segment[a,a] = {a}) /\
12228    (!a. segment(a,a) = {})`,
12229   REWRITE_TAC[segment; VECTOR_ARITH `(&1 - u) % a + u % a = a`] THEN
12230   SET_TAC[REAL_POS]);;
12231
12232 let IN_SEGMENT = prove
12233  (`!a b x:real^N.
12234         (x IN segment[a,b] <=>
12235          ?u. &0 <= u /\ u <= &1 /\ x = (&1 - u) % a + u % b) /\
12236         (x IN segment(a,b) <=>
12237          ~(a = b) /\ ?u. &0 < u /\ u < &1 /\ x = (&1 - u) % a + u % b)`,
12238   REPEAT STRIP_TAC THENL
12239    [REWRITE_TAC[segment; IN_ELIM_THM; CONJ_ASSOC]; ALL_TAC] THEN
12240   ASM_CASES_TAC `a:real^N = b` THEN
12241   ASM_REWRITE_TAC[SEGMENT_REFL; NOT_IN_EMPTY] THEN
12242   ASM_SIMP_TAC[OPEN_SEGMENT_ALT; IN_ELIM_THM; CONJ_ASSOC]);;
12243
12244 let SEGMENT_SYM = prove
12245  (`(!a b:real^N. segment[a,b] = segment[b,a]) /\
12246    (!a b:real^N. segment(a,b) = segment(b,a))`,
12247   MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN
12248   SIMP_TAC[open_segment] THEN
12249   CONJ_TAC THENL [ALL_TAC; SIMP_TAC[INSERT_AC]] THEN
12250   REWRITE_TAC[EXTENSION; IN_SEGMENT] THEN REPEAT GEN_TAC THEN EQ_TAC THEN
12251   DISCH_THEN(X_CHOOSE_TAC `u:real`) THEN EXISTS_TAC `&1 - u` THEN
12252   ASM_REWRITE_TAC[] THEN
12253   REPEAT CONJ_TAC THEN TRY ASM_ARITH_TAC THEN VECTOR_ARITH_TAC);;
12254
12255 let ENDS_IN_SEGMENT = prove
12256  (`!a b. a IN segment[a,b] /\ b IN segment[a,b]`,
12257   REPEAT STRIP_TAC THEN REWRITE_TAC[segment; IN_ELIM_THM] THENL
12258    [EXISTS_TAC `&0`; EXISTS_TAC `&1`] THEN
12259   (CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]));;
12260
12261 let ENDS_NOT_IN_SEGMENT = prove
12262  (`!a b. ~(a IN segment(a,b)) /\ ~(b IN segment(a,b))`,
12263   REWRITE_TAC[open_segment] THEN SET_TAC[]);;
12264
12265 let SEGMENT_CLOSED_OPEN = prove
12266  (`!a b. segment[a,b] = segment(a,b) UNION {a,b}`,
12267   REPEAT GEN_TAC THEN REWRITE_TAC[open_segment] THEN MATCH_MP_TAC(SET_RULE
12268    `a IN s /\ b IN s ==> s = (s DIFF {a,b}) UNION {a,b}`) THEN
12269   REWRITE_TAC[ENDS_IN_SEGMENT]);;
12270
12271 let MIDPOINT_IN_SEGMENT = prove
12272  (`(!a b:real^N. midpoint(a,b) IN segment[a,b]) /\
12273    (!a b:real^N. midpoint(a,b) IN segment(a,b) <=> ~(a = b))`,
12274   REWRITE_TAC[IN_SEGMENT] THEN REPEAT STRIP_TAC THENL
12275    [ALL_TAC; ASM_CASES_TAC `a:real^N = b` THEN ASM_REWRITE_TAC[]] THEN
12276   EXISTS_TAC `&1 / &2` THEN REWRITE_TAC[midpoint] THEN
12277   CONV_TAC REAL_RAT_REDUCE_CONV THEN VECTOR_ARITH_TAC);;
12278
12279 let BETWEEN_IN_SEGMENT = prove
12280  (`!x a b:real^N. between x (a,b) <=> x IN segment[a,b]`,
12281   REPEAT GEN_TAC THEN REWRITE_TAC[between] THEN
12282   ASM_CASES_TAC `a:real^N = b` THEN
12283   ASM_REWRITE_TAC[SEGMENT_REFL; IN_SING] THENL [NORM_ARITH_TAC; ALL_TAC] THEN
12284   REWRITE_TAC[segment; IN_ELIM_THM] THEN EQ_TAC THENL
12285    [DISCH_THEN(ASSUME_TAC o SYM) THEN
12286     EXISTS_TAC `dist(a:real^N,x) / dist(a,b)` THEN
12287     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ; DIST_POS_LT] THEN CONJ_TAC
12288     THENL [FIRST_ASSUM(SUBST1_TAC o SYM) THEN NORM_ARITH_TAC; ALL_TAC] THEN
12289     MATCH_MP_TAC VECTOR_MUL_LCANCEL_IMP THEN EXISTS_TAC `dist(a:real^N,b)` THEN
12290     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; VECTOR_ADD_LDISTRIB; REAL_SUB_LDISTRIB;
12291                  REAL_DIV_LMUL; DIST_EQ_0] THEN
12292     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [DIST_TRIANGLE_EQ] o SYM) THEN
12293     FIRST_ASSUM(SUBST1_TAC o SYM) THEN
12294     REWRITE_TAC[dist; REAL_ARITH `(a + b) * &1 - a = b`] THEN
12295     VECTOR_ARITH_TAC;
12296     STRIP_TAC THEN ASM_REWRITE_TAC[dist] THEN
12297     REWRITE_TAC[VECTOR_ARITH `a - ((&1 - u) % a + u % b) = u % (a - b)`;
12298                 VECTOR_ARITH `((&1 - u) % a + u % b) - b = (&1 - u) % (a - b)`;
12299                 NORM_MUL; GSYM REAL_ADD_LDISTRIB] THEN
12300     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD]);;
12301
12302 let IN_SEGMENT_COMPONENT = prove
12303  (`!a b x:real^N i.
12304         x IN segment[a,b] /\ 1 <= i /\ i <= dimindex(:N)
12305         ==> min (a$i) (b$i) <= x$i /\ x$i <= max (a$i) (b$i)`,
12306   REPEAT STRIP_TAC THEN
12307   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT]) THEN
12308   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
12309   FIRST_X_ASSUM(X_CHOOSE_THEN `t:real` STRIP_ASSUME_TAC) THEN
12310   ASM_REWRITE_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN
12311   SIMP_TAC[REAL_ARITH `c <= u * a + t * b <=> u * --a + t * --b <= --c`] THEN
12312   MATCH_MP_TAC REAL_CONVEX_BOUND_LE THEN ASM_REAL_ARITH_TAC);;
12313
12314 let SEGMENT_1 = prove
12315  (`(!a b. segment[a,b] =
12316           if drop a <= drop b then interval[a,b] else interval[b,a]) /\
12317    (!a b. segment(a,b) =
12318           if drop a <= drop b then interval(a,b) else interval(b,a))`,
12319   CONJ_TAC THEN REPEAT GEN_TAC THEN REWRITE_TAC[open_segment] THEN
12320   COND_CASES_TAC THEN
12321   REWRITE_TAC[IN_DIFF; IN_INSERT; NOT_IN_EMPTY;
12322               EXTENSION; GSYM BETWEEN_IN_SEGMENT; between; IN_INTERVAL_1] THEN
12323   REWRITE_TAC[GSYM DROP_EQ; DIST_REAL; GSYM drop] THEN ASM_REAL_ARITH_TAC);;
12324
12325 let OPEN_SEGMENT_1 = prove
12326  (`!a b:real^1. open(segment(a,b))`,
12327   REPEAT GEN_TAC THEN REWRITE_TAC[SEGMENT_1] THEN
12328   COND_CASES_TAC THEN REWRITE_TAC[OPEN_INTERVAL]);;
12329
12330 let SEGMENT_TRANSLATION = prove
12331  (`(!c a b. segment[c + a,c + b] = IMAGE (\x. c + x) (segment[a,b])) /\
12332    (!c a b. segment(c + a,c + b) = IMAGE (\x. c + x) (segment(a,b)))`,
12333   REWRITE_TAC[EXTENSION; IN_SEGMENT; IN_IMAGE] THEN
12334   REWRITE_TAC[VECTOR_ARITH `(&1 - u) % (c + a) + u % (c + b) =
12335                             c + (&1 - u) % a + u % b`] THEN
12336   REWRITE_TAC[VECTOR_ARITH `c + a:real^N = c + b <=> a = b`] THEN
12337   MESON_TAC[]);;
12338
12339 add_translation_invariants
12340  [CONJUNCT1 SEGMENT_TRANSLATION; CONJUNCT2 SEGMENT_TRANSLATION];;
12341
12342 let CLOSED_SEGMENT_LINEAR_IMAGE = prove
12343  (`!f a b. linear f
12344            ==> segment[f a,f b] = IMAGE f (segment[a,b])`,
12345   REPEAT STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_SEGMENT] THEN
12346   FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_CMUL th)]) THEN
12347   FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_ADD th)]) THEN
12348   MESON_TAC[]);;
12349
12350 add_linear_invariants [CLOSED_SEGMENT_LINEAR_IMAGE];;
12351
12352 let OPEN_SEGMENT_LINEAR_IMAGE = prove
12353  (`!f:real^M->real^N a b.
12354         linear f /\ (!x y. f x = f y ==> x = y)
12355         ==> segment(f a,f b) = IMAGE f (segment(a,b))`,
12356   REWRITE_TAC[open_segment] THEN GEOM_TRANSFORM_TAC[]);;
12357
12358 add_linear_invariants [OPEN_SEGMENT_LINEAR_IMAGE];;
12359
12360 let IN_OPEN_SEGMENT = prove
12361  (`!a b x:real^N.
12362         x IN segment(a,b) <=> x IN segment[a,b] /\ ~(x = a) /\ ~(x = b)`,
12363   REPEAT GEN_TAC THEN REWRITE_TAC[open_segment; IN_DIFF] THEN SET_TAC[]);;
12364
12365 let IN_OPEN_SEGMENT_ALT = prove
12366  (`!a b x:real^N.
12367         x IN segment(a,b) <=>
12368         x IN segment[a,b] /\ ~(x = a) /\ ~(x = b) /\ ~(a = b)`,
12369   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = b` THEN
12370   ASM_REWRITE_TAC[SEGMENT_REFL; IN_SING; NOT_IN_EMPTY] THEN
12371   ASM_MESON_TAC[IN_OPEN_SEGMENT]);;
12372
12373 let COLLINEAR_DIST_IN_CLOSED_SEGMENT = prove
12374  (`!a b x. collinear {x,a,b} /\
12375            dist(x,a) <= dist(a,b) /\ dist(x,b) <= dist(a,b)
12376            ==> x IN segment[a,b]`,
12377   REWRITE_TAC[GSYM BETWEEN_IN_SEGMENT; COLLINEAR_DIST_BETWEEN]);;
12378
12379 let COLLINEAR_DIST_IN_OPEN_SEGMENT = prove
12380  (`!a b x. collinear {x,a,b} /\
12381            dist(x,a) < dist(a,b) /\ dist(x,b) < dist(a,b)
12382            ==> x IN segment(a,b)`,
12383   REWRITE_TAC[IN_OPEN_SEGMENT] THEN
12384   MESON_TAC[COLLINEAR_DIST_IN_CLOSED_SEGMENT; REAL_LT_LE; DIST_SYM]);;
12385
12386 let SEGMENT_SCALAR_MULTIPLE = prove
12387  (`(!a b v. segment[a % v,b % v] =
12388             {x % v:real^N | a <= x /\ x <= b \/ b <= x /\ x <= a}) /\
12389    (!a b v. ~(v = vec 0)
12390             ==> segment(a % v,b % v) =
12391                 {x % v:real^N | a < x /\ x < b \/ b < x /\ x < a})`,
12392   MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN REPEAT STRIP_TAC THENL
12393    [REPEAT GEN_TAC THEN
12394     MP_TAC(SPECL [`a % basis 1:real^1`; `b % basis 1:real^1`]
12395      (CONJUNCT1 SEGMENT_1)) THEN
12396     REWRITE_TAC[segment; VECTOR_MUL_ASSOC; GSYM VECTOR_ADD_RDISTRIB] THEN
12397     REWRITE_TAC[SET_RULE `{f x % b | p x} = IMAGE (\a. a % b) {f x | p x}`] THEN
12398     DISCH_TAC THEN AP_TERM_TAC THEN
12399     FIRST_X_ASSUM(MP_TAC o AP_TERM `IMAGE drop`) THEN
12400     REWRITE_TAC[GSYM IMAGE_o; o_DEF; DROP_CMUL] THEN
12401     SIMP_TAC[drop; BASIS_COMPONENT; DIMINDEX_GE_1; LE_REFL] THEN
12402     REWRITE_TAC[REAL_MUL_RID; IMAGE_ID] THEN DISCH_THEN SUBST1_TAC THEN
12403     MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
12404     CONJ_TAC THENL [MESON_TAC[LIFT_DROP]; ALL_TAC] THEN
12405     REWRITE_TAC[FORALL_LIFT; LIFT_DROP] THEN GEN_TAC THEN
12406     COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP] THEN
12407     SIMP_TAC[drop; VECTOR_MUL_COMPONENT; BASIS_COMPONENT; DIMINDEX_GE_1;
12408              LE_REFL; IN_ELIM_THM] THEN ASM_REAL_ARITH_TAC;
12409     ASM_REWRITE_TAC[open_segment] THEN
12410     ASM_SIMP_TAC[VECTOR_MUL_RCANCEL; SET_RULE
12411      `(!x y. x % v = y % v <=> x = y)
12412       ==> {x % v | P x} DIFF {a % v,b % v} =
12413           {x % v | P x /\ ~(x = a) /\ ~(x = b)}`] THEN
12414     ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN AP_TERM_TAC THEN
12415     REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REAL_ARITH_TAC]);;
12416
12417 let FINITE_INTER_COLLINEAR_OPEN_SEGMENTS = prove
12418  (`!a b c d:real^N.
12419         collinear{a,b,c}
12420         ==> (FINITE(segment(a,b) INTER segment(c,d)) <=>
12421              segment(a,b) INTER segment(c,d) = {})`,
12422   REPEAT GEN_TAC THEN ABBREV_TAC `m:real^N = b - a` THEN POP_ASSUM MP_TAC THEN
12423   GEOM_NORMALIZE_TAC `m:real^N` THEN
12424   SIMP_TAC[VECTOR_SUB_EQ; SEGMENT_REFL; INTER_EMPTY; FINITE_EMPTY] THEN
12425   X_GEN_TAC `m:real^N` THEN DISCH_TAC THEN REPEAT GEN_TAC THEN
12426   DISCH_THEN(SUBST_ALL_TAC o SYM) THEN POP_ASSUM MP_TAC THEN
12427   GEOM_ORIGIN_TAC `a:real^N` THEN GEOM_BASIS_MULTIPLE_TAC 1 `b:real^N` THEN
12428   X_GEN_TAC `b:real` THEN DISCH_TAC THEN
12429   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
12430   SIMP_TAC[VECTOR_SUB_RZERO; NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
12431   ASM_REWRITE_TAC[real_abs; REAL_MUL_RID] THEN DISCH_THEN SUBST_ALL_TAC THEN
12432   POP_ASSUM(K ALL_TAC) THEN
12433   ASM_CASES_TAC `collinear{vec 0:real^N,&1 % basis 1,y}` THENL
12434    [POP_ASSUM MP_TAC THEN
12435     SIMP_TAC[COLLINEAR_LEMMA_ALT; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL] THEN
12436     MATCH_MP_TAC(TAUT
12437      `~a /\ (b ==> c ==> d) ==> a \/ b ==> a \/ c ==> d`) THEN
12438     CONJ_TAC THENL
12439      [SIMP_TAC[VECTOR_MUL_LID; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL];
12440       REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN
12441     X_GEN_TAC `b:real` THEN DISCH_THEN SUBST_ALL_TAC THEN
12442     X_GEN_TAC `a:real` THEN DISCH_THEN SUBST_ALL_TAC THEN
12443     REWRITE_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RID] THEN
12444     SUBST1_TAC(VECTOR_ARITH `vec 0:real^N = &0 % basis 1`) THEN
12445     SIMP_TAC[SEGMENT_SCALAR_MULTIPLE; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL;
12446      VECTOR_MUL_RCANCEL; IMAGE_EQ_EMPTY; FINITE_IMAGE_INJ_EQ; SET_RULE
12447      `(!x y. x % v = y % v <=> x = y)
12448       ==> {x % v | P x} INTER {x % v | Q x} =
12449           IMAGE (\x. x % v) {x | P x /\ Q x}`] THEN
12450     REWRITE_TAC[REAL_ARITH `(&0 < x /\ x < &1 \/ &1 < x /\ x < &0) /\
12451                             (b < x /\ x < a \/ a < x /\ x < b) <=>
12452                        max (&0) (min a b) < x /\ x < min (&1) (max a b)`] THEN
12453     SIMP_TAC[FINITE_REAL_INTERVAL; EXTENSION; NOT_IN_EMPTY; IN_ELIM_THM] THEN
12454     SIMP_TAC[GSYM REAL_LT_BETWEEN; GSYM NOT_EXISTS_THM] THEN REAL_ARITH_TAC;
12455     DISCH_TAC THEN ASM_CASES_TAC
12456      `segment(vec 0:real^N,&1 % basis 1) INTER segment (x,y) = {}` THEN
12457     ASM_REWRITE_TAC[FINITE_EMPTY] THEN DISCH_THEN(K ALL_TAC) THEN
12458     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
12459     REWRITE_TAC[open_segment; IN_DIFF; NOT_IN_EMPTY;
12460                 DE_MORGAN_THM; IN_INTER; IN_INSERT] THEN
12461     DISCH_THEN(X_CHOOSE_THEN `p:real^N` STRIP_ASSUME_TAC) THEN
12462     UNDISCH_TAC `~collinear{vec 0:real^N,&1 % basis 1, y}` THEN
12463     RULE_ASSUM_TAC(REWRITE_RULE[VECTOR_MUL_LID]) THEN
12464     REWRITE_TAC[VECTOR_MUL_LID] THEN
12465     MATCH_MP_TAC COLLINEAR_SUBSET THEN
12466     EXISTS_TAC `{p,x:real^N, y, vec 0, basis 1}` THEN
12467     CONJ_TAC THENL [ALL_TAC; SET_TAC[]] THEN
12468     MP_TAC(ISPECL [`{y:real^N,vec 0,basis 1}`; `p:real^N`; `x:real^N`]
12469         COLLINEAR_TRIPLES) THEN
12470     ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST1_TAC THEN
12471     REWRITE_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY] THEN CONJ_TAC THENL
12472      [ONCE_REWRITE_TAC[SET_RULE `{p,x,y} = {x,p,y}`] THEN
12473       MATCH_MP_TAC BETWEEN_IMP_COLLINEAR THEN
12474       ASM_REWRITE_TAC[BETWEEN_IN_SEGMENT];
12475       ALL_TAC] THEN
12476     ASM_SIMP_TAC[GSYM COLLINEAR_4_3] THEN
12477     ONCE_REWRITE_TAC[SET_RULE `{p,x,z,w} = {w,z,p,x}`] THEN
12478     SIMP_TAC[COLLINEAR_4_3; BASIS_NONZERO; DIMINDEX_GE_1; ARITH] THEN
12479     REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP BETWEEN_IMP_COLLINEAR o
12480         GEN_REWRITE_RULE I [GSYM BETWEEN_IN_SEGMENT])) THEN
12481     REPEAT(POP_ASSUM MP_TAC) THEN SIMP_TAC[INSERT_AC]]);;
12482
12483 let DIST_IN_CLOSED_SEGMENT,DIST_IN_OPEN_SEGMENT = (CONJ_PAIR o prove)
12484  (`(!a b x:real^N.
12485     x IN segment[a,b] ==> dist(x,a) <= dist(a,b) /\ dist(x,b) <= dist(a,b)) /\
12486    (!a b x:real^N.
12487     x IN segment(a,b) ==> dist(x,a) < dist(a,b) /\ dist(x,b) < dist(a,b))`,
12488   SIMP_TAC[IN_SEGMENT; RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM; dist;
12489            VECTOR_ARITH
12490     `((&1 - u) % a + u % b) - a:real^N = u % (b - a) /\
12491      ((&1 - u) % a + u % b) - b = --(&1 - u) % (b - a)`] THEN
12492   REWRITE_TAC[NORM_MUL; REAL_ABS_NEG; NORM_SUB] THEN CONJ_TAC THEN
12493   REPEAT GEN_TAC THEN STRIP_TAC THENL
12494    [REWRITE_TAC[REAL_ARITH `x * y <= y <=> x * y <= &1 * y`] THEN
12495     CONJ_TAC THEN MATCH_MP_TAC REAL_LE_RMUL THEN
12496     REWRITE_TAC[NORM_POS_LE] THEN ASM_REAL_ARITH_TAC;
12497     REWRITE_TAC[REAL_ARITH `x * y < y <=> x * y < &1 * y`] THEN
12498     ASM_SIMP_TAC[REAL_LT_RMUL_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
12499     ASM_REAL_ARITH_TAC]);;
12500
12501 let DIST_DECREASES_OPEN_SEGMENT = prove
12502  (`!a b c x:real^N.
12503       x IN segment(a,b) ==> dist(c,x) < dist(c,a) \/ dist(c,x) < dist(c,b)`,
12504   GEOM_ORIGIN_TAC `a:real^N` THEN GEOM_NORMALIZE_TAC `b:real^N` THEN
12505   REWRITE_TAC[SEGMENT_REFL; NOT_IN_EMPTY] THEN X_GEN_TAC `b:real^N` THEN
12506   GEOM_BASIS_MULTIPLE_TAC 1 `b:real^N` THEN X_GEN_TAC `b:real` THEN
12507   SIMP_TAC[NORM_MUL; NORM_BASIS; real_abs; DIMINDEX_GE_1; LE_REFL;
12508            REAL_MUL_RID; VECTOR_MUL_LID] THEN
12509   REPEAT(DISCH_THEN(K ALL_TAC)) THEN REPEAT GEN_TAC THEN
12510   REWRITE_TAC[IN_SEGMENT; dist] THEN STRIP_TAC THEN
12511   ASM_REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_LID] THEN
12512   SUBGOAL_THEN
12513    `norm((c$1 - u) % basis 1:real^N) < norm((c:real^N)$1 % basis 1:real^N) \/
12514     norm((c$1 - u) % basis 1:real^N) < norm((c$1 - &1) % basis 1:real^N)`
12515   MP_TAC THENL
12516    [SIMP_TAC[NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
12517     ASM_REAL_ARITH_TAC;
12518     ASM_SIMP_TAC[NORM_LT; DOT_LMUL; DOT_RMUL; DOT_BASIS; DIMINDEX_GE_1;
12519               DOT_LSUB; DOT_RSUB; LE_REFL; VECTOR_MUL_COMPONENT; VEC_COMPONENT;
12520               BASIS_COMPONENT; DOT_LZERO; DOT_RZERO; VECTOR_SUB_COMPONENT] THEN
12521     ASM_REAL_ARITH_TAC]);;
12522
12523 let DIST_DECREASES_CLOSED_SEGMENT = prove
12524  (`!a b c x:real^N.
12525       x IN segment[a,b] ==> dist(c,x) <= dist(c,a) \/ dist(c,x) <= dist(c,b)`,
12526   REWRITE_TAC[SEGMENT_CLOSED_OPEN; IN_UNION; IN_INSERT; NOT_IN_EMPTY] THEN
12527   ASM_MESON_TAC[DIST_DECREASES_OPEN_SEGMENT; REAL_LE_REFL; REAL_LT_IMP_LE]);;
12528
12529 (* ------------------------------------------------------------------------- *)
12530 (* Limit component bounds.                                                   *)
12531 (* ------------------------------------------------------------------------- *)
12532
12533 let LIM_COMPONENT_UBOUND = prove
12534  (`!net:(A)net f (l:real^N) b k.
12535         ~(trivial_limit net) /\ (f --> l) net /\
12536         eventually (\x. (f x)$k <= b) net /\
12537         1 <= k /\ k <= dimindex(:N)
12538         ==> l$k <= b`,
12539   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
12540    [`net:(A)net`; `f:A->real^N`; `{y:real^N | basis k dot y <= b}`; `l:real^N`]
12541    LIM_IN_CLOSED_SET) THEN
12542   ASM_SIMP_TAC[CLOSED_HALFSPACE_LE; IN_ELIM_THM; DOT_BASIS]);;
12543
12544 let LIM_COMPONENT_LBOUND = prove
12545  (`!net:(A)net f (l:real^N) b k.
12546         ~(trivial_limit net) /\ (f --> l) net /\
12547         eventually (\x. b <= (f x)$k) net /\
12548         1 <= k /\ k <= dimindex(:N)
12549         ==> b <= l$k`,
12550   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
12551    [`net:(A)net`; `f:A->real^N`; `{y:real^N | b <= basis k dot y}`; `l:real^N`]
12552    LIM_IN_CLOSED_SET) THEN
12553   ASM_SIMP_TAC[REWRITE_RULE[real_ge] CLOSED_HALFSPACE_GE;
12554                IN_ELIM_THM; DOT_BASIS]);;
12555
12556 let LIM_COMPONENT_EQ = prove
12557  (`!net f:A->real^N i l b.
12558         (f --> l) net /\ 1 <= i /\ i <= dimindex(:N) /\
12559         ~(trivial_limit net) /\ eventually (\x. f(x)$i = b) net
12560         ==> l$i = b`,
12561   REWRITE_TAC[GSYM REAL_LE_ANTISYM; EVENTUALLY_AND] THEN
12562   MESON_TAC[LIM_COMPONENT_UBOUND; LIM_COMPONENT_LBOUND]);;
12563
12564 let LIM_COMPONENT_LE = prove
12565  (`!net:(A)net f:A->real^N g:A->real^N k l m.
12566          ~(trivial_limit net) /\ (f --> l) net /\ (g --> m) net /\
12567         eventually (\x. (f x)$k <= (g x)$k) net /\
12568         1 <= k /\ k <= dimindex(:N)
12569         ==> l$k <= m$k`,
12570   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LE] THEN
12571   REWRITE_TAC[GSYM VECTOR_SUB_COMPONENT; LIM_COMPONENT_LBOUND] THEN
12572   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
12573   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> b /\ a ==> c ==> d`] THEN
12574   DISCH_THEN(MP_TAC o MATCH_MP LIM_SUB) THEN POP_ASSUM MP_TAC THEN
12575   REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC; LIM_COMPONENT_LBOUND]);;
12576
12577 let LIM_DROP_LE = prove
12578  (`!net:(A)net f g l m.
12579          ~(trivial_limit net) /\ (f --> l) net /\ (g --> m) net /\
12580         eventually (\x. drop(f x) <= drop(g x)) net
12581         ==> drop l <= drop m`,
12582   REWRITE_TAC[drop] THEN REPEAT STRIP_TAC THEN
12583   MATCH_MP_TAC(ISPEC `net:(A)net` LIM_COMPONENT_LE) THEN
12584   MAP_EVERY EXISTS_TAC [`f:A->real^1`; `g:A->real^1`] THEN
12585   ASM_REWRITE_TAC[DIMINDEX_1; LE_REFL]);;
12586
12587 let LIM_DROP_UBOUND = prove
12588  (`!net f:A->real^1 l b.
12589         (f --> l) net /\
12590         ~(trivial_limit net) /\ eventually (\x. drop(f x) <= b) net
12591         ==> drop l <= b`,
12592   SIMP_TAC[drop] THEN REPEAT STRIP_TAC THEN
12593   MATCH_MP_TAC LIM_COMPONENT_UBOUND THEN
12594   REWRITE_TAC[LE_REFL; DIMINDEX_1] THEN ASM_MESON_TAC[]);;
12595
12596 let LIM_DROP_LBOUND = prove
12597  (`!net f:A->real^1 l b.
12598         (f --> l) net /\
12599         ~(trivial_limit net) /\ eventually (\x. b <= drop(f x)) net
12600         ==> b <= drop l`,
12601   SIMP_TAC[drop] THEN REPEAT STRIP_TAC THEN
12602   MATCH_MP_TAC LIM_COMPONENT_LBOUND THEN
12603   REWRITE_TAC[LE_REFL; DIMINDEX_1] THEN ASM_MESON_TAC[]);;
12604
12605 (* ------------------------------------------------------------------------- *)
12606 (* Also extending closed bounds to closures.                                 *)
12607 (* ------------------------------------------------------------------------- *)
12608
12609 let IMAGE_CLOSURE_SUBSET = prove
12610  (`!f (s:real^N->bool) (t:real^M->bool).
12611       f continuous_on closure s /\ closed t /\ IMAGE f s SUBSET t
12612       ==> IMAGE f (closure s) SUBSET t`,
12613   REPEAT STRIP_TAC THEN
12614   SUBGOAL_THEN `closure s SUBSET {x | (f:real^N->real^M) x IN t}` MP_TAC
12615   THENL [MATCH_MP_TAC SUBSET_TRANS; SET_TAC []]  THEN
12616   EXISTS_TAC `{x | x IN closure s /\ (f:real^N->real^M) x IN t}` THEN
12617   CONJ_TAC THENL
12618   [MATCH_MP_TAC CLOSURE_MINIMAL; SET_TAC[]] THEN
12619   ASM_SIMP_TAC[CONTINUOUS_CLOSED_PREIMAGE; CLOSED_CLOSURE] THEN
12620   MP_TAC (ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[]);;
12621
12622 let CLOSURE_IMAGE_CLOSURE = prove
12623  (`!f:real^M->real^N s.
12624         f continuous_on closure s
12625         ==> closure(IMAGE f (closure s)) = closure(IMAGE f s)`,
12626   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
12627   SIMP_TAC[SUBSET_CLOSURE; IMAGE_SUBSET; CLOSURE_SUBSET] THEN
12628   SIMP_TAC[CLOSURE_MINIMAL_EQ; CLOSED_CLOSURE] THEN
12629   MATCH_MP_TAC IMAGE_CLOSURE_SUBSET THEN
12630   ASM_REWRITE_TAC[CLOSED_CLOSURE; CLOSURE_SUBSET]);;
12631
12632 let CLOSURE_IMAGE_BOUNDED = prove
12633  (`!f:real^M->real^N s.
12634         f continuous_on closure s /\ bounded s
12635         ==> closure(IMAGE f s) = IMAGE f (closure s)`,
12636   REPEAT STRIP_TAC THEN
12637   TRANS_TAC EQ_TRANS `closure(IMAGE (f:real^M->real^N) (closure s))` THEN
12638   CONJ_TAC THENL [ASM_MESON_TAC[CLOSURE_IMAGE_CLOSURE]; ALL_TAC] THEN
12639   MATCH_MP_TAC CLOSURE_CLOSED THEN MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
12640   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
12641   ASM_REWRITE_TAC[COMPACT_CLOSURE]);;
12642
12643 let CONTINUOUS_ON_CLOSURE_NORM_LE = prove
12644  (`!f:real^N->real^M s x b.
12645       f continuous_on (closure s) /\
12646       (!y. y IN s ==> norm(f y) <= b) /\
12647       x IN (closure s)
12648       ==> norm(f x) <= b`,
12649   REWRITE_TAC [GSYM IN_CBALL_0] THEN REPEAT STRIP_TAC THEN
12650   SUBGOAL_THEN `IMAGE (f:real^N->real^M) (closure s) SUBSET cball(vec 0,b)`
12651     MP_TAC THENL
12652   [MATCH_MP_TAC IMAGE_CLOSURE_SUBSET; ASM SET_TAC []] THEN
12653   ASM_REWRITE_TAC [CLOSED_CBALL] THEN ASM SET_TAC []);;
12654
12655 let CONTINUOUS_ON_CLOSURE_COMPONENT_LE = prove
12656  (`!f:real^N->real^M s x b k.
12657       f continuous_on (closure s) /\
12658       (!y. y IN s ==> (f y)$k <= b) /\
12659       x IN (closure s)
12660       ==> (f x)$k <= b`,
12661   REWRITE_TAC [GSYM IN_CBALL_0] THEN REPEAT STRIP_TAC THEN
12662   SUBGOAL_THEN `IMAGE (f:real^N->real^M) (closure s) SUBSET {x | x$k <= b}`
12663   MP_TAC THENL
12664    [MATCH_MP_TAC IMAGE_CLOSURE_SUBSET; ASM SET_TAC []] THEN
12665   ASM_REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_LE] THEN ASM SET_TAC[]);;
12666
12667 let CONTINUOUS_ON_CLOSURE_COMPONENT_GE = prove
12668  (`!f:real^N->real^M s x b k.
12669       f continuous_on (closure s) /\
12670       (!y. y IN s ==> b <= (f y)$k) /\
12671       x IN (closure s)
12672       ==> b <= (f x)$k`,
12673   REWRITE_TAC [GSYM IN_CBALL_0] THEN REPEAT STRIP_TAC THEN
12674   SUBGOAL_THEN `IMAGE (f:real^N->real^M) (closure s) SUBSET {x | x$k >= b}`
12675   MP_TAC THENL
12676    [MATCH_MP_TAC IMAGE_CLOSURE_SUBSET; ASM SET_TAC [real_ge]] THEN
12677   ASM_REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_GE] THEN ASM SET_TAC[real_ge]);;
12678
12679 (* ------------------------------------------------------------------------- *)
12680 (* Limits relative to a union.                                               *)
12681 (* ------------------------------------------------------------------------- *)
12682
12683 let LIM_WITHIN_UNION = prove
12684  (`(f --> l) (at x within (s UNION t)) <=>
12685    (f --> l) (at x within s) /\ (f --> l) (at x within t)`,
12686   REWRITE_TAC[LIM_WITHIN; IN_UNION; AND_FORALL_THM] THEN
12687   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN
12688   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
12689   EQ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN DISCH_THEN
12690    (CONJUNCTS_THEN2 (X_CHOOSE_TAC `d:real`) (X_CHOOSE_TAC `k:real`)) THEN
12691   EXISTS_TAC `min d k` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
12692   ASM_MESON_TAC[]);;
12693
12694 let CONTINUOUS_ON_UNION = prove
12695  (`!f s t. closed s /\ closed t /\ f continuous_on s /\ f continuous_on t
12696            ==> f continuous_on (s UNION t)`,
12697   REWRITE_TAC[CONTINUOUS_ON; CLOSED_LIMPT; IN_UNION; LIM_WITHIN_UNION] THEN
12698   MESON_TAC[LIM; TRIVIAL_LIMIT_WITHIN]);;
12699
12700 let CONTINUOUS_ON_CASES = prove
12701  (`!P f g:real^M->real^N s t.
12702         closed s /\ closed t /\ f continuous_on s /\ g continuous_on t /\
12703         (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x)
12704         ==> (\x. if P x then f x else g x) continuous_on (s UNION t)`,
12705   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_UNION THEN
12706   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THENL
12707    [EXISTS_TAC `f:real^M->real^N`; EXISTS_TAC `g:real^M->real^N`] THEN
12708   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
12709
12710 let CONTINUOUS_ON_UNION_LOCAL = prove
12711  (`!f:real^M->real^N s.
12712         closed_in (subtopology euclidean (s UNION t)) s /\
12713         closed_in (subtopology euclidean (s UNION t)) t /\
12714         f continuous_on s /\ f continuous_on t
12715         ==> f continuous_on (s UNION t)`,
12716   REWRITE_TAC[CONTINUOUS_ON; CLOSED_IN_LIMPT; IN_UNION; LIM_WITHIN_UNION] THEN
12717   MESON_TAC[LIM; TRIVIAL_LIMIT_WITHIN]);;
12718
12719 let CONTINUOUS_ON_CASES_LOCAL = prove
12720  (`!P f g:real^M->real^N s t.
12721         closed_in (subtopology euclidean (s UNION t)) s /\
12722         closed_in (subtopology euclidean (s UNION t)) t /\
12723         f continuous_on s /\ g continuous_on t /\
12724         (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x)
12725         ==> (\x. if P x then f x else g x) continuous_on (s UNION t)`,
12726   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_UNION_LOCAL THEN
12727   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THENL
12728    [EXISTS_TAC `f:real^M->real^N`; EXISTS_TAC `g:real^M->real^N`] THEN
12729   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
12730
12731 let CONTINUOUS_ON_CASES_LE = prove
12732  (`!f g:real^M->real^N h s a.
12733         f continuous_on {t | t IN s /\ h t <= a} /\
12734         g continuous_on {t | t IN s /\ a <= h t} /\
12735         (lift o h) continuous_on s /\
12736         (!t. t IN s /\ h t = a ==> f t = g t)
12737         ==> (\t. if h t <= a then f(t) else g(t)) continuous_on s`,
12738   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC
12739    `{t | t IN s /\ (h:real^M->real) t <= a} UNION
12740     {t | t IN s /\ a <= h t}` THEN
12741   CONJ_TAC THENL
12742    [ALL_TAC; SIMP_TAC[SUBSET; IN_UNION; IN_ELIM_THM; REAL_LE_TOTAL]] THEN
12743   MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL THEN ASM_REWRITE_TAC[] THEN
12744   REWRITE_TAC[IN_ELIM_THM; GSYM CONJ_ASSOC; REAL_LE_ANTISYM] THEN
12745   REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL
12746    [ALL_TAC; ASM_MESON_TAC[]] THEN
12747   CONJ_TAC THENL
12748    [SUBGOAL_THEN
12749      `{t | t IN s /\ (h:real^M->real) t <= a} =
12750       {t | t IN ({t | t IN s /\ h t <= a} UNION {t | t IN s /\ a <= h t}) /\
12751            (lift o h) t IN {x | x$1 <= a}}`
12752      (fun th -> GEN_REWRITE_TAC RAND_CONV [th])
12753     THENL
12754      [REWRITE_TAC[GSYM drop; o_THM; IN_ELIM_THM; LIFT_DROP; EXTENSION;
12755                   IN_UNION] THEN
12756       GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
12757       ASM_REAL_ARITH_TAC;
12758       MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
12759       ASM_REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_LE; ETA_AX] THEN
12760       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
12761         CONTINUOUS_ON_SUBSET)) THEN
12762       SET_TAC[]];
12763     SUBGOAL_THEN
12764      `{t | t IN s /\ a <= (h:real^M->real) t} =
12765       {t | t IN ({t | t IN s /\ h t <= a} UNION {t | t IN s /\ a <= h t}) /\
12766            (lift o h) t IN {x | x$1 >= a}}`
12767      (fun th -> GEN_REWRITE_TAC RAND_CONV [th])
12768     THENL
12769      [REWRITE_TAC[GSYM drop; o_THM; IN_ELIM_THM; LIFT_DROP; EXTENSION;
12770                   IN_UNION] THEN
12771       GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
12772       ASM_REAL_ARITH_TAC;
12773       MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
12774       ASM_REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_GE; ETA_AX] THEN
12775       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
12776         CONTINUOUS_ON_SUBSET)) THEN
12777       SET_TAC[]]]);;
12778
12779 let CONTINUOUS_ON_CASES_1 = prove
12780  (`!f g:real^1->real^N s a.
12781         f continuous_on {t | t IN s /\ drop t <= a} /\
12782         g continuous_on {t | t IN s /\ a <= drop t} /\
12783         (lift a IN s ==> f(lift a) = g(lift a))
12784         ==> (\t. if drop t <= a then f(t) else g(t)) continuous_on s`,
12785   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_CASES_LE THEN
12786   ASM_REWRITE_TAC[o_DEF; LIFT_DROP; CONTINUOUS_ON_ID] THEN
12787   REWRITE_TAC[GSYM LIFT_EQ; LIFT_DROP] THEN ASM_MESON_TAC[]);;
12788
12789 let EXTENSION_FROM_CLOPEN = prove
12790  (`!f:real^M->real^N s t u.
12791         open_in (subtopology euclidean s) t /\
12792         closed_in (subtopology euclidean s) t /\
12793         f continuous_on t /\ IMAGE f t SUBSET u /\ (u = {} ==> s = {})
12794         ==> ?g. g continuous_on s /\ IMAGE g s SUBSET u /\
12795                 !x. x IN t ==> g x = f x`,
12796   REPEAT GEN_TAC THEN ASM_CASES_TAC `u:real^N->bool = {}` THEN
12797   ASM_SIMP_TAC[CONTINUOUS_ON_EMPTY; IMAGE_CLAUSES; SUBSET_EMPTY;
12798                IMAGE_EQ_EMPTY; NOT_IN_EMPTY] THEN
12799   STRIP_TAC THEN
12800   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
12801   DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
12802   EXISTS_TAC `\x. if x IN t then (f:real^M->real^N) x else a` THEN
12803   SIMP_TAC[SUBSET; FORALL_IN_IMAGE] THEN
12804   CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
12805   FIRST_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
12806   SUBGOAL_THEN `s:real^M->bool = t UNION (s DIFF t)` SUBST1_TAC THENL
12807    [ASM SET_TAC[]; MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL] THEN
12808   ASM_SIMP_TAC[SET_RULE `t SUBSET s ==> t UNION (s DIFF t) = s`] THEN
12809   REWRITE_TAC[CONTINUOUS_ON_CONST; IN_DIFF] THEN
12810   CONJ_TAC THENL [MATCH_MP_TAC CLOSED_IN_DIFF; MESON_TAC[]] THEN
12811   ASM_REWRITE_TAC[CLOSED_IN_REFL]);;
12812
12813 (* ------------------------------------------------------------------------- *)
12814 (* Componentwise limits and continuity.                                      *)
12815 (* ------------------------------------------------------------------------- *)
12816
12817 let LIM_COMPONENTWISE_LIFT = prove
12818  (`!net f:A->real^N.
12819         (f --> l) net <=>
12820         !i. 1 <= i /\ i <= dimindex(:N)
12821             ==> ((\x. lift((f x)$i)) --> lift(l$i)) net`,
12822   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto] THEN EQ_TAC THENL
12823    [DISCH_TAC THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
12824     X_GEN_TAC `e:real` THEN
12825     DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN
12826     ASM_SIMP_TAC[GSYM VECTOR_SUB_COMPONENT] THEN
12827     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
12828     GEN_TAC THEN REWRITE_TAC[dist] THEN MATCH_MP_TAC(REAL_ARITH
12829      `y <= x ==> x < e ==> y < e`) THEN
12830     ASM_SIMP_TAC[COMPONENT_LE_NORM; GSYM LIFT_SUB; NORM_LIFT;
12831                  GSYM VECTOR_SUB_COMPONENT];
12832     GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [RIGHT_IMP_FORALL_THM] THEN
12833     ONCE_REWRITE_TAC[IMP_IMP] THEN ONCE_REWRITE_TAC[IMP_CONJ_ALT] THEN
12834     ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
12835     REWRITE_TAC[GSYM IN_NUMSEG; RIGHT_FORALL_IMP_THM] THEN
12836     SIMP_TAC[FORALL_EVENTUALLY; FINITE_NUMSEG; NUMSEG_EMPTY;
12837              GSYM NOT_LE; DIMINDEX_GE_1] THEN
12838     REWRITE_TAC[DIST_LIFT; GSYM VECTOR_SUB_COMPONENT] THEN
12839     DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
12840     FIRST_X_ASSUM(MP_TAC o SPEC `e / &(dimindex(:N))`) THEN
12841     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1] THEN
12842     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
12843     X_GEN_TAC `x:A` THEN SIMP_TAC[GSYM VECTOR_SUB_COMPONENT; dist] THEN
12844     DISCH_TAC THEN W(MP_TAC o PART_MATCH lhand NORM_LE_L1 o lhand o snd) THEN
12845     MATCH_MP_TAC(REAL_ARITH `s < e ==> n <= s ==> n < e`) THEN
12846     MATCH_MP_TAC SUM_BOUND_LT_GEN THEN
12847     ASM_SIMP_TAC[FINITE_NUMSEG; NUMSEG_EMPTY; GSYM NOT_LE; DIMINDEX_GE_1;
12848                  CARD_NUMSEG_1; GSYM IN_NUMSEG]]);;
12849
12850 let CONTINUOUS_COMPONENTWISE_LIFT = prove
12851  (`!net f:A->real^N.
12852         f continuous net <=>
12853         !i. 1 <= i /\ i <= dimindex(:N)
12854             ==> (\x. lift((f x)$i)) continuous net`,
12855   REWRITE_TAC[continuous; GSYM LIM_COMPONENTWISE_LIFT]);;
12856
12857 let CONTINUOUS_ON_COMPONENTWISE_LIFT = prove
12858  (`!f:real^M->real^N s.
12859         f continuous_on s <=>
12860         !i. 1 <= i /\ i <= dimindex(:N)
12861             ==> (\x. lift((f x)$i)) continuous_on s`,
12862   REPEAT GEN_TAC THEN
12863   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
12864   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
12865    [CONTINUOUS_COMPONENTWISE_LIFT] THEN
12866   MESON_TAC[]);;
12867
12868 (* ------------------------------------------------------------------------- *)
12869 (* Some more convenient intermediate-value theorem formulations.             *)
12870 (* ------------------------------------------------------------------------- *)
12871
12872 let CONNECTED_IVT_HYPERPLANE = prove
12873  (`!s x y:real^N a b.
12874         connected s /\
12875         x IN s /\ y IN s /\ a dot x <= b /\ b <= a dot y
12876         ==> ?z. z IN s /\ a dot z = b`,
12877   REPEAT STRIP_TAC THEN
12878   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [connected]) THEN
12879   REWRITE_TAC[NOT_EXISTS_THM] THEN DISCH_THEN(MP_TAC o SPECL
12880    [`{x:real^N | a dot x < b}`; `{x:real^N | a dot x > b}`]) THEN
12881   REWRITE_TAC[OPEN_HALFSPACE_LT; OPEN_HALFSPACE_GT] THEN
12882   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN STRIP_TAC THEN
12883   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_INTER; NOT_IN_EMPTY; SUBSET;
12884               IN_UNION; REAL_LT_LE; real_gt] THEN
12885   ASM_MESON_TAC[REAL_LE_TOTAL; REAL_LE_ANTISYM]);;
12886
12887 let CONNECTED_IVT_COMPONENT = prove
12888  (`!s x y:real^N a k.
12889         connected s /\ x IN s /\ y IN s /\
12890         1 <= k /\ k <= dimindex(:N) /\ x$k <= a /\ a <= y$k
12891         ==> ?z. z IN s /\ z$k = a`,
12892   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
12893    [`s:real^N->bool`; `x:real^N`; `y:real^N`; `(basis k):real^N`;
12894     `a:real`] CONNECTED_IVT_HYPERPLANE) THEN
12895   ASM_SIMP_TAC[DOT_BASIS]);;
12896
12897 (* ------------------------------------------------------------------------- *)
12898 (* Rather trivial observation that we can map any connected set on segment.  *)
12899 (* ------------------------------------------------------------------------- *)
12900
12901 let MAPPING_CONNECTED_ONTO_SEGMENT = prove
12902  (`!s:real^M->bool a b:real^N.
12903         connected s /\ ~(?a. s SUBSET {a})
12904         ==> ?f. f continuous_on s /\ IMAGE f s = segment[a,b]`,
12905   REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE
12906    `~(?a. s SUBSET {a}) ==> ?a b. a IN s /\ b IN s /\ ~(a = b)`)) THEN
12907   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
12908   MAP_EVERY X_GEN_TAC [`u:real^M`; `v:real^M`] THEN STRIP_TAC THEN EXISTS_TAC
12909    `\x:real^M. a + dist(u,x) / (dist(u,x) + dist(v,x)) % (b - a:real^N)` THEN
12910   CONJ_TAC THENL
12911    [MATCH_MP_TAC CONTINUOUS_ON_ADD THEN REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
12912     MATCH_MP_TAC CONTINUOUS_ON_MUL THEN SIMP_TAC[o_DEF; CONTINUOUS_ON_CONST];
12913     REWRITE_TAC[segment; VECTOR_ARITH
12914      `(&1 - u) % a + u % b:real^N = a + u % (b - a)`] THEN
12915     MATCH_MP_TAC(SET_RULE
12916      `IMAGE f s = {x | P x}
12917       ==> IMAGE (\x. a + f x % b) s = {a + u % b:real^N | P u}`) THEN
12918     REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; SUBSET; FORALL_IN_IMAGE] THEN
12919     ASM_SIMP_TAC[IN_ELIM_THM; REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ;
12920       NORM_ARITH `~(u:real^N = v) ==> &0 < dist(u,x) + dist(v,x)`] THEN
12921     CONJ_TAC THENL [CONV_TAC NORM_ARITH; REWRITE_TAC[IN_IMAGE]] THEN
12922     X_GEN_TAC `t:real` THEN STRIP_TAC THEN
12923     MP_TAC(ISPECL
12924      [`IMAGE (\x:real^M. lift(dist(u,x) / (dist(u,x) + dist(v,x)))) s`;
12925       `vec 0:real^1`; `vec 1:real^1`; `t:real`; `1`]
12926         CONNECTED_IVT_COMPONENT) THEN
12927     ASM_SIMP_TAC[VEC_COMPONENT; DIMINDEX_1; ARITH_LE] THEN
12928     REWRITE_TAC[EXISTS_IN_IMAGE; GSYM drop; LIFT_DROP] THEN
12929     ANTS_TAC THENL [REWRITE_TAC[IN_IMAGE]; MESON_TAC[]] THEN
12930     REPEAT CONJ_TAC THENL
12931      [MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[];
12932       EXISTS_TAC `u:real^M` THEN ASM_REWRITE_TAC[DIST_REFL; real_div] THEN
12933       REWRITE_TAC[GSYM LIFT_NUM; LIFT_EQ] THEN REAL_ARITH_TAC;
12934       EXISTS_TAC `v:real^M` THEN ASM_REWRITE_TAC[DIST_REFL] THEN
12935       ASM_SIMP_TAC[REAL_DIV_REFL; DIST_EQ_0; REAL_ADD_RID] THEN
12936       REWRITE_TAC[GSYM LIFT_NUM; LIFT_EQ]]] THEN
12937   REWRITE_TAC[real_div; LIFT_CMUL] THEN
12938   MATCH_MP_TAC CONTINUOUS_ON_MUL THEN
12939   REWRITE_TAC[CONTINUOUS_ON_LIFT_DIST] THEN
12940   MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_INV) THEN
12941   ASM_SIMP_TAC[LIFT_ADD; NORM_ARITH
12942    `~(u:real^N = v) ==> ~(dist(u,x) + dist(v,x) = &0)`] THEN
12943   MATCH_MP_TAC CONTINUOUS_ON_ADD THEN
12944   REWRITE_TAC[REWRITE_RULE[o_DEF] CONTINUOUS_ON_LIFT_DIST]);;
12945
12946 (* ------------------------------------------------------------------------- *)
12947 (* Also more convenient formulations of monotone convergence.                *)
12948 (* ------------------------------------------------------------------------- *)
12949
12950 let BOUNDED_INCREASING_CONVERGENT = prove
12951  (`!s:num->real^1.
12952         bounded {s n | n IN (:num)} /\ (!n. drop(s n) <= drop(s(SUC n)))
12953         ==> ?l. (s --> l) sequentially`,
12954   GEN_TAC THEN
12955   REWRITE_TAC[bounded; IN_ELIM_THM; ABS_DROP; LIM_SEQUENTIALLY; dist;
12956               DROP_SUB; IN_UNIV; GSYM EXISTS_DROP] THEN
12957   DISCH_TAC THEN MATCH_MP_TAC CONVERGENT_BOUNDED_MONOTONE THEN
12958   REWRITE_TAC[LEFT_EXISTS_AND_THM] THEN
12959   CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
12960   DISJ1_TAC THEN MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
12961   ASM_REWRITE_TAC[REAL_LE_TRANS; REAL_LE_REFL]);;
12962
12963 let BOUNDED_DECREASING_CONVERGENT = prove
12964  (`!s:num->real^1.
12965         bounded {s n | n IN (:num)} /\ (!n. drop(s(SUC n)) <= drop(s(n)))
12966         ==> ?l. (s --> l) sequentially`,
12967   GEN_TAC THEN REWRITE_TAC[bounded; FORALL_IN_GSPEC] THEN
12968   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
12969   MP_TAC(ISPEC `\n. --((s:num->real^1) n)` BOUNDED_INCREASING_CONVERGENT) THEN
12970   ASM_SIMP_TAC[bounded; FORALL_IN_GSPEC; NORM_NEG; DROP_NEG; REAL_LE_NEG2] THEN
12971   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [GSYM LIM_NEG_EQ] THEN
12972   REWRITE_TAC[VECTOR_NEG_NEG; ETA_AX] THEN MESON_TAC[]);;
12973
12974 (* ------------------------------------------------------------------------- *)
12975 (* Since we'll use some cardinality reasoning, add invariance theorems.      *)
12976 (* ------------------------------------------------------------------------- *)
12977
12978 let card_translation_invariants = (CONJUNCTS o prove)
12979  (`(!a (s:real^N->bool) (t:A->bool).
12980      IMAGE (\x. a + x) s =_c t <=> s =_c t) /\
12981    (!a (s:A->bool) (t:real^N->bool).
12982      s =_c IMAGE (\x. a + x) t <=> s =_c t) /\
12983    (!a (s:real^N->bool) (t:A->bool).
12984      IMAGE (\x. a + x) s <_c t <=> s <_c t) /\
12985    (!a (s:A->bool) (t:real^N->bool).
12986      s <_c IMAGE (\x. a + x) t <=> s <_c t) /\
12987    (!a (s:real^N->bool) (t:A->bool).
12988      IMAGE (\x. a + x) s <=_c t <=> s <=_c t) /\
12989    (!a (s:A->bool) (t:real^N->bool).
12990      s <=_c IMAGE (\x. a + x) t <=> s <=_c t) /\
12991    (!a (s:real^N->bool) (t:A->bool).
12992      IMAGE (\x. a + x) s >_c t <=> s >_c t) /\
12993    (!a (s:A->bool) (t:real^N->bool).
12994      s >_c IMAGE (\x. a + x) t <=> s >_c t) /\
12995    (!a (s:real^N->bool) (t:A->bool).
12996      IMAGE (\x. a + x) s >=_c t <=> s >=_c t) /\
12997    (!a (s:A->bool) (t:real^N->bool).
12998      s >=_c IMAGE (\x. a + x) t <=> s >=_c t)`,
12999   REWRITE_TAC[gt_c; ge_c] THEN REPEAT STRIP_TAC THENL
13000    [MATCH_MP_TAC CARD_EQ_CONG;
13001     MATCH_MP_TAC CARD_EQ_CONG;
13002     MATCH_MP_TAC CARD_LT_CONG;
13003     MATCH_MP_TAC CARD_LT_CONG;
13004     MATCH_MP_TAC CARD_LE_CONG;
13005     MATCH_MP_TAC CARD_LE_CONG;
13006     MATCH_MP_TAC CARD_LT_CONG;
13007     MATCH_MP_TAC CARD_LT_CONG;
13008     MATCH_MP_TAC CARD_LE_CONG;
13009     MATCH_MP_TAC CARD_LE_CONG] THEN
13010   REWRITE_TAC[CARD_EQ_REFL] THEN MATCH_MP_TAC CARD_EQ_IMAGE THEN
13011   SIMP_TAC[VECTOR_ARITH `a + x:real^N = a + y <=> x = y`]) in
13012 add_translation_invariants card_translation_invariants;;
13013
13014 let card_linear_invariants = (CONJUNCTS o prove)
13015  (`(!(f:real^M->real^N) s (t:A->bool).
13016      linear f /\ (!x y. f x = f y ==> x = y)
13017      ==> (IMAGE f s =_c t <=> s =_c t)) /\
13018    (!(f:real^M->real^N) (s:A->bool) t.
13019      linear f /\ (!x y. f x = f y ==> x = y)
13020      ==> (s =_c IMAGE f t <=> s =_c t)) /\
13021    (!(f:real^M->real^N) s (t:A->bool).
13022      linear f /\ (!x y. f x = f y ==> x = y)
13023      ==> (IMAGE f s <_c t <=> s <_c t)) /\
13024    (!(f:real^M->real^N) (s:A->bool) t.
13025      linear f /\ (!x y. f x = f y ==> x = y)
13026      ==> (s <_c IMAGE f t <=> s <_c t)) /\
13027    (!(f:real^M->real^N) s (t:A->bool).
13028      linear f /\ (!x y. f x = f y ==> x = y)
13029      ==> (IMAGE f s <=_c t <=> s <=_c t)) /\
13030    (!(f:real^M->real^N) (s:A->bool) t.
13031      linear f /\ (!x y. f x = f y ==> x = y)
13032      ==> (s <=_c IMAGE f t <=> s <=_c t)) /\
13033    (!(f:real^M->real^N) s (t:A->bool).
13034      linear f /\ (!x y. f x = f y ==> x = y)
13035      ==> (IMAGE f s >_c t <=> s >_c t)) /\
13036    (!(f:real^M->real^N) (s:A->bool) t.
13037      linear f /\ (!x y. f x = f y ==> x = y)
13038      ==> (s >_c IMAGE f t <=> s >_c t)) /\
13039    (!(f:real^M->real^N) s (t:A->bool).
13040      linear f /\ (!x y. f x = f y ==> x = y)
13041      ==> (IMAGE f s >=_c t <=> s >=_c t)) /\
13042    (!(f:real^M->real^N) (s:A->bool) t.
13043      linear f /\ (!x y. f x = f y ==> x = y)
13044      ==> (s >=_c IMAGE f t <=> s >=_c t))`,
13045   REWRITE_TAC[gt_c; ge_c] THEN REPEAT STRIP_TAC THENL
13046    [MATCH_MP_TAC CARD_EQ_CONG;
13047     MATCH_MP_TAC CARD_EQ_CONG;
13048     MATCH_MP_TAC CARD_LT_CONG;
13049     MATCH_MP_TAC CARD_LT_CONG;
13050     MATCH_MP_TAC CARD_LE_CONG;
13051     MATCH_MP_TAC CARD_LE_CONG;
13052     MATCH_MP_TAC CARD_LT_CONG;
13053     MATCH_MP_TAC CARD_LT_CONG;
13054     MATCH_MP_TAC CARD_LE_CONG;
13055     MATCH_MP_TAC CARD_LE_CONG] THEN
13056   REWRITE_TAC[CARD_EQ_REFL] THEN MATCH_MP_TAC CARD_EQ_IMAGE THEN
13057   ASM_MESON_TAC[]) in
13058 add_linear_invariants card_linear_invariants;;
13059
13060 (* ------------------------------------------------------------------------- *)
13061 (* Basic homeomorphism definitions.                                          *)
13062 (* ------------------------------------------------------------------------- *)
13063
13064 let homeomorphism = new_definition
13065   `homeomorphism (s,t) (f,g) <=>
13066      (!x. x IN s ==> (g(f(x)) = x)) /\ (IMAGE f s = t) /\ f continuous_on s /\
13067      (!y. y IN t ==> (f(g(y)) = y)) /\ (IMAGE g t = s) /\ g continuous_on t`;;
13068
13069 parse_as_infix("homeomorphic",(12,"right"));;
13070
13071 let homeomorphic = new_definition
13072   `s homeomorphic t <=> ?f g. homeomorphism (s,t) (f,g)`;;
13073
13074 let HOMEOMORPHISM = prove
13075  (`!s:real^M->bool t:real^N->bool f g.
13076         homeomorphism (s,t) (f,g) <=>
13077          f continuous_on s /\ IMAGE f s SUBSET t /\
13078          g continuous_on t /\ IMAGE g t SUBSET s /\
13079          (!x. x IN s ==> g (f x) = x) /\
13080          (!y. y IN t ==> f (g y) = y)`,
13081   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphism] THEN
13082   EQ_TAC THEN SIMP_TAC[] THEN SET_TAC[]);;
13083
13084 let HOMEOMORPHISM_OF_SUBSETS = prove
13085  (`!f g s t s' t'.
13086     homeomorphism (s,t) (f,g) /\ s' SUBSET s /\ t' SUBSET t /\ IMAGE f s' = t'
13087     ==> homeomorphism (s',t') (f,g)`,
13088   REWRITE_TAC[homeomorphism] THEN
13089   REPEAT STRIP_TAC THEN
13090   TRY(MATCH_MP_TAC CONTINUOUS_ON_SUBSET) THEN ASM SET_TAC[]);;
13091
13092 let HOMEOMORPHISM_ID = prove
13093  (`!s:real^N->bool. homeomorphism (s,s) ((\x. x),(\x. x))`,
13094   REWRITE_TAC[homeomorphism; IMAGE_ID; CONTINUOUS_ON_ID]);;
13095
13096 let HOMEOMORPHISM_I = prove
13097  (`!s:real^N->bool. homeomorphism (s,s) (I,I)`,
13098   REWRITE_TAC[I_DEF; HOMEOMORPHISM_ID]);;
13099
13100 let HOMEOMORPHIC_REFL = prove
13101  (`!s:real^N->bool. s homeomorphic s`,
13102   REWRITE_TAC[homeomorphic] THEN MESON_TAC[HOMEOMORPHISM_I]);;
13103
13104 let HOMEOMORPHISM_SYM = prove
13105  (`!f:real^M->real^N g s t.
13106         homeomorphism (s,t) (f,g) <=> homeomorphism (t,s) (g,f)`,
13107   REWRITE_TAC[homeomorphism] THEN MESON_TAC[]);;
13108
13109 let HOMEOMORPHIC_SYM = prove
13110  (`!s t. s homeomorphic t <=> t homeomorphic s`,
13111   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; homeomorphism] THEN
13112   GEN_REWRITE_TAC RAND_CONV [SWAP_EXISTS_THM] THEN
13113   REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN CONV_TAC TAUT);;
13114
13115 let HOMEOMORPHISM_COMPOSE = prove
13116  (`!f:real^M->real^N g h:real^N->real^P k s t u.
13117         homeomorphism (s,t) (f,g) /\ homeomorphism (t,u) (h,k)
13118         ==> homeomorphism (s,u) (h o f,g o k)`,
13119   SIMP_TAC[homeomorphism; CONTINUOUS_ON_COMPOSE; IMAGE_o; o_THM] THEN
13120   SET_TAC[]);;
13121
13122 let HOMEOMORPHIC_TRANS = prove
13123  (`!s:real^M->bool t:real^N->bool u:real^P->bool.
13124         s homeomorphic t /\ t homeomorphic u ==> s homeomorphic u`,
13125   REWRITE_TAC[homeomorphic] THEN MESON_TAC[HOMEOMORPHISM_COMPOSE]);;
13126
13127 let HOMEOMORPHIC_IMP_CARD_EQ = prove
13128  (`!s:real^M->bool t:real^N->bool. s homeomorphic t ==> s =_c t`,
13129   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; homeomorphism; eq_c] THEN
13130   MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]);;
13131
13132 let HOMEOMORPHIC_EMPTY = prove
13133  (`(!s. (s:real^N->bool) homeomorphic ({}:real^M->bool) <=> s = {}) /\
13134    (!s. ({}:real^M->bool) homeomorphic (s:real^N->bool) <=> s = {})`,
13135   REWRITE_TAC[homeomorphic; homeomorphism; IMAGE_CLAUSES; IMAGE_EQ_EMPTY] THEN
13136   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
13137   ASM_REWRITE_TAC[continuous_on; NOT_IN_EMPTY]);;
13138
13139 let HOMEOMORPHIC_MINIMAL = prove
13140  (`!s t. s homeomorphic t <=>
13141             ?f g. (!x. x IN s ==> f(x) IN t /\ (g(f(x)) = x)) /\
13142                   (!y. y IN t ==> g(y) IN s /\ (f(g(y)) = y)) /\
13143                   f continuous_on s /\ g continuous_on t`,
13144   REWRITE_TAC[homeomorphic; homeomorphism; EXTENSION; IN_IMAGE] THEN
13145   REPEAT GEN_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN MESON_TAC[]);;
13146
13147 let HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_SELF = prove
13148  (`!f:real^M->real^N s.
13149         linear f /\ (!x y. f x = f y ==> x = y)
13150         ==> (IMAGE f s) homeomorphic s`,
13151   REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
13152   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_LEFT_INVERSE]) THEN
13153   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN DISCH_TAC THEN
13154   EXISTS_TAC `f:real^M->real^N` THEN
13155   ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON; FORALL_IN_IMAGE; FUN_IN_IMAGE] THEN
13156   ASM_SIMP_TAC[continuous_on; IMP_CONJ; FORALL_IN_IMAGE] THEN
13157   X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
13158   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
13159   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_BOUNDED_BELOW_POS) THEN
13160   ASM_REWRITE_TAC[] THEN
13161   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
13162   EXISTS_TAC `e * B:real` THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
13163   X_GEN_TAC `y:real^M` THEN ASM_SIMP_TAC[dist; GSYM LINEAR_SUB] THEN
13164   DISCH_TAC THEN ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ] THEN
13165   MATCH_MP_TAC(REAL_ARITH `a <= b ==> b < x ==> a < x`) THEN
13166   ASM_SIMP_TAC[REAL_LE_RDIV_EQ]);;
13167
13168 let HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_LEFT_EQ = prove
13169  (`!f:real^M->real^N s t.
13170         linear f /\ (!x y. f x = f y ==> x = y)
13171         ==> ((IMAGE f s) homeomorphic t <=> s homeomorphic t)`,
13172   REPEAT GEN_TAC THEN DISCH_THEN(ASSUME_TAC o SPEC `s:real^M->bool` o
13173     MATCH_MP HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_SELF) THEN
13174   EQ_TAC THENL
13175    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [HOMEOMORPHIC_SYM]);
13176     POP_ASSUM MP_TAC] THEN
13177   REWRITE_TAC[IMP_IMP; HOMEOMORPHIC_TRANS]);;
13178
13179 let HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_RIGHT_EQ = prove
13180  (`!f:real^M->real^N s t.
13181         linear f /\ (!x y. f x = f y ==> x = y)
13182         ==> (s homeomorphic (IMAGE f t) <=> s homeomorphic t)`,
13183   ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
13184   REWRITE_TAC[HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_LEFT_EQ]);;
13185
13186 add_linear_invariants
13187   [HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_LEFT_EQ;
13188    HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_RIGHT_EQ];;
13189
13190 let HOMEOMORPHIC_TRANSLATION_SELF = prove
13191  (`!a:real^N s. (IMAGE (\x. a + x) s) homeomorphic s`,
13192   REPEAT GEN_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
13193   EXISTS_TAC `\x:real^N. x - a` THEN
13194   EXISTS_TAC `\x:real^N. a + x` THEN
13195   SIMP_TAC[FORALL_IN_IMAGE; CONTINUOUS_ON_SUB; CONTINUOUS_ON_ID;
13196            CONTINUOUS_ON_CONST; CONTINUOUS_ON_ADD; VECTOR_ADD_SUB] THEN
13197   REWRITE_TAC[IN_IMAGE] THEN MESON_TAC[]);;
13198
13199 let HOMEOMORPHIC_TRANSLATION_LEFT_EQ = prove
13200  (`!a:real^N s t.
13201       (IMAGE (\x. a + x) s) homeomorphic t <=> s homeomorphic t`,
13202   MESON_TAC[HOMEOMORPHIC_TRANSLATION_SELF;
13203             HOMEOMORPHIC_SYM; HOMEOMORPHIC_TRANS]);;
13204
13205 let HOMEOMORPHIC_TRANSLATION_RIGHT_EQ = prove
13206  (`!a:real^N s t.
13207       s homeomorphic (IMAGE (\x. a + x) t) <=> s homeomorphic t`,
13208   ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
13209   REWRITE_TAC[HOMEOMORPHIC_TRANSLATION_LEFT_EQ]);;
13210
13211 add_translation_invariants
13212   [HOMEOMORPHIC_TRANSLATION_LEFT_EQ;
13213    HOMEOMORPHIC_TRANSLATION_RIGHT_EQ];;
13214
13215 let HOMEOMORPHISM_IMP_QUOTIENT_MAP = prove
13216  (`!f:real^M->real^N g s t.
13217     homeomorphism (s,t) (f,g)
13218     ==> !u. u SUBSET t
13219             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
13220                  open_in (subtopology euclidean t) u)`,
13221   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphism] THEN
13222   STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_RIGHT_INVERSE_IMP_QUOTIENT_MAP THEN
13223   EXISTS_TAC `g:real^N->real^M` THEN ASM_REWRITE_TAC[SUBSET_REFL]);;
13224
13225 let HOMEOMORPHIC_PCROSS = prove
13226  (`!s:real^M->bool t:real^N->bool s':real^P->bool t':real^Q->bool.
13227         s homeomorphic s' /\ t homeomorphic t'
13228         ==> (s PCROSS t) homeomorphic (s' PCROSS t')`,
13229   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
13230   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
13231   DISCH_THEN(CONJUNCTS_THEN2
13232    (X_CHOOSE_THEN `f:real^M->real^P`
13233      (X_CHOOSE_THEN `f':real^P->real^M` STRIP_ASSUME_TAC))
13234    (X_CHOOSE_THEN `g:real^N->real^Q`
13235      (X_CHOOSE_THEN `g':real^Q->real^N` STRIP_ASSUME_TAC))) THEN
13236   MAP_EVERY EXISTS_TAC
13237    [`(\z. pastecart (f(fstcart z)) (g(sndcart z)))
13238      :real^(M,N)finite_sum->real^(P,Q)finite_sum`;
13239     `(\z. pastecart (f'(fstcart z)) (g'(sndcart z)))
13240      :real^(P,Q)finite_sum->real^(M,N)finite_sum`] THEN
13241   ASM_SIMP_TAC[FORALL_IN_PCROSS; FSTCART_PASTECART; SNDCART_PASTECART;
13242                SUBSET; FORALL_IN_IMAGE; PASTECART_IN_PCROSS] THEN
13243   CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN
13244   CONJ_TAC THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN
13245   MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
13246   SIMP_TAC[LINEAR_FSTCART; LINEAR_SNDCART; LINEAR_CONTINUOUS_ON] THEN
13247   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
13248           CONTINUOUS_ON_SUBSET)) THEN
13249   REWRITE_TAC[FORALL_IN_IMAGE; FORALL_IN_PCROSS; SUBSET] THEN
13250   SIMP_TAC[FSTCART_PASTECART; SNDCART_PASTECART]);;
13251
13252 let HOMEOMORPHIC_PCROSS_SYM = prove
13253  (`!s:real^M->bool t:real^N->bool. (s PCROSS t) homeomorphic (t PCROSS s)`,
13254   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; homeomorphism] THEN
13255   EXISTS_TAC `(\z. pastecart (sndcart z) (fstcart z))
13256               :real^(M,N)finite_sum->real^(N,M)finite_sum` THEN
13257   EXISTS_TAC `(\z. pastecart (sndcart z) (fstcart z))
13258               :real^(N,M)finite_sum->real^(M,N)finite_sum` THEN
13259   REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; SUBSET; FORALL_IN_IMAGE] THEN
13260   SIMP_TAC[CONTINUOUS_ON_PASTECART; LINEAR_CONTINUOUS_ON;
13261            LINEAR_FSTCART; LINEAR_SNDCART] THEN
13262   REWRITE_TAC[FORALL_IN_PCROSS; FSTCART_PASTECART; SNDCART_PASTECART;
13263     IN_IMAGE; EXISTS_PASTECART; PASTECART_INJ; PASTECART_IN_PCROSS] THEN
13264   MESON_TAC[]);;
13265
13266 let HOMEOMORPHIC_PCROSS_ASSOC = prove
13267  (`!s:real^M->bool t:real^N->bool u:real^P->bool.
13268         (s PCROSS (t PCROSS u)) homeomorphic ((s PCROSS t) PCROSS u)`,
13269   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
13270   MAP_EVERY EXISTS_TAC
13271    [`\z:real^(M,(N,P)finite_sum)finite_sum.
13272         pastecart (pastecart (fstcart z) (fstcart(sndcart z)))
13273                   (sndcart(sndcart z))`;
13274     `\z:real^((M,N)finite_sum,P)finite_sum.
13275         pastecart (fstcart(fstcart z))
13276                   (pastecart (sndcart(fstcart z)) (sndcart z))`] THEN
13277   REWRITE_TAC[FORALL_IN_PCROSS; SUBSET; FORALL_IN_IMAGE;
13278               RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
13279   SIMP_TAC[FSTCART_PASTECART; SNDCART_PASTECART; PASTECART_IN_PCROSS] THEN
13280   CONJ_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
13281   REPEAT(MATCH_MP_TAC LINEAR_PASTECART THEN CONJ_TAC) THEN
13282   TRY(GEN_REWRITE_TAC RAND_CONV [GSYM o_DEF] THEN
13283       MATCH_MP_TAC LINEAR_COMPOSE) THEN
13284   REWRITE_TAC[LINEAR_FSTCART; LINEAR_SNDCART]);;
13285
13286 let HOMEOMORPHIC_SCALING_LEFT = prove
13287  (`!c. &0 < c
13288        ==> !s t. (IMAGE (\x. c % x) s) homeomorphic t <=> s homeomorphic t`,
13289   REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN
13290   MATCH_MP_TAC HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_LEFT_EQ THEN
13291   ASM_SIMP_TAC[VECTOR_MUL_LCANCEL; REAL_LT_IMP_NZ; LINEAR_SCALING]);;
13292
13293 let HOMEOMORPHIC_SCALING_RIGHT = prove
13294  (`!c. &0 < c
13295        ==> !s t. s homeomorphic (IMAGE (\x. c % x) t) <=> s homeomorphic t`,
13296   REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN
13297   MATCH_MP_TAC HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_RIGHT_EQ THEN
13298   ASM_SIMP_TAC[VECTOR_MUL_LCANCEL; REAL_LT_IMP_NZ; LINEAR_SCALING]);;
13299
13300 let HOMEOMORPHIC_SUBSPACES = prove
13301  (`!s:real^M->bool t:real^N->bool.
13302         subspace s /\ subspace t /\ dim s = dim t ==> s homeomorphic t`,
13303   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
13304   DISCH_THEN(MP_TAC o MATCH_MP ISOMETRIES_SUBSPACES) THEN
13305   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^M->real^N` THEN
13306   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^M` THEN
13307   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_CBALL_0] THEN
13308   SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN ASM SET_TAC[]);;
13309
13310 let HOMEOMORPHIC_FINITE = prove
13311  (`!s:real^M->bool t:real^N->bool.
13312         FINITE s /\ FINITE t ==> (s homeomorphic t <=> CARD s = CARD t)`,
13313   REPEAT STRIP_TAC THEN EQ_TAC THENL
13314    [DISCH_THEN(MP_TAC o MATCH_MP HOMEOMORPHIC_IMP_CARD_EQ) THEN
13315     ASM_SIMP_TAC[CARD_EQ_CARD];
13316     STRIP_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
13317     MP_TAC(ISPECL [`s:real^M->bool`; `t:real^N->bool`]
13318         CARD_EQ_BIJECTIONS) THEN
13319     ASM_REWRITE_TAC[] THEN
13320     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
13321     ASM_SIMP_TAC[CONTINUOUS_ON_FINITE] THEN ASM SET_TAC[]]);;
13322
13323 let HOMEOMORPHIC_FINITE_STRONG = prove
13324  (`!s:real^M->bool t:real^N->bool.
13325         FINITE s \/ FINITE t
13326         ==> (s homeomorphic t <=> FINITE s /\ FINITE t /\ CARD s = CARD t)`,
13327   REPEAT GEN_TAC THEN DISCH_TAC THEN EQ_TAC THEN
13328   SIMP_TAC[HOMEOMORPHIC_FINITE] THEN DISCH_TAC THEN
13329   FIRST_ASSUM(MP_TAC o MATCH_MP CARD_FINITE_CONG o MATCH_MP
13330     HOMEOMORPHIC_IMP_CARD_EQ) THEN
13331   FIRST_X_ASSUM DISJ_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
13332   ASM_MESON_TAC[HOMEOMORPHIC_FINITE]);;
13333
13334 let HOMEOMORPHIC_SING = prove
13335  (`!a:real^M b:real^N. {a} homeomorphic {b}`,
13336   SIMP_TAC[HOMEOMORPHIC_FINITE; FINITE_SING; CARD_SING]);;
13337
13338 let HOMEOMORPHIC_PCROSS_SING = prove
13339  (`(!s:real^M->bool a:real^N. s homeomorphic (s PCROSS {a})) /\
13340    (!s:real^M->bool a:real^N. s homeomorphic ({a} PCROSS s))`,
13341   MATCH_MP_TAC(TAUT `(p ==> q) /\ p ==> p /\ q`) THEN CONJ_TAC THENL
13342    [MESON_TAC[HOMEOMORPHIC_PCROSS_SYM; HOMEOMORPHIC_TRANS]; ALL_TAC] THEN
13343   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
13344   EXISTS_TAC `\x. (pastecart x a:real^(M,N)finite_sum)` THEN
13345   EXISTS_TAC `fstcart:real^(M,N)finite_sum->real^M` THEN
13346   SIMP_TAC[CONTINUOUS_ON_PASTECART; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN
13347   SIMP_TAC[LINEAR_FSTCART; LINEAR_CONTINUOUS_ON; SUBSET; FORALL_IN_IMAGE] THEN
13348   REWRITE_TAC[FORALL_IN_PCROSS; PASTECART_IN_PCROSS; IN_SING] THEN
13349   SIMP_TAC[FSTCART_PASTECART]);;
13350
13351 (* ------------------------------------------------------------------------- *)
13352 (* Inverse function property for open/closed maps.                           *)
13353 (* ------------------------------------------------------------------------- *)
13354
13355 let CONTINUOUS_ON_INVERSE_OPEN_MAP = prove
13356  (`!f:real^M->real^N g s t.
13357         f continuous_on s /\ IMAGE f s = t /\ (!x. x IN s ==> g(f x) = x) /\
13358         (!u. open_in (subtopology euclidean s) u
13359              ==> open_in (subtopology euclidean t) (IMAGE f u))
13360         ==> g continuous_on t`,
13361   REPEAT STRIP_TAC THEN
13362   MP_TAC(ISPECL [`g:real^N->real^M`; `t:real^N->bool`; `s:real^M->bool`]
13363         CONTINUOUS_ON_OPEN_GEN) THEN
13364   ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN SUBST1_TAC] THEN
13365   X_GEN_TAC `u:real^M->bool` THEN DISCH_TAC THEN
13366   FIRST_X_ASSUM(MP_TAC o SPEC `u:real^M->bool`) THEN ASM_REWRITE_TAC[] THEN
13367   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
13368   FIRST_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN
13369   ASM SET_TAC[]);;
13370
13371 let CONTINUOUS_ON_INVERSE_CLOSED_MAP = prove
13372  (`!f:real^M->real^N g s t.
13373         f continuous_on s /\ IMAGE f s = t /\ (!x. x IN s ==> g(f x) = x) /\
13374         (!u. closed_in (subtopology euclidean s) u
13375              ==> closed_in (subtopology euclidean t) (IMAGE f u))
13376         ==> g continuous_on t`,
13377   REPEAT STRIP_TAC THEN
13378   MP_TAC(ISPECL [`g:real^N->real^M`; `t:real^N->bool`; `s:real^M->bool`]
13379         CONTINUOUS_ON_CLOSED_GEN) THEN
13380   ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN SUBST1_TAC] THEN
13381   X_GEN_TAC `u:real^M->bool` THEN DISCH_TAC THEN
13382   FIRST_X_ASSUM(MP_TAC o SPEC `u:real^M->bool`) THEN ASM_REWRITE_TAC[] THEN
13383   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
13384   FIRST_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [closed_in]) THEN
13385   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN ASM SET_TAC[]);;
13386
13387 let HOMEOMORPHISM_INJECTIVE_OPEN_MAP = prove
13388  (`!f:real^M->real^N s t.
13389         f continuous_on s /\ IMAGE f s = t /\
13390         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) /\
13391         (!u. open_in (subtopology euclidean s) u
13392              ==> open_in (subtopology euclidean t) (IMAGE f u))
13393         ==> ?g. homeomorphism (s,t) (f,g)`,
13394   REPEAT STRIP_TAC THEN
13395   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
13396   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^M` THEN
13397   DISCH_TAC THEN ASM_SIMP_TAC[homeomorphism] THEN
13398   REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
13399   MATCH_MP_TAC CONTINUOUS_ON_INVERSE_OPEN_MAP THEN ASM_MESON_TAC[]);;
13400
13401 let HOMEOMORPHISM_INJECTIVE_CLOSED_MAP = prove
13402  (`!f:real^M->real^N s t.
13403         f continuous_on s /\ IMAGE f s = t /\
13404         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) /\
13405         (!u. closed_in (subtopology euclidean s) u
13406              ==> closed_in (subtopology euclidean t) (IMAGE f u))
13407         ==> ?g. homeomorphism (s,t) (f,g)`,
13408   REPEAT STRIP_TAC THEN
13409   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
13410   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^M` THEN
13411   DISCH_TAC THEN ASM_SIMP_TAC[homeomorphism] THEN
13412   REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
13413   MATCH_MP_TAC CONTINUOUS_ON_INVERSE_CLOSED_MAP THEN ASM_MESON_TAC[]);;
13414
13415 let HOMEOMORPHISM_IMP_OPEN_MAP = prove
13416  (`!f:real^M->real^N g s t u.
13417         homeomorphism (s,t) (f,g) /\ open_in (subtopology euclidean s) u
13418         ==> open_in (subtopology euclidean t) (IMAGE f u)`,
13419   REWRITE_TAC[homeomorphism] THEN REPEAT STRIP_TAC THEN
13420   SUBGOAL_THEN `IMAGE (f:real^M->real^N) u =
13421                  {y | y IN t /\ g(y) IN u}`
13422   SUBST1_TAC THENL
13423    [FIRST_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN
13424     ASM SET_TAC[];
13425     MATCH_MP_TAC CONTINUOUS_ON_IMP_OPEN_IN THEN ASM_REWRITE_TAC[]]);;
13426
13427 let HOMEOMORPHISM_IMP_CLOSED_MAP = prove
13428  (`!f:real^M->real^N g s t u.
13429         homeomorphism (s,t) (f,g) /\ closed_in (subtopology euclidean s) u
13430         ==> closed_in (subtopology euclidean t) (IMAGE f u)`,
13431   REWRITE_TAC[homeomorphism] THEN REPEAT STRIP_TAC THEN
13432   SUBGOAL_THEN `IMAGE (f:real^M->real^N) u =
13433                  {y | y IN t /\ g(y) IN u}`
13434   SUBST1_TAC THENL
13435    [FIRST_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [closed_in]) THEN
13436     REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN ASM SET_TAC[];
13437     MATCH_MP_TAC CONTINUOUS_ON_IMP_CLOSED_IN THEN ASM_REWRITE_TAC[]]);;
13438
13439 let HOMEOMORPHISM_INJECTIVE_OPEN_MAP_EQ = prove
13440  (`!f:real^M->real^N s t.
13441         f continuous_on s /\ IMAGE f s = t /\
13442         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
13443         ==> ((?g. homeomorphism (s,t) (f,g)) <=>
13444              !u. open_in (subtopology euclidean s) u
13445                  ==> open_in (subtopology euclidean t) (IMAGE f u))`,
13446   REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL
13447    [MATCH_MP_TAC HOMEOMORPHISM_IMP_OPEN_MAP THEN ASM_MESON_TAC[];
13448     MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP THEN
13449     ASM_REWRITE_TAC[]]);;
13450
13451 let HOMEOMORPHISM_INJECTIVE_CLOSED_MAP_EQ = prove
13452  (`!f:real^M->real^N s t.
13453         f continuous_on s /\ IMAGE f s = t /\
13454         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
13455         ==> ((?g. homeomorphism (s,t) (f,g)) <=>
13456              !u. closed_in (subtopology euclidean s) u
13457                  ==> closed_in (subtopology euclidean t) (IMAGE f u))`,
13458   REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL
13459    [MATCH_MP_TAC HOMEOMORPHISM_IMP_CLOSED_MAP THEN ASM_MESON_TAC[];
13460     MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_CLOSED_MAP THEN
13461     ASM_REWRITE_TAC[]]);;
13462
13463 let INJECTIVE_MAP_OPEN_IFF_CLOSED = prove
13464  (`!f:real^M->real^N s t.
13465         f continuous_on s /\ IMAGE f s = t /\
13466         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
13467         ==> ((!u. open_in (subtopology euclidean s) u
13468                   ==> open_in (subtopology euclidean t) (IMAGE f u)) <=>
13469              (!u. closed_in (subtopology euclidean s) u
13470                   ==> closed_in (subtopology euclidean t) (IMAGE f u)))`,
13471   REPEAT STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
13472   EXISTS_TAC `?g:real^N->real^M. homeomorphism (s,t) (f,g)` THEN
13473   CONJ_TAC THENL
13474    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP_EQ;
13475     MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_CLOSED_MAP_EQ] THEN
13476   ASM_REWRITE_TAC[]);;
13477
13478 (* ------------------------------------------------------------------------- *)
13479 (* Relatively weak hypotheses if the domain of the function is compact.      *)
13480 (* ------------------------------------------------------------------------- *)
13481
13482 let CONTINUOUS_IMP_CLOSED_MAP = prove
13483  (`!f:real^M->real^N s t.
13484         f continuous_on s /\ IMAGE f s = t /\ compact s
13485         ==> !u. closed_in (subtopology euclidean s) u
13486                 ==> closed_in (subtopology euclidean t) (IMAGE f u)`,
13487   SIMP_TAC[CLOSED_IN_CLOSED_EQ; COMPACT_IMP_CLOSED] THEN
13488   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSED_SUBSET THEN
13489   EXPAND_TAC "t" THEN ASM_SIMP_TAC[IMAGE_SUBSET] THEN
13490   MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
13491   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
13492   ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_IN_CLOSED_TRANS;
13493                 BOUNDED_SUBSET; CONTINUOUS_ON_SUBSET]);;
13494
13495 let CONTINUOUS_IMP_QUOTIENT_MAP = prove
13496  (`!f:real^M->real^N s t.
13497         f continuous_on s /\ IMAGE f s = t /\ compact s
13498         ==> !u. u SUBSET t
13499                 ==> (open_in (subtopology euclidean s)
13500                              {x | x IN s /\ f x IN u} <=>
13501                      open_in (subtopology euclidean t) u)`,
13502   REPEAT GEN_TAC THEN STRIP_TAC THEN FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN
13503   MATCH_MP_TAC CLOSED_MAP_IMP_QUOTIENT_MAP THEN
13504   ASM_REWRITE_TAC[] THEN
13505   MATCH_MP_TAC CONTINUOUS_IMP_CLOSED_MAP THEN
13506   ASM_REWRITE_TAC[]);;
13507
13508 let CONTINUOUS_ON_INVERSE = prove
13509  (`!f:real^M->real^N g s.
13510         f continuous_on s /\ compact s /\ (!x. x IN s ==> (g(f(x)) = x))
13511         ==> g continuous_on (IMAGE f s)`,
13512   REPEAT STRIP_TAC THEN REWRITE_TAC[CONTINUOUS_ON_CLOSED] THEN
13513   SUBGOAL_THEN `IMAGE g (IMAGE (f:real^M->real^N) s) = s` SUBST1_TAC THENL
13514    [REWRITE_TAC[EXTENSION; IN_IMAGE] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
13515   X_GEN_TAC `t:real^M->bool` THEN DISCH_TAC THEN
13516   REWRITE_TAC[CLOSED_IN_CLOSED] THEN
13517   EXISTS_TAC `IMAGE (f:real^M->real^N) t` THEN CONJ_TAC THENL
13518    [MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
13519     MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
13520     FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET) THEN
13521     REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
13522     ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_IN_CLOSED_TRANS;
13523                   BOUNDED_SUBSET; CONTINUOUS_ON_SUBSET];
13524     REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM; IN_IMAGE] THEN
13525     ASM_MESON_TAC[CLOSED_IN_SUBSET; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY; SUBSET]]);;
13526
13527 let HOMEOMORPHISM_COMPACT = prove
13528  (`!s f t. compact s /\ f continuous_on s /\ (IMAGE f s = t) /\
13529            (!x y. x IN s /\ y IN s /\ (f x = f y) ==> (x = y))
13530            ==> ?g. homeomorphism(s,t) (f,g)`,
13531   REWRITE_TAC[INJECTIVE_ON_LEFT_INVERSE] THEN REPEAT GEN_TAC THEN
13532   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
13533   MATCH_MP_TAC MONO_EXISTS THEN ASM_SIMP_TAC[EXTENSION; homeomorphism] THEN
13534   FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN
13535   ASM_MESON_TAC[CONTINUOUS_ON_INVERSE; IN_IMAGE]);;
13536
13537 let HOMEOMORPHIC_COMPACT = prove
13538  (`!s f t. compact s /\ f continuous_on s /\ (IMAGE f s = t) /\
13539            (!x y. x IN s /\ y IN s /\ (f x = f y) ==> (x = y))
13540            ==> s homeomorphic t`,
13541   REWRITE_TAC[homeomorphic] THEN MESON_TAC[HOMEOMORPHISM_COMPACT]);;
13542
13543 (* ------------------------------------------------------------------------- *)
13544 (* Lemmas about composition of homeomorphisms.                               *)
13545 (* ------------------------------------------------------------------------- *)
13546
13547 let HOMEOMORPHISM_FROM_COMPOSITION_SURJECTIVE = prove
13548  (`!f:real^M->real^N g:real^N->real^P s t u.
13549         f continuous_on s /\ IMAGE f s = t /\
13550         g continuous_on t /\ IMAGE g t SUBSET u /\
13551         (?h. homeomorphism (s,u) (g o f,h))
13552         ==> (?f'. homeomorphism (s,t) (f,f')) /\
13553             (?g'. homeomorphism (t,u) (g,g'))`,
13554   REPEAT GEN_TAC THEN STRIP_TAC THEN
13555   RULE_ASSUM_TAC(REWRITE_RULE[homeomorphism; o_THM]) THEN
13556   MATCH_MP_TAC(TAUT `q /\ (q ==> p) ==> p /\ q`) THEN CONJ_TAC THENL
13557    [MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP THEN
13558     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
13559     MATCH_MP_TAC OPEN_MAP_FROM_COMPOSITION_SURJECTIVE THEN
13560     MAP_EVERY EXISTS_TAC [`f:real^M->real^N`; `s:real^M->bool`] THEN
13561     ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
13562     MATCH_MP_TAC HOMEOMORPHISM_IMP_OPEN_MAP THEN
13563     MAP_EVERY EXISTS_TAC [`h:real^P->real^M`; `s:real^M->bool`] THEN
13564     ASM_REWRITE_TAC[homeomorphism; o_THM];
13565     REWRITE_TAC[homeomorphism; o_THM] THEN
13566     DISCH_THEN(X_CHOOSE_THEN `g':real^P->real^N` STRIP_ASSUME_TAC) THEN
13567     EXISTS_TAC `(h:real^P->real^M) o (g:real^N->real^P)` THEN
13568     ASM_SIMP_TAC[o_THM; IMAGE_o] THEN
13569     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
13570     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
13571     ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]]);;
13572
13573 let HOMEOMORPHISM_FROM_COMPOSITION_INJECTIVE = prove
13574  (`!f:real^M->real^N g:real^N->real^P s t u.
13575         f continuous_on s /\ IMAGE f s SUBSET t /\
13576         g continuous_on t /\ IMAGE g t SUBSET u /\
13577         (!x y. x IN t /\ y IN t /\ g x = g y ==> x = y) /\
13578         (?h. homeomorphism (s,u) (g o f,h))
13579         ==> (?f'. homeomorphism (s,t) (f,f')) /\
13580             (?g'. homeomorphism (t,u) (g,g'))`,
13581   REPEAT GEN_TAC THEN STRIP_TAC THEN
13582   RULE_ASSUM_TAC(REWRITE_RULE[homeomorphism; o_THM]) THEN
13583   MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
13584    [MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP THEN
13585     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
13586     MATCH_MP_TAC OPEN_MAP_FROM_COMPOSITION_INJECTIVE THEN
13587     MAP_EVERY EXISTS_TAC [`g:real^N->real^P`; `u:real^P->bool`] THEN
13588     ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
13589     MATCH_MP_TAC HOMEOMORPHISM_IMP_OPEN_MAP THEN
13590     MAP_EVERY EXISTS_TAC [`h:real^P->real^M`; `s:real^M->bool`] THEN
13591     ASM_REWRITE_TAC[homeomorphism; o_THM];
13592     REWRITE_TAC[homeomorphism; o_THM] THEN
13593     DISCH_THEN(X_CHOOSE_THEN `f':real^N->real^M` STRIP_ASSUME_TAC) THEN
13594     EXISTS_TAC `(f:real^M->real^N) o (h:real^P->real^M)` THEN
13595     ASM_SIMP_TAC[o_THM; IMAGE_o] THEN
13596     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
13597     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
13598     ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]]);;
13599
13600 (* ------------------------------------------------------------------------- *)
13601 (* Preservation of topological properties.                                   *)
13602 (* ------------------------------------------------------------------------- *)
13603
13604 let HOMEOMORPHIC_COMPACTNESS = prove
13605  (`!s t. s homeomorphic t ==> (compact s <=> compact t)`,
13606   REWRITE_TAC[homeomorphic; homeomorphism] THEN
13607   MESON_TAC[COMPACT_CONTINUOUS_IMAGE]);;
13608
13609 let HOMEOMORPHIC_CONNECTEDNESS = prove
13610  (`!s t. s homeomorphic t ==> (connected s <=> connected t)`,
13611   REWRITE_TAC[homeomorphic; homeomorphism] THEN
13612   MESON_TAC[CONNECTED_CONTINUOUS_IMAGE]);;
13613
13614 (* ------------------------------------------------------------------------- *)
13615 (* Results on translation, scaling etc.                                      *)
13616 (* ------------------------------------------------------------------------- *)
13617
13618 let HOMEOMORPHIC_SCALING = prove
13619  (`!s:real^N->bool c. ~(c = &0) ==> s homeomorphic (IMAGE (\x. c % x) s)`,
13620   REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
13621   MAP_EVERY EXISTS_TAC [`\x:real^N. c % x`; `\x:real^N. inv(c) % x`] THEN
13622   ASM_SIMP_TAC[CONTINUOUS_ON_CMUL; CONTINUOUS_ON_ID; FORALL_IN_IMAGE] THEN
13623   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_MUL_RINV] THEN
13624   SIMP_TAC[VECTOR_MUL_LID; IN_IMAGE; REAL_MUL_LID] THEN MESON_TAC[]);;
13625
13626 let HOMEOMORPHIC_TRANSLATION = prove
13627  (`!s a:real^N. s homeomorphic (IMAGE (\x. a + x) s)`,
13628   REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
13629   MAP_EVERY EXISTS_TAC [`\x:real^N. a +  x`; `\x:real^N. --a + x`] THEN
13630   ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN
13631   SIMP_TAC[VECTOR_ADD_ASSOC; VECTOR_ADD_LINV; VECTOR_ADD_RINV;
13632            FORALL_IN_IMAGE; VECTOR_ADD_LID] THEN
13633   REWRITE_TAC[IN_IMAGE] THEN MESON_TAC[]);;
13634
13635 let HOMEOMORPHIC_AFFINITY = prove
13636  (`!s a:real^N c. ~(c = &0) ==> s homeomorphic (IMAGE (\x. a + c % x) s)`,
13637   REPEAT STRIP_TAC THEN
13638   MATCH_MP_TAC HOMEOMORPHIC_TRANS THEN
13639   EXISTS_TAC `IMAGE (\x:real^N. c % x) s` THEN
13640   ASM_SIMP_TAC[HOMEOMORPHIC_SCALING] THEN
13641   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
13642   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
13643   REWRITE_TAC[IMAGE_o; HOMEOMORPHIC_TRANSLATION]);;
13644
13645 let [HOMEOMORPHIC_BALLS; HOMEOMORPHIC_CBALLS; HOMEOMORPHIC_SPHERES] =
13646   (CONJUNCTS o prove)
13647  (`(!a:real^N b:real^N d e.
13648       &0 < d /\ &0 < e ==> ball(a,d) homeomorphic ball(b,e)) /\
13649    (!a:real^N b:real^N d e.
13650       &0 < d /\ &0 < e ==> cball(a,d) homeomorphic cball(b,e)) /\
13651    (!a:real^N b:real^N d e.
13652       &0 < d /\ &0 < e ==> sphere(a,d) homeomorphic sphere(b,e))`,
13653   REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
13654   EXISTS_TAC `\x:real^N. b + (e / d) % (x - a)` THEN
13655   EXISTS_TAC `\x:real^N. a + (d / e) % (x - b)` THEN
13656   ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_SUB; CONTINUOUS_ON_CMUL;
13657     CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID; IN_BALL; IN_CBALL; IN_SPHERE] THEN
13658   REWRITE_TAC[dist; VECTOR_ARITH `a - (a + b) = --b:real^N`; NORM_NEG] THEN
13659   REWRITE_TAC[real_div; VECTOR_ARITH
13660    `a + d % ((b + e % (x - a)) - b) = (&1 - d * e) % a + (d * e) % x`] THEN
13661   ONCE_REWRITE_TAC[REAL_ARITH
13662     `(e * d') * (d * e') = (d * d') * (e * e')`] THEN
13663   ASM_SIMP_TAC[REAL_MUL_RINV; REAL_LT_IMP_NZ; REAL_MUL_LID; REAL_SUB_REFL] THEN
13664   REWRITE_TAC[NORM_MUL; VECTOR_MUL_LZERO; VECTOR_MUL_LID; VECTOR_ADD_LID] THEN
13665   ASM_SIMP_TAC[REAL_ABS_MUL; REAL_ABS_INV; REAL_ARITH
13666    `&0 < x ==> (abs x = x)`] THEN
13667   GEN_REWRITE_TAC(BINOP_CONV o BINDER_CONV o funpow 2 RAND_CONV)
13668         [GSYM REAL_MUL_RID] THEN
13669   ONCE_REWRITE_TAC[AC REAL_MUL_AC `(a * b) * c = (a * c) * b`] THEN
13670   ASM_SIMP_TAC[REAL_LE_LMUL_EQ; GSYM real_div; REAL_LE_LDIV_EQ; REAL_MUL_LID;
13671     GSYM REAL_MUL_ASSOC; REAL_LT_LMUL_EQ; REAL_LT_LDIV_EQ; NORM_SUB] THEN
13672   ASM_SIMP_TAC[REAL_DIV_REFL; REAL_LT_IMP_NZ; REAL_MUL_RID]);;
13673
13674 (* ------------------------------------------------------------------------- *)
13675 (* Homeomorphism of one-point compactifications.                             *)
13676 (* ------------------------------------------------------------------------- *)
13677
13678 let HOMEOMORPHIC_ONE_POINT_COMPACTIFICATIONS = prove
13679  (`!s:real^M->bool t:real^N->bool a b.
13680         compact s /\ compact t /\ a IN s /\ b IN t /\
13681         (s DELETE a) homeomorphic (t DELETE b)
13682         ==> s homeomorphic t`,
13683   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHIC_COMPACT THEN
13684   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [homeomorphic]) THEN
13685   REWRITE_TAC[HOMEOMORPHISM; LEFT_IMP_EXISTS_THM] THEN
13686   MAP_EVERY X_GEN_TAC [`f:real^M->real^N`; `g:real^N->real^M`] THEN
13687   STRIP_TAC THEN
13688   EXISTS_TAC `\x. if x = a then b else (f:real^M->real^N) x` THEN
13689   ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
13690   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
13691   X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
13692   ASM_CASES_TAC `x:real^M = a` THEN ASM_REWRITE_TAC[] THENL
13693    [REWRITE_TAC[continuous_within] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
13694     MP_TAC(ISPECL [`b:real^N`; `e:real`] CENTRE_IN_BALL) THEN
13695     ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
13696     SUBGOAL_THEN
13697       `closed_in (subtopology euclidean s)
13698                  { x | x IN (s DELETE a) /\
13699                        (f:real^M->real^N)(x) IN t DIFF ball(b,e)}`
13700     MP_TAC THENL
13701      [MATCH_MP_TAC CLOSED_SUBSET THEN CONJ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
13702       MATCH_MP_TAC COMPACT_IMP_CLOSED THEN SUBGOAL_THEN
13703        `{x | x IN s DELETE a /\ f x IN t DIFF ball(b,e)} =
13704         IMAGE (g:real^N->real^M) (t DIFF ball (b,e))`
13705       SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
13706       MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
13707       ASM_SIMP_TAC[COMPACT_DIFF; OPEN_BALL] THEN
13708       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
13709         CONTINUOUS_ON_SUBSET)) THEN ASM SET_TAC[];
13710       REWRITE_TAC[closed_in; open_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
13711       DISCH_THEN(MP_TAC o SPEC `a:real^M` o last o CONJUNCTS) THEN
13712       ASM_REWRITE_TAC[IN_ELIM_THM; IN_DIFF; IN_DELETE] THEN
13713       SIMP_TAC[IMP_CONJ; DE_MORGAN_THM] THEN
13714       MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN
13715       ASM_REWRITE_TAC[] THEN COND_CASES_TAC THEN
13716       ASM_REWRITE_TAC[DIST_REFL] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
13717       RULE_ASSUM_TAC(REWRITE_RULE[IN_BALL]) THEN ASM SET_TAC[]];
13718     UNDISCH_TAC `(f:real^M->real^N) continuous_on (s DELETE a)` THEN
13719     REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
13720     DISCH_THEN(MP_TAC o SPEC `x:real^M`) THEN ASM_REWRITE_TAC[IN_DELETE] THEN
13721     REWRITE_TAC[continuous_within] THEN
13722     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
13723     ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[IN_DELETE] THEN
13724     DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
13725     EXISTS_TAC `min d (dist(a:real^M,x))` THEN
13726     ASM_REWRITE_TAC[REAL_LT_MIN; GSYM DIST_NZ] THEN
13727     ASM_MESON_TAC[REAL_LT_REFL]]);;
13728
13729 (* ------------------------------------------------------------------------- *)
13730 (* Homeomorphisms between open intervals in real^1 and then in real^N.       *)
13731 (* Could prove similar things for closed intervals, but they drop out of     *)
13732 (* later stuff in "convex.ml" even more easily.                              *)
13733 (* ------------------------------------------------------------------------- *)
13734
13735 let HOMEOMORPHIC_OPEN_INTERVALS_1 = prove
13736  (`!a b c d.
13737         drop a < drop b /\ drop c < drop d
13738         ==> interval(a,b) homeomorphic interval(c,d)`,
13739   SUBGOAL_THEN
13740    `!a b. drop a < drop b
13741           ==> interval(vec 0:real^1,vec 1) homeomorphic interval(a,b)`
13742   ASSUME_TAC THENL
13743    [REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
13744     EXISTS_TAC `(\x. a + drop x % (b - a)):real^1->real^1` THEN
13745     EXISTS_TAC `(\x. inv(drop b - drop a) % (x - a)):real^1->real^1` THEN
13746     ASM_REWRITE_TAC[IN_INTERVAL_1; GSYM DROP_EQ] THEN
13747     REWRITE_TAC[DROP_ADD; DROP_CMUL; DROP_NEG; DROP_VEC; DROP_SUB] THEN
13748     REWRITE_TAC[REAL_ARITH `inv b * a:real = a / b`] THEN
13749     ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_SUB_LT;
13750        REAL_LT_ADDR; REAL_EQ_LDIV_EQ; REAL_DIV_RMUL; REAL_LT_IMP_NZ;
13751        REAL_LT_MUL; REAL_MUL_LZERO; REAL_ADD_SUB; REAL_LT_RMUL_EQ;
13752        REAL_ARITH `a + x < b <=> x < &1 * (b - a)`] THEN
13753     REPEAT CONJ_TAC THENL
13754      [REAL_ARITH_TAC;
13755       MATCH_MP_TAC CONTINUOUS_ON_ADD THEN REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
13756       MATCH_MP_TAC CONTINUOUS_ON_VMUL THEN
13757       REWRITE_TAC[o_DEF; LIFT_DROP; CONTINUOUS_ON_ID];
13758       MATCH_MP_TAC CONTINUOUS_ON_CMUL THEN
13759       ASM_SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID]];
13760     REPEAT STRIP_TAC THEN
13761     FIRST_ASSUM(MP_TAC o SPECL [`a:real^1`; `b:real^1`]) THEN
13762     FIRST_X_ASSUM(MP_TAC o SPECL [`c:real^1`; `d:real^1`]) THEN
13763     ASM_REWRITE_TAC[GSYM IMP_CONJ_ALT] THEN
13764     GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [HOMEOMORPHIC_SYM] THEN
13765     REWRITE_TAC[HOMEOMORPHIC_TRANS]]);;
13766
13767 let HOMEOMORPHIC_OPEN_INTERVAL_UNIV_1 = prove
13768  (`!a b. drop a < drop b ==> interval(a,b) homeomorphic (:real^1)`,
13769   REPEAT STRIP_TAC THEN
13770   MP_TAC(SPECL [`a:real^1`; `b:real^1`; `--vec 1:real^1`; `vec 1:real^1`]
13771         HOMEOMORPHIC_OPEN_INTERVALS_1) THEN
13772   ASM_REWRITE_TAC[DROP_VEC; DROP_NEG] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
13773   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] HOMEOMORPHIC_TRANS) THEN
13774   POP_ASSUM_LIST(K ALL_TAC) THEN
13775   REWRITE_TAC[HOMEOMORPHIC_MINIMAL; IN_UNIV] THEN
13776   EXISTS_TAC `\x:real^1. inv(&1 - norm x) % x` THEN
13777   EXISTS_TAC `\y. if &0 <= drop y then inv(&1 + drop y) % y
13778                   else inv(&1 - drop y) % y` THEN
13779   REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
13780    [X_GEN_TAC `x:real^1` THEN REWRITE_TAC[IN_INTERVAL_1] THEN
13781     REWRITE_TAC[DROP_NEG; DROP_VEC; DROP_CMUL; NORM_REAL; GSYM drop] THEN
13782     SIMP_TAC[REAL_LE_MUL_EQ; REAL_LT_INV_EQ; REAL_LE_MUL_EQ; REAL_ARITH
13783      `--a < x /\ x < a ==> &0 < a - abs x`] THEN
13784     SIMP_TAC[real_abs; VECTOR_MUL_ASSOC] THEN
13785     COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
13786     GEN_REWRITE_TAC RAND_CONV [GSYM VECTOR_MUL_LID] THEN
13787     AP_THM_TAC THEN AP_TERM_TAC THEN
13788     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD;
13789     X_GEN_TAC `y:real^1` THEN COND_CASES_TAC THEN
13790     ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_NEG; DROP_VEC; REAL_BOUNDS_LT] THEN
13791     REWRITE_TAC[DROP_CMUL; REAL_ABS_MUL; REAL_ABS_INV] THEN
13792     REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_MUL_SYM] real_div)] THEN
13793     ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_ARITH `&0 <= x ==> &0 < abs(&1 + x)`;
13794                  REAL_ARITH `~(&0 <= x) ==> &0 < abs(&1 - x)`] THEN
13795     (CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
13796     REWRITE_TAC[NORM_REAL; VECTOR_MUL_ASSOC] THEN
13797     REWRITE_TAC[GSYM drop; DROP_CMUL; REAL_ABS_MUL] THEN
13798     ASM_REWRITE_TAC[real_abs; REAL_LE_INV_EQ] THEN
13799     ASM_SIMP_TAC[REAL_ARITH `&0 <= x ==> &0 <= &1 + x`;
13800                  REAL_ARITH `~(&0 <= x) ==> &0 <= &1 - x`] THEN
13801     GEN_REWRITE_TAC RAND_CONV [GSYM VECTOR_MUL_LID] THEN
13802     AP_THM_TAC THEN AP_TERM_TAC THEN
13803     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD;
13804     MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
13805     X_GEN_TAC `x:real^1` THEN
13806     REWRITE_TAC[IN_INTERVAL_1; DROP_NEG; DROP_VEC] THEN
13807     DISCH_TAC THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
13808     REWRITE_TAC[CONTINUOUS_AT_ID] THEN
13809     ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_INV THEN
13810     REWRITE_TAC[NETLIMIT_AT; o_DEF; LIFT_SUB; LIFT_DROP] THEN
13811     CONJ_TAC THENL
13812      [MATCH_MP_TAC CONTINUOUS_SUB THEN
13813       SIMP_TAC[CONTINUOUS_CONST; REWRITE_RULE[o_DEF] CONTINUOUS_AT_LIFT_NORM];
13814       REWRITE_TAC[NORM_REAL; GSYM drop] THEN ASM_REAL_ARITH_TAC];
13815     SUBGOAL_THEN `(:real^1) = {x | x$1 >= &0} UNION {x | x$1 <= &0}`
13816     SUBST1_TAC THENL
13817      [REWRITE_TAC[EXTENSION; IN_UNION; IN_UNION; IN_ELIM_THM; IN_UNIV] THEN
13818       REAL_ARITH_TAC;
13819       MATCH_MP_TAC CONTINUOUS_ON_CASES THEN
13820       REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_LE; CLOSED_HALFSPACE_COMPONENT_GE;
13821                   IN_ELIM_THM] THEN
13822       REWRITE_TAC[GSYM drop; REAL_NOT_LE; real_ge; REAL_LET_ANTISYM] THEN
13823       SIMP_TAC[REAL_LE_ANTISYM; REAL_SUB_RZERO; REAL_ADD_RID] THEN
13824       CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
13825       X_GEN_TAC `y:real^1` THEN REWRITE_TAC[IN_ELIM_THM; real_ge] THEN
13826       DISCH_TAC THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
13827       REWRITE_TAC[CONTINUOUS_AT_ID] THEN
13828       ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_INV THEN
13829       REWRITE_TAC[NETLIMIT_AT; o_DEF; LIFT_ADD; LIFT_SUB; LIFT_DROP] THEN
13830       ASM_SIMP_TAC[CONTINUOUS_ADD; CONTINUOUS_AT_ID; CONTINUOUS_SUB;
13831                    CONTINUOUS_CONST] THEN
13832       ASM_REAL_ARITH_TAC]]);;
13833
13834 let HOMEOMORPHIC_OPEN_INTERVALS = prove
13835  (`!a b:real^N c d:real^N.
13836         (interval(a,b) = {} <=> interval(c,d) = {})
13837         ==> interval(a,b) homeomorphic interval(c,d)`,
13838   REPEAT GEN_TAC THEN ASM_CASES_TAC `interval(c:real^N,d) = {}` THEN
13839   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN ASM_REWRITE_TAC[HOMEOMORPHIC_REFL] THEN
13840   SUBGOAL_THEN
13841    `!i. 1 <= i /\ i <= dimindex(:N)
13842         ==> interval(lift((a:real^N)$i),lift((b:real^N)$i)) homeomorphic
13843             interval(lift((c:real^N)$i),lift((d:real^N)$i))`
13844   MP_TAC THENL
13845    [RULE_ASSUM_TAC(REWRITE_RULE[INTERVAL_NE_EMPTY]) THEN
13846     ASM_SIMP_TAC[HOMEOMORPHIC_OPEN_INTERVALS_1; LIFT_DROP];
13847     ALL_TAC] THEN
13848   REWRITE_TAC[HOMEOMORPHIC_MINIMAL; IN_INTERVAL_1; LIFT_DROP] THEN
13849   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
13850   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
13851   MAP_EVERY X_GEN_TAC [`f:num->real^1->real^1`; `g:num->real^1->real^1`] THEN
13852   DISCH_TAC THEN
13853   EXISTS_TAC
13854    `(\x. lambda i.
13855        drop((f:num->real^1->real^1) i (lift(x$i)))):real^N->real^N` THEN
13856   EXISTS_TAC
13857    `(\x. lambda i.
13858        drop((g:num->real^1->real^1) i (lift(x$i)))):real^N->real^N` THEN
13859   ASM_SIMP_TAC[IN_INTERVAL; LAMBDA_BETA; CART_EQ; LIFT_DROP] THEN
13860   ONCE_REWRITE_TAC[CONTINUOUS_ON_COMPONENTWISE_LIFT] THEN
13861   SIMP_TAC[LAMBDA_BETA; LIFT_DROP] THEN CONJ_TAC THEN REPEAT STRIP_TAC THEN
13862   ONCE_REWRITE_TAC[GSYM o_DEF] THEN
13863   MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
13864   ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT] THEN
13865   MATCH_MP_TAC CONTINUOUS_ON_SUBSET THENL
13866    [EXISTS_TAC `interval(lift((a:real^N)$i),lift((b:real^N)$i))`;
13867     EXISTS_TAC `interval(lift((c:real^N)$i),lift((d:real^N)$i))`] THEN
13868   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1] THEN
13869   ASM_SIMP_TAC[LIFT_DROP; IN_INTERVAL]);;
13870
13871 let HOMEOMORPHIC_OPEN_INTERVAL_UNIV = prove
13872  (`!a b:real^N.
13873         ~(interval(a,b) = {})
13874         ==> interval(a,b) homeomorphic (:real^N)`,
13875   REPEAT STRIP_TAC THEN
13876   SUBGOAL_THEN
13877    `!i. 1 <= i /\ i <= dimindex(:N)
13878         ==> interval(lift((a:real^N)$i),lift((b:real^N)$i)) homeomorphic
13879             (:real^1)`
13880   MP_TAC THENL
13881    [RULE_ASSUM_TAC(REWRITE_RULE[INTERVAL_NE_EMPTY]) THEN
13882     ASM_SIMP_TAC[HOMEOMORPHIC_OPEN_INTERVAL_UNIV_1; LIFT_DROP];
13883     ALL_TAC] THEN
13884   REWRITE_TAC[HOMEOMORPHIC_MINIMAL; IN_INTERVAL_1; LIFT_DROP] THEN
13885   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
13886   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM; IN_UNIV] THEN
13887   MAP_EVERY X_GEN_TAC [`f:num->real^1->real^1`; `g:num->real^1->real^1`] THEN
13888   DISCH_TAC THEN
13889   EXISTS_TAC
13890    `(\x. lambda i.
13891        drop((f:num->real^1->real^1) i (lift(x$i)))):real^N->real^N` THEN
13892   EXISTS_TAC
13893    `(\x. lambda i.
13894        drop((g:num->real^1->real^1) i (lift(x$i)))):real^N->real^N` THEN
13895   ASM_SIMP_TAC[IN_INTERVAL; LAMBDA_BETA; CART_EQ; LIFT_DROP; IN_UNIV] THEN
13896   ONCE_REWRITE_TAC[CONTINUOUS_ON_COMPONENTWISE_LIFT] THEN
13897   SIMP_TAC[LAMBDA_BETA; LIFT_DROP] THEN CONJ_TAC THEN REPEAT STRIP_TAC THEN
13898   ONCE_REWRITE_TAC[GSYM o_DEF] THEN
13899   MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
13900   ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT] THEN
13901   MATCH_MP_TAC CONTINUOUS_ON_SUBSET THENL
13902    [EXISTS_TAC `interval(lift((a:real^N)$i),lift((b:real^N)$i))`;
13903     EXISTS_TAC `(:real^1)`] THEN
13904   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1; IN_UNIV] THEN
13905   ASM_SIMP_TAC[LIFT_DROP; IN_INTERVAL]);;
13906
13907 let HOMEOMORPHIC_BALL_UNIV = prove
13908  (`!a:real^N r. &0 < r ==> ball(a,r) homeomorphic (:real^N)`,
13909   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN REPEAT STRIP_TAC THEN
13910   SUBGOAL_THEN `?y:real^N. r = norm(y)` (CHOOSE_THEN SUBST_ALL_TAC) THENL
13911    [ASM_MESON_TAC[VECTOR_CHOOSE_SIZE; REAL_LT_IMP_LE]; POP_ASSUM MP_TAC] THEN
13912   REWRITE_TAC[NORM_POS_LT] THEN GEOM_NORMALIZE_TAC `y:real^N` THEN
13913   SIMP_TAC[] THEN GEN_TAC THEN REPEAT(DISCH_THEN(K ALL_TAC)) THEN
13914   REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
13915   EXISTS_TAC `\z:real^N. inv(&1 - norm(z)) % z` THEN
13916   EXISTS_TAC `\z:real^N. inv(&1 + norm(z)) % z` THEN
13917   REWRITE_TAC[IN_BALL; IN_UNIV; DIST_0; VECTOR_MUL_ASSOC; VECTOR_MUL_EQ_0;
13918               VECTOR_ARITH `a % x:real^N = x <=> (a - &1) % x = vec 0`] THEN
13919   REPEAT CONJ_TAC THENL
13920    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN DISJ1_TAC THEN
13921     REWRITE_TAC[GSYM REAL_INV_MUL; REAL_SUB_0; REAL_INV_EQ_1] THEN
13922     REWRITE_TAC[NORM_MUL; REAL_ABS_INV] THEN
13923     ASM_SIMP_TAC[REAL_ARITH `x < &1 ==> abs(&1 - x) = &1 - x`] THEN
13924     POP_ASSUM MP_TAC THEN CONV_TAC REAL_FIELD;
13925     X_GEN_TAC `y:real^N` THEN REWRITE_TAC[NORM_MUL; REAL_ABS_INV] THEN
13926     ASM_SIMP_TAC[NORM_POS_LE; REAL_ARITH
13927      `&0 <= y ==> inv(abs(&1 + y)) * z = z / (&1 + y)`] THEN
13928     ASM_SIMP_TAC[NORM_POS_LE; REAL_LT_LDIV_EQ; REAL_ARITH
13929       `&0 <= y ==> &0 < &1 + y`] THEN
13930     CONJ_TAC THENL [REAL_ARITH_TAC; DISJ1_TAC] THEN
13931     REWRITE_TAC[GSYM REAL_INV_MUL; REAL_SUB_0; REAL_INV_EQ_1] THEN
13932     MP_TAC(ISPEC `y:real^N` NORM_POS_LE) THEN CONV_TAC REAL_FIELD;
13933     MATCH_MP_TAC CONTINUOUS_ON_MUL THEN REWRITE_TAC[CONTINUOUS_ON_ID] THEN
13934     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
13935     MATCH_MP_TAC CONTINUOUS_ON_INV THEN
13936     SIMP_TAC[IN_BALL_0; REAL_SUB_0; REAL_ARITH `x < &1 ==> ~(&1 = x)`] THEN
13937     REWRITE_TAC[o_DEF; LIFT_SUB] THEN MATCH_MP_TAC CONTINUOUS_ON_SUB THEN
13938     REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
13939     MATCH_MP_TAC CONTINUOUS_ON_LIFT_NORM_COMPOSE THEN
13940     REWRITE_TAC[CONTINUOUS_ON_ID];
13941     MATCH_MP_TAC CONTINUOUS_ON_MUL THEN REWRITE_TAC[CONTINUOUS_ON_ID] THEN
13942     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
13943     MATCH_MP_TAC CONTINUOUS_ON_INV THEN
13944     SIMP_TAC[NORM_POS_LE; REAL_ARITH `&0 <= x ==> ~(&1 + x = &0)`] THEN
13945     REWRITE_TAC[o_DEF; LIFT_ADD] THEN MATCH_MP_TAC CONTINUOUS_ON_ADD THEN
13946     REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
13947     MATCH_MP_TAC CONTINUOUS_ON_LIFT_NORM_COMPOSE THEN
13948     REWRITE_TAC[CONTINUOUS_ON_ID]]);;
13949
13950 (* ------------------------------------------------------------------------- *)
13951 (* Cardinalities of various useful sets.                                     *)
13952 (* ------------------------------------------------------------------------- *)
13953
13954 let CARD_EQ_EUCLIDEAN = prove
13955  (`(:real^N) =_c (:real)`,
13956   MATCH_MP_TAC CARD_EQ_CART THEN REWRITE_TAC[real_INFINITE]);;
13957
13958 let UNCOUNTABLE_EUCLIDEAN = prove
13959  (`~COUNTABLE(:real^N)`,
13960   MATCH_MP_TAC CARD_EQ_REAL_IMP_UNCOUNTABLE THEN
13961   REWRITE_TAC[CARD_EQ_EUCLIDEAN]);;
13962
13963 let CARD_EQ_INTERVAL = prove
13964  (`(!a b:real^N. ~(interval(a,b) = {}) ==> interval[a,b] =_c (:real)) /\
13965    (!a b:real^N. ~(interval(a,b) = {}) ==> interval(a,b) =_c (:real))`,
13966   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN
13967   ASM_CASES_TAC `interval(a:real^N,b) = {}` THEN ASM_REWRITE_TAC[] THEN
13968   CONJ_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
13969    [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
13970     REWRITE_TAC[CARD_LE_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
13971     REWRITE_TAC[CARD_EQ_EUCLIDEAN];
13972     TRANS_TAC CARD_LE_TRANS `interval(a:real^N,b)` THEN
13973     SIMP_TAC[CARD_LE_SUBSET; INTERVAL_OPEN_SUBSET_CLOSED];
13974     TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
13975     REWRITE_TAC[CARD_LE_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
13976     REWRITE_TAC[CARD_EQ_EUCLIDEAN];
13977     ALL_TAC] THEN
13978   TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
13979   SIMP_TAC[ONCE_REWRITE_RULE[CARD_EQ_SYM] CARD_EQ_IMP_LE;
13980            CARD_EQ_EUCLIDEAN] THEN
13981   FIRST_X_ASSUM(MP_TAC o MATCH_MP HOMEOMORPHIC_OPEN_INTERVAL_UNIV) THEN
13982   DISCH_THEN(MP_TAC o MATCH_MP HOMEOMORPHIC_IMP_CARD_EQ) THEN
13983   MESON_TAC[CARD_EQ_IMP_LE; CARD_EQ_SYM]);;
13984
13985 let UNCOUNTABLE_INTERVAL = prove
13986  (`(!a b. ~(interval(a,b) = {}) ==> ~COUNTABLE(interval[a,b])) /\
13987    (!a b. ~(interval(a,b) = {}) ==> ~COUNTABLE(interval(a,b)))`,
13988   SIMP_TAC[CARD_EQ_REAL_IMP_UNCOUNTABLE; CARD_EQ_INTERVAL]);;
13989
13990 let COUNTABLE_OPEN_INTERVAL = prove
13991  (`!a b. COUNTABLE(interval(a,b)) <=> interval(a,b) = {}`,
13992   MESON_TAC[COUNTABLE_EMPTY; UNCOUNTABLE_INTERVAL]);;
13993
13994 let CARD_EQ_OPEN = prove
13995  (`!s:real^N->bool. open s /\ ~(s = {}) ==> s =_c (:real)`,
13996   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
13997    [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
13998     REWRITE_TAC[CARD_LE_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
13999     REWRITE_TAC[CARD_EQ_EUCLIDEAN];
14000     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_INTERVAL]) THEN
14001     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
14002     DISCH_THEN(X_CHOOSE_TAC `c:real^N`) THEN
14003     DISCH_THEN(MP_TAC o SPEC `c:real^N`) THEN
14004     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
14005     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN
14006     ASM_CASES_TAC `interval(a:real^N,b) = {}` THEN
14007     ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN STRIP_TAC THEN
14008     TRANS_TAC CARD_LE_TRANS `interval[a:real^N,b]` THEN
14009     ASM_SIMP_TAC[CARD_LE_SUBSET] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
14010     ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN ASM_SIMP_TAC[CARD_EQ_INTERVAL]]);;
14011
14012 let UNCOUNTABLE_OPEN = prove
14013  (`!s:real^N->bool. open s /\ ~(s = {}) ==> ~(COUNTABLE s)`,
14014   SIMP_TAC[CARD_EQ_OPEN; CARD_EQ_REAL_IMP_UNCOUNTABLE]);;
14015
14016 let CARD_EQ_BALL = prove
14017  (`!a:real^N r. &0 < r ==> ball(a,r) =_c (:real)`,
14018   SIMP_TAC[CARD_EQ_OPEN; OPEN_BALL; BALL_EQ_EMPTY; GSYM REAL_NOT_LT]);;
14019
14020 let CARD_EQ_CBALL = prove
14021  (`!a:real^N r. &0 < r ==> cball(a,r) =_c (:real)`,
14022   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
14023    [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
14024     REWRITE_TAC[CARD_LE_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
14025     REWRITE_TAC[CARD_EQ_EUCLIDEAN];
14026     TRANS_TAC CARD_LE_TRANS `ball(a:real^N,r)` THEN
14027     SIMP_TAC[CARD_LE_SUBSET; BALL_SUBSET_CBALL] THEN
14028     MATCH_MP_TAC CARD_EQ_IMP_LE THEN
14029     ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN ASM_SIMP_TAC[CARD_EQ_BALL]]);;
14030
14031 let FINITE_IMP_NOT_OPEN = prove
14032  (`!s:real^N->bool. FINITE s /\ ~(s = {}) ==> ~(open s)`,
14033   MESON_TAC[UNCOUNTABLE_OPEN; FINITE_IMP_COUNTABLE]);;
14034
14035 let OPEN_IMP_INFINITE = prove
14036  (`!s. open s ==> s = {} \/ INFINITE s`,
14037   MESON_TAC[FINITE_IMP_NOT_OPEN; INFINITE]);;
14038
14039 let EMPTY_INTERIOR_FINITE = prove
14040  (`!s:real^N->bool. FINITE s ==> interior s = {}`,
14041   REPEAT STRIP_TAC THEN MP_TAC(ISPEC `s:real^N->bool` OPEN_INTERIOR) THEN
14042   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
14043   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] FINITE_IMP_NOT_OPEN) THEN
14044   MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `s:real^N->bool` THEN
14045   ASM_REWRITE_TAC[INTERIOR_SUBSET]);;
14046
14047 let CARD_EQ_CONNECTED = prove
14048  (`!s a b:real^N.
14049         connected s /\ a IN s /\ b IN s /\ ~(a = b) ==> s =_c (:real)`,
14050   GEOM_ORIGIN_TAC `b:real^N` THEN GEOM_NORMALIZE_TAC `a:real^N` THEN
14051   REWRITE_TAC[NORM_EQ_SQUARE; REAL_POS; REAL_POW_ONE] THEN
14052   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
14053    [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
14054     SIMP_TAC[CARD_LE_UNIV; CARD_EQ_EUCLIDEAN; CARD_EQ_IMP_LE];
14055     TRANS_TAC CARD_LE_TRANS `interval[vec 0:real^1,vec 1]` THEN CONJ_TAC THENL
14056      [MATCH_MP_TAC(ONCE_REWRITE_RULE[CARD_EQ_SYM] CARD_EQ_IMP_LE) THEN
14057       SIMP_TAC[UNIT_INTERVAL_NONEMPTY; CARD_EQ_INTERVAL];
14058       REWRITE_TAC[LE_C] THEN EXISTS_TAC `\x:real^N. lift(a dot x)` THEN
14059       SIMP_TAC[FORALL_LIFT; LIFT_EQ; IN_INTERVAL_1; LIFT_DROP; DROP_VEC] THEN
14060       X_GEN_TAC `t:real` THEN STRIP_TAC THEN
14061       MATCH_MP_TAC CONNECTED_IVT_HYPERPLANE THEN
14062       MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `a:real^N`] THEN
14063       ASM_REWRITE_TAC[DOT_RZERO]]]);;
14064
14065 let UNCOUNTABLE_CONNECTED = prove
14066  (`!s a b:real^N.
14067         connected s /\ a IN s /\ b IN s /\ ~(a = b) ==> ~COUNTABLE s`,
14068   REPEAT GEN_TAC THEN STRIP_TAC THEN
14069   MATCH_MP_TAC CARD_EQ_REAL_IMP_UNCOUNTABLE THEN
14070   MATCH_MP_TAC CARD_EQ_CONNECTED THEN
14071   ASM_MESON_TAC[]);;
14072
14073 let CARD_LT_IMP_DISCONNECTED = prove
14074  (`!s x:real^N. s <_c (:real) /\ x IN s ==> connected_component s x = {x}`,
14075   REPEAT STRIP_TAC THEN REWRITE_TAC[SET_RULE
14076    `s = {a} <=> a IN s /\ !a b. a IN s /\ b IN s /\ ~(a = b) ==> F`] THEN
14077   REPEAT STRIP_TAC THEN REWRITE_TAC[IN] THEN
14078   ASM_REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ] THEN
14079   MP_TAC(ISPECL [`connected_component s (x:real^N)`; `a:real^N`; `b:real^N`]
14080         CARD_EQ_CONNECTED) THEN
14081   ASM_REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT] THEN
14082   DISCH_TAC THEN UNDISCH_TAC `(s:real^N->bool) <_c (:real)` THEN
14083   REWRITE_TAC[CARD_NOT_LT] THEN
14084   TRANS_TAC CARD_LE_TRANS `connected_component s (x:real^N)` THEN
14085   ASM_SIMP_TAC[ONCE_REWRITE_RULE[CARD_EQ_SYM] CARD_EQ_IMP_LE] THEN
14086   MATCH_MP_TAC CARD_LE_SUBSET THEN REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]);;
14087
14088 let COUNTABLE_IMP_DISCONNECTED = prove
14089  (`!s x:real^N. COUNTABLE s /\ x IN s ==> connected_component s x = {x}`,
14090   SIMP_TAC[CARD_LT_IMP_DISCONNECTED; COUNTABLE_IMP_CARD_LT_REAL]);;
14091
14092 let CONNECTED_CARD_EQ_IFF_NONTRIVIAL = prove
14093  (`!s:real^N->bool.
14094         connected s ==> (s =_c (:real) <=> ~(?a. s SUBSET {a}))`,
14095   REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL
14096    [ALL_TAC; MATCH_MP_TAC CARD_EQ_CONNECTED THEN ASM SET_TAC[]] THEN
14097   FIRST_ASSUM(MP_TAC o MATCH_MP(REWRITE_RULE[IMP_CONJ_ALT] FINITE_SUBSET)) THEN
14098   REWRITE_TAC[FINITE_SING] THEN
14099   ASM_MESON_TAC[CARD_EQ_REAL_IMP_UNCOUNTABLE; FINITE_IMP_COUNTABLE]);;
14100
14101 (* ------------------------------------------------------------------------- *)
14102 (* "Iff" forms of constancy of function from connected set into a set that   *)
14103 (* is smaller than R, or countable, or finite, or disconnected, or discrete. *)
14104 (* ------------------------------------------------------------------------- *)
14105
14106 let [CONTINUOUS_DISCONNECTED_RANGE_CONSTANT_EQ;
14107      CONTINUOUS_DISCRETE_RANGE_CONSTANT_EQ;
14108      CONTINUOUS_FINITE_RANGE_CONSTANT_EQ] = (CONJUNCTS o prove)
14109   (`(!s. connected s <=>
14110          !f:real^M->real^N t.
14111             f continuous_on s /\ IMAGE f s SUBSET t /\
14112             (!y. y IN t ==> connected_component t y = {y})
14113             ==> ?a. !x. x IN s ==> f x = a) /\
14114     (!s. connected s <=>
14115          !f:real^M->real^N.
14116             f continuous_on s /\
14117             (!x. x IN s
14118                  ==> ?e. &0 < e /\
14119                          !y. y IN s /\ ~(f y = f x) ==> e <= norm(f y - f x))
14120             ==> ?a. !x. x IN s ==> f x = a) /\
14121     (!s. connected s <=>
14122          !f:real^M->real^N.
14123             f continuous_on s /\ FINITE(IMAGE f s)
14124             ==> ?a. !x. x IN s ==> f x = a)`,
14125   REWRITE_TAC[AND_FORALL_THM] THEN X_GEN_TAC `s:real^M->bool` THEN
14126   MATCH_MP_TAC(TAUT
14127    `(s ==> t) /\ (t ==> u) /\ (u ==> v) /\ (v ==> s)
14128     ==> (s <=> t) /\ (s <=> u) /\ (s <=> v)`) THEN
14129   REPEAT CONJ_TAC THENL
14130    [REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^M->bool = {}` THEN
14131     ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
14132     FIRST_X_ASSUM(X_CHOOSE_TAC `x:real^M` o
14133         GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
14134     EXISTS_TAC `(f:real^M->real^N) x` THEN
14135     MATCH_MP_TAC(SET_RULE
14136      `IMAGE f s SUBSET {a} ==> !y. y IN s ==> f y = a`) THEN
14137     FIRST_X_ASSUM(MP_TAC o SPEC `(f:real^M->real^N) x`) THEN
14138     ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN(SUBST1_TAC o SYM)] THEN
14139     MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
14140     ASM_SIMP_TAC[CONNECTED_CONTINUOUS_IMAGE] THEN ASM SET_TAC[];
14141     REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
14142     EXISTS_TAC `IMAGE (f:real^M->real^N) s` THEN
14143     ASM_REWRITE_TAC[FORALL_IN_IMAGE; SUBSET_REFL] THEN
14144     X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
14145     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^M`) THEN ASM_REWRITE_TAC[] THEN
14146     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
14147     MATCH_MP_TAC(SET_RULE
14148      `(!y. y IN s /\ f y IN connected_component (IMAGE f s) a ==> f y = a) /\
14149       connected_component (IMAGE f s) a SUBSET (IMAGE f s) /\
14150       connected_component (IMAGE f s) a a
14151       ==> connected_component (IMAGE f s) a = {a}`) THEN
14152     REWRITE_TAC[CONNECTED_COMPONENT_SUBSET; CONNECTED_COMPONENT_REFL_EQ] THEN
14153     ASM_SIMP_TAC[FUN_IN_IMAGE] THEN X_GEN_TAC `y:real^M` THEN STRIP_TAC THEN
14154     MP_TAC(ISPEC `connected_component (IMAGE (f:real^M->real^N) s) (f x)`
14155         CONNECTED_CLOSED) THEN
14156     REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT] THEN
14157     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
14158     ASM_REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
14159      [`cball((f:real^M->real^N) x,e / &2)`;
14160       `(:real^N) DIFF ball((f:real^M->real^N) x,e)`] THEN
14161     REWRITE_TAC[GSYM OPEN_CLOSED; OPEN_BALL; CLOSED_CBALL] THEN
14162     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN REPEAT CONJ_TAC THENL
14163      [REWRITE_TAC[SUBSET; IN_CBALL; IN_UNION; IN_DIFF; IN_BALL; IN_UNIV] THEN
14164       MATCH_MP_TAC(MESON[SUBSET; CONNECTED_COMPONENT_SUBSET]
14165        `(!x. x IN s ==> P x)
14166         ==> (!x. x IN connected_component s y ==> P x)`) THEN
14167       REWRITE_TAC[FORALL_IN_IMAGE] THEN X_GEN_TAC `z:real^M` THEN
14168       DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `z:real^M`) THEN
14169       ASM_REWRITE_TAC[] THEN CONV_TAC NORM_ARITH;
14170       MATCH_MP_TAC(SET_RULE
14171        `(!x. x IN s /\ x IN t ==> F) ==> s INTER t INTER u = {}`) THEN
14172       REWRITE_TAC[IN_BALL; IN_CBALL; IN_DIFF; IN_UNIV] THEN
14173       UNDISCH_TAC `&0 < e` THEN CONV_TAC NORM_ARITH;
14174       EXISTS_TAC `(f:real^M->real^N) x` THEN
14175       ASM_SIMP_TAC[CENTRE_IN_CBALL; REAL_HALF; REAL_LT_IMP_LE; IN_INTER] THEN
14176       REWRITE_TAC[IN] THEN
14177       ASM_SIMP_TAC[CONNECTED_COMPONENT_REFL_EQ; FUN_IN_IMAGE];
14178       EXISTS_TAC `(f:real^M->real^N) y` THEN
14179       ASM_REWRITE_TAC[IN_INTER; IN_DIFF; IN_UNIV; IN_BALL; REAL_NOT_LT] THEN
14180       ASM_SIMP_TAC[ONCE_REWRITE_RULE[DIST_SYM] dist]];
14181     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `f:real^M->real^N` THEN
14182     DISCH_THEN(fun th -> STRIP_TAC THEN MATCH_MP_TAC th) THEN
14183     ASM_REWRITE_TAC[] THEN X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
14184     ASM_CASES_TAC `IMAGE (f:real^M->real^N) s DELETE (f x) = {}` THENL
14185      [EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN ASM SET_TAC[];
14186       ALL_TAC] THEN
14187     EXISTS_TAC
14188      `inf{norm(z - f x) |z| z IN IMAGE (f:real^M->real^N) s DELETE (f x)}` THEN
14189     REWRITE_TAC[SIMPLE_IMAGE] THEN
14190     ASM_SIMP_TAC[REAL_LT_INF_FINITE; REAL_INF_LE_FINITE; FINITE_DELETE;
14191                  FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
14192     REWRITE_TAC[FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
14193     REWRITE_TAC[IN_DELETE; NORM_POS_LT; VECTOR_SUB_EQ; IN_IMAGE] THEN
14194     MESON_TAC[REAL_LE_REFL];
14195     REWRITE_TAC[CONNECTED_CLOSED_IN_EQ] THEN
14196     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
14197     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
14198     MAP_EVERY X_GEN_TAC [`t:real^M->bool`; `u:real^M->bool`] THEN
14199     STRIP_TAC THEN DISCH_THEN(MP_TAC o SPEC
14200      `(\x. if x IN t then vec 0 else basis 1):real^M->real^N`) THEN
14201     REWRITE_TAC[NOT_IMP] THEN REPEAT CONJ_TAC THENL
14202      [EXPAND_TAC "s" THEN MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL THEN
14203       ASM_REWRITE_TAC[CONTINUOUS_ON_CONST] THEN ASM SET_TAC[];
14204       MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `{vec 0:real^N,basis 1}` THEN
14205       REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY] THEN SET_TAC[];
14206       SUBGOAL_THEN `?a b:real^M. a IN s /\ a IN t /\ b IN s /\ ~(b IN t)`
14207       STRIP_ASSUME_TAC THENL
14208        [ASM SET_TAC[]; DISCH_THEN(CHOOSE_THEN MP_TAC)] THEN
14209       DISCH_THEN(fun th -> MP_TAC(SPEC `a:real^M` th) THEN
14210                            MP_TAC(SPEC `b:real^M` th)) THEN
14211       ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
14212       CONV_TAC(RAND_CONV SYM_CONV) THEN
14213       SIMP_TAC[BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1; REAL_LE_REFL]]]);;
14214
14215 let CONTINUOUS_DISCONNECTED_RANGE_CONSTANT = prove
14216  (`!f:real^M->real^N s.
14217         connected s /\
14218         f continuous_on s /\ IMAGE f s SUBSET t /\
14219         (!y. y IN t ==> connected_component t y = {y})
14220         ==> ?a. !x. x IN s ==> f x = a`,
14221   MESON_TAC[CONTINUOUS_DISCONNECTED_RANGE_CONSTANT_EQ]);;
14222
14223 let CONTINUOUS_DISCRETE_RANGE_CONSTANT = prove
14224  (`!f:real^M->real^N s.
14225         connected s /\
14226         f continuous_on s /\
14227         (!x. x IN s
14228              ==> ?e. &0 < e /\
14229                      !y. y IN s /\ ~(f y = f x) ==> e <= norm(f y - f x))
14230         ==> ?a. !x. x IN s ==> f x = a`,
14231   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
14232   REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
14233   REWRITE_TAC[IMP_IMP; GSYM CONTINUOUS_DISCRETE_RANGE_CONSTANT_EQ]);;
14234
14235 let CONTINUOUS_FINITE_RANGE_CONSTANT = prove
14236  (`!f:real^M->real^N s.
14237         connected s /\
14238         f continuous_on s /\
14239         FINITE(IMAGE f s)
14240         ==> ?a. !x. x IN s ==> f x = a`,
14241   MESON_TAC[CONTINUOUS_FINITE_RANGE_CONSTANT_EQ]);;
14242
14243 let CONTINUOUS_COUNTABLE_RANGE_CONSTANT_EQ = prove
14244  (`!s. connected s <=>
14245          !f:real^M->real^N.
14246             f continuous_on s /\ COUNTABLE(IMAGE f s)
14247             ==> ?a. !x. x IN s ==> f x = a`,
14248   GEN_TAC THEN EQ_TAC THENL
14249    [REWRITE_TAC[CONTINUOUS_DISCONNECTED_RANGE_CONSTANT_EQ];
14250     REWRITE_TAC[CONTINUOUS_FINITE_RANGE_CONSTANT_EQ]] THEN
14251   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
14252   ASM_SIMP_TAC[FINITE_IMP_COUNTABLE] THEN
14253   EXISTS_TAC `IMAGE (f:real^M->real^N) s` THEN
14254   ASM_SIMP_TAC[COUNTABLE_IMP_DISCONNECTED; SUBSET_REFL]);;
14255
14256 let CONTINUOUS_CARD_LT_RANGE_CONSTANT_EQ = prove
14257  (`!s. connected s <=>
14258          !f:real^M->real^N.
14259             f continuous_on s /\ (IMAGE f s) <_c (:real)
14260             ==> ?a. !x. x IN s ==> f x = a`,
14261   GEN_TAC THEN EQ_TAC THENL
14262    [REWRITE_TAC[CONTINUOUS_DISCONNECTED_RANGE_CONSTANT_EQ];
14263     REWRITE_TAC[CONTINUOUS_COUNTABLE_RANGE_CONSTANT_EQ]] THEN
14264   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
14265   ASM_SIMP_TAC[COUNTABLE_IMP_CARD_LT_REAL] THEN
14266   EXISTS_TAC `IMAGE (f:real^M->real^N) s` THEN
14267   ASM_SIMP_TAC[CARD_LT_IMP_DISCONNECTED; SUBSET_REFL]);;
14268
14269 let CONTINUOUS_COUNTABLE_RANGE_CONSTANT = prove
14270  (`!f:real^M->real^N s.
14271         connected s /\ f continuous_on s /\ COUNTABLE(IMAGE f s)
14272         ==> ?a. !x. x IN s ==> f x = a`,
14273   MESON_TAC[CONTINUOUS_COUNTABLE_RANGE_CONSTANT_EQ]);;
14274
14275 let CONTINUOUS_CARD_LT_RANGE_CONSTANT = prove
14276  (`!f:real^M->real^N s.
14277         connected s /\ f continuous_on s /\ (IMAGE f s) <_c (:real)
14278         ==> ?a. !x. x IN s ==> f x = a`,
14279   MESON_TAC[CONTINUOUS_CARD_LT_RANGE_CONSTANT_EQ]);;
14280
14281 (* ------------------------------------------------------------------------- *)
14282 (* Homeomorphism of hyperplanes.                                             *)
14283 (* ------------------------------------------------------------------------- *)
14284
14285 let HOMEOMORPHIC_HYPERPLANES = prove
14286  (`!a:real^N b c:real^N d.
14287         ~(a = vec 0) /\ ~(c = vec 0)
14288         ==> {x | a dot x = b} homeomorphic {x | c dot x = d}`,
14289   let lemma = prove
14290    (`~(a = vec 0)
14291      ==> {x:real^N | a dot x = b} homeomorphic {x:real^N | x$1 = &0}`,
14292     REPEAT STRIP_TAC THEN SUBGOAL_THEN `?c:real^N. a dot c = b`
14293     STRIP_ASSUME_TAC THENL
14294      [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [CART_EQ]) THEN
14295       REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; VEC_COMPONENT] THEN
14296       DISCH_THEN(X_CHOOSE_THEN `k:num` STRIP_ASSUME_TAC) THEN
14297       EXISTS_TAC `b / (a:real^N)$k % basis k:real^N` THEN
14298       ASM_SIMP_TAC[DOT_RMUL; DOT_BASIS; REAL_DIV_RMUL];
14299       FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
14300       ABBREV_TAC `p = {x:real^N | x$1 = &0}` THEN
14301       GEOM_ORIGIN_TAC `c:real^N` THEN
14302       REWRITE_TAC[VECTOR_ADD_RID; DOT_RADD; DOT_RZERO; REAL_EQ_ADD_LCANCEL_0;
14303                   REAL_ADD_RID] THEN
14304       REPEAT STRIP_TAC THEN UNDISCH_TAC `~(a:real^N = vec 0)` THEN
14305       GEOM_BASIS_MULTIPLE_TAC 1 `a:real^N` THEN
14306       SIMP_TAC[VECTOR_MUL_EQ_0; DE_MORGAN_THM; DOT_LMUL; REAL_ENTIRE] THEN
14307       SIMP_TAC[DOT_BASIS; LE_REFL; DIMINDEX_GE_1] THEN
14308       EXPAND_TAC "p" THEN REWRITE_TAC[HOMEOMORPHIC_REFL]]) in
14309   REPEAT STRIP_TAC THEN
14310   TRANS_TAC HOMEOMORPHIC_TRANS `{x:real^N | x$1 = &0}` THEN
14311   ASM_SIMP_TAC[lemma] THEN ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
14312   ASM_SIMP_TAC[lemma]);;
14313
14314 let HOMEOMORPHIC_HYPERPLANE_STANDARD_HYPERPLANE = prove
14315  (`!a:real^N b k c.
14316         ~(a = vec 0) /\ 1 <= k /\ k <= dimindex(:N)
14317         ==> {x | a dot x = b} homeomorphic {x:real^N | x$k = c}`,
14318   REPEAT STRIP_TAC THEN
14319   SUBGOAL_THEN `{x:real^N | x$k = c} = {x | basis k dot x = c}` SUBST1_TAC
14320   THENL [ASM_SIMP_TAC[DOT_BASIS]; MATCH_MP_TAC HOMEOMORPHIC_HYPERPLANES] THEN
14321   ASM_SIMP_TAC[BASIS_NONZERO]);;
14322
14323 let HOMEOMORPHIC_STANDARD_HYPERPLANE_HYPERPLANE = prove
14324  (`!a:real^N b k c.
14325         ~(a = vec 0) /\ 1 <= k /\ k <= dimindex(:N)
14326         ==> {x:real^N | x$k = c} homeomorphic {x | a dot x = b}`,
14327   ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
14328   REWRITE_TAC[HOMEOMORPHIC_HYPERPLANE_STANDARD_HYPERPLANE]);;
14329
14330 let HOMEOMORPHIC_HYPERPLANE_UNIV = prove
14331  (`!a b. ~(a = vec 0) /\ dimindex(:N) = dimindex(:M) + 1
14332          ==> {x:real^N | a dot x = b} homeomorphic (:real^M)`,
14333   REPEAT STRIP_TAC THEN TRANS_TAC HOMEOMORPHIC_TRANS
14334    `{x:real^N | basis(dimindex(:N)) dot x = &0}` THEN
14335   ASM_SIMP_TAC[HOMEOMORPHIC_HYPERPLANES; BASIS_NONZERO;
14336                LE_REFL; DIMINDEX_GE_1] THEN
14337   REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
14338   EXISTS_TAC `(\x. lambda i. x$i):real^N->real^M` THEN
14339   EXISTS_TAC `(\x. lambda i. if i <= dimindex(:M) then x$i else &0)
14340               :real^M->real^N` THEN
14341   REPEAT CONJ_TAC THENL
14342    [MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
14343     SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
14344              VECTOR_MUL_COMPONENT];
14345     REWRITE_TAC[SUBSET_UNIV];
14346     MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
14347     SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
14348              VECTOR_MUL_COMPONENT] THEN
14349     REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
14350     REAL_ARITH_TAC;
14351     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM; IN_UNIV] THEN
14352     ASM_SIMP_TAC[DOT_BASIS; LAMBDA_BETA; LE_REFL; ARITH_RULE `1 <= n + 1`;
14353                  ARITH_RULE `~(m + 1 <= m)`];
14354     ASM_SIMP_TAC[IN_ELIM_THM; LAMBDA_BETA; DOT_BASIS; LE_REFL; CART_EQ;
14355                  ARITH_RULE `1 <= n + 1`] THEN
14356     GEN_TAC THEN DISCH_TAC THEN X_GEN_TAC `i:num` THEN
14357     ASM_CASES_TAC `i = dimindex(:M) + 1` THEN ASM_REWRITE_TAC[COND_ID] THEN
14358     COND_CASES_TAC THEN REWRITE_TAC[] THEN ASM_ARITH_TAC;
14359     ASM_SIMP_TAC[LAMBDA_BETA; CART_EQ; IN_UNIV; LE_REFL;
14360                  ARITH_RULE `i <= n ==> i <= n + 1`]]);;
14361
14362 (* ------------------------------------------------------------------------- *)
14363 (* "Isometry" (up to constant bounds) of injective linear map etc.           *)
14364 (* ------------------------------------------------------------------------- *)
14365
14366 let CAUCHY_ISOMETRIC = prove
14367  (`!f s e x.
14368         &0 < e /\ subspace s /\
14369         linear f /\ (!x. x IN s ==> norm(f x) >= e * norm(x)) /\
14370         (!n. x(n) IN s) /\ cauchy(f o x)
14371         ==> cauchy x`,
14372   REPEAT GEN_TAC THEN REWRITE_TAC[real_ge] THEN
14373   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
14374   REWRITE_TAC[CAUCHY; dist; o_THM] THEN
14375   FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_SUB th)]) THEN
14376   DISCH_THEN(fun th -> X_GEN_TAC `d:real` THEN DISCH_TAC THEN MP_TAC th) THEN
14377   DISCH_THEN(MP_TAC o SPEC `d * e`) THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
14378   ASM_MESON_TAC[REAL_LE_RDIV_EQ; REAL_MUL_SYM; REAL_LET_TRANS; SUBSPACE_SUB;
14379                 REAL_LT_LDIV_EQ]);;
14380
14381 let COMPLETE_ISOMETRIC_IMAGE = prove
14382  (`!f:real^M->real^N s e.
14383         &0 < e /\ subspace s /\
14384         linear f /\ (!x. x IN s ==> norm(f x) >= e * norm(x)) /\
14385         complete s
14386         ==> complete(IMAGE f s)`,
14387   REPEAT GEN_TAC THEN REWRITE_TAC[complete; EXISTS_IN_IMAGE] THEN
14388   STRIP_TAC THEN X_GEN_TAC `g:num->real^N` THEN
14389   REWRITE_TAC[IN_IMAGE; SKOLEM_THM; FORALL_AND_THM] THEN
14390   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
14391   DISCH_THEN(X_CHOOSE_THEN `x:num->real^M` MP_TAC) THEN
14392   GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [GSYM FUN_EQ_THM] THEN
14393   REWRITE_TAC[GSYM o_DEF] THEN
14394   DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
14395   FIRST_X_ASSUM(MP_TAC o SPEC `x:num->real^M`) THEN
14396   ASM_MESON_TAC[CAUCHY_ISOMETRIC; LINEAR_CONTINUOUS_AT;
14397                 CONTINUOUS_AT_SEQUENTIALLY]);;
14398
14399 let INJECTIVE_IMP_ISOMETRIC = prove
14400  (`!f:real^M->real^N s.
14401         closed s /\ subspace s /\
14402         linear f /\ (!x. x IN s /\ (f x = vec 0) ==> (x = vec 0))
14403         ==> ?e. &0 < e /\ !x. x IN s ==> norm(f x) >= e * norm(x)`,
14404   REPEAT STRIP_TAC THEN
14405   ASM_CASES_TAC `s SUBSET {vec 0 :real^M}` THENL
14406    [EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01; REAL_MUL_LID; real_ge] THEN
14407     ASM_MESON_TAC[SUBSET; IN_SING; NORM_0; LINEAR_0; REAL_LE_REFL];
14408     ALL_TAC] THEN
14409   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [SUBSET]) THEN
14410   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; IN_SING] THEN
14411   DISCH_THEN(X_CHOOSE_THEN `a:real^M` STRIP_ASSUME_TAC) THEN
14412   MP_TAC(ISPECL
14413    [`{(f:real^M->real^N) x | x IN s /\ norm(x) = norm(a:real^M)}`;
14414     `vec 0:real^N`] DISTANCE_ATTAINS_INF) THEN
14415   ANTS_TAC THENL
14416    [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
14417     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
14418     MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
14419     SUBST1_TAC(SET_RULE
14420      `{f x | x IN s /\ norm(x) = norm(a:real^M)} =
14421       IMAGE (f:real^M->real^N) (s INTER {x | norm x = norm a})`) THEN
14422     MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
14423     ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN
14424     MATCH_MP_TAC CLOSED_INTER_COMPACT THEN ASM_REWRITE_TAC[] THEN
14425     SUBGOAL_THEN
14426      `{x:real^M | norm x = norm(a:real^M)} = frontier(cball(vec 0,norm a))`
14427     SUBST1_TAC THENL
14428      [ASM_SIMP_TAC[FRONTIER_CBALL; NORM_POS_LT; dist; VECTOR_SUB_LZERO;
14429                    NORM_NEG; sphere];
14430       ASM_SIMP_TAC[COMPACT_FRONTIER; COMPACT_CBALL]];
14431     ALL_TAC] THEN
14432   ONCE_REWRITE_TAC[SET_RULE `{f x | P x} = IMAGE f {x | P x}`] THEN
14433   REWRITE_TAC[FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
14434   DISCH_THEN(X_CHOOSE_THEN `b:real^M` MP_TAC) THEN
14435   REWRITE_TAC[IN_ELIM_THM; dist; VECTOR_SUB_LZERO; NORM_NEG] THEN
14436   STRIP_TAC THEN REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE] THEN
14437   EXISTS_TAC `norm((f:real^M->real^N) b) / norm(b)` THEN CONJ_TAC THENL
14438    [ASM_MESON_TAC[REAL_LT_DIV; NORM_POS_LT; NORM_EQ_0]; ALL_TAC] THEN
14439   X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
14440   ASM_CASES_TAC `x:real^M = vec 0` THENL
14441    [FIRST_ASSUM(fun th -> ASM_REWRITE_TAC[MATCH_MP LINEAR_0 th]) THEN
14442     REWRITE_TAC[NORM_0; REAL_MUL_RZERO; real_ge; REAL_LE_REFL];
14443     ALL_TAC] THEN
14444   FIRST_X_ASSUM(MP_TAC o SPEC `(norm(a:real^M) / norm(x)) % x:real^M`) THEN
14445   ANTS_TAC THENL
14446    [ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
14447     ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN ASM_MESON_TAC[subspace];
14448     ALL_TAC] THEN
14449   FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP LINEAR_CMUL th]) THEN
14450   ASM_REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; real_ge] THEN
14451   ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ; NORM_POS_LT] THEN
14452   REWRITE_TAC[real_div; REAL_MUL_AC]);;
14453
14454 let CLOSED_INJECTIVE_IMAGE_SUBSPACE = prove
14455  (`!f s. subspace s /\
14456          linear f /\
14457          (!x. x IN s /\ f(x) = vec 0 ==> x = vec 0) /\
14458          closed s
14459          ==> closed(IMAGE f s)`,
14460   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM COMPLETE_EQ_CLOSED] THEN
14461   MATCH_MP_TAC COMPLETE_ISOMETRIC_IMAGE THEN
14462   ASM_REWRITE_TAC[COMPLETE_EQ_CLOSED] THEN
14463   MATCH_MP_TAC INJECTIVE_IMP_ISOMETRIC THEN
14464   ASM_REWRITE_TAC[]);;
14465
14466 (* ------------------------------------------------------------------------- *)
14467 (* Relating linear images to open/closed/interior/closure.                   *)
14468 (* ------------------------------------------------------------------------- *)
14469
14470 let OPEN_SURJECTIVE_LINEAR_IMAGE = prove
14471  (`!f:real^M->real^N.
14472         linear f /\ (!y. ?x. f x = y)
14473         ==> !s. open s ==> open(IMAGE f s)`,
14474   GEN_TAC THEN STRIP_TAC THEN
14475   REWRITE_TAC[open_def; FORALL_IN_IMAGE] THEN
14476   FIRST_ASSUM(MP_TAC o GEN `k:num` o SPEC `basis k:real^N`) THEN
14477   REWRITE_TAC[SKOLEM_THM] THEN
14478   DISCH_THEN(X_CHOOSE_THEN `b:num->real^M` STRIP_ASSUME_TAC) THEN
14479   SUBGOAL_THEN `bounded(IMAGE (b:num->real^M) (1..dimindex(:N)))` MP_TAC THENL
14480    [SIMP_TAC[FINITE_IMP_BOUNDED; FINITE_IMAGE; FINITE_NUMSEG]; ALL_TAC] THEN
14481   REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE; IN_NUMSEG] THEN
14482   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
14483   X_GEN_TAC `s:real^M->bool` THEN MATCH_MP_TAC MONO_FORALL THEN
14484   X_GEN_TAC `x:real^M` THEN ASM_CASES_TAC `(x:real^M) IN s` THEN
14485   ASM_REWRITE_TAC[] THEN
14486   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
14487   EXISTS_TAC `e / B / &(dimindex(:N))` THEN
14488   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; DIMINDEX_GE_1; LE_1] THEN
14489   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_IMAGE] THEN
14490   ABBREV_TAC `u = y - (f:real^M->real^N) x` THEN
14491   EXISTS_TAC `x + vsum(1..dimindex(:N)) (\i. (u:real^N)$i % b i):real^M` THEN
14492   ASM_SIMP_TAC[LINEAR_ADD; LINEAR_VSUM; FINITE_NUMSEG; o_DEF;
14493                LINEAR_CMUL; BASIS_EXPANSION] THEN
14494   CONJ_TAC THENL [EXPAND_TAC "u" THEN VECTOR_ARITH_TAC; ALL_TAC] THEN
14495   FIRST_X_ASSUM MATCH_MP_TAC THEN
14496   REWRITE_TAC[NORM_ARITH `dist(x + y,x) = norm y`] THEN
14497   MATCH_MP_TAC REAL_LET_TRANS THEN
14498   EXISTS_TAC `(dist(y,(f:real^M->real^N) x) * &(dimindex(:N))) * B` THEN
14499   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; DIMINDEX_GE_1; LE_1] THEN
14500   MATCH_MP_TAC VSUM_NORM_TRIANGLE THEN REWRITE_TAC[FINITE_NUMSEG] THEN
14501   ONCE_REWRITE_TAC[REAL_ARITH `(a * b) * c:real = b * a * c`] THEN
14502   GEN_REWRITE_TAC(RAND_CONV o LAND_CONV o RAND_CONV) [GSYM CARD_NUMSEG_1] THEN
14503   MATCH_MP_TAC SUM_BOUND THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
14504   X_GEN_TAC `k:num` THEN STRIP_TAC THEN REWRITE_TAC[NORM_MUL; dist] THEN
14505   MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS; NORM_POS_LE] THEN
14506   ASM_SIMP_TAC[COMPONENT_LE_NORM]);;
14507
14508 let OPEN_BIJECTIVE_LINEAR_IMAGE_EQ = prove
14509  (`!f:real^M->real^N s.
14510         linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
14511         ==> (open(IMAGE f s) <=> open s)`,
14512   REPEAT STRIP_TAC THEN EQ_TAC THENL
14513    [DISCH_TAC; ASM_MESON_TAC[OPEN_SURJECTIVE_LINEAR_IMAGE]] THEN
14514   SUBGOAL_THEN `s = {x | (f:real^M->real^N) x IN IMAGE f s}`
14515   SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
14516   MATCH_MP_TAC CONTINUOUS_OPEN_PREIMAGE_UNIV THEN
14517   ASM_SIMP_TAC[LINEAR_CONTINUOUS_AT]);;
14518
14519 add_linear_invariants [OPEN_BIJECTIVE_LINEAR_IMAGE_EQ];;
14520
14521 let CLOSED_INJECTIVE_LINEAR_IMAGE = prove
14522  (`!f:real^M->real^N.
14523         linear f /\ (!x y. f x = f y ==> x = y)
14524         ==> !s. closed s ==> closed(IMAGE f s)`,
14525   REPEAT STRIP_TAC THEN
14526   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_LEFT_INVERSE) THEN
14527   ASM_REWRITE_TAC[] THEN
14528   DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^M` STRIP_ASSUME_TAC) THEN
14529   MATCH_MP_TAC CLOSED_IN_CLOSED_TRANS THEN
14530   EXISTS_TAC `IMAGE (f:real^M->real^N) (:real^M)` THEN
14531   CONJ_TAC THENL
14532    [MP_TAC(ISPECL [`g:real^N->real^M`; `IMAGE (f:real^M->real^N) (:real^M)`;
14533                    `IMAGE (g:real^N->real^M) (IMAGE (f:real^M->real^N) s)`]
14534         CONTINUOUS_CLOSED_IN_PREIMAGE) THEN
14535     ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN ANTS_TAC THENL
14536      [ASM_REWRITE_TAC[GSYM IMAGE_o; IMAGE_I]; ALL_TAC] THEN
14537     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
14538     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [FUN_EQ_THM]) THEN
14539     REWRITE_TAC[EXTENSION; o_THM; I_THM] THEN SET_TAC[];
14540     MATCH_MP_TAC CLOSED_INJECTIVE_IMAGE_SUBSPACE THEN
14541     ASM_REWRITE_TAC[IN_UNIV; SUBSPACE_UNIV; CLOSED_UNIV] THEN
14542     X_GEN_TAC `x:real^M` THEN
14543     DISCH_THEN(MP_TAC o AP_TERM `g:real^N->real^M`) THEN
14544     RULE_ASSUM_TAC(REWRITE_RULE[FUN_EQ_THM; I_THM; o_THM]) THEN
14545     ASM_MESON_TAC[LINEAR_0]]);;
14546
14547 let CLOSED_INJECTIVE_LINEAR_IMAGE_EQ = prove
14548  (`!f:real^M->real^N s.
14549         linear f /\ (!x y. f x = f y ==> x = y)
14550         ==> (closed(IMAGE f s) <=> closed s)`,
14551   REPEAT STRIP_TAC THEN EQ_TAC THENL
14552    [DISCH_TAC; ASM_MESON_TAC[CLOSED_INJECTIVE_LINEAR_IMAGE]] THEN
14553   SUBGOAL_THEN `s = {x | (f:real^M->real^N) x IN IMAGE f s}`
14554   SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
14555   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
14556   ASM_SIMP_TAC[LINEAR_CONTINUOUS_AT]);;
14557
14558 add_linear_invariants [CLOSED_INJECTIVE_LINEAR_IMAGE_EQ];;
14559
14560 let CLOSURE_LINEAR_IMAGE_SUBSET = prove
14561  (`!f:real^M->real^N s.
14562         linear f ==> IMAGE f (closure s) SUBSET closure(IMAGE f s)`,
14563   REPEAT STRIP_TAC THEN
14564   MATCH_MP_TAC IMAGE_CLOSURE_SUBSET THEN
14565   ASM_SIMP_TAC[CLOSED_CLOSURE; CLOSURE_SUBSET; LINEAR_CONTINUOUS_ON]);;
14566
14567 let CLOSURE_INJECTIVE_LINEAR_IMAGE  = prove
14568  (`!f:real^M->real^N s.
14569         linear f /\ (!x y. f x = f y ==> x = y)
14570         ==> closure(IMAGE f s) = IMAGE f (closure s)`,
14571   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
14572   ASM_SIMP_TAC[CLOSURE_LINEAR_IMAGE_SUBSET] THEN
14573   MATCH_MP_TAC CLOSURE_MINIMAL THEN
14574   SIMP_TAC[CLOSURE_SUBSET; IMAGE_SUBSET] THEN
14575   ASM_MESON_TAC[CLOSED_INJECTIVE_LINEAR_IMAGE; CLOSED_CLOSURE]);;
14576
14577 add_linear_invariants [CLOSURE_INJECTIVE_LINEAR_IMAGE];;
14578
14579 let CLOSURE_BOUNDED_LINEAR_IMAGE = prove
14580  (`!f:real^M->real^N s.
14581         linear f /\ bounded s
14582         ==> closure(IMAGE f s) = IMAGE f (closure s)`,
14583   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
14584   ASM_SIMP_TAC[CLOSURE_LINEAR_IMAGE_SUBSET] THEN
14585   MATCH_MP_TAC CLOSURE_MINIMAL THEN
14586   SIMP_TAC[CLOSURE_SUBSET; IMAGE_SUBSET] THEN
14587   MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
14588   MATCH_MP_TAC COMPACT_LINEAR_IMAGE THEN
14589   ASM_REWRITE_TAC[COMPACT_CLOSURE]);;
14590
14591 let LINEAR_INTERIOR_IMAGE_SUBSET = prove
14592  (`!f:real^M->real^N s.
14593         linear f /\ (!x y. f x = f y ==> x = y)
14594        ==> interior(IMAGE f s) SUBSET IMAGE f (interior s)`,
14595   MESON_TAC[INTERIOR_IMAGE_SUBSET; LINEAR_CONTINUOUS_AT]);;
14596
14597 let LINEAR_IMAGE_SUBSET_INTERIOR = prove
14598  (`!f:real^M->real^N s.
14599         linear f /\ (!y. ?x. f x = y)
14600         ==> IMAGE f (interior s) SUBSET interior(IMAGE f s)`,
14601   REPEAT STRIP_TAC THEN MATCH_MP_TAC INTERIOR_MAXIMAL THEN
14602   ASM_SIMP_TAC[OPEN_SURJECTIVE_LINEAR_IMAGE; OPEN_INTERIOR;
14603                IMAGE_SUBSET; INTERIOR_SUBSET]);;
14604
14605 let INTERIOR_BIJECTIVE_LINEAR_IMAGE = prove
14606  (`!f:real^M->real^N s.
14607         linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
14608         ==> interior(IMAGE f s) = IMAGE f (interior s)`,
14609   REWRITE_TAC[interior] THEN GEOM_TRANSFORM_TAC[]);;
14610
14611 add_linear_invariants [INTERIOR_BIJECTIVE_LINEAR_IMAGE];;
14612
14613 let FRONTIER_BIJECTIVE_LINEAR_IMAGE = prove
14614  (`!f:real^M->real^N s.
14615         linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
14616         ==> frontier(IMAGE f s) = IMAGE f (frontier s)`,
14617   REWRITE_TAC[frontier] THEN GEOM_TRANSFORM_TAC[]);;
14618
14619 add_linear_invariants [FRONTIER_BIJECTIVE_LINEAR_IMAGE];;
14620
14621 (* ------------------------------------------------------------------------- *)
14622 (* Corollaries, reformulations and special cases for M = N.                  *)
14623 (* ------------------------------------------------------------------------- *)
14624
14625 let IN_INTERIOR_LINEAR_IMAGE = prove
14626  (`!f:real^M->real^N g s x.
14627         linear f /\ linear g /\ (f o g = I) /\ x IN interior s
14628         ==> (f x) IN interior (IMAGE f s)`,
14629   REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN REPEAT STRIP_TAC THEN
14630   MP_TAC(ISPECL [`f:real^M->real^N`; `s:real^M->bool`]
14631     LINEAR_IMAGE_SUBSET_INTERIOR) THEN
14632   ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
14633   ASM_MESON_TAC[]);;
14634
14635 let LINEAR_OPEN_MAPPING = prove
14636  (`!f:real^M->real^N g.
14637         linear f /\ linear g /\ (f o g = I)
14638         ==> !s. open s ==> open(IMAGE f s)`,
14639   REPEAT GEN_TAC THEN REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN DISCH_TAC THEN
14640   MATCH_MP_TAC OPEN_SURJECTIVE_LINEAR_IMAGE THEN
14641   ASM_MESON_TAC[]);;
14642
14643 let INTERIOR_INJECTIVE_LINEAR_IMAGE = prove
14644  (`!f:real^N->real^N s.
14645         linear f /\ (!x y. f x = f y ==> x = y)
14646         ==> interior(IMAGE f s) = IMAGE f (interior s)`,
14647   REPEAT STRIP_TAC THEN MATCH_MP_TAC INTERIOR_BIJECTIVE_LINEAR_IMAGE THEN
14648   ASM_MESON_TAC[LINEAR_INJECTIVE_IMP_SURJECTIVE]);;
14649
14650 let INTERIOR_SURJECTIVE_LINEAR_IMAGE = prove
14651  (`!f:real^N->real^N s.
14652         linear f /\ (!y. ?x. f x = y)
14653         ==> interior(IMAGE f s) = IMAGE f (interior s)`,
14654   REPEAT STRIP_TAC THEN MATCH_MP_TAC INTERIOR_BIJECTIVE_LINEAR_IMAGE THEN
14655   ASM_MESON_TAC[LINEAR_SURJECTIVE_IMP_INJECTIVE]);;
14656
14657 let CLOSURE_SURJECTIVE_LINEAR_IMAGE = prove
14658  (`!f:real^N->real^N s.
14659         linear f /\ (!y. ?x. f x = y)
14660         ==> closure(IMAGE f s) = IMAGE f (closure s)`,
14661   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_INJECTIVE_LINEAR_IMAGE THEN
14662   ASM_MESON_TAC[LINEAR_SURJECTIVE_IMP_INJECTIVE]);;
14663
14664 let FRONTIER_INJECTIVE_LINEAR_IMAGE = prove
14665  (`!f:real^N->real^N s.
14666         linear f /\ (!x y. f x = f y ==> x = y)
14667         ==> frontier(IMAGE f s) = IMAGE f (frontier s)`,
14668   REPEAT STRIP_TAC THEN MATCH_MP_TAC FRONTIER_BIJECTIVE_LINEAR_IMAGE THEN
14669   ASM_MESON_TAC[LINEAR_INJECTIVE_IMP_SURJECTIVE]);;
14670
14671 let FRONTIER_SURJECTIVE_LINEAR_IMAGE = prove
14672  (`!f:real^N->real^N.
14673         linear f /\ (!y. ?x. f x = y)
14674         ==> frontier(IMAGE f s) = IMAGE f (frontier s)`,
14675   REPEAT STRIP_TAC THEN MATCH_MP_TAC FRONTIER_BIJECTIVE_LINEAR_IMAGE THEN
14676   ASM_MESON_TAC[LINEAR_SURJECTIVE_IMP_INJECTIVE]);;
14677
14678 let COMPLETE_INJECTIVE_LINEAR_IMAGE = prove
14679  (`!f:real^M->real^N.
14680         linear f /\ (!x y. f x = f y ==> x = y)
14681         ==> !s. complete s ==> complete(IMAGE f s)`,
14682   REWRITE_TAC[COMPLETE_EQ_CLOSED; CLOSED_INJECTIVE_LINEAR_IMAGE]);;
14683
14684 let COMPLETE_INJECTIVE_LINEAR_IMAGE_EQ = prove
14685  (`!f:real^M->real^N s.
14686         linear f /\ (!x y. f x = f y ==> x = y)
14687         ==> (complete(IMAGE f s) <=> complete s)`,
14688   REWRITE_TAC[COMPLETE_EQ_CLOSED; CLOSED_INJECTIVE_LINEAR_IMAGE_EQ]);;
14689
14690 add_linear_invariants [COMPLETE_INJECTIVE_LINEAR_IMAGE_EQ];;
14691
14692 let LIMPT_INJECTIVE_LINEAR_IMAGE_EQ = prove
14693  (`!f:real^M->real^N s.
14694         linear f /\ (!x y. f x = f y ==> x = y)
14695         ==> ((f x) limit_point_of (IMAGE f s) <=> x limit_point_of s)`,
14696   REWRITE_TAC[LIMPT_APPROACHABLE; EXISTS_IN_IMAGE] THEN
14697   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN
14698   DISCH_TAC THENL
14699    [MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_BOUNDED_BELOW_POS);
14700     MP_TAC(ISPEC `f:real^M->real^N` LINEAR_BOUNDED_POS)] THEN
14701   ASM_REWRITE_TAC[] THEN
14702   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THENL
14703    [FIRST_X_ASSUM(MP_TAC o SPEC `e * B:real`);
14704     FIRST_X_ASSUM(MP_TAC o SPEC `e / B:real`)] THEN
14705   ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_MUL; dist; GSYM LINEAR_SUB] THEN
14706   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
14707   REPEAT(MATCH_MP_TAC MONO_AND THEN
14708          CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC]) THEN
14709   ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ] THEN
14710   MATCH_MP_TAC(REAL_ARITH `a <= b ==> b < x ==> a < x`) THEN
14711   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN ASM_SIMP_TAC[REAL_LE_RDIV_EQ]);;
14712
14713 add_linear_invariants [LIMPT_INJECTIVE_LINEAR_IMAGE_EQ];;
14714
14715 let LIMPT_TRANSLATION_EQ = prove
14716  (`!a s x. (a + x) limit_point_of (IMAGE (\y. a + y) s) <=> x limit_point_of s`,
14717   REWRITE_TAC[limit_point_of] THEN GEOM_TRANSLATE_TAC[]);;
14718
14719 add_translation_invariants [LIMPT_TRANSLATION_EQ];;
14720
14721 let OPEN_OPEN_LEFT_PROJECTION = prove
14722  (`!s t:real^(M,N)finite_sum->bool.
14723         open s /\ open t ==> open {x | x IN s /\ ?y. pastecart x y IN t}`,
14724   REPEAT STRIP_TAC THEN
14725   SUBGOAL_THEN
14726    `{x | x IN s /\ ?y. (pastecart x y:real^(M,N)finite_sum) IN t} =
14727     s INTER IMAGE fstcart t`
14728   SUBST1_TAC THENL
14729    [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_INTER; IN_IMAGE] THEN
14730     MESON_TAC[FSTCART_PASTECART; PASTECART_FST_SND];
14731     MATCH_MP_TAC OPEN_INTER THEN ASM_REWRITE_TAC[] THEN
14732     MATCH_MP_TAC(REWRITE_RULE[IMP_IMP; RIGHT_IMP_FORALL_THM]
14733       OPEN_SURJECTIVE_LINEAR_IMAGE) THEN
14734     ASM_REWRITE_TAC[LINEAR_FSTCART] THEN MESON_TAC[FSTCART_PASTECART]]);;
14735
14736 let OPEN_OPEN_RIGHT_PROJECTION = prove
14737  (`!s t:real^(M,N)finite_sum->bool.
14738         open s /\ open t ==> open {y | y IN s /\ ?x. pastecart x y IN t}`,
14739   REPEAT STRIP_TAC THEN
14740   SUBGOAL_THEN
14741    `{y | y IN s /\ ?x. (pastecart x y:real^(M,N)finite_sum) IN t} =
14742     s INTER IMAGE sndcart t`
14743   SUBST1_TAC THENL
14744    [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_INTER; IN_IMAGE] THEN
14745     MESON_TAC[SNDCART_PASTECART; PASTECART_FST_SND];
14746     MATCH_MP_TAC OPEN_INTER THEN ASM_REWRITE_TAC[] THEN
14747     MATCH_MP_TAC(REWRITE_RULE[IMP_IMP; RIGHT_IMP_FORALL_THM]
14748       OPEN_SURJECTIVE_LINEAR_IMAGE) THEN
14749     ASM_REWRITE_TAC[LINEAR_SNDCART] THEN MESON_TAC[SNDCART_PASTECART]]);;
14750
14751 (* ------------------------------------------------------------------------- *)
14752 (* Even more special cases.                                                  *)
14753 (* ------------------------------------------------------------------------- *)
14754
14755 let INTERIOR_NEGATIONS = prove
14756  (`!s. interior(IMAGE (--) s) = IMAGE (--) (interior s)`,
14757   GEN_TAC THEN MATCH_MP_TAC INTERIOR_INJECTIVE_LINEAR_IMAGE THEN
14758   REWRITE_TAC[linear] THEN REPEAT CONJ_TAC THEN VECTOR_ARITH_TAC);;
14759
14760 let SYMMETRIC_INTERIOR = prove
14761  (`!s:real^N->bool.
14762         (!x. x IN s ==> --x IN s)
14763         ==> !x. x IN interior s ==> (--x) IN interior s`,
14764   REPEAT GEN_TAC THEN DISCH_TAC THEN GEN_TAC THEN
14765   DISCH_THEN(MP_TAC o MATCH_MP(ISPEC `(--):real^N->real^N` FUN_IN_IMAGE)) THEN
14766   REWRITE_TAC[GSYM INTERIOR_NEGATIONS] THEN
14767   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
14768   REWRITE_TAC[EXTENSION; IN_IMAGE] THEN ASM_MESON_TAC[VECTOR_NEG_NEG]);;
14769
14770 let CLOSURE_NEGATIONS = prove
14771  (`!s. closure(IMAGE (--) s) = IMAGE (--) (closure s)`,
14772   GEN_TAC THEN MATCH_MP_TAC CLOSURE_INJECTIVE_LINEAR_IMAGE THEN
14773   REWRITE_TAC[linear] THEN REPEAT CONJ_TAC THEN VECTOR_ARITH_TAC);;
14774
14775 let SYMMETRIC_CLOSURE = prove
14776  (`!s:real^N->bool.
14777         (!x. x IN s ==> --x IN s)
14778         ==> !x. x IN closure s ==> (--x) IN closure s`,
14779   REPEAT GEN_TAC THEN DISCH_TAC THEN GEN_TAC THEN
14780   DISCH_THEN(MP_TAC o MATCH_MP(ISPEC `(--):real^N->real^N` FUN_IN_IMAGE)) THEN
14781   REWRITE_TAC[GSYM CLOSURE_NEGATIONS] THEN
14782   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
14783   REWRITE_TAC[EXTENSION; IN_IMAGE] THEN ASM_MESON_TAC[VECTOR_NEG_NEG]);;
14784
14785 (* ------------------------------------------------------------------------- *)
14786 (* Some properties of a canonical subspace.                                  *)
14787 (* ------------------------------------------------------------------------- *)
14788
14789 let SUBSPACE_SUBSTANDARD = prove
14790  (`!d. subspace
14791          {x:real^N | !i. d < i /\ i <= dimindex(:N) ==> x$i = &0}`,
14792   GEN_TAC THEN ASM_CASES_TAC `d <= dimindex(:N)` THENL
14793    [MP_TAC(ARITH_RULE `!i. d < i ==> 1 <= i`) THEN
14794     SIMP_TAC[subspace; IN_ELIM_THM; REAL_MUL_RZERO; REAL_ADD_LID;
14795              VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT; VEC_COMPONENT];
14796     ASM_SIMP_TAC[ARITH_RULE `~(d:num <= e) ==> (d < i /\ i <= e <=> F)`] THEN
14797     REWRITE_TAC[SET_RULE `{x | T} = UNIV`; SUBSPACE_UNIV]]);;
14798
14799 let CLOSED_SUBSTANDARD = prove
14800  (`!d. closed
14801         {x:real^N | !i. d < i /\ i <= dimindex(:N) ==> x$i = &0}`,
14802   GEN_TAC THEN
14803   SUBGOAL_THEN
14804    `{x:real^N | !i. d < i /\ i <= dimindex(:N) ==> x$i = &0} =
14805     INTERS {{x | basis i dot x = &0} | d < i /\ i <= dimindex(:N)}`
14806   SUBST1_TAC THENL
14807    [ALL_TAC;
14808     SIMP_TAC[CLOSED_INTERS; CLOSED_HYPERPLANE; IN_ELIM_THM;
14809              LEFT_IMP_EXISTS_THM]] THEN
14810   GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[IN_INTERS; IN_ELIM_THM] THEN
14811   SIMP_TAC[LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN
14812   MP_TAC(ARITH_RULE `!i. d < i ==> 1 <= i`) THEN
14813   SIMP_TAC[DOT_BASIS] THEN MESON_TAC[]);;
14814
14815 let DIM_SUBSTANDARD = prove
14816  (`!d. d <= dimindex(:N)
14817        ==> (dim {x:real^N | !i. d < i /\ i <= dimindex(:N)
14818                                 ==> x$i = &0} =
14819             d)`,
14820   REPEAT STRIP_TAC THEN MATCH_MP_TAC DIM_UNIQUE THEN
14821   EXISTS_TAC `IMAGE (basis:num->real^N) (1..d)` THEN REPEAT CONJ_TAC THENL
14822    [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM; IN_NUMSEG] THEN
14823     MESON_TAC[BASIS_COMPONENT; ARITH_RULE `d < i ==> 1 <= i`; NOT_LT];
14824     ALL_TAC;
14825     MATCH_MP_TAC INDEPENDENT_MONO THEN
14826     EXISTS_TAC `{basis i :real^N | 1 <= i /\ i <= dimindex(:N)}` THEN
14827     REWRITE_TAC[INDEPENDENT_STDBASIS]THEN
14828     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM; IN_NUMSEG] THEN
14829     ASM_MESON_TAC[LE_TRANS];
14830     MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN REWRITE_TAC[HAS_SIZE_NUMSEG_1] THEN
14831     REWRITE_TAC[IN_NUMSEG] THEN ASM_MESON_TAC[LE_TRANS; BASIS_INJ]] THEN
14832   POP_ASSUM MP_TAC THEN SPEC_TAC(`d:num`,`d:num`) THEN
14833   INDUCT_TAC THENL
14834    [REWRITE_TAC[ARITH_RULE `0 < i <=> 1 <= i`; SPAN_STDBASIS] THEN
14835     SUBGOAL_THEN `IMAGE basis (1 .. 0) :real^N->bool = {}` SUBST1_TAC THENL
14836      [REWRITE_TAC[IMAGE_EQ_EMPTY; NUMSEG_EMPTY; ARITH]; ALL_TAC] THEN
14837     DISCH_TAC THEN REWRITE_TAC[SPAN_EMPTY; SUBSET; IN_ELIM_THM; IN_SING] THEN
14838     SIMP_TAC[CART_EQ; VEC_COMPONENT];
14839     ALL_TAC] THEN
14840   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o check (is_imp o concl)) THEN
14841   ASM_SIMP_TAC[ARITH_RULE `SUC d <= n ==> d <= n`] THEN
14842   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN DISCH_TAC THEN
14843   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
14844   FIRST_X_ASSUM(MP_TAC o SPEC `x - (x$(SUC d)) % basis(SUC d) :real^N`) THEN
14845   ANTS_TAC THENL
14846    [X_GEN_TAC `i:num` THEN STRIP_TAC THEN
14847     FIRST_ASSUM(ASSUME_TAC o MATCH_MP(ARITH_RULE `d < i ==> 1 <= i`)) THEN
14848     ASM_SIMP_TAC[VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT] THEN
14849     ASM_SIMP_TAC[BASIS_COMPONENT] THEN COND_CASES_TAC THEN
14850     ASM_REWRITE_TAC[REAL_MUL_RID; REAL_SUB_REFL] THEN
14851     ASM_REWRITE_TAC[REAL_MUL_RZERO; REAL_SUB_RZERO] THEN
14852     ASM_MESON_TAC[ARITH_RULE `d < i /\ ~(i = SUC d) ==> SUC d < i`];
14853     ALL_TAC] THEN
14854   DISCH_TAC THEN
14855   SUBST1_TAC(VECTOR_ARITH
14856    `x = (x - (x$(SUC d)) % basis(SUC d)) +
14857         x$(SUC d) % basis(SUC d) :real^N`) THEN
14858   MATCH_MP_TAC SPAN_ADD THEN CONJ_TAC THENL
14859    [ASM_MESON_TAC[SPAN_MONO; SUBSET_IMAGE; SUBSET; SUBSET_NUMSEG; LE_REFL; LE];
14860     MATCH_MP_TAC SPAN_MUL THEN MATCH_MP_TAC SPAN_SUPERSET THEN
14861     REWRITE_TAC[IN_IMAGE; IN_NUMSEG] THEN
14862     MESON_TAC[LE_REFL; ARITH_RULE `1 <= SUC d`]]);;
14863
14864 (* ------------------------------------------------------------------------- *)
14865 (* Hence closure and completeness of all subspaces.                          *)
14866 (* ------------------------------------------------------------------------- *)
14867
14868 let CLOSED_SUBSPACE = prove
14869  (`!s:real^N->bool. subspace s ==> closed s`,
14870   REPEAT STRIP_TAC THEN ABBREV_TAC `d = dim(s:real^N->bool)` THEN
14871   MP_TAC(MATCH_MP DIM_SUBSTANDARD
14872     (ISPEC `s:real^N->bool` DIM_SUBSET_UNIV)) THEN
14873   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
14874   MP_TAC(ISPECL
14875    [`{x:real^N | !i. d < i /\ i <= dimindex(:N)
14876                                 ==> x$i = &0}`;
14877     `s:real^N->bool`] SUBSPACE_ISOMORPHISM) THEN
14878   ASM_REWRITE_TAC[SUBSPACE_SUBSTANDARD] THEN
14879   DISCH_THEN(X_CHOOSE_THEN `f:real^N->real^N` MP_TAC) THEN
14880   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
14881   DISCH_THEN(CONJUNCTS_THEN2 (SUBST_ALL_TAC o SYM) STRIP_ASSUME_TAC) THEN
14882   MATCH_MP_TAC(ISPEC `f:real^N->real^N` CLOSED_INJECTIVE_IMAGE_SUBSPACE) THEN
14883   ASM_REWRITE_TAC[SUBSPACE_SUBSTANDARD; CLOSED_SUBSTANDARD] THEN
14884   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
14885   ASM_REWRITE_TAC[] THEN
14886   CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[LINEAR_0]] THEN
14887   REWRITE_TAC[IN_ELIM_THM] THEN
14888   ASM_MESON_TAC[VEC_COMPONENT; ARITH_RULE `d < i ==> 1 <= i`]);;
14889
14890 let COMPLETE_SUBSPACE = prove
14891  (`!s:real^N->bool. subspace s ==> complete s`,
14892   REWRITE_TAC[COMPLETE_EQ_CLOSED; CLOSED_SUBSPACE]);;
14893
14894 let CLOSED_SPAN = prove
14895  (`!s. closed(span s)`,
14896   SIMP_TAC[CLOSED_SUBSPACE; SUBSPACE_SPAN]);;
14897
14898 let DIM_CLOSURE = prove
14899  (`!s:real^N->bool. dim(closure s) = dim s`,
14900   GEN_TAC THEN REWRITE_TAC[GSYM LE_ANTISYM] THEN CONJ_TAC THENL
14901    [GEN_REWRITE_TAC RAND_CONV [GSYM DIM_SPAN]; ALL_TAC] THEN
14902   MATCH_MP_TAC DIM_SUBSET THEN REWRITE_TAC[CLOSURE_SUBSET] THEN
14903   MATCH_MP_TAC CLOSURE_MINIMAL THEN
14904   SIMP_TAC[CLOSED_SUBSPACE; SUBSPACE_SPAN; SPAN_INC]);;
14905
14906 let CLOSED_BOUNDEDPREIM_CONTINUOUS_IMAGE = prove
14907  (`!f:real^M->real^N s.
14908       closed s /\ f continuous_on s /\
14909       (!e. bounded {x | x IN s /\ norm(f x) <= e})
14910       ==> closed(IMAGE f s)`,
14911   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSED_INTERS_COMPACT] THEN
14912   REWRITE_TAC[SET_RULE
14913    `cball(vec 0,e) INTER IMAGE (f:real^M->real^N) s =
14914     IMAGE f (s INTER {x | x IN s /\ f x IN cball(vec 0,e)})`] THEN
14915   X_GEN_TAC `e:real` THEN MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
14916   CONJ_TAC THENL
14917    [MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:real^M->bool` THEN
14918     ASM_REWRITE_TAC[] THEN SET_TAC[];
14919     MATCH_MP_TAC CLOSED_INTER_COMPACT THEN ASM_REWRITE_TAC[] THEN
14920     REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN CONJ_TAC THENL
14921      [ASM_REWRITE_TAC[IN_CBALL_0];
14922       ASM_SIMP_TAC[CONTINUOUS_CLOSED_PREIMAGE; CLOSED_CBALL]]]);;
14923
14924 let CLOSED_INJECTIVE_IMAGE_SUBSET_SUBSPACE = prove
14925  (`!f:real^M->real^N s t.
14926         closed s /\ s SUBSET t /\ subspace t /\
14927         linear f /\
14928         (!x. x IN t /\ f(x) = vec 0 ==> x = vec 0)
14929         ==> closed(IMAGE f s)`,
14930   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSED_BOUNDEDPREIM_CONTINUOUS_IMAGE THEN
14931   ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN
14932   MP_TAC(ISPECL [`f:real^M->real^N`; `t:real^M->bool`]
14933     INJECTIVE_IMP_ISOMETRIC) THEN
14934   ASM_SIMP_TAC[CLOSED_SUBSPACE; real_ge] THEN
14935   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
14936   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
14937   X_GEN_TAC `e:real` THEN MATCH_MP_TAC BOUNDED_SUBSET THEN
14938   EXISTS_TAC `cball(vec 0:real^M,e / B)` THEN
14939   REWRITE_TAC[BOUNDED_CBALL] THEN
14940   ASM_SIMP_TAC[SUBSET; IN_ELIM_THM; IN_CBALL_0; REAL_LE_RDIV_EQ] THEN
14941   ASM_MESON_TAC[SUBSET; REAL_LE_TRANS]);;
14942
14943 let BASIS_COORDINATES_LIPSCHITZ = prove
14944  (`!b:real^N->bool.
14945         independent b
14946         ==> ?B. &0 < B /\
14947                 !c v. v IN b
14948                       ==> abs(c v) <= B * norm(vsum b (\v. c(v) % v))`,
14949   X_GEN_TAC `k:real^N->bool` THEN DISCH_TAC THEN
14950   FIRST_ASSUM(STRIP_ASSUME_TAC o MATCH_MP INDEPENDENT_BOUND) THEN
14951   FIRST_ASSUM(X_CHOOSE_THEN `b:num->real^N` STRIP_ASSUME_TAC o
14952         GEN_REWRITE_RULE I [FINITE_INDEX_NUMSEG]) THEN
14953   ABBREV_TAC `n = CARD(k:real^N->bool)` THEN
14954   MP_TAC(ISPECL
14955    [`(\x. vsum(1..n) (\i. x$i % b i)):real^N->real^N`;
14956     `span(IMAGE basis (1..n)):real^N->bool`]
14957         INJECTIVE_IMP_ISOMETRIC) THEN
14958   REWRITE_TAC[SUBSPACE_SPAN] THEN ANTS_TAC THENL
14959    [CONJ_TAC THENL [SIMP_TAC[CLOSED_SUBSPACE; SUBSPACE_SPAN]; ALL_TAC] THEN
14960     CONJ_TAC THENL
14961      [MATCH_MP_TAC LINEAR_COMPOSE_VSUM THEN
14962       REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN REPEAT STRIP_TAC THEN
14963       MATCH_MP_TAC LINEAR_VMUL_COMPONENT THEN
14964       SIMP_TAC[LINEAR_ID] THEN ASM_ARITH_TAC;
14965       ALL_TAC] THEN
14966     X_GEN_TAC `x:real^N` THEN
14967     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
14968     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SPAN_IMAGE_BASIS]) THEN
14969     REWRITE_TAC[IN_NUMSEG] THEN DISCH_TAC THEN
14970     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
14971     DISCH_THEN(X_CHOOSE_TAC `c:real^N->num`) THEN
14972     SUBGOAL_THEN
14973      `vsum(1..n) (\i. (x:real^N)$i % b i:real^N) = vsum k (\v. x$(c v) % v)`
14974     SUBST1_TAC THENL
14975      [MATCH_MP_TAC VSUM_EQ_GENERAL_INVERSES THEN
14976       MAP_EVERY EXISTS_TAC [`b:num->real^N`; `c:real^N->num`] THEN
14977       ASM SET_TAC[];
14978       ALL_TAC] THEN
14979     DISCH_TAC THEN
14980     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INDEPENDENT_EXPLICIT]) THEN
14981     DISCH_THEN(MP_TAC o SPEC `\v:real^N. (x:real^N)$(c v)` o CONJUNCT2) THEN
14982     ASM_REWRITE_TAC[] THEN ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
14983     REWRITE_TAC[CART_EQ; FORALL_IN_IMAGE; VEC_COMPONENT] THEN
14984     ASM_MESON_TAC[IN_NUMSEG];
14985     ALL_TAC] THEN
14986   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
14987   EXISTS_TAC `inv(B:real)` THEN ASM_REWRITE_TAC[REAL_LT_INV_EQ] THEN
14988   ASM_REWRITE_TAC[FORALL_IN_IMAGE; IN_NUMSEG] THEN
14989   MAP_EVERY X_GEN_TAC [`c:real^N->real`; `j:num`] THEN STRIP_TAC THEN
14990   ONCE_REWRITE_TAC[REAL_ARITH `inv B * x = x / B`] THEN
14991   ASM_SIMP_TAC[REAL_LE_RDIV_EQ] THEN
14992   W(MP_TAC o PART_MATCH (lhs o rand) VSUM_IMAGE o rand o rand o snd) THEN
14993   ASM_REWRITE_TAC[FINITE_NUMSEG] THEN DISCH_THEN SUBST1_TAC THEN
14994   FIRST_X_ASSUM(MP_TAC o SPEC
14995    `(lambda i. if 1 <= i /\ i <= n then c(b i:real^N) else &0):real^N`) THEN
14996   SIMP_TAC[IN_SPAN_IMAGE_BASIS; LAMBDA_BETA] THEN
14997   ANTS_TAC THENL [MESON_TAC[IN_NUMSEG]; ALL_TAC] THEN
14998   MATCH_MP_TAC(REAL_ARITH `x = v /\ u <= y ==> x >= y ==> u <= v`) THEN
14999   CONJ_TAC THENL
15000    [AP_TERM_TAC THEN MATCH_MP_TAC VSUM_EQ_NUMSEG THEN
15001     SUBGOAL_THEN `!i. i <= n ==> i <= dimindex(:N)` MP_TAC THENL
15002      [ASM_ARITH_TAC; SIMP_TAC[LAMBDA_BETA] THEN DISCH_THEN(K ALL_TAC)] THEN
15003     REWRITE_TAC[o_THM];
15004     GEN_REWRITE_TAC RAND_CONV [REAL_MUL_SYM] THEN
15005     ASM_SIMP_TAC[REAL_LE_RMUL_EQ] THEN
15006     MP_TAC(ISPECL
15007      [`(lambda i. if 1 <= i /\ i <= n then c(b i:real^N) else &0):real^N`;
15008       `j:num`] COMPONENT_LE_NORM) THEN
15009     SUBGOAL_THEN `1 <= j /\ j <= dimindex(:N)` MP_TAC THENL
15010      [ASM_ARITH_TAC; SIMP_TAC[LAMBDA_BETA] THEN ASM_REWRITE_TAC[]]]);;
15011
15012 let BASIS_COORDINATES_CONTINUOUS = prove
15013  (`!b:real^N->bool e.
15014         independent b /\ &0 < e
15015         ==> ?d. &0 < d /\
15016                 !c. norm(vsum b (\v. c(v) % v)) < d
15017                     ==> !v. v IN b ==> abs(c v) < e`,
15018   REPEAT STRIP_TAC THEN
15019   FIRST_X_ASSUM(MP_TAC o MATCH_MP BASIS_COORDINATES_LIPSCHITZ) THEN
15020   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
15021   EXISTS_TAC `e / B:real` THEN ASM_SIMP_TAC[REAL_LT_DIV] THEN
15022   X_GEN_TAC `c:real^N->real` THEN DISCH_TAC THEN
15023   X_GEN_TAC `v:real^N` THEN DISCH_TAC THEN
15024   MATCH_MP_TAC REAL_LET_TRANS THEN
15025   EXISTS_TAC `B * norm(vsum b (\v:real^N. c v % v))` THEN
15026   ASM_SIMP_TAC[] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
15027   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ]);;
15028
15029 (* ------------------------------------------------------------------------- *)
15030 (* Affine transformations of intervals.                                      *)
15031 (* ------------------------------------------------------------------------- *)
15032
15033 let AFFINITY_INVERSES = prove
15034  (`!m c. ~(m = &0)
15035          ==> (\x. m % x + c) o (\x. inv(m) % x + (--(inv(m) % c))) = I /\
15036              (\x. inv(m) % x + (--(inv(m) % c))) o (\x. m % x + c) = I`,
15037   REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN
15038   REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_RNEG] THEN
15039   SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_MUL_RINV] THEN
15040   REPEAT STRIP_TAC THEN VECTOR_ARITH_TAC);;
15041
15042 let REAL_AFFINITY_LE = prove
15043  (`!m c x y. &0 < m ==> (m * x + c <= y <=> x <= inv(m) * y + --(c / m))`,
15044   REWRITE_TAC[REAL_ARITH `m * x + c <= y <=> x * m <= y - c`] THEN
15045   SIMP_TAC[GSYM REAL_LE_RDIV_EQ] THEN REAL_ARITH_TAC);;
15046
15047 let REAL_LE_AFFINITY = prove
15048  (`!m c x y. &0 < m ==> (y <= m * x + c <=> inv(m) * y + --(c / m) <= x)`,
15049   REWRITE_TAC[REAL_ARITH `y <= m * x + c <=> y - c <= x * m`] THEN
15050   SIMP_TAC[GSYM REAL_LE_LDIV_EQ] THEN REAL_ARITH_TAC);;
15051
15052 let REAL_AFFINITY_LT = prove
15053  (`!m c x y. &0 < m ==> (m * x + c < y <=> x < inv(m) * y + --(c / m))`,
15054   SIMP_TAC[REAL_LE_AFFINITY; GSYM REAL_NOT_LE]);;
15055
15056 let REAL_LT_AFFINITY = prove
15057  (`!m c x y. &0 < m ==> (y < m * x + c <=> inv(m) * y + --(c / m) < x)`,
15058   SIMP_TAC[REAL_AFFINITY_LE; GSYM REAL_NOT_LE]);;
15059
15060 let REAL_AFFINITY_EQ = prove
15061  (`!m c x y. ~(m = &0) ==> (m * x + c = y <=> x = inv(m) * y + --(c / m))`,
15062   CONV_TAC REAL_FIELD);;
15063
15064 let REAL_EQ_AFFINITY = prove
15065  (`!m c x y. ~(m = &0) ==> (y = m * x + c  <=> inv(m) * y + --(c / m) = x)`,
15066   CONV_TAC REAL_FIELD);;
15067
15068 let VECTOR_AFFINITY_EQ = prove
15069  (`!m c x y. ~(m = &0)
15070              ==> (m % x + c = y <=> x = inv(m) % y + --(inv(m) % c))`,
15071   SIMP_TAC[CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
15072            real_div; VECTOR_NEG_COMPONENT; REAL_AFFINITY_EQ] THEN
15073   REWRITE_TAC[REAL_MUL_AC]);;
15074
15075 let VECTOR_EQ_AFFINITY = prove
15076  (`!m c x y. ~(m = &0)
15077              ==> (y = m % x + c <=> inv(m) % y + --(inv(m) % c) = x)`,
15078   SIMP_TAC[CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
15079            real_div; VECTOR_NEG_COMPONENT; REAL_EQ_AFFINITY] THEN
15080   REWRITE_TAC[REAL_MUL_AC]);;
15081
15082 let IMAGE_AFFINITY_INTERVAL = prove
15083  (`!a b:real^N m c.
15084         IMAGE (\x. m % x + c) (interval[a,b]) =
15085             if interval[a,b] = {} then {}
15086             else if &0 <= m then interval[m % a + c,m % b + c]
15087             else interval[m % b + c,m % a + c]`,
15088   REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[IMAGE_CLAUSES] THEN
15089   ASM_CASES_TAC `m = &0` THEN ASM_REWRITE_TAC[REAL_LE_LT] THENL
15090    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_LID; COND_ID] THEN
15091     REWRITE_TAC[INTERVAL_SING] THEN ASM SET_TAC[];
15092     ALL_TAC] THEN
15093   FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
15094    `~(x = &0) ==> &0 < x \/ &0 < --x`)) THEN
15095   ASM_SIMP_TAC[EXTENSION; IN_IMAGE; REAL_ARITH `&0 < --x ==> ~(&0 < x)`] THENL
15096    [ALL_TAC;
15097     ONCE_REWRITE_TAC[VECTOR_ARITH `x = m % y + c <=> c = (--m) % y + x`]] THEN
15098   ASM_SIMP_TAC[VECTOR_EQ_AFFINITY; REAL_LT_IMP_NZ; UNWIND_THM1] THEN
15099   SIMP_TAC[IN_INTERVAL; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
15100            VECTOR_NEG_COMPONENT] THEN
15101   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_LT_INV_EQ]) THEN
15102   SIMP_TAC[REAL_AFFINITY_LE; REAL_LE_AFFINITY; real_div] THEN
15103   DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[REAL_INV_INV] THEN
15104   REWRITE_TAC[REAL_MUL_LNEG; REAL_NEGNEG] THEN
15105   ASM_SIMP_TAC[REAL_FIELD `&0 < m ==> (inv m * x) * m = x`] THEN
15106   GEN_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN AP_TERM_TAC THEN REAL_ARITH_TAC);;
15107
15108 (* ------------------------------------------------------------------------- *)
15109 (* Existence of eigenvectors. The proof is only in this file because it uses *)
15110 (* a few simple results about continuous functions (at least                 *)
15111 (* CONTINUOUS_ON_LIFT_DOT2, CONTINUOUS_ATTAINS_SUP and CLOSED_SUBSPACE).     *)
15112 (* ------------------------------------------------------------------------- *)
15113
15114 let SELF_ADJOINT_HAS_EIGENVECTOR_IN_SUBSPACE = prove
15115  (`!f:real^N->real^N s.
15116         linear f /\ adjoint f = f /\
15117         subspace s /\ ~(s = {vec 0}) /\ (!x. x IN s ==> f x IN s)
15118         ==> ?v c. v IN s /\ norm(v) = &1 /\ f(v) = c % v`,
15119   let lemma = prove
15120    (`!a b. (!x. a * x <= b * x pow 2) ==> &0 <= b ==> a = &0`,
15121     REPEAT GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[REAL_LE_LT] THEN
15122     ASM_CASES_TAC `b = &0` THEN ASM_REWRITE_TAC[] THENL
15123      [FIRST_X_ASSUM(fun t -> MP_TAC(SPEC `&1` t) THEN
15124         MP_TAC(SPEC `-- &1` t)) THEN ASM_REAL_ARITH_TAC;
15125       DISCH_TAC THEN  FIRST_X_ASSUM(MP_TAC o SPEC `a / &2 / b`) THEN
15126       ASM_SIMP_TAC[REAL_FIELD
15127        `&0 < b ==> (b * (a / b) pow 2) = a pow 2 / b`] THEN
15128       REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN SIMP_TAC[GSYM real_div] THEN
15129       ASM_SIMP_TAC[REAL_LE_DIV2_EQ] THEN
15130       REWRITE_TAC[REAL_LT_SQUARE; REAL_ARITH
15131         `(a * a) / &2 <= (a / &2) pow 2 <=> ~(&0 < a * a)`]]) in
15132   REPEAT STRIP_TAC THEN
15133   MP_TAC(ISPECL [`\x:real^N. (f x) dot x`;
15134                  `s INTER sphere(vec 0:real^N,&1)`]
15135         CONTINUOUS_ATTAINS_SUP) THEN
15136   REWRITE_TAC[EXISTS_IN_GSPEC; FORALL_IN_GSPEC; o_DEF] THEN ANTS_TAC THENL
15137    [ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_DOT2; LINEAR_CONTINUOUS_ON;
15138                    CONTINUOUS_ON_ID] THEN
15139     ASM_SIMP_TAC[COMPACT_SPHERE; CLOSED_INTER_COMPACT; CLOSED_SUBSPACE] THEN
15140     FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE
15141       `~(s = {a}) ==> a IN s ==> ?b. ~(b = a) /\ b IN s`)) THEN
15142     ASM_SIMP_TAC[SUBSPACE_0; IN_SPHERE_0; GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN
15143     DISCH_THEN(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
15144     EXISTS_TAC `inv(norm x) % x:real^N` THEN
15145     ASM_REWRITE_TAC[IN_ELIM_THM; VECTOR_SUB_RZERO; NORM_MUL] THEN
15146     ASM_SIMP_TAC[SUBSPACE_MUL; REAL_ABS_INV; REAL_ABS_NORM] THEN
15147     ASM_SIMP_TAC[REAL_MUL_LINV; NORM_EQ_0];
15148     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v:real^N` THEN
15149     REWRITE_TAC[IN_INTER; IN_SPHERE_0] THEN STRIP_TAC THEN
15150     ABBREV_TAC `c = (f:real^N->real^N) v dot v` THEN
15151     EXISTS_TAC `c:real` THEN ASM_REWRITE_TAC[]] THEN
15152   ABBREV_TAC `p = \x y:real^N. c * (x dot y) - (f x) dot y` THEN
15153   SUBGOAL_THEN `!x:real^N. x IN s ==> &0 <= p x x` (LABEL_TAC "POSDEF") THENL
15154    [X_GEN_TAC `x:real^N` THEN EXPAND_TAC "p" THEN REWRITE_TAC[] THEN
15155     ASM_CASES_TAC `x:real^N = vec 0` THEN DISCH_TAC THEN
15156     ASM_REWRITE_TAC[DOT_RZERO; REAL_MUL_RZERO; REAL_SUB_LE; REAL_LE_REFL] THEN
15157     FIRST_X_ASSUM(MP_TAC o SPEC `inv(norm x) % x:real^N`) THEN
15158     ASM_SIMP_TAC[SUBSPACE_MUL] THEN
15159     ASM_SIMP_TAC[LINEAR_CMUL; NORM_MUL; REAL_ABS_INV; DOT_RMUL] THEN
15160     ASM_SIMP_TAC[REAL_ABS_NORM; REAL_MUL_LINV; NORM_EQ_0; DOT_LMUL] THEN
15161     ASM_SIMP_TAC[GSYM REAL_LE_LDIV_EQ; DOT_POS_LT] THEN
15162     REWRITE_TAC[GSYM NORM_POW_2; real_div; REAL_INV_POW] THEN REAL_ARITH_TAC;
15163     ALL_TAC] THEN
15164   SUBGOAL_THEN `!y:real^N. y IN s ==> !a. p v y * a <= p y y * a pow 2`
15165   MP_TAC THENL
15166    [REPEAT STRIP_TAC THEN
15167     REMOVE_THEN "POSDEF" (MP_TAC o SPEC `v - (&2 * a) % y:real^N`) THEN
15168     EXPAND_TAC "p" THEN ASM_SIMP_TAC[SUBSPACE_SUB; SUBSPACE_MUL] THEN
15169     ASM_SIMP_TAC[LINEAR_SUB; LINEAR_CMUL] THEN
15170     REWRITE_TAC[DOT_LSUB; DOT_LMUL] THEN
15171     REWRITE_TAC[DOT_RSUB; DOT_RMUL] THEN
15172     SUBGOAL_THEN `f y dot (v:real^N) = f v dot y` SUBST1_TAC THENL
15173      [ASM_MESON_TAC[ADJOINT_CLAUSES; DOT_SYM]; ALL_TAC] THEN
15174     ASM_REWRITE_TAC[GSYM NORM_POW_2] THEN REWRITE_TAC[NORM_POW_2] THEN
15175     MATCH_MP_TAC(REAL_ARITH
15176         `&4 * (z - y) = x ==> &0 <= x ==> y <= z`) THEN
15177     REWRITE_TAC[DOT_SYM] THEN CONV_TAC REAL_RING;
15178     DISCH_THEN(MP_TAC o GEN `y:real^N` o DISCH `(y:real^N) IN s` o
15179       MATCH_MP lemma o C MP (ASSUME `(y:real^N) IN s`) o SPEC `y:real^N`) THEN
15180     ASM_SIMP_TAC[] THEN EXPAND_TAC "p" THEN
15181     REWRITE_TAC[GSYM DOT_LMUL; GSYM DOT_LSUB] THEN
15182     DISCH_THEN(MP_TAC o SPEC `c % v - f v:real^N`) THEN
15183     ASM_SIMP_TAC[SUBSPACE_MUL; SUBSPACE_SUB; DOT_EQ_0; VECTOR_SUB_EQ]]);;
15184
15185 let SELF_ADJOINT_HAS_EIGENVECTOR = prove
15186  (`!f:real^N->real^N.
15187         linear f /\ adjoint f = f ==> ?v c. norm(v) = &1 /\ f(v) = c % v`,
15188   REPEAT STRIP_TAC THEN
15189   MP_TAC(ISPECL [`f:real^N->real^N`; `(:real^N)`]
15190         SELF_ADJOINT_HAS_EIGENVECTOR_IN_SUBSPACE) THEN
15191   ASM_REWRITE_TAC[SUBSPACE_UNIV; IN_UNIV] THEN DISCH_THEN MATCH_MP_TAC THEN
15192   MATCH_MP_TAC(SET_RULE `!a. ~(a IN s) ==> ~(UNIV = s)`) THEN
15193   EXISTS_TAC `vec 1:real^N` THEN
15194   REWRITE_TAC[IN_SING; VEC_EQ; ARITH_EQ]);;
15195
15196 let SELF_ADJOINT_HAS_EIGENVECTOR_BASIS_OF_SUBSPACE = prove
15197  (`!f:real^N->real^N s.
15198         linear f /\ adjoint f = f /\
15199         subspace s /\ (!x. x IN s ==> f x IN s)
15200         ==> ?b. b SUBSET s /\
15201                 pairwise orthogonal b /\
15202                 (!x. x IN b ==> norm x = &1 /\ ?c. f(x) = c % x) /\
15203                 independent b /\
15204                 span b = s /\
15205                 b HAS_SIZE dim s`,
15206   let lemma = prove
15207    (`!f:real^N->real^N s.
15208           linear f /\ adjoint f = f /\ subspace s /\ (!x. x IN s ==> f x IN s)
15209           ==> ?b. b SUBSET s /\ b HAS_SIZE dim s /\
15210                   pairwise orthogonal b /\
15211                   (!x. x IN b ==> norm x = &1 /\ ?c. f(x) = c % x)`,
15212     REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN REWRITE_TAC[IMP_IMP] THEN
15213     GEN_TAC THEN STRIP_TAC THEN GEN_TAC THEN
15214     WF_INDUCT_TAC `dim(s:real^N->bool)` THEN STRIP_TAC THEN
15215     ASM_CASES_TAC `dim(s:real^N->bool) = 0` THENL
15216      [EXISTS_TAC `{}:real^N->bool` THEN
15217       ASM_SIMP_TAC[HAS_SIZE_CLAUSES; NOT_IN_EMPTY;
15218                    PAIRWISE_EMPTY; EMPTY_SUBSET];
15219       ALL_TAC] THEN
15220     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [DIM_EQ_0]) THEN
15221     DISCH_THEN(ASSUME_TAC o MATCH_MP (SET_RULE
15222      `~(s SUBSET {a}) ==> ~(s = {a})`)) THEN
15223     MP_TAC(ISPECL [`f:real^N->real^N`; `s:real^N->bool`]
15224       SELF_ADJOINT_HAS_EIGENVECTOR_IN_SUBSPACE) THEN
15225     ASM_REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN
15226     DISCH_THEN(X_CHOOSE_THEN `v:real^N` MP_TAC) THEN
15227     ASM_CASES_TAC `v:real^N = vec 0` THEN ASM_REWRITE_TAC[NORM_0] THEN
15228     CONV_TAC REAL_RAT_REDUCE_CONV THEN
15229     DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
15230     FIRST_X_ASSUM(MP_TAC o SPEC `{y:real^N | y IN s /\ orthogonal v y}`) THEN
15231     REWRITE_TAC[SUBSPACE_ORTHOGONAL_TO_VECTOR; IN_ELIM_THM] THEN
15232     MP_TAC(ISPECL [`span {v:real^N}`; `s:real^N->bool`]
15233           DIM_SUBSPACE_ORTHOGONAL_TO_VECTORS) THEN
15234     REWRITE_TAC[ONCE_REWRITE_RULE[ORTHOGONAL_SYM] ORTHOGONAL_TO_SPAN_EQ] THEN
15235     ASM_REWRITE_TAC[SUBSPACE_SPAN; IN_SING; FORALL_UNWIND_THM2] THEN
15236     ANTS_TAC THENL
15237      [MATCH_MP_TAC SPAN_SUBSET_SUBSPACE THEN ASM SET_TAC[];
15238       DISCH_THEN(SUBST1_TAC o SYM)] THEN
15239     ASM_REWRITE_TAC[DIM_SPAN; DIM_SING; ARITH_RULE `n < n + 1`] THEN
15240     ANTS_TAC THENL
15241      [REWRITE_TAC[SET_RULE `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
15242       ASM_SIMP_TAC[SUBSPACE_INTER; SUBSPACE_ORTHOGONAL_TO_VECTOR] THEN
15243       REWRITE_TAC[orthogonal] THEN X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
15244       MATCH_MP_TAC EQ_TRANS THEN
15245       EXISTS_TAC `(f:real^N->real^N) v dot x` THEN CONJ_TAC THENL
15246        [ASM_MESON_TAC[ADJOINT_CLAUSES];
15247         ASM_MESON_TAC[DOT_LMUL; REAL_MUL_RZERO]];
15248       DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC) THEN
15249       EXISTS_TAC `(v:real^N) INSERT b` THEN
15250       ASM_REWRITE_TAC[FORALL_IN_INSERT] THEN
15251       CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
15252       ASM_REWRITE_TAC[PAIRWISE_INSERT] THEN
15253       RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE; SUBSET; IN_ELIM_THM]) THEN
15254       CONJ_TAC THENL
15255        [ASM_SIMP_TAC[HAS_SIZE; FINITE_INSERT; CARD_CLAUSES] THEN
15256         COND_CASES_TAC THEN ASM_REWRITE_TAC[ADD1] THEN
15257         ASM_MESON_TAC[ORTHOGONAL_REFL];
15258         RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; IN_ELIM_THM]) THEN
15259         ASM_MESON_TAC[ORTHOGONAL_SYM]]]) in
15260   REPEAT STRIP_TAC THEN
15261   MP_TAC(ISPECL [`f:real^N->real^N`; `s:real^N->bool`] lemma) THEN
15262   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN
15263   X_GEN_TAC `b:real^N->bool` THEN
15264   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
15265   MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
15266    [MATCH_MP_TAC PAIRWISE_ORTHOGONAL_INDEPENDENT THEN
15267     ASM_MESON_TAC[NORM_ARITH `~(norm(vec 0:real^N) = &1)`];
15268     DISCH_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
15269      [ASM_MESON_TAC[SPAN_SUBSET_SUBSPACE];
15270       MATCH_MP_TAC CARD_GE_DIM_INDEPENDENT THEN
15271       RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
15272       ASM_REWRITE_TAC[LE_REFL]]]);;
15273
15274 let SELF_ADJOINT_HAS_EIGENVECTOR_BASIS = prove
15275  (`!f:real^N->real^N.
15276         linear f /\ adjoint f = f
15277         ==> ?b. pairwise orthogonal b /\
15278                 (!x. x IN b ==> norm x = &1 /\ ?c. f(x) = c % x) /\
15279                 independent b /\
15280                 span b = (:real^N) /\
15281                 b HAS_SIZE (dimindex(:N))`,
15282   REPEAT STRIP_TAC THEN
15283   MP_TAC(ISPECL [`f:real^N->real^N`; `(:real^N)`]
15284         SELF_ADJOINT_HAS_EIGENVECTOR_BASIS_OF_SUBSPACE) THEN
15285   ASM_REWRITE_TAC[SUBSPACE_UNIV; IN_UNIV; DIM_UNIV; SUBSET_UNIV]);;
15286
15287 (* ------------------------------------------------------------------------- *)
15288 (* Diagonalization of symmetric matrix.                                      *)
15289 (* ------------------------------------------------------------------------- *)
15290
15291 let SYMMETRIC_MATRIX_DIAGONALIZABLE_EXPLICIT = prove
15292  (`!A:real^N^N.
15293     transp A = A
15294     ==> ?P d. orthogonal_matrix P /\
15295               transp P ** A ** P = (lambda i j. if i = j then d i else &0)`,
15296   let lemma1 = prove
15297    (`!A:real^N^N P:real^N^N d.
15298        A ** P = P ** (lambda i j. if i = j then d i else &0) <=>
15299        !i. 1 <= i /\ i <= dimindex(:N)
15300            ==> A ** column i P = d i % column i P`,
15301     SIMP_TAC[CART_EQ; matrix_mul; matrix_vector_mul; LAMBDA_BETA;
15302              column; VECTOR_MUL_COMPONENT] THEN
15303     REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[COND_RAND] THEN
15304     SIMP_TAC[REAL_MUL_RZERO; SUM_DELTA; IN_NUMSEG] THEN
15305     EQ_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[] THEN
15306     REWRITE_TAC[REAL_MUL_SYM]) in
15307   let lemma2 = prove
15308    (`!A:real^N^N P:real^N^N d.
15309           orthogonal_matrix P /\
15310           transp P ** A ** P = (lambda i j. if i = j then d i else &0) <=>
15311           orthogonal_matrix P /\
15312           !i. 1 <= i /\ i <= dimindex(:N)
15313               ==> A ** column i P = d i % column i P`,
15314     REPEAT GEN_TAC THEN REWRITE_TAC[GSYM lemma1; orthogonal_matrix] THEN
15315     ABBREV_TAC `D:real^N^N = lambda i j. if i = j then d i else &0` THEN
15316     MESON_TAC[MATRIX_MUL_ASSOC; MATRIX_MUL_LID]) in
15317   REPEAT STRIP_TAC THEN
15318   REWRITE_TAC[lemma2] THEN REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN
15319   REWRITE_TAC[GSYM SKOLEM_THM] THEN
15320   MP_TAC(ISPEC `\x:real^N. (A:real^N^N) ** x`
15321     SELF_ADJOINT_HAS_EIGENVECTOR_BASIS) THEN
15322   ASM_SIMP_TAC[MATRIX_SELF_ADJOINT; MATRIX_VECTOR_MUL_LINEAR;
15323                MATRIX_OF_MATRIX_VECTOR_MUL] THEN
15324   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` MP_TAC) THEN
15325   REWRITE_TAC[CONJ_ASSOC] THEN ONCE_REWRITE_TAC[IMP_CONJ_ALT] THEN
15326   REWRITE_TAC[HAS_SIZE] THEN STRIP_TAC THEN
15327   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [FINITE_INDEX_NUMSEG]) THEN
15328   ASM_REWRITE_TAC[IN_NUMSEG; TAUT
15329    `p /\ q /\ x = y ==> a = b <=> p /\ q /\ ~(a = b) ==> ~(x = y)`] THEN
15330   DISCH_THEN(X_CHOOSE_THEN `f:num->real^N` STRIP_ASSUME_TAC) THEN
15331   ASM_REWRITE_TAC[PAIRWISE_IMAGE; FORALL_IN_IMAGE] THEN
15332   ASM_SIMP_TAC[pairwise; IN_NUMSEG] THEN STRIP_TAC THEN
15333   EXISTS_TAC `transp(lambda i. f i):real^N^N` THEN
15334   SIMP_TAC[COLUMN_TRANSP; ORTHOGONAL_MATRIX_TRANSP] THEN
15335   SIMP_TAC[ORTHOGONAL_MATRIX_ORTHONORMAL_ROWS_INDEXED; row] THEN
15336   SIMP_TAC[LAMBDA_ETA; LAMBDA_BETA; pairwise; IN_NUMSEG] THEN
15337   ASM_MESON_TAC[]);;
15338
15339 let SYMMETRIC_MATRIX_IMP_DIAGONALIZABLE = prove
15340  (`!A:real^N^N.
15341      transp A = A
15342      ==> ?P. orthogonal_matrix P /\ diagonal_matrix(transp P ** A ** P)`,
15343   GEN_TAC THEN
15344   DISCH_THEN(MP_TAC o MATCH_MP SYMMETRIC_MATRIX_DIAGONALIZABLE_EXPLICIT) THEN
15345   MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
15346   SIMP_TAC[diagonal_matrix; LAMBDA_BETA]);;
15347
15348 let SYMMETRIC_MATRIX_EQ_DIAGONALIZABLE = prove
15349  (`!A:real^N^N.
15350      transp A = A <=>
15351      ?P. orthogonal_matrix P /\ diagonal_matrix(transp P ** A ** P)`,
15352   GEN_TAC THEN EQ_TAC THEN
15353   REWRITE_TAC[SYMMETRIC_MATRIX_IMP_DIAGONALIZABLE] THEN
15354   REWRITE_TAC[orthogonal_matrix] THEN
15355   DISCH_THEN(X_CHOOSE_THEN `P:real^N^N` STRIP_ASSUME_TAC) THEN
15356   ABBREV_TAC `D:real^N^N = transp P ** (A:real^N^N) ** P` THEN
15357   SUBGOAL_THEN `A:real^N^N = P ** (D:real^N^N) ** transp P` SUBST1_TAC THENL
15358    [EXPAND_TAC "D" THEN REWRITE_TAC[MATRIX_MUL_ASSOC] THEN
15359     ASM_REWRITE_TAC[MATRIX_MUL_LID] THEN
15360     ASM_REWRITE_TAC[GSYM MATRIX_MUL_ASSOC; MATRIX_MUL_RID];
15361     REWRITE_TAC[MATRIX_TRANSP_MUL; TRANSP_TRANSP; MATRIX_MUL_ASSOC] THEN
15362     ASM_MESON_TAC[TRANSP_DIAGONAL_MATRIX]]);;
15363
15364 (* ------------------------------------------------------------------------- *)
15365 (* Some matrix identities are easier to deduce for invertible matrices. We   *)
15366 (* can then extend by continuity, which is why this material needs to be     *)
15367 (* here after basic topological notions have been defined.                   *)
15368 (* ------------------------------------------------------------------------- *)
15369
15370 let CONTINUOUS_LIFT_DET = prove
15371  (`!(A:A->real^N^N) net.
15372         (!i j. 1 <= i /\ i <= dimindex(:N) /\
15373                1 <= j /\ j <= dimindex(:N)
15374                ==> (\x. lift(A x$i$j)) continuous net)
15375         ==> (\x. lift(det(A x))) continuous net`,
15376   REPEAT STRIP_TAC THEN REWRITE_TAC[det] THEN
15377   SIMP_TAC[LIFT_SUM; FINITE_PERMUTATIONS; FINITE_NUMSEG; o_DEF] THEN
15378   MATCH_MP_TAC CONTINUOUS_VSUM THEN
15379   SIMP_TAC[FINITE_PERMUTATIONS; FINITE_NUMSEG; LIFT_CMUL; IN_ELIM_THM] THEN
15380   X_GEN_TAC `p:num->num` THEN DISCH_TAC THEN
15381   MATCH_MP_TAC CONTINUOUS_CMUL THEN
15382   MATCH_MP_TAC CONTINUOUS_LIFT_PRODUCT THEN
15383   REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
15384   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
15385   FIRST_ASSUM(MP_TAC o MATCH_MP PERMUTES_IMAGE) THEN
15386   DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE `s = t ==> s SUBSET t`)) THEN
15387   ASM_SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_NUMSEG]);;
15388
15389 let CONTINUOUS_ON_LIFT_DET = prove
15390  (`!A:real^M->real^N^N s.
15391         (!i j. 1 <= i /\ i <= dimindex(:N) /\
15392                1 <= j /\ j <= dimindex(:N)
15393                ==> (\x. lift(A x$i$j)) continuous_on s)
15394         ==> (\x. lift(det(A x))) continuous_on s`,
15395   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_LIFT_DET]);;
15396
15397 let NEARBY_INVERTIBLE_MATRIX = prove
15398  (`!A:real^N^N.
15399      ?e. &0 < e /\ !x. ~(x = &0) /\ abs x < e ==> invertible(A + x %% mat 1)`,
15400   GEN_TAC THEN MP_TAC(ISPEC `A:real^N^N` CHARACTERISTIC_POLYNOMIAL) THEN
15401   DISCH_THEN(X_CHOOSE_THEN `a:num->real` STRIP_ASSUME_TAC) THEN
15402   MP_TAC(ISPECL [`dimindex(:N)`; `a:num->real`] REAL_POLYFUN_FINITE_ROOTS) THEN
15403   MATCH_MP_TAC(TAUT `q /\ (p ==> r) ==> (p <=> q) ==> r`) THEN CONJ_TAC THENL
15404    [EXISTS_TAC `dimindex(:N)` THEN ASM_REWRITE_TAC[IN_NUMSEG] THEN ARITH_TAC;
15405     ALL_TAC] THEN
15406   DISCH_THEN(MP_TAC o ISPEC `lift` o MATCH_MP FINITE_IMAGE) THEN
15407   DISCH_THEN(MP_TAC o MATCH_MP LIMIT_POINT_FINITE) THEN
15408   DISCH_THEN(MP_TAC o SPEC `lift(&0)`) THEN
15409   REWRITE_TAC[LIMPT_APPROACHABLE; EXISTS_IN_IMAGE; EXISTS_IN_GSPEC] THEN
15410   REWRITE_TAC[DIST_LIFT; LIFT_EQ; REAL_SUB_RZERO; NOT_FORALL_THM; NOT_IMP] THEN
15411   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN
15412   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
15413   DISCH_THEN(fun th -> X_GEN_TAC `x:real` THEN STRIP_TAC THEN
15414                 MP_TAC(SPEC `--x:real` th)) THEN
15415   FIRST_X_ASSUM(SUBST1_TAC o SYM o SPEC `--x:real`) THEN
15416   ASM_REWRITE_TAC[REAL_NEG_EQ_0; REAL_ABS_NEG] THEN
15417   ONCE_REWRITE_TAC[GSYM INVERTIBLE_NEG] THEN
15418   REWRITE_TAC[INVERTIBLE_DET_NZ; CONTRAPOS_THM] THEN
15419   REWRITE_TAC[MATRIX_SUB; MATRIX_NEG_MINUS1] THEN
15420   ONCE_REWRITE_TAC[REAL_ARITH `--x = -- &1 * x`] THEN
15421   REWRITE_TAC[GSYM MATRIX_CMUL_ADD_LDISTRIB; GSYM MATRIX_CMUL_ASSOC] THEN
15422   REWRITE_TAC[MATRIX_CMUL_LID; MATRIX_ADD_SYM]);;
15423
15424 let MATRIX_WLOG_INVERTIBLE = prove
15425  (`!P. (!A:real^N^N. invertible A ==> P A) /\
15426        (!A:real^N^N. ?d. &0 < d /\
15427                          closed {x | x IN cball(vec 0,d) /\
15428                                      P(A + drop x %% mat 1)})
15429        ==> !A:real^N^N. P A`,
15430   REPEAT GEN_TAC THEN
15431   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
15432   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
15433   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
15434   FIRST_ASSUM(MP_TAC o SPEC `vec 0:real^1` o
15435     GEN_REWRITE_RULE I [CLOSED_LIMPT]) THEN
15436   ASM_SIMP_TAC[IN_ELIM_THM; DROP_VEC; MATRIX_CMUL_LZERO; MATRIX_ADD_RID] THEN
15437   ANTS_TAC THENL [ALL_TAC; CONV_TAC TAUT] THEN
15438   MP_TAC(ISPEC `A:real^N^N` NEARBY_INVERTIBLE_MATRIX) THEN
15439   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
15440   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `k:real` THEN
15441   DISCH_TAC THEN REWRITE_TAC[EXISTS_LIFT; IN_ELIM_THM] THEN
15442   REWRITE_TAC[GSYM LIFT_NUM; IN_CBALL_0; NORM_LIFT; DIST_LIFT] THEN
15443   REWRITE_TAC[REAL_SUB_RZERO; LIFT_EQ; LIFT_DROP] THEN
15444   EXISTS_TAC `min d ((min e k) / &2)` THEN
15445   CONJ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
15446   CONJ_TAC THENL [ASM_REAL_ARITH_TAC; FIRST_X_ASSUM MATCH_MP_TAC] THEN
15447   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC);;
15448
15449 let SYLVESTER_DETERMINANT_IDENTITY = prove
15450  (`!A:real^N^M B:real^M^N. det(mat 1 + A ** B) = det(mat 1 + B ** A)`,
15451   let lemma1 = prove
15452    (`!A:real^N^N B:real^N^N. det(mat 1 + A ** B) = det(mat 1 + B ** A)`,
15453     ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN GEN_TAC THEN
15454     MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN CONJ_TAC THENL
15455      [REPEAT STRIP_TAC THEN
15456       SUBGOAL_THEN `det((mat 1 + A ** B) ** A:real^N^N) =
15457                     det(A ** (mat 1 + B ** A))`
15458       MP_TAC THENL
15459        [REWRITE_TAC[MATRIX_ADD_RDISTRIB; MATRIX_ADD_LDISTRIB] THEN
15460         REWRITE_TAC[MATRIX_MUL_LID; MATRIX_MUL_RID; MATRIX_MUL_ASSOC];
15461         REWRITE_TAC[DET_MUL] THEN
15462         FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INVERTIBLE_DET_NZ]) THEN
15463         CONV_TAC REAL_RING];
15464       X_GEN_TAC `A:real^N^N` THEN EXISTS_TAC `&1` THEN
15465       REWRITE_TAC[REAL_LT_01; SET_RULE
15466        `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
15467       MATCH_MP_TAC CLOSED_INTER THEN REWRITE_TAC[CLOSED_CBALL] THEN
15468       ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN
15469       REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM] THEN
15470       REWRITE_TAC[SET_RULE `{x | f x = a} = {x | f x IN {a}}`] THEN
15471       MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
15472       REWRITE_TAC[CLOSED_SING; LIFT_SUB] THEN X_GEN_TAC `x:real^1` THEN
15473       REWRITE_TAC[o_DEF; LIFT_SUB] THEN MATCH_MP_TAC CONTINUOUS_SUB THEN
15474       CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN
15475       MAP_EVERY X_GEN_TAC [`i:num`; `j:num`] THEN STRIP_TAC THEN
15476       ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; LIFT_ADD] THEN
15477       MATCH_MP_TAC CONTINUOUS_ADD THEN
15478       ASM_SIMP_TAC[matrix_mul; LAMBDA_BETA; CONTINUOUS_CONST] THEN
15479       SIMP_TAC[LIFT_SUM; FINITE_NUMSEG; o_DEF] THEN
15480       MATCH_MP_TAC CONTINUOUS_VSUM THEN
15481       REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN X_GEN_TAC `k:num` THEN
15482       DISCH_TAC THENL [ONCE_REWRITE_TAC[REAL_MUL_SYM]; ALL_TAC] THEN
15483       REWRITE_TAC[LIFT_CMUL] THEN MATCH_MP_TAC CONTINUOUS_CMUL THEN
15484       REWRITE_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT; LIFT_ADD] THEN
15485       MATCH_MP_TAC CONTINUOUS_ADD THEN REWRITE_TAC[CONTINUOUS_CONST] THEN
15486       REWRITE_TAC[ONCE_REWRITE_RULE[REAL_MUL_SYM] LIFT_CMUL] THEN
15487       MATCH_MP_TAC CONTINUOUS_CMUL THEN
15488       REWRITE_TAC[LIFT_DROP; CONTINUOUS_AT_ID]]) in
15489   let lemma2 = prove
15490    (`!A:real^N^M B:real^M^N.
15491           dimindex(:M) <= dimindex(:N)
15492           ==> det(mat 1 + A ** B) = det(mat 1 + B ** A)`,
15493     REPEAT STRIP_TAC THEN
15494     MAP_EVERY ABBREV_TAC
15495      [`A':real^N^N =
15496           lambda i j. if i <= dimindex(:M) then (A:real^N^M)$i$j
15497                       else &0`;
15498       `B':real^N^N =
15499           lambda i j. if j <= dimindex(:M) then (B:real^M^N)$i$j
15500                       else &0`] THEN
15501     MP_TAC(ISPECL [`A':real^N^N`; `B':real^N^N`] lemma1) THEN
15502     SUBGOAL_THEN
15503      `(B':real^N^N) ** (A':real^N^N) = (B:real^M^N) ** (A:real^N^M)`
15504     SUBST1_TAC THENL
15505      [MAP_EVERY EXPAND_TAC ["A'"; "B'"] THEN
15506       SIMP_TAC[CART_EQ; LAMBDA_BETA; matrix_mul] THEN REPEAT STRIP_TAC THEN
15507       MATCH_MP_TAC SUM_EQ_SUPERSET THEN
15508       ASM_SIMP_TAC[IN_NUMSEG; REAL_MUL_LZERO; FINITE_NUMSEG; SUBSET_NUMSEG;
15509                    LE_REFL; TAUT `(p /\ q) /\ ~(p /\ r) <=> p /\ q /\ ~r`];
15510       DISCH_THEN(SUBST1_TAC o SYM)] THEN
15511     REWRITE_TAC[det] THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC
15512      `sum {p | p permutes 1..dimindex(:N) /\ !i. dimindex(:M) < i ==> p i = i}
15513           (\p. sign p * product (1..dimindex(:N))
15514                      (\i. (mat 1 + (A':real^N^N) ** (B':real^N^N))$i$p i))` THEN
15515     CONJ_TAC THENL
15516      [ALL_TAC;
15517       CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_SUPERSET THEN
15518       CONJ_TAC THENL [SET_TAC[]; SIMP_TAC[IN_ELIM_THM; IMP_CONJ]] THEN
15519       X_GEN_TAC `p:num->num` THEN REPEAT STRIP_TAC THEN
15520       REWRITE_TAC[REAL_ENTIRE; PRODUCT_EQ_0_NUMSEG] THEN DISJ2_TAC THEN
15521       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_FORALL_THM]) THEN
15522       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `k:num` THEN
15523       REWRITE_TAC[NOT_IMP] THEN STRIP_TAC THEN
15524       FIRST_ASSUM(MP_TAC o SPEC `k:num` o CONJUNCT1 o
15525         GEN_REWRITE_RULE I [permutes]) THEN
15526       ASM_REWRITE_TAC[IN_NUMSEG] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
15527       FIRST_ASSUM(MP_TAC o MATCH_MP PERMUTES_IMAGE) THEN
15528       DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE `s = t ==> s SUBSET t`)) THEN
15529       ASM_SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_NUMSEG] THEN
15530       DISCH_THEN(MP_TAC o SPEC `k:num`) THEN ASM_SIMP_TAC[] THEN STRIP_TAC THEN
15531       ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MAT_COMPONENT; REAL_ADD_LID] THEN
15532       ASM_SIMP_TAC[matrix_mul; LAMBDA_BETA] THEN
15533       MATCH_MP_TAC SUM_EQ_0_NUMSEG THEN REPEAT STRIP_TAC THEN
15534       REWRITE_TAC[REAL_ENTIRE] THEN DISJ1_TAC THEN EXPAND_TAC "A'" THEN
15535       ASM_SIMP_TAC[LAMBDA_BETA; GSYM NOT_LT]] THEN
15536     CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_EQ_GENERAL THEN
15537     EXISTS_TAC `\f:num->num. f` THEN REWRITE_TAC[IN_ELIM_THM] THEN
15538     CONJ_TAC THEN X_GEN_TAC `p:num->num` THEN STRIP_TAC THENL
15539      [REWRITE_TAC[MESON[] `(?!x. P x /\ x = y) <=> P y`] THEN CONJ_TAC THENL
15540        [MATCH_MP_TAC PERMUTES_SUBSET THEN
15541         EXISTS_TAC `1..dimindex(:M)` THEN
15542         ASM_REWRITE_TAC[SUBSET_NUMSEG; LE_REFL];
15543         X_GEN_TAC `k:num` THEN DISCH_TAC THEN
15544         FIRST_X_ASSUM(MATCH_MP_TAC o CONJUNCT1 o
15545           GEN_REWRITE_RULE I [permutes]) THEN
15546         ASM_REWRITE_TAC[IN_NUMSEG; DE_MORGAN_THM; NOT_LE]];
15547       MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
15548        [MATCH_MP_TAC PERMUTES_SUPERSET THEN
15549         EXISTS_TAC `1..dimindex(:N)` THEN
15550         ASM_REWRITE_TAC[IN_DIFF; IN_NUMSEG] THEN ASM_MESON_TAC[NOT_LE];
15551         DISCH_TAC] THEN
15552       AP_TERM_TAC THEN FIRST_ASSUM(SUBST1_TAC o MATCH_MP (ARITH_RULE
15553        `m:num <= n ==> n = m + (n - m)`)) THEN
15554       SIMP_TAC[PRODUCT_ADD_SPLIT; ARITH_RULE `1 <= n + 1`] THEN
15555       MATCH_MP_TAC(REAL_RING `x = y /\ z = &1 ==> x = y * z`) THEN
15556       CONJ_TAC THENL
15557        [MATCH_MP_TAC PRODUCT_EQ_NUMSEG THEN
15558         X_GEN_TAC `i:num` THEN STRIP_TAC THEN
15559         SUBGOAL_THEN `i <= dimindex(:N)` ASSUME_TAC THENL
15560          [ASM_ARITH_TAC; ALL_TAC] THEN
15561         MP_TAC(ISPECL [`p:num->num`; `1..dimindex(:M)`] PERMUTES_IMAGE) THEN
15562         ASM_REWRITE_TAC[] THEN
15563         DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE `s = t ==> s SUBSET t`)) THEN
15564         ASM_SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_NUMSEG] THEN
15565         DISCH_THEN(MP_TAC o SPEC `i:num`) THEN
15566         ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
15567         SUBGOAL_THEN `(p:num->num) i <= dimindex(:N)` ASSUME_TAC THENL
15568          [ASM_ARITH_TAC; ALL_TAC] THEN
15569         ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MAT_COMPONENT] THEN
15570         AP_TERM_TAC THEN ASM_SIMP_TAC[matrix_mul; LAMBDA_BETA] THEN
15571         MATCH_MP_TAC SUM_EQ_NUMSEG THEN REPEAT STRIP_TAC THEN
15572         MAP_EVERY EXPAND_TAC ["A'"; "B'"] THEN
15573         ASM_SIMP_TAC[LAMBDA_BETA];
15574         MATCH_MP_TAC PRODUCT_EQ_1_NUMSEG THEN
15575         ASM_SIMP_TAC[ARITH_RULE `n + 1 <= i ==> n < i`] THEN
15576         ASM_SIMP_TAC[ARITH_RULE `m:num <= n ==> m + (n - m) = n`] THEN
15577         X_GEN_TAC `i:num` THEN STRIP_TAC THEN
15578         SUBGOAL_THEN `1 <= i` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
15579         ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MAT_COMPONENT] THEN
15580         ASM_SIMP_TAC[REAL_EQ_ADD_LCANCEL_0; matrix_mul; LAMBDA_BETA] THEN
15581         MATCH_MP_TAC SUM_EQ_0_NUMSEG THEN REPEAT STRIP_TAC THEN
15582         REWRITE_TAC[REAL_ENTIRE] THEN DISJ1_TAC THEN EXPAND_TAC "A'" THEN
15583         ASM_SIMP_TAC[LAMBDA_BETA; ARITH_RULE `m + 1 <= i ==> ~(i <= m)`]]]) in
15584   REPEAT GEN_TAC THEN DISJ_CASES_TAC (ARITH_RULE
15585    `dimindex(:M) <= dimindex(:N) \/ dimindex(:N) <= dimindex(:M)`)
15586   THENL [ALL_TAC; CONV_TAC SYM_CONV] THEN
15587   MATCH_MP_TAC lemma2 THEN ASM_REWRITE_TAC[]);;
15588
15589 let COFACTOR_MATRIX_MUL = prove
15590  (`!A B:real^N^N. cofactor(A ** B) = cofactor(A) ** cofactor(B)`,
15591   MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN CONJ_TAC THENL
15592    [GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN
15593     CONJ_TAC THENL
15594      [ASM_SIMP_TAC[COFACTOR_MATRIX_INV; GSYM INVERTIBLE_DET_NZ;
15595                    INVERTIBLE_MATRIX_MUL] THEN
15596       REWRITE_TAC[DET_MUL; MATRIX_MUL_LMUL] THEN
15597       REWRITE_TAC[MATRIX_MUL_RMUL; MATRIX_CMUL_ASSOC;
15598                   GSYM MATRIX_TRANSP_MUL] THEN
15599       ASM_SIMP_TAC[MATRIX_INV_MUL];
15600       GEN_TAC THEN EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01]];
15601     X_GEN_TAC `A:real^N^N` THEN EXISTS_TAC `&1` THEN
15602     REWRITE_TAC[REAL_LT_01] THEN REWRITE_TAC[RIGHT_AND_FORALL_THM] THEN
15603     MATCH_MP_TAC CLOSED_FORALL THEN GEN_TAC] THEN
15604   REWRITE_TAC[SET_RULE
15605    `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
15606   MATCH_MP_TAC CLOSED_INTER THEN REWRITE_TAC[CLOSED_CBALL] THEN
15607   REWRITE_TAC[CART_EQ] THEN
15608   MATCH_MP_TAC CLOSED_FORALL_IN THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
15609   MATCH_MP_TAC CLOSED_FORALL_IN THEN X_GEN_TAC `j:num` THEN STRIP_TAC THEN
15610   ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN
15611   REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM] THEN
15612   REWRITE_TAC[SET_RULE `{x | f x = a} = {x | f x IN {a}}`] THEN
15613   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
15614   REWRITE_TAC[CLOSED_SING; LIFT_SUB] THEN X_GEN_TAC `x:real^1` THEN
15615   ASM_SIMP_TAC[matrix_mul; LAMBDA_BETA; cofactor; LIFT_SUM;
15616                FINITE_NUMSEG; o_DEF] THEN
15617   (MATCH_MP_TAC CONTINUOUS_SUB THEN CONJ_TAC THENL
15618     [ALL_TAC;
15619      MATCH_MP_TAC CONTINUOUS_VSUM THEN
15620      REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
15621      X_GEN_TAC `k:num` THEN STRIP_TAC THEN
15622      REWRITE_TAC[LIFT_CMUL] THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
15623      REWRITE_TAC[o_DEF] THEN CONJ_TAC]) THEN
15624   MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN
15625   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
15626   ASM_SIMP_TAC[LAMBDA_BETA; CONTINUOUS_CONST] THEN
15627   REPEAT(W(fun (asl,w) ->
15628    let t = find_term is_cond w in
15629    ASM_CASES_TAC (lhand(rator t)) THEN ASM_REWRITE_TAC[CONTINUOUS_CONST])) THEN
15630   SIMP_TAC[LIFT_SUM; FINITE_NUMSEG; o_DEF] THEN
15631   TRY(MATCH_MP_TAC CONTINUOUS_VSUM THEN REWRITE_TAC[FINITE_NUMSEG] THEN
15632       REWRITE_TAC[IN_NUMSEG] THEN X_GEN_TAC `p:num` THEN STRIP_TAC) THEN
15633   REWRITE_TAC[LIFT_CMUL] THEN
15634   TRY(MATCH_MP_TAC CONTINUOUS_MUL THEN
15635       REWRITE_TAC[o_DEF; CONTINUOUS_CONST]) THEN
15636   REWRITE_TAC[MATRIX_ADD_COMPONENT; LIFT_ADD] THEN
15637   MATCH_MP_TAC CONTINUOUS_ADD THEN REWRITE_TAC[CONTINUOUS_CONST] THEN
15638   REWRITE_TAC[MATRIX_CMUL_COMPONENT; LIFT_CMUL; o_DEF] THEN
15639   MATCH_MP_TAC CONTINUOUS_MUL THEN
15640   REWRITE_TAC[CONTINUOUS_CONST; o_DEF; LIFT_DROP; CONTINUOUS_AT_ID]);;
15641
15642 let DET_COFACTOR = prove
15643  (`!A:real^N^N. det(cofactor A) = det(A) pow (dimindex(:N) - 1)`,
15644   MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN CONJ_TAC THEN
15645   X_GEN_TAC `A:real^N^N` THENL
15646    [REWRITE_TAC[INVERTIBLE_DET_NZ] THEN STRIP_TAC THEN
15647     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_FIELD
15648      `~(a = &0) ==> a * x = a * y ==> x = y`)) THEN
15649     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM DET_TRANSP] THEN
15650     REWRITE_TAC[GSYM DET_MUL; MATRIX_MUL_RIGHT_COFACTOR] THEN
15651     REWRITE_TAC[DET_CMUL; GSYM(CONJUNCT2 real_pow); DET_I; REAL_MUL_RID] THEN
15652     SIMP_TAC[DIMINDEX_GE_1; ARITH_RULE `1 <= n ==> SUC(n - 1) = n`];
15653     ALL_TAC] THEN
15654   EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN
15655   REWRITE_TAC[SET_RULE
15656    `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
15657   MATCH_MP_TAC CLOSED_INTER THEN REWRITE_TAC[CLOSED_CBALL] THEN
15658   ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN
15659   REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM] THEN
15660   REWRITE_TAC[SET_RULE `{x | f x = a} = {x | f x IN {a}}`] THEN
15661   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
15662   REWRITE_TAC[CLOSED_SING; LIFT_SUB] THEN X_GEN_TAC `x:real^1` THEN
15663   MATCH_MP_TAC CONTINUOUS_SUB THEN
15664   CONJ_TAC THENL [ALL_TAC; MATCH_MP_TAC CONTINUOUS_LIFT_POW] THEN
15665   MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN
15666   MAP_EVERY X_GEN_TAC [`i:num`; `j:num`] THEN STRIP_TAC THEN
15667   ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT; LIFT_ADD;
15668                LIFT_CMUL; LIFT_DROP; CONTINUOUS_ADD; CONTINUOUS_CONST;
15669                CONTINUOUS_MUL; o_DEF; LIFT_DROP; CONTINUOUS_AT_ID] THEN
15670   ASM_SIMP_TAC[cofactor; LAMBDA_BETA] THEN
15671   MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN
15672   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
15673   ASM_SIMP_TAC[LAMBDA_BETA] THEN
15674   REPEAT(W(fun (asl,w) ->
15675    let t = find_term is_cond w in
15676    ASM_CASES_TAC (lhand(rator t)) THEN ASM_REWRITE_TAC[CONTINUOUS_CONST])) THEN
15677   ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT; LIFT_ADD;
15678                LIFT_CMUL; LIFT_DROP; CONTINUOUS_ADD; CONTINUOUS_CONST;
15679                CONTINUOUS_MUL; o_DEF; LIFT_DROP; CONTINUOUS_AT_ID]);;
15680
15681 let INVERTIBLE_COFACTOR = prove
15682  (`!A:real^N^N. invertible(cofactor A) <=> dimindex(:N) = 1 \/ invertible A`,
15683   SIMP_TAC[DET_COFACTOR; INVERTIBLE_DET_NZ; REAL_POW_EQ_0; DE_MORGAN_THM;
15684            DIMINDEX_GE_1; ARITH_RULE `1 <= n ==> (n - 1 = 0 <=> n = 1)`;
15685            DISJ_ACI]);;
15686
15687 let COFACTOR_COFACTOR = prove
15688  (`!A:real^N^N.
15689      2 <= dimindex(:N)
15690      ==> cofactor(cofactor A) = (det(A) pow (dimindex(:N) - 2)) %% A`,
15691   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
15692   MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN CONJ_TAC THEN
15693   X_GEN_TAC `A:real^N^N` THENL
15694    [REWRITE_TAC[INVERTIBLE_DET_NZ] THEN DISCH_TAC THEN
15695     MP_TAC(ISPECL [`A:real^N^N`; `transp(cofactor A):real^N^N`]
15696         COFACTOR_MATRIX_MUL) THEN
15697     REWRITE_TAC[MATRIX_MUL_RIGHT_COFACTOR; COFACTOR_CMUL; COFACTOR_I] THEN
15698     REWRITE_TAC[COFACTOR_TRANSP] THEN
15699     DISCH_THEN(MP_TAC o AP_TERM `transp:real^N^N->real^N^N`) THEN
15700     REWRITE_TAC[MATRIX_TRANSP_MUL; TRANSP_TRANSP; TRANSP_MATRIX_CMUL] THEN
15701     REWRITE_TAC[TRANSP_MAT] THEN
15702     DISCH_THEN(MP_TAC o AP_TERM `(\x. x ** A):real^N^N->real^N^N`) THEN
15703     REWRITE_TAC[GSYM MATRIX_MUL_ASSOC; MATRIX_MUL_LEFT_COFACTOR] THEN
15704     REWRITE_TAC[MATRIX_MUL_LMUL; MATRIX_MUL_RMUL] THEN
15705     REWRITE_TAC[MATRIX_MUL_LID; MATRIX_MUL_RID] THEN
15706     DISCH_THEN(MP_TAC o AP_TERM `\x:real^N^N. inv(det(A:real^N^N)) %% x`) THEN
15707     ASM_SIMP_TAC[MATRIX_CMUL_ASSOC; REAL_MUL_LINV; MATRIX_CMUL_LID] THEN
15708     DISCH_THEN(SUBST1_TAC o SYM) THEN AP_THM_TAC THEN AP_TERM_TAC THEN
15709     ASM_SIMP_TAC[REAL_POW_SUB; ARITH_RULE `2 <= n ==> 1 <= n`] THEN
15710     REWRITE_TAC[REAL_POW_2; real_div; REAL_INV_POW] THEN REAL_ARITH_TAC;
15711     POP_ASSUM(K ALL_TAC)] THEN
15712   EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN
15713   REWRITE_TAC[SET_RULE
15714    `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
15715   MATCH_MP_TAC CLOSED_INTER THEN REWRITE_TAC[CLOSED_CBALL] THEN
15716   REWRITE_TAC[CART_EQ] THEN
15717   MATCH_MP_TAC CLOSED_FORALL_IN THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
15718   MATCH_MP_TAC CLOSED_FORALL_IN THEN X_GEN_TAC `j:num` THEN STRIP_TAC THEN
15719   ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN
15720   REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM] THEN
15721   REWRITE_TAC[SET_RULE `{x | f x = a} = {x | f x IN {a}}`] THEN
15722   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
15723   REWRITE_TAC[CLOSED_SING; LIFT_SUB] THEN X_GEN_TAC `x:real^1` THEN
15724   MATCH_MP_TAC CONTINUOUS_SUB THEN CONJ_TAC THENL
15725    [REPLICATE_TAC 2
15726      (ONCE_REWRITE_TAC[cofactor] THEN ASM_SIMP_TAC[LAMBDA_BETA] THEN
15727       MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN REPEAT STRIP_TAC THEN
15728       ASM_SIMP_TAC[LAMBDA_BETA] THEN
15729       REPEAT(W(fun (asl,w) ->
15730        let t = find_term is_cond w in
15731        ASM_CASES_TAC (lhand(rator t)) THEN
15732        ASM_REWRITE_TAC[CONTINUOUS_CONST])));
15733     REWRITE_TAC[MATRIX_CMUL_COMPONENT; LIFT_CMUL] THEN
15734     MATCH_MP_TAC CONTINUOUS_MUL THEN REWRITE_TAC[o_DEF] THEN CONJ_TAC THENL
15735      [MATCH_MP_TAC CONTINUOUS_LIFT_POW THEN
15736       MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN REPEAT STRIP_TAC;
15737       ALL_TAC]] THEN
15738   REWRITE_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT] THEN
15739   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
15740   REWRITE_TAC[LIFT_ADD; LIFT_CMUL; LIFT_DROP] THEN
15741   SIMP_TAC[CONTINUOUS_ADD; CONTINUOUS_CONST; CONTINUOUS_CMUL;
15742            CONTINUOUS_AT_ID]);;
15743
15744 let RANK_COFACTOR_EQ_FULL = prove
15745  (`!A:real^N^N. rank(cofactor A) = dimindex(:N) <=>
15746                 dimindex(:N) = 1 \/ rank A = dimindex(:N)`,
15747   REWRITE_TAC[RANK_EQ_FULL_DET; DET_COFACTOR; REAL_POW_EQ_0] THEN
15748   SIMP_TAC[DIMINDEX_GE_1; ARITH_RULE `1 <= n ==> (n - 1 = 0 <=> n = 1)`] THEN
15749   CONV_TAC TAUT);;
15750
15751 let COFACTOR_EQ_0 = prove
15752  (`!A:real^N^N. cofactor A = mat 0 <=> rank(A) < dimindex(:N) - 1`,
15753   let lemma1 = prove
15754    (`!A:real^N^N. rank(A) < dimindex(:N) - 1 ==> cofactor A = mat 0`,
15755     GEN_TAC THEN REWRITE_TAC[RANK_ROW] THEN DISCH_TAC THEN
15756     SIMP_TAC[CART_EQ; cofactor; MAT_COMPONENT; LAMBDA_BETA; COND_ID] THEN
15757     X_GEN_TAC `m:num` THEN STRIP_TAC THEN X_GEN_TAC `n:num` THEN STRIP_TAC THEN
15758     REWRITE_TAC[DET_EQ_0_RANK] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
15759      (ARITH_RULE `r < n - 1 ==> s <= r + 1 ==> s < n`)) THEN
15760     REWRITE_TAC[RANK_ROW; rows] THEN MATCH_MP_TAC LE_TRANS THEN
15761     EXISTS_TAC
15762      `dim (basis n INSERT
15763            {row i ((lambda k l. if l = n then &0 else (A:real^N^N)$k$l)
15764                    :real^N^N)
15765             | i IN (1..dimindex(:N)) DELETE m})` THEN
15766     CONJ_TAC THENL
15767      [MATCH_MP_TAC DIM_SUBSET THEN REWRITE_TAC[GSYM IN_NUMSEG] THEN
15768       MATCH_MP_TAC(SET_RULE
15769        `m IN s /\ (!i. i IN s DELETE m ==> f i = g i) /\ f m = a
15770         ==> {f i | i IN s} SUBSET a INSERT {g i | i IN s DELETE m}`) THEN
15771       ASM_SIMP_TAC[IN_NUMSEG; IN_DELETE; row; LAMBDA_BETA; basis; LAMBDA_ETA];
15772       REWRITE_TAC[DIM_INSERT] THEN MATCH_MP_TAC(ARITH_RULE
15773        `n <= k ==> (if p then n else n + 1) <= k + 1`) THEN
15774       MATCH_MP_TAC(MESON[DIM_LINEAR_IMAGE_LE; DIM_SUBSET; LE_TRANS]
15775        `(?f. linear f /\ t SUBSET IMAGE f s) ==> dim t <= dim s`) THEN
15776       EXISTS_TAC `(\x. lambda i. if i = n then &0 else x$i)
15777                   :real^N->real^N` THEN
15778       REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN CONJ_TAC THENL
15779        [SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
15780                   VECTOR_MUL_COMPONENT] THEN
15781         REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
15782         REAL_ARITH_TAC;
15783         X_GEN_TAC `i:num` THEN REWRITE_TAC[IN_NUMSEG; IN_DELETE] THEN
15784         STRIP_TAC THEN REWRITE_TAC[IN_IMAGE] THEN
15785         ONCE_REWRITE_TAC[CONJ_SYM] THEN
15786         REWRITE_TAC[EXISTS_IN_GSPEC] THEN EXISTS_TAC `i:num` THEN
15787         ASM_SIMP_TAC[row; CART_EQ; LAMBDA_BETA]]])
15788   and lemma2 = prove
15789    (`!A:real^N^N.
15790           rank A < dimindex(:N)
15791           ==> ?n x. 1 <= n /\ n <= dimindex(:N) /\
15792                     rank A <
15793                     rank((lambda i. if i = n then x else row i A):real^N^N)`,
15794     REPEAT STRIP_TAC THEN SUBGOAL_THEN
15795      `?n. 1 <= n /\ n <= dimindex(:N) /\
15796           row n (A:real^N^N) IN
15797           span {row j A | j IN (1..dimindex(:N)) DELETE n}`
15798     MP_TAC THENL
15799      [MP_TAC(ISPEC `transp A:real^N^N` HOMOGENEOUS_LINEAR_EQUATIONS_DET) THEN
15800       ASM_REWRITE_TAC[DET_EQ_0_RANK; RANK_TRANSP] THEN
15801       DISCH_THEN(X_CHOOSE_THEN `c:real^N` STRIP_ASSUME_TAC) THEN
15802       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [CART_EQ]) THEN
15803       REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; VEC_COMPONENT] THEN
15804       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `n:num` THEN STRIP_TAC THEN
15805       ASM_REWRITE_TAC[] THEN
15806       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CART_EQ]) THEN
15807       SIMP_TAC[matrix_vector_mul; transp; VEC_COMPONENT; LAMBDA_BETA] THEN
15808       DISCH_TAC THEN
15809       SUBGOAL_THEN `row n A = vsum ((1..dimindex(:N)) DELETE n)
15810                        (\i. --((c:real^N)$i / c$n) % row i (A:real^N^N))`
15811       SUBST1_TAC THENL
15812        [ASM_SIMP_TAC[VSUM_DELETE; FINITE_NUMSEG; IN_NUMSEG; REAL_DIV_REFL] THEN
15813         REWRITE_TAC[VECTOR_ARITH `n = x - -- &1 % n <=> x:real^N = vec 0`] THEN
15814         SIMP_TAC[VSUM_COMPONENT; row; VECTOR_MUL_COMPONENT; LAMBDA_BETA;
15815           CART_EQ; REAL_ARITH `--(x / y) * z:real = --(inv y) * z * x`] THEN
15816         ASM_SIMP_TAC[SUM_LMUL; VEC_COMPONENT; REAL_MUL_RZERO];
15817         MATCH_MP_TAC SPAN_VSUM THEN SIMP_TAC[FINITE_DELETE; FINITE_NUMSEG] THEN
15818         X_GEN_TAC `i:num` THEN REWRITE_TAC[IN_DELETE; IN_NUMSEG] THEN
15819         STRIP_TAC THEN MATCH_MP_TAC SPAN_MUL THEN
15820         MATCH_MP_TAC SPAN_SUPERSET THEN ASM SET_TAC[]];
15821       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `n:num` THEN STRIP_TAC THEN
15822       ASM_REWRITE_TAC[] THEN
15823       SUBGOAL_THEN `span {row j (A:real^N^N) | j IN (1..dimindex(:N)) DELETE n}
15824                     PSUBSET (:real^N)`
15825       MP_TAC THENL
15826        [REWRITE_TAC[PSUBSET; SUBSET_UNIV] THEN
15827         DISCH_THEN(MP_TAC o AP_TERM `dim:(real^N->bool)->num`) THEN
15828         REWRITE_TAC[DIM_UNIV] THEN
15829         MATCH_MP_TAC(ARITH_RULE `1 <= n /\ x <= n - 1 ==> ~(x = n)`) THEN
15830         REWRITE_TAC[DIMINDEX_GE_1; DIM_SPAN] THEN
15831         W(MP_TAC o PART_MATCH (lhand o rand) DIM_LE_CARD o lhand o snd) THEN
15832         ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
15833         SIMP_TAC[FINITE_IMAGE; FINITE_DELETE; FINITE_NUMSEG] THEN
15834         MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] LE_TRANS) THEN
15835         W(MP_TAC o PART_MATCH (lhand o rand) CARD_IMAGE_LE o lhand o snd) THEN
15836         SIMP_TAC[FINITE_DELETE; FINITE_NUMSEG] THEN
15837         MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] LE_TRANS) THEN
15838         ASM_SIMP_TAC[CARD_DELETE; IN_NUMSEG; FINITE_NUMSEG] THEN
15839         REWRITE_TAC[CARD_NUMSEG_1; LE_REFL];
15840         DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
15841          `s PSUBSET UNIV ==> ?x. ~(x IN s)`)) THEN
15842         MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN
15843         REWRITE_TAC[RANK_ROW] THEN DISCH_TAC THEN
15844         SUBGOAL_THEN
15845          `!A:real^N^N. rows A = row n A INSERT
15846                                 {row j A | j IN (1..dimindex (:N)) DELETE n}`
15847          (fun th -> REWRITE_TAC[th])
15848         THENL
15849          [REWRITE_TAC[rows; IN_DELETE; IN_NUMSEG] THEN ASM SET_TAC[];
15850           ASM_SIMP_TAC[DIM_INSERT]] THEN
15851         COND_CASES_TAC THENL
15852          [FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN
15853           FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
15854             `x IN span s ==> x = y /\ s = t ==> ~(y IN span t) ==> q`)) THEN
15855           ASM_SIMP_TAC[row; LAMBDA_BETA; LAMBDA_ETA];
15856           MATCH_MP_TAC(ARITH_RULE `s = t ==> s < t + 1`) THEN
15857           AP_TERM_TAC THEN REWRITE_TAC[row]] THEN
15858         MATCH_MP_TAC(SET_RULE
15859          `(!x. x IN s ==> f x = g x) ==> {f x | x IN s} = {g x | x IN s}`) THEN
15860         ASM_SIMP_TAC[IN_DELETE; IN_NUMSEG; LAMBDA_BETA; CART_EQ]]]) in
15861   GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[lemma1] THEN DISCH_TAC THEN
15862   MATCH_MP_TAC(ARITH_RULE
15863    `r <= n /\ ~(r = n) /\ ~(r = n - 1) ==> r < n - 1`) THEN
15864   REPEAT CONJ_TAC THENL
15865    [MP_TAC(ISPEC `A:real^N^N` RANK_BOUND) THEN ARITH_TAC;
15866     REWRITE_TAC[RANK_EQ_FULL_DET] THEN
15867     MP_TAC(SYM(ISPEC `A:real^N^N` MATRIX_MUL_LEFT_COFACTOR)) THEN
15868     ASM_REWRITE_TAC[MATRIX_CMUL_EQ_0; TRANSP_MAT; MATRIX_MUL_LZERO] THEN
15869     REWRITE_TAC[MAT_EQ; ARITH_EQ];
15870     DISCH_TAC] THEN
15871   MP_TAC(ISPEC `A:real^N^N` lemma2) THEN
15872   ASM_REWRITE_TAC[DIMINDEX_GE_1; ARITH_RULE `n - 1 < n <=> 1 <= n`] THEN
15873   DISCH_THEN(X_CHOOSE_THEN `n:num` (X_CHOOSE_THEN `x:real^N`
15874     STRIP_ASSUME_TAC)) THEN
15875   FIRST_ASSUM(MP_TAC o MATCH_MP (ARITH_RULE
15876    `n - 1 < k ==> k <= MIN n n ==> k = n`)) THEN
15877   REWRITE_TAC[RANK_BOUND; RANK_EQ_FULL_DET] THEN
15878   MP_TAC(GEN `A:real^N^N` (ISPECL [`A:real^N^N`; `n:num`]
15879     DET_COFACTOR_EXPANSION)) THEN
15880   ASM_SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC) THEN MATCH_MP_TAC SUM_EQ_0 THEN
15881   X_GEN_TAC `m:num` THEN SIMP_TAC[IN_NUMSEG; REAL_ENTIRE] THEN STRIP_TAC THEN
15882   DISJ2_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CART_EQ]) THEN
15883   DISCH_THEN(MP_TAC o SPEC `n:num`) THEN ASM_REWRITE_TAC[CART_EQ] THEN
15884   DISCH_THEN(MP_TAC o SPEC `m:num`) THEN
15885   ASM_SIMP_TAC[MAT_COMPONENT; COND_ID] THEN
15886   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EQ_TRANS) THEN
15887   ASM_SIMP_TAC[cofactor; LAMBDA_BETA] THEN AP_TERM_TAC THEN
15888   ASM_SIMP_TAC[CART_EQ; LAMBDA_BETA; row] THEN
15889   REPEAT STRIP_TAC THEN
15890   REPEAT(COND_CASES_TAC THEN ASM_SIMP_TAC[LAMBDA_BETA]) THEN
15891   ASM_MESON_TAC[]);;
15892
15893 let RANK_COFACTOR_EQ_1 = prove
15894  (`!A:real^N^N. rank(cofactor A) = 1 <=>
15895                 dimindex(:N) = 1 \/ rank A = dimindex(:N) - 1`,
15896   GEN_TAC THEN ASM_CASES_TAC `dimindex(:N) = 1` THENL
15897    [ASM_MESON_TAC[RANK_COFACTOR_EQ_FULL]; ASM_REWRITE_TAC[]] THEN
15898   EQ_TAC THENL
15899    [ASM_CASES_TAC `cofactor A:real^N^N = mat 0` THEN
15900     ASM_REWRITE_TAC[RANK_0; ARITH_EQ] THEN DISCH_TAC THEN
15901     MATCH_MP_TAC(ARITH_RULE
15902      `~(r < n - 1) /\ ~(r = n) /\ r <= MIN n n ==> r = n - 1`) THEN
15903     ASM_REWRITE_TAC[RANK_BOUND; GSYM COFACTOR_EQ_0] THEN
15904     MP_TAC(ISPEC `A:real^N^N` RANK_COFACTOR_EQ_FULL) THEN ASM_REWRITE_TAC[];
15905     DISCH_TAC THEN MATCH_MP_TAC(ARITH_RULE
15906      `~(n = 0) /\ n <= 1 ==> n = 1`) THEN
15907     ASM_REWRITE_TAC[RANK_EQ_0; COFACTOR_EQ_0; LT_REFL] THEN
15908     MP_TAC(ISPECL [`A:real^N^N`; `transp(cofactor A):real^N^N`]
15909       RANK_SYLVESTER) THEN
15910     ASM_REWRITE_TAC[MATRIX_MUL_RIGHT_COFACTOR; RANK_TRANSP] THEN
15911     FIRST_ASSUM(MP_TAC o MATCH_MP (ARITH_RULE
15912      `a = n - 1 ==> 1 <= n ==> a < n`)) THEN
15913     ASM_SIMP_TAC[GSYM DET_EQ_0_RANK; DIMINDEX_GE_1] THEN
15914     DISCH_TAC THEN REWRITE_TAC[MATRIX_CMUL_LZERO; RANK_0] THEN
15915     ARITH_TAC]);;
15916
15917 let RANK_COFACTOR = prove
15918  (`!A:real^N^N.
15919         rank(cofactor A) = if rank(A) = dimindex(:N) then dimindex(:N)
15920                            else if rank(A) = dimindex(:N) - 1 then 1
15921                            else 0`,
15922   GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[RANK_COFACTOR_EQ_FULL] THEN
15923   COND_CASES_TAC THEN ASM_REWRITE_TAC[RANK_COFACTOR_EQ_1] THEN
15924   REWRITE_TAC[RANK_EQ_0; COFACTOR_EQ_0] THEN
15925   MATCH_MP_TAC(ARITH_RULE
15926    `r <= MIN n n /\ ~(r = n) /\ ~(r = n - 1) ==> r < n - 1`) THEN
15927   ASM_REWRITE_TAC[RANK_BOUND]);;
15928
15929 (* ------------------------------------------------------------------------- *)
15930 (* Not in so many words, but combining this with intermediate value theorem  *)
15931 (* implies the determinant is an open map.                                   *)
15932 (* ------------------------------------------------------------------------- *)
15933
15934 let DET_OPEN_MAP = prove
15935  (`!A:real^N^N e.
15936         &0 < e
15937         ==> (?B:real^N^N. (!i j. abs(B$i$j - A$i$j) < e) /\ det B < det A) /\
15938             (?C:real^N^N. (!i j. abs(C$i$j - A$i$j) < e) /\ det C > det A)`,
15939   let lemma1 = prove
15940    (`!A:real^N^N i e.
15941           1 <= i /\ i <= dimindex(:N) /\ row i A = vec 0 /\ &0 < e
15942           ==> (?B:real^N^N. (!i j. abs(B$i$j - A$i$j) < e) /\ det B < &0) /\
15943               (?C:real^N^N. (!i j. abs(C$i$j - A$i$j) < e) /\ det C > &0)`,
15944     REPEAT GEN_TAC THEN STRIP_TAC THEN
15945     SUBGOAL_THEN `det(A:real^N^N) = &0` ASSUME_TAC THENL
15946      [ASM_MESON_TAC[DET_ZERO_ROW]; ALL_TAC] THEN
15947     MP_TAC(ISPEC `A:real^N^N` NEARBY_INVERTIBLE_MATRIX) THEN
15948     DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
15949     FIRST_X_ASSUM(MP_TAC o SPEC `min d e / &2`) THEN
15950     ANTS_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[INVERTIBLE_DET_NZ]] THEN
15951     DISCH_THEN(STRIP_ASSUME_TAC o MATCH_MP (REAL_ARITH
15952      `~(x = &0) ==> x < &0 \/ &0 < x`))
15953     THENL [ALL_TAC; ONCE_REWRITE_TAC[CONJ_SYM]] THEN
15954     (CONJ_TAC THENL
15955        [EXISTS_TAC `A + min d e / &2 %% mat 1:real^N^N`;
15956         EXISTS_TAC `(lambda j. if j = i then
15957                          --(&1) % row i (A + min d e / &2 %% mat 1:real^N^N)
15958                          else row j (A + min d e / &2 %% mat 1:real^N^N))
15959                     :real^N^N`]) THEN
15960     ASM_SIMP_TAC[DET_ROW_MUL; MESON[]
15961      `(if j = i then f i else f j) = f j`] THEN
15962     REWRITE_TAC[row; LAMBDA_ETA] THEN
15963     ASM_REWRITE_TAC[real_gt; GSYM row] THEN
15964     TRY(CONJ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC]) THEN
15965     (MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN
15966      SUBGOAL_THEN `?k. 1 <= k /\ k <= dimindex(:N) /\ !A:real^N^N. A$m = A$k`
15967      CHOOSE_TAC THENL [REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
15968      SUBGOAL_THEN `?l. 1 <= l /\ l <= dimindex(:N) /\ !z:real^N. z$n = z$l`
15969      CHOOSE_TAC THENL [REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC]) THEN
15970     ASM_SIMP_TAC[LAMBDA_BETA] THEN
15971     TRY COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
15972     ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT; MAT_COMPONENT;
15973                  VECTOR_MUL_COMPONENT] THEN
15974     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CART_EQ]) THEN
15975     DISCH_THEN(MP_TAC o SPEC `l:num`) THEN
15976     ASM_SIMP_TAC[row; LAMBDA_BETA; VEC_COMPONENT] THEN
15977     COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC)
15978   and lemma2 = prove
15979    (`!A:real^N^N x:real^N i.
15980           1 <= i /\ i <= dimindex(:N) /\ x$i = &1
15981           ==> det(lambda k. if k = i then transp A ** x else row k A) = det A`,
15982     REPEAT STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
15983     EXISTS_TAC
15984      `det(lambda k. if k = i
15985                     then row i (A:real^N^N) + (transp A ** x - row i A)
15986                     else row k A)` THEN
15987     CONJ_TAC THENL
15988      [REWRITE_TAC[VECTOR_ARITH `r + (x - r):real^N = x`]; ALL_TAC] THEN
15989     MATCH_MP_TAC DET_ROW_SPAN THEN
15990     SUBGOAL_THEN
15991      `transp(A:real^N^N) ** x - row i A =
15992       vsum ((1..dimindex(:N)) DELETE i) (\k. x$k % row k A)`
15993     SUBST1_TAC THENL
15994      [SIMP_TAC[CART_EQ; VSUM_COMPONENT; VECTOR_SUB_COMPONENT; row; transp;
15995                LAMBDA_BETA; matrix_vector_mul; VECTOR_MUL_COMPONENT] THEN
15996       ASM_SIMP_TAC[SUM_DELETE; IN_NUMSEG; FINITE_NUMSEG; REAL_MUL_LID] THEN
15997       REWRITE_TAC[REAL_MUL_AC];
15998       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SPAN_VSUM THEN
15999       REWRITE_TAC[FINITE_DELETE; IN_DELETE; IN_NUMSEG; FINITE_NUMSEG] THEN
16000       X_GEN_TAC `j:num` THEN STRIP_TAC THEN MATCH_MP_TAC SPAN_MUL THEN
16001       MATCH_MP_TAC SPAN_SUPERSET THEN ASM SET_TAC[]]) in
16002   REPEAT GEN_TAC THEN DISCH_TAC THEN
16003   ASM_CASES_TAC `cofactor(A:real^N^N) = mat 0` THENL
16004    [MP_TAC(SYM(ISPEC `A:real^N^N` MATRIX_MUL_LEFT_COFACTOR)) THEN
16005     ASM_REWRITE_TAC[MATRIX_CMUL_EQ_0; TRANSP_MAT; MATRIX_MUL_LZERO] THEN
16006     REWRITE_TAC[MAT_EQ; ARITH_EQ] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
16007     SUBGOAL_THEN
16008      `?c i. 1 <= i /\ i <= dimindex(:N) /\ c$i = &1 /\
16009             transp(A:real^N^N) ** c = vec 0`
16010     STRIP_ASSUME_TAC THENL
16011      [MP_TAC(ISPEC `transp A:real^N^N` HOMOGENEOUS_LINEAR_EQUATIONS_DET) THEN
16012       ASM_REWRITE_TAC[DET_TRANSP] THEN
16013       DISCH_THEN(X_CHOOSE_THEN `c:real^N` STRIP_ASSUME_TAC) THEN
16014       ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
16015       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [CART_EQ]) THEN
16016       REWRITE_TAC[VEC_COMPONENT; NOT_IMP; NOT_FORALL_THM] THEN
16017       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
16018       EXISTS_TAC `inv(c$i) % c:real^N` THEN
16019       ASM_SIMP_TAC[VECTOR_MUL_COMPONENT; REAL_MUL_LINV] THEN
16020       ASM_REWRITE_TAC[MATRIX_VECTOR_MUL_RMUL; VECTOR_MUL_RZERO];
16021       ALL_TAC] THEN
16022     MP_TAC(ISPECL
16023     [`(lambda k. if k = i then transp A ** c else row k (A:real^N^N)):real^N^N`;
16024      `i:num`; `min e (e / &(dimindex(:N)) /
16025                       (&1 + norm(&2 % basis i - c:real^N)))`] lemma1) THEN
16026     ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1;
16027                  NORM_ARITH `&0 < &1 + norm(x:real^N)`] THEN
16028     ANTS_TAC THENL
16029      [ASM_SIMP_TAC[row; CART_EQ; VEC_COMPONENT; LAMBDA_BETA];
16030       ALL_TAC] THEN
16031     MATCH_MP_TAC MONO_AND THEN CONJ_TAC THEN
16032     ABBREV_TAC `A':real^N^N =
16033                 lambda k. if k = i then vec 0 else row k (A:real^N^N)` THEN
16034     DISCH_THEN(X_CHOOSE_THEN `B:real^N^N` STRIP_ASSUME_TAC) THEN
16035     EXISTS_TAC `(lambda k. if k = i then transp(B:real^N^N) **
16036                                          (&2 % basis i - c)
16037                            else row k B):real^N^N` THEN
16038     ASM_SIMP_TAC[lemma2; BASIS_COMPONENT; VECTOR_MUL_COMPONENT;
16039                  VECTOR_SUB_COMPONENT; REAL_ARITH `&2 * x - x = x`] THEN
16040     (MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN
16041      SUBGOAL_THEN `?k. 1 <= k /\ k <= dimindex(:N) /\ !A:real^N^N. A$m = A$k`
16042      CHOOSE_TAC THENL [REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
16043      SUBGOAL_THEN `?l. 1 <= l /\ l <= dimindex(:N) /\ !z:real^N. z$n = z$l`
16044      CHOOSE_TAC THENL [REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC]) THEN
16045     EXPAND_TAC "A'" THEN ASM_SIMP_TAC[LAMBDA_BETA] THEN
16046     (COND_CASES_TAC THENL
16047       [ALL_TAC;
16048        FIRST_X_ASSUM(MP_TAC o SPECL [`k:num`; `l:num`]) THEN
16049        EXPAND_TAC "A'" THEN ASM_SIMP_TAC[LAMBDA_BETA; row]] THEN
16050      SUBGOAL_THEN
16051       `(A:real^N^N)$k$l = (transp(A':real^N^N) ** (&2 % basis i - c:real^N))$l`
16052      SUBST1_TAC THENL
16053       [ASM_SIMP_TAC[matrix_vector_mul; transp; LAMBDA_BETA] THEN
16054        EXPAND_TAC "A'" THEN ASM_SIMP_TAC[LAMBDA_BETA] THEN
16055        REWRITE_TAC[COND_RAND; COND_RATOR] THEN
16056        SIMP_TAC[VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT; BASIS_COMPONENT;
16057          VEC_COMPONENT; REAL_MUL_RZERO; REAL_SUB_LZERO; REAL_MUL_LZERO] THEN
16058        ASM_SIMP_TAC[SUM_CASES; FINITE_NUMSEG; SUM_0; REAL_ADD_LID] THEN
16059        ASM_SIMP_TAC[GSYM DELETE; SUM_DELETE; IN_NUMSEG; FINITE_NUMSEG] THEN
16060        UNDISCH_TAC `transp(A:real^N^N) ** (c:real^N) = vec 0` THEN
16061        ASM_SIMP_TAC[CART_EQ; VEC_COMPONENT; matrix_vector_mul; LAMBDA_BETA;
16062                     row; transp] THEN
16063        DISCH_THEN(MP_TAC o SPEC `l:num`) THEN ASM_REWRITE_TAC[] THEN
16064        SIMP_TAC[REAL_MUL_RNEG; SUM_NEG] THEN REAL_ARITH_TAC;
16065        REWRITE_TAC[GSYM VECTOR_SUB_COMPONENT; GSYM TRANSP_MATRIX_SUB;
16066                    GSYM MATRIX_VECTOR_MUL_SUB_RDISTRIB]] THEN
16067       ASM_SIMP_TAC[matrix_vector_mul; transp; LAMBDA_BETA] THEN
16068       W(MP_TAC o PART_MATCH lhand SUM_ABS_NUMSEG o lhand o snd) THEN
16069       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LET_TRANS) THEN
16070       MATCH_MP_TAC SUM_BOUND_LT_GEN THEN
16071       ASM_SIMP_TAC[FINITE_NUMSEG; NUMSEG_EMPTY;
16072                    GSYM NOT_LE; DIMINDEX_GE_1] THEN
16073       X_GEN_TAC `r:num` THEN REWRITE_TAC[CARD_NUMSEG_1; IN_NUMSEG] THEN
16074       STRIP_TAC THEN REWRITE_TAC[REAL_ABS_MUL] THEN
16075       TRANS_TAC REAL_LET_TRANS
16076        `abs((B - A':real^N^N)$r$l) * (&1 + norm(&2 % basis i - c:real^N))` THEN
16077       CONJ_TAC THENL
16078        [MATCH_MP_TAC REAL_LE_LMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN
16079         MATCH_MP_TAC(REAL_ARITH `a <= b ==> a <= &1 + b`) THEN
16080         ASM_SIMP_TAC[COMPONENT_LE_NORM];
16081         ASM_SIMP_TAC[MATRIX_SUB_COMPONENT; GSYM REAL_LT_RDIV_EQ;
16082                      NORM_ARITH `&0 < &1 + norm(x:real^N)`]]);
16083     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [CART_EQ]) THEN
16084     SIMP_TAC[CART_EQ; MAT_COMPONENT; COND_ID] THEN
16085     REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; real_gt] THEN
16086     DISCH_THEN(X_CHOOSE_THEN `i:num` (CONJUNCTS_THEN2 STRIP_ASSUME_TAC
16087      (X_CHOOSE_THEN `j:num` STRIP_ASSUME_TAC))) THEN
16088     FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
16089      `~(x = &0) ==> &0 < x \/ x < &0`))
16090     THENL [ALL_TAC; ONCE_REWRITE_TAC[CONJ_SYM]] THEN
16091     (CONJ_TAC THENL
16092      [EXISTS_TAC `(lambda m n. if m = i /\ n = j
16093                                then (A:real^N^N)$i$j -
16094                                     e / (&1 + abs(cofactor A$i$j))
16095                                else A$m$n):real^N^N`;
16096       EXISTS_TAC `(lambda m n. if m = i /\ n = j
16097                                then (A:real^N^N)$i$j +
16098                                     e / (&1 + abs(cofactor A$i$j))
16099                                else A$m$n):real^N^N`]) THEN
16100      (CONJ_TAC THENL
16101        [MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN
16102         SUBGOAL_THEN `?k. 1 <= k /\ k <= dimindex(:N) /\ !A:real^N^N. A$m = A$k`
16103         CHOOSE_TAC THENL [REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
16104         SUBGOAL_THEN `?l. 1 <= l /\ l <= dimindex(:N) /\ !z:real^N. z$n = z$l`
16105         CHOOSE_TAC THENL [REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
16106         ASM_SIMP_TAC[LAMBDA_BETA] THEN
16107         COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_SUB_REFL; REAL_ABS_NUM] THEN
16108         REWRITE_TAC[REAL_ARITH `abs(a - e - a) = abs e`;
16109                     REAL_ARITH `abs((a + e) - a) = abs e`] THEN
16110         REWRITE_TAC[REAL_ABS_DIV; REAL_ABS_NUM; REAL_ABS_ABS] THEN
16111         ASM_SIMP_TAC[REAL_ARITH `abs(&1 + abs x) = &1 + abs x`;
16112                      REAL_LT_LDIV_EQ; REAL_ARITH `&0 < &1 + abs x`] THEN
16113         MATCH_MP_TAC(REAL_ARITH
16114          `&0 < e /\ &0 < e * x ==> abs e < e * (&1 + x)`) THEN
16115         ASM_SIMP_TAC[REAL_LT_MUL_EQ] THEN ASM_REAL_ARITH_TAC;
16116         ALL_TAC]) THEN
16117     MP_TAC(GEN `A:real^N^N` (SPECL [`A:real^N^N`; `i:num`]
16118         DET_COFACTOR_EXPANSION)) THEN
16119     ASM_SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC) THEN
16120     ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
16121     ASM_SIMP_TAC[GSYM SUM_SUB_NUMSEG; LAMBDA_BETA] THEN
16122     REWRITE_TAC[REAL_ARITH `p - A$i$j * cofactor A$i$j =
16123                             --(A$i$j * cofactor A$i$j - p)`] THEN
16124     REWRITE_TAC[SUM_NEG; REAL_ARITH
16125      `a * b - c * d:real = b * (a - c) + c * (b - d)`] THEN
16126     REWRITE_TAC[SUM_ADD_NUMSEG; REAL_NEG_ADD] THEN MATCH_MP_TAC(REAL_ARITH
16127      `b = &0 /\ &0 < a ==> &0 < a + b`) THEN
16128     (CONJ_TAC THENL
16129       [REWRITE_TAC[REAL_NEG_EQ_0] THEN
16130        MATCH_MP_TAC SUM_EQ_0 THEN X_GEN_TAC `m:num` THEN
16131        REWRITE_TAC[IN_NUMSEG; REAL_ENTIRE] THEN STRIP_TAC THEN DISJ2_TAC THEN
16132        REWRITE_TAC[REAL_SUB_0] THEN REWRITE_TAC[cofactor] THEN
16133        ASM_SIMP_TAC[LAMBDA_BETA] THEN AP_TERM_TAC THEN
16134        ASM_SIMP_TAC[CART_EQ; LAMBDA_BETA] THEN ASM_MESON_TAC[];
16135        ALL_TAC]) THEN
16136     REWRITE_TAC[GSYM SUM_NEG; GSYM REAL_MUL_RNEG] THEN
16137     MATCH_MP_TAC SUM_POS_LT THEN REWRITE_TAC[FINITE_NUMSEG] THEN
16138     MATCH_MP_TAC(MESON[REAL_LT_IMP_LE; REAL_LE_REFL]
16139      `(?i. P i /\ &0 < f i /\ (!j. P j /\ ~(j = i) ==> f j = &0))
16140       ==> (!j. P j ==> &0 <= f j) /\ (?j. P j /\ &0 < f j)`) THEN
16141     EXISTS_TAC `j:num` THEN ASM_REWRITE_TAC[FINITE_NUMSEG] THEN
16142     ASM_SIMP_TAC[REAL_SUB_REFL; REAL_MUL_RZERO; IN_NUMSEG; REAL_NEG_0] THEN
16143     REWRITE_TAC[REAL_ARITH `a - (a + e):real = --e`;
16144                 REAL_ARITH `a - (a - e):real = e`; REAL_NEG_NEG] THEN
16145     ASM_SIMP_TAC[REAL_LT_MUL_EQ] THEN
16146     REWRITE_TAC[REAL_ARITH `&0 < a * --b <=> &0 < --a * b`] THEN
16147     ASM_SIMP_TAC[REAL_LT_MUL_EQ; REAL_NEG_GT0] THEN
16148     MATCH_MP_TAC REAL_LT_DIV THEN ASM_REAL_ARITH_TAC]);;
16149
16150 (* ------------------------------------------------------------------------- *)
16151 (* Infinite sums of vectors. Allow general starting point (and more).        *)
16152 (* ------------------------------------------------------------------------- *)
16153
16154 parse_as_infix("sums",(12,"right"));;
16155
16156 let sums = new_definition
16157   `(f sums l) s = ((\n. vsum(s INTER (0..n)) f) --> l) sequentially`;;
16158
16159 let infsum = new_definition
16160  `infsum s f = @l. (f sums l) s`;;
16161
16162 let summable = new_definition
16163  `summable s f = ?l. (f sums l) s`;;
16164
16165 let SUMS_SUMMABLE = prove
16166  (`!f l s. (f sums l) s ==> summable s f`,
16167   REWRITE_TAC[summable] THEN MESON_TAC[]);;
16168
16169 let SUMS_INFSUM = prove
16170  (`!f s. (f sums (infsum s f)) s <=> summable s f`,
16171   REWRITE_TAC[infsum; summable] THEN MESON_TAC[]);;
16172
16173 let SUMS_LIM = prove
16174  (`!f:num->real^N s.
16175       (f sums lim sequentially (\n. vsum (s INTER (0..n)) f)) s
16176       <=> summable s f`,
16177   GEN_TAC THEN GEN_TAC THEN EQ_TAC THENL [MESON_TAC[summable];
16178   REWRITE_TAC[summable; sums] THEN STRIP_TAC THEN REWRITE_TAC[lim] THEN
16179   ASM_MESON_TAC[]]);;
16180
16181 let FINITE_INTER_NUMSEG = prove
16182  (`!s m n. FINITE(s INTER (m..n))`,
16183   MESON_TAC[FINITE_SUBSET; FINITE_NUMSEG; INTER_SUBSET]);;
16184
16185 let SERIES_FROM = prove
16186  (`!f l k. (f sums l) (from k) = ((\n. vsum(k..n) f) --> l) sequentially`,
16187   REPEAT GEN_TAC THEN REWRITE_TAC[sums] THEN
16188   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN
16189   AP_THM_TAC THEN AP_TERM_TAC THEN
16190   REWRITE_TAC[EXTENSION; numseg; from; IN_ELIM_THM; IN_INTER] THEN ARITH_TAC);;
16191
16192 let SERIES_UNIQUE = prove
16193  (`!f:num->real^N l l' s. (f sums l) s /\ (f sums l') s ==> (l = l')`,
16194   REWRITE_TAC[sums] THEN MESON_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; LIM_UNIQUE]);;
16195
16196 let INFSUM_UNIQUE = prove
16197  (`!f:num->real^N l s. (f sums l) s ==> infsum s f = l`,
16198   MESON_TAC[SERIES_UNIQUE; SUMS_INFSUM; summable]);;
16199
16200 let SERIES_TERMS_TOZERO = prove
16201  (`!f l n. (f sums l) (from n) ==> (f --> vec 0) sequentially`,
16202   REPEAT GEN_TAC THEN SIMP_TAC[sums; LIM_SEQUENTIALLY; FROM_INTER_NUMSEG] THEN
16203   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
16204   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
16205   ASM_REWRITE_TAC[REAL_HALF] THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN
16206   EXISTS_TAC `N + n + 1` THEN X_GEN_TAC `m:num` THEN DISCH_TAC THEN
16207   FIRST_X_ASSUM(fun th ->
16208     MP_TAC(SPEC `m - 1` th) THEN MP_TAC(SPEC `m:num` th)) THEN
16209   SUBGOAL_THEN `0 < m /\ n <= m` (fun th -> SIMP_TAC[VSUM_CLAUSES_RIGHT; th])
16210   THENL [ASM_ARITH_TAC; ALL_TAC] THEN
16211   REPEAT(ANTS_TAC THENL [ASM_ARITH_TAC; DISCH_TAC]) THEN
16212   REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
16213
16214 let SERIES_FINITE = prove
16215  (`!f s. FINITE s ==> (f sums (vsum s f)) s`,
16216   REPEAT GEN_TAC THEN REWRITE_TAC[num_FINITE; LEFT_IMP_EXISTS_THM] THEN
16217   X_GEN_TAC `n:num` THEN REWRITE_TAC[sums; LIM_SEQUENTIALLY] THEN
16218   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `n:num` THEN
16219   X_GEN_TAC `m:num` THEN DISCH_TAC THEN
16220   SUBGOAL_THEN `s INTER (0..m) = s`
16221    (fun th -> ASM_REWRITE_TAC[th; DIST_REFL]) THEN
16222   REWRITE_TAC[EXTENSION; IN_INTER; IN_NUMSEG; LE_0] THEN
16223   ASM_MESON_TAC[LE_TRANS]);;
16224
16225 let SERIES_LINEAR = prove
16226  (`!f h l s. (f sums l) s /\ linear h ==> ((\n. h(f n)) sums h l) s`,
16227   SIMP_TAC[sums; LIM_LINEAR; FINITE_INTER; FINITE_NUMSEG;
16228            GSYM(REWRITE_RULE[o_DEF] LINEAR_VSUM)]);;
16229
16230 let SERIES_0 = prove
16231  (`!s. ((\n. vec 0) sums (vec 0)) s`,
16232   REWRITE_TAC[sums; VSUM_0; LIM_CONST]);;
16233
16234 let SERIES_ADD = prove
16235  (`!x x0 y y0 s.
16236      (x sums x0) s /\ (y sums y0) s ==> ((\n. x n + y n) sums (x0 + y0)) s`,
16237   SIMP_TAC[sums; FINITE_INTER_NUMSEG; VSUM_ADD; LIM_ADD]);;
16238
16239 let SERIES_SUB = prove
16240  (`!x x0 y y0 s.
16241      (x sums x0) s /\ (y sums y0) s ==> ((\n. x n - y n) sums (x0 - y0)) s`,
16242   SIMP_TAC[sums; FINITE_INTER_NUMSEG; VSUM_SUB; LIM_SUB]);;
16243
16244 let SERIES_CMUL = prove
16245  (`!x x0 c s. (x sums x0) s ==> ((\n. c % x n) sums (c % x0)) s`,
16246   SIMP_TAC[sums; FINITE_INTER_NUMSEG; VSUM_LMUL; LIM_CMUL]);;
16247
16248 let SERIES_NEG = prove
16249  (`!x x0 s. (x sums x0) s ==> ((\n. --(x n)) sums (--x0)) s`,
16250   SIMP_TAC[sums; FINITE_INTER_NUMSEG; VSUM_NEG; LIM_NEG]);;
16251
16252 let SUMS_IFF = prove
16253  (`!f g k. (!x. x IN k ==> f x = g x) ==> ((f sums l) k <=> (g sums l) k)`,
16254   REPEAT STRIP_TAC THEN REWRITE_TAC[sums] THEN
16255   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN
16256   MATCH_MP_TAC VSUM_EQ THEN ASM_SIMP_TAC[IN_INTER]);;
16257
16258 let SUMS_EQ = prove
16259  (`!f g k. (!x. x IN k ==> f x = g x) /\ (f sums l) k ==> (g sums l) k`,
16260   MESON_TAC[SUMS_IFF]);;
16261
16262 let SUMS_0 = prove
16263  (`!f:num->real^N s. (!n. n IN s ==> f n = vec 0) ==> (f sums vec 0) s`,
16264   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUMS_EQ THEN
16265   EXISTS_TAC `\n:num. vec 0:real^N` THEN ASM_SIMP_TAC[SERIES_0]);;
16266
16267 let SERIES_FINITE_SUPPORT = prove
16268  (`!f:num->real^N s k.
16269      FINITE (s INTER k) /\ (!x. x IN k /\ ~(x IN s) ==> f x = vec 0)
16270      ==> (f sums vsum (s INTER k) f) k`,
16271   REWRITE_TAC[sums; LIM_SEQUENTIALLY] THEN REPEAT STRIP_TAC THEN
16272   FIRST_ASSUM(MP_TAC o ISPEC `\x:num. x` o MATCH_MP UPPER_BOUND_FINITE_SET) THEN
16273   REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
16274   STRIP_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
16275   SUBGOAL_THEN `vsum (k INTER (0..n)) (f:num->real^N) = vsum(s INTER k) f`
16276    (fun th -> ASM_REWRITE_TAC[DIST_REFL; th]) THEN
16277   MATCH_MP_TAC VSUM_SUPERSET THEN
16278   ASM_SIMP_TAC[SUBSET; IN_INTER; IN_NUMSEG; LE_0] THEN
16279   ASM_MESON_TAC[IN_INTER; LE_TRANS]);;
16280
16281 let SERIES_COMPONENT = prove
16282  (`!f s l:real^N k. (f sums l) s /\ 1 <= k /\ k <= dimindex(:N)
16283                     ==> ((\i. lift(f(i)$k)) sums lift(l$k)) s`,
16284   REPEAT GEN_TAC THEN REWRITE_TAC[sums] THEN STRIP_TAC THEN
16285   ONCE_REWRITE_TAC[GSYM o_DEF] THEN
16286   ASM_SIMP_TAC[GSYM LIFT_SUM; GSYM VSUM_COMPONENT;
16287                FINITE_INTER; FINITE_NUMSEG] THEN
16288   ASM_SIMP_TAC[o_DEF; LIM_COMPONENT]);;
16289
16290 let SERIES_DIFFS = prove
16291  (`!f:num->real^N k.
16292         (f --> vec 0) sequentially
16293         ==> ((\n. f(n) - f(n + 1)) sums f(k)) (from k)`,
16294   REWRITE_TAC[sums; FROM_INTER_NUMSEG; VSUM_DIFFS] THEN
16295   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_TRANSFORM_EVENTUALLY THEN
16296   EXISTS_TAC `\n. (f:num->real^N) k - f(n + 1)` THEN CONJ_TAC THENL
16297    [REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN EXISTS_TAC `k:num` THEN
16298     SIMP_TAC[];
16299     GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_SUB_RZERO] THEN
16300     MATCH_MP_TAC LIM_SUB THEN REWRITE_TAC[LIM_CONST] THEN
16301     MATCH_MP_TAC SEQ_OFFSET THEN ASM_REWRITE_TAC[]]);;
16302
16303 let SERIES_TRIVIAL = prove
16304  (`!f. (f sums vec 0) {}`,
16305   REWRITE_TAC[sums; INTER_EMPTY; VSUM_CLAUSES; LIM_CONST]);;
16306
16307 let SERIES_RESTRICT = prove
16308  (`!f k l:real^N.
16309         ((\n. if n IN k then f(n) else vec 0) sums l) (:num) <=>
16310         (f sums l) k`,
16311   REPEAT GEN_TAC THEN REWRITE_TAC[sums] THEN
16312   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
16313   REWRITE_TAC[FUN_EQ_THM; INTER_UNIV] THEN GEN_TAC THEN
16314   MATCH_MP_TAC(MESON[] `vsum s f = vsum t f /\ vsum t f = vsum t g
16315                         ==> vsum s f = vsum t g`) THEN
16316   CONJ_TAC THENL
16317    [MATCH_MP_TAC VSUM_SUPERSET THEN SET_TAC[];
16318     MATCH_MP_TAC VSUM_EQ THEN SIMP_TAC[IN_INTER]]);;
16319
16320 let SERIES_VSUM = prove
16321  (`!f l k s. FINITE s /\ s SUBSET k /\ (!x. ~(x IN s) ==> f x = vec 0) /\
16322              vsum s f = l ==> (f sums l) k`,
16323   REPEAT STRIP_TAC THEN EXPAND_TAC "l" THEN
16324   SUBGOAL_THEN `s INTER k = s:num->bool` ASSUME_TAC THENL
16325    [ASM SET_TAC []; ASM_MESON_TAC [SERIES_FINITE_SUPPORT]]);;
16326
16327 let SUMS_REINDEX = prove
16328  (`!k a l:real^N n.
16329    ((\x. a(x + k)) sums l) (from n) <=> (a sums l) (from(n + k))`,
16330   REPEAT GEN_TAC THEN REWRITE_TAC[sums; FROM_INTER_NUMSEG] THEN
16331   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM VSUM_OFFSET] THEN
16332   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
16333   ASM_MESON_TAC[ARITH_RULE `N + k:num <= n ==> n = (n - k) + k /\ N <= n - k`;
16334                 ARITH_RULE `N + k:num <= n ==> N <= n + k`]);;
16335
16336 let SUMS_REINDEX_GEN = prove
16337  (`!k a l:real^N s.
16338      ((\x. a(x + k)) sums l) s <=> (a sums l) (IMAGE (\i. i + k) s)`,
16339   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM SERIES_RESTRICT] THEN
16340   MP_TAC(ISPECL
16341    [`k:num`;
16342     `\i. if i IN IMAGE (\i. i + k) s then (a:num->real^N) i else vec 0`;
16343     `l:real^N`; `0`] SUMS_REINDEX) THEN
16344   REWRITE_TAC[FROM_0] THEN
16345   SIMP_TAC[EQ_ADD_RCANCEL; SET_RULE
16346    `(!x y:num. x + k = y + k <=> x = y)
16347          ==> ((x + k) IN IMAGE (\i. i + k) s <=> x IN s)`] THEN
16348   DISCH_THEN SUBST1_TAC THEN
16349   GEN_REWRITE_TAC LAND_CONV [GSYM SERIES_RESTRICT] THEN
16350   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
16351   REWRITE_TAC[FUN_EQ_THM; IN_FROM; ADD_CLAUSES] THEN
16352   SUBGOAL_THEN `!x:num. x IN IMAGE (\i. i + k) s ==> k <= x` MP_TAC THENL
16353    [REWRITE_TAC[FORALL_IN_IMAGE] THEN ARITH_TAC; SET_TAC[]]);;
16354
16355 (* ------------------------------------------------------------------------- *)
16356 (* Similar combining theorems just for summability.                          *)
16357 (* ------------------------------------------------------------------------- *)
16358
16359 let SUMMABLE_LINEAR = prove
16360  (`!f h s. summable s f /\ linear h ==> summable s (\n. h(f n))`,
16361   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_LINEAR]);;
16362
16363 let SUMMABLE_0 = prove
16364  (`!s. summable s (\n. vec 0)`,
16365   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_0]);;
16366
16367 let SUMMABLE_ADD = prove
16368  (`!x y s. summable s x /\ summable s y ==> summable s (\n. x n + y n)`,
16369   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_ADD]);;
16370
16371 let SUMMABLE_SUB = prove
16372  (`!x y s. summable s x /\ summable s y ==> summable s (\n. x n - y n)`,
16373   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_SUB]);;
16374
16375 let SUMMABLE_CMUL = prove
16376  (`!s x c. summable s x ==> summable s (\n. c % x n)`,
16377   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_CMUL]);;
16378
16379 let SUMMABLE_NEG = prove
16380  (`!x s. summable s x ==> summable s (\n. --(x n))`,
16381   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_NEG]);;
16382
16383 let SUMMABLE_IFF = prove
16384  (`!f g k. (!x. x IN k ==> f x = g x) ==> (summable k f <=> summable k g)`,
16385   REWRITE_TAC[summable] THEN MESON_TAC[SUMS_IFF]);;
16386
16387 let SUMMABLE_EQ = prove
16388  (`!f g k. (!x. x IN k ==> f x = g x) /\ summable k f ==> summable k g`,
16389   REWRITE_TAC[summable] THEN MESON_TAC[SUMS_EQ]);;
16390
16391 let SUMMABLE_COMPONENT = prove
16392  (`!f:num->real^N s k.
16393         summable s f /\ 1 <= k /\ k <= dimindex(:N)
16394         ==> summable s (\i. lift(f(i)$k))`,
16395   REPEAT STRIP_TAC THEN
16396   FIRST_X_ASSUM(X_CHOOSE_TAC `l:real^N` o REWRITE_RULE[summable]) THEN
16397   REWRITE_TAC[summable] THEN EXISTS_TAC `lift((l:real^N)$k)` THEN
16398   ASM_SIMP_TAC[SERIES_COMPONENT]);;
16399
16400 let SERIES_SUBSET = prove
16401  (`!x s t l.
16402         s SUBSET t /\
16403         ((\i. if i IN s then x i else vec 0) sums l) t
16404         ==> (x sums l) s`,
16405   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
16406   REWRITE_TAC[sums] THEN MATCH_MP_TAC EQ_IMP THEN
16407   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN
16408   ASM_SIMP_TAC[GSYM VSUM_RESTRICT_SET; FINITE_INTER_NUMSEG] THEN
16409   AP_THM_TAC THEN AP_TERM_TAC THEN POP_ASSUM MP_TAC THEN SET_TAC[]);;
16410
16411 let SUMMABLE_SUBSET = prove
16412  (`!x s t.
16413         s SUBSET t /\
16414         summable t (\i. if i IN s then x i else vec 0)
16415         ==> summable s x`,
16416   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_SUBSET]);;
16417
16418 let SUMMABLE_TRIVIAL = prove
16419  (`!f:num->real^N. summable {} f`,
16420   GEN_TAC THEN REWRITE_TAC[summable] THEN EXISTS_TAC `vec 0:real^N` THEN
16421   REWRITE_TAC[SERIES_TRIVIAL]);;
16422
16423 let SUMMABLE_RESTRICT = prove
16424  (`!f:num->real^N k.
16425         summable (:num) (\n. if n IN k then f(n) else vec 0) <=>
16426         summable k f`,
16427   REWRITE_TAC[summable; SERIES_RESTRICT]);;
16428
16429 let SUMS_FINITE_DIFF = prove
16430  (`!f:num->real^N t s l.
16431         t SUBSET s /\ FINITE t /\ (f sums l) s
16432         ==> (f sums (l - vsum t f)) (s DIFF t)`,
16433   REPEAT GEN_TAC THEN
16434   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
16435   FIRST_ASSUM(MP_TAC o ISPEC `f:num->real^N` o MATCH_MP SERIES_FINITE) THEN
16436   ONCE_REWRITE_TAC[GSYM SERIES_RESTRICT] THEN
16437   REWRITE_TAC[IMP_IMP] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
16438   DISCH_THEN(MP_TAC o MATCH_MP SERIES_SUB) THEN
16439   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
16440   REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `x:num` THEN REWRITE_TAC[IN_DIFF] THEN
16441   FIRST_ASSUM(MP_TAC o SPEC `x:num` o GEN_REWRITE_RULE I [SUBSET]) THEN
16442   MAP_EVERY ASM_CASES_TAC [`(x:num) IN s`; `(x:num) IN t`] THEN
16443   ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC);;
16444
16445 let SUMS_FINITE_UNION = prove
16446  (`!f:num->real^N s t l.
16447         FINITE t /\ (f sums l) s
16448         ==> (f sums (l + vsum (t DIFF s) f)) (s UNION t)`,
16449   REPEAT GEN_TAC THEN
16450   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
16451   FIRST_ASSUM(MP_TAC o SPEC `s:num->bool` o MATCH_MP FINITE_DIFF) THEN
16452   DISCH_THEN(MP_TAC o ISPEC `f:num->real^N` o MATCH_MP SERIES_FINITE) THEN
16453   ONCE_REWRITE_TAC[GSYM SERIES_RESTRICT] THEN
16454   REWRITE_TAC[IMP_IMP] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
16455   DISCH_THEN(MP_TAC o MATCH_MP SERIES_ADD) THEN
16456   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
16457   REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `x:num` THEN
16458   REWRITE_TAC[IN_DIFF; IN_UNION] THEN
16459   MAP_EVERY ASM_CASES_TAC [`(x:num) IN s`; `(x:num) IN t`] THEN
16460   ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC);;
16461
16462 let SUMS_OFFSET = prove
16463  (`!f l:real^N m n.
16464            (f sums l) (from m) /\ 0 < n /\ m <= n
16465            ==> (f sums l - vsum (m..n - 1) f) (from n)`,
16466   REPEAT STRIP_TAC THEN
16467   SUBGOAL_THEN `from n = from m DIFF (m..(n-1))` SUBST1_TAC THENL
16468    [REWRITE_TAC[EXTENSION; IN_FROM; IN_DIFF; IN_NUMSEG] THEN ASM_ARITH_TAC;
16469     MATCH_MP_TAC SUMS_FINITE_DIFF THEN ASM_REWRITE_TAC[FINITE_NUMSEG] THEN
16470     SIMP_TAC[SUBSET; IN_FROM; IN_NUMSEG]]);;
16471
16472 let SUMS_OFFSET_REV = prove
16473  (`!f:num->real^N l m n.
16474         (f sums l) (from m) /\ 0 < m /\ n <= m
16475
16476         ==> (f sums (l + vsum(n..m-1) f)) (from n)`,
16477   REPEAT STRIP_TAC THEN
16478   MP_TAC(ISPECL [`f:num->real^N`; `from m`; `n..m-1`; `l:real^N`]
16479                 SUMS_FINITE_UNION) THEN
16480   ASM_REWRITE_TAC[FINITE_NUMSEG] THEN MATCH_MP_TAC EQ_IMP THEN
16481   BINOP_TAC THENL [AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC; ALL_TAC] THEN
16482   REWRITE_TAC[EXTENSION; IN_DIFF; IN_UNION; IN_FROM; IN_NUMSEG] THEN
16483   ASM_ARITH_TAC);;
16484
16485 let SUMMABLE_REINDEX = prove
16486  (`!k a n. summable (from n) (\x. a (x + k)) <=> summable (from(n + k)) a`,
16487   REWRITE_TAC[summable; GSYM SUMS_REINDEX]);;
16488
16489 let SERIES_DROP_LE = prove
16490  (`!f g s a b.
16491         (f sums a) s /\ (g sums b) s /\
16492         (!x. x IN s ==> drop(f x) <= drop(g x))
16493         ==> drop a <= drop b`,
16494   REWRITE_TAC[sums] THEN REPEAT STRIP_TAC THEN
16495   MATCH_MP_TAC(ISPEC `sequentially` LIM_DROP_LE) THEN
16496   REWRITE_TAC[EVENTUALLY_SEQUENTIALLY; TRIVIAL_LIMIT_SEQUENTIALLY] THEN
16497   EXISTS_TAC `\n. vsum (s INTER (0..n)) (f:num->real^1)` THEN
16498   EXISTS_TAC `\n. vsum (s INTER (0..n)) (g:num->real^1)` THEN
16499   ASM_REWRITE_TAC[DROP_VSUM] THEN EXISTS_TAC `0` THEN REPEAT STRIP_TAC THEN
16500   MATCH_MP_TAC SUM_LE THEN
16501   ASM_SIMP_TAC[FINITE_INTER; FINITE_NUMSEG; o_THM; IN_INTER; IN_NUMSEG]);;
16502
16503 let SERIES_DROP_POS = prove
16504  (`!f s a.
16505         (f sums a) s /\ (!x. x IN s ==> &0 <= drop(f x))
16506         ==> &0 <= drop a`,
16507   REPEAT STRIP_TAC THEN
16508   MP_TAC(ISPECL [`(\n. vec 0):num->real^1`; `f:num->real^1`; `s:num->bool`;
16509                  `vec 0:real^1`; `a:real^1`] SERIES_DROP_LE) THEN
16510   ASM_SIMP_TAC[SUMS_0; DROP_VEC]);;
16511
16512 let SERIES_BOUND = prove
16513  (`!f:num->real^N g s a b.
16514         (f sums a) s /\ ((lift o g) sums (lift b)) s /\
16515         (!i. i IN s ==> norm(f i) <= g i)
16516         ==> norm(a) <= b`,
16517   REWRITE_TAC[sums] THEN REPEAT STRIP_TAC THEN
16518   MATCH_MP_TAC(ISPEC `sequentially` LIM_NORM_UBOUND) THEN
16519   EXISTS_TAC `\n. vsum (s INTER (0..n)) (f:num->real^N)` THEN
16520   ASM_REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY] THEN
16521   REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN EXISTS_TAC `0` THEN
16522   X_GEN_TAC `m:num` THEN DISCH_TAC THEN
16523   TRANS_TAC REAL_LE_TRANS `sum (s INTER (0..m)) g` THEN CONJ_TAC THEN
16524   ASM_SIMP_TAC[VSUM_NORM_LE; IN_INTER; FINITE_NUMSEG; FINITE_INTER] THEN
16525   RULE_ASSUM_TAC(REWRITE_RULE[GSYM sums]) THEN
16526   UNDISCH_TAC `((lift o g) sums lift b) s` THEN
16527   GEN_REWRITE_TAC LAND_CONV [GSYM SERIES_RESTRICT] THEN
16528   REWRITE_TAC[GSYM FROM_0] THEN DISCH_THEN(MP_TAC o SPEC `m + 1` o MATCH_MP
16529    (ONCE_REWRITE_RULE[IMP_CONJ] SUMS_OFFSET)) THEN
16530   ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
16531   REWRITE_TAC[ARITH_RULE `0 < m + 1`; o_DEF; ADD_SUB] THEN
16532   REWRITE_TAC[GSYM VSUM_RESTRICT_SET] THEN
16533   REWRITE_TAC[VSUM_REAL; o_DEF; LIFT_DROP; ETA_AX] THEN
16534   DISCH_THEN(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] SERIES_DROP_POS)) THEN
16535   REWRITE_TAC[DROP_SUB; LIFT_DROP; ONCE_REWRITE_RULE[INTER_COMM] (GSYM INTER);
16536               REAL_SUB_LE] THEN
16537   DISCH_THEN MATCH_MP_TAC THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
16538   ASM_SIMP_TAC[LIFT_DROP; DROP_VEC; REAL_LE_REFL] THEN
16539   ASM_MESON_TAC[NORM_ARITH `norm(x:real^N) <= y ==> &0 <= y`]);;
16540
16541 (* ------------------------------------------------------------------------- *)
16542 (* Similar combining theorems for infsum.                                    *)
16543 (* ------------------------------------------------------------------------- *)
16544
16545 let INFSUM_LINEAR = prove
16546  (`!f h s. summable s f /\ linear h
16547            ==> infsum s (\n. h(f n)) = h(infsum s f)`,
16548   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
16549   MATCH_MP_TAC SERIES_LINEAR THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
16550
16551 let INFSUM_0 = prove
16552  (`infsum s (\i. vec 0) = vec 0`,
16553   MATCH_MP_TAC INFSUM_UNIQUE THEN REWRITE_TAC[SERIES_0]);;
16554
16555 let INFSUM_ADD = prove
16556  (`!x y s. summable s x /\ summable s y
16557            ==> infsum s (\i. x i + y i) = infsum s x + infsum s y`,
16558   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
16559   MATCH_MP_TAC SERIES_ADD THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
16560
16561 let INFSUM_SUB = prove
16562  (`!x y s. summable s x /\ summable s y
16563            ==> infsum s (\i. x i - y i) = infsum s x - infsum s y`,
16564   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
16565   MATCH_MP_TAC SERIES_SUB THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
16566
16567 let INFSUM_CMUL = prove
16568  (`!s x c. summable s x ==> infsum s (\n. c % x n) = c % infsum s x`,
16569   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
16570   MATCH_MP_TAC SERIES_CMUL THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
16571
16572 let INFSUM_NEG = prove
16573  (`!s x. summable s x ==> infsum s (\n. --(x n)) = --(infsum s x)`,
16574   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
16575   MATCH_MP_TAC SERIES_NEG THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
16576
16577 let INFSUM_EQ = prove
16578  (`!f g k. summable k f /\ summable k g /\ (!x. x IN k ==> f x = g x)
16579            ==> infsum k f = infsum k g`,
16580   REPEAT STRIP_TAC THEN REWRITE_TAC[infsum] THEN
16581   AP_TERM_TAC THEN ABS_TAC THEN ASM_MESON_TAC[SUMS_EQ; SUMS_INFSUM]);;
16582
16583 let INFSUM_RESTRICT = prove
16584  (`!k a:num->real^N.
16585         infsum (:num) (\n. if n IN k then a n else vec 0) = infsum k a`,
16586   REPEAT GEN_TAC THEN
16587   MP_TAC(ISPECL [`a:num->real^N`; `k:num->bool`] SUMMABLE_RESTRICT) THEN
16588   ASM_CASES_TAC `summable k (a:num->real^N)` THEN ASM_REWRITE_TAC[] THEN
16589   STRIP_TAC THENL
16590    [MATCH_MP_TAC INFSUM_UNIQUE THEN
16591     ASM_REWRITE_TAC[SERIES_RESTRICT; SUMS_INFSUM];
16592     RULE_ASSUM_TAC(REWRITE_RULE[summable; NOT_EXISTS_THM]) THEN
16593     ASM_REWRITE_TAC[infsum]]);;
16594
16595 let PARTIAL_SUMS_COMPONENT_LE_INFSUM = prove
16596  (`!f:num->real^N s k n.
16597         1 <= k /\ k <= dimindex(:N) /\
16598         (!i. i IN s ==> &0 <= (f i)$k) /\
16599         summable s f
16600         ==> (vsum (s INTER (0..n)) f)$k <= (infsum s f)$k`,
16601   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM SUMS_INFSUM] THEN
16602   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
16603   REWRITE_TAC[sums; LIM_SEQUENTIALLY] THEN DISCH_TAC THEN
16604   REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
16605   FIRST_X_ASSUM(MP_TAC o SPEC
16606    `vsum (s INTER (0..n)) (f:num->real^N)$k - (infsum s f)$k`) THEN
16607   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
16608   DISCH_THEN(X_CHOOSE_THEN `N:num` (MP_TAC o SPEC `N + n:num`)) THEN
16609   REWRITE_TAC[LE_ADD; REAL_NOT_LT; dist] THEN
16610   MATCH_MP_TAC REAL_LE_TRANS THEN
16611   EXISTS_TAC `abs((vsum (s INTER (0..N + n)) f - infsum s f:real^N)$k)` THEN
16612   ASM_SIMP_TAC[COMPONENT_LE_NORM] THEN REWRITE_TAC[VECTOR_SUB_COMPONENT] THEN
16613   MATCH_MP_TAC(REAL_ARITH `s < a /\ a <= b ==> a - s <= abs(b - s)`) THEN
16614   ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN
16615   SIMP_TAC[NUMSEG_ADD_SPLIT; LE_0; UNION_OVER_INTER] THEN
16616   W(MP_TAC o PART_MATCH (lhs o rand) VSUM_UNION o lhand o rand o snd) THEN
16617   ANTS_TAC THENL
16618    [SIMP_TAC[FINITE_INTER; FINITE_NUMSEG; DISJOINT; EXTENSION] THEN
16619     REWRITE_TAC[IN_INTER; NOT_IN_EMPTY; IN_NUMSEG] THEN ARITH_TAC;
16620     DISCH_THEN SUBST1_TAC THEN
16621     REWRITE_TAC[REAL_LE_ADDR; VECTOR_ADD_COMPONENT] THEN
16622     ASM_SIMP_TAC[VSUM_COMPONENT] THEN MATCH_MP_TAC SUM_POS_LE THEN
16623     ASM_SIMP_TAC[FINITE_INTER; IN_INTER; FINITE_NUMSEG]]);;
16624
16625 let PARTIAL_SUMS_DROP_LE_INFSUM = prove
16626  (`!f s n.
16627         (!i. i IN s ==> &0 <= drop(f i)) /\
16628         summable s f
16629         ==> drop(vsum (s INTER (0..n)) f) <= drop(infsum s f)`,
16630   REPEAT STRIP_TAC THEN REWRITE_TAC[drop] THEN
16631   MATCH_MP_TAC PARTIAL_SUMS_COMPONENT_LE_INFSUM THEN
16632   ASM_REWRITE_TAC[DIMINDEX_1; LE_REFL; GSYM drop]);;
16633
16634 (* ------------------------------------------------------------------------- *)
16635 (* Cauchy criterion for series.                                              *)
16636 (* ------------------------------------------------------------------------- *)
16637
16638 let SEQUENCE_CAUCHY_WLOG = prove
16639  (`!P s. (!m n:num. P m /\ P n ==> dist(s m,s n) < e) <=>
16640          (!m n. P m /\ P n /\ m <= n ==> dist(s m,s n) < e)`,
16641   MESON_TAC[DIST_SYM; LE_CASES]);;
16642
16643 let VSUM_DIFF_LEMMA = prove
16644  (`!f:num->real^N k m n.
16645         m <= n
16646         ==> vsum(k INTER (0..n)) f - vsum(k INTER (0..m)) f =
16647             vsum(k INTER (m+1..n)) f`,
16648   REPEAT STRIP_TAC THEN
16649   MP_TAC(ISPECL [`f:num->real^N`; `k INTER (0..n)`; `k INTER (0..m)`]
16650     VSUM_DIFF) THEN
16651   ANTS_TAC THENL
16652    [SIMP_TAC[FINITE_INTER; FINITE_NUMSEG] THEN MATCH_MP_TAC
16653      (SET_RULE `s SUBSET t ==> (u INTER s SUBSET u INTER t)`) THEN
16654     REWRITE_TAC[SUBSET; IN_NUMSEG] THEN POP_ASSUM MP_TAC THEN ARITH_TAC;
16655     DISCH_THEN(SUBST1_TAC o SYM) THEN AP_THM_TAC THEN AP_TERM_TAC THEN
16656     REWRITE_TAC[SET_RULE
16657      `(k INTER s) DIFF (k INTER t) = k INTER (s DIFF t)`] THEN
16658     AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_DIFF; IN_NUMSEG] THEN
16659     POP_ASSUM MP_TAC THEN ARITH_TAC]);;
16660
16661 let NORM_VSUM_TRIVIAL_LEMMA = prove
16662  (`!e. &0 < e ==> (P ==> norm(vsum(s INTER (m..n)) f) < e <=>
16663                    P ==> n < m \/ norm(vsum(s INTER (m..n)) f) < e)`,
16664   REPEAT STRIP_TAC THEN ASM_CASES_TAC `n:num < m` THEN ASM_REWRITE_TAC[] THEN
16665   FIRST_X_ASSUM(SUBST1_TAC o GEN_REWRITE_RULE I [GSYM NUMSEG_EMPTY]) THEN
16666   ASM_REWRITE_TAC[VSUM_CLAUSES; NORM_0; INTER_EMPTY]);;
16667
16668 let SERIES_CAUCHY = prove
16669  (`!f s. (?l. (f sums l) s) =
16670          !e. &0 < e
16671              ==> ?N. !m n. m >= N
16672                            ==> norm(vsum(s INTER (m..n)) f) < e`,
16673   REPEAT GEN_TAC THEN REWRITE_TAC[sums; CONVERGENT_EQ_CAUCHY; cauchy] THEN
16674   REWRITE_TAC[SEQUENCE_CAUCHY_WLOG] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
16675   SIMP_TAC[dist; VSUM_DIFF_LEMMA; NORM_VSUM_TRIVIAL_LEMMA] THEN
16676   REWRITE_TAC[GE; TAUT `a ==> b \/ c <=> a /\ ~b ==> c`] THEN
16677   REWRITE_TAC[NOT_LT; ARITH_RULE
16678    `(N <= m /\ N <= n /\ m <= n) /\ m + 1 <= n <=>
16679     N + 1 <= m + 1 /\ m + 1 <= n`] THEN
16680   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN
16681   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
16682   EQ_TAC THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THENL
16683    [EXISTS_TAC `N + 1`; EXISTS_TAC `N:num`] THEN
16684   REPEAT STRIP_TAC THEN
16685   ASM_SIMP_TAC[ARITH_RULE `N + 1 <= m + 1 ==> N <= m + 1`] THEN
16686   FIRST_X_ASSUM(MP_TAC o SPECL [`m - 1`; `n:num`]) THEN
16687   SUBGOAL_THEN `m - 1 + 1 = m` SUBST_ALL_TAC THENL
16688    [ALL_TAC; ANTS_TAC THEN SIMP_TAC[]] THEN
16689   ASM_ARITH_TAC);;
16690
16691 let SUMMABLE_CAUCHY = prove
16692  (`!f s. summable s f <=>
16693          !e. &0 < e
16694              ==> ?N. !m n. m >= N ==> norm(vsum(s INTER (m..n)) f) < e`,
16695   REWRITE_TAC[summable; GSYM SERIES_CAUCHY]);;
16696
16697 let SUMMABLE_IFF_EVENTUALLY = prove
16698  (`!f g k. (?N. !n. N <= n /\ n IN k ==> f n = g n)
16699            ==> (summable k f <=> summable k g)`,
16700   REWRITE_TAC[summable; SERIES_CAUCHY] THEN REPEAT GEN_TAC THEN
16701   DISCH_THEN(X_CHOOSE_THEN `N0:num` STRIP_ASSUME_TAC) THEN
16702   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN
16703   AP_TERM_TAC THEN EQ_TAC THEN
16704   DISCH_THEN(X_CHOOSE_THEN `N1:num`
16705    (fun th -> EXISTS_TAC `N0 + N1:num` THEN MP_TAC th)) THEN
16706   REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
16707   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
16708   (ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC]) THEN
16709   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
16710   MATCH_MP_TAC VSUM_EQ THEN ASM_SIMP_TAC[IN_INTER; IN_NUMSEG] THEN
16711   REPEAT STRIP_TAC THENL [ALL_TAC; CONV_TAC SYM_CONV] THEN
16712   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
16713   ASM_ARITH_TAC);;
16714
16715 let SUMMABLE_EQ_EVENTUALLY = prove
16716  (`!f g k. (?N. !n. N <= n /\ n IN k ==> f n = g n) /\ summable k f
16717            ==> summable k g`,
16718   MESON_TAC[SUMMABLE_IFF_EVENTUALLY]);;
16719
16720 let SUMMABLE_IFF_COFINITE = prove
16721  (`!f s t. FINITE((s DIFF t) UNION (t DIFF s))
16722            ==> (summable s f <=> summable t f)`,
16723   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM SUMMABLE_RESTRICT] THEN
16724   MATCH_MP_TAC SUMMABLE_IFF_EVENTUALLY THEN
16725   FIRST_ASSUM(MP_TAC o ISPEC `\x:num.x` o MATCH_MP UPPER_BOUND_FINITE_SET) THEN
16726   DISCH_THEN(X_CHOOSE_THEN `N:num` MP_TAC) THEN REWRITE_TAC[IN_UNIV] THEN
16727   DISCH_TAC THEN EXISTS_TAC `N + 1` THEN
16728   REWRITE_TAC[ARITH_RULE `N + 1 <= n <=> ~(n <= N)`] THEN ASM SET_TAC[]);;
16729
16730 let SUMMABLE_EQ_COFINITE = prove
16731  (`!f s t. FINITE((s DIFF t) UNION (t DIFF s)) /\ summable s f
16732            ==> summable t f`,
16733   MESON_TAC[SUMMABLE_IFF_COFINITE]);;
16734
16735 let SUMMABLE_FROM_ELSEWHERE = prove
16736  (`!f m n. summable (from m) f ==> summable (from n) f`,
16737   REPEAT GEN_TAC THEN
16738   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] SUMMABLE_EQ_COFINITE) THEN
16739   MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `0..(m+n)` THEN
16740   SIMP_TAC[FINITE_NUMSEG; SUBSET; IN_NUMSEG; IN_UNION; IN_DIFF; IN_FROM] THEN
16741   ARITH_TAC);;
16742
16743 (* ------------------------------------------------------------------------- *)
16744 (* Uniform vesion of Cauchy criterion.                                       *)
16745 (* ------------------------------------------------------------------------- *)
16746
16747 let SERIES_CAUCHY_UNIFORM = prove
16748  (`!P f:A->num->real^N k.
16749         (?l. !e. &0 < e
16750                  ==> ?N. !n x. N <= n /\ P x
16751                                ==> dist(vsum(k INTER (0..n)) (f x),
16752                                         l x) < e) <=>
16753         (!e. &0 < e ==> ?N. !m n x. N <= m /\ P x
16754                                     ==> norm(vsum(k INTER (m..n)) (f x)) < e)`,
16755   REPEAT GEN_TAC THEN
16756   REWRITE_TAC[sums; UNIFORMLY_CONVERGENT_EQ_CAUCHY; cauchy] THEN
16757   ONCE_REWRITE_TAC[MESON[]
16758    `(!m n:num y. N <= m /\ N <= n /\ P y ==> Q m n y) <=>
16759     (!y. P y ==> !m n. N <= m /\ N <= n ==> Q m n y)`] THEN
16760   REWRITE_TAC[SEQUENCE_CAUCHY_WLOG] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
16761   SIMP_TAC[dist; VSUM_DIFF_LEMMA; NORM_VSUM_TRIVIAL_LEMMA] THEN
16762   REWRITE_TAC[GE; TAUT `a ==> b \/ c <=> a /\ ~b ==> c`] THEN
16763   REWRITE_TAC[NOT_LT; ARITH_RULE
16764    `(N <= m /\ N <= n /\ m <= n) /\ m + 1 <= n <=>
16765     N + 1 <= m + 1 /\ m + 1 <= n`] THEN
16766   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN
16767   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
16768   EQ_TAC THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THENL
16769    [EXISTS_TAC `N + 1`; EXISTS_TAC `N:num`] THEN
16770   REPEAT STRIP_TAC THEN
16771   ASM_SIMP_TAC[ARITH_RULE `N + 1 <= m + 1 ==> N <= m + 1`] THEN
16772   FIRST_X_ASSUM(MP_TAC o SPEC `x:A`) THEN ASM_REWRITE_TAC[] THEN
16773   DISCH_THEN(MP_TAC o SPECL [`m - 1`; `n:num`]) THEN
16774   SUBGOAL_THEN `m - 1 + 1 = m` SUBST_ALL_TAC THENL
16775    [ALL_TAC; ANTS_TAC THEN SIMP_TAC[]] THEN
16776   ASM_ARITH_TAC);;
16777
16778 (* ------------------------------------------------------------------------- *)
16779 (* So trivially, terms of a convergent series go to zero.                    *)
16780 (* ------------------------------------------------------------------------- *)
16781
16782 let SERIES_GOESTOZERO = prove
16783  (`!s x. summable s x
16784          ==> !e. &0 < e
16785                  ==> eventually (\n. n IN s ==> norm(x n) < e) sequentially`,
16786   REPEAT GEN_TAC THEN REWRITE_TAC[summable; SERIES_CAUCHY] THEN
16787   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
16788   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
16789   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN DISCH_TAC THEN
16790   X_GEN_TAC `n:num` THEN REPEAT STRIP_TAC THEN
16791   FIRST_X_ASSUM(MP_TAC o SPECL [`n:num`; `n:num`]) THEN
16792   ASM_SIMP_TAC[NUMSEG_SING; GE; SET_RULE `n IN s ==> s INTER {n} = {n}`] THEN
16793   REWRITE_TAC[VSUM_SING]);;
16794
16795 let SUMMABLE_IMP_TOZERO = prove
16796  (`!f:num->real^N k.
16797        summable k f
16798        ==> ((\n. if n IN k then f(n) else vec 0) --> vec 0) sequentially`,
16799   REPEAT GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM SUMMABLE_RESTRICT] THEN
16800   REWRITE_TAC[summable; LIM_SEQUENTIALLY; INTER_UNIV; sums] THEN
16801   DISCH_THEN(X_CHOOSE_TAC `l:real^N`) THEN X_GEN_TAC `e:real` THEN
16802   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
16803   ASM_REWRITE_TAC[REAL_HALF; LEFT_IMP_EXISTS_THM] THEN
16804   X_GEN_TAC `N:num` THEN DISCH_TAC THEN EXISTS_TAC `N + 1` THEN
16805   X_GEN_TAC `n:num` THEN DISCH_TAC THEN
16806   FIRST_X_ASSUM(fun th ->
16807     MP_TAC(SPEC `n - 1` th) THEN MP_TAC(SPEC `n:num` th)) THEN
16808   ASM_SIMP_TAC[ARITH_RULE `N + 1 <= n ==> N <= n /\ N <= n - 1`] THEN
16809   ABBREV_TAC `m = n - 1` THEN
16810   SUBGOAL_THEN `n = SUC m` SUBST1_TAC THENL
16811    [ASM_ARITH_TAC; ALL_TAC] THEN
16812   REWRITE_TAC[VSUM_CLAUSES_NUMSEG; LE_0] THEN
16813   REWRITE_TAC[NORM_ARITH `dist(x,vec 0) = norm x`] THEN
16814   COND_CASES_TAC THEN ASM_REWRITE_TAC[NORM_0] THEN CONV_TAC NORM_ARITH);;
16815
16816 let SUMMABLE_IMP_BOUNDED = prove
16817  (`!f:num->real^N k. summable k f ==> bounded (IMAGE f k)`,
16818   REPEAT GEN_TAC THEN
16819   DISCH_THEN(MP_TAC o MATCH_MP SUMMABLE_IMP_TOZERO) THEN
16820   DISCH_THEN(MP_TAC o MATCH_MP CONVERGENT_IMP_BOUNDED) THEN
16821   REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE; IN_UNIV] THEN
16822   MATCH_MP_TAC MONO_EXISTS THEN MESON_TAC[REAL_LT_IMP_LE; NORM_0]);;
16823
16824 let SUMMABLE_IMP_SUMS_BOUNDED = prove
16825  (`!f:num->real^N k.
16826        summable (from k) f ==> bounded { vsum(k..n) f | n IN (:num) }`,
16827   REWRITE_TAC[summable; sums; LEFT_IMP_EXISTS_THM] THEN REPEAT GEN_TAC THEN
16828   DISCH_THEN(MP_TAC o MATCH_MP CONVERGENT_IMP_BOUNDED) THEN
16829   REWRITE_TAC[FROM_INTER_NUMSEG; SIMPLE_IMAGE]);;
16830
16831 (* ------------------------------------------------------------------------- *)
16832 (* Comparison test.                                                          *)
16833 (* ------------------------------------------------------------------------- *)
16834
16835 let SERIES_COMPARISON = prove
16836  (`!f g s. (?l. ((lift o g) sums l) s) /\
16837            (?N. !n. n >= N /\ n IN s ==> norm(f n) <= g n)
16838            ==> ?l:real^N. (f sums l) s`,
16839   REPEAT GEN_TAC THEN REWRITE_TAC[SERIES_CAUCHY] THEN
16840   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC (X_CHOOSE_TAC `N1:num`)) THEN
16841   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
16842   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
16843   DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN
16844   EXISTS_TAC `N1 + N2:num` THEN
16845   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN DISCH_TAC THEN
16846   MATCH_MP_TAC REAL_LET_TRANS THEN
16847   EXISTS_TAC `norm (vsum (s INTER (m .. n)) (lift o g))` THEN CONJ_TAC THENL
16848    [SIMP_TAC[GSYM LIFT_SUM; FINITE_INTER_NUMSEG; NORM_LIFT] THEN
16849     MATCH_MP_TAC(REAL_ARITH `x <= a ==> x <= abs(a)`) THEN
16850     MATCH_MP_TAC VSUM_NORM_LE THEN
16851     REWRITE_TAC[FINITE_INTER_NUMSEG; IN_INTER; IN_NUMSEG] THEN
16852     ASM_MESON_TAC[ARITH_RULE `m >= N1 + N2:num /\ m <= x ==> x >= N1`];
16853     ASM_MESON_TAC[ARITH_RULE `m >= N1 + N2:num ==> m >= N2`]]);;
16854
16855 let SUMMABLE_COMPARISON = prove
16856  (`!f g s. summable s (lift o g) /\
16857            (?N. !n. n >= N /\ n IN s ==> norm(f n) <= g n)
16858            ==> summable s f`,
16859   REWRITE_TAC[summable; SERIES_COMPARISON]);;
16860
16861 let SERIES_LIFT_ABSCONV_IMP_CONV = prove
16862  (`!x:num->real^N k. summable k (\n. lift(norm(x n))) ==> summable k x`,
16863   REWRITE_TAC[summable] THEN REPEAT STRIP_TAC THEN
16864   MATCH_MP_TAC SERIES_COMPARISON THEN
16865   EXISTS_TAC `\n:num. norm(x n:real^N)` THEN
16866   ASM_REWRITE_TAC[o_DEF; REAL_LE_REFL] THEN ASM_MESON_TAC[]);;
16867
16868 let SUMMABLE_SUBSET_ABSCONV = prove
16869  (`!x:num->real^N s t.
16870         summable s (\n. lift(norm(x n))) /\ t SUBSET s
16871         ==> summable t (\n. lift(norm(x n)))`,
16872   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUMMABLE_SUBSET THEN
16873   EXISTS_TAC `s:num->bool` THEN ASM_REWRITE_TAC[] THEN
16874   REWRITE_TAC[summable] THEN MATCH_MP_TAC SERIES_COMPARISON THEN
16875   EXISTS_TAC `\n:num. norm(x n:real^N)` THEN
16876   ASM_REWRITE_TAC[o_DEF; GSYM summable] THEN
16877   EXISTS_TAC `0` THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
16878   REWRITE_TAC[REAL_LE_REFL; NORM_LIFT; REAL_ABS_NORM; NORM_0; NORM_POS_LE]);;
16879
16880 let SERIES_COMPARISON_BOUND = prove
16881  (`!f:num->real^N g s a.
16882         (g sums a) s /\ (!i. i IN s ==> norm(f i) <= drop(g i))
16883         ==> ?l. (f sums l) s /\ norm(l) <= drop a`,
16884   REPEAT STRIP_TAC THEN
16885   MP_TAC(ISPECL [`f:num->real^N`; `drop o (g:num->real^1)`; `s:num->bool`]
16886         SUMMABLE_COMPARISON) THEN
16887   REWRITE_TAC[o_DEF; LIFT_DROP; GE; ETA_AX; summable] THEN
16888   ANTS_TAC THENL [ASM_MESON_TAC[]; MATCH_MP_TAC MONO_EXISTS] THEN
16889   X_GEN_TAC `l:real^N` THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
16890   RULE_ASSUM_TAC(REWRITE_RULE[FROM_0; INTER_UNIV; sums]) THEN
16891   MATCH_MP_TAC SERIES_BOUND THEN MAP_EVERY EXISTS_TAC
16892    [`f:num->real^N`; `drop o (g:num->real^1)`; `s:num->bool`] THEN
16893   ASM_REWRITE_TAC[sums; o_DEF; LIFT_DROP; ETA_AX]);;
16894
16895 (* ------------------------------------------------------------------------- *)
16896 (* Uniform version of comparison test.                                       *)
16897 (* ------------------------------------------------------------------------- *)
16898
16899 let SERIES_COMPARISON_UNIFORM = prove
16900  (`!f g P s. (?l. ((lift o g) sums l) s) /\
16901              (?N. !n x. N <= n /\ n IN s /\ P x ==> norm(f x n) <= g n)
16902              ==> ?l:A->real^N.
16903                     !e. &0 < e
16904                         ==> ?N. !n x. N <= n /\ P x
16905                                       ==> dist(vsum(s INTER (0..n)) (f x),
16906                                                l x) < e`,
16907   REPEAT GEN_TAC THEN SIMP_TAC[GE; SERIES_CAUCHY; SERIES_CAUCHY_UNIFORM] THEN
16908   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC (X_CHOOSE_TAC `N1:num`)) THEN
16909   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
16910   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
16911   DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN
16912   EXISTS_TAC `N1 + N2:num` THEN
16913   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`; `x:A`] THEN DISCH_TAC THEN
16914   MATCH_MP_TAC REAL_LET_TRANS THEN
16915   EXISTS_TAC `norm (vsum (s INTER (m .. n)) (lift o g))` THEN CONJ_TAC THENL
16916    [SIMP_TAC[GSYM LIFT_SUM; FINITE_INTER_NUMSEG; NORM_LIFT] THEN
16917     MATCH_MP_TAC(REAL_ARITH `x <= a ==> x <= abs(a)`) THEN
16918     MATCH_MP_TAC VSUM_NORM_LE THEN
16919     REWRITE_TAC[FINITE_INTER_NUMSEG; IN_INTER; IN_NUMSEG] THEN
16920     ASM_MESON_TAC[ARITH_RULE `N1 + N2:num <= m /\ m <= x ==> N1 <= x`];
16921     ASM_MESON_TAC[ARITH_RULE `N1 + N2:num <= m ==> N2 <= m`]]);;
16922
16923 (* ------------------------------------------------------------------------- *)
16924 (* Ratio test.                                                               *)
16925 (* ------------------------------------------------------------------------- *)
16926
16927 let SERIES_RATIO = prove
16928  (`!c a s N.
16929       c < &1 /\
16930       (!n. n >= N ==> norm(a(SUC n)) <= c * norm(a(n)))
16931       ==> ?l:real^N. (a sums l) s`,
16932   REWRITE_TAC[GE] THEN REPEAT STRIP_TAC THEN
16933   MATCH_MP_TAC SERIES_COMPARISON THEN
16934   DISJ_CASES_TAC(REAL_ARITH `c <= &0 \/ &0 < c`) THENL
16935    [EXISTS_TAC `\n:num. &0` THEN REWRITE_TAC[o_DEF; LIFT_NUM] THEN
16936     CONJ_TAC THENL [MESON_TAC[SERIES_0]; ALL_TAC] THEN
16937     EXISTS_TAC `N + 1` THEN REWRITE_TAC[GE] THEN REPEAT STRIP_TAC THEN
16938     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `c * norm(a(n - 1):real^N)` THEN
16939     CONJ_TAC THENL
16940      [ASM_MESON_TAC[ARITH_RULE `N + 1 <= n ==> SUC(n - 1) = n /\ N <= n - 1`];
16941       ALL_TAC] THEN
16942     MATCH_MP_TAC(REAL_ARITH `&0 <= --c * x ==> c * x <= &0`) THEN
16943     MATCH_MP_TAC REAL_LE_MUL THEN REWRITE_TAC[NORM_POS_LE] THEN
16944     UNDISCH_TAC `c <= &0` THEN REAL_ARITH_TAC;
16945     ASSUME_TAC(MATCH_MP REAL_LT_IMP_LE (ASSUME `&0 < c`))] THEN
16946   EXISTS_TAC `\n. norm(a(N):real^N) * c pow (n - N)` THEN
16947   REWRITE_TAC[] THEN CONJ_TAC THENL
16948    [ALL_TAC;
16949     EXISTS_TAC `N:num` THEN
16950     SIMP_TAC[GE; LE_EXISTS; IMP_CONJ; ADD_SUB2; LEFT_IMP_EXISTS_THM] THEN
16951     SUBGOAL_THEN `!d:num. norm(a(N + d):real^N) <= norm(a N) * c pow d`
16952      (fun th -> MESON_TAC[th]) THEN INDUCT_TAC THEN
16953     REWRITE_TAC[ADD_CLAUSES; real_pow; REAL_MUL_RID; REAL_LE_REFL] THEN
16954     MATCH_MP_TAC REAL_LE_TRANS THEN
16955     EXISTS_TAC `c * norm((a:num->real^N) (N + d))` THEN
16956     ASM_SIMP_TAC[LE_ADD] THEN ASM_MESON_TAC[REAL_LE_LMUL; REAL_MUL_AC]] THEN
16957   GEN_REWRITE_TAC I [SERIES_CAUCHY] THEN X_GEN_TAC `e:real` THEN
16958   SIMP_TAC[GSYM LIFT_SUM; FINITE_INTER; NORM_LIFT; FINITE_NUMSEG] THEN
16959   DISCH_TAC THEN SIMP_TAC[SUM_LMUL; FINITE_INTER; FINITE_NUMSEG] THEN
16960   ASM_CASES_TAC `(a:num->real^N) N = vec 0` THENL
16961    [ASM_REWRITE_TAC[NORM_0; REAL_MUL_LZERO; REAL_ABS_NUM]; ALL_TAC] THEN
16962   MP_TAC(SPECL [`c:real`; `((&1 - c) * e) / norm((a:num->real^N) N)`]
16963                REAL_ARCH_POW_INV) THEN
16964   ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_MUL; REAL_SUB_LT; NORM_POS_LT; GE] THEN
16965   DISCH_THEN(X_CHOOSE_TAC `M:num`) THEN EXISTS_TAC `N + M:num` THEN
16966   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN DISCH_TAC THEN
16967   MATCH_MP_TAC REAL_LET_TRANS THEN
16968   EXISTS_TAC `abs(norm((a:num->real^N) N) *
16969                   sum(m..n) (\i. c pow (i - N)))` THEN
16970   CONJ_TAC THENL
16971    [REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_LMUL THEN
16972     REWRITE_TAC[REAL_ABS_POS] THEN
16973     MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ x <= y ==> abs x <= abs y`) THEN
16974     ASM_SIMP_TAC[SUM_POS_LE; FINITE_INTER_NUMSEG; REAL_POW_LE] THEN
16975     MATCH_MP_TAC SUM_SUBSET THEN ASM_SIMP_TAC[REAL_POW_LE] THEN
16976     REWRITE_TAC[FINITE_INTER_NUMSEG; FINITE_NUMSEG] THEN
16977     REWRITE_TAC[IN_INTER; IN_DIFF] THEN MESON_TAC[];
16978     ALL_TAC] THEN
16979   REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NORM] THEN
16980   DISJ_CASES_TAC(ARITH_RULE `n:num < m \/ m <= n`) THENL
16981    [ASM_SIMP_TAC[SUM_TRIV_NUMSEG; REAL_ABS_NUM; REAL_MUL_RZERO]; ALL_TAC] THEN
16982   SUBGOAL_THEN `m = 0 + m /\ n = (n - m) + m` (CONJUNCTS_THEN SUBST1_TAC) THENL
16983    [UNDISCH_TAC `m:num <= n` THEN ARITH_TAC; ALL_TAC] THEN
16984   REWRITE_TAC[SUM_OFFSET] THEN UNDISCH_TAC `N + M:num <= m` THEN
16985   SIMP_TAC[LE_EXISTS] THEN DISCH_THEN(X_CHOOSE_THEN `d:num` SUBST_ALL_TAC) THEN
16986   REWRITE_TAC[ARITH_RULE `(i + (N + M) + d) - N:num = (M + d) + i`] THEN
16987   ONCE_REWRITE_TAC[REAL_POW_ADD] THEN REWRITE_TAC[SUM_LMUL; SUM_GP] THEN
16988   ASM_SIMP_TAC[LT; REAL_LT_IMP_NE] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
16989   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT; REAL_ABS_MUL] THEN
16990   REWRITE_TAC[REAL_ABS_POW] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
16991   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_ABS_DIV; REAL_POW_LT; REAL_ARITH
16992    `&0 < c /\ c < &1 ==> &0 < abs c /\ &0 < abs(&1 - c)`; REAL_LT_LDIV_EQ] THEN
16993   MATCH_MP_TAC(REAL_ARITH
16994    `&0 < x /\ x <= &1 /\ &1 <= e ==> abs(c pow 0 - x) < e`) THEN
16995   ASM_SIMP_TAC[REAL_POW_LT; REAL_POW_1_LE; REAL_LT_IMP_LE] THEN
16996   ASM_SIMP_TAC[REAL_ARITH `c < &1 ==> x * abs(&1 - c) = (&1 - c) * x`] THEN
16997   REWRITE_TAC[real_div; REAL_INV_MUL; REAL_POW_ADD; REAL_MUL_ASSOC] THEN
16998   REWRITE_TAC[REAL_ARITH
16999    `(((a * b) * c) * d) * e = (e * ((a * b) * c)) * d`] THEN
17000   ASM_SIMP_TAC[GSYM real_div; REAL_LE_RDIV_EQ; REAL_POW_LT; REAL_MUL_LID;
17001                REAL_ARITH `&0 < c ==> abs c = c`] THEN
17002   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
17003    `xm < e ==> &0 <= (d - &1) * e ==> xm <= d * e`)) THEN
17004   MATCH_MP_TAC REAL_LE_MUL THEN CONJ_TAC THENL
17005    [REWRITE_TAC[REAL_SUB_LE; GSYM REAL_POW_INV] THEN
17006     MATCH_MP_TAC REAL_POW_LE_1 THEN
17007     MATCH_MP_TAC REAL_INV_1_LE THEN ASM_SIMP_TAC[REAL_LT_IMP_LE];
17008     MATCH_MP_TAC REAL_LT_IMP_LE THEN
17009     ASM_SIMP_TAC[REAL_SUB_LT; REAL_LT_MUL; REAL_LT_DIV; NORM_POS_LT]]);;
17010
17011 (* ------------------------------------------------------------------------- *)
17012 (* Ostensibly weaker versions of the boundedness of partial sums.            *)
17013 (* ------------------------------------------------------------------------- *)
17014
17015 let BOUNDED_PARTIAL_SUMS = prove
17016  (`!f:num->real^N k.
17017         bounded { vsum(k..n) f | n IN (:num) }
17018         ==> bounded { vsum(m..n) f | m IN (:num) /\ n IN (:num) }`,
17019   REPEAT STRIP_TAC THEN
17020   SUBGOAL_THEN `bounded { vsum(0..n) f:real^N | n IN (:num) }` MP_TAC THENL
17021    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
17022     REWRITE_TAC[bounded] THEN
17023     REWRITE_TAC[SIMPLE_IMAGE; FORALL_IN_IMAGE; IN_UNIV] THEN
17024     DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
17025     EXISTS_TAC `sum { i:num | i < k} (\i. norm(f i:real^N)) + B` THEN
17026     X_GEN_TAC `i:num` THEN ASM_CASES_TAC `i:num < k` THENL
17027      [MATCH_MP_TAC(REAL_ARITH
17028        `!y. x <= y /\ y <= a /\ &0 < b ==> x <= a + b`) THEN
17029       EXISTS_TAC `sum (0..i) (\i. norm(f i:real^N))` THEN
17030       ASM_SIMP_TAC[VSUM_NORM; FINITE_NUMSEG] THEN
17031       MATCH_MP_TAC SUM_SUBSET THEN
17032       REWRITE_TAC[FINITE_NUMSEG; FINITE_NUMSEG_LT; NORM_POS_LE] THEN
17033       REWRITE_TAC[IN_DIFF; IN_NUMSEG; IN_ELIM_THM] THEN ASM_ARITH_TAC;
17034       ALL_TAC] THEN
17035     ASM_CASES_TAC `k = 0` THENL
17036      [FIRST_X_ASSUM SUBST_ALL_TAC THEN MATCH_MP_TAC(REAL_ARITH
17037        `x <= B /\ &0 <= b ==> x <= b + B`) THEN
17038       ASM_SIMP_TAC[SUM_POS_LE; FINITE_NUMSEG_LT; NORM_POS_LE];
17039       ALL_TAC] THEN
17040     MP_TAC(ISPECL [`f:num->real^N`; `0`; `k:num`; `i:num`]
17041       VSUM_COMBINE_L) THEN
17042     ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
17043     DISCH_THEN(SUBST1_TAC o SYM) THEN ASM_REWRITE_TAC[NUMSEG_LT] THEN
17044     MATCH_MP_TAC(NORM_ARITH
17045      `norm(x) <= a /\ norm(y) <= b ==> norm(x + y) <= a + b`) THEN
17046     ASM_SIMP_TAC[VSUM_NORM; FINITE_NUMSEG];
17047     ALL_TAC] THEN
17048   DISCH_THEN(fun th ->
17049     MP_TAC(MATCH_MP BOUNDED_DIFFS (W CONJ th)) THEN MP_TAC th) THEN
17050   REWRITE_TAC[IMP_IMP; GSYM BOUNDED_UNION] THEN
17051   MATCH_MP_TAC(REWRITE_RULE[TAUT `a /\ b ==> c <=> b ==> a ==> c`]
17052         BOUNDED_SUBSET) THEN
17053   REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNION; LEFT_IMP_EXISTS_THM; IN_UNIV] THEN
17054   MAP_EVERY X_GEN_TAC [`x:real^N`; `m:num`; `n:num`] THEN
17055   DISCH_THEN SUBST1_TAC THEN
17056   ASM_CASES_TAC `m = 0` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
17057   ASM_CASES_TAC `n:num < m` THENL
17058    [DISJ2_TAC THEN REPEAT(EXISTS_TAC `vsum(0..0) (f:num->real^N)`) THEN
17059     ASM_SIMP_TAC[VSUM_TRIV_NUMSEG; VECTOR_SUB_REFL] THEN MESON_TAC[];
17060     ALL_TAC] THEN
17061   DISJ2_TAC THEN MAP_EVERY EXISTS_TAC
17062    [`vsum(0..n) (f:num->real^N)`; `vsum(0..(m-1)) (f:num->real^N)`] THEN
17063   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
17064   MP_TAC(ISPECL [`f:num->real^N`; `0`; `m:num`; `n:num`]
17065       VSUM_COMBINE_L) THEN
17066   ANTS_TAC THENL [ASM_ARITH_TAC; VECTOR_ARITH_TAC]);;
17067
17068 (* ------------------------------------------------------------------------- *)
17069 (* General Dirichlet convergence test (could make this uniform on a set).    *)
17070 (* ------------------------------------------------------------------------- *)
17071
17072 let SUMMABLE_BILINEAR_PARTIAL_PRE = prove
17073  (`!f g h:real^M->real^N->real^P l k.
17074         bilinear h /\
17075         ((\n. h (f(n + 1)) (g(n))) --> l) sequentially /\
17076         summable (from k) (\n. h (f(n + 1) - f(n)) (g(n)))
17077         ==> summable (from k) (\n. h (f n) (g(n) - g(n - 1)))`,
17078   REPEAT GEN_TAC THEN
17079   REWRITE_TAC[summable; sums; FROM_INTER_NUMSEG] THEN
17080   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
17081   FIRST_ASSUM(fun th ->
17082    REWRITE_TAC[MATCH_MP BILINEAR_VSUM_PARTIAL_PRE th]) THEN
17083   DISCH_THEN(X_CHOOSE_TAC `l':real^P`) THEN
17084   EXISTS_TAC `l - (h:real^M->real^N->real^P) (f k) (g(k - 1)) - l'` THEN
17085   REWRITE_TAC[LIM_CASES_SEQUENTIALLY] THEN
17086   REPEAT(MATCH_MP_TAC LIM_SUB THEN ASM_REWRITE_TAC[LIM_CONST]));;
17087
17088 let SERIES_DIRICHLET_BILINEAR = prove
17089  (`!f g h:real^M->real^N->real^P k m p l.
17090         bilinear h /\
17091         bounded { vsum (m..n) f | n IN (:num)} /\
17092         summable (from p) (\n. lift(norm(g(n + 1) - g(n)))) /\
17093         ((\n. h (g(n + 1)) (vsum(1..n) f)) --> l) sequentially
17094         ==> summable (from k) (\n. h (g n) (f n))`,
17095   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUMMABLE_FROM_ELSEWHERE THEN
17096   EXISTS_TAC `1` THEN
17097   FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP BOUNDED_PARTIAL_SUMS) THEN
17098   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
17099   SIMP_TAC[IN_ELIM_THM; IN_UNIV; LEFT_IMP_EXISTS_THM] THEN
17100   REWRITE_TAC[MESON[] `(!x a b. x = f a b ==> p a b) <=> (!a b. p a b)`] THEN
17101   X_GEN_TAC `B:real` THEN STRIP_TAC THEN
17102   FIRST_ASSUM(MP_TAC o MATCH_MP BILINEAR_BOUNDED_POS) THEN
17103   DISCH_THEN(X_CHOOSE_THEN `C:real` STRIP_ASSUME_TAC) THEN
17104   MATCH_MP_TAC SUMMABLE_EQ THEN
17105   EXISTS_TAC `\n. (h:real^M->real^N->real^P)
17106                   (g n) (vsum (1..n) f - vsum (1..n-1) f)` THEN
17107   SIMP_TAC[IN_FROM; GSYM NUMSEG_RREC] THEN
17108   SIMP_TAC[VSUM_CLAUSES; FINITE_NUMSEG; IN_NUMSEG;
17109            ARITH_RULE `1 <= n ==> ~(n <= n - 1)`] THEN
17110   CONJ_TAC THENL
17111    [REPEAT STRIP_TAC THEN ASM_SIMP_TAC[BILINEAR_RADD; BILINEAR_RSUB] THEN
17112     VECTOR_ARITH_TAC;
17113     ALL_TAC] THEN
17114   MATCH_MP_TAC SUMMABLE_FROM_ELSEWHERE THEN EXISTS_TAC `p:num` THEN
17115   MP_TAC(ISPECL [`g:num->real^M`; `\n. vsum(1..n) f:real^N`;
17116                  `h:real^M->real^N->real^P`; `l:real^P`; `p:num`]
17117          SUMMABLE_BILINEAR_PARTIAL_PRE) THEN
17118   REWRITE_TAC[] THEN DISCH_THEN MATCH_MP_TAC THEN
17119   ASM_REWRITE_TAC[] THEN
17120   SUBGOAL_THEN
17121     `summable (from p) (lift o (\n. C * B * norm(g(n + 1) - g(n):real^M)))`
17122   MP_TAC THENL [ASM_SIMP_TAC[o_DEF; LIFT_CMUL; SUMMABLE_CMUL]; ALL_TAC] THEN
17123   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] SUMMABLE_COMPARISON) THEN
17124   EXISTS_TAC `0` THEN REWRITE_TAC[IN_FROM; GE; LE_0] THEN
17125   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
17126    `C * norm(g(n + 1) - g(n):real^M) * norm(vsum (1..n) f:real^N)` THEN
17127   ASM_SIMP_TAC[REAL_LE_LMUL_EQ] THEN
17128   GEN_REWRITE_TAC RAND_CONV [REAL_MUL_SYM] THEN
17129   ASM_SIMP_TAC[REAL_LE_LMUL; NORM_POS_LE]);;
17130
17131 let SERIES_DIRICHLET = prove
17132  (`!f:num->real^N g N k m.
17133         bounded { vsum (m..n) f | n IN (:num)} /\
17134         (!n. N <= n ==> g(n + 1) <= g(n)) /\
17135         ((lift o g) --> vec 0) sequentially
17136         ==> summable (from k) (\n. g(n) % f(n))`,
17137   REPEAT STRIP_TAC THEN
17138   MP_TAC(ISPECL [`f:num->real^N`; `lift o (g:num->real)`;
17139                  `\x y:real^N. drop x % y`] SERIES_DIRICHLET_BILINEAR) THEN
17140   REWRITE_TAC[o_THM; LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN
17141   MAP_EVERY EXISTS_TAC [`m:num`; `N:num`; `vec 0:real^N`] THEN CONJ_TAC THENL
17142    [REWRITE_TAC[bilinear; linear; DROP_ADD; DROP_CMUL] THEN
17143     REPEAT STRIP_TAC THEN VECTOR_ARITH_TAC;
17144     ALL_TAC] THEN
17145   ASM_REWRITE_TAC[GSYM LIFT_SUB; NORM_LIFT] THEN
17146   FIRST_ASSUM(MP_TAC o SPEC `1` o MATCH_MP SEQ_OFFSET) THEN
17147   REWRITE_TAC[o_THM] THEN DISCH_TAC THEN CONJ_TAC THENL
17148    [MATCH_MP_TAC SUMMABLE_EQ_EVENTUALLY THEN
17149     EXISTS_TAC `\n. lift(g(n) - g(n + 1))` THEN REWRITE_TAC[] THEN
17150     CONJ_TAC THENL
17151      [ASM_MESON_TAC[REAL_ARITH `b <= a ==> abs(b - a) = a - b`];
17152       REWRITE_TAC[summable; sums; FROM_INTER_NUMSEG; VSUM_DIFFS; LIFT_SUB] THEN
17153       REWRITE_TAC[LIM_CASES_SEQUENTIALLY] THEN
17154       EXISTS_TAC `lift(g(N:num)) - vec 0` THEN
17155       MATCH_MP_TAC LIM_SUB THEN ASM_REWRITE_TAC[LIM_CONST]];
17156     MATCH_MP_TAC LIM_NULL_VMUL_BOUNDED THEN ASM_REWRITE_TAC[o_DEF] THEN
17157     REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
17158     FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP BOUNDED_PARTIAL_SUMS) THEN
17159     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
17160     SIMP_TAC[IN_ELIM_THM; IN_UNIV] THEN MESON_TAC[]]);;
17161
17162 (* ------------------------------------------------------------------------- *)
17163 (* Rearranging absolutely convergent series.                                 *)
17164 (* ------------------------------------------------------------------------- *)
17165
17166 let SERIES_INJECTIVE_IMAGE_STRONG = prove
17167  (`!x:num->real^N s f.
17168         summable (IMAGE f s) (\n. lift(norm(x n))) /\
17169         (!m n. m IN s /\ n IN s /\ f m = f n ==> m = n)
17170         ==> ((\n. vsum (IMAGE f s INTER (0..n)) x -
17171                   vsum (s INTER (0..n)) (x o f)) --> vec 0)
17172             sequentially`,
17173   let lemma = prove
17174    (`!f:A->real^N s t.
17175           FINITE s /\ FINITE t
17176           ==> vsum s f - vsum t f = vsum (s DIFF t) f - vsum (t DIFF s) f`,
17177     REPEAT STRIP_TAC THEN
17178     ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s DIFF (s INTER t)`] THEN
17179     ASM_SIMP_TAC[VSUM_DIFF; INTER_SUBSET] THEN
17180     REWRITE_TAC[INTER_COMM] THEN VECTOR_ARITH_TAC) in
17181   REPEAT STRIP_TAC THEN REWRITE_TAC[LIM_SEQUENTIALLY] THEN
17182   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
17183   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUMMABLE_CAUCHY]) THEN
17184   SIMP_TAC[VSUM_REAL; FINITE_INTER; FINITE_NUMSEG] THEN
17185   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [o_DEF] THEN
17186   REWRITE_TAC[NORM_LIFT; LIFT_DROP] THEN
17187   SIMP_TAC[real_abs; SUM_POS_LE; NORM_POS_LE; FINITE_INTER; FINITE_NUMSEG] THEN
17188   DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN
17189   ASM_REWRITE_TAC[dist; GE; VECTOR_SUB_RZERO; REAL_HALF] THEN
17190   DISCH_THEN(X_CHOOSE_THEN `N:num` STRIP_ASSUME_TAC) THEN
17191   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
17192   DISCH_THEN(X_CHOOSE_TAC `g:num->num`) THEN
17193   MP_TAC(ISPECL [`g:num->num`; `0..N`] UPPER_BOUND_FINITE_SET) THEN
17194   REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG; LE_0] THEN
17195   DISCH_THEN(X_CHOOSE_TAC `P:num`) THEN
17196   EXISTS_TAC `MAX N P` THEN X_GEN_TAC `n:num` THEN
17197   SIMP_TAC[ARITH_RULE `MAX a b <= c <=> a <= c /\ b <= c`] THEN DISCH_TAC THEN
17198   W(MP_TAC o PART_MATCH (rand o rand) VSUM_IMAGE o rand o
17199     rand o lhand o snd) THEN
17200   ANTS_TAC THENL
17201    [ASM_MESON_TAC[FINITE_INTER; FINITE_NUMSEG; IN_INTER];
17202     DISCH_THEN(SUBST1_TAC o SYM)] THEN
17203   W(MP_TAC o PART_MATCH (lhand o rand) lemma o rand o lhand o snd) THEN
17204   SIMP_TAC[FINITE_INTER; FINITE_IMAGE; FINITE_NUMSEG] THEN
17205   DISCH_THEN SUBST1_TAC THEN MATCH_MP_TAC(NORM_ARITH
17206    `norm a < e / &2 /\ norm b < e / &2 ==> norm(a - b:real^N) < e`) THEN
17207   CONJ_TAC THEN
17208   W(MP_TAC o PART_MATCH (lhand o rand) VSUM_NORM o lhand o snd) THEN
17209   SIMP_TAC[FINITE_DIFF; FINITE_IMAGE; FINITE_INTER; FINITE_NUMSEG] THEN
17210   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LET_TRANS) THEN
17211   MATCH_MP_TAC REAL_LET_TRANS THENL
17212    [EXISTS_TAC
17213      `sum(IMAGE (f:num->num) s INTER (N..n)) (\i. norm(x i :real^N))` THEN
17214     ASM_SIMP_TAC[LE_REFL] THEN MATCH_MP_TAC SUM_SUBSET_SIMPLE THEN
17215     SIMP_TAC[NORM_POS_LE; FINITE_INTER; FINITE_NUMSEG] THEN
17216     MATCH_MP_TAC(SET_RULE
17217      `(!x. x IN s /\ f(x) IN n /\ ~(x IN m) ==> f x IN t)
17218       ==> (IMAGE f s INTER n) DIFF (IMAGE f (s INTER m)) SUBSET
17219           IMAGE f s INTER t`) THEN
17220     ASM_SIMP_TAC[IN_NUMSEG; LE_0; NOT_LE] THEN
17221     X_GEN_TAC `i:num` THEN STRIP_TAC THEN
17222     MATCH_MP_TAC LT_IMP_LE THEN ONCE_REWRITE_TAC[GSYM NOT_LE] THEN
17223     FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE BINDER_CONV
17224      [GSYM CONTRAPOS_THM]) THEN
17225     ASM_SIMP_TAC[] THEN ASM_ARITH_TAC;
17226     MP_TAC(ISPECL [`f:num->num`; `0..n`] UPPER_BOUND_FINITE_SET) THEN
17227     REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG; LE_0] THEN
17228     DISCH_THEN(X_CHOOSE_TAC `p:num`) THEN
17229     EXISTS_TAC
17230      `sum(IMAGE (f:num->num) s INTER (N..p)) (\i. norm(x i :real^N))` THEN
17231     ASM_SIMP_TAC[LE_REFL] THEN MATCH_MP_TAC SUM_SUBSET_SIMPLE THEN
17232     SIMP_TAC[NORM_POS_LE; FINITE_INTER; FINITE_NUMSEG] THEN
17233     MATCH_MP_TAC(SET_RULE
17234      `(!x. x IN s /\ x IN n /\ ~(f x IN m) ==> f x IN t)
17235       ==> (IMAGE f (s INTER n) DIFF (IMAGE f s) INTER m) SUBSET
17236           (IMAGE f s INTER t)`) THEN
17237     ASM_SIMP_TAC[IN_NUMSEG; LE_0] THEN ASM_ARITH_TAC]);;
17238
17239 let SERIES_INJECTIVE_IMAGE = prove
17240  (`!x:num->real^N s f l.
17241         summable (IMAGE f s) (\n. lift(norm(x n))) /\
17242         (!m n. m IN s /\ n IN s /\ f m = f n ==> m = n)
17243         ==> (((x o f) sums l) s <=> (x sums l) (IMAGE f s))`,
17244   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN REWRITE_TAC[sums] THEN
17245   MATCH_MP_TAC LIM_TRANSFORM_EQ THEN REWRITE_TAC[] THEN
17246   MATCH_MP_TAC SERIES_INJECTIVE_IMAGE_STRONG THEN
17247   ASM_REWRITE_TAC[]);;
17248
17249 let SERIES_REARRANGE_EQ = prove
17250  (`!x:num->real^N s p l.
17251         summable s (\n. lift(norm(x n))) /\ p permutes s
17252         ==> (((x o p) sums l) s <=> (x sums l) s)`,
17253   REPEAT STRIP_TAC THEN
17254   MP_TAC(ISPECL [`x:num->real^N`; `s:num->bool`; `p:num->num`; `l:real^N`]
17255         SERIES_INJECTIVE_IMAGE) THEN
17256   ASM_SIMP_TAC[PERMUTES_IMAGE] THEN
17257   ASM_MESON_TAC[PERMUTES_INJECTIVE]);;
17258
17259 let SERIES_REARRANGE = prove
17260  (`!x:num->real^N s p l.
17261         summable s (\n. lift(norm(x n))) /\ p permutes s /\ (x sums l) s
17262         ==> ((x o p) sums l) s`,
17263   MESON_TAC[SERIES_REARRANGE_EQ]);;
17264
17265 let SUMMABLE_REARRANGE = prove
17266  (`!x s p.
17267         summable s (\n. lift(norm(x n))) /\ p permutes s
17268         ==> summable s (x o p)`,
17269   MESON_TAC[SERIES_LIFT_ABSCONV_IMP_CONV; summable; SERIES_REARRANGE]);;
17270
17271 (* ------------------------------------------------------------------------- *)
17272 (* Banach fixed point theorem (not really topological...)                    *)
17273 (* ------------------------------------------------------------------------- *)
17274
17275 let BANACH_FIX = prove
17276  (`!f s c. complete s /\ ~(s = {}) /\
17277            &0 <= c /\ c < &1 /\
17278            (IMAGE f s) SUBSET s /\
17279            (!x y. x IN s /\ y IN s ==> dist(f(x),f(y)) <= c * dist(x,y))
17280            ==> ?!x:real^N. x IN s /\ (f x = x)`,
17281   REPEAT STRIP_TAC THEN REWRITE_TAC[EXISTS_UNIQUE_THM] THEN CONJ_TAC THENL
17282    [ALL_TAC;
17283     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
17284     SUBGOAL_THEN `dist((f:real^N->real^N) x,f y) <= c * dist(x,y)` MP_TAC THENL
17285      [ASM_MESON_TAC[]; ALL_TAC] THEN
17286     ASM_REWRITE_TAC[REAL_ARITH `a <= c * a <=> &0 <= --a * (&1 - c)`] THEN
17287     ASM_SIMP_TAC[GSYM REAL_LE_LDIV_EQ; REAL_SUB_LT; real_div] THEN
17288     REWRITE_TAC[REAL_MUL_LZERO; REAL_ARITH `&0 <= --x <=> ~(&0 < x)`] THEN
17289     MESON_TAC[DIST_POS_LT]] THEN
17290   STRIP_ASSUME_TAC(prove_recursive_functions_exist num_RECURSION
17291     `(z 0 = @x:real^N. x IN s) /\ (!n. z(SUC n) = f(z n))`) THEN
17292   SUBGOAL_THEN `!n. (z:num->real^N) n IN s` ASSUME_TAC THENL
17293    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN
17294     ASM_MESON_TAC[MEMBER_NOT_EMPTY; SUBSET; IN_IMAGE];
17295     ALL_TAC] THEN
17296   UNDISCH_THEN `z 0 = @x:real^N. x IN s` (K ALL_TAC) THEN
17297   SUBGOAL_THEN `?x:real^N. x IN s /\ (z --> x) sequentially` MP_TAC THENL
17298    [ALL_TAC;
17299     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
17300     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
17301     ABBREV_TAC `e = dist(f(a:real^N),a)` THEN
17302     SUBGOAL_THEN `~(&0 < e)` (fun th -> ASM_MESON_TAC[th; DIST_POS_LT]) THEN
17303     DISCH_TAC THEN
17304     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
17305     DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN
17306     ASM_REWRITE_TAC[REAL_HALF] THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN
17307     SUBGOAL_THEN
17308      `dist(f(z N),a:real^N) < e / &2 /\ dist(f(z(N:num)),f(a)) < e / &2`
17309      (fun th -> ASM_MESON_TAC[th; DIST_TRIANGLE_HALF_R; REAL_LT_REFL]) THEN
17310     CONJ_TAC THENL [ASM_MESON_TAC[ARITH_RULE `N <= SUC N`]; ALL_TAC] THEN
17311     MATCH_MP_TAC REAL_LET_TRANS THEN
17312     EXISTS_TAC `c * dist((z:num->real^N) N,a)` THEN ASM_SIMP_TAC[] THEN
17313     MATCH_MP_TAC(REAL_ARITH `x < y /\ c * x <= &1 * x ==> c * x < y`) THEN
17314     ASM_SIMP_TAC[LE_REFL; REAL_LE_RMUL; DIST_POS_LE; REAL_LT_IMP_LE]] THEN
17315   FIRST_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [complete]) THEN
17316   ASM_REWRITE_TAC[CAUCHY] THEN
17317   SUBGOAL_THEN `!n. dist(z(n):real^N,z(SUC n)) <= c pow n * dist(z(0),z(1))`
17318   ASSUME_TAC THENL
17319    [INDUCT_TAC THEN
17320     REWRITE_TAC[real_pow; ARITH; REAL_MUL_LID; REAL_LE_REFL] THEN
17321     MATCH_MP_TAC REAL_LE_TRANS THEN
17322     EXISTS_TAC `c * dist(z(n):real^N,z(SUC n))` THEN
17323     CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
17324     REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN ASM_SIMP_TAC[REAL_LE_LMUL];
17325     ALL_TAC] THEN
17326   SUBGOAL_THEN
17327    `!m n:num. (&1 - c) * dist(z(m):real^N,z(m+n))
17328                 <= c pow m * dist(z(0),z(1)) * (&1 - c pow n)`
17329   ASSUME_TAC THENL
17330    [GEN_TAC THEN INDUCT_TAC THENL
17331      [REWRITE_TAC[ADD_CLAUSES; DIST_REFL; REAL_MUL_RZERO] THEN
17332       MATCH_MP_TAC REAL_LE_MUL THEN
17333       ASM_SIMP_TAC[REAL_LE_MUL; REAL_POW_LE; DIST_POS_LE; REAL_SUB_LE;
17334                    REAL_POW_1_LE; REAL_LT_IMP_LE];
17335       ALL_TAC] THEN
17336     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
17337     `(&1 - c) * (dist(z m:real^N,z(m + n)) + dist(z(m + n),z(m + SUC n)))` THEN
17338     ASM_SIMP_TAC[REAL_LE_LMUL; REAL_SUB_LE; REAL_LT_IMP_LE; DIST_TRIANGLE] THEN
17339     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
17340       `c * x <= y ==> c * x' + y <= y' ==> c * (x + x') <= y'`)) THEN
17341     REWRITE_TAC[REAL_ARITH
17342      `q + a * b * (&1 - x) <= a * b * (&1 - y) <=> q <= a * b * (x - y)`] THEN
17343     REWRITE_TAC[ADD_CLAUSES; real_pow] THEN
17344     REWRITE_TAC[REAL_ARITH `a * b * (d - c * d) = (&1 - c) * a * d * b`] THEN
17345     MATCH_MP_TAC REAL_LE_LMUL THEN
17346     ASM_SIMP_TAC[REAL_SUB_LE; REAL_LT_IMP_LE] THEN
17347     REWRITE_TAC[GSYM REAL_POW_ADD; REAL_MUL_ASSOC] THEN ASM_MESON_TAC[];
17348     ALL_TAC] THEN
17349   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
17350   ASM_CASES_TAC `(z:num->real^N) 0 = z 1` THENL
17351    [FIRST_X_ASSUM SUBST_ALL_TAC THEN EXISTS_TAC `0` THEN
17352     REWRITE_TAC[GE; LE_0] THEN X_GEN_TAC `n:num` THEN
17353     FIRST_X_ASSUM(MP_TAC o SPECL [`0`; `n:num`]) THEN
17354     REWRITE_TAC[ADD_CLAUSES; DIST_REFL; REAL_MUL_LZERO; REAL_MUL_RZERO] THEN
17355     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
17356     ASM_CASES_TAC `(z:num->real^N) 0 = z n` THEN
17357     ASM_REWRITE_TAC[DIST_REFL; REAL_NOT_LE] THEN
17358     ASM_SIMP_TAC[REAL_LT_MUL; DIST_POS_LT; REAL_SUB_LT];
17359     ALL_TAC] THEN
17360   MP_TAC(SPECL [`c:real`; `e * (&1 - c) / dist((z:num->real^N) 0,z 1)`]
17361    REAL_ARCH_POW_INV) THEN
17362   ASM_SIMP_TAC[REAL_LT_MUL; REAL_LT_DIV; REAL_SUB_LT; DIST_POS_LT] THEN
17363   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
17364   REWRITE_TAC[real_div; GE; REAL_MUL_ASSOC] THEN
17365   ASM_SIMP_TAC[REAL_LT_RDIV_EQ; GSYM real_div; DIST_POS_LT] THEN
17366   ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ; REAL_SUB_LT] THEN DISCH_TAC THEN
17367   REWRITE_TAC[LE_EXISTS; LEFT_IMP_EXISTS_THM] THEN
17368   GEN_TAC THEN X_GEN_TAC `d:num` THEN DISCH_THEN SUBST_ALL_TAC THEN
17369   ONCE_REWRITE_TAC[DIST_SYM] THEN
17370   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP(REAL_ARITH
17371     `d < e ==> x <= d ==> x < e`)) THEN
17372   ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_SUB_LT] THEN
17373   FIRST_X_ASSUM(MP_TAC o SPECL [`N:num`; `d:num`]) THEN
17374   MATCH_MP_TAC(REAL_ARITH
17375   `(c * d) * e <= (c * d) * &1 ==> x * y <= c * d * e ==> y * x <= c * d`) THEN
17376   MATCH_MP_TAC REAL_LE_LMUL THEN
17377   ASM_SIMP_TAC[REAL_LE_MUL; REAL_POW_LE; DIST_POS_LE; REAL_ARITH
17378    `&0 <= x ==> &1 - x <= &1`]);;
17379
17380 (* ------------------------------------------------------------------------- *)
17381 (* Edelstein fixed point theorem.                                            *)
17382 (* ------------------------------------------------------------------------- *)
17383
17384 let EDELSTEIN_FIX = prove
17385  (`!f s. compact s /\ ~(s = {}) /\ (IMAGE f s) SUBSET s /\
17386          (!x y. x IN s /\ y IN s /\ ~(x = y) ==> dist(f(x),f(y)) < dist(x,y))
17387          ==> ?!x:real^N. x IN s /\ f x = x`,
17388   MAP_EVERY X_GEN_TAC [`g:real^N->real^N`; `s:real^N->bool`] THEN
17389   REPEAT STRIP_TAC THEN REWRITE_TAC[EXISTS_UNIQUE_THM] THEN CONJ_TAC THENL
17390    [ALL_TAC; ASM_MESON_TAC[REAL_LT_REFL]] THEN
17391   SUBGOAL_THEN
17392    `!x y. x IN s /\ y IN s ==> dist((g:real^N->real^N)(x),g(y)) <= dist(x,y)`
17393   ASSUME_TAC THENL
17394    [REPEAT STRIP_TAC THEN ASM_CASES_TAC `x:real^N = y` THEN
17395     ASM_SIMP_TAC[DIST_REFL; REAL_LE_LT];
17396     ALL_TAC] THEN
17397   ASM_CASES_TAC `?x:real^N. x IN s /\ ~(g x = x)` THENL
17398    [ALL_TAC; ASM SET_TAC[]] THEN
17399   FIRST_X_ASSUM(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
17400   ABBREV_TAC `y = (g:real^N->real^N) x` THEN
17401   SUBGOAL_THEN `(y:real^N) IN s` ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
17402   FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_PCROSS o W CONJ) THEN
17403   REWRITE_TAC[compact; PCROSS] THEN
17404   (STRIP_ASSUME_TAC o prove_general_recursive_function_exists)
17405     `?f:num->real^N->real^N.
17406         (!z. f 0 z = z) /\ (!z n. f (SUC n) z = g(f n z))` THEN
17407   SUBGOAL_THEN `!n z. z IN s ==> (f:num->real^N->real^N) n z IN s`
17408   STRIP_ASSUME_TAC THENL [INDUCT_TAC THEN ASM SET_TAC[]; ALL_TAC] THEN
17409   SUBGOAL_THEN
17410    `!m n w z. m <= n /\ w IN s /\ z IN s
17411               ==> dist((f:num->real^N->real^N) n w,f n z) <= dist(f m w,f m z)`
17412   ASSUME_TAC THENL
17413    [REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
17414     MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
17415     RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; FORALL_IN_IMAGE]) THEN
17416     ASM_SIMP_TAC[REAL_LE_REFL] THEN MESON_TAC[REAL_LE_TRANS];
17417     ALL_TAC] THEN
17418   DISCH_THEN(MP_TAC o SPEC
17419    `\n:num. pastecart (f n (x:real^N)) (f n y:real^N)`) THEN
17420   ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN
17421   MAP_EVERY X_GEN_TAC [`l:real^(N,N)finite_sum`; `s:num->num`] THEN
17422   REWRITE_TAC[o_DEF; IN_ELIM_THM] THEN
17423   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
17424   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
17425   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN
17426   DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC SUBST_ALL_TAC) THEN
17427   SUBGOAL_THEN
17428    `(\x:real^(N,N)finite_sum. fstcart x) continuous_on UNIV /\
17429     (\x:real^(N,N)finite_sum. sndcart x) continuous_on UNIV`
17430   MP_TAC THENL
17431    [CONJ_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
17432     REWRITE_TAC[ETA_AX; LINEAR_FSTCART; LINEAR_SNDCART];
17433     ALL_TAC] THEN
17434   REWRITE_TAC[CONTINUOUS_ON_SEQUENTIALLY; IN_UNIV] THEN
17435   DISCH_THEN(CONJUNCTS_THEN(fun th -> FIRST_ASSUM(MP_TAC o MATCH_MP th))) THEN
17436   REWRITE_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART; IMP_IMP] THEN
17437   ONCE_REWRITE_TAC[CONJ_SYM] THEN
17438   DISCH_THEN(fun th -> CONJUNCTS_THEN2 (LABEL_TAC "A") (LABEL_TAC "B") th THEN
17439     MP_TAC(MATCH_MP LIM_SUB th)) THEN
17440   REWRITE_TAC[] THEN DISCH_THEN(LABEL_TAC "AB") THEN
17441   SUBGOAL_THEN
17442    `!n. dist(a:real^N,b) <= dist((f:num->real^N->real^N) n x,f n y)`
17443   STRIP_ASSUME_TAC THENL
17444    [X_GEN_TAC `N:num` THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
17445     ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN DISCH_TAC THEN
17446     USE_THEN "AB" (MP_TAC o REWRITE_RULE[LIM_SEQUENTIALLY]) THEN
17447     DISCH_THEN(fun th -> FIRST_X_ASSUM(MP_TAC o MATCH_MP th)) THEN
17448     REWRITE_TAC[NOT_EXISTS_THM] THEN X_GEN_TAC `M:num` THEN
17449     DISCH_THEN(MP_TAC o SPEC `M + N:num`) THEN REWRITE_TAC[LE_ADD] THEN
17450     MATCH_MP_TAC(NORM_ARITH
17451      `dist(fx,fy) <= dist(x,y)
17452       ==> ~(dist(fx - fy,a - b) < dist(a,b) - dist(x,y))`) THEN
17453     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
17454     FIRST_X_ASSUM(MP_TAC o SPEC `M + N:num` o MATCH_MP MONOTONE_BIGGER) THEN
17455     ARITH_TAC;
17456     ALL_TAC] THEN
17457   SUBGOAL_THEN `b:real^N = a` SUBST_ALL_TAC THENL
17458    [MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
17459     ABBREV_TAC `e = dist(a,b) - dist((g:real^N->real^N) a,g b)` THEN
17460     SUBGOAL_THEN `&0 < e` ASSUME_TAC THENL
17461      [ASM_MESON_TAC[REAL_SUB_LT]; ALL_TAC] THEN
17462     SUBGOAL_THEN
17463      `?n. dist((f:num->real^N->real^N) n x,a) < e / &2 /\
17464           dist(f n y,b) < e / &2`
17465     STRIP_ASSUME_TAC THENL
17466      [MAP_EVERY (fun s -> USE_THEN s (MP_TAC o SPEC `e / &2` o
17467         REWRITE_RULE[LIM_SEQUENTIALLY])) ["A"; "B"] THEN
17468       ASM_REWRITE_TAC[REAL_HALF] THEN
17469       DISCH_THEN(X_CHOOSE_TAC `M:num`) THEN
17470       DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN
17471       EXISTS_TAC `(s:num->num) (M + N)` THEN
17472       CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ARITH_TAC;
17473       ALL_TAC] THEN
17474     SUBGOAL_THEN `dist(f (SUC n) x,(g:real^N->real^N) a) +
17475                   dist((f:num->real^N->real^N) (SUC n) y,g b) < e`
17476     MP_TAC THENL
17477      [ASM_REWRITE_TAC[] THEN
17478       MATCH_MP_TAC(REAL_ARITH `x < e / &2 /\ y < e / &2 ==> x + y < e`) THEN
17479       CONJ_TAC THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
17480        `dist(x,y) < e
17481         ==> dist(g x,g y) <= dist(x,y) ==> dist(g x,g y) < e`)) THEN
17482       ASM_SIMP_TAC[];
17483       ALL_TAC] THEN
17484     MP_TAC(SPEC `SUC n` (ASSUME
17485     `!n. dist (a:real^N,b) <=
17486          dist ((f:num->real^N->real^N) n x,f n y)`)) THEN
17487     EXPAND_TAC "e" THEN NORM_ARITH_TAC;
17488     ALL_TAC] THEN
17489   EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN
17490   MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
17491   EXISTS_TAC `\n:num. (f:num->real^N->real^N) (SUC(s n)) x` THEN
17492   REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY] THEN CONJ_TAC THENL
17493    [ASM_REWRITE_TAC[] THEN
17494     SUBGOAL_THEN `(g:real^N->real^N) continuous_on s` MP_TAC THENL
17495      [REWRITE_TAC[continuous_on] THEN ASM_MESON_TAC[REAL_LET_TRANS];
17496       ALL_TAC] THEN
17497     REWRITE_TAC[CONTINUOUS_ON_SEQUENTIALLY; o_DEF] THEN
17498     DISCH_THEN MATCH_MP_TAC THEN ASM_SIMP_TAC[];
17499     SUBGOAL_THEN `!n. (f:num->real^N->real^N) (SUC n) x = f n y`
17500      (fun th -> ASM_SIMP_TAC[th]) THEN
17501     INDUCT_TAC THEN ASM_REWRITE_TAC[]]);;
17502
17503 (* ------------------------------------------------------------------------- *)
17504 (* Dini's theorem.                                                           *)
17505 (* ------------------------------------------------------------------------- *)
17506
17507 let DINI = prove
17508  (`!f:num->real^N->real^1 g s.
17509         compact s /\ (!n. (f n) continuous_on s) /\ g continuous_on s /\
17510         (!x. x IN s ==> ((\n. (f n x)) --> g x) sequentially) /\
17511         (!n x. x IN s ==> drop(f n x) <= drop(f (n + 1) x))
17512         ==> !e. &0 < e
17513                 ==> eventually (\n. !x. x IN s ==> norm(f n x - g x) < e)
17514                                sequentially`,
17515   REPEAT STRIP_TAC THEN
17516   SUBGOAL_THEN
17517    `!x:real^N m n:num. x IN s /\ m <= n ==> drop(f m x) <= drop(f n x)`
17518   ASSUME_TAC THENL
17519    [GEN_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
17520     MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN ASM_SIMP_TAC[ADD1] THEN
17521     REAL_ARITH_TAC;
17522     ALL_TAC] THEN
17523   SUBGOAL_THEN `!n:num x:real^N. x IN s ==> drop(f n x) <= drop(g x)`
17524   ASSUME_TAC THENL
17525    [REPEAT STRIP_TAC THEN
17526     MATCH_MP_TAC(ISPEC `sequentially` LIM_DROP_LE) THEN
17527     EXISTS_TAC `\m:num. (f:num->real^N->real^1) n x` THEN
17528     EXISTS_TAC `\m:num. (f:num->real^N->real^1) m x` THEN
17529     ASM_SIMP_TAC[LIM_CONST; TRIVIAL_LIMIT_SEQUENTIALLY] THEN
17530     REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN ASM_MESON_TAC[];
17531     ALL_TAC] THEN
17532   RULE_ASSUM_TAC(REWRITE_RULE[LIM_SEQUENTIALLY; dist]) THEN
17533   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I
17534    [COMPACT_EQ_HEINE_BOREL_SUBTOPOLOGY]) THEN
17535   DISCH_THEN(MP_TAC o SPEC
17536    `IMAGE (\n. { x | x IN s /\ norm((f:num->real^N->real^1) n x - g x) < e})
17537           (:num)`) THEN
17538   REWRITE_TAC[FORALL_IN_IMAGE; IN_UNIV] THEN
17539   ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN
17540   REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE; SUBSET_UNION; UNIONS_IMAGE] THEN
17541   REWRITE_TAC[IN_UNIV; IN_ELIM_THM; EVENTUALLY_SEQUENTIALLY] THEN
17542   SIMP_TAC[SUBSET; IN_UNIV; IN_ELIM_THM] THEN ANTS_TAC THENL
17543    [CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[LE_REFL]] THEN
17544     X_GEN_TAC `n:num` THEN REWRITE_TAC[GSYM IN_BALL_0] THEN
17545     MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE THEN
17546     ASM_SIMP_TAC[OPEN_BALL; CONTINUOUS_ON_SUB; ETA_AX];
17547
17548     DISCH_THEN(X_CHOOSE_THEN `k:num->bool` (CONJUNCTS_THEN2
17549      (MP_TAC o SPEC `\n:num. n` o MATCH_MP UPPER_BOUND_FINITE_SET)
17550      (LABEL_TAC "*"))) THEN
17551     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
17552     REWRITE_TAC[] THEN STRIP_TAC THEN X_GEN_TAC `n:num` THEN
17553     DISCH_TAC THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
17554     REMOVE_THEN "*" (MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
17555     DISCH_THEN(X_CHOOSE_THEN `m:num` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
17556     REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB] THEN MATCH_MP_TAC(REAL_ARITH
17557      `m <= n /\ n <= g ==> abs(m - g) < e ==> abs(n - g) < e`) THEN
17558     ASM_MESON_TAC[LE_TRANS]]);;
17559
17560 (* ------------------------------------------------------------------------- *)
17561 (* Closest point of a (closed) set to a point.                               *)
17562 (* ------------------------------------------------------------------------- *)
17563
17564 let closest_point = new_definition
17565  `closest_point s a = @x. x IN s /\ !y. y IN s ==> dist(a,x) <= dist(a,y)`;;
17566
17567 let CLOSEST_POINT_EXISTS = prove
17568  (`!s a. closed s /\ ~(s = {})
17569          ==> (closest_point s a) IN s /\
17570              !y. y IN s ==> dist(a,closest_point s a) <= dist(a,y)`,
17571   REWRITE_TAC[closest_point] THEN CONV_TAC(ONCE_DEPTH_CONV SELECT_CONV) THEN
17572   REWRITE_TAC[DISTANCE_ATTAINS_INF]);;
17573
17574 let CLOSEST_POINT_IN_SET = prove
17575  (`!s a. closed s /\ ~(s = {}) ==> (closest_point s a) IN s`,
17576   MESON_TAC[CLOSEST_POINT_EXISTS]);;
17577
17578 let CLOSEST_POINT_LE = prove
17579  (`!s a x. closed s /\ x IN s ==> dist(a,closest_point s a) <= dist(a,x)`,
17580   MESON_TAC[CLOSEST_POINT_EXISTS; MEMBER_NOT_EMPTY]);;
17581
17582 let CLOSEST_POINT_SELF = prove
17583  (`!s x:real^N. x IN s ==> closest_point s x = x`,
17584   REPEAT STRIP_TAC THEN REWRITE_TAC[closest_point] THEN
17585   MATCH_MP_TAC SELECT_UNIQUE THEN REWRITE_TAC[] THEN GEN_TAC THEN EQ_TAC THENL
17586    [STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
17587     ASM_SIMP_TAC[DIST_LE_0; DIST_REFL];
17588     STRIP_TAC THEN ASM_REWRITE_TAC[DIST_REFL; DIST_POS_LE]]);;
17589
17590 let CLOSEST_POINT_REFL = prove
17591  (`!s x:real^N. closed s /\ ~(s = {}) ==> (closest_point s x = x <=> x IN s)`,
17592   MESON_TAC[CLOSEST_POINT_IN_SET; CLOSEST_POINT_SELF]);;
17593
17594 let DIST_CLOSEST_POINT_LIPSCHITZ = prove
17595  (`!s x y:real^N.
17596         closed s /\ ~(s = {})
17597         ==> abs(dist(x,closest_point s x) - dist(y,closest_point s y))
17598             <= dist(x,y)`,
17599   REPEAT GEN_TAC THEN DISCH_TAC THEN
17600   FIRST_ASSUM(MP_TAC o MATCH_MP CLOSEST_POINT_EXISTS) THEN
17601   DISCH_THEN(fun th ->
17602     CONJUNCTS_THEN2 ASSUME_TAC
17603      (MP_TAC o SPEC `closest_point s (y:real^N)`) (SPEC `x:real^N` th) THEN
17604     CONJUNCTS_THEN2 ASSUME_TAC
17605      (MP_TAC o SPEC `closest_point s (x:real^N)`) (SPEC `y:real^N` th)) THEN
17606   ASM_REWRITE_TAC[] THEN NORM_ARITH_TAC);;
17607
17608 let CONTINUOUS_AT_DIST_CLOSEST_POINT = prove
17609  (`!s x:real^N.
17610         closed s /\ ~(s = {})
17611         ==> (\x. lift(dist(x,closest_point s x))) continuous (at x)`,
17612   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_at; DIST_LIFT] THEN
17613   ASM_MESON_TAC[DIST_CLOSEST_POINT_LIPSCHITZ; REAL_LET_TRANS]);;
17614
17615 let CONTINUOUS_ON_DIST_CLOSEST_POINT = prove
17616  (`!s t. closed s /\ ~(s = {})
17617          ==> (\x. lift(dist(x,closest_point s x))) continuous_on t`,
17618   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON;
17619             CONTINUOUS_AT_DIST_CLOSEST_POINT]);;
17620
17621 let UNIFORMLY_CONTINUOUS_ON_DIST_CLOSEST_POINT = prove
17622  (`!s t:real^N->bool.
17623         closed s /\ ~(s = {})
17624         ==> (\x. lift(dist(x,closest_point s x))) uniformly_continuous_on t`,
17625   REPEAT STRIP_TAC THEN REWRITE_TAC[uniformly_continuous_on; DIST_LIFT] THEN
17626   ASM_MESON_TAC[DIST_CLOSEST_POINT_LIPSCHITZ; REAL_LET_TRANS]);;
17627
17628 let SEGMENT_TO_CLOSEST_POINT = prove
17629  (`!s a:real^N.
17630         closed s /\ ~(s = {})
17631         ==> segment(a,closest_point s a) INTER s = {}`,
17632   REPEAT STRIP_TAC THEN
17633   REWRITE_TAC[SET_RULE `s INTER t = {} <=> !x. x IN s ==> ~(x IN t)`] THEN
17634   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP DIST_IN_OPEN_SEGMENT) THEN
17635   MATCH_MP_TAC(TAUT `(r ==> ~p) ==> p /\ q ==> ~r`) THEN
17636   ASM_MESON_TAC[CLOSEST_POINT_EXISTS; REAL_NOT_LT; DIST_SYM]);;
17637
17638 let SEGMENT_TO_POINT_EXISTS = prove
17639  (`!s a:real^N.
17640         closed s /\ ~(s = {}) ==> ?b. b IN s /\ segment(a,b) INTER s = {}`,
17641   MESON_TAC[SEGMENT_TO_CLOSEST_POINT; CLOSEST_POINT_EXISTS]);;
17642
17643 let CLOSEST_POINT_IN_INTERIOR = prove
17644  (`!s x:real^N.
17645         closed s /\ ~(s = {})
17646         ==> ((closest_point s x) IN interior s <=> x IN interior s)`,
17647   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THEN
17648   ASM_SIMP_TAC[CLOSEST_POINT_SELF] THEN
17649   MATCH_MP_TAC(TAUT `~q /\ ~p ==> (p <=> q)`) THEN
17650   CONJ_TAC THENL [ASM_MESON_TAC[INTERIOR_SUBSET; SUBSET]; STRIP_TAC] THEN
17651   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR_CBALL]) THEN
17652   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
17653   SUBGOAL_THEN `closest_point s (x:real^N) IN s` ASSUME_TAC THENL
17654    [ASM_MESON_TAC[INTERIOR_SUBSET; SUBSET]; ALL_TAC] THEN
17655   SUBGOAL_THEN `~(closest_point s (x:real^N) = x)` ASSUME_TAC THENL
17656    [ASM_MESON_TAC[]; ALL_TAC] THEN
17657   MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`;
17658    `closest_point s x -
17659     (min (&1) (e / norm(closest_point s x - x))) %
17660     (closest_point s x - x):real^N`]
17661     CLOSEST_POINT_LE) THEN
17662   ASM_REWRITE_TAC[dist; NOT_IMP; VECTOR_ARITH
17663    `x - (y - e % (y - x)):real^N = (&1 - e) % (x - y)`] THEN
17664   CONJ_TAC THENL
17665    [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
17666     REWRITE_TAC[IN_CBALL; NORM_ARITH `dist(a:real^N,a - x) = norm x`] THEN
17667     REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
17668     ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
17669     MATCH_MP_TAC(REAL_ARITH `&0 <= a ==> abs(min (&1) a) <= a`) THEN
17670     ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LE_DIV; NORM_POS_LE];
17671     REWRITE_TAC[NORM_MUL; REAL_ARITH
17672      `~(n <= a * n) <=> &0 < (&1 - a) * n`] THEN
17673     MATCH_MP_TAC REAL_LT_MUL THEN
17674     ASM_SIMP_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
17675     MATCH_MP_TAC(REAL_ARITH
17676      `&0 < e /\ e <= &1 ==> &0 < &1 - abs(&1 - e)`) THEN
17677     REWRITE_TAC[REAL_MIN_LE; REAL_LT_MIN; REAL_LT_01; REAL_LE_REFL] THEN
17678     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ]]);;
17679
17680 let CLOSEST_POINT_IN_FRONTIER = prove
17681  (`!s x:real^N.
17682         closed s /\ ~(s = {}) /\ ~(x IN interior s)
17683         ==> (closest_point s x) IN frontier s`,
17684   SIMP_TAC[frontier; IN_DIFF; CLOSEST_POINT_IN_INTERIOR] THEN
17685   SIMP_TAC[CLOSEST_POINT_IN_SET; CLOSURE_CLOSED]);;
17686
17687 (* ------------------------------------------------------------------------- *)
17688 (* More general infimum of distance between two sets.                        *)
17689 (* ------------------------------------------------------------------------- *)
17690
17691 let setdist = new_definition
17692  `setdist(s,t) =
17693         if s = {} \/ t = {} then &0
17694         else inf {dist(x,y) | x IN s /\ y IN t}`;;
17695
17696 let SETDIST_EMPTY = prove
17697  (`(!t. setdist({},t) = &0) /\ (!s. setdist(s,{}) = &0)`,
17698   REWRITE_TAC[setdist]);;
17699
17700 let SETDIST_POS_LE = prove
17701  (`!s t. &0 <= setdist(s,t)`,
17702   REPEAT GEN_TAC THEN REWRITE_TAC[setdist] THEN
17703   COND_CASES_TAC THEN REWRITE_TAC[REAL_LE_REFL] THEN
17704   MATCH_MP_TAC REAL_LE_INF THEN
17705   REWRITE_TAC[FORALL_IN_GSPEC; DIST_POS_LE] THEN ASM SET_TAC[]);;
17706
17707 let REAL_LE_SETDIST = prove
17708   (`!s t:real^N->bool d.
17709         ~(s = {}) /\ ~(t = {}) /\
17710         (!x y. x IN s /\ y IN t ==> d <= dist(x,y))
17711         ==> d <= setdist(s,t)`,
17712   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[setdist] THEN
17713   MP_TAC(ISPEC `{dist(x:real^N,y) | x IN s /\ y IN t}` INF) THEN
17714   REWRITE_TAC[FORALL_IN_GSPEC] THEN ANTS_TAC THENL
17715    [CONJ_TAC THENL [ASM SET_TAC[]; MESON_TAC[DIST_POS_LE]]; ALL_TAC] THEN
17716   ASM_MESON_TAC[]);;
17717
17718 let SETDIST_LE_DIST = prove
17719  (`!s t x y:real^N. x IN s /\ y IN t ==> setdist(s,t) <= dist(x,y)`,
17720   REPEAT GEN_TAC THEN REWRITE_TAC[setdist] THEN
17721   COND_CASES_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
17722   MP_TAC(ISPEC `{dist(x:real^N,y) | x IN s /\ y IN t}` INF) THEN
17723   REWRITE_TAC[FORALL_IN_GSPEC] THEN ANTS_TAC THENL
17724    [CONJ_TAC THENL [ASM SET_TAC[]; MESON_TAC[DIST_POS_LE]]; ALL_TAC] THEN
17725   ASM_MESON_TAC[]);;
17726
17727 let REAL_LE_SETDIST_EQ = prove
17728  (`!d s t:real^N->bool.
17729         d <= setdist(s,t) <=>
17730         (!x y. x IN s /\ y IN t ==> d <= dist(x,y)) /\
17731         (s = {} \/ t = {} ==> d <= &0)`,
17732   REPEAT GEN_TAC THEN MAP_EVERY ASM_CASES_TAC
17733    [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
17734   ASM_REWRITE_TAC[SETDIST_EMPTY; NOT_IN_EMPTY] THEN
17735   ASM_MESON_TAC[REAL_LE_SETDIST; SETDIST_LE_DIST; REAL_LE_TRANS]);;
17736
17737 let REAL_SETDIST_LT_EXISTS = prove
17738  (`!s t:real^N->bool b.
17739         ~(s = {}) /\ ~(t = {}) /\ setdist(s,t) < b
17740         ==> ?x y. x IN s /\ y IN t /\ dist(x,y) < b`,
17741   REWRITE_TAC[GSYM REAL_NOT_LE; REAL_LE_SETDIST_EQ] THEN MESON_TAC[]);;
17742
17743 let SETDIST_REFL = prove
17744  (`!s:real^N->bool. setdist(s,s) = &0`,
17745   GEN_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM; SETDIST_POS_LE] THEN
17746   ASM_CASES_TAC `s:real^N->bool = {}` THENL
17747    [ASM_REWRITE_TAC[setdist; REAL_LE_REFL]; ALL_TAC] THEN
17748   ASM_MESON_TAC[SETDIST_LE_DIST; MEMBER_NOT_EMPTY; DIST_REFL]);;
17749
17750 let SETDIST_SYM = prove
17751  (`!s t. setdist(s,t) = setdist(t,s)`,
17752   REPEAT GEN_TAC THEN REWRITE_TAC[setdist; DISJ_SYM] THEN
17753   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
17754   AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
17755   MESON_TAC[DIST_SYM]);;
17756
17757 let SETDIST_TRIANGLE = prove
17758  (`!s a t:real^N->bool.
17759         setdist(s,t) <= setdist(s,{a}) + setdist({a},t)`,
17760   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
17761   ASM_REWRITE_TAC[SETDIST_EMPTY; REAL_ADD_LID; SETDIST_POS_LE] THEN
17762   ASM_CASES_TAC `t:real^N->bool = {}` THEN
17763   ASM_REWRITE_TAC[SETDIST_EMPTY; REAL_ADD_RID; SETDIST_POS_LE] THEN
17764   ONCE_REWRITE_TAC[GSYM REAL_LE_SUB_RADD] THEN
17765   MATCH_MP_TAC REAL_LE_SETDIST THEN
17766   ASM_REWRITE_TAC[NOT_INSERT_EMPTY; IN_SING; IMP_CONJ;
17767                   RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2] THEN
17768   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
17769   ONCE_REWRITE_TAC[REAL_ARITH `x - y <= z <=> x - z <= y`] THEN
17770   MATCH_MP_TAC REAL_LE_SETDIST THEN
17771   ASM_REWRITE_TAC[NOT_INSERT_EMPTY; IN_SING; IMP_CONJ;
17772                   RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2] THEN
17773   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
17774   REWRITE_TAC[REAL_LE_SUB_RADD] THEN MATCH_MP_TAC REAL_LE_TRANS THEN
17775   EXISTS_TAC `dist(x:real^N,y)` THEN
17776   ASM_SIMP_TAC[SETDIST_LE_DIST] THEN CONV_TAC NORM_ARITH);;
17777
17778 let SETDIST_SINGS = prove
17779  (`!x y. setdist({x},{y}) = dist(x,y)`,
17780   REWRITE_TAC[setdist; NOT_INSERT_EMPTY] THEN
17781   REWRITE_TAC[SET_RULE `{f x y | x IN {a} /\ y IN {b}} = {f a b}`] THEN
17782   SIMP_TAC[INF_INSERT_FINITE; FINITE_EMPTY]);;
17783
17784 let SETDIST_LIPSCHITZ = prove
17785  (`!s t x y:real^N. abs(setdist({x},s) - setdist({y},s)) <= dist(x,y)`,
17786   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM SETDIST_SINGS] THEN
17787   REWRITE_TAC[REAL_ARITH
17788    `abs(x - y) <= z <=> x <= z + y /\ y <= z + x`] THEN
17789   MESON_TAC[SETDIST_TRIANGLE; SETDIST_SYM]);;
17790
17791 let CONTINUOUS_AT_LIFT_SETDIST = prove
17792  (`!s x:real^N. (\y. lift(setdist({y},s))) continuous (at x)`,
17793   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_at; DIST_LIFT] THEN
17794   ASM_MESON_TAC[SETDIST_LIPSCHITZ; REAL_LET_TRANS]);;
17795
17796 let CONTINUOUS_ON_LIFT_SETDIST = prove
17797  (`!s t:real^N->bool. (\y. lift(setdist({y},s))) continuous_on t`,
17798   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON;
17799             CONTINUOUS_AT_LIFT_SETDIST]);;
17800
17801 let UNIFORMLY_CONTINUOUS_ON_LIFT_SETDIST = prove
17802  (`!s t:real^N->bool.
17803          (\y. lift(setdist({y},s))) uniformly_continuous_on t`,
17804   REPEAT GEN_TAC THEN REWRITE_TAC[uniformly_continuous_on; DIST_LIFT] THEN
17805   ASM_MESON_TAC[SETDIST_LIPSCHITZ; REAL_LET_TRANS]);;
17806
17807 let SETDIST_DIFFERENCES = prove
17808  (`!s t. setdist(s,t) = setdist({vec 0},{x - y:real^N | x IN s /\ y IN t})`,
17809   REPEAT GEN_TAC THEN REWRITE_TAC[setdist; NOT_INSERT_EMPTY;
17810      SET_RULE `{f x y | x IN s /\ y IN t} = {} <=> s = {} \/ t = {}`] THEN
17811   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN
17812   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_SING] THEN
17813   REWRITE_TAC[GSYM CONJ_ASSOC; RIGHT_EXISTS_AND_THM; UNWIND_THM2; DIST_0] THEN
17814   REWRITE_TAC[dist] THEN MESON_TAC[]);;
17815
17816 let SETDIST_SUBSET_RIGHT = prove
17817  (`!s t u:real^N->bool.
17818     ~(t = {}) /\ t SUBSET u ==> setdist(s,u) <= setdist(s,t)`,
17819   REPEAT STRIP_TAC THEN
17820   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `u:real^N->bool = {}`] THEN
17821   ASM_REWRITE_TAC[SETDIST_EMPTY; SETDIST_POS_LE; REAL_LE_REFL] THEN
17822   ASM_REWRITE_TAC[setdist] THEN MATCH_MP_TAC REAL_LE_INF_SUBSET THEN
17823   ASM_REWRITE_TAC[FORALL_IN_GSPEC; SUBSET] THEN
17824   REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
17825   MESON_TAC[DIST_POS_LE]);;
17826
17827 let SETDIST_SUBSET_LEFT = prove
17828  (`!s t u:real^N->bool.
17829     ~(s = {}) /\ s SUBSET t ==> setdist(t,u) <= setdist(s,u)`,
17830   MESON_TAC[SETDIST_SUBSET_RIGHT; SETDIST_SYM]);;
17831
17832 let SETDIST_CLOSURE = prove
17833  (`(!s t:real^N->bool. setdist(closure s,t) = setdist(s,t)) /\
17834    (!s t:real^N->bool. setdist(s,closure t) = setdist(s,t))`,
17835   GEN_REWRITE_TAC RAND_CONV [SWAP_FORALL_THM] THEN
17836   GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [SETDIST_SYM] THEN
17837   REWRITE_TAC[] THEN
17838   REWRITE_TAC[MESON[REAL_LE_ANTISYM]
17839    `x:real = y <=> !d. d <= x <=> d <= y`] THEN
17840   REPEAT GEN_TAC THEN REWRITE_TAC[REAL_LE_SETDIST_EQ] THEN
17841   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
17842   ASM_REWRITE_TAC[CLOSURE_EQ_EMPTY; CLOSURE_EMPTY; NOT_IN_EMPTY] THEN
17843   MATCH_MP_TAC(SET_RULE
17844    `s SUBSET c /\
17845     (!y. Q y /\ (!x. x IN s ==> P x y) ==> (!x. x IN c ==> P x y))
17846    ==> ((!x y. x IN c /\ Q y ==> P x y) <=>
17847         (!x y. x IN s /\ Q y ==> P x y))`) THEN
17848   REWRITE_TAC[CLOSURE_SUBSET] THEN GEN_TAC THEN STRIP_TAC THEN
17849   MATCH_MP_TAC CONTINUOUS_GE_ON_CLOSURE THEN
17850   ASM_REWRITE_TAC[o_DEF; dist] THEN
17851   MATCH_MP_TAC CONTINUOUS_ON_LIFT_NORM_COMPOSE THEN
17852   SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID]);;
17853
17854 let SETDIST_COMPACT_CLOSED = prove
17855  (`!s t:real^N->bool.
17856         compact s /\ closed t /\ ~(s = {}) /\ ~(t = {})
17857         ==> ?x y. x IN s /\ y IN t /\ dist(x,y) = setdist(s,t)`,
17858   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
17859   MATCH_MP_TAC(MESON[]
17860    `(!x y. P x /\ Q y ==> S x y) /\ (?x y. P x /\ Q y /\ R x y)
17861     ==> ?x y. P x /\ Q y /\ R x y /\ S x y`) THEN
17862   SIMP_TAC[SETDIST_LE_DIST] THEN
17863   ASM_REWRITE_TAC[REAL_LE_SETDIST_EQ] THEN
17864   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN t}`; `vec 0:real^N`]
17865         DISTANCE_ATTAINS_INF) THEN
17866   ASM_SIMP_TAC[COMPACT_CLOSED_DIFFERENCES; EXISTS_IN_GSPEC; FORALL_IN_GSPEC;
17867                DIST_0; GSYM CONJ_ASSOC] THEN
17868   REWRITE_TAC[dist] THEN DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]);;
17869
17870 let SETDIST_CLOSED_COMPACT = prove
17871  (`!s t:real^N->bool.
17872         closed s /\ compact t /\ ~(s = {}) /\ ~(t = {})
17873         ==> ?x y. x IN s /\ y IN t /\ dist(x,y) = setdist(s,t)`,
17874   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
17875   MATCH_MP_TAC(MESON[]
17876    `(!x y. P x /\ Q y ==> S x y) /\ (?x y. P x /\ Q y /\ R x y)
17877     ==> ?x y. P x /\ Q y /\ R x y /\ S x y`) THEN
17878   SIMP_TAC[SETDIST_LE_DIST] THEN
17879   ASM_REWRITE_TAC[REAL_LE_SETDIST_EQ] THEN
17880   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN t}`; `vec 0:real^N`]
17881         DISTANCE_ATTAINS_INF) THEN
17882   ASM_SIMP_TAC[CLOSED_COMPACT_DIFFERENCES; EXISTS_IN_GSPEC; FORALL_IN_GSPEC;
17883                DIST_0; GSYM CONJ_ASSOC] THEN
17884   REWRITE_TAC[dist] THEN DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]);;
17885
17886 let SETDIST_EQ_0_COMPACT_CLOSED = prove
17887  (`!s t:real^N->bool.
17888         compact s /\ closed t
17889         ==> (setdist(s,t) = &0 <=> s = {} \/ t = {} \/ ~(s INTER t = {}))`,
17890   REPEAT STRIP_TAC THEN
17891   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
17892   ASM_REWRITE_TAC[SETDIST_EMPTY] THEN EQ_TAC THENL
17893    [MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`]
17894       SETDIST_COMPACT_CLOSED) THEN ASM_REWRITE_TAC[] THEN
17895     REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN MESON_TAC[DIST_EQ_0];
17896     REWRITE_TAC[GSYM REAL_LE_ANTISYM; SETDIST_POS_LE] THEN
17897     REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN
17898     MESON_TAC[SETDIST_LE_DIST; DIST_EQ_0]]);;
17899
17900 let SETDIST_EQ_0_CLOSED_COMPACT = prove
17901  (`!s t:real^N->bool.
17902         closed s /\ compact t
17903         ==> (setdist(s,t) = &0 <=> s = {} \/ t = {} \/ ~(s INTER t = {}))`,
17904   ONCE_REWRITE_TAC[SETDIST_SYM] THEN
17905   SIMP_TAC[SETDIST_EQ_0_COMPACT_CLOSED] THEN SET_TAC[]);;
17906
17907 let SETDIST_EQ_0_BOUNDED = prove
17908  (`!s t:real^N->bool.
17909         (bounded s \/ bounded t)
17910         ==> (setdist(s,t) = &0 <=>
17911              s = {} \/ t = {} \/ ~(closure(s) INTER closure(t) = {}))`,
17912   REPEAT GEN_TAC THEN
17913   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
17914   ASM_REWRITE_TAC[SETDIST_EMPTY] THEN STRIP_TAC THEN
17915   ONCE_REWRITE_TAC[MESON[SETDIST_CLOSURE]
17916    `setdist(s,t) = setdist(closure s,closure t)`] THEN
17917   ASM_SIMP_TAC[SETDIST_EQ_0_COMPACT_CLOSED; SETDIST_EQ_0_CLOSED_COMPACT;
17918                COMPACT_CLOSURE; CLOSED_CLOSURE; CLOSURE_EQ_EMPTY]);;
17919
17920
17921 let SETDIST_TRANSLATION = prove
17922  (`!a:real^N s t.
17923         setdist(IMAGE (\x. a + x) s,IMAGE (\x. a + x) t) = setdist(s,t)`,
17924   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[SETDIST_DIFFERENCES] THEN
17925   AP_TERM_TAC THEN AP_TERM_TAC THEN
17926   REWRITE_TAC[SET_RULE
17927    `{f x y | x IN IMAGE g s /\ y IN IMAGE g t} =
17928     {f (g x) (g y) | x IN s /\ y IN t}`] THEN
17929   REWRITE_TAC[VECTOR_ARITH `(a + x) - (a + y):real^N = x - y`]);;
17930
17931 add_translation_invariants [SETDIST_TRANSLATION];;
17932
17933 let SETDIST_LINEAR_IMAGE = prove
17934  (`!f:real^M->real^N s t.
17935         linear f /\ (!x. norm(f x) = norm x)
17936         ==> setdist(IMAGE f s,IMAGE f t) = setdist(s,t)`,
17937   REPEAT STRIP_TAC THEN REWRITE_TAC[setdist; IMAGE_EQ_EMPTY] THEN
17938   COND_CASES_TAC THEN ASM_REWRITE_TAC[dist] THEN AP_TERM_TAC THEN
17939   REWRITE_TAC[SET_RULE
17940    `{f x y | x IN IMAGE g s /\ y IN IMAGE g t} =
17941     {f (g x) (g y) | x IN s /\ y IN t}`] THEN
17942   FIRST_X_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_SUB th)]) THEN
17943   ASM_REWRITE_TAC[]);;
17944
17945 add_linear_invariants [SETDIST_LINEAR_IMAGE];;
17946
17947 let SETDIST_UNIQUE = prove
17948  (`!s t a b:real^N d.
17949         a IN s /\ b IN t /\ dist(a,b) = d /\
17950         (!x y. x IN s /\ y IN t ==> dist(a,b) <= dist(x,y))
17951         ==> setdist(s,t) = d`,
17952   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN CONJ_TAC THENL
17953    [ASM_MESON_TAC[SETDIST_LE_DIST];
17954     MATCH_MP_TAC REAL_LE_SETDIST THEN ASM SET_TAC[]]);;
17955
17956 let SETDIST_CLOSEST_POINT = prove
17957  (`!a:real^N s.
17958       closed s /\ ~(s = {}) ==> setdist({a},s) = dist(a,closest_point s a)`,
17959   REPEAT STRIP_TAC THEN MATCH_MP_TAC SETDIST_UNIQUE THEN
17960   REWRITE_TAC[RIGHT_EXISTS_AND_THM; IN_SING; UNWIND_THM2] THEN
17961   EXISTS_TAC `closest_point s (a:real^N)` THEN
17962   ASM_MESON_TAC[CLOSEST_POINT_EXISTS; DIST_SYM]);;
17963
17964 let SETDIST_EQ_0_SING = prove
17965  (`(!s x:real^N. setdist({x},s) = &0 <=> s = {} \/ x IN closure s) /\
17966    (!s x:real^N. setdist(s,{x}) = &0 <=> s = {} \/ x IN closure s)`,
17967   SIMP_TAC[SETDIST_EQ_0_BOUNDED; BOUNDED_SING; CLOSURE_SING] THEN SET_TAC[]);;
17968
17969 let SETDIST_EQ_0_CLOSED = prove
17970  (`!s x. closed s ==> (setdist({x},s) = &0 <=> s = {} \/ x IN s)`,
17971   SIMP_TAC[SETDIST_EQ_0_COMPACT_CLOSED; COMPACT_SING] THEN SET_TAC[]);;
17972
17973 let SETDIST_EQ_0_CLOSED_IN = prove
17974  (`!u s x. closed_in (subtopology euclidean u) s /\ x IN u
17975            ==> (setdist({x},s) = &0 <=> s = {} \/ x IN s)`,
17976   REWRITE_TAC[SETDIST_EQ_0_SING; CLOSED_IN_INTER_CLOSURE] THEN SET_TAC[]);;
17977
17978 let SETDIST_SING_IN_SET = prove
17979  (`!x s. x IN s ==> setdist({x},s) = &0`,
17980   SIMP_TAC[SETDIST_EQ_0_SING; REWRITE_RULE[SUBSET] CLOSURE_SUBSET]);;
17981
17982 let SETDIST_SING_TRIANGLE = prove
17983  (`!s x y:real^N. abs(setdist({x},s) - setdist({y},s)) <= dist(x,y)`,
17984   REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
17985   ASM_REWRITE_TAC[SETDIST_EMPTY; REAL_SUB_REFL; REAL_ABS_NUM; DIST_POS_LE] THEN
17986   REWRITE_TAC[GSYM REAL_BOUNDS_LE; REAL_NEG_SUB] THEN REPEAT STRIP_TAC THEN
17987   ONCE_REWRITE_TAC[REAL_ARITH `a - b <= c <=> a - c <= b`;
17988                    REAL_ARITH `--a <= b - c <=> c - a <= b`] THEN
17989   MATCH_MP_TAC REAL_LE_SETDIST THEN ASM_REWRITE_TAC[NOT_INSERT_EMPTY] THEN
17990   SIMP_TAC[IN_SING; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2] THEN
17991   X_GEN_TAC `z:real^N` THEN DISCH_TAC THENL
17992    [MATCH_MP_TAC(NORM_ARITH
17993      `a <= dist(y:real^N,z) ==> a - dist(x,y) <= dist(x,z)`);
17994     MATCH_MP_TAC(NORM_ARITH
17995      `a <= dist(x:real^N,z) ==> a - dist(x,y) <= dist(y,z)`)] THEN
17996   MATCH_MP_TAC SETDIST_LE_DIST THEN ASM_REWRITE_TAC[IN_SING]);;
17997
17998 let SETDIST_LE_SING = prove
17999  (`!s t x:real^N. x IN s ==> setdist(s,t) <= setdist({x},t)`,
18000   REPEAT STRIP_TAC THEN MATCH_MP_TAC SETDIST_SUBSET_LEFT THEN ASM SET_TAC[]);;
18001
18002 let SETDIST_BALLS = prove
18003  (`(!a b:real^N r s.
18004         setdist(ball(a,r),ball(b,s)) =
18005         if r <= &0 \/ s <= &0 then &0 else max (&0) (dist(a,b) - (r + s))) /\
18006    (!a b:real^N r s.
18007         setdist(ball(a,r),cball(b,s)) =
18008         if r <= &0 \/ s < &0 then &0 else max (&0) (dist(a,b) - (r + s))) /\
18009    (!a b:real^N r s.
18010         setdist(cball(a,r),ball(b,s)) =
18011         if r < &0 \/ s <= &0 then &0 else max (&0) (dist(a,b) - (r + s))) /\
18012    (!a b:real^N r s.
18013         setdist(cball(a,r),cball(b,s)) =
18014         if r < &0 \/ s < &0 then &0 else max (&0) (dist(a,b) - (r + s)))`,
18015   REWRITE_TAC[MESON[]
18016    `(x = if p then y else z) <=> (p ==> x = y) /\ (~p ==> x = z)`] THEN
18017   SIMP_TAC[TAUT `p \/ q ==> r <=> (p ==> r) /\ (q ==> r)`] THEN
18018   SIMP_TAC[BALL_EMPTY; CBALL_EMPTY; SETDIST_EMPTY; DE_MORGAN_THM] THEN
18019   ONCE_REWRITE_TAC[MESON[SETDIST_CLOSURE]
18020    `setdist(s,t) = setdist(closure s,closure t)`] THEN
18021   SIMP_TAC[REAL_NOT_LE; REAL_NOT_LT; CLOSURE_BALL] THEN
18022   REWRITE_TAC[SETDIST_CLOSURE] THEN
18023   MATCH_MP_TAC(TAUT `(s ==> p /\ q /\ r) /\ s ==> p /\ q /\ r /\ s`) THEN
18024   CONJ_TAC THENL [MESON_TAC[REAL_LT_IMP_LE]; REPEAT GEN_TAC] THEN
18025   REWRITE_TAC[real_max; REAL_SUB_LE] THEN COND_CASES_TAC THEN
18026   SIMP_TAC[SETDIST_EQ_0_BOUNDED; BOUNDED_CBALL; CLOSED_CBALL; CLOSURE_CLOSED;
18027            CBALL_EQ_EMPTY; INTER_BALLS_EQ_EMPTY]
18028   THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
18029   ASM_CASES_TAC `b:real^N = a` THENL
18030    [FIRST_X_ASSUM SUBST_ALL_TAC THEN
18031     RULE_ASSUM_TAC(REWRITE_RULE[DIST_REFL]) THEN
18032     ASM_CASES_TAC `r = &0 /\ s = &0` THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
18033     ASM_SIMP_TAC[CBALL_SING; SETDIST_SINGS] THEN REAL_ARITH_TAC;
18034     STRIP_TAC] THEN
18035   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN CONJ_TAC THENL
18036    [ALL_TAC;
18037     MATCH_MP_TAC REAL_LE_SETDIST THEN
18038     ASM_REWRITE_TAC[CBALL_EQ_EMPTY; REAL_NOT_LT; IN_CBALL] THEN
18039     CONV_TAC NORM_ARITH] THEN
18040   MATCH_MP_TAC REAL_LE_TRANS THEN
18041   EXISTS_TAC `dist(a + r / dist(a,b) % (b - a):real^N,
18042                    b - s / dist(a,b) % (b - a))` THEN
18043   CONJ_TAC THENL
18044    [MATCH_MP_TAC SETDIST_LE_DIST THEN
18045     REWRITE_TAC[IN_CBALL; NORM_ARITH `dist(a:real^N,a + x) = norm x`;
18046                 NORM_ARITH `dist(a:real^N,a - x) = norm x`] THEN
18047     ONCE_REWRITE_TAC[DIST_SYM] THEN
18048     REWRITE_TAC[dist; NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
18049     ASM_SIMP_TAC[REAL_DIV_RMUL; VECTOR_SUB_EQ; NORM_EQ_0] THEN
18050     ASM_REAL_ARITH_TAC;
18051     REWRITE_TAC[dist; VECTOR_ARITH
18052      `(a + d % (b - a)) - (b - e % (b - a)):real^N =
18053       (&1 - d - e) % (a - b)`] THEN
18054     REWRITE_TAC[NORM_MUL; REAL_ARITH
18055       `&1 - r / y - s / y = &1 - (r + s) / y`] THEN
18056     ONCE_REWRITE_TAC[GSYM REAL_ABS_NORM] THEN
18057     REWRITE_TAC[GSYM REAL_ABS_MUL] THEN REWRITE_TAC[REAL_ABS_NORM] THEN
18058     ASM_SIMP_TAC[VECTOR_SUB_EQ; NORM_EQ_0; REAL_FIELD
18059      `~(n = &0) ==> (&1 - x / n) * n = n - x`] THEN
18060     REWRITE_TAC[GSYM dist] THEN ASM_REAL_ARITH_TAC]);;
18061
18062 (* ------------------------------------------------------------------------- *)
18063 (* Use set distance for an easy proof of separation properties etc.          *)
18064 (* ------------------------------------------------------------------------- *)
18065
18066 let SEPARATION_CLOSURES = prove
18067  (`!s t:real^N->bool.
18068         s INTER closure(t) = {} /\ t INTER closure(s) = {}
18069         ==> ?u v. DISJOINT u v /\ open u /\ open v /\
18070                   s SUBSET u /\ t SUBSET v`,
18071   REPEAT STRIP_TAC THEN
18072   ASM_CASES_TAC `s:real^N->bool = {}` THENL
18073    [MAP_EVERY EXISTS_TAC [`{}:real^N->bool`; `(:real^N)`] THEN
18074     ASM_REWRITE_TAC[OPEN_EMPTY; OPEN_UNIV] THEN ASM SET_TAC[];
18075     ALL_TAC] THEN
18076   ASM_CASES_TAC `t:real^N->bool = {}` THENL
18077    [MAP_EVERY EXISTS_TAC [`(:real^N)`; `{}:real^N->bool`] THEN
18078     ASM_REWRITE_TAC[OPEN_EMPTY; OPEN_UNIV] THEN ASM SET_TAC[];
18079     ALL_TAC] THEN
18080   EXISTS_TAC `{x | x IN (:real^N) /\
18081                    lift(setdist({x},t) - setdist({x},s)) IN
18082                    {x | &0 < x$1}}` THEN
18083   EXISTS_TAC `{x | x IN (:real^N) /\
18084                    lift(setdist({x},t) - setdist({x},s)) IN
18085                    {x | x$1 < &0}}` THEN
18086   REPEAT CONJ_TAC THENL
18087    [REWRITE_TAC[SET_RULE `DISJOINT s t <=> !x. x IN s /\ x IN t ==> F`] THEN
18088     REWRITE_TAC[IN_ELIM_THM; IN_UNIV] THEN REAL_ARITH_TAC;
18089     MATCH_MP_TAC CONTINUOUS_OPEN_PREIMAGE THEN
18090     SIMP_TAC[REWRITE_RULE[real_gt] OPEN_HALFSPACE_COMPONENT_GT; OPEN_UNIV] THEN
18091     SIMP_TAC[LIFT_SUB; CONTINUOUS_ON_SUB; CONTINUOUS_ON_LIFT_SETDIST];
18092     MATCH_MP_TAC CONTINUOUS_OPEN_PREIMAGE THEN
18093     SIMP_TAC[OPEN_HALFSPACE_COMPONENT_LT; OPEN_UNIV] THEN
18094     SIMP_TAC[LIFT_SUB; CONTINUOUS_ON_SUB; CONTINUOUS_ON_LIFT_SETDIST];
18095     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNIV; GSYM drop; LIFT_DROP] THEN
18096     GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC(REAL_ARITH
18097      `&0 <= x /\ y = &0 /\ ~(x = &0) ==> &0 < x - y`);
18098     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNIV; GSYM drop; LIFT_DROP] THEN
18099     GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC(REAL_ARITH
18100      `&0 <= y /\ x = &0 /\ ~(y = &0) ==> x - y < &0`)] THEN
18101   ASM_SIMP_TAC[SETDIST_POS_LE; SETDIST_EQ_0_BOUNDED; BOUNDED_SING] THEN
18102   ASM_SIMP_TAC[CLOSED_SING; CLOSURE_CLOSED; NOT_INSERT_EMPTY;
18103                REWRITE_RULE[SUBSET] CLOSURE_SUBSET;
18104                SET_RULE `{a} INTER s = {} <=> ~(a IN s)`] THEN
18105   ASM SET_TAC[]);;
18106
18107 let SEPARATION_NORMAL = prove
18108  (`!s t:real^N->bool.
18109         closed s /\ closed t /\ s INTER t = {}
18110         ==> ?u v. open u /\ open v /\
18111                   s SUBSET u /\ t SUBSET v /\ u INTER v = {}`,
18112   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM DISJOINT] THEN
18113   ONCE_REWRITE_TAC[TAUT
18114     `a /\ b /\ c /\ d /\ e <=> e /\ a /\ b /\ c /\ d`] THEN
18115   MATCH_MP_TAC SEPARATION_CLOSURES THEN
18116   ASM_SIMP_TAC[CLOSURE_CLOSED] THEN ASM SET_TAC[]);;
18117
18118 let SEPARATION_NORMAL_LOCAL = prove
18119  (`!s t u:real^N->bool.
18120         closed_in (subtopology euclidean u) s /\
18121         closed_in (subtopology euclidean u) t /\
18122         s INTER t = {}
18123         ==> ?s' t'. open_in (subtopology euclidean u) s' /\
18124                     open_in (subtopology euclidean u) t' /\
18125                     s SUBSET s' /\ t SUBSET t' /\ s' INTER t' = {}`,
18126   REPEAT STRIP_TAC THEN
18127   ASM_CASES_TAC `s:real^N->bool = {}` THENL
18128    [MAP_EVERY EXISTS_TAC [`{}:real^N->bool`; `u:real^N->bool`] THEN
18129     ASM_SIMP_TAC[OPEN_IN_REFL; OPEN_IN_EMPTY; INTER_EMPTY; EMPTY_SUBSET] THEN
18130     ASM_MESON_TAC[CLOSED_IN_IMP_SUBSET];
18131     ALL_TAC] THEN
18132   ASM_CASES_TAC `t:real^N->bool = {}` THENL
18133    [MAP_EVERY EXISTS_TAC [`u:real^N->bool`; `{}:real^N->bool`] THEN
18134     ASM_SIMP_TAC[OPEN_IN_REFL; OPEN_IN_EMPTY; INTER_EMPTY; EMPTY_SUBSET] THEN
18135     ASM_MESON_TAC[CLOSED_IN_IMP_SUBSET];
18136     ALL_TAC] THEN
18137   EXISTS_TAC `{x:real^N | x IN u /\ setdist({x},s) < setdist({x},t)}` THEN
18138   EXISTS_TAC `{x:real^N | x IN u /\ setdist({x},t) < setdist({x},s)}` THEN
18139   SIMP_TAC[EXTENSION; SUBSET; IN_ELIM_THM; SETDIST_SING_IN_SET; IN_INTER;
18140            NOT_IN_EMPTY; SETDIST_POS_LE; CONJ_ASSOC;
18141            REAL_ARITH `&0 < x <=> &0 <= x /\ ~(x = &0)`] THEN
18142   CONJ_TAC THENL [ALL_TAC; MESON_TAC[REAL_LT_ANTISYM]] THEN
18143   ONCE_REWRITE_TAC[GSYM CONJ_ASSOC] THEN CONJ_TAC THENL
18144    [ALL_TAC;
18145     ASM_MESON_TAC[SETDIST_EQ_0_CLOSED_IN; CLOSED_IN_IMP_SUBSET; SUBSET;
18146                   MEMBER_NOT_EMPTY; IN_INTER]] THEN
18147   ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
18148   ONCE_REWRITE_TAC[MESON[LIFT_DROP] `&0 < x <=> &0 < drop(lift x)`] THEN
18149   REWRITE_TAC[SET_RULE
18150    `{x | x IN u /\ &0 < drop(f x)} =
18151     {x | x IN u /\ f x IN {x | &0 < drop x}}`] THEN
18152   REWRITE_TAC[drop] THEN CONJ_TAC THEN
18153   MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE THEN
18154   REWRITE_TAC[OPEN_HALFSPACE_COMPONENT_LT; LIFT_SUB;
18155            REWRITE_RULE[real_gt] OPEN_HALFSPACE_COMPONENT_GT; OPEN_UNIV] THEN
18156   SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_LIFT_SETDIST]);;
18157
18158 let SEPARATION_NORMAL_COMPACT = prove
18159  (`!s t:real^N->bool.
18160         compact s /\ closed t /\ s INTER t = {}
18161         ==> ?u v. open u /\ compact(closure u) /\ open v /\
18162                   s SUBSET u /\ t SUBSET v /\ u INTER v = {}`,
18163   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_CLOSURE] THEN
18164   REPEAT STRIP_TAC THEN FIRST_ASSUM
18165    (MP_TAC o SPEC `vec 0:real^N` o MATCH_MP BOUNDED_SUBSET_BALL) THEN
18166   DISCH_THEN(X_CHOOSE_THEN `r:real` STRIP_ASSUME_TAC) THEN
18167   MP_TAC(ISPECL [`s:real^N->bool`; `t UNION ((:real^N) DIFF ball(vec 0,r))`]
18168         SEPARATION_NORMAL) THEN
18169   ASM_SIMP_TAC[CLOSED_UNION; GSYM OPEN_CLOSED; OPEN_BALL] THEN
18170   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
18171   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
18172   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
18173   CONJ_TAC THENL [MATCH_MP_TAC BOUNDED_CLOSURE; ASM SET_TAC[]] THEN
18174   MATCH_MP_TAC BOUNDED_SUBSET THEN EXISTS_TAC `ball(vec 0:real^N,r)` THEN
18175   REWRITE_TAC[BOUNDED_BALL] THEN ASM SET_TAC[]);;
18176
18177 let SEPARATION_HAUSDORFF = prove
18178  (`!x:real^N y.
18179       ~(x = y)
18180       ==> ?u v. open u /\ open v /\ x IN u /\ y IN v /\ (u INTER v = {})`,
18181   REPEAT STRIP_TAC THEN
18182   MP_TAC(SPECL [`{x:real^N}`; `{y:real^N}`] SEPARATION_NORMAL) THEN
18183   REWRITE_TAC[SING_SUBSET; CLOSED_SING] THEN
18184   DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]);;
18185
18186 let SEPARATION_T2 = prove
18187  (`!x:real^N y.
18188         ~(x = y) <=> ?u v. open u /\ open v /\ x IN u /\ y IN v /\
18189                            (u INTER v = {})`,
18190   REPEAT STRIP_TAC THEN EQ_TAC THEN ASM_SIMP_TAC[SEPARATION_HAUSDORFF] THEN
18191   REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN MESON_TAC[]);;
18192
18193 let SEPARATION_T1 = prove
18194  (`!x:real^N y.
18195         ~(x = y) <=> ?u v. open u /\ open v /\ x IN u /\ ~(y IN u) /\
18196                            ~(x IN v) /\ y IN v`,
18197   REPEAT STRIP_TAC THEN EQ_TAC THENL
18198    [ASM_SIMP_TAC[SEPARATION_T2; EXTENSION; NOT_IN_EMPTY; IN_INTER];
18199     ALL_TAC] THEN MESON_TAC[]);;
18200
18201 let SEPARATION_T0 = prove
18202  (`!x:real^N y. ~(x = y) <=> ?u. open u /\ ~(x IN u <=> y IN u)`,
18203   MESON_TAC[SEPARATION_T1]);;
18204
18205 (* ------------------------------------------------------------------------- *)
18206 (* Hausdorff distance between sets.                                          *)
18207 (* ------------------------------------------------------------------------- *)
18208
18209 let hausdist = new_definition
18210  `hausdist(s:real^N->bool,t:real^N->bool) =
18211         let ds = {setdist({x},t) | x IN s} UNION {setdist({y},s) | y IN t} in
18212         if ~(ds = {}) /\ (?b. !d. d IN ds ==> d <= b) then sup ds
18213         else &0`;;
18214
18215 let HAUSDIST_POS_LE = prove
18216  (`!s t:real^N->bool. &0 <= hausdist(s,t)`,
18217   REPEAT GEN_TAC THEN REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF] THEN
18218   REWRITE_TAC[FORALL_IN_GSPEC; FORALL_IN_UNION] THEN
18219   COND_CASES_TAC THEN REWRITE_TAC[REAL_LE_REFL] THEN
18220   MATCH_MP_TAC REAL_LE_SUP THEN
18221   ASM_REWRITE_TAC[FORALL_IN_GSPEC; FORALL_IN_UNION; SETDIST_POS_LE] THEN
18222   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
18223   ASM_REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN
18224   MATCH_MP_TAC(SET_RULE
18225    `~(s = {}) /\ (!x. x IN s ==> P x) ==> ?y. y IN s /\ P y`) THEN
18226   ASM_REWRITE_TAC[FORALL_IN_GSPEC; FORALL_IN_UNION; SETDIST_POS_LE]);;
18227
18228 let HAUSDIST_REFL = prove
18229  (`!s:real^N->bool. hausdist(s,s) = &0`,
18230   GEN_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM; HAUSDIST_POS_LE] THEN
18231   REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF] THEN
18232   COND_CASES_TAC THEN REWRITE_TAC[REAL_LE_REFL] THEN
18233   MATCH_MP_TAC REAL_SUP_LE THEN
18234   REWRITE_TAC[FORALL_IN_GSPEC; FORALL_IN_UNION] THEN
18235   ASM_SIMP_TAC[SETDIST_SING_IN_SET; REAL_LE_REFL]);;
18236
18237 let HAUSDIST_SYM = prove
18238  (`!s t:real^N->bool. hausdist(s,t) = hausdist(t,s)`,
18239   REPEAT GEN_TAC THEN REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF] THEN
18240   GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [UNION_COMM] THEN
18241   REWRITE_TAC[]);;
18242
18243 let HAUSDIST_EMPTY = prove
18244  (`(!t:real^N->bool. hausdist ({},t) = &0) /\
18245    (!s:real^N->bool. hausdist (s,{}) = &0)`,
18246   REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF; SETDIST_EMPTY] THEN
18247   REWRITE_TAC[SET_RULE `{f x | x IN {}} = {}`; UNION_EMPTY] THEN
18248   REWRITE_TAC[SET_RULE `{c |x| x IN s} = {} <=> s = {}`] THEN
18249   X_GEN_TAC `s:real^N->bool` THEN
18250   ASM_CASES_TAC `s:real^N->bool = {}` THEN ASM_REWRITE_TAC[] THEN
18251   ASM_SIMP_TAC[SET_RULE `~(s = {}) ==> {c |x| x IN s} = {c}`] THEN
18252   REWRITE_TAC[SUP_SING; COND_ID]);;
18253
18254 let HAUSDIST_SINGS = prove
18255  (`!x y:real^N. hausdist({x},{y}) = dist(x,y)`,
18256   REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF; SETDIST_SINGS] THEN
18257   REWRITE_TAC[SET_RULE `{f x | x IN {a}} = {f a}`] THEN
18258   REWRITE_TAC[DIST_SYM; UNION_IDEMPOT; SUP_SING; NOT_INSERT_EMPTY] THEN
18259   REWRITE_TAC[IN_SING; FORALL_UNWIND_THM2] THEN
18260   MESON_TAC[REAL_LE_REFL]);;
18261
18262 let HAUSDIST_EQ = prove
18263  (`!s t:real^M->bool s' t':real^N->bool.
18264         (!b. (!x. x IN s ==> setdist({x},t) <= b) /\
18265              (!y. y IN t ==> setdist({y},s) <= b) <=>
18266              (!x. x IN s' ==> setdist({x},t') <= b) /\
18267              (!y. y IN t' ==> setdist({y},s') <= b))
18268         ==> hausdist(s,t) = hausdist(s',t')`,
18269   REPEAT STRIP_TAC THEN REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF] THEN
18270   MATCH_MP_TAC(MESON[]
18271    `(p <=> p') /\ s = s'
18272     ==> (if p then s else &0) = (if p' then s' else &0)`) THEN
18273   CONJ_TAC THENL
18274    [BINOP_TAC THENL
18275      [PURE_REWRITE_TAC[SET_RULE `s = {} <=> !x. x IN s ==> F`];
18276       AP_TERM_TAC THEN ABS_TAC];
18277     MATCH_MP_TAC SUP_EQ] THEN
18278   PURE_REWRITE_TAC[FORALL_IN_UNION; FORALL_IN_GSPEC] THEN
18279   ASM_REWRITE_TAC[] THEN
18280   REWRITE_TAC[DE_MORGAN_THM; NOT_FORALL_THM; MEMBER_NOT_EMPTY] THEN
18281   REWRITE_TAC[GSYM DE_MORGAN_THM] THEN AP_TERM_TAC THEN EQ_TAC THEN
18282   DISCH_THEN(fun th -> POP_ASSUM MP_TAC THEN ASSUME_TAC th) THEN
18283   ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
18284   DISCH_THEN(MP_TAC o SPEC `--(&1):real`) THEN
18285   SIMP_TAC[SETDIST_POS_LE; REAL_ARITH `&0 <= x ==> ~(x <= --(&1))`] THEN
18286   SET_TAC[]);;
18287
18288 let HAUSDIST_TRANSLATION = prove
18289  (`!a s t:real^N->bool.
18290         hausdist(IMAGE (\x. a + x) s,IMAGE (\x. a + x) t) = hausdist(s,t)`,
18291   REPEAT GEN_TAC THEN REWRITE_TAC[hausdist] THEN
18292   REWRITE_TAC[SET_RULE `{f x | x IN IMAGE g s} = {f(g x) | x IN s}`] THEN
18293   REWRITE_TAC[SET_RULE `{a + x:real^N} = IMAGE (\x. a + x) {x}`] THEN
18294   REWRITE_TAC[SETDIST_TRANSLATION]);;
18295
18296 add_translation_invariants [HAUSDIST_TRANSLATION];;
18297
18298 let HAUSDIST_LINEAR_IMAGE = prove
18299  (`!f:real^M->real^N s t.
18300            linear f /\ (!x. norm(f x) = norm x)
18301            ==> hausdist(IMAGE f s,IMAGE f t) = hausdist(s,t)`,
18302   REPEAT STRIP_TAC THEN
18303   REPEAT GEN_TAC THEN REWRITE_TAC[hausdist] THEN
18304   REWRITE_TAC[SET_RULE `{f x | x IN IMAGE g s} = {f(g x) | x IN s}`] THEN
18305   ONCE_REWRITE_TAC[SET_RULE `{(f:real^M->real^N) x} = IMAGE f {x}`] THEN
18306   ASM_SIMP_TAC[SETDIST_LINEAR_IMAGE]);;
18307
18308 add_linear_invariants [HAUSDIST_LINEAR_IMAGE];;
18309
18310 let HAUSDIST_CLOSURE = prove
18311  (`(!s t:real^N->bool. hausdist(closure s,t) = hausdist(s,t)) /\
18312    (!s t:real^N->bool. hausdist(s,closure t) = hausdist(s,t))`,
18313   REPEAT STRIP_TAC THEN MATCH_MP_TAC HAUSDIST_EQ THEN
18314   GEN_TAC THEN BINOP_TAC THEN REWRITE_TAC[SETDIST_CLOSURE] THEN
18315   PURE_ONCE_REWRITE_TAC[SET_RULE
18316    `(!x. P x ==> Q x) <=> (!x. P x ==> x IN {x | Q x})`] THEN
18317   MATCH_MP_TAC FORALL_IN_CLOSURE_EQ THEN
18318   REWRITE_TAC[EMPTY_GSPEC; CONTINUOUS_ON_ID; CLOSED_EMPTY] THEN
18319   ONCE_REWRITE_TAC[MESON[LIFT_DROP] `x <= b <=> drop(lift x) <= b`] THEN
18320   REWRITE_TAC[SET_RULE
18321     `{x | drop(lift(f x)) <= b} =
18322      {x | x IN UNIV /\ lift(f x) IN {x | drop x <= b}}`] THEN
18323   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE THEN
18324   REWRITE_TAC[CLOSED_UNIV; CONTINUOUS_ON_LIFT_SETDIST] THEN
18325   REWRITE_TAC[drop; CLOSED_HALFSPACE_COMPONENT_LE]);;
18326
18327 let REAL_HAUSDIST_LE = prove
18328  (`!s t:real^N->bool b.
18329         ~(s = {}) /\ ~(t = {}) /\
18330         (!x. x IN s ==> setdist({x},t) <= b) /\
18331         (!y. y IN t ==> setdist({y},s) <= b)
18332         ==> hausdist(s,t) <= b`,
18333   REPEAT STRIP_TAC THEN
18334   REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF; SETDIST_SINGS] THEN
18335   ASM_REWRITE_TAC[EMPTY_UNION; SET_RULE `{f x | x IN s} = {} <=> s = {}`] THEN
18336   REWRITE_TAC[FORALL_IN_UNION; FORALL_IN_GSPEC] THEN
18337   COND_CASES_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
18338   MATCH_MP_TAC REAL_SUP_LE THEN
18339   ASM_REWRITE_TAC[EMPTY_UNION; SET_RULE `{f x | x IN s} = {} <=> s = {}`] THEN
18340   ASM_REWRITE_TAC[FORALL_IN_UNION; FORALL_IN_GSPEC]);;
18341
18342 let REAL_HAUSDIST_LE_SUMS = prove
18343  (`!s t:real^N->bool b.
18344         ~(s = {}) /\ ~(t = {}) /\
18345         s SUBSET {y + z | y IN t /\ z IN cball(vec 0,b)} /\
18346         t SUBSET {y + z | y IN s /\ z IN cball(vec 0,b)}
18347         ==> hausdist(s,t) <= b`,
18348   REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_CBALL_0] THEN
18349   REWRITE_TAC[VECTOR_ARITH `a:real^N = b + x <=> a - b = x`;
18350               ONCE_REWRITE_RULE[CONJ_SYM] UNWIND_THM1] THEN
18351   REWRITE_TAC[GSYM dist] THEN REPEAT STRIP_TAC THEN
18352   MATCH_MP_TAC REAL_HAUSDIST_LE THEN
18353   ASM_MESON_TAC[SETDIST_LE_DIST; REAL_LE_TRANS; IN_SING]);;
18354
18355 let REAL_LE_HAUSDIST  = prove
18356  (`!s t:real^N->bool a b c z.
18357         ~(s = {}) /\ ~(t = {}) /\
18358         (!x. x IN s ==> setdist({x},t) <= b) /\
18359         (!y. y IN t ==> setdist({y},s) <= c) /\
18360         (z IN s /\ a <= setdist({z},t) \/ z IN t /\ a <= setdist({z},s))
18361         ==> a <= hausdist(s,t)`,
18362   REPEAT GEN_TAC THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
18363   REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF; SETDIST_SINGS] THEN
18364   ASM_REWRITE_TAC[EMPTY_UNION; SET_RULE `{f x | x IN s} = {} <=> s = {}`] THEN
18365   REWRITE_TAC[FORALL_IN_UNION; FORALL_IN_GSPEC] THEN COND_CASES_TAC THENL
18366    [MATCH_MP_TAC REAL_LE_SUP THEN
18367     ASM_SIMP_TAC[EMPTY_UNION; SET_RULE `{f x | x IN s} = {} <=> s = {}`] THEN
18368     REWRITE_TAC[FORALL_IN_UNION; FORALL_IN_GSPEC];
18369     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
18370     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
18371     REWRITE_TAC[NOT_FORALL_THM]] THEN
18372   EXISTS_TAC `max b c:real` THEN
18373   ASM_SIMP_TAC[REAL_LE_MAX] THEN ASM SET_TAC[]);;
18374
18375 let SETDIST_LE_HAUSDIST = prove
18376  (`!s t:real^N->bool.
18377         bounded s /\ bounded t ==> setdist(s,t) <= hausdist(s,t)`,
18378   REPEAT STRIP_TAC THEN
18379   ASM_CASES_TAC `s:real^N->bool = {}` THEN
18380   ASM_REWRITE_TAC[SETDIST_EMPTY; HAUSDIST_EMPTY; REAL_LE_REFL] THEN
18381   ASM_CASES_TAC `t:real^N->bool = {}` THEN
18382   ASM_REWRITE_TAC[SETDIST_EMPTY; HAUSDIST_EMPTY; REAL_LE_REFL] THEN
18383   MATCH_MP_TAC REAL_LE_HAUSDIST THEN REWRITE_TAC[CONJ_ASSOC] THEN
18384   ASM_REWRITE_TAC[RIGHT_EXISTS_AND_THM; LEFT_EXISTS_AND_THM] THEN
18385   CONJ_TAC THENL
18386    [ALL_TAC; ASM_MESON_TAC[SETDIST_LE_SING; MEMBER_NOT_EMPTY]] THEN
18387   MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`] BOUNDED_DIFFS) THEN
18388   ASM_REWRITE_TAC[] THEN REWRITE_TAC[bounded; FORALL_IN_GSPEC; GSYM dist] THEN
18389   DISCH_THEN(X_CHOOSE_TAC `b:real`) THEN
18390   CONJ_TAC THEN EXISTS_TAC `b:real` THEN REPEAT STRIP_TAC THEN
18391   ASM_MESON_TAC[REAL_LE_TRANS; SETDIST_LE_DIST; MEMBER_NOT_EMPTY; IN_SING;
18392                 DIST_SYM]);;
18393
18394 let SETDIST_SING_LE_HAUSDIST = prove
18395  (`!s t x:real^N.
18396         bounded s /\ bounded t /\ x IN s ==> setdist({x},t) <= hausdist(s,t)`,
18397   REPEAT GEN_TAC THEN
18398   ASM_CASES_TAC `s:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
18399   ASM_CASES_TAC `t:real^N->bool = {}` THEN
18400   ASM_REWRITE_TAC[SETDIST_EMPTY; HAUSDIST_EMPTY; REAL_LE_REFL] THEN
18401   STRIP_TAC THEN MATCH_MP_TAC REAL_LE_HAUSDIST THEN
18402   ASM_REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN
18403   REWRITE_TAC[LEFT_EXISTS_AND_THM; EXISTS_OR_THM; CONJ_ASSOC] THEN
18404   CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[REAL_LE_REFL]] THEN CONJ_TAC THEN
18405   MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`] BOUNDED_DIFFS) THEN
18406   ASM_REWRITE_TAC[] THEN REWRITE_TAC[bounded; FORALL_IN_GSPEC] THEN
18407   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[GSYM dist] THEN GEN_TAC THENL
18408    [ALL_TAC; ONCE_REWRITE_TAC[SWAP_FORALL_THM]] THEN
18409   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `y:real^N` THEN
18410   REPEAT STRIP_TAC THENL
18411    [UNDISCH_TAC `~(t:real^N->bool = {})`;
18412     UNDISCH_TAC `~(s:real^N->bool = {})`] THEN
18413   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
18414   DISCH_THEN(X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC) THEN
18415   FIRST_X_ASSUM(MP_TAC o SPEC `z:real^N`) THEN ASM_REWRITE_TAC[] THEN
18416   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] REAL_LE_TRANS) THENL
18417    [ALL_TAC; ONCE_REWRITE_TAC[DIST_SYM]] THEN
18418   MATCH_MP_TAC SETDIST_LE_DIST THEN ASM_REWRITE_TAC[IN_SING]);;
18419
18420 let UPPER_LOWER_HEMICONTINUOUS = prove
18421  (`!f:real^M->real^N->bool t s.
18422       (!x. x IN s ==> f(x) SUBSET t) /\
18423       (!u. open_in (subtopology euclidean t) u
18424            ==> open_in (subtopology euclidean s)
18425                        {x | x IN s /\ f(x) SUBSET u}) /\
18426       (!u. closed_in (subtopology euclidean t) u
18427            ==> closed_in (subtopology euclidean s)
18428                          {x | x IN s /\ f(x) SUBSET u})
18429       ==> !x e. x IN s /\ &0 < e /\ bounded(f x)
18430                 ==> ?d. &0 < d /\
18431                         !x'. x' IN s /\ dist(x,x') < d
18432                              ==> hausdist(f x,f x') < e`,
18433   REPEAT GEN_TAC THEN DISCH_TAC THEN REPEAT STRIP_TAC THEN
18434   ASM_CASES_TAC `(f:real^M->real^N->bool) x = {}` THENL
18435    [ASM_REWRITE_TAC[HAUSDIST_EMPTY] THEN MESON_TAC[REAL_LT_01]; ALL_TAC] THEN
18436   FIRST_ASSUM(MP_TAC o SPECL [`x:real^M`; `e / &2`] o MATCH_MP
18437         UPPER_LOWER_HEMICONTINUOUS_EXPLICIT) THEN
18438   ASM_REWRITE_TAC[REAL_HALF] THEN
18439   DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN
18440   FIRST_ASSUM(MP_TAC o SPEC `vec 0:real^N` o MATCH_MP BOUNDED_SUBSET_BALL) THEN
18441   DISCH_THEN(X_CHOOSE_THEN `r:real` STRIP_ASSUME_TAC) THEN
18442   FIRST_ASSUM(MP_TAC o SPEC `t INTER ball(vec 0:real^N,r)` o
18443         CONJUNCT1 o CONJUNCT2) THEN
18444   SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_BALL] THEN REWRITE_TAC[open_in] THEN
18445   DISCH_THEN(MP_TAC o SPEC `x:real^M` o CONJUNCT2) THEN
18446   ASM_SIMP_TAC[SUBSET_INTER; IN_ELIM_THM] THEN
18447   DISCH_THEN(X_CHOOSE_THEN `d2:real` STRIP_ASSUME_TAC) THEN
18448   EXISTS_TAC `min d1 d2:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
18449   X_GEN_TAC `x':real^M` THEN STRIP_TAC THEN
18450   REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `x':real^M`)) THEN
18451   ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN ASM_REWRITE_TAC[] THEN
18452   STRIP_TAC THEN STRIP_TAC THEN
18453   ASM_CASES_TAC `(f:real^M->real^N->bool) x' = {}` THEN
18454   ASM_REWRITE_TAC[HAUSDIST_EMPTY] THEN
18455   MATCH_MP_TAC(REAL_ARITH `&0 < e /\ x <= e / &2 ==> x < e`) THEN
18456   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_HAUSDIST_LE THEN
18457   ASM_MESON_TAC[SETDIST_LE_DIST; DIST_SYM; REAL_LE_TRANS;
18458                 IN_SING; REAL_LT_IMP_LE]);;
18459
18460 let HAUSDIST_NONTRIVIAL = prove
18461  (`!s t:real^N->bool.
18462         bounded s /\ bounded t /\ ~(s = {}) /\ ~(t = {})
18463         ==> hausdist(s,t) =
18464             sup({setdist ({x},t) | x IN s} UNION {setdist ({y},s) | y IN t})`,
18465   REPEAT STRIP_TAC THEN REWRITE_TAC[hausdist; LET_DEF; LET_END_DEF] THEN
18466   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
18467   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [DE_MORGAN_THM]) THEN
18468   ASM_SIMP_TAC[EMPTY_UNION; SIMPLE_IMAGE; IMAGE_EQ_EMPTY] THEN
18469   MATCH_MP_TAC(TAUT `p ==> ~p ==> q`) THEN
18470   MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`] BOUNDED_DIFFS) THEN
18471   ASM_REWRITE_TAC[bounded; FORALL_IN_UNION; FORALL_IN_IMAGE; GSYM dist] THEN
18472   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
18473   ASM_MESON_TAC[SETDIST_LE_DIST; dist; DIST_SYM; REAL_LE_TRANS;
18474                 MEMBER_NOT_EMPTY; IN_SING]);;
18475
18476 let HAUSDIST_NONTRIVIAL_ALT = prove
18477  (`!s t:real^N->bool.
18478         bounded s /\ bounded t /\ ~(s = {}) /\ ~(t = {})
18479         ==> hausdist(s,t) = max (sup {setdist ({x},t) | x IN s})
18480                                 (sup {setdist ({y},s) | y IN t})`,
18481   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[HAUSDIST_NONTRIVIAL] THEN
18482   MATCH_MP_TAC SUP_UNION THEN
18483   ASM_REWRITE_TAC[SIMPLE_IMAGE; FORALL_IN_IMAGE; IMAGE_EQ_EMPTY] THEN
18484   CONJ_TAC THEN
18485   MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`] BOUNDED_DIFFS) THEN
18486   ASM_REWRITE_TAC[bounded; FORALL_IN_UNION; FORALL_IN_IMAGE; GSYM dist] THEN
18487   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[FORALL_IN_GSPEC; GSYM dist] THEN
18488   ASM_MESON_TAC[SETDIST_LE_DIST; dist; DIST_SYM; REAL_LE_TRANS;
18489                 MEMBER_NOT_EMPTY; IN_SING]);;
18490
18491 let REAL_HAUSDIST_LE_EQ = prove
18492  (`!s t:real^N->bool b.
18493         ~(s = {}) /\ ~(t = {}) /\ bounded s /\ bounded t
18494         ==> (hausdist(s,t) <= b <=>
18495              (!x. x IN s ==> setdist({x},t) <= b) /\
18496              (!y. y IN t ==> setdist({y},s) <= b))`,
18497   REPEAT STRIP_TAC THEN
18498   ASM_SIMP_TAC[HAUSDIST_NONTRIVIAL_ALT; REAL_MAX_LE] THEN
18499   BINOP_TAC THEN
18500   ONCE_REWRITE_TAC[SET_RULE `(!x. x IN s ==> f x <= b) <=>
18501                              (!y. y IN {f x | x IN s} ==> y <= b)`] THEN
18502   MATCH_MP_TAC REAL_SUP_LE_EQ THEN
18503   ASM_REWRITE_TAC[SIMPLE_IMAGE; IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
18504   MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`] BOUNDED_DIFFS) THEN
18505   ASM_REWRITE_TAC[bounded; FORALL_IN_UNION; FORALL_IN_IMAGE; GSYM dist] THEN
18506   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[FORALL_IN_GSPEC; GSYM dist] THEN
18507   ASM_MESON_TAC[SETDIST_LE_DIST; dist; DIST_SYM; REAL_LE_TRANS;
18508                 MEMBER_NOT_EMPTY; IN_SING]);;
18509
18510 let HAUSDIST_COMPACT_EXISTS = prove
18511  (`!s t:real^N->bool.
18512         bounded s /\ compact t /\ ~(t = {})
18513         ==> !x. x IN s ==> ?y. y IN t /\ dist(x,y) <= hausdist(s,t)`,
18514   REPEAT STRIP_TAC THEN
18515   ASM_CASES_TAC `s:real^N->bool = {}` THENL [ASM SET_TAC[]; ALL_TAC] THEN
18516   MP_TAC(ISPECL [`{x:real^N}`; `t:real^N->bool`]
18517         SETDIST_COMPACT_CLOSED) THEN
18518   ASM_SIMP_TAC[COMPACT_SING; COMPACT_IMP_CLOSED; NOT_INSERT_EMPTY] THEN
18519   REWRITE_TAC[IN_SING; UNWIND_THM2; RIGHT_EXISTS_AND_THM; UNWIND_THM1] THEN
18520   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real^N` THEN
18521   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
18522   MATCH_MP_TAC REAL_LE_HAUSDIST THEN
18523   ASM_REWRITE_TAC[LEFT_EXISTS_AND_THM; RIGHT_EXISTS_AND_THM] THEN
18524   REWRITE_TAC[CONJ_ASSOC] THEN
18525   CONJ_TAC THENL [CONJ_TAC; ASM_MESON_TAC[REAL_LE_REFL]] THEN
18526   MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`] BOUNDED_DIFFS) THEN
18527   ASM_SIMP_TAC[COMPACT_IMP_BOUNDED] THEN
18528   REWRITE_TAC[bounded; FORALL_IN_GSPEC; GSYM dist] THEN
18529   MATCH_MP_TAC MONO_EXISTS THEN
18530   ASM_MESON_TAC[SETDIST_LE_DIST; dist; DIST_SYM; REAL_LE_TRANS;
18531                 MEMBER_NOT_EMPTY; IN_SING]);;
18532
18533 let HAUSDIST_COMPACT_SUMS = prove
18534  (`!s t:real^N->bool.
18535         bounded s /\ compact t /\ ~(t = {})
18536         ==> s SUBSET {y + z | y IN t /\ z IN cball(vec 0,hausdist(s,t))}`,
18537   REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_CBALL_0] THEN
18538   REWRITE_TAC[VECTOR_ARITH `a:real^N = b + x <=> a - b = x`;
18539               ONCE_REWRITE_RULE[CONJ_SYM] UNWIND_THM1] THEN
18540   REWRITE_TAC[GSYM dist; HAUSDIST_COMPACT_EXISTS]);;
18541
18542 let HAUSDIST_TRANS = prove
18543  (`!s t u:real^N->bool.
18544         bounded s /\ bounded t /\ bounded u /\ ~(t = {})
18545         ==> hausdist(s,u) <= hausdist(s,t) + hausdist(t,u)`,
18546   let lemma = prove
18547    (`!s t u:real^N->bool.
18548           bounded s /\ bounded t /\ bounded u /\
18549           ~(s = {}) /\ ~(t = {}) /\ ~(u = {})
18550           ==> !x. x IN s ==> setdist({x},u) <= hausdist(s,t) + hausdist(t,u)`,
18551     REPEAT STRIP_TAC THEN
18552     MP_TAC(ISPECL [`closure s:real^N->bool`; `closure t:real^N->bool`]
18553         HAUSDIST_COMPACT_EXISTS) THEN
18554     ASM_SIMP_TAC[COMPACT_CLOSURE; BOUNDED_CLOSURE; CLOSURE_EQ_EMPTY] THEN
18555     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
18556     ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET; HAUSDIST_CLOSURE] THEN
18557     DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
18558     MP_TAC(ISPECL [`closure t:real^N->bool`; `closure u:real^N->bool`]
18559       HAUSDIST_COMPACT_EXISTS) THEN
18560     ASM_SIMP_TAC[COMPACT_CLOSURE; BOUNDED_CLOSURE; CLOSURE_EQ_EMPTY] THEN
18561     DISCH_THEN(MP_TAC o SPEC `y:real^N`) THEN
18562     ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET; HAUSDIST_CLOSURE] THEN
18563     DISCH_THEN(X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC) THEN
18564     TRANS_TAC REAL_LE_TRANS `dist(x:real^N,z)` THEN  CONJ_TAC THENL
18565      [ASM_MESON_TAC[SETDIST_CLOSURE; SETDIST_LE_DIST; IN_SING]; ALL_TAC] THEN
18566     TRANS_TAC REAL_LE_TRANS `dist(x:real^N,y) + dist(y,z)` THEN
18567     REWRITE_TAC[DIST_TRIANGLE] THEN ASM_REAL_ARITH_TAC) in
18568   REPEAT STRIP_TAC THEN
18569   ASM_CASES_TAC `s:real^N->bool = {}` THEN
18570   ASM_REWRITE_TAC[HAUSDIST_EMPTY; REAL_ADD_LID; HAUSDIST_POS_LE] THEN
18571   ASM_CASES_TAC `u:real^N->bool = {}` THEN
18572   ASM_REWRITE_TAC[HAUSDIST_EMPTY; REAL_ADD_RID; HAUSDIST_POS_LE] THEN
18573   ASM_SIMP_TAC[REAL_HAUSDIST_LE_EQ] THEN
18574   ASM_MESON_TAC[lemma; HAUSDIST_SYM; SETDIST_SYM; REAL_ADD_SYM]);;
18575
18576 let HAUSDIST_EQ_0 = prove
18577  (`!s t:real^N->bool.
18578       bounded s /\ bounded t
18579       ==> (hausdist(s,t) = &0 <=> s = {} \/ t = {} \/ closure s = closure t)`,
18580   REPEAT STRIP_TAC THEN
18581   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
18582   ASM_REWRITE_TAC[HAUSDIST_EMPTY] THEN
18583   ASM_SIMP_TAC[GSYM REAL_LE_ANTISYM; HAUSDIST_POS_LE; REAL_HAUSDIST_LE_EQ] THEN
18584   SIMP_TAC[SETDIST_POS_LE; REAL_ARITH `&0 <= x ==> (x <= &0 <=> x = &0)`] THEN
18585   ASM_REWRITE_TAC[SETDIST_EQ_0_SING; GSYM SUBSET_ANTISYM_EQ; SUBSET] THEN
18586   SIMP_TAC[FORALL_IN_CLOSURE_EQ; CLOSED_CLOSURE; CONTINUOUS_ON_ID]);;
18587
18588 let HAUSDIST_COMPACT_NONTRIVIAL = prove
18589  (`!s t:real^N->bool.
18590         compact s /\ compact t /\ ~(s = {}) /\ ~(t = {})
18591         ==> hausdist(s,t) =
18592             inf {e | &0 <= e /\
18593                    s SUBSET {x + y | x IN t /\ norm y <= e} /\
18594                    t SUBSET {x + y | x IN s /\ norm y <= e}}`,
18595   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN
18596   MATCH_MP_TAC REAL_INF_UNIQUE THEN
18597   REWRITE_TAC[FORALL_IN_GSPEC; EXISTS_IN_GSPEC] THEN
18598   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
18599   REWRITE_TAC[VECTOR_ARITH `a:real^N = b + x <=> a - b = x`;
18600               ONCE_REWRITE_RULE[CONJ_SYM] UNWIND_THM1] THEN
18601   REWRITE_TAC[GSYM dist] THEN CONJ_TAC THENL
18602    [REPEAT STRIP_TAC THEN
18603     MATCH_MP_TAC REAL_HAUSDIST_LE THEN
18604     ASM_MESON_TAC[SETDIST_LE_DIST; DIST_SYM; REAL_LE_TRANS;
18605                   IN_SING; REAL_LT_IMP_LE];
18606     REPEAT STRIP_TAC THEN EXISTS_TAC `hausdist(s:real^N->bool,t)` THEN
18607     ASM_REWRITE_TAC[HAUSDIST_POS_LE] THEN
18608     ASM_MESON_TAC[DIST_SYM; HAUSDIST_SYM;
18609                   HAUSDIST_COMPACT_EXISTS; COMPACT_IMP_BOUNDED]]);;
18610
18611 let HAUSDIST_BALLS = prove
18612  (`(!a b:real^N r s.
18613         hausdist(ball(a,r),ball(b,s)) =
18614         if r <= &0 \/ s <= &0 then &0 else dist(a,b) + abs(r - s)) /\
18615    (!a b:real^N r s.
18616         hausdist(ball(a,r),cball(b,s)) =
18617         if r <= &0 \/ s < &0 then &0 else dist(a,b) + abs(r - s)) /\
18618    (!a b:real^N r s.
18619         hausdist(cball(a,r),ball(b,s)) =
18620         if r < &0 \/ s <= &0 then &0 else dist(a,b) + abs(r - s)) /\
18621    (!a b:real^N r s.
18622         hausdist(cball(a,r),cball(b,s)) =
18623         if r < &0 \/ s < &0 then &0 else dist(a,b) + abs(r - s))`,
18624   REWRITE_TAC[MESON[]
18625    `(x = if p then y else z) <=> (p ==> x = y) /\ (~p ==> x = z)`] THEN
18626   SIMP_TAC[TAUT `p \/ q ==> r <=> (p ==> r) /\ (q ==> r)`] THEN
18627   SIMP_TAC[BALL_EMPTY; CBALL_EMPTY; HAUSDIST_EMPTY; DE_MORGAN_THM] THEN
18628   ONCE_REWRITE_TAC[MESON[HAUSDIST_CLOSURE]
18629    `hausdist(s,t) = hausdist(closure s,closure t)`] THEN
18630   SIMP_TAC[REAL_NOT_LE; REAL_NOT_LT; CLOSURE_BALL] THEN
18631   REWRITE_TAC[HAUSDIST_CLOSURE] THEN
18632   MATCH_MP_TAC(TAUT `(s ==> p /\ q /\ r) /\ s ==> p /\ q /\ r /\ s`) THEN
18633   CONJ_TAC THENL [MESON_TAC[REAL_LT_IMP_LE]; REPEAT STRIP_TAC] THEN
18634   ASM_SIMP_TAC[HAUSDIST_NONTRIVIAL; BOUNDED_CBALL; CBALL_EQ_EMPTY;
18635                REAL_NOT_LT] THEN
18636   MATCH_MP_TAC SUP_UNIQUE THEN
18637   REWRITE_TAC[FORALL_IN_GSPEC; FORALL_IN_UNION] THEN
18638   REWRITE_TAC[MESON[CBALL_SING] `{a} = cball(a:real^N,&0)`] THEN
18639   ASM_REWRITE_TAC[SETDIST_BALLS; REAL_LT_REFL] THEN
18640   X_GEN_TAC `c:real` THEN REWRITE_TAC[IN_CBALL] THEN
18641   EQ_TAC THENL [ALL_TAC; NORM_ARITH_TAC] THEN
18642   ASM_CASES_TAC `b:real^N = a` THENL
18643    [ASM_REWRITE_TAC[DIST_SYM; DIST_REFL; REAL_MAX_LE] THEN
18644     DISCH_THEN(CONJUNCTS_THEN2
18645      (MP_TAC o SPEC `a + r % basis 1:real^N`)
18646      (MP_TAC o SPEC `a + s % basis 1:real^N`)) THEN
18647     REWRITE_TAC[NORM_ARITH `dist(a:real^N,a + x) = norm x`] THEN
18648     SIMP_TAC[NORM_MUL; NORM_BASIS; LE_REFL; DIMINDEX_GE_1] THEN
18649     ASM_REAL_ARITH_TAC;
18650     DISCH_THEN(CONJUNCTS_THEN2
18651      (MP_TAC o SPEC `a - r / dist(a,b) % (b - a):real^N`)
18652      (MP_TAC o SPEC `b - s / dist(a,b) % (a - b):real^N`)) THEN
18653     REWRITE_TAC[NORM_ARITH `dist(a:real^N,a - x) = norm x`] THEN
18654     REWRITE_TAC[dist; NORM_MUL; VECTOR_ARITH
18655      `b - e % (a - b) - a:real^N = (&1 + e) % (b - a)`] THEN
18656     ONCE_REWRITE_TAC[GSYM REAL_ABS_NORM] THEN
18657     REWRITE_TAC[GSYM REAL_ABS_MUL] THEN REWRITE_TAC[REAL_ABS_NORM] THEN
18658     REWRITE_TAC[NORM_SUB; REAL_ADD_RDISTRIB; REAL_MUL_LID] THEN
18659     ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ] THEN
18660     ASM_REAL_ARITH_TAC]);;
18661
18662 let HAUSDIST_ALT = prove
18663  (`!s t:real^N->bool.
18664         bounded s /\ bounded t /\ ~(s = {}) /\ ~(t = {})
18665         ==> hausdist(s,t) =
18666             sup {abs(setdist({x},s) - setdist({x},t)) | x IN (:real^N)}`,
18667   REPEAT GEN_TAC THEN
18668   ONCE_REWRITE_TAC[GSYM COMPACT_CLOSURE; GSYM(CONJUNCT2 SETDIST_CLOSURE);
18669     GSYM CLOSURE_EQ_EMPTY; MESON[HAUSDIST_CLOSURE]
18670     `hausdist(s:real^N->bool,t) = hausdist(closure s,closure t)`] THEN
18671   SPEC_TAC(`closure t:real^N->bool`,`t:real^N->bool`) THEN
18672   SPEC_TAC(`closure s:real^N->bool`,`s:real^N->bool`) THEN
18673   REPEAT STRIP_TAC THEN
18674   ASM_SIMP_TAC[HAUSDIST_NONTRIVIAL; COMPACT_IMP_BOUNDED] THEN
18675   MATCH_MP_TAC SUP_EQ THEN
18676   REWRITE_TAC[FORALL_IN_UNION; FORALL_IN_GSPEC; IN_UNIV] THEN
18677   REWRITE_TAC[REAL_ARITH `abs(y - x) <= b <=> x <= y + b /\ y <= x + b`] THEN
18678   GEN_TAC THEN REWRITE_TAC[FORALL_AND_THM] THEN BINOP_TAC THEN
18679   (EQ_TAC THENL [ALL_TAC; MESON_TAC[SETDIST_SING_IN_SET; REAL_ADD_LID]]) THEN
18680   DISCH_TAC THEN X_GEN_TAC `z:real^N` THENL
18681    [MP_TAC(ISPECL[`{z:real^N}`; `s:real^N->bool`] SETDIST_CLOSED_COMPACT);
18682     MP_TAC(ISPECL[`{z:real^N}`; `t:real^N->bool`] SETDIST_CLOSED_COMPACT)] THEN
18683   ASM_REWRITE_TAC[CLOSED_SING; NOT_INSERT_EMPTY] THEN
18684   REWRITE_TAC[IN_SING; RIGHT_EXISTS_AND_THM; UNWIND_THM2] THEN
18685   DISCH_THEN(X_CHOOSE_THEN `y:real^N` (STRIP_ASSUME_TAC o GSYM)) THEN
18686   FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THENL
18687    [MP_TAC(ISPECL[`{y:real^N}`; `t:real^N->bool`] SETDIST_CLOSED_COMPACT);
18688     MP_TAC(ISPECL[`{y:real^N}`; `s:real^N->bool`] SETDIST_CLOSED_COMPACT)] THEN
18689   ASM_REWRITE_TAC[CLOSED_SING; NOT_INSERT_EMPTY] THEN
18690   REWRITE_TAC[IN_SING; RIGHT_EXISTS_AND_THM; UNWIND_THM2] THEN
18691   DISCH_THEN(X_CHOOSE_THEN `x:real^N` (STRIP_ASSUME_TAC o GSYM)) THEN
18692   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
18693   TRANS_TAC REAL_LE_TRANS `dist(z:real^N,x)` THEN
18694   ASM_SIMP_TAC[SETDIST_LE_DIST; IN_SING] THEN
18695   UNDISCH_TAC `dist(y:real^N,x) <= b` THEN CONV_TAC NORM_ARITH);;
18696
18697 let CONTINUOUS_DIAMETER = prove
18698  (`!s:real^N->bool e.
18699         bounded s /\ ~(s = {}) /\ &0 < e
18700         ==> ?d. &0 < d /\
18701                 !t. bounded t /\ ~(t = {}) /\ hausdist(s,t) < d
18702                     ==> abs(diameter s - diameter t) < e`,
18703   REPEAT STRIP_TAC THEN EXISTS_TAC `e / &2` THEN
18704   ASM_REWRITE_TAC[REAL_HALF] THEN REPEAT STRIP_TAC THEN
18705   SUBGOAL_THEN `diameter(s:real^N->bool) - diameter(t:real^N->bool) =
18706                 diameter(closure s) - diameter(closure t)`
18707   SUBST1_TAC THENL [ASM_MESON_TAC[DIAMETER_CLOSURE]; ALL_TAC] THEN
18708   MATCH_MP_TAC REAL_LET_TRANS THEN
18709   EXISTS_TAC `&2 * hausdist(s:real^N->bool,t)` THEN
18710   CONJ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
18711   MP_TAC(ISPECL [`vec 0:real^N`; `hausdist(s:real^N->bool,t)`]
18712     DIAMETER_CBALL) THEN
18713   ASM_SIMP_TAC[HAUSDIST_POS_LE; GSYM REAL_NOT_LE] THEN
18714   DISCH_THEN(SUBST1_TAC o SYM) THEN MATCH_MP_TAC(REAL_ARITH
18715    `x <= y + e /\ y <= x + e ==> abs(x - y) <= e`) THEN
18716   CONJ_TAC THEN
18717   W(MP_TAC o PART_MATCH (rand o rand) DIAMETER_SUMS o rand o snd) THEN
18718   ASM_SIMP_TAC[BOUNDED_CBALL; BOUNDED_CLOSURE] THEN
18719   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] REAL_LE_TRANS) THEN
18720   MATCH_MP_TAC DIAMETER_SUBSET THEN
18721   ASM_SIMP_TAC[BOUNDED_SUMS; BOUNDED_CBALL; BOUNDED_CLOSURE] THEN
18722   ONCE_REWRITE_TAC[MESON[HAUSDIST_CLOSURE]
18723    `hausdist(s:real^N->bool,t) = hausdist(closure s,closure t)`]
18724   THENL [ALL_TAC; ONCE_REWRITE_TAC[HAUSDIST_SYM]] THEN
18725   MATCH_MP_TAC HAUSDIST_COMPACT_SUMS THEN
18726   ASM_SIMP_TAC[COMPACT_CLOSURE; BOUNDED_CLOSURE; CLOSURE_EQ_EMPTY]);;
18727
18728 (* ------------------------------------------------------------------------- *)
18729 (* Isometries are embeddings, and even surjective in the compact case.       *)
18730 (* ------------------------------------------------------------------------- *)
18731
18732 let ISOMETRY_IMP_OPEN_MAP = prove
18733  (`!f:real^M->real^N s t u.
18734         IMAGE f s = t /\
18735         (!x y. x IN s /\ y IN s ==> dist(f x,f y) = dist(x,y)) /\
18736         open_in (subtopology euclidean s) u
18737         ==> open_in (subtopology euclidean t) (IMAGE f u)`,
18738   REWRITE_TAC[open_in; FORALL_IN_IMAGE] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
18739   CONJ_TAC THENL [ASM SET_TAC[]; X_GEN_TAC `x:real^M` THEN DISCH_TAC] THEN
18740   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^M`) THEN ASM_REWRITE_TAC[] THEN
18741   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN
18742   STRIP_TAC THEN ASM_REWRITE_TAC[IMP_CONJ] THEN
18743   EXPAND_TAC "t" THEN REWRITE_TAC[FORALL_IN_IMAGE] THEN
18744   RULE_ASSUM_TAC(REWRITE_RULE[SUBSET]) THEN
18745   ASM_SIMP_TAC[IN_IMAGE] THEN ASM_MESON_TAC[]);;
18746
18747 let ISOMETRY_IMP_EMBEDDING = prove
18748  (`!f:real^M->real^N s t.
18749         IMAGE f s = t /\ (!x y. x IN s /\ y IN s ==> dist(f x,f y) = dist(x,y))
18750         ==> ?g. homeomorphism (s,t) (f,g)`,
18751   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP THEN
18752   ASM_SIMP_TAC[ISOMETRY_ON_IMP_CONTINUOUS_ON] THEN
18753   CONJ_TAC THENL [ASM_MESON_TAC[DIST_EQ_0]; REPEAT STRIP_TAC] THEN
18754   MATCH_MP_TAC ISOMETRY_IMP_OPEN_MAP THEN ASM_MESON_TAC[]);;
18755
18756 let ISOMETRY_IMP_HOMEOMORPHISM_COMPACT = prove
18757  (`!f s:real^N->bool.
18758         compact s /\ IMAGE f s SUBSET s /\
18759         (!x y. x IN s /\ y IN s ==> dist(f x,f y) = dist(x,y))
18760         ==> ?g. homeomorphism (s,s) (f,g)`,
18761   REPEAT STRIP_TAC THEN
18762   SUBGOAL_THEN `IMAGE (f:real^N->real^N) s = s`
18763    (fun th -> ASM_MESON_TAC[th; ISOMETRY_IMP_EMBEDDING]) THEN
18764   FIRST_ASSUM(ASSUME_TAC o MATCH_MP ISOMETRY_ON_IMP_CONTINUOUS_ON) THEN
18765   ASM_REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN REWRITE_TAC[SUBSET] THEN
18766   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
18767   SUBGOAL_THEN `setdist({x},IMAGE (f:real^N->real^N) s) = &0` MP_TAC THENL
18768    [MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ ~(&0 < x) ==> x = &0`) THEN
18769     REWRITE_TAC[SETDIST_POS_LE] THEN DISCH_TAC THEN
18770     (X_CHOOSE_THEN `z:num->real^N` STRIP_ASSUME_TAC o
18771      prove_recursive_functions_exist num_RECURSION)
18772      `z 0 = (x:real^N) /\ !n. z(SUC n) = f(z n)` THEN
18773     SUBGOAL_THEN `!n. (z:num->real^N) n IN s` ASSUME_TAC THENL
18774      [INDUCT_TAC THEN ASM SET_TAC[]; ALL_TAC] THEN
18775     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [compact]) THEN
18776     DISCH_THEN(MP_TAC o SPEC `z:num->real^N`) THEN
18777     ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
18778     MAP_EVERY X_GEN_TAC [`l:real^N`; `r:num->num`] THEN STRIP_TAC THEN
18779     FIRST_ASSUM(MP_TAC o MATCH_MP CONVERGENT_IMP_CAUCHY) THEN
18780     REWRITE_TAC[cauchy] THEN
18781     DISCH_THEN(MP_TAC o SPEC `setdist({x},IMAGE (f:real^N->real^N) s)`) THEN
18782     ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `N:num`
18783      (MP_TAC o SPECL [`N:num`; `N + 1`])) THEN
18784     ANTS_TAC THENL [ARITH_TAC; REWRITE_TAC[REAL_NOT_LT; o_THM]] THEN
18785     SUBGOAL_THEN `(r:num->num) N < r (N + 1)` MP_TAC THENL
18786      [FIRST_X_ASSUM MATCH_MP_TAC THEN ARITH_TAC;
18787       REWRITE_TAC[LT_EXISTS; LEFT_IMP_EXISTS_THM]] THEN
18788     X_GEN_TAC `d:num` THEN DISCH_THEN SUBST1_TAC THEN
18789     TRANS_TAC REAL_LE_TRANS `dist(x:real^N,z(SUC d))` THEN CONJ_TAC THENL
18790      [MATCH_MP_TAC SETDIST_LE_DIST THEN ASM SET_TAC[]; ALL_TAC] THEN
18791     MATCH_MP_TAC REAL_EQ_IMP_LE THEN
18792     SPEC_TAC(`(r:num->num) N`,`m:num`) THEN
18793     INDUCT_TAC THEN ASM_MESON_TAC[ADD_CLAUSES];
18794     REWRITE_TAC[SETDIST_EQ_0_SING; IMAGE_EQ_EMPTY] THEN
18795     ASM_MESON_TAC[COMPACT_IMP_CLOSED; NOT_IN_EMPTY;
18796                   COMPACT_CONTINUOUS_IMAGE; CLOSURE_CLOSED]]);;
18797
18798 (* ------------------------------------------------------------------------- *)
18799 (* Urysohn's lemma (for real^N, where the proof is easy using distances).    *)
18800 (* ------------------------------------------------------------------------- *)
18801
18802 let URYSOHN_LOCAL_STRONG = prove
18803  (`!s t u a b.
18804         closed_in (subtopology euclidean u) s /\
18805         closed_in (subtopology euclidean u) t /\
18806         s INTER t = {} /\ ~(a = b)
18807         ==> ?f:real^N->real^M.
18808                f continuous_on u /\
18809                (!x. x IN u ==> f(x) IN segment[a,b]) /\
18810                (!x. x IN u ==> (f x = a <=> x IN s)) /\
18811                (!x. x IN u ==> (f x = b <=> x IN t))`,
18812   let lemma = prove
18813    (`!s t u a b.
18814           closed_in (subtopology euclidean u) s /\
18815           closed_in (subtopology euclidean u) t /\
18816           s INTER t = {} /\ ~(s = {}) /\ ~(t = {}) /\ ~(a = b)
18817           ==> ?f:real^N->real^M.
18818                  f continuous_on u /\
18819                  (!x. x IN u ==> f(x) IN segment[a,b]) /\
18820                  (!x. x IN u ==> (f x = a <=> x IN s)) /\
18821                  (!x. x IN u ==> (f x = b <=> x IN t))`,
18822     REPEAT STRIP_TAC THEN EXISTS_TAC
18823       `\x:real^N. a + setdist({x},s) / (setdist({x},s) + setdist({x},t)) %
18824                       (b - a:real^M)` THEN REWRITE_TAC[] THEN
18825     SUBGOAL_THEN
18826      `(!x:real^N. x IN u ==> (setdist({x},s) = &0 <=> x IN s)) /\
18827       (!x:real^N. x IN u ==> (setdist({x},t) = &0 <=> x IN t))`
18828     STRIP_ASSUME_TAC THENL
18829      [ASM_REWRITE_TAC[SETDIST_EQ_0_SING] THEN CONJ_TAC THENL
18830        [MP_TAC(ISPEC `s:real^N->bool` CLOSED_IN_CLOSED);
18831         MP_TAC(ISPEC `t:real^N->bool` CLOSED_IN_CLOSED)] THEN
18832       DISCH_THEN(MP_TAC o SPEC `u:real^N->bool`) THEN
18833       ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool`
18834        (CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC)) THEN
18835       ASM_MESON_TAC[CLOSURE_CLOSED; INTER_SUBSET; SUBSET_CLOSURE; SUBSET;
18836                     IN_INTER; CLOSURE_SUBSET];
18837       ALL_TAC] THEN
18838     SUBGOAL_THEN `!x:real^N. x IN u ==> &0 < setdist({x},s) + setdist({x},t)`
18839     ASSUME_TAC THENL
18840      [REPEAT STRIP_TAC THEN MATCH_MP_TAC(REAL_ARITH
18841         `&0 <= x /\ &0 <= y /\ ~(x = &0 /\ y = &0) ==> &0 < x + y`) THEN
18842       REWRITE_TAC[SETDIST_POS_LE] THEN ASM SET_TAC[];
18843       ALL_TAC] THEN
18844     REPEAT CONJ_TAC THENL
18845      [MATCH_MP_TAC CONTINUOUS_ON_ADD THEN REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
18846       REWRITE_TAC[real_div; GSYM VECTOR_MUL_ASSOC] THEN
18847       REPEAT(MATCH_MP_TAC CONTINUOUS_ON_MUL THEN CONJ_TAC) THEN
18848       REWRITE_TAC[CONTINUOUS_ON_CONST; o_DEF] THEN
18849       REWRITE_TAC[CONTINUOUS_ON_LIFT_SETDIST] THEN
18850       MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_INV) THEN
18851       ASM_SIMP_TAC[REAL_LT_IMP_NZ] THEN
18852       REWRITE_TAC[LIFT_ADD] THEN MATCH_MP_TAC CONTINUOUS_ON_ADD THEN
18853       REWRITE_TAC[CONTINUOUS_ON_LIFT_SETDIST];
18854       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
18855       REWRITE_TAC[segment; IN_ELIM_THM] THEN
18856       REWRITE_TAC[VECTOR_MUL_EQ_0; LEFT_OR_DISTRIB; VECTOR_ARITH
18857        `a + x % (b - a):real^N = (&1 - u) % a + u % b <=>
18858         (x - u) % (b - a) = vec 0`;
18859        EXISTS_OR_THM] THEN
18860       DISJ1_TAC THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
18861       REWRITE_TAC[REAL_SUB_0; UNWIND_THM1] THEN
18862       ASM_SIMP_TAC[REAL_LE_DIV; REAL_LE_ADD; SETDIST_POS_LE; REAL_LE_LDIV_EQ;
18863                    REAL_ARITH `a <= &1 * (a + b) <=> &0 <= b`];
18864       REWRITE_TAC[VECTOR_ARITH `a + x:real^N = a <=> x = vec 0`];
18865       REWRITE_TAC[VECTOR_ARITH `a + x % (b - a):real^N = b <=>
18866                                 (x - &1) % (b - a) = vec 0`]] THEN
18867     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
18868     ASM_SIMP_TAC[REAL_SUB_0; REAL_EQ_LDIV_EQ;
18869                  REAL_MUL_LZERO; REAL_MUL_LID] THEN
18870     REWRITE_TAC[REAL_ARITH `x:real = x + y <=> y = &0`] THEN
18871     ASM_REWRITE_TAC[]) in
18872   MATCH_MP_TAC(MESON[]
18873    `(!s t. P s t <=> P t s) /\
18874     (!s t. ~(s = {}) /\ ~(t = {}) ==> P s t) /\
18875     P {} {} /\ (!t. ~(t = {}) ==> P {} t)
18876     ==> !s t. P s t`) THEN
18877   REPEAT CONJ_TAC THENL
18878    [REPEAT GEN_TAC THEN
18879     GEN_REWRITE_TAC (RAND_CONV o BINDER_CONV) [SWAP_FORALL_THM] THEN
18880     REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
18881     REWRITE_TAC[SEGMENT_SYM; INTER_COMM; CONJ_ACI; EQ_SYM_EQ];
18882     SIMP_TAC[lemma];
18883     REPEAT STRIP_TAC THEN EXISTS_TAC `(\x. midpoint(a,b)):real^N->real^M` THEN
18884     ASM_SIMP_TAC[NOT_IN_EMPTY; CONTINUOUS_ON_CONST; MIDPOINT_IN_SEGMENT] THEN
18885     REWRITE_TAC[midpoint] THEN CONJ_TAC THEN GEN_TAC THEN DISCH_TAC THEN
18886     UNDISCH_TAC `~(a:real^M = b)` THEN REWRITE_TAC[CONTRAPOS_THM] THEN
18887     VECTOR_ARITH_TAC;
18888     REPEAT STRIP_TAC THEN ASM_CASES_TAC `t:real^N->bool = u` THENL
18889      [EXISTS_TAC `(\x. b):real^N->real^M` THEN
18890       ASM_REWRITE_TAC[NOT_IN_EMPTY; ENDS_IN_SEGMENT; IN_UNIV;
18891                       CONTINUOUS_ON_CONST];
18892       SUBGOAL_THEN `?c:real^N. c IN u /\ ~(c IN t)` STRIP_ASSUME_TAC THENL
18893        [REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET)) THEN
18894         REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN ASM SET_TAC[];
18895         ALL_TAC] THEN
18896       MP_TAC(ISPECL [`{c:real^N}`; `t:real^N->bool`; `u:real^N->bool`;
18897                      `midpoint(a,b):real^M`; `b:real^M`] lemma) THEN
18898       ASM_REWRITE_TAC[CLOSED_IN_SING; MIDPOINT_EQ_ENDPOINT] THEN
18899       ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
18900       MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[NOT_IN_EMPTY] THEN
18901       X_GEN_TAC `f:real^N->real^M` THEN STRIP_TAC THEN CONJ_TAC THENL
18902        [SUBGOAL_THEN
18903          `segment[midpoint(a,b):real^M,b] SUBSET segment[a,b]` MP_TAC
18904         THENL
18905          [REWRITE_TAC[SUBSET; IN_SEGMENT; midpoint] THEN GEN_TAC THEN
18906           DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
18907           EXISTS_TAC `(&1 + u) / &2` THEN ASM_REWRITE_TAC[] THEN
18908           REPEAT(CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
18909           VECTOR_ARITH_TAC;
18910           ASM SET_TAC[]];
18911         SUBGOAL_THEN `~(a IN segment[midpoint(a,b):real^M,b])` MP_TAC THENL
18912          [ALL_TAC; ASM_MESON_TAC[]] THEN
18913         DISCH_THEN(MP_TAC o CONJUNCT2 o MATCH_MP DIST_IN_CLOSED_SEGMENT) THEN
18914         REWRITE_TAC[DIST_MIDPOINT] THEN
18915         UNDISCH_TAC `~(a:real^M = b)` THEN NORM_ARITH_TAC]]]);;
18916
18917 let URYSOHN_LOCAL = prove
18918  (`!s t u a b.
18919         closed_in (subtopology euclidean u) s /\
18920         closed_in (subtopology euclidean u) t /\
18921         s INTER t = {}
18922         ==> ?f:real^N->real^M.
18923                f continuous_on u /\
18924                (!x. x IN u ==> f(x) IN segment[a,b]) /\
18925                (!x. x IN s ==> f x = a) /\
18926                (!x. x IN t ==> f x = b)`,
18927   REPEAT STRIP_TAC THEN ASM_CASES_TAC `a:real^M = b` THENL
18928    [EXISTS_TAC `(\x. b):real^N->real^M` THEN
18929     ASM_REWRITE_TAC[ENDS_IN_SEGMENT; CONTINUOUS_ON_CONST];
18930     MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`; `u:real^N->bool`;
18931                    `a:real^M`; `b:real^M`] URYSOHN_LOCAL_STRONG) THEN
18932     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN
18933     REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET)) THEN
18934     REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN SET_TAC[]]);;
18935
18936 let URYSOHN_STRONG = prove
18937  (`!s t a b.
18938         closed s /\ closed t /\ s INTER t = {} /\ ~(a = b)
18939         ==> ?f:real^N->real^M.
18940                f continuous_on (:real^N) /\ (!x. f(x) IN segment[a,b]) /\
18941                (!x. f x = a <=> x IN s) /\ (!x. f x = b <=> x IN t)`,
18942   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN] THEN
18943   ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_UNIV] THEN
18944   DISCH_THEN(MP_TAC o MATCH_MP URYSOHN_LOCAL_STRONG) THEN
18945   REWRITE_TAC[IN_UNIV]);;
18946
18947 let URYSOHN = prove
18948  (`!s t a b.
18949         closed s /\ closed t /\ s INTER t = {}
18950         ==> ?f:real^N->real^M.
18951                f continuous_on (:real^N) /\ (!x. f(x) IN segment[a,b]) /\
18952                (!x. x IN s ==> f x = a) /\ (!x. x IN t ==> f x = b)`,
18953   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN] THEN
18954   ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_UNIV] THEN DISCH_THEN
18955    (MP_TAC o ISPECL [`a:real^M`; `b:real^M`] o MATCH_MP URYSOHN_LOCAL) THEN
18956   REWRITE_TAC[IN_UNIV]);;
18957
18958 (* ------------------------------------------------------------------------- *)
18959 (* Countability of some relevant sets.                                       *)
18960 (* ------------------------------------------------------------------------- *)
18961
18962 let COUNTABLE_INTEGER = prove
18963  (`COUNTABLE integer`,
18964   MATCH_MP_TAC COUNTABLE_SUBSET THEN EXISTS_TAC
18965    `IMAGE (\n. (&n:real)) (:num) UNION IMAGE (\n. --(&n)) (:num)` THEN
18966   SIMP_TAC[COUNTABLE_IMAGE; COUNTABLE_UNION; NUM_COUNTABLE] THEN
18967   REWRITE_TAC[SUBSET; IN_UNION; IN_IMAGE; IN_UNIV] THEN
18968   REWRITE_TAC[IN; INTEGER_CASES]);;
18969
18970 let CARD_EQ_INTEGER = prove
18971  (`integer =_c (:num)`,
18972   REWRITE_TAC[GSYM CARD_LE_ANTISYM; GSYM COUNTABLE_ALT; COUNTABLE_INTEGER] THEN
18973   REWRITE_TAC[le_c] THEN EXISTS_TAC `real_of_num` THEN
18974   REWRITE_TAC[IN_UNIV; REAL_OF_NUM_EQ] THEN
18975   REWRITE_TAC[IN; INTEGER_CLOSED]);;
18976
18977 let COUNTABLE_RATIONAL = prove
18978  (`COUNTABLE rational`,
18979   MATCH_MP_TAC COUNTABLE_SUBSET THEN
18980   EXISTS_TAC `IMAGE (\(x,y). x / y) (integer CROSS integer)` THEN
18981   SIMP_TAC[COUNTABLE_IMAGE; COUNTABLE_CROSS; COUNTABLE_INTEGER] THEN
18982   REWRITE_TAC[SUBSET; IN_IMAGE; EXISTS_PAIR_THM; IN_CROSS] THEN
18983   REWRITE_TAC[rational; IN] THEN MESON_TAC[]);;
18984
18985 let CARD_EQ_RATIONAL = prove
18986  (`rational =_c (:num)`,
18987   REWRITE_TAC[GSYM CARD_LE_ANTISYM; GSYM COUNTABLE_ALT; COUNTABLE_RATIONAL] THEN
18988   REWRITE_TAC[le_c] THEN EXISTS_TAC `real_of_num` THEN
18989   REWRITE_TAC[IN_UNIV; REAL_OF_NUM_EQ] THEN
18990   REWRITE_TAC[IN; RATIONAL_CLOSED]);;
18991
18992 let COUNTABLE_INTEGER_COORDINATES = prove
18993  (`COUNTABLE { x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }`,
18994   MATCH_MP_TAC COUNTABLE_CART THEN
18995   REWRITE_TAC[SET_RULE `{x | P x} = P`; COUNTABLE_INTEGER]);;
18996
18997 let COUNTABLE_RATIONAL_COORDINATES = prove
18998  (`COUNTABLE { x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) }`,
18999   MATCH_MP_TAC COUNTABLE_CART THEN
19000   REWRITE_TAC[SET_RULE `{x | P x} = P`; COUNTABLE_RATIONAL]);;
19001
19002 (* ------------------------------------------------------------------------- *)
19003 (* Density of points with rational, or just dyadic rational, coordinates.    *)
19004 (* ------------------------------------------------------------------------- *)
19005
19006 let CLOSURE_DYADIC_RATIONALS = prove
19007  (`closure { inv(&2 pow n) % x |n,x|
19008              !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) } = (:real^N)`,
19009   REWRITE_TAC[EXTENSION; CLOSURE_APPROACHABLE; IN_UNIV; EXISTS_IN_GSPEC] THEN
19010   MAP_EVERY X_GEN_TAC [`x:real^N`; `e:real`] THEN DISCH_TAC THEN
19011   MP_TAC(SPECL [`inv(&2)`; `e / &(dimindex(:N))`] REAL_ARCH_POW_INV) THEN
19012   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1;
19013                REAL_POW_INV; REAL_LT_RDIV_EQ] THEN
19014   CONV_TAC REAL_RAT_REDUCE_CONV THEN MATCH_MP_TAC MONO_EXISTS THEN
19015   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
19016   EXISTS_TAC `(lambda i. floor(&2 pow n * (x:real^N)$i)):real^N` THEN
19017   ASM_SIMP_TAC[LAMBDA_BETA; FLOOR; dist; NORM_MUL] THEN
19018   MATCH_MP_TAC(MATCH_MP (REWRITE_RULE[IMP_CONJ] REAL_LET_TRANS)
19019    (SPEC_ALL NORM_LE_L1)) THEN
19020   SIMP_TAC[LAMBDA_BETA; VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT] THEN
19021   MATCH_MP_TAC REAL_LET_TRANS THEN
19022   EXISTS_TAC `&(dimindex(:N)) * inv(&2 pow n)` THEN ASM_REWRITE_TAC[] THEN
19023   GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o RAND_CONV) [GSYM CARD_NUMSEG_1] THEN
19024   MATCH_MP_TAC SUM_BOUND THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
19025   X_GEN_TAC `k:num` THEN STRIP_TAC THEN
19026   GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN
19027   SIMP_TAC[REAL_ABS_MUL; REAL_POW_EQ_0; REAL_OF_NUM_EQ; ARITH;
19028     REAL_FIELD `~(a = &0) ==> inv a * b - x = inv a * (b - a * x)`] THEN
19029   MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN
19030   REWRITE_TAC[REAL_LE_REFL; REAL_ABS_POW; REAL_ABS_INV; REAL_ABS_NUM] THEN
19031   MP_TAC(SPEC `&2 pow n * (x:real^N)$k` FLOOR) THEN REAL_ARITH_TAC);;
19032
19033 let CLOSURE_RATIONAL_COORDINATES = prove
19034  (`closure { x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) } =
19035    (:real^N)`,
19036   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
19037   EXISTS_TAC
19038    `closure { inv(&2 pow n) % x:real^N |n,x|
19039               !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }` THEN
19040
19041   CONJ_TAC THENL [ALL_TAC; REWRITE_TAC[CLOSURE_DYADIC_RATIONALS]] THEN
19042   MATCH_MP_TAC SUBSET_CLOSURE THEN
19043   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC; IN_ELIM_THM; VECTOR_MUL_COMPONENT] THEN
19044   ASM_SIMP_TAC[RATIONAL_CLOSED]);;
19045
19046 let CLOSURE_DYADIC_RATIONALS_IN_OPEN_SET = prove
19047  (`!s:real^N->bool.
19048         open s
19049         ==> closure(s INTER
19050                     { inv(&2 pow n) % x | n,x |
19051                       !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }) =
19052             closure s`,
19053   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_OPEN_INTER_SUPERSET THEN
19054   ASM_REWRITE_TAC[CLOSURE_DYADIC_RATIONALS; SUBSET_UNIV]);;
19055
19056 let CLOSURE_RATIONALS_IN_OPEN_SET = prove
19057  (`!s:real^N->bool.
19058         open s
19059         ==> closure(s INTER
19060                     { inv(&2 pow n) % x | n,x |
19061                       !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }) =
19062             closure s`,
19063   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_OPEN_INTER_SUPERSET THEN
19064   ASM_REWRITE_TAC[CLOSURE_DYADIC_RATIONALS; SUBSET_UNIV]);;
19065
19066 (* ------------------------------------------------------------------------- *)
19067 (* Various separability-type properties.                                     *)
19068 (* ------------------------------------------------------------------------- *)
19069
19070 let UNIV_SECOND_COUNTABLE = prove
19071  (`?b. COUNTABLE b /\ (!c. c IN b ==> open c) /\
19072        !s:real^N->bool. open s ==> ?u. u SUBSET b /\ s = UNIONS u`,
19073   EXISTS_TAC
19074    `IMAGE (\(v:real^N,q). ball(v,q))
19075           ({v | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(v$i)} CROSS
19076            rational)` THEN
19077   REPEAT CONJ_TAC THENL
19078    [MATCH_MP_TAC COUNTABLE_IMAGE THEN MATCH_MP_TAC COUNTABLE_CROSS THEN
19079     REWRITE_TAC[COUNTABLE_RATIONAL] THEN MATCH_MP_TAC COUNTABLE_CART THEN
19080     REWRITE_TAC[COUNTABLE_RATIONAL; SET_RULE `{x | P x} = P`];
19081     REWRITE_TAC[FORALL_IN_IMAGE; CROSS; FORALL_IN_GSPEC; OPEN_BALL];
19082     REPEAT STRIP_TAC THEN
19083     ASM_CASES_TAC `s:real^N->bool = {}` THENL
19084      [EXISTS_TAC `{}:(real^N->bool)->bool` THEN
19085       ASM_REWRITE_TAC[UNIONS_0; EMPTY_SUBSET];
19086       ALL_TAC] THEN
19087     EXISTS_TAC `{c | c IN IMAGE (\(v:real^N,q). ball(v,q))
19088           ({v | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(v$i)} CROSS
19089            rational) /\ c SUBSET s}` THEN
19090     CONJ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
19091     MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL [ALL_TAC; SET_TAC[]] THEN
19092     REWRITE_TAC[SUBSET; IN_UNIONS; IN_ELIM_THM] THEN
19093     REWRITE_TAC[GSYM CONJ_ASSOC; EXISTS_IN_IMAGE] THEN
19094     REWRITE_TAC[CROSS; EXISTS_PAIR_THM; EXISTS_IN_GSPEC] THEN
19095     REWRITE_TAC[IN_ELIM_PAIR_THM] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
19096     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
19097     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
19098     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; SUBSET; IN_BALL] THEN
19099     X_GEN_TAC `e:real` THEN STRIP_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN
19100     MP_TAC(REWRITE_RULE[EXTENSION; IN_UNIV] CLOSURE_RATIONAL_COORDINATES) THEN
19101     REWRITE_TAC[CLOSURE_APPROACHABLE] THEN
19102     DISCH_THEN(MP_TAC o SPECL [`x:real^N`; `e / &4`]) THEN
19103     ANTS_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[IN_ELIM_THM]] THEN
19104     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
19105     SUBGOAL_THEN `?x. rational x /\ e / &3 < x /\ x < e / &2`
19106      (X_CHOOSE_THEN `q:real` STRIP_ASSUME_TAC)
19107     THENL
19108      [MP_TAC(ISPECL [`&5 / &12 * e`; `e / &12`] RATIONAL_APPROXIMATION) THEN
19109       ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
19110       SIMP_TAC[] THEN REAL_ARITH_TAC;
19111       EXISTS_TAC `q:real` THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
19112        [ASM_REWRITE_TAC[IN];
19113         REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
19114         REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC;
19115         ASM_REAL_ARITH_TAC]]]);;
19116
19117 let UNIV_SECOND_COUNTABLE_SEQUENCE = prove
19118  (`?b:num->real^N->bool.
19119         (!m n. b m = b n <=> m = n) /\
19120         (!n. open(b n)) /\
19121         (!s. open s ==> ?k. s = UNIONS {b n | n IN k})`,
19122   X_CHOOSE_THEN `bb:(real^N->bool)->bool` STRIP_ASSUME_TAC
19123     UNIV_SECOND_COUNTABLE THEN
19124   MP_TAC(ISPEC `bb:(real^N->bool)->bool` COUNTABLE_AS_INJECTIVE_IMAGE) THEN
19125   ANTS_TAC THENL
19126    [ASM_REWRITE_TAC[INFINITE] THEN DISCH_TAC THEN
19127     SUBGOAL_THEN
19128      `INFINITE {ball(vec 0:real^N,inv(&n + &1)) | n IN (:num)}`
19129     MP_TAC THENL
19130      [REWRITE_TAC[SIMPLE_IMAGE] THEN MATCH_MP_TAC(REWRITE_RULE
19131        [RIGHT_IMP_FORALL_THM; IMP_IMP] INFINITE_IMAGE_INJ) THEN
19132       REWRITE_TAC[num_INFINITE] THEN MATCH_MP_TAC WLOG_LT THEN SIMP_TAC[] THEN
19133       CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
19134       MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN DISCH_TAC THEN
19135       REWRITE_TAC[EXTENSION] THEN
19136       DISCH_THEN(MP_TAC o SPEC `inv(&n + &1) % basis 1:real^N`) THEN
19137       REWRITE_TAC[IN_BALL; DIST_0; NORM_MUL; REAL_ABS_INV] THEN
19138       SIMP_TAC[NORM_BASIS; DIMINDEX_GE_1; LE_REFL; REAL_MUL_RID] THEN
19139       ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
19140       REWRITE_TAC[REAL_ARITH `abs(&n + &1) = &n + &1`; REAL_LT_REFL] THEN
19141       MATCH_MP_TAC REAL_LT_INV2 THEN
19142       REWRITE_TAC[REAL_OF_NUM_LT; REAL_OF_NUM_ADD] THEN ASM_ARITH_TAC;
19143       REWRITE_TAC[INFINITE; SIMPLE_IMAGE] THEN
19144       MATCH_MP_TAC FINITE_SUBSET THEN
19145       EXISTS_TAC `IMAGE UNIONS {u | u SUBSET bb} :(real^N->bool)->bool` THEN
19146       ASM_SIMP_TAC[FINITE_IMAGE; FINITE_POWERSET] THEN
19147       GEN_REWRITE_TAC I [SUBSET] THEN SIMP_TAC[FORALL_IN_IMAGE; IN_UNIV] THEN
19148       X_GEN_TAC `n:num` THEN REWRITE_TAC[IN_IMAGE; IN_ELIM_THM] THEN
19149       ASM_MESON_TAC[OPEN_BALL]];
19150     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:num->real^N->bool` THEN
19151     DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
19152     RULE_ASSUM_TAC(REWRITE_RULE[FORALL_IN_IMAGE; IN_UNIV]) THEN
19153     REPEAT(CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC]) THEN
19154     X_GEN_TAC `s:real^N->bool` THEN DISCH_TAC THEN
19155     FIRST_X_ASSUM(MP_TAC o SPEC `s:real^N->bool`) THEN
19156     ASM_REWRITE_TAC[SUBSET_IMAGE; LEFT_AND_EXISTS_THM; SUBSET_UNIV] THEN
19157     ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
19158     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[SIMPLE_IMAGE]]);;
19159
19160 let SUBSET_SECOND_COUNTABLE = prove
19161  (`!s:real^N->bool.
19162        ?b. COUNTABLE b /\
19163            (!c. c IN b ==> ~(c = {}) /\ open_in(subtopology euclidean s) c) /\
19164            !t. open_in(subtopology euclidean s) t
19165                ==> ?u. u SUBSET b /\ t = UNIONS u`,
19166   GEN_TAC THEN
19167   SUBGOAL_THEN
19168    `?b. COUNTABLE b /\
19169            (!c:real^N->bool. c IN b ==> open_in(subtopology euclidean s) c) /\
19170            !t. open_in(subtopology euclidean s) t
19171                ==> ?u. u SUBSET b /\ t = UNIONS u`
19172   STRIP_ASSUME_TAC THENL
19173    [X_CHOOSE_THEN `B:(real^N->bool)->bool` STRIP_ASSUME_TAC
19174       UNIV_SECOND_COUNTABLE THEN
19175     EXISTS_TAC `{s INTER c :real^N->bool | c IN B}` THEN
19176     ASM_SIMP_TAC[SIMPLE_IMAGE; COUNTABLE_IMAGE] THEN
19177     ASM_SIMP_TAC[FORALL_IN_IMAGE; EXISTS_SUBSET_IMAGE; OPEN_IN_OPEN_INTER] THEN
19178     REWRITE_TAC[OPEN_IN_OPEN] THEN
19179     X_GEN_TAC `t:real^N->bool` THEN
19180     DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
19181     FIRST_X_ASSUM SUBST_ALL_TAC THEN
19182     SUBGOAL_THEN `?b. b SUBSET B /\ u:real^N->bool = UNIONS b`
19183     STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
19184     FIRST_X_ASSUM SUBST_ALL_TAC THEN
19185     EXISTS_TAC `b:(real^N->bool)->bool` THEN ASM_REWRITE_TAC[] THEN
19186     REWRITE_TAC[INTER_UNIONS] THEN AP_TERM_TAC THEN SET_TAC[];
19187     EXISTS_TAC `b DELETE ({}:real^N->bool)` THEN
19188     ASM_SIMP_TAC[COUNTABLE_DELETE; IN_DELETE; SUBSET_DELETE] THEN
19189     X_GEN_TAC `t:real^N->bool` THEN DISCH_THEN(ANTE_RES_THEN MP_TAC) THEN
19190     DISCH_THEN(X_CHOOSE_THEN `u:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
19191     EXISTS_TAC `u DELETE ({}:real^N->bool)` THEN
19192     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
19193     FIRST_X_ASSUM SUBST_ALL_TAC THEN
19194     REWRITE_TAC[EXTENSION; IN_UNIONS] THEN
19195     GEN_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN
19196     REWRITE_TAC[IN_DELETE] THEN SET_TAC[]]);;
19197
19198 let SEPARABLE = prove
19199  (`!s:real^N->bool.
19200         ?t. COUNTABLE t /\ t SUBSET s /\ s SUBSET closure t`,
19201   MP_TAC SUBSET_SECOND_COUNTABLE THEN
19202   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `s:real^N->bool` THEN
19203   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_AND_EXISTS_THM] THEN
19204   DISCH_THEN(X_CHOOSE_THEN `B:(real^N->bool)->bool`
19205    (CONJUNCTS_THEN2 ASSUME_TAC (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC))) THEN
19206   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
19207   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
19208   X_GEN_TAC `f:(real^N->bool)->real^N` THEN DISCH_TAC THEN
19209   EXISTS_TAC `IMAGE (f:(real^N->bool)->real^N) B` THEN
19210   ASM_SIMP_TAC[COUNTABLE_IMAGE] THEN CONJ_TAC THENL
19211    [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
19212     X_GEN_TAC `c:real^N->bool` THEN DISCH_TAC THEN
19213     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN
19214     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
19215     FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_SUBSET) THEN
19216     REWRITE_TAC[TOPSPACE_SUBTOPOLOGY; TOPSPACE_EUCLIDEAN] THEN ASM SET_TAC[];
19217     REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE; EXISTS_IN_IMAGE] THEN
19218     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
19219     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
19220     UNDISCH_THEN
19221      `!t:real^N->bool.
19222         open_in (subtopology euclidean s) t
19223         ==> (?u. u SUBSET B /\ t = UNIONS u)`
19224      (MP_TAC o SPEC `s INTER ball(x:real^N,e)`) THEN
19225     SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_BALL; LEFT_IMP_EXISTS_THM] THEN
19226     X_GEN_TAC `b:(real^N->bool)->bool` THEN
19227     ASM_CASES_TAC `b:(real^N->bool)->bool = {}` THENL
19228      [MATCH_MP_TAC(TAUT `~b ==> a /\ b ==> c`) THEN
19229       ASM_REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY; UNIONS_0] THEN
19230       ASM_MESON_TAC[CENTRE_IN_BALL];
19231       STRIP_TAC THEN
19232       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
19233       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `c:real^N->bool` THEN
19234       DISCH_TAC THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
19235       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
19236       DISCH_THEN(MP_TAC o SPEC `(f:(real^N->bool)->real^N) c`) THEN
19237       ONCE_REWRITE_TAC[DIST_SYM] THEN REWRITE_TAC[IN_INTER; IN_BALL] THEN
19238       MATCH_MP_TAC(TAUT `a /\ c ==> (a /\ b <=> c) ==> b`) THEN
19239       CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
19240       FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN
19241       ANTS_TAC THENL [ASM SET_TAC[]; STRIP_TAC] THEN
19242       FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_SUBSET) THEN
19243       REWRITE_TAC[TOPSPACE_SUBTOPOLOGY; TOPSPACE_EUCLIDEAN] THEN
19244       ASM SET_TAC[]]]);;
19245
19246 let OPEN_SET_RATIONAL_COORDINATES = prove
19247  (`!s. open s /\ ~(s = {})
19248        ==> ?x:real^N. x IN s /\
19249                       !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)`,
19250   REPEAT STRIP_TAC THEN
19251   SUBGOAL_THEN
19252    `~(closure { x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) } INTER
19253     (s:real^N->bool) = {})`
19254   MP_TAC THENL
19255    [ASM_REWRITE_TAC[CLOSURE_RATIONAL_COORDINATES; INTER_UNIV]; ALL_TAC] THEN
19256   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; CLOSURE_APPROACHABLE; IN_INTER;
19257               IN_ELIM_THM] THEN
19258   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
19259   FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N` o REWRITE_RULE[open_def]) THEN
19260   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
19261
19262 let OPEN_COUNTABLE_UNION_OPEN_INTERVALS,
19263     OPEN_COUNTABLE_UNION_CLOSED_INTERVALS = (CONJ_PAIR o prove)
19264  (`(!s:real^N->bool.
19265         open s
19266         ==> ?D. COUNTABLE D /\
19267                 (!i. i IN D ==> i SUBSET s /\ ?a b. i = interval(a,b)) /\
19268                 UNIONS D = s) /\
19269    (!s:real^N->bool.
19270         open s
19271         ==> ?D. COUNTABLE D /\
19272                 (!i. i IN D ==> i SUBSET s /\ ?a b. i = interval[a,b]) /\
19273                 UNIONS D = s)`,
19274   REPEAT STRIP_TAC THENL
19275    [EXISTS_TAC
19276      `{i | i IN IMAGE (\(a:real^N,b). interval(a,b))
19277             ({x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)} CROSS
19278              {x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)}) /\
19279            i SUBSET s}`;
19280     EXISTS_TAC
19281      `{i | i IN IMAGE (\(a:real^N,b). interval[a,b])
19282             ({x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)} CROSS
19283              {x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)}) /\
19284            i SUBSET s}`] THEN
19285   (SIMP_TAC[COUNTABLE_RESTRICT; COUNTABLE_IMAGE; COUNTABLE_CROSS;
19286            COUNTABLE_RATIONAL_COORDINATES] THEN
19287    REWRITE_TAC[IN_ELIM_THM; UNIONS_GSPEC; IMP_CONJ; GSYM CONJ_ASSOC] THEN
19288    REWRITE_TAC[FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
19289    REWRITE_TAC[FORALL_PAIR_THM; EXISTS_PAIR_THM; IN_CROSS; IN_ELIM_THM] THEN
19290    CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
19291    REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
19292    X_GEN_TAC `x:real^N` THEN EQ_TAC THENL [SET_TAC[]; DISCH_TAC] THEN
19293    FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N` o REWRITE_RULE[open_def]) THEN
19294    ASM_REWRITE_TAC[] THEN
19295    DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
19296    SUBGOAL_THEN
19297     `!i. 1 <= i /\ i <= dimindex(:N)
19298          ==> ?a b. rational a /\ rational b /\
19299                    a < (x:real^N)$i /\ (x:real^N)$i < b /\
19300                    abs(b - a) < e / &(dimindex(:N))`
19301    MP_TAC THENL
19302     [REPEAT STRIP_TAC THEN MATCH_MP_TAC RATIONAL_APPROXIMATION_STRADDLE THEN
19303      ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1];
19304      REWRITE_TAC[LAMBDA_SKOLEM]] THEN
19305    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
19306    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN
19307    DISCH_TAC THEN ASM_SIMP_TAC[SUBSET; IN_INTERVAL; REAL_LT_IMP_LE] THEN
19308    X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
19309    REWRITE_TAC[dist] THEN MP_TAC(ISPEC `y - x:real^N` NORM_LE_L1) THEN
19310    MATCH_MP_TAC(REAL_ARITH `s < e ==> n <= s ==> n < e`) THEN
19311    MATCH_MP_TAC SUM_BOUND_LT_GEN THEN
19312    REWRITE_TAC[FINITE_NUMSEG; NUMSEG_EMPTY; NOT_LT; CARD_NUMSEG_1] THEN
19313    REWRITE_TAC[DIMINDEX_GE_1; IN_NUMSEG; VECTOR_SUB_COMPONENT] THEN
19314    X_GEN_TAC `k:num` THEN STRIP_TAC THEN
19315    REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `k:num`)) THEN ASM_REWRITE_TAC[] THEN
19316    ASM_REAL_ARITH_TAC));;
19317
19318 let LINDELOF = prove
19319  (`!f:(real^N->bool)->bool.
19320         (!s. s IN f ==> open s)
19321         ==> ?f'. f' SUBSET f /\ COUNTABLE f' /\ UNIONS f' = UNIONS f`,
19322   REPEAT STRIP_TAC THEN
19323   SUBGOAL_THEN
19324    `?b. COUNTABLE b /\
19325         (!c:real^N->bool. c IN b ==> open c) /\
19326         (!s. open s ==> ?u. u SUBSET b /\ s = UNIONS u)`
19327   STRIP_ASSUME_TAC THENL [ASM_REWRITE_TAC[UNIV_SECOND_COUNTABLE]; ALL_TAC] THEN
19328   ABBREV_TAC
19329    `d = {s:real^N->bool | s IN b /\ ?u. u IN f /\ s SUBSET u}` THEN
19330   SUBGOAL_THEN
19331    `COUNTABLE d /\ UNIONS f :real^N->bool = UNIONS d`
19332   STRIP_ASSUME_TAC THENL
19333    [EXPAND_TAC "d" THEN ASM_SIMP_TAC[COUNTABLE_RESTRICT] THEN ASM SET_TAC[];
19334     ALL_TAC] THEN
19335   SUBGOAL_THEN
19336    `!s:real^N->bool. ?u. s IN d ==> u IN f /\ s SUBSET u`
19337   MP_TAC THENL [EXPAND_TAC "d" THEN SET_TAC[]; ALL_TAC] THEN
19338   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
19339   X_GEN_TAC `g:(real^N->bool)->(real^N->bool)` THEN STRIP_TAC THEN
19340   EXISTS_TAC `IMAGE (g:(real^N->bool)->(real^N->bool)) d` THEN
19341   ASM_SIMP_TAC[COUNTABLE_IMAGE; UNIONS_IMAGE] THEN
19342   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN ASM SET_TAC[]);;
19343
19344 let LINDELOF_OPEN_IN = prove
19345  (`!f u:real^N->bool.
19346         (!s. s IN f ==> open_in (subtopology euclidean u) s)
19347         ==> ?f'. f' SUBSET f /\ COUNTABLE f' /\ UNIONS f' = UNIONS f`,
19348   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN] THEN
19349   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
19350   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
19351   X_GEN_TAC `v:(real^N->bool)->real^N->bool` THEN DISCH_TAC THEN
19352   MP_TAC(ISPEC `IMAGE (v:(real^N->bool)->real^N->bool) f` LINDELOF) THEN
19353   ASM_SIMP_TAC[FORALL_IN_IMAGE] THEN
19354   ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN
19355   REWRITE_TAC[EXISTS_COUNTABLE_SUBSET_IMAGE] THEN
19356   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f':(real^N->bool)->bool` THEN
19357   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
19358   SUBGOAL_THEN
19359   `!f'. f' SUBSET f ==> UNIONS f' = (u:real^N->bool) INTER UNIONS (IMAGE v f')`
19360   MP_TAC THENL [ASM SET_TAC[]; ASM_SIMP_TAC[SUBSET_REFL]]);;
19361
19362 let COUNTABLE_DISJOINT_OPEN_SUBSETS = prove
19363  (`!f. (!s:real^N->bool. s IN f ==> open s) /\ pairwise DISJOINT f
19364        ==> COUNTABLE f`,
19365   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP LINDELOF) THEN
19366   DISCH_THEN(X_CHOOSE_THEN `g:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
19367   MATCH_MP_TAC COUNTABLE_SUBSET THEN
19368   EXISTS_TAC `({}:real^N->bool) INSERT g` THEN
19369   ASM_REWRITE_TAC[COUNTABLE_INSERT] THEN
19370   REWRITE_TAC[SUBSET; IN_INSERT] THEN
19371   REPEAT(POP_ASSUM MP_TAC) THEN
19372   REWRITE_TAC[EXTENSION; SUBSET] THEN
19373   REWRITE_TAC[IN_UNIONS; pairwise] THEN
19374   REWRITE_TAC[SET_RULE `DISJOINT s t <=> !x. ~(x IN s /\ x IN t)`] THEN
19375   REWRITE_TAC[NOT_IN_EMPTY] THEN MESON_TAC[]);;
19376
19377 let CARD_EQ_OPEN_SETS = prove
19378  (`{s:real^N->bool | open s} =_c (:real)`,
19379   REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
19380    [X_CHOOSE_THEN `b:(real^N->bool)->bool` STRIP_ASSUME_TAC
19381       UNIV_SECOND_COUNTABLE THEN
19382     TRANS_TAC CARD_LE_TRANS `{s:(real^N->bool)->bool | s SUBSET b}` THEN
19383     CONJ_TAC THENL
19384      [REWRITE_TAC[LE_C] THEN
19385       EXISTS_TAC `UNIONS:((real^N->bool)->bool)->real^N->bool` THEN
19386       REWRITE_TAC[IN_ELIM_THM] THEN ASM_MESON_TAC[];
19387       TRANS_TAC CARD_LE_TRANS `{s | s SUBSET (:num)}` THEN CONJ_TAC THENL
19388        [MATCH_MP_TAC CARD_LE_POWERSET THEN ASM_REWRITE_TAC[GSYM COUNTABLE_ALT];
19389         REWRITE_TAC[SUBSET_UNIV; UNIV_GSPEC] THEN
19390         MESON_TAC[CARD_EQ_IMP_LE; CARD_EQ_SYM; CARD_EQ_REAL]]];
19391     REWRITE_TAC[le_c; IN_UNIV; IN_ELIM_THM] THEN
19392     EXISTS_TAC `\x. ball(x % basis 1:real^N,&1)` THEN
19393     REWRITE_TAC[OPEN_BALL; GSYM SUBSET_ANTISYM_EQ; SUBSET_BALLS] THEN
19394     CONV_TAC REAL_RAT_REDUCE_CONV THEN
19395     REWRITE_TAC[NORM_ARITH `dist(p:real^N,q) + &1 <= &1 <=> p = q`] THEN
19396     REWRITE_TAC[VECTOR_MUL_RCANCEL; EQ_SYM_EQ] THEN
19397     SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; ARITH]]);;
19398
19399 let CARD_EQ_CLOSED_SETS = prove
19400  (`{s:real^N->bool | closed s} =_c (:real)`,
19401   SUBGOAL_THEN
19402    `{s:real^N->bool | closed s} =
19403     IMAGE (\s. (:real^N) DIFF s) {s | open s}`
19404   SUBST1_TAC THENL
19405    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
19406     REWRITE_TAC[IN_ELIM_THM; GSYM OPEN_CLOSED] THEN
19407     MESON_TAC[SET_RULE `UNIV DIFF (UNIV DIFF s) = s`];
19408     TRANS_TAC CARD_EQ_TRANS `{s:real^N->bool | open s}` THEN
19409     REWRITE_TAC[CARD_EQ_OPEN_SETS] THEN
19410     MATCH_MP_TAC CARD_EQ_IMAGE THEN SET_TAC[]]);;
19411
19412 let CARD_EQ_COMPACT_SETS = prove
19413  (`{s:real^N->bool | compact s} =_c (:real)`,
19414   REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
19415    [TRANS_TAC CARD_LE_TRANS `{s:real^N->bool | closed s}` THEN
19416     SIMP_TAC[CARD_EQ_IMP_LE; CARD_EQ_CLOSED_SETS] THEN
19417     MATCH_MP_TAC CARD_LE_SUBSET THEN
19418     SIMP_TAC[SUBSET; IN_ELIM_THM; COMPACT_IMP_CLOSED];
19419     REWRITE_TAC[le_c; IN_UNIV; IN_ELIM_THM] THEN
19420     EXISTS_TAC `\x. {x % basis 1:real^N}` THEN
19421     REWRITE_TAC[COMPACT_SING; SET_RULE `{x} = {y} <=> x = y`] THEN
19422     SIMP_TAC[VECTOR_MUL_RCANCEL; BASIS_NONZERO; DIMINDEX_GE_1; ARITH]]);;
19423
19424 let COUNTABLE_NON_CONDENSATION_POINTS = prove
19425  (`!s:real^N->bool. COUNTABLE(s DIFF {x | x condensation_point_of s})`,
19426   REPEAT STRIP_TAC THEN REWRITE_TAC[condensation_point_of] THEN
19427   MATCH_MP_TAC COUNTABLE_SUBSET THEN
19428   X_CHOOSE_THEN `b:(real^N->bool)->bool` STRIP_ASSUME_TAC
19429    UNIV_SECOND_COUNTABLE THEN
19430   EXISTS_TAC
19431    `s INTER UNIONS { u:real^N->bool | u IN b /\ COUNTABLE(s INTER u)}` THEN
19432   REWRITE_TAC[INTER_UNIONS; IN_ELIM_THM] THEN CONJ_TAC THENL
19433    [MATCH_MP_TAC COUNTABLE_UNIONS THEN SIMP_TAC[FORALL_IN_GSPEC] THEN
19434     ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN
19435     ASM_SIMP_TAC[COUNTABLE_IMAGE; COUNTABLE_RESTRICT];
19436     SIMP_TAC[SUBSET; UNIONS_GSPEC; IN_ELIM_THM; IN_INTER; IN_DIFF] THEN
19437     X_GEN_TAC `x:real^N` THEN
19438     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
19439     REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; LEFT_IMP_EXISTS_THM] THEN
19440     X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
19441     SUBGOAL_THEN `?u:real^N->bool. x IN u /\ u IN b /\ u SUBSET t` MP_TAC THENL
19442      [ASM SET_TAC[]; MATCH_MP_TAC MONO_EXISTS] THEN
19443     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
19444     MATCH_MP_TAC COUNTABLE_SUBSET THEN
19445     EXISTS_TAC `s INTER t:real^N->bool` THEN ASM SET_TAC[]]);;
19446
19447 let CARD_EQ_CONDENSATION_POINTS_IN_SET = prove
19448  (`!s:real^N->bool.
19449      ~(COUNTABLE s) ==> {x | x IN s /\ x condensation_point_of s} =_c s`,
19450   REPEAT STRIP_TAC THEN
19451   TRANS_TAC CARD_EQ_TRANS
19452    `(s DIFF {x | x condensation_point_of s}) +_c
19453     {x:real^N | x IN s /\ x condensation_point_of s}` THEN
19454   CONJ_TAC THENL
19455    [ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN MATCH_MP_TAC CARD_ADD_ABSORB THEN
19456     MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
19457      [POP_ASSUM MP_TAC THEN REWRITE_TAC[INFINITE; CONTRAPOS_THM] THEN
19458       DISCH_THEN(MP_TAC o CONJ (SPEC `s:real^N->bool`
19459        COUNTABLE_NON_CONDENSATION_POINTS) o MATCH_MP FINITE_IMP_COUNTABLE) THEN
19460       REWRITE_TAC[GSYM COUNTABLE_UNION] THEN MATCH_MP_TAC EQ_IMP THEN
19461       AP_TERM_TAC THEN SET_TAC[];
19462       REWRITE_TAC[INFINITE_CARD_LE] THEN
19463       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] CARD_LE_TRANS) THEN
19464       REWRITE_TAC[GSYM COUNTABLE_ALT; COUNTABLE_NON_CONDENSATION_POINTS]];
19465     ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN
19466     W(MP_TAC o PART_MATCH (rand o rand) CARD_DISJOINT_UNION o rand o snd) THEN
19467     ANTS_TAC THENL [SET_TAC[]; ALL_TAC] THEN
19468     MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN SET_TAC[]]);;
19469
19470 let LIMPT_OF_CONDENSATION_POINTS,CONDENSATION_POINT_OF_CONDENSATION_POINTS =
19471   (CONJ_PAIR o prove)
19472  (`(!x:real^N s.
19473         x limit_point_of {y | y condensation_point_of s} <=>
19474         x condensation_point_of s) /\
19475    (!x:real^N s.
19476         x condensation_point_of {y | y condensation_point_of s} <=>
19477         x condensation_point_of s)`,
19478   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
19479    `(r ==> q) /\ (q ==> p) /\ (p ==> r)
19480     ==> (q <=> p) /\ (r <=> p)`) THEN
19481   REWRITE_TAC[CONDENSATION_POINT_IMP_LIMPT] THEN CONJ_TAC THENL
19482    [REWRITE_TAC[LIMPT_APPROACHABLE; CONDENSATION_POINT_INFINITE_BALL] THEN
19483     REPEAT GEN_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN DISCH_TAC THEN
19484     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
19485     FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
19486     DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
19487     FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
19488     ASM_REWRITE_TAC[REAL_HALF; CONTRAPOS_THM] THEN
19489     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] COUNTABLE_SUBSET) THEN
19490     SIMP_TAC[SUBSET; IN_INTER; IN_BALL] THEN
19491     REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC;
19492     ONCE_REWRITE_TAC[CONDENSATION_POINT_INFINITE_BALL] THEN DISCH_TAC THEN
19493     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
19494     FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
19495     ASM_REWRITE_TAC[REAL_HALF] THEN DISCH_THEN(MP_TAC o MATCH_MP
19496      (MESON[CARD_EQ_CONDENSATION_POINTS_IN_SET; CARD_COUNTABLE_CONG]
19497         `~COUNTABLE s
19498          ==> ~COUNTABLE {x | x IN s /\ x condensation_point_of s}`)) THEN
19499     REWRITE_TAC[UNCOUNTABLE_REAL; CONTRAPOS_THM] THEN
19500     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] COUNTABLE_SUBSET) THEN
19501     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_INTER] THEN X_GEN_TAC `y:real^N` THEN
19502     REPEAT STRIP_TAC THENL
19503      [ASM_MESON_TAC[CONDENSATION_POINT_OF_SUBSET; INTER_SUBSET]; ALL_TAC] THEN
19504     MATCH_MP_TAC(SET_RULE `!s. x IN s /\ s SUBSET t ==> x IN t`) THEN
19505     EXISTS_TAC `closure(s INTER ball(x:real^N,e / &2))` THEN CONJ_TAC THENL
19506      [REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM] THEN DISJ2_TAC THEN
19507       ASM_SIMP_TAC[CONDENSATION_POINT_IMP_LIMPT];
19508       TRANS_TAC SUBSET_TRANS `closure(ball(x:real^N,e / &2))` THEN
19509       SIMP_TAC[SUBSET_CLOSURE; INTER_SUBSET] THEN
19510       ASM_SIMP_TAC[CLOSURE_BALL; REAL_HALF; SUBSET_BALLS; DIST_REFL] THEN
19511       ASM_REAL_ARITH_TAC]]);;
19512
19513 let CLOSED_CONDENSATION_POINTS = prove
19514  (`!s:real^N->bool. closed {x | x condensation_point_of s}`,
19515   SIMP_TAC[CLOSED_LIMPT; LIMPT_OF_CONDENSATION_POINTS; IN_ELIM_THM]);;
19516
19517 let CANTOR_BENDIXSON = prove
19518  (`!s:real^N->bool.
19519         closed s
19520         ==> ?t u. closed t /\ (!x. x IN t ==> x limit_point_of t) /\
19521                   COUNTABLE u /\ s = t UNION u`,
19522   REPEAT STRIP_TAC THEN MAP_EVERY EXISTS_TAC
19523    [`{x:real^N | x condensation_point_of s}`;
19524     `s DIFF {x:real^N | x condensation_point_of s}`] THEN
19525   REWRITE_TAC[COUNTABLE_NON_CONDENSATION_POINTS; CLOSED_CONDENSATION_POINTS;
19526               IN_ELIM_THM; LIMPT_OF_CONDENSATION_POINTS] THEN
19527   REWRITE_TAC[SET_RULE `s = t UNION (s DIFF t) <=> t SUBSET s`] THEN
19528   RULE_ASSUM_TAC(REWRITE_RULE[CLOSED_LIMPT]) THEN
19529   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
19530   ASM_MESON_TAC[CONDENSATION_POINT_IMP_LIMPT]);;
19531
19532 (* ------------------------------------------------------------------------- *)
19533 (* A discrete set is countable, and an uncountable set has a limit point.    *)
19534 (* ------------------------------------------------------------------------- *)
19535
19536 let DISCRETE_IMP_COUNTABLE = prove
19537  (`!s:real^N->bool.
19538         (!x. x IN s ==> ?e. &0 < e /\
19539                             !y. y IN s /\ ~(y = x) ==> e <= norm(y - x))
19540         ==> COUNTABLE s`,
19541   REPEAT STRIP_TAC THEN
19542   SUBGOAL_THEN
19543    `!x. x IN s
19544         ==> ?q. (!i. 1 <= i /\ i <= dimindex(:N) ==> rational(q$i)) /\
19545                 !y:real^N. y IN s /\ ~(y = x) ==> norm(x - q) < norm(y - q)`
19546   MP_TAC THENL
19547    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
19548     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
19549     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
19550     MP_TAC(SET_RULE `x IN (:real^N)`) THEN
19551     REWRITE_TAC[GSYM CLOSURE_RATIONAL_COORDINATES] THEN
19552     REWRITE_TAC[CLOSURE_APPROACHABLE; IN_ELIM_THM] THEN
19553     DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
19554     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `q:real^N` THEN
19555     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
19556     X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
19557     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THEN
19558     REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC;
19559     POP_ASSUM(K ALL_TAC) THEN
19560     REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
19561     X_GEN_TAC `q:real^N->real^N` THEN DISCH_TAC THEN
19562     MP_TAC(ISPECL
19563      [`s:real^N->bool`;
19564       `{ x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) }`;
19565       `(:num)`] CARD_LE_TRANS) THEN
19566     REWRITE_TAC[COUNTABLE; ge_c] THEN DISCH_THEN MATCH_MP_TAC THEN
19567     SIMP_TAC[REWRITE_RULE[COUNTABLE; ge_c] COUNTABLE_RATIONAL_COORDINATES] THEN
19568     REWRITE_TAC[le_c] THEN EXISTS_TAC `q:real^N->real^N` THEN
19569     ASM_SIMP_TAC[IN_ELIM_THM] THEN ASM_MESON_TAC[REAL_LT_ANTISYM]]);;
19570
19571 let UNCOUNTABLE_CONTAINS_LIMIT_POINT = prove
19572  (`!s. ~(COUNTABLE s) ==> ?x. x IN s /\ x limit_point_of s`,
19573   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP
19574    (ONCE_REWRITE_RULE[GSYM CONTRAPOS_THM] DISCRETE_IMP_COUNTABLE)) THEN
19575   REWRITE_TAC[LIMPT_APPROACHABLE; GSYM REAL_NOT_LT; dist] THEN
19576   MESON_TAC[]);;
19577
19578 (* ------------------------------------------------------------------------- *)
19579 (* The Brouwer reduction theorem.                                            *)
19580 (* ------------------------------------------------------------------------- *)
19581
19582 let BROUWER_REDUCTION_THEOREM_GEN = prove
19583  (`!P s:real^N->bool.
19584         (!f. (!n. closed(f n) /\ P(f n)) /\ (!n. f(SUC n) SUBSET f(n))
19585               ==> P(INTERS {f n | n IN (:num)})) /\
19586         closed s /\ P s
19587         ==> ?t. t SUBSET s /\ closed t /\ P t /\
19588                 (!u. u SUBSET s /\ closed u /\ P u ==> ~(u PSUBSET t))`,
19589   REPEAT STRIP_TAC THEN
19590   SUBGOAL_THEN
19591    `?b:num->real^N->bool.
19592         (!m n. b m = b n <=> m = n) /\
19593         (!n. open (b n)) /\
19594         (!s. open s ==> (?k. s = UNIONS {b n | n IN k}))`
19595   STRIP_ASSUME_TAC THENL
19596    [REWRITE_TAC[UNIV_SECOND_COUNTABLE_SEQUENCE]; ALL_TAC] THEN
19597   X_CHOOSE_THEN `a:num->real^N->bool` MP_TAC
19598    (prove_recursive_functions_exist num_RECURSION
19599    `a 0 = (s:real^N->bool) /\
19600     (!n. a(SUC n) =
19601          if ?u. u SUBSET a(n) /\ closed u /\ P u /\ u INTER (b n) = {}
19602          then @u. u SUBSET a(n) /\ closed u /\ P u /\ u INTER (b n) = {}
19603          else a(n))`) THEN
19604   DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "base") (LABEL_TAC "step")) THEN
19605   EXISTS_TAC `INTERS {a n :real^N->bool | n IN (:num)}` THEN
19606   SUBGOAL_THEN `!n. (a:num->real^N->bool)(SUC n) SUBSET a(n)` ASSUME_TAC THENL
19607    [GEN_TAC THEN ASM_REWRITE_TAC[] THEN
19608     COND_CASES_TAC THEN REWRITE_TAC[SUBSET_REFL] THEN
19609     FIRST_X_ASSUM(MP_TAC o SELECT_RULE) THEN MESON_TAC[];
19610     ALL_TAC] THEN
19611   SUBGOAL_THEN `!n. (a:num->real^N->bool) n SUBSET s` ASSUME_TAC THENL
19612    [INDUCT_TAC THEN ASM_MESON_TAC[SUBSET_REFL; SUBSET_TRANS]; ALL_TAC] THEN
19613   SUBGOAL_THEN `!n. closed((a:num->real^N->bool) n) /\ P(a n)` ASSUME_TAC THENL
19614    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN
19615     COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
19616     FIRST_X_ASSUM(MP_TAC o SELECT_RULE) THEN MESON_TAC[];
19617     ALL_TAC] THEN
19618   REPEAT CONJ_TAC THENL
19619    [ASM SET_TAC[];
19620     MATCH_MP_TAC CLOSED_INTERS THEN
19621     ASM_REWRITE_TAC[FORALL_IN_GSPEC; IN_UNIV] THEN SET_TAC[];
19622     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[];
19623     X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
19624     REWRITE_TAC[PSUBSET_ALT] THEN
19625     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
19626     REWRITE_TAC[INTERS_GSPEC; EXISTS_IN_GSPEC; IN_UNIV] THEN
19627     DISCH_THEN(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
19628     SUBGOAL_THEN
19629      `?n. x IN (b:num->real^N->bool)(n) /\ t INTER b n = {}`
19630     STRIP_ASSUME_TAC THENL
19631      [MP_TAC(ISPEC `(:real^N) DIFF t` OPEN_CONTAINS_BALL) THEN
19632       ASM_REWRITE_TAC[GSYM closed] THEN
19633       DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
19634       ASM_REWRITE_TAC[IN_DIFF; IN_UNIV; LEFT_IMP_EXISTS_THM] THEN
19635       REWRITE_TAC[SET_RULE `s SUBSET UNIV DIFF t <=> t INTER s = {}`] THEN
19636       X_GEN_TAC `e:real` THEN
19637       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
19638       MP_TAC(ISPECL [`x:real^N`; `e:real`] CENTRE_IN_BALL) THEN
19639       FIRST_X_ASSUM(MP_TAC o SPEC `ball(x:real^N,e)`) THEN
19640       ASM_REWRITE_TAC[OPEN_BALL; LEFT_IMP_EXISTS_THM] THEN
19641       X_GEN_TAC `k:num->bool` THEN DISCH_THEN SUBST1_TAC THEN
19642       REWRITE_TAC[IN_UNIONS; INTER_UNIONS; EMPTY_UNIONS; FORALL_IN_GSPEC] THEN
19643       SET_TAC[];
19644       REMOVE_THEN "step" (MP_TAC o SPEC `n:num`) THEN
19645       COND_CASES_TAC THENL
19646        [DISCH_THEN(ASSUME_TAC o SYM) THEN
19647         FIRST_X_ASSUM(MP_TAC o SELECT_RULE) THEN ASM_REWRITE_TAC[] THEN
19648         ASM SET_TAC[];
19649         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
19650         DISCH_THEN(MP_TAC o SPEC `t:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
19651         ASM SET_TAC[]]]]);;
19652
19653 let BROUWER_REDUCTION_THEOREM = prove
19654  (`!P s:real^N->bool.
19655         (!f. (!n. compact(f n) /\ ~(f n = {}) /\ P(f n)) /\
19656              (!n. f(SUC n) SUBSET f(n))
19657              ==> P(INTERS {f n | n IN (:num)})) /\
19658         compact s /\ ~(s = {}) /\ P s
19659         ==> ?t. t SUBSET s /\ compact t /\ ~(t = {}) /\ P t /\
19660                 (!u. u SUBSET s /\ closed u /\ ~(u = {}) /\ P u
19661                      ==> ~(u PSUBSET t))`,
19662   REPEAT STRIP_TAC THEN
19663   MP_TAC(ISPECL [`\t:real^N->bool. ~(t = {}) /\ t SUBSET s /\ P t`;
19664                  `s:real^N->bool`]
19665         BROUWER_REDUCTION_THEOREM_GEN) THEN
19666   ASM_SIMP_TAC[COMPACT_IMP_CLOSED; SUBSET_REFL] THEN ANTS_TAC THENL
19667    [GEN_TAC THEN STRIP_TAC THEN
19668     SUBGOAL_THEN `!n. compact((f:num->real^N->bool) n)` ASSUME_TAC THENL
19669      [ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_SUBSET]; ALL_TAC] THEN
19670     REPEAT CONJ_TAC THENL
19671      [MATCH_MP_TAC COMPACT_NEST THEN ASM_REWRITE_TAC[] THEN
19672       MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN ASM_SIMP_TAC[] THEN SET_TAC[];
19673       ASM SET_TAC[];
19674       FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[]];
19675     MATCH_MP_TAC MONO_EXISTS THEN ASM_SIMP_TAC[] THEN
19676     ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_SUBSET]]);;
19677
19678 (* ------------------------------------------------------------------------- *)
19679 (* The Arzela-Ascoli theorem.                                                *)
19680 (* ------------------------------------------------------------------------- *)
19681
19682 let SUBSEQUENCE_DIAGONALIZATION_LEMMA = prove
19683  (`!P:num->(num->A)->bool.
19684     (!i r:num->A. ?k. (!m n. m < n ==> k m < k n) /\ P i (r o k)) /\
19685     (!i r:num->A k1 k2 N.
19686         P i (r o k1) /\ (!j. N <= j ==> ?j'. j <= j' /\ k2 j = k1 j')
19687         ==> P i (r o k2))
19688     ==> !r:num->A. ?k. (!m n. m < n ==> k m < k n) /\ (!i. P i (r o k))`,
19689   REPEAT GEN_TAC THEN
19690   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
19691   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [SKOLEM_THM] THEN
19692   REWRITE_TAC[FORALL_AND_THM; TAUT
19693    `(p ==> q /\ r) <=> (p ==> q) /\ (p ==> r)`] THEN
19694   DISCH_THEN(X_CHOOSE_THEN
19695    `kk:num->(num->A)->num->num` STRIP_ASSUME_TAC) THEN
19696   X_GEN_TAC `r:num->A` THEN
19697   (STRIP_ASSUME_TAC o prove_recursive_functions_exist num_RECURSION)
19698     `(rr 0 = (kk:num->(num->A)->num->num) 0 r) /\
19699      (!n. rr(SUC n) = rr n o kk (SUC n) (r o rr n))` THEN
19700   EXISTS_TAC `\n. (rr:num->num->num) n n` THEN REWRITE_TAC[ETA_AX] THEN
19701   SUBGOAL_THEN
19702    `(!i. (!m n. m < n ==> (rr:num->num->num) i m < rr i n)) /\
19703     (!i. (P:num->(num->A)->bool) i (r o rr i))`
19704   STRIP_ASSUME_TAC THENL
19705    [REWRITE_TAC[AND_FORALL_THM] THEN
19706     INDUCT_TAC THEN ASM_REWRITE_TAC[o_ASSOC] THEN
19707     REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[];
19708     ALL_TAC] THEN
19709   SUBGOAL_THEN `!i j n. i <= j ==> (rr:num->num->num) i n <= rr j n`
19710   ASSUME_TAC THENL
19711    [REPEAT GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [LE_EXISTS] THEN
19712     SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN SPEC_TAC(`j:num`,`j:num`) THEN
19713     ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN SIMP_TAC[FORALL_UNWIND_THM2] THEN
19714     INDUCT_TAC THEN REWRITE_TAC[ADD_CLAUSES; LE_REFL] THEN
19715     ASM_REWRITE_TAC[] THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP
19716      (REWRITE_RULE[IMP_CONJ] LE_TRANS)) THEN REWRITE_TAC[o_THM] THEN
19717     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP
19718      (MESON[LE_LT]
19719        `!f:num->num.
19720         (!m n. m < n ==> f m < f n) ==> (!m n. m <= n ==> f m <= f n)`) o
19721        SPEC `i + d:num`) THEN
19722     SPEC_TAC(`n:num`,`n:num`) THEN MATCH_MP_TAC MONOTONE_BIGGER THEN
19723     ASM_SIMP_TAC[];
19724     ALL_TAC] THEN
19725   CONJ_TAC THENL
19726    [MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN DISCH_TAC THEN
19727     MATCH_MP_TAC LET_TRANS THEN
19728     EXISTS_TAC `(rr:num->num->num) n m` THEN
19729     ASM_MESON_TAC[LT_IMP_LE];
19730     ALL_TAC] THEN
19731   SUBGOAL_THEN
19732    `!m n i. n <= m ==> ?j. i <= j /\ (rr:num->num->num) m i = rr n j`
19733   ASSUME_TAC THENL
19734    [ALL_TAC;
19735     X_GEN_TAC `i:num` THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
19736     EXISTS_TAC `(rr:num->num->num) i` THEN ASM_REWRITE_TAC[] THEN
19737     EXISTS_TAC `i:num` THEN ASM_MESON_TAC[]] THEN
19738   SUBGOAL_THEN
19739    `!p d i. ?j. i <= j /\ (rr:num->num->num) (p + d) i = rr p j`
19740    (fun th -> MESON_TAC[LE_EXISTS; th]) THEN
19741   X_GEN_TAC `p:num` THEN  MATCH_MP_TAC num_INDUCTION THEN
19742   ASM_REWRITE_TAC[ADD_CLAUSES] THEN CONJ_TAC THENL
19743    [MESON_TAC[LE_REFL]; ALL_TAC] THEN
19744   X_GEN_TAC `d:num` THEN DISCH_THEN(LABEL_TAC "+") THEN
19745   X_GEN_TAC `i:num` THEN ASM_REWRITE_TAC[o_THM] THEN
19746   REMOVE_THEN "+" (MP_TAC o SPEC
19747    `(kk:num->(num->A)->num->num) (SUC(p + d))
19748         ((r:num->A) o (rr:num->num->num) (p + d)) i`) THEN
19749   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `j:num` THEN
19750   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
19751   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LE_TRANS) THEN
19752   SPEC_TAC(`i:num`,`i:num`) THEN MATCH_MP_TAC MONOTONE_BIGGER THEN
19753   ASM_REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[]);;
19754
19755 let FUNCTION_CONVERGENT_SUBSEQUENCE = prove
19756  (`!f:num->real^M->real^N s M.
19757         COUNTABLE s /\ (!n x. x IN s ==> norm(f n x) <= M)
19758         ==> ?k. (!m n:num. m < n ==> k m < k n) /\
19759                 !x. x IN s ==> ?l. ((\n. f (k n) x) --> l) sequentially`,
19760   REPEAT STRIP_TAC THEN
19761   ASM_CASES_TAC `s:real^M->bool = {}` THENL
19762    [EXISTS_TAC `\n:num. n` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY];
19763     ALL_TAC] THEN
19764   MP_TAC(ISPEC `s:real^M->bool` COUNTABLE_AS_IMAGE) THEN
19765   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
19766   X_GEN_TAC `X:num->real^M` THEN DISCH_THEN SUBST_ALL_TAC THEN
19767   MP_TAC(ISPEC
19768     `\i r. ?l. ((\n. ((f:num->real^M->real^N) o (r:num->num)) n
19769                      ((X:num->real^M) i)) --> l) sequentially`
19770    SUBSEQUENCE_DIAGONALIZATION_LEMMA) THEN
19771   REWRITE_TAC[FORALL_IN_IMAGE; o_THM; IN_UNIV] THEN
19772   ANTS_TAC THENL [ALL_TAC; DISCH_THEN MATCH_ACCEPT_TAC] THEN CONJ_TAC THENL
19773    [RULE_ASSUM_TAC(REWRITE_RULE[FORALL_IN_IMAGE; IN_UNIV]) THEN
19774     MAP_EVERY X_GEN_TAC [`i:num`; `r:num->num`] THEN
19775     MP_TAC(ISPEC `cball(vec 0:real^N,M)` compact) THEN
19776     REWRITE_TAC[COMPACT_CBALL] THEN DISCH_THEN(MP_TAC o SPEC
19777      `\n. (f:num->real^M->real^N) ((r:num->num) n) (X(i:num))`) THEN
19778     ASM_REWRITE_TAC[IN_CBALL_0; o_DEF] THEN MESON_TAC[];
19779     REPEAT GEN_TAC THEN REWRITE_TAC[LIM_SEQUENTIALLY; GE] THEN
19780     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
19781     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
19782     MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
19783     MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
19784     ASM_MESON_TAC[LE_TRANS; ARITH_RULE `MAX a b <= c <=> a <= c /\ b <= c`]]);;
19785
19786 let ARZELA_ASCOLI = prove
19787  (`!f:num->real^M->real^N s M.
19788         compact s /\
19789         (!n x. x IN s ==> norm(f n x) <= M) /\
19790         (!x e. x IN s /\ &0 < e
19791                ==> ?d. &0 < d /\
19792                        !n y. y IN s /\ norm(x - y) < d
19793                              ==> norm(f n x - f n y) < e)
19794         ==> ?g. g continuous_on s /\
19795                 ?r. (!m n:num. m < n ==> r m < r n) /\
19796                     !e. &0 < e
19797                         ==> ?N. !n x. n >= N /\ x IN s
19798                                       ==> norm(f(r n) x - g x) < e`,
19799   REPEAT STRIP_TAC THEN REWRITE_TAC[GE] THEN
19800   MATCH_MP_TAC(MESON[]
19801    `(!k g. V k g ==> N g) /\ (?k. M k /\ ?g. V k g)
19802     ==> ?g. N g /\ ?k. M k /\ V k g`) THEN
19803   CONJ_TAC THENL
19804    [MAP_EVERY X_GEN_TAC [`k:num->num`; `g:real^M->real^N`] THEN
19805     STRIP_TAC THEN MATCH_MP_TAC(ISPEC `sequentially`
19806       CONTINUOUS_UNIFORM_LIMIT) THEN
19807     EXISTS_TAC `(f:num->real^M->real^N) o (k:num->num)` THEN
19808     ASM_SIMP_TAC[EVENTUALLY_SEQUENTIALLY; o_THM; TRIVIAL_LIMIT_SEQUENTIALLY;
19809                  RIGHT_IMP_FORALL_THM; IMP_IMP] THEN
19810     EXISTS_TAC `0` THEN REWRITE_TAC[continuous_on; dist] THEN
19811     ASM_MESON_TAC[NORM_SUB];
19812     ALL_TAC] THEN
19813   MP_TAC(ISPECL
19814    [`IMAGE (f:num->real^M->real^N) (:num)`;
19815     `s:real^M->bool`]
19816    COMPACT_UNIFORMLY_EQUICONTINUOUS) THEN
19817   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE; IN_UNIV] THEN
19818   ANTS_TAC THENL
19819    [REWRITE_TAC[dist] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN ASM_MESON_TAC[];
19820     ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(K ALL_TAC o SPEC `x:real^M`)] THEN
19821   REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN
19822   REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC; dist] THEN
19823   DISCH_THEN(ASSUME_TAC o ONCE_REWRITE_RULE[NORM_SUB]) THEN
19824   REWRITE_TAC[GSYM dist; UNIFORMLY_CONVERGENT_EQ_CAUCHY] THEN
19825   X_CHOOSE_THEN `r:real^M->bool` STRIP_ASSUME_TAC
19826    (ISPEC `s:real^M->bool` SEPARABLE) THEN
19827   MP_TAC(ISPECL [`f:num->real^M->real^N`; `r:real^M->bool`; `M:real`]
19828         FUNCTION_CONVERGENT_SUBSEQUENCE) THEN
19829   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
19830   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `k:num->num` THEN
19831   REWRITE_TAC[CONVERGENT_EQ_CAUCHY; cauchy] THEN
19832   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "*")) THEN
19833   ASM_REWRITE_TAC[] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
19834   FIRST_X_ASSUM(MP_TAC o SPEC `e / &3`) THEN
19835   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
19836   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
19837   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL]) THEN
19838   DISCH_THEN(MP_TAC o SPEC `IMAGE (\x:real^M. ball(x,d)) r`) THEN
19839   REWRITE_TAC[FORALL_IN_IMAGE; OPEN_BALL] THEN
19840   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`] THEN
19841   REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE] THEN ANTS_TAC THENL
19842    [MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `closure r:real^M->bool` THEN
19843     ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE] THEN
19844     X_GEN_TAC `x:real^M` THEN DISCH_THEN(MP_TAC o SPEC `d:real`) THEN
19845     ASM_REWRITE_TAC[UNIONS_IMAGE; IN_ELIM_THM; IN_BALL];
19846     DISCH_THEN(X_CHOOSE_THEN `t:real^M->bool` STRIP_ASSUME_TAC)] THEN
19847   REMOVE_THEN "*" MP_TAC THEN REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN
19848   GEN_REWRITE_TAC LAND_CONV [SWAP_FORALL_THM] THEN
19849   DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
19850   ASM_REWRITE_TAC[REAL_ARITH `&0 < e / &3 <=> &0 < e`] THEN
19851   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
19852   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
19853   X_GEN_TAC `M:real^M->num` THEN DISCH_THEN(LABEL_TAC "*") THEN
19854   MP_TAC(ISPECL [`M:real^M->num`; `t:real^M->bool`]
19855     UPPER_BOUND_FINITE_SET) THEN
19856   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
19857   DISCH_TAC THEN
19858   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`; `x:real^M`] THEN STRIP_TAC THEN
19859   UNDISCH_TAC `s SUBSET UNIONS (IMAGE (\x:real^M. ball (x,d)) t)` THEN
19860   REWRITE_TAC[SUBSET; UNIONS_IMAGE; IN_ELIM_THM] THEN
19861   DISCH_THEN(MP_TAC o SPEC `x:real^M`) THEN
19862   ASM_REWRITE_TAC[IN_BALL; LEFT_IMP_EXISTS_THM; dist] THEN
19863   X_GEN_TAC `y:real^M` THEN STRIP_TAC THEN
19864   MATCH_MP_TAC(NORM_ARITH
19865    `norm(f (k(m:num)) y - f (k m) x) < e / &3 /\
19866     norm(f (k n) y - f (k n) x) < e / &3 /\
19867     norm(f (k m) y - f (k n) y) < e / &3
19868     ==> norm(f (k m) x - f (k n) x :real^M) < e`) THEN
19869   ASM_SIMP_TAC[] THEN REMOVE_THEN "*" (MP_TAC o SPEC `y:real^M`) THEN
19870   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
19871   DISCH_THEN(MP_TAC o SPECL [`m:num`; `n:num`]) THEN
19872   ASM_REWRITE_TAC[dist; GE] THEN ASM_MESON_TAC[SUBSET; LE_TRANS]);;
19873
19874 (* ------------------------------------------------------------------------- *)
19875 (* Two forms of the Baire propery of dense sets.                             *)
19876 (* ------------------------------------------------------------------------- *)
19877
19878 let BAIRE = prove
19879  (`!g s:real^N->bool.
19880         closed s /\ COUNTABLE g /\
19881         (!t. t IN g
19882              ==> open_in (subtopology euclidean s) t /\ s SUBSET closure t)
19883         ==> s SUBSET closure(INTERS g)`,
19884   REPEAT STRIP_TAC THEN ASM_CASES_TAC `g:(real^N->bool)->bool = {}` THEN
19885   ASM_REWRITE_TAC[INTERS_0; CLOSURE_UNIV; SUBSET_UNIV] THEN
19886   MP_TAC(ISPEC `g:(real^N->bool)->bool` COUNTABLE_AS_IMAGE) THEN
19887   ASM_REWRITE_TAC[] THEN
19888   MAP_EVERY (C UNDISCH_THEN (K ALL_TAC))
19889    [`COUNTABLE(g:(real^N->bool)->bool)`;
19890     `~(g:(real^N->bool)->bool = {})`] THEN
19891   DISCH_THEN(X_CHOOSE_THEN `g:num->real^N->bool` SUBST_ALL_TAC) THEN
19892   RULE_ASSUM_TAC(REWRITE_RULE[FORALL_IN_IMAGE; IN_UNIV]) THEN
19893   REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE] THEN
19894   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
19895   X_GEN_TAC `e:real` THEN DISCH_TAC THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
19896   REWRITE_TAC[GSYM IN_BALL; GSYM IN_INTER; MEMBER_NOT_EMPTY] THEN
19897   SUBGOAL_THEN
19898    `?t:num->real^N->bool.
19899         (!n. open_in (subtopology euclidean s) (t n) /\ ~(t n = {}) /\
19900              s INTER closure(t n) SUBSET g n /\
19901              closure(t n) SUBSET ball(x,e)) /\
19902         (!n. t(SUC n) SUBSET t n)`
19903   STRIP_ASSUME_TAC THENL
19904    [SUBGOAL_THEN
19905      `!u n. open_in (subtopology euclidean s) u /\ ~(u = {}) /\
19906             closure u SUBSET ball(x,e)
19907             ==> ?y. open_in (subtopology euclidean s) y /\
19908                     ~(y = {}) /\
19909                     s INTER closure y SUBSET (g:num->real^N->bool) n /\
19910                     closure y SUBSET ball(x,e) /\
19911                     y SUBSET u`
19912     ASSUME_TAC THENL
19913      [MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `n:num`] THEN STRIP_TAC THEN
19914       SUBGOAL_THEN `?y:real^N. y IN u /\ y IN g(n:num)` STRIP_ASSUME_TAC THENL
19915        [FIRST_X_ASSUM(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC o SPEC `n:num`) THEN
19916         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
19917         FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
19918         DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
19919         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [open_in]) THEN
19920         DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (MP_TAC o SPEC `y:real^N`)) THEN
19921         ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `d:real` THEN
19922         STRIP_TAC THEN REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE] THEN
19923         ASM SET_TAC[];
19924         ALL_TAC] THEN
19925       SUBGOAL_THEN
19926        `open_in (subtopology euclidean s) (u INTER g(n:num):real^N->bool)`
19927       MP_TAC THENL [ASM_SIMP_TAC[OPEN_IN_INTER]; ALL_TAC] THEN
19928       GEN_REWRITE_TAC LAND_CONV [OPEN_IN_CONTAINS_BALL] THEN
19929       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (MP_TAC o SPEC `y:real^N`)) THEN
19930       ASM_REWRITE_TAC[IN_INTER] THEN
19931       DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
19932       EXISTS_TAC `s INTER ball(y:real^N,d / &2)` THEN
19933       SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_BALL] THEN REPEAT CONJ_TAC THENL
19934        [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `y:real^N` THEN
19935         ASM_REWRITE_TAC[CENTRE_IN_BALL; REAL_HALF; IN_INTER] THEN
19936         ASM SET_TAC[];
19937         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
19938          `b SUBSET u INTER g ==> !s. s SUBSET b ==> s SUBSET g`)) THEN
19939         MATCH_MP_TAC(SET_RULE
19940          `closure(s INTER b) SUBSET closure b /\ closure b SUBSET c
19941           ==> s INTER closure(s INTER b) SUBSET c INTER s`) THEN
19942         SIMP_TAC[SUBSET_CLOSURE; INTER_SUBSET] THEN
19943         ASM_SIMP_TAC[CLOSURE_BALL; SUBSET_BALLS; REAL_HALF; DIST_REFL] THEN
19944         ASM_REAL_ARITH_TAC;
19945         FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
19946           SUBSET_TRANS)) THEN MATCH_MP_TAC SUBSET_CLOSURE;
19947         ALL_TAC] THEN
19948       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
19949        `b INTER s SUBSET u INTER g ==> c SUBSET b
19950         ==> s INTER c SUBSET u`)) THEN
19951       REWRITE_TAC[SUBSET_BALLS; DIST_REFL] THEN ASM_REAL_ARITH_TAC;
19952       MATCH_MP_TAC DEPENDENT_CHOICE THEN ASM_SIMP_TAC[GSYM CONJ_ASSOC] THEN
19953       FIRST_X_ASSUM(MP_TAC o SPECL [`s INTER ball(x:real^N,e / &2)`; `0`]) THEN
19954       ASM_SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_BALL; GSYM MEMBER_NOT_EMPTY] THEN
19955       ANTS_TAC THENL [REWRITE_TAC[LEFT_AND_EXISTS_THM]; MESON_TAC[]] THEN
19956       EXISTS_TAC `x:real^N` THEN
19957       ASM_REWRITE_TAC[CENTRE_IN_BALL; REAL_HALF; IN_INTER] THEN
19958       TRANS_TAC SUBSET_TRANS `closure(ball(x:real^N,e / &2))` THEN
19959       SIMP_TAC[SUBSET_CLOSURE; INTER_SUBSET] THEN
19960       ASM_SIMP_TAC[CLOSURE_BALL; SUBSET_BALLS; REAL_HALF; DIST_REFL] THEN
19961       ASM_REAL_ARITH_TAC];
19962     MP_TAC(ISPEC
19963      `(\n. s INTER closure(t n)):num->real^N->bool` COMPACT_NEST) THEN
19964     ANTS_TAC THENL
19965      [REWRITE_TAC[FORALL_AND_THM] THEN REPEAT CONJ_TAC THENL
19966        [GEN_TAC THEN MATCH_MP_TAC CLOSED_INTER_COMPACT THEN
19967         ASM_MESON_TAC[BOUNDED_SUBSET; BOUNDED_BALL; COMPACT_EQ_BOUNDED_CLOSED;
19968                       CLOSED_CLOSURE];
19969         GEN_TAC THEN MATCH_MP_TAC(SET_RULE
19970          `~(t = {}) /\ t SUBSET s /\ t SUBSET closure t
19971           ==> ~(s INTER closure t = {})`) THEN
19972         ASM_MESON_TAC[CLOSURE_SUBSET; OPEN_IN_IMP_SUBSET];
19973         MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
19974         ASM_SIMP_TAC[SUBSET_CLOSURE; SET_RULE
19975          `t SUBSET u ==> s INTER t SUBSET s INTER u`] THEN
19976         SET_TAC[]];
19977       MATCH_MP_TAC(SET_RULE `s SUBSET t ==> ~(s = {}) ==> ~(t = {})`) THEN
19978       REWRITE_TAC[SUBSET_INTER] THEN
19979       REWRITE_TAC[SUBSET; IN_INTERS; FORALL_IN_IMAGE; FORALL_IN_GSPEC] THEN
19980       ASM SET_TAC[]]]);;
19981
19982 let BAIRE_ALT = prove
19983  (`!g s:real^N->bool.
19984         closed s /\ ~(s = {}) /\ COUNTABLE g /\ UNIONS g = s
19985         ==> ?t u. t IN g /\ open_in (subtopology euclidean s) u /\
19986                   u SUBSET (closure t)`,
19987   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
19988   [`IMAGE (\t:real^N->bool. s DIFF closure t) g`; `s:real^N->bool`] BAIRE) THEN
19989   ASM_SIMP_TAC[COUNTABLE_IMAGE; FORALL_IN_IMAGE] THEN
19990   MATCH_MP_TAC(TAUT `~q /\ (~r ==> p) ==> (p ==> q) ==> r`) THEN
19991   CONJ_TAC THENL
19992    [MATCH_MP_TAC(SET_RULE
19993      `~(s = {}) /\ (t = {} ==> closure t = {}) /\ t = {}
19994       ==> ~(s SUBSET closure t)`) THEN
19995     ASM_SIMP_TAC[CLOSURE_EMPTY] THEN
19996     MATCH_MP_TAC(SET_RULE `i SUBSET s /\ s DIFF i = s ==> i = {}`) THEN
19997     CONJ_TAC THENL [REWRITE_TAC[INTERS_IMAGE] THEN ASM SET_TAC[]; ALL_TAC] THEN
19998     REWRITE_TAC[DIFF_INTERS] THEN
19999     REWRITE_TAC[SET_RULE `{f x | x IN IMAGE g s} = {f(g x) | x IN s}`] THEN
20000     REWRITE_TAC[SET_RULE `s DIFF (s DIFF t) = s INTER t`] THEN
20001     REWRITE_TAC[SET_RULE `{s INTER closure t | t IN g} =
20002                           {s INTER t | t IN IMAGE closure g}`] THEN
20003     SIMP_TAC[GSYM INTER_UNIONS; SET_RULE `s INTER t = s <=> s SUBSET t`] THEN
20004     FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
20005     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM IMAGE_ID] THEN
20006     MATCH_MP_TAC UNIONS_MONO_IMAGE THEN REWRITE_TAC[CLOSURE_SUBSET];
20007     REWRITE_TAC[NOT_EXISTS_THM] THEN STRIP_TAC THEN
20008     X_GEN_TAC `t:real^N->bool` THEN REPEAT STRIP_TAC THENL
20009      [ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s DIFF (s INTER t)`] THEN
20010       MATCH_MP_TAC OPEN_IN_DIFF THEN
20011       ASM_SIMP_TAC[CLOSED_IN_CLOSED_INTER; CLOSED_CLOSURE; OPEN_IN_REFL];
20012       REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20013       REWRITE_TAC[CLOSURE_APPROACHABLE] THEN
20014       X_GEN_TAC `e:real` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL
20015        [`t:real^N->bool`; `s INTER ball(x:real^N,e)`]) THEN
20016       ASM_SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_BALL; SUBSET; IN_INTER; IN_BALL;
20017                    IN_DIFF] THEN
20018       MESON_TAC[DIST_SYM]]]);;
20019
20020 (* ------------------------------------------------------------------------- *)
20021 (* Several variants of paracompactness.                                      *)
20022 (* ------------------------------------------------------------------------- *)
20023
20024 let PARACOMPACT = prove
20025  (`!s c. (!t:real^N->bool. t IN c ==> open t) /\ s SUBSET UNIONS c
20026          ==> ?c'. s SUBSET UNIONS c' /\
20027                   (!u. u IN c'
20028                        ==> open u /\ ?t. t IN c /\ u SUBSET t) /\
20029                   (!x. x IN s
20030                        ==> ?v. open v /\ x IN v /\
20031                                FINITE {u | u IN c' /\ ~(u INTER v = {})})`,
20032   REPEAT STRIP_TAC THEN
20033   ASM_CASES_TAC `s:real^N->bool = {}` THENL
20034    [EXISTS_TAC `{}:(real^N->bool)->bool` THEN
20035     ASM_REWRITE_TAC[EMPTY_SUBSET; NOT_IN_EMPTY];
20036     ALL_TAC] THEN
20037   SUBGOAL_THEN
20038    `!x:real^N. x IN s
20039                ==> ?t u. x IN u /\ open u /\ closure u SUBSET t /\ t IN c`
20040   MP_TAC THENL
20041    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20042     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N` o GEN_REWRITE_RULE I [SUBSET]) THEN
20043     ASM_REWRITE_TAC[IN_UNIONS] THEN MATCH_MP_TAC MONO_EXISTS THEN
20044     X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
20045     FIRST_X_ASSUM(MP_TAC o SPEC `t:real^N->bool`) THEN
20046     ASM_REWRITE_TAC[] THEN
20047     GEN_REWRITE_TAC LAND_CONV [OPEN_CONTAINS_CBALL] THEN
20048     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
20049     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
20050     EXISTS_TAC `ball(x:real^N,e)` THEN
20051     ASM_SIMP_TAC[OPEN_BALL; CENTRE_IN_BALL; CLOSURE_BALL];
20052     GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
20053     REWRITE_TAC[LEFT_IMP_EXISTS_THM; SKOLEM_THM] THEN
20054     MAP_EVERY X_GEN_TAC
20055       [`f:real^N->real^N->bool`; `e:real^N->real^N->bool`] THEN
20056     STRIP_TAC] THEN
20057   MP_TAC(ISPEC `IMAGE (e:real^N->real^N->bool) s` LINDELOF) THEN
20058   ASM_SIMP_TAC[FORALL_IN_IMAGE] THEN
20059   ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN
20060   REWRITE_TAC[EXISTS_COUNTABLE_SUBSET_IMAGE] THEN
20061   DISCH_THEN(X_CHOOSE_THEN `k:real^N->bool`
20062     (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
20063   ASM_CASES_TAC `k:real^N->bool = {}` THENL
20064    [ASM_REWRITE_TAC[] THEN ASM SET_TAC[]; ALL_TAC] THEN
20065   MP_TAC(ISPEC `k:real^N->bool` COUNTABLE_AS_IMAGE) THEN
20066   ASM_REWRITE_TAC[] THEN
20067   DISCH_THEN(X_CHOOSE_THEN `a:num->real^N` SUBST_ALL_TAC) THEN
20068   STRIP_TAC THEN EXISTS_TAC
20069   `{ f(a n:real^N) DIFF UNIONS {closure(e(a m)):real^N->bool | m < n} |
20070      n IN (:num)}` THEN
20071   REWRITE_TAC[FORALL_IN_GSPEC; IN_UNIV] THEN REPEAT CONJ_TAC THENL
20072    [X_GEN_TAC `n:num` THEN CONJ_TAC THENL
20073      [MATCH_MP_TAC OPEN_DIFF THEN
20074       CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
20075       MATCH_MP_TAC CLOSED_UNIONS THEN
20076       REWRITE_TAC[FORALL_IN_GSPEC; CLOSED_CLOSURE] THEN
20077       ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN
20078       SIMP_TAC[FINITE_IMAGE; FINITE_NUMSEG_LT];
20079       EXISTS_TAC `f((a:num->real^N) n):real^N->bool` THEN ASM SET_TAC[]];
20080     REWRITE_TAC[SUBSET; UNIONS_GSPEC; IN_ELIM_THM; IN_DIFF] THEN
20081     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20082     SUBGOAL_THEN `?n. x IN (f((a:num->real^N) n):real^N->bool)` MP_TAC THENL
20083      [RULE_ASSUM_TAC(REWRITE_RULE[UNIONS_IMAGE; EXISTS_IN_IMAGE]) THEN
20084       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
20085       DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
20086       ASM_REWRITE_TAC[IN_ELIM_THM; IN_UNIV] THEN
20087       DISCH_THEN(MP_TAC o snd o EQ_IMP_RULE) THEN
20088       ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
20089       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `n:num` THEN
20090       STRIP_TAC THEN
20091       FIRST_X_ASSUM(MP_TAC o SPEC `(a:num->real^N) n`) THEN
20092       ANTS_TAC THENL [ASM SET_TAC[]; ASM_MESON_TAC[CLOSURE_SUBSET; SUBSET]];
20093       GEN_REWRITE_TAC LAND_CONV [num_WOP] THEN
20094       MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[]];
20095     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20096     RULE_ASSUM_TAC(REWRITE_RULE[UNIONS_IMAGE; EXISTS_IN_IMAGE]) THEN
20097     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
20098     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
20099     ASM_REWRITE_TAC[IN_ELIM_THM; IN_UNIV] THEN
20100     DISCH_THEN(MP_TAC o snd o EQ_IMP_RULE) THEN
20101     ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
20102     DISCH_THEN(X_CHOOSE_TAC `n:num`) THEN
20103     EXISTS_TAC `e((a:num->real^N) n):real^N->bool` THEN
20104     ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
20105     REWRITE_TAC[SET_RULE
20106      `{u | (?n. u = f n) /\ P u} = IMAGE f {n |n| P(f n) /\ n IN (:num)}`] THEN
20107     MATCH_MP_TAC FINITE_IMAGE THEN MATCH_MP_TAC FINITE_SUBSET THEN
20108     EXISTS_TAC `{m:num | m <= n}` THEN REWRITE_TAC[FINITE_NUMSEG_LE] THEN
20109     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNIV] THEN
20110     X_GEN_TAC `m:num` THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
20111     REWRITE_TAC[NOT_LE] THEN DISCH_TAC THEN
20112     MATCH_MP_TAC(SET_RULE `u SUBSET t ==> (s DIFF t) INTER u = {}`) THEN
20113     REWRITE_TAC[SUBSET; IN_UNIONS; EXISTS_IN_GSPEC] THEN
20114     ASM_MESON_TAC[CLOSURE_SUBSET; SUBSET]]);;
20115
20116 let PARACOMPACT_CLOSED_IN = prove
20117  (`!u:real^N->bool s c.
20118         closed_in (subtopology euclidean u) s /\
20119         (!t:real^N->bool. t IN c ==> open_in (subtopology euclidean u) t) /\
20120         s SUBSET UNIONS c
20121          ==> ?c'. s SUBSET UNIONS c' /\
20122                   (!v. v IN c'
20123                        ==> open_in (subtopology euclidean u) v /\
20124                            ?t. t IN c /\ v SUBSET t) /\
20125                   (!x. x IN u
20126                        ==> ?v. open_in (subtopology euclidean u) v /\ x IN v /\
20127                                FINITE {n | n IN c' /\ ~(n INTER v = {})})`,
20128   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC
20129    (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC)) THEN
20130   REWRITE_TAC[OPEN_IN_OPEN] THEN
20131   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
20132   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
20133   X_GEN_TAC `uu:(real^N->bool)->(real^N->bool)` THEN
20134   DISCH_THEN(ASSUME_TAC o GSYM) THEN
20135   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CLOSED_IN_CLOSED]) THEN
20136   DISCH_THEN(X_CHOOSE_THEN `k:real^N->bool`
20137    (CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC)) THEN
20138   MP_TAC(ISPECL
20139    [`u:real^N->bool`;
20140     `((:real^N) DIFF k) INSERT IMAGE (uu:(real^N->bool)->(real^N->bool)) c`]
20141    PARACOMPACT) THEN
20142   ASM_SIMP_TAC[FORALL_IN_IMAGE; UNIONS_IMAGE; UNIONS_INSERT; FORALL_IN_INSERT;
20143                EXISTS_IN_IMAGE; EXISTS_IN_INSERT; GSYM closed] THEN
20144   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
20145   DISCH_THEN(X_CHOOSE_THEN `d:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
20146   EXISTS_TAC `{u INTER v:real^N->bool | v IN d /\ ~(v INTER k = {})}` THEN
20147   REPEAT CONJ_TAC THENL
20148    [REWRITE_TAC[UNIONS_GSPEC] THEN ASM SET_TAC[];
20149     REWRITE_TAC[FORALL_IN_GSPEC] THEN ASM SET_TAC[];
20150     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20151     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
20152     DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool` STRIP_ASSUME_TAC) THEN
20153     EXISTS_TAC `u INTER v:real^N->bool` THEN ASM_REWRITE_TAC[IN_INTER] THEN
20154     CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
20155     ONCE_REWRITE_TAC[SET_RULE
20156      `{y | y IN {f x | P x} /\ Q y} = IMAGE f {x | P x /\ Q(f x)}`] THEN
20157     MATCH_MP_TAC FINITE_IMAGE THEN
20158     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
20159      (REWRITE_RULE[IMP_CONJ] FINITE_SUBSET)) THEN SET_TAC[]]);;
20160
20161 let PARACOMPACT_CLOSED = prove
20162  (`!s:real^N->bool c.
20163         closed s /\ (!t:real^N->bool. t IN c ==> open t) /\ s SUBSET UNIONS c
20164         ==> ?c'. s SUBSET UNIONS c' /\
20165                  (!u. u IN c' ==> open u /\ ?t. t IN c /\ u SUBSET t) /\
20166                  (!x. ?v. open v /\ x IN v /\
20167                           FINITE {u | u IN c' /\ ~(u INTER v = {})})`,
20168   REPEAT STRIP_TAC THEN
20169   MP_TAC(ISPECL [`(:real^N)`; `s:real^N->bool`; `c:(real^N->bool)->bool`]
20170         PARACOMPACT_CLOSED_IN) THEN
20171   ASM_REWRITE_TAC[SUBTOPOLOGY_UNIV; GSYM OPEN_IN; GSYM CLOSED_IN; IN_UNIV]);;
20172
20173 (* ------------------------------------------------------------------------- *)
20174 (* Partitions of unity subordinate to locally finite open coverings.         *)
20175 (* ------------------------------------------------------------------------- *)
20176
20177 let SUBORDINATE_PARTITION_OF_UNITY = prove
20178  (`!c s. s SUBSET UNIONS c /\ (!u. u IN c ==> open u) /\
20179          (!x. x IN s
20180               ==> ?v. open v /\ x IN v /\
20181                       FINITE {u | u IN c /\ ~(u INTER v = {})})
20182          ==> ?f:(real^N->bool)->real^N->real.
20183                       (!u. u IN c
20184                            ==> (lift o f u) continuous_on s /\
20185                                !x. x IN s ==> &0 <= f u x) /\
20186                       (!x u. u IN c /\ x IN s /\ ~(x IN u) ==> f u x = &0) /\
20187                       (!x. x IN s ==> sum c (\u. f u x) = &1) /\
20188                       (!x. x IN s
20189                            ==> ?n. open n /\ x IN n /\
20190                                    FINITE {u | u IN c /\
20191                                            ~(!x. x IN n ==> f u x = &0)})`,
20192   REPEAT STRIP_TAC THEN
20193   ASM_CASES_TAC `?u:real^N->bool. u IN c /\ s SUBSET u` THENL
20194    [FIRST_X_ASSUM(CHOOSE_THEN STRIP_ASSUME_TAC) THEN
20195     EXISTS_TAC `\v:real^N->bool x:real^N. if v = u then &1 else &0` THEN
20196     REWRITE_TAC[COND_RAND; COND_RATOR; o_DEF; REAL_POS;
20197                 REAL_OF_NUM_EQ; ARITH_EQ;
20198                 MESON[] `(if p then q else T) <=> p ==> q`] THEN
20199     ASM_SIMP_TAC[CONTINUOUS_ON_CONST; COND_ID; SUM_DELTA] THEN
20200     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
20201     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20202     EXISTS_TAC `ball(x:real^N,&1)` THEN
20203     REWRITE_TAC[OPEN_BALL; CENTRE_IN_BALL; REAL_LT_01] THEN
20204     MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `{u:real^N->bool}` THEN
20205     REWRITE_TAC[FINITE_SING; SUBSET; IN_ELIM_THM; IN_SING] THEN
20206     X_GEN_TAC `v:real^N->bool` THEN
20207     ASM_CASES_TAC `v:real^N->bool = u` THEN ASM_REWRITE_TAC[];
20208     ALL_TAC] THEN
20209   EXISTS_TAC `\u:real^N->bool x:real^N.
20210         if x IN s
20211         then setdist({x},s DIFF u) / sum c (\v. setdist({x},s DIFF v))
20212         else &0` THEN
20213   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
20214   SIMP_TAC[SUM_POS_LE; SETDIST_POS_LE; REAL_LE_DIV] THEN
20215   SIMP_TAC[SETDIST_SING_IN_SET; IN_DIFF; real_div; REAL_MUL_LZERO] THEN
20216   REWRITE_TAC[SUM_RMUL] THEN REWRITE_TAC[GSYM real_div] THEN
20217   MATCH_MP_TAC(TAUT `r /\ p /\ q ==> p /\ q /\ r`) THEN CONJ_TAC THENL
20218    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20219     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
20220     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `n:real^N->bool` THEN
20221     REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
20222     ASM_REWRITE_TAC[] THEN
20223     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] FINITE_SUBSET) THEN
20224     REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `u:real^N->bool` THEN
20225     ASM_CASES_TAC `(u:real^N->bool) IN c` THEN
20226     ASM_REWRITE_TAC[CONTRAPOS_THM] THEN DISCH_TAC THEN
20227     X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
20228     REWRITE_TAC[real_div; REAL_ENTIRE] THEN
20229     COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
20230     ASM_CASES_TAC `(y:real^N) IN u` THEN
20231     ASM_SIMP_TAC[SETDIST_SING_IN_SET; IN_DIFF; REAL_MUL_LZERO] THEN
20232     ASM SET_TAC[];
20233     ALL_TAC] THEN
20234   SUBGOAL_THEN
20235    `!v x:real^N. v IN c /\ x IN s /\ x IN v ==> &0 < setdist({x},s DIFF v)`
20236   ASSUME_TAC THENL
20237    [REPEAT STRIP_TAC THEN
20238     SIMP_TAC[SETDIST_POS_LE; REAL_ARITH `&0 < x <=> &0 <= x /\ ~(x = &0)`] THEN
20239     MP_TAC(ISPECL [`s:real^N->bool`; `s DIFF v:real^N->bool`; `x:real^N`]
20240         SETDIST_EQ_0_CLOSED_IN) THEN
20241     ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
20242     ASM_SIMP_TAC[CLOSED_IN_CLOSED_INTER; GSYM OPEN_CLOSED] THEN
20243     DISCH_THEN SUBST1_TAC THEN ASM_REWRITE_TAC[] THEN
20244     ASM_REWRITE_TAC[IN_INTER; IN_DIFF; IN_UNION] THEN ASM SET_TAC[];
20245     ALL_TAC] THEN
20246   SUBGOAL_THEN
20247    `!x:real^N. x IN s ==> &0 < sum c (\v. setdist ({x},s DIFF v))`
20248   ASSUME_TAC THENL
20249    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20250     ONCE_REWRITE_TAC[GSYM SUM_SUPPORT] THEN
20251     REWRITE_TAC[support; NEUTRAL_REAL_ADD] THEN
20252     MATCH_MP_TAC SUM_POS_LT THEN REWRITE_TAC[SETDIST_POS_LE] THEN
20253     CONJ_TAC THENL
20254      [FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
20255       DISCH_THEN(CHOOSE_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
20256       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
20257       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] FINITE_SUBSET) THEN
20258       REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `u:real^N->bool` THEN
20259       ASM_CASES_TAC `(x:real^N) IN u` THEN
20260       ASM_SIMP_TAC[SETDIST_SING_IN_SET; IN_DIFF] THEN ASM SET_TAC[];
20261       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
20262       DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN REWRITE_TAC[IN_UNIONS] THEN
20263       ASM_REWRITE_TAC[IN_ELIM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
20264       ASM_MESON_TAC[REAL_LT_IMP_NZ]];
20265     ALL_TAC] THEN
20266   ASM_SIMP_TAC[REAL_LT_IMP_NZ; REAL_DIV_REFL; o_DEF] THEN
20267   X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
20268   MATCH_MP_TAC CONTINUOUS_ON_EQ THEN
20269   EXISTS_TAC `\x:real^N.
20270         lift(setdist({x},s DIFF u) / sum c (\v. setdist({x},s DIFF v)))` THEN
20271   SIMP_TAC[] THEN REWRITE_TAC[real_div; LIFT_CMUL] THEN
20272   MATCH_MP_TAC CONTINUOUS_ON_MUL THEN
20273   SIMP_TAC[CONTINUOUS_ON_LIFT_SETDIST; o_DEF] THEN
20274   MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_INV) THEN
20275   ASM_SIMP_TAC[REAL_LT_IMP_NZ; CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
20276   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
20277   FIRST_X_ASSUM(fun th ->
20278     MP_TAC(SPEC `x:real^N` th) THEN ASM_REWRITE_TAC[] THEN
20279     DISCH_THEN(X_CHOOSE_THEN `n:real^N->bool` STRIP_ASSUME_TAC)) THEN
20280   MATCH_MP_TAC CONTINUOUS_TRANSFORM_WITHIN_OPEN_IN THEN
20281   MAP_EVERY EXISTS_TAC
20282    [`\x:real^N. lift(sum {v | v IN c /\ ~(v INTER n = {})}
20283                          (\v. setdist({x},s DIFF v)))`;
20284     `s INTER n:real^N->bool`] THEN
20285   ASM_SIMP_TAC[IN_INTER; OPEN_IN_OPEN_INTER] THEN CONJ_TAC THENL
20286    [X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN AP_TERM_TAC THEN
20287     CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_EQ_SUPERSET THEN
20288     ASM_REWRITE_TAC[SUBSET_RESTRICT] THEN X_GEN_TAC `v:real^N->bool` THEN
20289     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
20290     ASM_REWRITE_TAC[IN_ELIM_THM] THEN DISCH_TAC THEN
20291     MATCH_MP_TAC SETDIST_SING_IN_SET THEN ASM SET_TAC[];
20292     ASM_SIMP_TAC[LIFT_SUM; o_DEF] THEN MATCH_MP_TAC CONTINUOUS_VSUM THEN
20293     ASM_SIMP_TAC[CONTINUOUS_AT_LIFT_SETDIST; CONTINUOUS_AT_WITHIN]]);;