Update from HH
[Multivariate Analysis/.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 BALL_TRANSLATION = prove
530  (`!a x r. ball(a + x,r) = IMAGE (\y. a + y) (ball(x,r))`,
531   REWRITE_TAC[ball] THEN GEOM_TRANSLATE_TAC[]);;
532
533 let CBALL_TRANSLATION = prove
534  (`!a x r. cball(a + x,r) = IMAGE (\y. a + y) (cball(x,r))`,
535   REWRITE_TAC[cball] THEN GEOM_TRANSLATE_TAC[]);;
536
537 let SPHERE_TRANSLATION = prove
538  (`!a x r. sphere(a + x,r) = IMAGE (\y. a + y) (sphere(x,r))`,
539   REWRITE_TAC[sphere] THEN GEOM_TRANSLATE_TAC[]);;
540
541 add_translation_invariants
542   [BALL_TRANSLATION; CBALL_TRANSLATION; SPHERE_TRANSLATION];;
543
544 let BALL_LINEAR_IMAGE = prove
545  (`!f:real^M->real^N x r.
546         linear f /\ (!y. ?x. f x = y) /\ (!x. norm(f x) = norm x)
547         ==> ball(f x,r) = IMAGE f (ball(x,r))`,
548   REWRITE_TAC[ball] THEN GEOM_TRANSFORM_TAC[]);;
549
550 let CBALL_LINEAR_IMAGE = prove
551  (`!f:real^M->real^N x r.
552         linear f /\ (!y. ?x. f x = y) /\ (!x. norm(f x) = norm x)
553         ==> cball(f x,r) = IMAGE f (cball(x,r))`,
554   REWRITE_TAC[cball] THEN GEOM_TRANSFORM_TAC[]);;
555
556 let SPHERE_LINEAR_IMAGE = prove
557  (`!f:real^M->real^N x r.
558         linear f /\ (!y. ?x. f x = y) /\ (!x. norm(f x) = norm x)
559         ==> sphere(f x,r) = IMAGE f (sphere(x,r))`,
560   REWRITE_TAC[sphere] THEN GEOM_TRANSFORM_TAC[]);;
561
562 add_linear_invariants
563   [BALL_LINEAR_IMAGE; CBALL_LINEAR_IMAGE; SPHERE_LINEAR_IMAGE];;
564
565 let BALL_SCALING = prove
566  (`!c. &0 < c ==> !x r. ball(c % x,c * r) = IMAGE (\x. c % x) (ball(x,r))`,
567   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN
568   MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN REWRITE_TAC[] THEN CONJ_TAC THENL
569    [ASM_MESON_TAC[SURJECTIVE_SCALING; REAL_LT_IMP_NZ]; ALL_TAC] THEN
570   REWRITE_TAC[IN_BALL; DIST_MUL] THEN
571   ASM_SIMP_TAC[REAL_ARITH `&0 < c ==> abs c = c`; REAL_LT_LMUL_EQ]);;
572
573 let CBALL_SCALING = prove
574  (`!c. &0 < c ==> !x r. cball(c % x,c * r) = IMAGE (\x. c % x) (cball(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_CBALL; DIST_MUL] THEN
579   ASM_SIMP_TAC[REAL_ARITH `&0 < c ==> abs c = c`; REAL_LE_LMUL_EQ]);;
580
581 add_scaling_theorems [BALL_SCALING; CBALL_SCALING];;
582
583 let CBALL_DIFF_BALL = prove
584  (`!a r. cball(a,r) DIFF ball(a,r) = sphere(a,r)`,
585   REWRITE_TAC[ball; cball; sphere; EXTENSION; IN_DIFF; IN_ELIM_THM] THEN
586   REAL_ARITH_TAC);;
587
588 let BALL_UNION_SPHERE = prove
589  (`!a r. ball(a,r) UNION sphere(a,r) = cball(a,r)`,
590   REWRITE_TAC[ball; cball; sphere; EXTENSION; IN_UNION; IN_ELIM_THM] THEN
591   REAL_ARITH_TAC);;
592
593 let SPHERE_UNION_BALL = prove
594  (`!a r. sphere(a,r) UNION ball(a,r)  = cball(a,r)`,
595   REWRITE_TAC[ball; cball; sphere; EXTENSION; IN_UNION; IN_ELIM_THM] THEN
596   REAL_ARITH_TAC);;
597
598 let CBALL_DIFF_SPHERE = prove
599  (`!a r. cball(a,r) DIFF sphere(a,r) = ball(a,r)`,
600   REWRITE_TAC[EXTENSION; IN_DIFF; IN_SPHERE; IN_BALL; IN_CBALL] THEN
601   REAL_ARITH_TAC);;
602
603 let OPEN_BALL = prove
604  (`!x e. open(ball(x,e))`,
605   REWRITE_TAC[open_def; ball; IN_ELIM_THM] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
606   MESON_TAC[REAL_SUB_LT; REAL_LT_SUB_LADD; REAL_ADD_SYM; REAL_LET_TRANS;
607             DIST_TRIANGLE_ALT]);;
608
609 let CENTRE_IN_BALL = prove
610  (`!x e. x IN ball(x,e) <=> &0 < e`,
611   MESON_TAC[IN_BALL; DIST_REFL]);;
612
613 let OPEN_CONTAINS_BALL = prove
614  (`!s. open s <=> !x. x IN s ==> ?e. &0 < e /\ ball(x,e) SUBSET s`,
615   REWRITE_TAC[open_def; SUBSET; IN_BALL] THEN REWRITE_TAC[DIST_SYM]);;
616
617 let OPEN_CONTAINS_BALL_EQ = prove
618  (`!s. open s ==> (!x. x IN s <=> ?e. &0 < e /\ ball(x,e) SUBSET s)`,
619   MESON_TAC[OPEN_CONTAINS_BALL; SUBSET; CENTRE_IN_BALL]);;
620
621 let BALL_EQ_EMPTY = prove
622  (`!x e. (ball(x,e) = {}) <=> e <= &0`,
623   REWRITE_TAC[EXTENSION; IN_BALL; NOT_IN_EMPTY; REAL_NOT_LT] THEN
624   MESON_TAC[DIST_POS_LE; REAL_LE_TRANS; DIST_REFL]);;
625
626 let BALL_EMPTY = prove
627  (`!x e. e <= &0 ==> ball(x,e) = {}`,
628   REWRITE_TAC[BALL_EQ_EMPTY]);;
629
630 let OPEN_CONTAINS_CBALL = prove
631  (`!s. open s <=> !x. x IN s ==> ?e. &0 < e /\ cball(x,e) SUBSET s`,
632   GEN_TAC THEN REWRITE_TAC[OPEN_CONTAINS_BALL] THEN EQ_TAC THENL
633    [ALL_TAC; ASM_MESON_TAC[SUBSET_TRANS; BALL_SUBSET_CBALL]] THEN
634   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
635   REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL] THEN
636   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
637   EXISTS_TAC `e / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
638   SUBGOAL_THEN `e / &2 < e` (fun th -> ASM_MESON_TAC[th; REAL_LET_TRANS]) THEN
639   ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
640   UNDISCH_TAC `&0 < e` THEN REAL_ARITH_TAC);;
641
642 let OPEN_CONTAINS_CBALL_EQ = prove
643  (`!s. open s ==> (!x. x IN s <=> ?e. &0 < e /\ cball(x,e) SUBSET s)`,
644   MESON_TAC[OPEN_CONTAINS_CBALL; SUBSET; REAL_LT_IMP_LE; CENTRE_IN_CBALL]);;
645
646 let SPHERE_EQ_EMPTY = prove
647  (`!a:real^N r. sphere(a,r) = {} <=> r < &0`,
648   REWRITE_TAC[sphere; EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY] THEN
649   REPEAT GEN_TAC THEN EQ_TAC THENL [ALL_TAC; CONV_TAC NORM_ARITH] THEN
650   MESON_TAC[VECTOR_CHOOSE_DIST; REAL_NOT_LE]);;
651
652 let SPHERE_EMPTY = prove
653  (`!a:real^N r. r < &0 ==> sphere(a,r) = {}`,
654   REWRITE_TAC[SPHERE_EQ_EMPTY]);;
655
656 let NEGATIONS_BALL = prove
657  (`!r. IMAGE (--) (ball(vec 0:real^N,r)) = ball(vec 0,r)`,
658   GEN_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
659   REWRITE_TAC[IN_BALL_0; NORM_NEG] THEN MESON_TAC[VECTOR_NEG_NEG]);;
660
661 let NEGATIONS_CBALL = prove
662  (`!r. IMAGE (--) (cball(vec 0:real^N,r)) = cball(vec 0,r)`,
663   GEN_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
664   REWRITE_TAC[IN_CBALL_0; NORM_NEG] THEN MESON_TAC[VECTOR_NEG_NEG]);;
665
666 let NEGATIONS_SPHERE = prove
667  (`!r. IMAGE (--) (sphere(vec 0:real^N,r)) = sphere(vec 0,r)`,
668   GEN_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
669   REWRITE_TAC[IN_SPHERE_0; NORM_NEG] THEN MESON_TAC[VECTOR_NEG_NEG]);;
670
671 (* ------------------------------------------------------------------------- *)
672 (* Basic "localization" results are handy for connectedness.                 *)
673 (* ------------------------------------------------------------------------- *)
674
675 let OPEN_IN_OPEN = prove
676  (`!s:real^N->bool u.
677         open_in (subtopology euclidean u) s <=> ?t. open t /\ (s = u INTER t)`,
678   REPEAT STRIP_TAC THEN REWRITE_TAC[OPEN_IN_SUBTOPOLOGY; GSYM OPEN_IN] THEN
679   REWRITE_TAC[INTER_ACI]);;
680
681 let OPEN_IN_INTER_OPEN = prove
682  (`!s t u:real^N->bool.
683         open_in (subtopology euclidean u) s /\ open t
684         ==> open_in (subtopology euclidean u) (s INTER t)`,
685   REWRITE_TAC[OPEN_IN_OPEN] THEN REPEAT STRIP_TAC THEN
686   ASM_REWRITE_TAC[INTER_ASSOC] THEN ASM_MESON_TAC[OPEN_INTER]);;
687
688 let OPEN_IN_OPEN_INTER = prove
689  (`!u s. open s ==> open_in (subtopology euclidean u) (u INTER s)`,
690   REWRITE_TAC[OPEN_IN_OPEN] THEN MESON_TAC[]);;
691
692 let OPEN_OPEN_IN_TRANS = prove
693  (`!s t. open s /\ open t /\ t SUBSET s
694          ==> open_in (subtopology euclidean s) t`,
695   MESON_TAC[OPEN_IN_OPEN_INTER; SET_RULE `t SUBSET s ==> t = s INTER t`]);;
696
697 let OPEN_SUBSET = prove
698  (`!s t:real^N->bool.
699         s SUBSET t /\ open s ==> open_in (subtopology euclidean t) s`,
700   REPEAT STRIP_TAC THEN REWRITE_TAC[OPEN_IN_OPEN] THEN
701   EXISTS_TAC `s:real^N->bool` THEN ASM SET_TAC[]);;
702
703 let CLOSED_IN_CLOSED = prove
704  (`!s:real^N->bool u.
705     closed_in (subtopology euclidean u) s <=> ?t. closed t /\ (s = u INTER t)`,
706   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSED_IN_SUBTOPOLOGY; GSYM CLOSED_IN] THEN
707   REWRITE_TAC[INTER_ACI]);;
708
709 let CLOSED_SUBSET_EQ = prove
710  (`!u s:real^N->bool.
711         closed s ==> (closed_in (subtopology euclidean u) s <=> s SUBSET u)`,
712   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
713    [FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET) THEN
714     REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY];
715     REWRITE_TAC[CLOSED_IN_CLOSED] THEN EXISTS_TAC `s:real^N->bool` THEN
716     ASM SET_TAC[]]);;
717
718 let CLOSED_IN_INTER_CLOSED = prove
719  (`!s t u:real^N->bool.
720         closed_in (subtopology euclidean u) s /\ closed t
721         ==> closed_in (subtopology euclidean u) (s INTER t)`,
722   REWRITE_TAC[CLOSED_IN_CLOSED] THEN REPEAT STRIP_TAC THEN
723   ASM_REWRITE_TAC[INTER_ASSOC] THEN ASM_MESON_TAC[CLOSED_INTER]);;
724
725 let CLOSED_IN_CLOSED_INTER = prove
726  (`!u s. closed s ==> closed_in (subtopology euclidean u) (u INTER s)`,
727   REWRITE_TAC[CLOSED_IN_CLOSED] THEN MESON_TAC[]);;
728
729 let CLOSED_CLOSED_IN_TRANS = prove
730  (`!s t. closed s /\ closed t /\ t SUBSET s
731          ==> closed_in (subtopology euclidean s) t`,
732   MESON_TAC[CLOSED_IN_CLOSED_INTER; SET_RULE `t SUBSET s ==> t = s INTER t`]);;
733
734 let CLOSED_SUBSET = prove
735  (`!s t:real^N->bool.
736         s SUBSET t /\ closed s ==> closed_in (subtopology euclidean t) s`,
737   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSED_IN_CLOSED] THEN
738   EXISTS_TAC `s:real^N->bool` THEN ASM SET_TAC[]);;
739
740 let OPEN_IN_SUBSET_TRANS = prove
741  (`!s t u:real^N->bool.
742         open_in (subtopology euclidean u) s /\ s SUBSET t /\ t SUBSET u
743         ==> open_in (subtopology euclidean t) s`,
744   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN; LEFT_AND_EXISTS_THM] THEN
745   MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]);;
746
747 let CLOSED_IN_SUBSET_TRANS = prove
748  (`!s t u:real^N->bool.
749         closed_in (subtopology euclidean u) s /\ s SUBSET t /\ t SUBSET u
750         ==> closed_in (subtopology euclidean t) s`,
751   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN_CLOSED; LEFT_AND_EXISTS_THM] THEN
752   MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]);;
753
754 let open_in = prove
755  (`!u s:real^N->bool.
756         open_in (subtopology euclidean u) s <=>
757           s SUBSET u /\
758           !x. x IN s ==> ?e. &0 < e /\
759                              !x'. x' IN u /\ dist(x',x) < e ==> x' IN s`,
760   REPEAT GEN_TAC THEN
761   REWRITE_TAC[OPEN_IN_SUBTOPOLOGY; GSYM OPEN_IN] THEN EQ_TAC THENL
762    [REWRITE_TAC[open_def] THEN ASM SET_TAC[INTER_SUBSET; IN_INTER];
763     ALL_TAC] THEN
764   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
765   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
766   REWRITE_TAC[SKOLEM_THM] THEN DISCH_THEN(X_CHOOSE_TAC `d:real^N->real`) THEN
767   EXISTS_TAC `UNIONS {b | ?x:real^N. (b = ball(x,d x)) /\ x IN s}` THEN
768   CONJ_TAC THENL
769    [MATCH_MP_TAC OPEN_UNIONS THEN
770     ASM_SIMP_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM; OPEN_BALL];
771     GEN_REWRITE_TAC I [EXTENSION] THEN
772     REWRITE_TAC[IN_INTER; IN_UNIONS; IN_ELIM_THM] THEN
773     ASM_MESON_TAC[SUBSET; DIST_REFL; DIST_SYM; IN_BALL]]);;
774
775 let OPEN_IN_CONTAINS_BALL = prove
776  (`!s t:real^N->bool.
777         open_in (subtopology euclidean t) s <=>
778         s SUBSET t /\
779         !x. x IN s ==> ?e. &0 < e /\ ball(x,e) INTER t SUBSET s`,
780   REWRITE_TAC[open_in; INTER; SUBSET; IN_ELIM_THM; IN_BALL] THEN
781   MESON_TAC[DIST_SYM]);;
782
783 let OPEN_IN_CONTAINS_CBALL = prove
784  (`!s t:real^N->bool.
785         open_in (subtopology euclidean t) s <=>
786         s SUBSET t /\
787         !x. x IN s ==> ?e. &0 < e /\ cball(x,e) INTER t SUBSET s`,
788   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_CONTAINS_BALL] THEN
789   AP_TERM_TAC THEN REWRITE_TAC[IN_BALL; IN_INTER; SUBSET; IN_CBALL] THEN
790   MESON_TAC[REAL_ARITH `&0 < e ==> &0 < e / &2 /\ (x <= e / &2 ==> x < e)`;
791             REAL_LT_IMP_LE]);;
792
793 (* ------------------------------------------------------------------------- *)
794 (* These "transitivity" results are handy too.                               *)
795 (* ------------------------------------------------------------------------- *)
796
797 let OPEN_IN_TRANS = prove
798  (`!s t u. open_in (subtopology euclidean t) s /\
799            open_in (subtopology euclidean u) t
800            ==> open_in (subtopology euclidean u) s`,
801   ASM_MESON_TAC[OPEN_IN_OPEN; OPEN_IN; OPEN_INTER; INTER_ASSOC]);;
802
803 let OPEN_IN_OPEN_TRANS = prove
804  (`!s t. open_in (subtopology euclidean t) s /\ open t ==> open s`,
805   REWRITE_TAC[ONCE_REWRITE_RULE[GSYM SUBTOPOLOGY_UNIV] OPEN_IN] THEN
806   REWRITE_TAC[OPEN_IN_TRANS]);;
807
808 let CLOSED_IN_TRANS = prove
809  (`!s t u. closed_in (subtopology euclidean t) s /\
810            closed_in (subtopology euclidean u) t
811            ==> closed_in (subtopology euclidean u) s`,
812   ASM_MESON_TAC[CLOSED_IN_CLOSED; CLOSED_IN; CLOSED_INTER; INTER_ASSOC]);;
813
814 let CLOSED_IN_CLOSED_TRANS = prove
815  (`!s t. closed_in (subtopology euclidean t) s /\ closed t ==> closed s`,
816   REWRITE_TAC[ONCE_REWRITE_RULE[GSYM SUBTOPOLOGY_UNIV] CLOSED_IN] THEN
817   REWRITE_TAC[CLOSED_IN_TRANS]);;
818
819 let OPEN_IN_SUBTOPOLOGY_INTER_SUBSET = prove
820  (`!s u v. open_in (subtopology euclidean u) (u INTER s) /\ v SUBSET u
821            ==> open_in (subtopology euclidean v) (v INTER s)`,
822   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN; LEFT_AND_EXISTS_THM] THEN
823   MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]);;
824
825 let OPEN_IN_OPEN_EQ = prove
826  (`!s t. open s
827          ==> (open_in (subtopology euclidean s) t <=> open t /\ t SUBSET s)`,
828   MESON_TAC[OPEN_OPEN_IN_TRANS; OPEN_IN_OPEN_TRANS; open_in]);;
829
830 let CLOSED_IN_CLOSED_EQ = prove
831  (`!s t. closed s
832          ==> (closed_in (subtopology euclidean s) t <=>
833               closed t /\ t SUBSET s)`,
834   MESON_TAC[CLOSED_CLOSED_IN_TRANS; CLOSED_IN_CLOSED_TRANS; closed_in;
835             TOPSPACE_EUCLIDEAN_SUBTOPOLOGY]);;
836
837 (* ------------------------------------------------------------------------- *)
838 (* Also some invariance theorems for relative topology.                      *)
839 (* ------------------------------------------------------------------------- *)
840
841 let OPEN_IN_TRANSLATION_EQ = prove
842  (`!a s t. open_in (subtopology euclidean (IMAGE (\x. a + x) t))
843                    (IMAGE (\x. a + x) s) <=>
844            open_in (subtopology euclidean t) s`,
845   REWRITE_TAC[open_in] THEN GEOM_TRANSLATE_TAC[]);;
846
847 add_translation_invariants [OPEN_IN_TRANSLATION_EQ];;
848
849 let CLOSED_IN_TRANSLATION_EQ = prove
850  (`!a s t. closed_in (subtopology euclidean (IMAGE (\x. a + x) t))
851                    (IMAGE (\x. a + x) s) <=>
852            closed_in (subtopology euclidean t) s`,
853   REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
854   GEOM_TRANSLATE_TAC[]);;
855
856 add_translation_invariants [CLOSED_IN_TRANSLATION_EQ];;
857
858 let OPEN_IN_INJECTIVE_LINEAR_IMAGE = prove
859  (`!f:real^M->real^N s t.
860           linear f /\ (!x y. f x = f y ==> x = y)
861           ==> (open_in (subtopology euclidean (IMAGE f t)) (IMAGE f s) <=>
862                open_in (subtopology euclidean t) s)`,
863   REWRITE_TAC[open_in; FORALL_IN_IMAGE; IMP_CONJ; SUBSET] THEN
864   REPEAT STRIP_TAC THEN
865   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (SET_RULE
866    `(!x y. f x = f y ==> x = y) ==> (!x s. f x IN IMAGE f s <=> x IN s)`)) THEN
867   ASM_REWRITE_TAC[] THEN
868   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_BOUNDED_POS) THEN
869   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_BOUNDED_BELOW_POS) THEN
870   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
871   X_GEN_TAC `B2:real` THEN STRIP_TAC THEN
872   X_GEN_TAC `B1:real` THEN STRIP_TAC THEN
873   AP_TERM_TAC THEN AP_TERM_TAC THEN
874   GEN_REWRITE_TAC I [FUN_EQ_THM] THEN X_GEN_TAC `x:real^M` THEN
875   REWRITE_TAC[] THEN AP_TERM_TAC THEN
876   FIRST_ASSUM(ASSUME_TAC o GSYM o MATCH_MP LINEAR_SUB) THEN
877   ASM_REWRITE_TAC[dist; IMP_IMP] THEN EQ_TAC THEN
878   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THENL
879    [EXISTS_TAC `e / B1:real`; EXISTS_TAC `e * B2:real`] THEN
880   ASM_SIMP_TAC[REAL_LT_MUL; REAL_LT_DIV] THEN
881   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THENL
882    [MATCH_MP_TAC(REAL_ARITH
883      `norm(f x) <= B1 * norm(x) /\ norm(x) * B1 < e ==> norm(f x) < e`) THEN
884     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ];
885     MATCH_MP_TAC(REAL_ARITH
886      `norm x <= norm (f x :real^N) / B2 /\ norm(f x) / B2 < e
887       ==> norm x < e`) THEN
888     ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LT_LDIV_EQ]]);;
889
890 add_linear_invariants [OPEN_IN_INJECTIVE_LINEAR_IMAGE];;
891
892 let CLOSED_IN_INJECTIVE_LINEAR_IMAGE = prove
893  (`!f:real^M->real^N s t.
894           linear f /\ (!x y. f x = f y ==> x = y)
895           ==> (closed_in (subtopology euclidean (IMAGE f t)) (IMAGE f s) <=>
896                closed_in (subtopology euclidean t) s)`,
897   REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
898   GEOM_TRANSFORM_TAC[]);;
899
900 add_linear_invariants [CLOSED_IN_INJECTIVE_LINEAR_IMAGE];;
901
902 (* ------------------------------------------------------------------------- *)
903 (* Connectedness.                                                            *)
904 (* ------------------------------------------------------------------------- *)
905
906 let connected = new_definition
907   `connected s <=>
908       ~(?e1 e2. open e1 /\ open e2 /\ s SUBSET (e1 UNION e2) /\
909                 (e1 INTER e2 INTER s = {}) /\
910                 ~(e1 INTER s = {}) /\ ~(e2 INTER s = {}))`;;
911
912 let CONNECTED_CLOSED = prove
913  (`!s:real^N->bool.
914         connected s <=>
915         ~(?e1 e2. closed e1 /\ closed e2 /\ s SUBSET (e1 UNION e2) /\
916                   (e1 INTER e2 INTER s = {}) /\
917                   ~(e1 INTER s = {}) /\ ~(e2 INTER s = {}))`,
918   GEN_TAC THEN REWRITE_TAC[connected] THEN AP_TERM_TAC THEN
919   EQ_TAC THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
920   MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN STRIP_TAC THEN
921   MAP_EVERY EXISTS_TAC [`(:real^N) DIFF v`; `(:real^N) DIFF u`] THEN
922   ASM_REWRITE_TAC[GSYM closed; GSYM OPEN_CLOSED] THEN ASM SET_TAC[]);;
923
924 let CONNECTED_OPEN_IN = prove
925  (`!s. connected s <=>
926            ~(?e1 e2.
927                  open_in (subtopology euclidean s) e1 /\
928                  open_in (subtopology euclidean s) e2 /\
929                  s SUBSET e1 UNION e2 /\
930                  e1 INTER e2 = {} /\
931                  ~(e1 = {}) /\
932                  ~(e2 = {}))`,
933   GEN_TAC THEN REWRITE_TAC[connected; OPEN_IN_OPEN] THEN
934   REWRITE_TAC[LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
935   CONV_TAC(ONCE_DEPTH_CONV UNWIND_CONV) THEN
936   AP_TERM_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
937   SET_TAC[]);;
938
939 let CONNECTED_OPEN_IN_EQ = prove
940  (`!s. connected s <=>
941            ~(?e1 e2.
942                  open_in (subtopology euclidean s) e1 /\
943                  open_in (subtopology euclidean s) e2 /\
944                  e1 UNION e2 = s /\ e1 INTER e2 = {} /\
945                  ~(e1 = {}) /\ ~(e2 = {}))`,
946   GEN_TAC THEN REWRITE_TAC[CONNECTED_OPEN_IN] THEN
947   AP_TERM_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
948   EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[SUBSET_REFL] THEN
949   RULE_ASSUM_TAC(REWRITE_RULE[OPEN_IN_CLOSED_IN_EQ;
950    TOPSPACE_EUCLIDEAN_SUBTOPOLOGY]) THEN
951   ASM SET_TAC[]);;
952
953 let CONNECTED_CLOSED_IN = prove
954  (`!s. connected s <=>
955            ~(?e1 e2.
956                  closed_in (subtopology euclidean s) e1 /\
957                  closed_in (subtopology euclidean s) e2 /\
958                  s SUBSET e1 UNION e2 /\
959                  e1 INTER e2 = {} /\
960                  ~(e1 = {}) /\
961                  ~(e2 = {}))`,
962   GEN_TAC THEN REWRITE_TAC[CONNECTED_CLOSED; CLOSED_IN_CLOSED] THEN
963   REWRITE_TAC[LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
964   CONV_TAC(ONCE_DEPTH_CONV UNWIND_CONV) THEN
965   AP_TERM_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
966   SET_TAC[]);;
967
968 let CONNECTED_CLOSED_IN_EQ = prove
969  (`!s. connected s <=>
970            ~(?e1 e2.
971                  closed_in (subtopology euclidean s) e1 /\
972                  closed_in (subtopology euclidean s) e2 /\
973
974                  e1 UNION e2 = s /\ e1 INTER e2 = {} /\
975                  ~(e1 = {}) /\ ~(e2 = {}))`,
976   GEN_TAC THEN REWRITE_TAC[CONNECTED_CLOSED_IN] THEN
977   AP_TERM_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
978   EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[SUBSET_REFL] THEN
979   RULE_ASSUM_TAC(REWRITE_RULE[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY]) THEN
980   ASM SET_TAC[]);;
981
982 let CONNECTED_CLOPEN = prove
983  (`!s. connected s <=>
984         !t. open_in (subtopology euclidean s) t /\
985             closed_in (subtopology euclidean s) t ==> t = {} \/ t = s`,
986   GEN_TAC THEN REWRITE_TAC[connected; OPEN_IN_OPEN; CLOSED_IN_CLOSED] THEN
987   GEN_REWRITE_TAC (LAND_CONV o RAND_CONV o BINDER_CONV) [GSYM EXISTS_DIFF] THEN
988   ONCE_REWRITE_TAC[TAUT `(~a <=> b) <=> (a <=> ~b)`] THEN
989   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; GSYM CONJ_ASSOC; DE_MORGAN_THM] THEN
990   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c /\ d <=> b /\ a /\ c /\ d`] THEN
991   REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN REWRITE_TAC[GSYM closed] THEN
992   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN AP_TERM_TAC THEN ABS_TAC THEN
993   REWRITE_TAC[LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
994   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN AP_TERM_TAC THEN ABS_TAC THEN
995   REWRITE_TAC[TAUT `(a /\ b) /\ (c /\ d) /\ e <=> a /\ c /\ b /\ d /\ e`] THEN
996   REWRITE_TAC[RIGHT_EXISTS_AND_THM; UNWIND_THM2] THEN
997   AP_TERM_TAC THEN AP_TERM_TAC THEN SET_TAC[]);;
998
999 let CONNECTED_CLOSED_SET = prove
1000  (`!s:real^N->bool.
1001         closed s
1002         ==> (connected s <=>
1003              ~(?e1 e2. closed e1 /\ closed e2 /\ ~(e1 = {}) /\ ~(e2 = {}) /\
1004                        e1 UNION e2 = s /\ e1 INTER e2 = {}))`,
1005   REPEAT STRIP_TAC THEN EQ_TAC THENL
1006    [REWRITE_TAC[CONNECTED_CLOSED; CONTRAPOS_THM] THEN
1007     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
1008     SIMP_TAC[] THEN SET_TAC[];
1009     REWRITE_TAC[CONNECTED_CLOSED_IN; CONTRAPOS_THM; LEFT_IMP_EXISTS_THM] THEN
1010     REWRITE_TAC[CLOSED_IN_CLOSED; LEFT_IMP_EXISTS_THM; IMP_CONJ] THEN
1011     REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN REWRITE_TAC[IMP_IMP] THEN
1012     MAP_EVERY X_GEN_TAC
1013      [`e1:real^N->bool`; `e2:real^N->bool`;
1014       `u:real^N->bool`; `v:real^N->bool`] THEN
1015     STRIP_TAC THEN MAP_EVERY (C UNDISCH_THEN SUBST_ALL_TAC)
1016      [`e1:real^N->bool = s INTER u`;
1017       `e2:real^N->bool = s INTER v`] THEN
1018     MAP_EVERY EXISTS_TAC
1019      [`s INTER u:real^N->bool`; `s INTER v:real^N->bool`] THEN
1020     ASM_SIMP_TAC[CLOSED_INTER] THEN ASM SET_TAC[]]);;
1021
1022 let CONNECTED_OPEN_SET = prove
1023  (`!s:real^N->bool.
1024         open s
1025         ==> (connected s <=>
1026              ~(?e1 e2. open e1 /\ open e2 /\ ~(e1 = {}) /\ ~(e2 = {}) /\
1027                        e1 UNION e2 = s /\ e1 INTER e2 = {}))`,
1028   REPEAT STRIP_TAC THEN EQ_TAC THENL
1029    [REWRITE_TAC[connected; CONTRAPOS_THM] THEN
1030     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
1031     SIMP_TAC[] THEN SET_TAC[];
1032     REWRITE_TAC[CONNECTED_OPEN_IN; CONTRAPOS_THM; LEFT_IMP_EXISTS_THM] THEN
1033     REWRITE_TAC[OPEN_IN_OPEN; LEFT_IMP_EXISTS_THM; IMP_CONJ] THEN
1034     REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN REWRITE_TAC[IMP_IMP] THEN
1035     MAP_EVERY X_GEN_TAC
1036      [`e1:real^N->bool`; `e2:real^N->bool`;
1037       `u:real^N->bool`; `v:real^N->bool`] THEN
1038     STRIP_TAC THEN MAP_EVERY (C UNDISCH_THEN SUBST_ALL_TAC)
1039      [`e1:real^N->bool = s INTER u`;
1040       `e2:real^N->bool = s INTER v`] THEN
1041     MAP_EVERY EXISTS_TAC
1042      [`s INTER u:real^N->bool`; `s INTER v:real^N->bool`] THEN
1043     ASM_SIMP_TAC[OPEN_INTER] THEN ASM SET_TAC[]]);;
1044
1045 let CONNECTED_EMPTY = prove
1046  (`connected {}`,
1047   REWRITE_TAC[connected; INTER_EMPTY]);;
1048
1049 let CONNECTED_SING = prove
1050  (`!a. connected{a}`,
1051   REWRITE_TAC[connected] THEN SET_TAC[]);;
1052
1053 let CONNECTED_UNIONS = prove
1054  (`!P:(real^N->bool)->bool.
1055         (!s. s IN P ==> connected s) /\ ~(INTERS P = {})
1056         ==> connected(UNIONS P)`,
1057   GEN_TAC THEN REWRITE_TAC[connected; NOT_EXISTS_THM] THEN STRIP_TAC THEN
1058   MAP_EVERY X_GEN_TAC [`e1:real^N->bool`; `e2:real^N->bool`] THEN
1059   STRIP_TAC THEN UNDISCH_TAC `~(INTERS P :real^N->bool = {})` THEN
1060   PURE_REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTERS] THEN
1061   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
1062   SUBGOAL_THEN `(a:real^N) IN e1 \/ a IN e2` STRIP_ASSUME_TAC THENL
1063    [ASM SET_TAC[];
1064     UNDISCH_TAC `~(e2 INTER UNIONS P:real^N->bool = {})`;
1065     UNDISCH_TAC `~(e1 INTER UNIONS P:real^N->bool = {})`] THEN
1066   PURE_REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER; IN_UNIONS] THEN
1067   DISCH_THEN(X_CHOOSE_THEN `b:real^N`
1068    (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
1069   DISCH_THEN(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
1070   UNDISCH_TAC `!t:real^N->bool. t IN P ==> a IN t` THEN
1071   DISCH_THEN(MP_TAC o SPEC `s:real^N->bool`) THEN
1072   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
1073   FIRST_X_ASSUM(MP_TAC o SPEC `s:real^N->bool`) THEN
1074   ASM_REWRITE_TAC[] THEN
1075   DISCH_THEN(MP_TAC o SPECL [`e1:real^N->bool`; `e2:real^N->bool`]) THEN
1076   ASM SET_TAC[]);;
1077
1078 let CONNECTED_UNION = prove
1079  (`!s t:real^N->bool.
1080         connected s /\ connected t /\ ~(s INTER t = {})
1081         ==> connected (s UNION t)`,
1082   REWRITE_TAC[GSYM UNIONS_2; GSYM INTERS_2] THEN
1083   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_UNIONS THEN
1084   ASM SET_TAC[]);;
1085
1086 let CONNECTED_DIFF_OPEN_FROM_CLOSED = prove
1087  (`!s t u:real^N->bool.
1088         s SUBSET t /\ t SUBSET u /\
1089         open s /\ closed t /\ connected u /\ connected(t DIFF s)
1090         ==> connected(u DIFF s)`,
1091   REPEAT STRIP_TAC THEN REWRITE_TAC[connected; NOT_EXISTS_THM] THEN
1092   MAP_EVERY X_GEN_TAC [`v:real^N->bool`; `w:real^N->bool`] THEN STRIP_TAC THEN
1093   UNDISCH_TAC `connected(t DIFF s:real^N->bool)` THEN SIMP_TAC[connected] THEN
1094   MAP_EVERY EXISTS_TAC [`v:real^N->bool`; `w:real^N->bool`] THEN
1095   ASM_REWRITE_TAC[] THEN
1096   REPLICATE_TAC 2 (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
1097   POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN
1098   MAP_EVERY (fun t -> SPEC_TAC(t,t)) [`v:real^N->bool`; `w:real^N->bool`] THEN
1099   MATCH_MP_TAC(MESON[]
1100    `(!v w. P v w ==> P w v) /\ (!w v. P v w /\ Q w ==> F)
1101     ==> !w v. P v w ==> ~(Q v) /\ ~(Q w)`) THEN
1102   CONJ_TAC THENL [SIMP_TAC[CONJ_ACI; INTER_ACI; UNION_ACI]; ALL_TAC] THEN
1103   REPEAT STRIP_TAC THEN
1104   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [connected]) THEN SIMP_TAC[] THEN
1105   MAP_EVERY EXISTS_TAC [`v UNION s:real^N->bool`; `w DIFF t:real^N->bool`] THEN
1106   ASM_SIMP_TAC[OPEN_UNION; OPEN_DIFF] THEN ASM SET_TAC[]);;
1107
1108 let CONNECTED_DISJOINT_UNIONS_OPEN_UNIQUE = prove
1109  (`!f:(real^N->bool)->bool f'.
1110          pairwise DISJOINT f /\ pairwise DISJOINT f' /\
1111         (!s. s IN f ==> open s /\ connected s /\ ~(s = {})) /\
1112         (!s. s IN f' ==> open s /\ connected s /\ ~(s = {})) /\
1113         UNIONS f = UNIONS f'
1114         ==> f = f'`,
1115   GEN_REWRITE_TAC (funpow 2 BINDER_CONV o RAND_CONV) [EXTENSION] THEN
1116   MATCH_MP_TAC(MESON[]
1117    `(!s t. P s t ==> P t s) /\ (!s t x. P s t /\ x IN s ==> x IN t)
1118     ==> (!s t. P s t ==> (!x. x IN s <=> x IN t))`) THEN
1119   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
1120   GEN_TAC THEN GEN_TAC THEN X_GEN_TAC `s:real^N->bool` THEN STRIP_TAC THEN
1121   SUBGOAL_THEN
1122    `?t a:real^N. t IN f' /\ a IN s /\ a IN t` STRIP_ASSUME_TAC
1123   THENL [ASM SET_TAC[]; ALL_TAC] THEN
1124   SUBGOAL_THEN `s:real^N->bool = t` (fun th -> ASM_REWRITE_TAC[th]) THEN
1125   REWRITE_TAC[EXTENSION] THEN POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN
1126   MAP_EVERY (fun t -> SPEC_TAC(t,t))
1127    [`s:real^N->bool`; `t:real^N->bool`;
1128     `f:(real^N->bool)->bool`; `f':(real^N->bool)->bool`] THEN
1129   MATCH_MP_TAC(MESON[]
1130    `(!f f' s t. P f f' s t ==> P f' f t s) /\
1131     (!f f' s t x. P f f' s t /\ x IN s ==> x IN t)
1132     ==> (!f' f t s. P f f' s t ==> (!x. x IN s <=> x IN t))`) THEN
1133   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
1134   REPLICATE_TAC 4 GEN_TAC THEN X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
1135   UNDISCH_TAC
1136    `!s:real^N->bool. s IN f ==> open s /\ connected s /\ ~(s = {})` THEN
1137   DISCH_THEN(MP_TAC o SPEC `s:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
1138   STRIP_TAC THEN ASM_CASES_TAC `(b:real^N) IN t` THEN
1139   ASM_REWRITE_TAC[] THEN
1140   UNDISCH_TAC `connected(s:real^N->bool)` THEN
1141   REWRITE_TAC[connected] THEN
1142   MAP_EVERY EXISTS_TAC
1143    [`t:real^N->bool`; `UNIONS(f' DELETE (t:real^N->bool))`] THEN
1144   REPEAT STRIP_TAC THENL
1145    [ASM_SIMP_TAC[];
1146     MATCH_MP_TAC OPEN_UNIONS THEN ASM_SIMP_TAC[IN_DELETE];
1147     REWRITE_TAC[GSYM UNIONS_INSERT] THEN ASM SET_TAC[];
1148     MATCH_MP_TAC(SET_RULE `t INTER u = {} ==> t INTER u INTER s = {}`) THEN
1149     REWRITE_TAC[INTER_UNIONS; EMPTY_UNIONS; FORALL_IN_GSPEC] THEN
1150     REWRITE_TAC[IN_DELETE; GSYM DISJOINT] THEN ASM_MESON_TAC[pairwise];
1151     ASM SET_TAC[];
1152     ASM SET_TAC[]]);;
1153
1154 (* ------------------------------------------------------------------------- *)
1155 (* Sort of induction principle for connected sets.                           *)
1156 (* ------------------------------------------------------------------------- *)
1157
1158 let CONNECTED_INDUCTION = prove
1159  (`!P Q s:real^N->bool.
1160         connected s /\
1161         (!t a. open_in (subtopology euclidean s) t /\ a IN t
1162                ==> ?z. z IN t /\ P z) /\
1163         (!a. a IN s
1164              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
1165                      !x y. x IN t /\ y IN t /\ P x /\ P y /\ Q x ==> Q y)
1166         ==> !a b. a IN s /\ b IN s /\ P a /\ P b /\ Q a ==> Q b`,
1167   REPEAT STRIP_TAC THEN
1168   GEN_REWRITE_TAC I [TAUT `p <=> ~ ~p`] THEN DISCH_TAC THEN
1169   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONNECTED_OPEN_IN]) THEN
1170   REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
1171    [`{b:real^N | ?t. open_in (subtopology euclidean s) t /\ b IN t /\
1172                      !x. x IN t /\ P x ==> Q x}`;
1173     `{b:real^N | ?t. open_in (subtopology euclidean s) t /\ b IN t /\
1174                      !x. x IN t /\ P x ==> ~(Q x)}`] THEN
1175   REPEAT CONJ_TAC THENL
1176    [ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN
1177     X_GEN_TAC `c:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
1178     MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[];
1179     ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN
1180     X_GEN_TAC `c:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
1181     MATCH_MP_TAC MONO_EXISTS THEN ASM SET_TAC[];
1182     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNION] THEN
1183     X_GEN_TAC `c:real^N` THEN DISCH_TAC THEN
1184     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N`) THEN ASM SET_TAC[];
1185     REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY; IN_ELIM_THM] THEN
1186     X_GEN_TAC `c:real^N` THEN DISCH_THEN(CONJUNCTS_THEN2
1187      (X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC)
1188      (X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC)) THEN
1189     FIRST_X_ASSUM(MP_TAC o SPECL [`t INTER u:real^N->bool`; `c:real^N`]) THEN
1190     ASM_SIMP_TAC[OPEN_IN_INTER] THEN ASM SET_TAC[];
1191     ASM SET_TAC[];
1192     ASM SET_TAC[]]);;
1193
1194 let CONNECTED_EQUIVALENCE_RELATION_GEN = prove
1195  (`!P R s:real^N->bool.
1196         connected s /\
1197         (!x y. R x y ==> R y x) /\
1198         (!x y z. R x y /\ R y z ==> R x z) /\
1199         (!t a. open_in (subtopology euclidean s) t /\ a IN t
1200                ==> ?z. z IN t /\ P z) /\
1201         (!a. a IN s
1202              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
1203                      !x y. x IN t /\ y IN t /\ P x /\ P y ==> R x y)
1204         ==> !a b. a IN s /\ b IN s /\ P a /\ P b ==> R a b`,
1205   REPEAT GEN_TAC THEN STRIP_TAC THEN
1206   SUBGOAL_THEN
1207    `!a:real^N. a IN s /\ P a
1208                ==> !b c. b IN s /\ c IN s /\ P b /\ P c /\ R a b ==> R a c`
1209   MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
1210   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC CONNECTED_INDUCTION THEN
1211   ASM_MESON_TAC[]);;
1212
1213 let CONNECTED_INDUCTION_SIMPLE = prove
1214  (`!P s:real^N->bool.
1215         connected s /\
1216         (!a. a IN s
1217              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
1218                      !x y. x IN t /\ y IN t /\ P x ==> P y)
1219         ==> !a b. a IN s /\ b IN s /\ P a ==> P b`,
1220   MP_TAC(ISPEC `\x:real^N. T` CONNECTED_INDUCTION) THEN
1221   REWRITE_TAC[] THEN
1222   REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN MESON_TAC[]);;
1223
1224 let CONNECTED_EQUIVALENCE_RELATION = prove
1225  (`!R s:real^N->bool.
1226         connected s /\
1227         (!x y. R x y ==> R y x) /\
1228         (!x y z. R x y /\ R y z ==> R x z) /\
1229         (!a. a IN s
1230              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
1231                      !x. x IN t ==> R a x)
1232         ==> !a b. a IN s /\ b IN s ==> R a b`,
1233   REPEAT GEN_TAC THEN STRIP_TAC THEN
1234   SUBGOAL_THEN
1235    `!a:real^N. a IN s ==> !b c. b IN s /\ c IN s /\ R a b ==> R a c`
1236   MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
1237   GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC CONNECTED_INDUCTION_SIMPLE THEN
1238   ASM_MESON_TAC[]);;
1239
1240 (* ------------------------------------------------------------------------- *)
1241 (* Limit points.                                                             *)
1242 (* ------------------------------------------------------------------------- *)
1243
1244 parse_as_infix ("limit_point_of",(12,"right"));;
1245
1246 let limit_point_of = new_definition
1247  `x limit_point_of s <=>
1248         !t. x IN t /\ open t ==> ?y. ~(y = x) /\ y IN s /\ y IN t`;;
1249
1250 let LIMPT_SUBSET = prove
1251  (`!x s t. x limit_point_of s /\ s SUBSET t ==> x limit_point_of t`,
1252   REWRITE_TAC[limit_point_of; SUBSET] THEN MESON_TAC[]);;
1253
1254 let LIMPT_APPROACHABLE = prove
1255  (`!x s. x limit_point_of s <=>
1256                 !e. &0 < e ==> ?x'. x' IN s /\ ~(x' = x) /\ dist(x',x) < e`,
1257   REPEAT GEN_TAC THEN REWRITE_TAC[limit_point_of] THEN
1258   MESON_TAC[open_def; DIST_SYM; OPEN_BALL; CENTRE_IN_BALL; IN_BALL]);;
1259
1260 let LIMPT_APPROACHABLE_LE = prove
1261  (`!x s. x limit_point_of s <=>
1262                 !e. &0 < e ==> ?x'. x' IN s /\ ~(x' = x) /\ dist(x',x) <= e`,
1263   REPEAT GEN_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN
1264   MATCH_MP_TAC(TAUT `(~a <=> ~b) ==> (a <=> b)`) THEN
1265   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
1266   REWRITE_TAC[TAUT `~(a /\ b /\ c) <=> c ==> ~(a /\ b)`; APPROACHABLE_LT_LE]);;
1267
1268 let LIMPT_UNIV = prove
1269  (`!x:real^N. x limit_point_of UNIV`,
1270   GEN_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE; IN_UNIV] THEN
1271   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1272   SUBGOAL_THEN `?c:real^N. norm(c) = e / &2` CHOOSE_TAC THENL
1273    [ASM_SIMP_TAC[VECTOR_CHOOSE_SIZE; REAL_HALF; REAL_LT_IMP_LE];
1274     ALL_TAC] THEN
1275   EXISTS_TAC `x + c:real^N` THEN
1276   REWRITE_TAC[dist; VECTOR_EQ_ADDR] THEN ASM_REWRITE_TAC[VECTOR_ADD_SUB] THEN
1277   SUBGOAL_THEN `&0 < e / &2 /\ e / &2 < e`
1278    (fun th -> ASM_MESON_TAC[th; NORM_0; REAL_LT_REFL]) THEN
1279   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
1280   UNDISCH_TAC `&0 < e` THEN REAL_ARITH_TAC);;
1281
1282 let CLOSED_LIMPT = prove
1283  (`!s. closed s <=> !x. x limit_point_of s ==> x IN s`,
1284   REWRITE_TAC[closed] THEN ONCE_REWRITE_TAC[OPEN_SUBOPEN] THEN
1285   REWRITE_TAC[limit_point_of; IN_DIFF; IN_UNIV; SUBSET] THEN MESON_TAC[]);;
1286
1287 let LIMPT_EMPTY = prove
1288  (`!x. ~(x limit_point_of {})`,
1289   REWRITE_TAC[LIMPT_APPROACHABLE; NOT_IN_EMPTY] THEN MESON_TAC[REAL_LT_01]);;
1290
1291 let NO_LIMIT_POINT_IMP_CLOSED = prove
1292  (`!s. ~(?x. x limit_point_of s) ==> closed s`,
1293   MESON_TAC[CLOSED_LIMPT]);;
1294
1295 let CLOSED_POSITIVE_ORTHANT = prove
1296  (`closed {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
1297                           ==> &0 <= x$i}`,
1298   REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE] THEN
1299   REWRITE_TAC[IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
1300   X_GEN_TAC `i:num` THEN STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
1301   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `--(x:real^N $ i)`) THEN
1302   ASM_REWRITE_TAC[REAL_LT_RNEG; REAL_ADD_LID; NOT_EXISTS_THM] THEN
1303   X_GEN_TAC `y:real^N` THEN
1304   MATCH_MP_TAC(TAUT `(a ==> ~c) ==> ~(a /\ b /\ c)`) THEN DISCH_TAC THEN
1305   MATCH_MP_TAC(REAL_ARITH `!b. abs x <= b /\ b <= a ==> ~(a + x < &0)`) THEN
1306   EXISTS_TAC `abs((y - x :real^N)$i)` THEN
1307   ASM_SIMP_TAC[dist; COMPONENT_LE_NORM] THEN
1308   ASM_SIMP_TAC[VECTOR_SUB_COMPONENT; REAL_ARITH
1309    `x < &0 /\ &0 <= y ==> abs(x) <= abs(y - x)`]);;
1310
1311 let FINITE_SET_AVOID = prove
1312  (`!a:real^N s. FINITE s
1313                 ==> ?d. &0 < d /\ !x. x IN s /\ ~(x = a) ==> d <= dist(a,x)`,
1314   GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
1315   REWRITE_TAC[NOT_IN_EMPTY] THEN
1316   CONJ_TAC THENL [MESON_TAC[REAL_LT_01]; ALL_TAC] THEN
1317   MAP_EVERY X_GEN_TAC [`x:real^N`; `s:real^N->bool`] THEN
1318   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
1319   FIRST_X_ASSUM(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
1320   ASM_CASES_TAC `x:real^N = a` THEN REWRITE_TAC[IN_INSERT] THENL
1321    [ASM_MESON_TAC[]; ALL_TAC] THEN
1322   EXISTS_TAC `min d (dist(a:real^N,x))` THEN
1323   ASM_REWRITE_TAC[REAL_LT_MIN; GSYM DIST_NZ; REAL_MIN_LE] THEN
1324   ASM_MESON_TAC[REAL_LE_REFL]);;
1325
1326 let LIMIT_POINT_FINITE = prove
1327  (`!s a. FINITE s ==> ~(a limit_point_of s)`,
1328   REWRITE_TAC[LIMPT_APPROACHABLE; GSYM REAL_NOT_LE] THEN
1329   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM; REAL_NOT_LE;
1330     REAL_NOT_LT; TAUT `~(a /\ b /\ c) <=> a /\ b ==> ~c`] THEN
1331   MESON_TAC[FINITE_SET_AVOID; DIST_SYM]);;
1332
1333 let LIMPT_SING = prove
1334  (`!x y:real^N. ~(x limit_point_of {y})`,
1335   SIMP_TAC[LIMIT_POINT_FINITE; FINITE_SING]);;
1336
1337 let LIMIT_POINT_UNION = prove
1338  (`!s t x:real^N. x limit_point_of (s UNION t) <=>
1339                   x limit_point_of s \/ x limit_point_of t`,
1340   REPEAT GEN_TAC THEN EQ_TAC THENL
1341    [ALL_TAC; MESON_TAC[LIMPT_SUBSET; SUBSET_UNION]] THEN
1342   REWRITE_TAC[LIMPT_APPROACHABLE; IN_UNION] THEN DISCH_TAC THEN
1343   MATCH_MP_TAC(TAUT `(~a ==> b) ==> a \/ b`) THEN
1344   REWRITE_TAC[NOT_FORALL_THM; LEFT_IMP_EXISTS_THM; NOT_IMP] THEN
1345   X_GEN_TAC `e:real` THEN STRIP_TAC THEN X_GEN_TAC `d:real` THEN DISCH_TAC THEN
1346   FIRST_X_ASSUM(MP_TAC o SPEC `min d e`) THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
1347   ASM_MESON_TAC[]);;
1348
1349 let LIMPT_INSERT = prove
1350  (`!s x y:real^N. x limit_point_of (y INSERT s) <=> x limit_point_of s`,
1351   ONCE_REWRITE_TAC[SET_RULE `y INSERT s = {y} UNION s`] THEN
1352   REWRITE_TAC[LIMIT_POINT_UNION] THEN
1353   SIMP_TAC[FINITE_SING; LIMIT_POINT_FINITE]);;
1354
1355 let LIMPT_OF_LIMPTS = prove
1356  (`!x:real^N s.
1357      x limit_point_of {y | y limit_point_of s} ==> x limit_point_of s`,
1358   REWRITE_TAC[LIMPT_APPROACHABLE; IN_ELIM_THM] THEN REPEAT GEN_TAC THEN
1359   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1360   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
1361   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
1362   FIRST_X_ASSUM(MP_TAC o SPEC `dist(y:real^N,x)`) THEN
1363   ASM_SIMP_TAC[DIST_POS_LT] THEN MATCH_MP_TAC MONO_EXISTS THEN
1364   GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1365   REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
1366
1367 let CLOSED_LIMPTS = prove
1368  (`!s. closed {x:real^N | x limit_point_of s}`,
1369   REWRITE_TAC[CLOSED_LIMPT; IN_ELIM_THM; LIMPT_OF_LIMPTS]);;
1370
1371 let DISCRETE_IMP_CLOSED = prove
1372  (`!s:real^N->bool e.
1373         &0 < e /\
1374         (!x y. x IN s /\ y IN s /\ norm(y - x) < e ==> y = x)
1375         ==> closed s`,
1376   REPEAT STRIP_TAC THEN
1377   SUBGOAL_THEN `!x:real^N. ~(x limit_point_of s)`
1378     (fun th -> MESON_TAC[th; CLOSED_LIMPT]) THEN
1379   GEN_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN DISCH_TAC THEN
1380   FIRST_ASSUM(MP_TAC o SPEC `e / &2`) THEN
1381   REWRITE_TAC[REAL_HALF; ASSUME `&0 < e`] THEN
1382   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
1383   FIRST_X_ASSUM(MP_TAC o SPEC `min (e / &2) (dist(x:real^N,y))`) THEN
1384   ASM_SIMP_TAC[REAL_LT_MIN; DIST_POS_LT; REAL_HALF] THEN
1385   DISCH_THEN(X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC) THEN
1386   FIRST_X_ASSUM(MP_TAC o SPECL [`y:real^N`; `z:real^N`]) THEN
1387   ASM_REWRITE_TAC[] THEN ASM_NORM_ARITH_TAC);;
1388
1389 let LIMPT_OF_UNIV = prove
1390  (`!x. x limit_point_of (:real^N)`,
1391   GEN_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE; IN_UNIV] THEN
1392   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1393   MP_TAC(ISPECL [`x:real^N`; `e / &2`] VECTOR_CHOOSE_DIST) THEN
1394   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
1395   POP_ASSUM MP_TAC THEN CONV_TAC NORM_ARITH);;
1396
1397 let LIMPT_OF_OPEN_IN = prove
1398  (`!s t x:real^N.
1399         open_in (subtopology euclidean s) t /\ x limit_point_of s /\ x IN t
1400         ==> x limit_point_of t`,
1401   REWRITE_TAC[open_in; SUBSET; LIMPT_APPROACHABLE] THEN
1402   REPEAT GEN_TAC THEN STRIP_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1403   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
1404   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
1405   FIRST_X_ASSUM(MP_TAC o SPEC `min d e / &2`) THEN
1406   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
1407   GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THEN
1408   TRY(FIRST_X_ASSUM MATCH_MP_TAC) THEN ASM_REWRITE_TAC[] THEN
1409   ASM_REAL_ARITH_TAC);;
1410
1411 let LIMPT_OF_OPEN = prove
1412  (`!s x:real^N. open s /\ x IN s ==> x limit_point_of s`,
1413   REWRITE_TAC[OPEN_IN] THEN ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_UNIV] THEN
1414   MESON_TAC[LIMPT_OF_OPEN_IN; LIMPT_OF_UNIV]);;
1415
1416 let OPEN_IN_SING = prove
1417  (`!s a. open_in (subtopology euclidean s) {a} <=>
1418          a IN s /\ ~(a limit_point_of s)`,
1419   REWRITE_TAC[open_in; LIMPT_APPROACHABLE; SING_SUBSET; IN_SING] THEN
1420   REWRITE_TAC[FORALL_UNWIND_THM2] THEN MESON_TAC[]);;
1421
1422 (* ------------------------------------------------------------------------- *)
1423 (* Interior of a set.                                                        *)
1424 (* ------------------------------------------------------------------------- *)
1425
1426 let interior = new_definition
1427   `interior s = {x | ?t. open t /\ x IN t /\ t SUBSET s}`;;
1428
1429 let INTERIOR_EQ = prove
1430  (`!s. (interior s = s) <=> open s`,
1431   GEN_TAC THEN REWRITE_TAC[EXTENSION; interior; IN_ELIM_THM] THEN
1432   GEN_REWRITE_TAC RAND_CONV [OPEN_SUBOPEN] THEN MESON_TAC[SUBSET]);;
1433
1434 let INTERIOR_OPEN = prove
1435  (`!s. open s ==> (interior s = s)`,
1436   MESON_TAC[INTERIOR_EQ]);;
1437
1438 let INTERIOR_EMPTY = prove
1439  (`interior {} = {}`,
1440   SIMP_TAC[INTERIOR_OPEN; OPEN_EMPTY]);;
1441
1442 let INTERIOR_UNIV = prove
1443  (`interior(:real^N) = (:real^N)`,
1444   SIMP_TAC[INTERIOR_OPEN; OPEN_UNIV]);;
1445
1446 let OPEN_INTERIOR = prove
1447  (`!s. open(interior s)`,
1448   GEN_TAC THEN REWRITE_TAC[interior] THEN GEN_REWRITE_TAC I [OPEN_SUBOPEN] THEN
1449   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
1450
1451 let INTERIOR_INTERIOR = prove
1452  (`!s. interior(interior s) = interior s`,
1453   MESON_TAC[INTERIOR_EQ; OPEN_INTERIOR]);;
1454
1455 let INTERIOR_SUBSET = prove
1456  (`!s. (interior s) SUBSET s`,
1457   REWRITE_TAC[SUBSET; interior; IN_ELIM_THM] THEN MESON_TAC[]);;
1458
1459 let SUBSET_INTERIOR = prove
1460  (`!s t. s SUBSET t ==> (interior s) SUBSET (interior t)`,
1461   REWRITE_TAC[interior; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
1462
1463 let INTERIOR_MAXIMAL = prove
1464  (`!s t. t SUBSET s /\ open t ==> t SUBSET (interior s)`,
1465   REWRITE_TAC[interior; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
1466
1467 let INTERIOR_MAXIMAL_EQ = prove
1468  (`!s t:real^N->bool. open s ==> (s SUBSET interior t <=> s SUBSET t)`,
1469   MESON_TAC[INTERIOR_MAXIMAL; SUBSET_TRANS; INTERIOR_SUBSET]);;
1470
1471 let INTERIOR_UNIQUE = prove
1472  (`!s t. t SUBSET s /\ open t /\ (!t'. t' SUBSET s /\ open t' ==> t' SUBSET t)
1473          ==> (interior s = t)`,
1474   MESON_TAC[SUBSET_ANTISYM; INTERIOR_MAXIMAL; INTERIOR_SUBSET;
1475             OPEN_INTERIOR]);;
1476
1477 let IN_INTERIOR = prove
1478  (`!x s. x IN interior s <=> ?e. &0 < e /\ ball(x,e) SUBSET s`,
1479   REWRITE_TAC[interior; IN_ELIM_THM] THEN
1480   MESON_TAC[OPEN_CONTAINS_BALL; SUBSET_TRANS; CENTRE_IN_BALL; OPEN_BALL]);;
1481
1482 let OPEN_SUBSET_INTERIOR = prove
1483  (`!s t. open s ==> (s SUBSET interior t <=> s SUBSET t)`,
1484   MESON_TAC[INTERIOR_MAXIMAL; INTERIOR_SUBSET; SUBSET_TRANS]);;
1485
1486 let INTERIOR_INTER = prove
1487  (`!s t:real^N->bool. interior(s INTER t) = interior s INTER interior t`,
1488   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
1489    [REWRITE_TAC[SUBSET_INTER] THEN CONJ_TAC THEN
1490     MATCH_MP_TAC SUBSET_INTERIOR THEN REWRITE_TAC[INTER_SUBSET];
1491     MATCH_MP_TAC INTERIOR_MAXIMAL THEN SIMP_TAC[OPEN_INTER; OPEN_INTERIOR] THEN
1492     MATCH_MP_TAC(SET_RULE
1493       `s SUBSET s' /\ t SUBSET t' ==> s INTER t SUBSET s' INTER t'`) THEN
1494     REWRITE_TAC[INTERIOR_SUBSET]]);;
1495
1496 let INTERIOR_FINITE_INTERS = prove
1497  (`!s:(real^N->bool)->bool.
1498         FINITE s ==> interior(INTERS s) = INTERS(IMAGE interior s)`,
1499   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
1500   REWRITE_TAC[INTERS_0; INTERS_INSERT; INTERIOR_UNIV; IMAGE_CLAUSES] THEN
1501   SIMP_TAC[INTERIOR_INTER]);;
1502
1503 let INTERIOR_INTERS_SUBSET = prove
1504  (`!f. interior(INTERS f) SUBSET INTERS (IMAGE interior f)`,
1505   REWRITE_TAC[SUBSET; IN_INTERIOR; IN_INTERS; FORALL_IN_IMAGE] THEN
1506   MESON_TAC[]);;
1507
1508 let UNION_INTERIOR_SUBSET = prove
1509  (`!s t:real^N->bool.
1510         interior s UNION interior t SUBSET interior(s UNION t)`,
1511   SIMP_TAC[INTERIOR_MAXIMAL_EQ; OPEN_UNION; OPEN_INTERIOR] THEN
1512   REPEAT GEN_TAC THEN MATCH_MP_TAC(SET_RULE
1513    `s SUBSET s' /\ t SUBSET t' ==> (s UNION t) SUBSET (s' UNION t')`) THEN
1514   REWRITE_TAC[INTERIOR_SUBSET]);;
1515
1516 let INTERIOR_EQ_EMPTY = prove
1517  (`!s:real^N->bool. interior s = {} <=> !t. open t /\ t SUBSET s ==> t = {}`,
1518   MESON_TAC[INTERIOR_MAXIMAL_EQ; SUBSET_EMPTY;
1519             OPEN_INTERIOR; INTERIOR_SUBSET]);;
1520
1521 let INTERIOR_EQ_EMPTY_ALT = prove
1522  (`!s:real^N->bool.
1523         interior s = {} <=>
1524         !t. open t /\ ~(t = {}) ==> ~(t DIFF s = {})`,
1525   GEN_TAC THEN REWRITE_TAC[INTERIOR_EQ_EMPTY] THEN SET_TAC[]);;
1526
1527 let INTERIOR_LIMIT_POINT = prove
1528  (`!s x:real^N. x IN interior s ==> x limit_point_of s`,
1529   REPEAT GEN_TAC THEN
1530   REWRITE_TAC[IN_INTERIOR; IN_ELIM_THM; SUBSET; IN_BALL] THEN
1531   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
1532   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `d:real` THEN
1533   DISCH_TAC THEN
1534   MP_TAC(ISPECL [`x:real^N`; `min d e / &2`] VECTOR_CHOOSE_DIST) THEN
1535   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
1536   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
1537   REPEAT CONJ_TAC THENL
1538    [FIRST_X_ASSUM MATCH_MP_TAC;
1539     CONV_TAC (RAND_CONV SYM_CONV) THEN REWRITE_TAC[GSYM DIST_EQ_0];
1540     ONCE_REWRITE_TAC[DIST_SYM]] THEN
1541   ASM_REAL_ARITH_TAC);;
1542
1543 let INTERIOR_SING = prove
1544  (`!a:real^N. interior {a} = {}`,
1545   REWRITE_TAC[EXTENSION; NOT_IN_EMPTY] THEN
1546   MESON_TAC[INTERIOR_LIMIT_POINT; LIMPT_SING]);;
1547
1548 let INTERIOR_CLOSED_UNION_EMPTY_INTERIOR = prove
1549  (`!s t:real^N->bool.
1550         closed(s) /\ interior(t) = {}
1551         ==> interior(s UNION t) = interior(s)`,
1552   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
1553   SIMP_TAC[SUBSET_INTERIOR; SUBSET_UNION] THEN
1554   REWRITE_TAC[SUBSET; IN_INTERIOR; IN_INTER; IN_UNION] THEN
1555   X_GEN_TAC `x:real^N` THEN MATCH_MP_TAC MONO_EXISTS THEN
1556   X_GEN_TAC `e:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1557   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
1558   SUBGOAL_THEN `(y:real^N) limit_point_of s`
1559    (fun th -> ASM_MESON_TAC[CLOSED_LIMPT; th]) THEN
1560   REWRITE_TAC[IN_INTERIOR; NOT_IN_EMPTY; LIMPT_APPROACHABLE] THEN
1561   X_GEN_TAC `d:real` THEN DISCH_TAC THEN
1562   SUBGOAL_THEN
1563    `?z:real^N. ~(z IN t) /\ ~(z = y) /\ dist(z,y) < d /\ dist(x,z) < e`
1564    (fun th -> ASM_MESON_TAC[th; IN_BALL]) THEN
1565   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_BALL]) THEN
1566   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
1567   REWRITE_TAC[IN_INTERIOR; NOT_IN_EMPTY; NOT_EXISTS_THM] THEN
1568   ABBREV_TAC `k = min d (e - dist(x:real^N,y))` THEN
1569   SUBGOAL_THEN `&0 < k` ASSUME_TAC THENL
1570    [ASM_ARITH_TAC; ALL_TAC] THEN
1571   SUBGOAL_THEN `?w:real^N. dist(y,w) = k / &2` CHOOSE_TAC THENL
1572    [ASM_SIMP_TAC[VECTOR_CHOOSE_DIST; REAL_HALF; REAL_LT_IMP_LE]; ALL_TAC] THEN
1573   DISCH_THEN(MP_TAC o SPECL [`w:real^N`; `k / &4`]) THEN
1574   ASM_SIMP_TAC[SUBSET; NOT_FORALL_THM; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH;
1575                NOT_IMP; IN_BALL] THEN
1576   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `z:real^N` THEN
1577   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN ASM_REWRITE_TAC[] THEN
1578   ASM_NORM_ARITH_TAC);;
1579
1580 let INTERIOR_UNION_EQ_EMPTY = prove
1581  (`!s t:real^N->bool.
1582         closed s \/ closed t
1583         ==> (interior(s UNION t) = {} <=>
1584              interior s = {} /\ interior t = {})`,
1585   REPEAT GEN_TAC THEN DISCH_TAC THEN EQ_TAC THENL
1586    [ASM_MESON_TAC[SUBSET_UNION; SUBSET_INTERIOR; SUBSET_EMPTY];
1587     ASM_MESON_TAC[UNION_COMM; INTERIOR_CLOSED_UNION_EMPTY_INTERIOR]]);;
1588
1589 let INTERIOR_UNIONS_OPEN_SUBSETS = prove
1590  (`!s:real^N->bool. UNIONS {t | open t /\ t SUBSET s} = interior s`,
1591   GEN_TAC THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC INTERIOR_UNIQUE THEN
1592   SIMP_TAC[OPEN_UNIONS; IN_ELIM_THM] THEN SET_TAC[]);;
1593
1594 (* ------------------------------------------------------------------------- *)
1595 (* Closure of a set.                                                         *)
1596 (* ------------------------------------------------------------------------- *)
1597
1598 let closure = new_definition
1599   `closure s = s UNION {x | x limit_point_of s}`;;
1600
1601 let CLOSURE_INTERIOR = prove
1602  (`!s:real^N->bool. closure s = UNIV DIFF (interior (UNIV DIFF s))`,
1603   REWRITE_TAC[EXTENSION; closure; IN_UNION; IN_DIFF; IN_UNIV; interior;
1604               IN_ELIM_THM; limit_point_of; SUBSET] THEN
1605   MESON_TAC[]);;
1606
1607 let INTERIOR_CLOSURE = prove
1608  (`!s:real^N->bool. interior s = UNIV DIFF (closure (UNIV DIFF s))`,
1609   let lemma = prove(`!s t. UNIV DIFF (UNIV DIFF t) = t`,SET_TAC[]) in
1610   REWRITE_TAC[CLOSURE_INTERIOR; lemma]);;
1611
1612 let CLOSED_CLOSURE = prove
1613  (`!s. closed(closure s)`,
1614   let lemma = prove(`UNIV DIFF (UNIV DIFF s) = s`,SET_TAC[]) in
1615   REWRITE_TAC[closed; CLOSURE_INTERIOR; lemma; OPEN_INTERIOR]);;
1616
1617 let CLOSURE_HULL = prove
1618  (`!s. closure s = closed hull s`,
1619   GEN_TAC THEN MATCH_MP_TAC(GSYM HULL_UNIQUE) THEN
1620   REWRITE_TAC[CLOSED_CLOSURE; SUBSET] THEN
1621   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM; CLOSED_LIMPT] THEN
1622   MESON_TAC[limit_point_of]);;
1623
1624 let CLOSURE_EQ = prove
1625  (`!s. (closure s = s) <=> closed s`,
1626   SIMP_TAC[CLOSURE_HULL; HULL_EQ; CLOSED_INTERS]);;
1627
1628 let CLOSURE_CLOSED = prove
1629  (`!s. closed s ==> (closure s = s)`,
1630   MESON_TAC[CLOSURE_EQ]);;
1631
1632 let CLOSURE_CLOSURE = prove
1633  (`!s. closure(closure s) = closure s`,
1634   REWRITE_TAC[CLOSURE_HULL; HULL_HULL]);;
1635
1636 let CLOSURE_SUBSET = prove
1637  (`!s. s SUBSET (closure s)`,
1638   REWRITE_TAC[CLOSURE_HULL; HULL_SUBSET]);;
1639
1640 let SUBSET_CLOSURE = prove
1641  (`!s t. s SUBSET t ==> (closure s) SUBSET (closure t)`,
1642   REWRITE_TAC[CLOSURE_HULL; HULL_MONO]);;
1643
1644 let CLOSURE_UNION = prove
1645  (`!s t:real^N->bool. closure(s UNION t) = closure s UNION closure t`,
1646   REWRITE_TAC[LIMIT_POINT_UNION; closure] THEN SET_TAC[]);;
1647
1648 let CLOSURE_INTER_SUBSET = prove
1649  (`!s t. closure(s INTER t) SUBSET closure(s) INTER closure(t)`,
1650   REPEAT GEN_TAC THEN REWRITE_TAC[SUBSET_INTER] THEN
1651   CONJ_TAC THEN MATCH_MP_TAC SUBSET_CLOSURE THEN SET_TAC[]);;
1652
1653 let CLOSURE_INTERS_SUBSET = prove
1654  (`!f. closure(INTERS f) SUBSET INTERS(IMAGE closure f)`,
1655   REWRITE_TAC[SET_RULE `s SUBSET INTERS f <=> !t. t IN f ==> s SUBSET t`] THEN
1656   REWRITE_TAC[FORALL_IN_IMAGE] THEN REPEAT STRIP_TAC THEN
1657   MATCH_MP_TAC SUBSET_CLOSURE THEN ASM SET_TAC[]);;
1658
1659 let CLOSURE_MINIMAL = prove
1660  (`!s t. s SUBSET t /\ closed t ==> (closure s) SUBSET t`,
1661   REWRITE_TAC[HULL_MINIMAL; CLOSURE_HULL]);;
1662
1663 let CLOSURE_MINIMAL_EQ = prove
1664  (`!s t:real^N->bool. closed t ==> (closure s SUBSET t <=> s SUBSET t)`,
1665   MESON_TAC[SUBSET_TRANS; CLOSURE_SUBSET; CLOSURE_MINIMAL]);;
1666
1667 let CLOSURE_UNIQUE = prove
1668  (`!s t. s SUBSET t /\ closed t /\
1669          (!t'. s SUBSET t' /\ closed t' ==> t SUBSET t')
1670          ==> (closure s = t)`,
1671   REWRITE_TAC[CLOSURE_HULL; HULL_UNIQUE]);;
1672
1673 let CLOSURE_EMPTY = prove
1674  (`closure {} = {}`,
1675   SIMP_TAC[CLOSURE_CLOSED; CLOSED_EMPTY]);;
1676
1677 let CLOSURE_UNIV = prove
1678  (`closure(:real^N) = (:real^N)`,
1679   SIMP_TAC[CLOSURE_CLOSED; CLOSED_UNIV]);;
1680
1681 let CLOSURE_UNIONS = prove
1682  (`!f. FINITE f ==> closure(UNIONS f) = UNIONS {closure s | s IN f}`,
1683   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
1684   REWRITE_TAC[UNIONS_0; UNIONS_INSERT; SET_RULE `{f x | x IN {}} = {}`;
1685      SET_RULE `{f x | x IN a INSERT s} = (f a) INSERT {f x | x IN s}`] THEN
1686   SIMP_TAC[CLOSURE_EMPTY; CLOSURE_UNION]);;
1687
1688 let CLOSURE_EQ_EMPTY = prove
1689  (`!s. closure s = {} <=> s = {}`,
1690   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CLOSURE_EMPTY] THEN
1691   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> t = {} ==> s = {}`) THEN
1692   REWRITE_TAC[CLOSURE_SUBSET]);;
1693
1694 let CLOSURE_SUBSET_EQ = prove
1695  (`!s:real^N->bool. closure s SUBSET s <=> closed s`,
1696   GEN_TAC THEN REWRITE_TAC[GSYM CLOSURE_EQ] THEN
1697   MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[]);;
1698
1699 let OPEN_INTER_CLOSURE_EQ_EMPTY = prove
1700  (`!s t:real^N->bool.
1701         open s ==> (s INTER (closure t) = {} <=> s INTER t = {})`,
1702   REPEAT STRIP_TAC THEN EQ_TAC THENL
1703    [MP_TAC(ISPEC `t:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[]; ALL_TAC] THEN
1704   DISCH_TAC THEN REWRITE_TAC[CLOSURE_INTERIOR] THEN
1705   MATCH_MP_TAC(SET_RULE `s SUBSET t ==> s INTER (UNIV DIFF t) = {}`) THEN
1706   ASM_SIMP_TAC[OPEN_SUBSET_INTERIOR] THEN ASM SET_TAC[]);;
1707
1708 let OPEN_INTER_CLOSURE_SUBSET = prove
1709  (`!s t:real^N->bool.
1710         open s ==> (s INTER (closure t)) SUBSET closure(s INTER t)`,
1711   REPEAT STRIP_TAC THEN
1712   SIMP_TAC[SUBSET; IN_INTER; closure; IN_UNION; IN_ELIM_THM] THEN
1713   X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
1714   DISJ2_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN
1715   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
1716   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [open_def]) THEN
1717   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
1718   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
1719   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIMPT_APPROACHABLE]) THEN
1720   DISCH_THEN(MP_TAC o SPEC `min d e`) THEN
1721   ASM_REWRITE_TAC[REAL_LT_MIN; IN_INTER] THEN
1722   MATCH_MP_TAC MONO_EXISTS THEN ASM_MESON_TAC[]);;
1723
1724 let CLOSURE_OPEN_INTER_SUPERSET = prove
1725  (`!s t:real^N->bool.
1726         open s /\ s SUBSET closure t ==> closure(s INTER t) = closure s`,
1727   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
1728   SIMP_TAC[SUBSET_CLOSURE; INTER_SUBSET] THEN
1729   MATCH_MP_TAC CLOSURE_MINIMAL THEN REWRITE_TAC[CLOSED_CLOSURE] THEN
1730   W(MP_TAC o PART_MATCH (rand o rand)
1731     OPEN_INTER_CLOSURE_SUBSET o rand o snd) THEN
1732   ASM_REWRITE_TAC[] THEN
1733   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] SUBSET_TRANS) THEN ASM SET_TAC[]);;
1734
1735 let CLOSURE_COMPLEMENT = prove
1736  (`!s:real^N->bool. closure(UNIV DIFF s) = UNIV DIFF interior(s)`,
1737   REWRITE_TAC[SET_RULE `s = UNIV DIFF t <=> UNIV DIFF s = t`] THEN
1738   REWRITE_TAC[GSYM INTERIOR_CLOSURE]);;
1739
1740 let INTERIOR_COMPLEMENT = prove
1741  (`!s:real^N->bool. interior(UNIV DIFF s) = UNIV DIFF closure(s)`,
1742   REWRITE_TAC[SET_RULE `s = UNIV DIFF t <=> UNIV DIFF s = t`] THEN
1743   REWRITE_TAC[GSYM CLOSURE_INTERIOR]);;
1744
1745 let CONNECTED_INTERMEDIATE_CLOSURE = prove
1746  (`!s t:real^N->bool.
1747         connected s /\ s SUBSET t /\ t SUBSET closure s ==> connected t`,
1748   REPEAT GEN_TAC THEN REWRITE_TAC[connected; NOT_EXISTS_THM] THEN
1749   STRIP_TAC THEN
1750   MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN STRIP_TAC THEN
1751   FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^N->bool`; `v:real^N->bool`]) THEN
1752   ASM_REWRITE_TAC[] THEN ASSUME_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN
1753   REPLICATE_TAC 2 (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
1754   REWRITE_TAC[GSYM DE_MORGAN_THM] THEN STRIP_TAC THENL
1755    [SUBGOAL_THEN `(closure s) SUBSET ((:real^N) DIFF u)` MP_TAC THENL
1756      [MATCH_MP_TAC CLOSURE_MINIMAL THEN ASM_REWRITE_TAC[GSYM OPEN_CLOSED];
1757       ALL_TAC];
1758     SUBGOAL_THEN `(closure s) SUBSET ((:real^N) DIFF v)` MP_TAC THENL
1759      [MATCH_MP_TAC CLOSURE_MINIMAL THEN ASM_REWRITE_TAC[GSYM OPEN_CLOSED];
1760       ALL_TAC]] THEN
1761   ASM SET_TAC[]);;
1762
1763 let CONNECTED_CLOSURE = prove
1764  (`!s:real^N->bool. connected s ==> connected(closure s)`,
1765   MESON_TAC[CONNECTED_INTERMEDIATE_CLOSURE; CLOSURE_SUBSET; SUBSET_REFL]);;
1766
1767 let CONNECTED_UNION_STRONG = prove
1768  (`!s t:real^N->bool.
1769         connected s /\ connected t /\ ~(closure s INTER t = {})
1770         ==> connected(s UNION t)`,
1771   REPEAT STRIP_TAC THEN
1772   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
1773   DISCH_THEN(X_CHOOSE_TAC `p:real^N`) THEN
1774   SUBGOAL_THEN `s UNION t = ((p:real^N) INSERT s) UNION t` SUBST1_TAC THENL
1775    [ASM SET_TAC[]; ALL_TAC] THEN
1776   MATCH_MP_TAC CONNECTED_UNION THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
1777    [MATCH_MP_TAC CONNECTED_INTERMEDIATE_CLOSURE THEN
1778     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
1779     MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
1780     ASM SET_TAC[]]);;
1781
1782 let INTERIOR_DIFF = prove
1783  (`!s t. interior(s DIFF t) = interior(s) DIFF closure(t)`,
1784   ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
1785   REWRITE_TAC[INTERIOR_INTER; CLOSURE_INTERIOR] THEN SET_TAC[]);;
1786
1787 let LIMPT_OF_CLOSURE = prove
1788  (`!x:real^N s. x limit_point_of closure s <=> x limit_point_of s`,
1789   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM; LIMIT_POINT_UNION] THEN
1790   REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT `(q ==> p) ==> (p \/ q <=> p)`) THEN
1791   REWRITE_TAC[LIMPT_OF_LIMPTS]);;
1792
1793 let CLOSED_IN_LIMPT = prove
1794  (`!s t. closed_in (subtopology euclidean t) s <=>
1795          s SUBSET t /\ !x:real^N. x limit_point_of s /\ x IN t ==> x IN s`,
1796   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN_CLOSED] THEN EQ_TAC THENL
1797    [DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
1798     ASM_SIMP_TAC[IN_INTER] THEN
1799     ASM_MESON_TAC[CLOSED_LIMPT; LIMPT_SUBSET; INTER_SUBSET];
1800     STRIP_TAC THEN EXISTS_TAC `closure s :real^N->bool` THEN
1801     REWRITE_TAC[CLOSED_CLOSURE] THEN REWRITE_TAC[closure] THEN
1802     ASM SET_TAC[]]);;
1803
1804 let INTERIOR_CLOSURE_IDEMP = prove
1805  (`!s:real^N->bool.
1806         interior(closure(interior(closure s))) = interior(closure s)`,
1807   GEN_TAC THEN MATCH_MP_TAC INTERIOR_UNIQUE THEN
1808   ASM_MESON_TAC[OPEN_INTERIOR; CLOSURE_SUBSET; CLOSURE_CLOSURE; SUBSET_TRANS;
1809                 OPEN_SUBSET_INTERIOR;SUBSET_CLOSURE; INTERIOR_SUBSET]);;
1810
1811 let CLOSURE_INTERIOR_IDEMP = prove
1812  (`!s:real^N->bool.
1813         closure(interior(closure(interior s))) = closure(interior s)`,
1814   GEN_TAC THEN
1815   ONCE_REWRITE_TAC[SET_RULE `s = t <=> UNIV DIFF s = UNIV DIFF t`] THEN
1816   REWRITE_TAC[GSYM INTERIOR_COMPLEMENT; GSYM CLOSURE_COMPLEMENT] THEN
1817   REWRITE_TAC[INTERIOR_CLOSURE_IDEMP]);;
1818
1819 let NOWHERE_DENSE_UNION = prove
1820  (`!s t:real^N->bool.
1821         interior(closure(s UNION t)) = {} <=>
1822         interior(closure s) = {} /\ interior(closure t) = {}`,
1823   SIMP_TAC[CLOSURE_UNION; INTERIOR_UNION_EQ_EMPTY; CLOSED_CLOSURE]);;
1824
1825 let NOWHERE_DENSE = prove
1826  (`!s:real^N->bool.
1827         interior(closure s) = {} <=>
1828         !t. open t /\ ~(t = {})
1829             ==> ?u. open u /\ ~(u = {}) /\ u SUBSET t /\ u INTER s = {}`,
1830   GEN_TAC THEN REWRITE_TAC[INTERIOR_EQ_EMPTY_ALT] THEN EQ_TAC THEN
1831   DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THENL
1832    [EXISTS_TAC `t DIFF closure s:real^N->bool` THEN
1833     ASM_SIMP_TAC[OPEN_DIFF; CLOSED_CLOSURE] THEN
1834     MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN SET_TAC[];
1835     FIRST_X_ASSUM(MP_TAC o SPEC `t:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
1836     DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
1837     MP_TAC(ISPECL [`u:real^N->bool`; `s:real^N->bool`]
1838         OPEN_INTER_CLOSURE_EQ_EMPTY) THEN
1839     ASM SET_TAC[]]);;
1840
1841 (* ------------------------------------------------------------------------- *)
1842 (* Frontier (aka boundary).                                                  *)
1843 (* ------------------------------------------------------------------------- *)
1844
1845 let frontier = new_definition
1846   `frontier s = (closure s) DIFF (interior s)`;;
1847
1848 let FRONTIER_CLOSED = prove
1849  (`!s. closed(frontier s)`,
1850   SIMP_TAC[frontier; CLOSED_DIFF; CLOSED_CLOSURE; OPEN_INTERIOR]);;
1851
1852 let FRONTIER_CLOSURES = prove
1853  (`!s:real^N->bool. frontier s = (closure s) INTER (closure(UNIV DIFF s))`,
1854   let lemma = prove(`s DIFF (UNIV DIFF t) = s INTER t`,SET_TAC[]) in
1855   REWRITE_TAC[frontier; INTERIOR_CLOSURE; lemma]);;
1856
1857 let FRONTIER_STRADDLE = prove
1858  (`!a:real^N s.
1859      a IN frontier s <=>
1860         !e. &0 < e ==> (?x. x IN s /\ dist(a,x) < e) /\
1861                        (?x. ~(x IN s) /\ dist(a,x) < e)`,
1862   REPEAT GEN_TAC THEN REWRITE_TAC[FRONTIER_CLOSURES; IN_INTER] THEN
1863   REWRITE_TAC[closure; IN_UNION; IN_ELIM_THM; limit_point_of;
1864               IN_UNIV; IN_DIFF] THEN
1865   ASM_MESON_TAC[IN_BALL; SUBSET; OPEN_CONTAINS_BALL;
1866                 CENTRE_IN_BALL; OPEN_BALL; DIST_REFL]);;
1867
1868 let FRONTIER_SUBSET_CLOSED = prove
1869  (`!s. closed s ==> (frontier s) SUBSET s`,
1870   MESON_TAC[frontier; CLOSURE_CLOSED; SUBSET_DIFF]);;
1871
1872 let FRONTIER_EMPTY = prove
1873  (`frontier {} = {}`,
1874   REWRITE_TAC[frontier; CLOSURE_EMPTY; EMPTY_DIFF]);;
1875
1876 let FRONTIER_UNIV = prove
1877  (`frontier(:real^N) = {}`,
1878   REWRITE_TAC[frontier; CLOSURE_UNIV; INTERIOR_UNIV] THEN SET_TAC[]);;
1879
1880 let FRONTIER_SUBSET_EQ = prove
1881  (`!s:real^N->bool. (frontier s) SUBSET s <=> closed s`,
1882   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[FRONTIER_SUBSET_CLOSED] THEN
1883   REWRITE_TAC[frontier] THEN
1884   DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
1885    `s DIFF t SUBSET u ==> t SUBSET u ==> s SUBSET u`)) THEN
1886   REWRITE_TAC[INTERIOR_SUBSET; CLOSURE_SUBSET_EQ]);;
1887
1888 let FRONTIER_COMPLEMENT = prove
1889  (`!s:real^N->bool. frontier(UNIV DIFF s) = frontier s`,
1890   REWRITE_TAC[frontier; CLOSURE_COMPLEMENT; INTERIOR_COMPLEMENT] THEN
1891   SET_TAC[]);;
1892
1893 let FRONTIER_DISJOINT_EQ = prove
1894  (`!s. (frontier s) INTER s = {} <=> open s`,
1895   ONCE_REWRITE_TAC[GSYM FRONTIER_COMPLEMENT; OPEN_CLOSED] THEN
1896   REWRITE_TAC[GSYM FRONTIER_SUBSET_EQ] THEN SET_TAC[]);;
1897
1898 let FRONTIER_INTER_SUBSET = prove
1899  (`!s t. frontier(s INTER t) SUBSET frontier(s) UNION frontier(t)`,
1900   REPEAT GEN_TAC THEN REWRITE_TAC[frontier; INTERIOR_INTER] THEN
1901   MATCH_MP_TAC(SET_RULE
1902    `cst SUBSET cs INTER ct
1903     ==> cst DIFF (s INTER t) SUBSET (cs DIFF s) UNION (ct DIFF t)`) THEN
1904   REWRITE_TAC[CLOSURE_INTER_SUBSET]);;
1905
1906 let FRONTIER_UNION_SUBSET = prove
1907  (`!s t:real^N->bool. frontier(s UNION t) SUBSET frontier s UNION frontier t`,
1908   ONCE_REWRITE_TAC[GSYM FRONTIER_COMPLEMENT] THEN
1909   REWRITE_TAC[SET_RULE `u DIFF (s UNION t) = (u DIFF s) INTER (u DIFF t)`] THEN
1910   REWRITE_TAC[FRONTIER_INTER_SUBSET]);;
1911
1912 let FRONTIER_INTERIORS = prove
1913  (`!s. frontier s = (:real^N) DIFF interior(s) DIFF interior((:real^N) DIFF s)`,
1914   REWRITE_TAC[frontier; CLOSURE_INTERIOR] THEN SET_TAC[]);;
1915
1916 let FRONTIER_FRONTIER_SUBSET = prove
1917  (`!s:real^N->bool. frontier(frontier s) SUBSET frontier s`,
1918   GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [frontier] THEN
1919   SIMP_TAC[CLOSURE_CLOSED; FRONTIER_CLOSED] THEN SET_TAC[]);;
1920
1921 let INTERIOR_FRONTIER = prove
1922  (`!s:real^N->bool.
1923         interior(frontier s) = interior(closure s) DIFF closure(interior s)`,
1924   ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
1925   REWRITE_TAC[GSYM INTERIOR_COMPLEMENT; GSYM INTERIOR_INTER; frontier] THEN
1926   GEN_TAC THEN AP_TERM_TAC THEN SET_TAC[]);;
1927
1928 let INTERIOR_FRONTIER_EMPTY = prove
1929  (`!s:real^N->bool. open s \/ closed s ==> interior(frontier s) = {}`,
1930   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[INTERIOR_FRONTIER] THEN
1931   ASM_SIMP_TAC[CLOSURE_CLOSED; INTERIOR_OPEN] THEN
1932   REWRITE_TAC[SET_RULE `s DIFF t = {} <=> s SUBSET t`] THEN
1933   REWRITE_TAC[INTERIOR_SUBSET; CLOSURE_SUBSET]);;
1934
1935 let FRONTIER_FRONTIER_FRONTIER = prove
1936  (`!s:real^N->bool. frontier(frontier(frontier s)) = frontier(frontier s)`,
1937   GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [frontier] THEN
1938   SIMP_TAC[CLOSURE_CLOSED; FRONTIER_CLOSED; INTERIOR_FRONTIER_EMPTY] THEN
1939   SET_TAC[]);;
1940
1941 let CONNECTED_INTER_FRONTIER = prove
1942  (`!s t:real^N->bool.
1943         connected s /\ ~(s INTER t = {}) /\ ~(s DIFF t = {})
1944         ==> ~(s INTER frontier t = {})`,
1945   REWRITE_TAC[FRONTIER_INTERIORS] THEN REPEAT STRIP_TAC THEN
1946   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONNECTED_OPEN_IN]) THEN
1947   REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
1948    [`s INTER interior t:real^N->bool`;
1949     `s INTER (interior((:real^N) DIFF t))`] THEN
1950   SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_INTERIOR] THEN
1951   MAP_EVERY (MP_TAC o C ISPEC INTERIOR_SUBSET)
1952    [`t:real^N->bool`; `(:real^N) DIFF t`] THEN
1953   ASM SET_TAC[]);;
1954
1955 let INTERIOR_CLOSED_EQ_EMPTY_AS_FRONTIER = prove
1956  (`!s:real^N->bool.
1957         closed s /\ interior s = {} <=> ?t. open t /\ s = frontier t`,
1958   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THENL
1959    [EXISTS_TAC `(:real^N) DIFF s` THEN
1960     ASM_SIMP_TAC[OPEN_DIFF; OPEN_UNIV; FRONTIER_COMPLEMENT] THEN
1961     ASM_SIMP_TAC[frontier; CLOSURE_CLOSED; DIFF_EMPTY];
1962     ASM_SIMP_TAC[FRONTIER_CLOSED; INTERIOR_FRONTIER_EMPTY]]);;
1963
1964 let FRONTIER_UNION = prove
1965  (`!s t:real^N->bool.
1966         closure s INTER closure t = {}
1967         ==> frontier(s UNION t) = frontier(s) UNION frontier(t)`,
1968   REPEAT STRIP_TAC THEN
1969   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[FRONTIER_UNION_SUBSET] THEN
1970   GEN_REWRITE_TAC RAND_CONV [frontier] THEN
1971   REWRITE_TAC[CLOSURE_UNION] THEN MATCH_MP_TAC(SET_RULE
1972    `(fs SUBSET cs /\ ft SUBSET ct) /\ k INTER fs = {} /\ k INTER ft = {}
1973     ==> (fs UNION ft) SUBSET (cs UNION ct) DIFF k`) THEN
1974   CONJ_TAC THENL [REWRITE_TAC[frontier] THEN SET_TAC[]; ALL_TAC] THEN
1975   CONJ_TAC THENL
1976    [ALL_TAC;
1977     ONCE_REWRITE_TAC[UNION_COMM] THEN
1978     RULE_ASSUM_TAC(ONCE_REWRITE_RULE[INTER_COMM])] THEN
1979   FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
1980    `s INTER t = {} ==> s' SUBSET s /\ s' INTER u INTER (UNIV DIFF t) = {}
1981       ==> u INTER s' = {}`)) THEN
1982   REWRITE_TAC[frontier; SUBSET_DIFF; GSYM INTERIOR_COMPLEMENT] THEN
1983   REWRITE_TAC[GSYM INTERIOR_INTER; SET_RULE
1984    `(s UNION t) INTER (UNIV DIFF t) = s DIFF t`] THEN
1985   MATCH_MP_TAC(SET_RULE
1986     `ti SUBSET si ==> (c DIFF si) INTER ti = {}`) THEN
1987   SIMP_TAC[SUBSET_INTERIOR; SUBSET_DIFF]);;
1988
1989 let CLOSURE_UNION_FRONTIER = prove
1990  (`!s:real^N->bool. closure s = s UNION frontier s`,
1991   GEN_TAC THEN REWRITE_TAC[frontier] THEN
1992   MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET) THEN
1993   MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN
1994   SET_TAC[]);;
1995
1996 (* ------------------------------------------------------------------------- *)
1997 (* A variant of nets (slightly non-standard but good for our purposes).      *)
1998 (* ------------------------------------------------------------------------- *)
1999
2000 let net_tybij = new_type_definition "net" ("mk_net","netord")
2001  (prove
2002    (`?g:A->A->bool. !x y. (!z. g z x ==> g z y) \/ (!z. g z y ==> g z x)`,
2003     EXISTS_TAC `\x:A y:A. F` THEN REWRITE_TAC[]));;
2004
2005 let NET = prove
2006  (`!n x y. (!z. netord n z x ==> netord n z y) \/
2007            (!z. netord n z y ==> netord n z x)`,
2008    REWRITE_TAC[net_tybij; ETA_AX]);;
2009
2010 let OLDNET = prove
2011  (`!n x y. netord n x x /\ netord n y y
2012            ==> ?z. netord n z z /\
2013                    !w. netord n w z ==> netord n w x /\ netord n w y`,
2014   MESON_TAC[NET]);;
2015
2016 let NET_DILEMMA = prove
2017  (`!net. (?a. (?x. netord net x a) /\ (!x. netord net x a ==> P x)) /\
2018          (?b. (?x. netord net x b) /\ (!x. netord net x b ==> Q x))
2019          ==> ?c. (?x. netord net x c) /\ (!x. netord net x c ==> P x /\ Q x)`,
2020   MESON_TAC[NET]);;
2021
2022 (* ------------------------------------------------------------------------- *)
2023 (* Common nets and the "within" modifier for nets.                           *)
2024 (* ------------------------------------------------------------------------- *)
2025
2026 parse_as_infix("within",(14,"right"));;
2027 parse_as_infix("in_direction",(14,"right"));;
2028
2029 let at = new_definition
2030   `at a = mk_net(\x y. &0 < dist(x,a) /\ dist(x,a) <= dist(y,a))`;;
2031
2032 let at_infinity = new_definition
2033   `at_infinity = mk_net(\x y. norm(x) >= norm(y))`;;
2034
2035 let sequentially = new_definition
2036   `sequentially = mk_net(\m:num n. m >= n)`;;
2037
2038 let within = new_definition
2039   `net within s = mk_net(\x y. netord net x y /\ x IN s)`;;
2040
2041 let in_direction = new_definition
2042   `a in_direction v = (at a) within {b | ?c. &0 <= c /\ (b - a = c % v)}`;;
2043
2044 (* ------------------------------------------------------------------------- *)
2045 (* Prove that they are all nets.                                             *)
2046 (* ------------------------------------------------------------------------- *)
2047
2048 let NET_PROVE_TAC[def] =
2049   REWRITE_TAC[GSYM FUN_EQ_THM; def] THEN
2050   REWRITE_TAC[ETA_AX] THEN
2051   ASM_SIMP_TAC[GSYM(CONJUNCT2 net_tybij)];;
2052
2053 let AT = prove
2054  (`!a:real^N x y.
2055         netord(at a) x y <=> &0 < dist(x,a) /\ dist(x,a) <= dist(y,a)`,
2056   GEN_TAC THEN NET_PROVE_TAC[at] THEN
2057   MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS; REAL_LET_TRANS]);;
2058
2059 let AT_INFINITY = prove
2060  (`!x y. netord at_infinity x y <=> norm(x) >= norm(y)`,
2061   NET_PROVE_TAC[at_infinity] THEN
2062   REWRITE_TAC[real_ge; REAL_LE_REFL] THEN
2063   MESON_TAC[REAL_LE_TOTAL; REAL_LE_REFL; REAL_LE_TRANS]);;
2064
2065 let SEQUENTIALLY = prove
2066  (`!m n. netord sequentially m n <=> m >= n`,
2067   NET_PROVE_TAC[sequentially] THEN REWRITE_TAC[GE; LE_REFL] THEN
2068   MESON_TAC[LE_CASES; LE_REFL; LE_TRANS]);;
2069
2070 let WITHIN = prove
2071  (`!n s x y. netord(n within s) x y <=> netord n x y /\ x IN s`,
2072   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[within; GSYM FUN_EQ_THM] THEN
2073   REWRITE_TAC[GSYM(CONJUNCT2 net_tybij); ETA_AX] THEN
2074   MESON_TAC[NET]);;
2075
2076 let IN_DIRECTION = prove
2077  (`!a v x y. netord(a in_direction v) x y <=>
2078                 &0 < dist(x,a) /\ dist(x,a) <= dist(y,a) /\
2079                  ?c. &0 <= c /\ (x - a = c % v)`,
2080   REWRITE_TAC[WITHIN; AT; in_direction; IN_ELIM_THM; CONJ_ACI]);;
2081
2082 let WITHIN_UNIV = prove
2083  (`!x:real^N. at x within UNIV = at x`,
2084   REWRITE_TAC[within; at; IN_UNIV] THEN REWRITE_TAC[ETA_AX; net_tybij]);;
2085
2086 let WITHIN_WITHIN = prove
2087  (`!net s t. (net within s) within t = net within (s INTER t)`,
2088   ONCE_REWRITE_TAC[within] THEN
2089   REWRITE_TAC[WITHIN; IN_INTER; GSYM CONJ_ASSOC]);;
2090
2091 (* ------------------------------------------------------------------------- *)
2092 (* Identify trivial limits, where we can't approach arbitrarily closely.     *)
2093 (* ------------------------------------------------------------------------- *)
2094
2095 let trivial_limit = new_definition
2096   `trivial_limit net <=>
2097      (!a:A b. a = b) \/
2098      ?a:A b. ~(a = b) /\ !x. ~(netord(net) x a) /\ ~(netord(net) x b)`;;
2099
2100 let TRIVIAL_LIMIT_WITHIN = prove
2101  (`!a:real^N. trivial_limit (at a within s) <=> ~(a limit_point_of s)`,
2102   REWRITE_TAC[trivial_limit; LIMPT_APPROACHABLE_LE; WITHIN; AT; DIST_NZ] THEN
2103   REPEAT GEN_TAC THEN EQ_TAC THENL
2104    [DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL
2105      [MESON_TAC[REAL_LT_01; REAL_LT_REFL; VECTOR_CHOOSE_DIST;
2106                 DIST_REFL; REAL_LT_IMP_LE];
2107       DISCH_THEN(X_CHOOSE_THEN `b:real^N` (X_CHOOSE_THEN `c:real^N`
2108         STRIP_ASSUME_TAC)) THEN
2109       SUBGOAL_THEN `&0 < dist(a,b:real^N) \/ &0 < dist(a,c:real^N)` MP_TAC THEN
2110       ASM_MESON_TAC[DIST_TRIANGLE; DIST_SYM; GSYM DIST_NZ; GSYM DIST_EQ_0;
2111                     REAL_ARITH `x <= &0 + &0 ==> ~(&0 < x)`]];
2112     REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; LEFT_IMP_EXISTS_THM] THEN
2113     X_GEN_TAC `e:real` THEN DISCH_TAC THEN DISJ2_TAC THEN
2114     EXISTS_TAC `a:real^N` THEN
2115     SUBGOAL_THEN `?b:real^N. dist(a,b) = e` MP_TAC THENL
2116      [ASM_SIMP_TAC[VECTOR_CHOOSE_DIST; REAL_LT_IMP_LE]; ALL_TAC] THEN
2117     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN
2118     DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
2119     ASM_MESON_TAC[REAL_NOT_LE; DIST_REFL; DIST_NZ; DIST_SYM]]);;
2120
2121 let TRIVIAL_LIMIT_AT = prove
2122  (`!a. ~(trivial_limit (at a))`,
2123   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
2124   REWRITE_TAC[TRIVIAL_LIMIT_WITHIN; LIMPT_UNIV]);;
2125
2126 let TRIVIAL_LIMIT_AT_INFINITY = prove
2127  (`~(trivial_limit at_infinity)`,
2128   REWRITE_TAC[trivial_limit; AT_INFINITY; real_ge] THEN
2129   MESON_TAC[REAL_LE_REFL; VECTOR_CHOOSE_SIZE; REAL_LT_01; REAL_LT_LE]);;
2130
2131 let TRIVIAL_LIMIT_SEQUENTIALLY = prove
2132  (`~(trivial_limit sequentially)`,
2133   REWRITE_TAC[trivial_limit; SEQUENTIALLY] THEN
2134   MESON_TAC[GE_REFL; NOT_SUC]);;
2135
2136 let LIM_WITHIN_CLOSED_TRIVIAL = prove
2137  (`!a s. closed s /\ ~(a IN s) ==> trivial_limit (at a within s)`,
2138   REWRITE_TAC[TRIVIAL_LIMIT_WITHIN] THEN MESON_TAC[CLOSED_LIMPT]);;
2139
2140 let NONTRIVIAL_LIMIT_WITHIN = prove
2141  (`!net s. trivial_limit net ==> trivial_limit(net within s)`,
2142   REWRITE_TAC[trivial_limit; WITHIN] THEN MESON_TAC[]);;
2143
2144 (* ------------------------------------------------------------------------- *)
2145 (* Some property holds "sufficiently close" to the limit point.              *)
2146 (* ------------------------------------------------------------------------- *)
2147
2148 let eventually = new_definition
2149  `eventually p net <=>
2150         trivial_limit net \/
2151         ?y. (?x. netord net x y) /\ (!x. netord net x y ==> p x)`;;
2152
2153 let EVENTUALLY_HAPPENS = prove
2154  (`!net p. eventually p net ==> trivial_limit net \/ ?x. p x`,
2155   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2156
2157 let EVENTUALLY_WITHIN_LE = prove
2158  (`!s a:real^M p.
2159      eventually p (at a within s) <=>
2160         ?d. &0 < d /\ !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) <= d ==> p(x)`,
2161   REWRITE_TAC[eventually; AT; WITHIN; TRIVIAL_LIMIT_WITHIN] THEN
2162   REWRITE_TAC[LIMPT_APPROACHABLE_LE; DIST_NZ] THEN
2163   REPEAT GEN_TAC THEN EQ_TAC THENL [MESON_TAC[REAL_LTE_TRANS]; ALL_TAC] THEN
2164   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
2165   MATCH_MP_TAC(TAUT `(a ==> b) ==> ~a \/ b`) THEN DISCH_TAC THEN
2166   SUBGOAL_THEN `?b:real^M. dist(a,b) = d` MP_TAC THENL
2167    [ASM_SIMP_TAC[VECTOR_CHOOSE_DIST; REAL_LT_IMP_LE]; ALL_TAC] THEN
2168   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^M` THEN
2169   DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
2170   ASM_MESON_TAC[REAL_NOT_LE; DIST_REFL; DIST_NZ; DIST_SYM]);;
2171
2172 let EVENTUALLY_WITHIN = prove
2173  (`!s a:real^M p.
2174      eventually p (at a within s) <=>
2175         ?d. &0 < d /\ !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) < d ==> p(x)`,
2176   REWRITE_TAC[EVENTUALLY_WITHIN_LE] THEN
2177   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> c ==> a /\ b ==> d`] THEN
2178   REWRITE_TAC[APPROACHABLE_LT_LE]);;
2179
2180 let EVENTUALLY_AT = prove
2181  (`!a p. eventually p (at a) <=>
2182          ?d. &0 < d /\ !x. &0 < dist(x,a) /\ dist(x,a) < d ==> p(x)`,
2183   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
2184   REWRITE_TAC[EVENTUALLY_WITHIN; IN_UNIV]);;
2185
2186 let EVENTUALLY_SEQUENTIALLY = prove
2187  (`!p. eventually p sequentially <=> ?N. !n. N <= n ==> p n`,
2188   REWRITE_TAC[eventually; SEQUENTIALLY; GE; LE_REFL;
2189     TRIVIAL_LIMIT_SEQUENTIALLY] THEN  MESON_TAC[LE_REFL]);;
2190
2191 let EVENTUALLY_AT_INFINITY = prove
2192  (`!p. eventually p at_infinity <=> ?b. !x. norm(x) >= b ==> p x`,
2193   REWRITE_TAC[eventually; AT_INFINITY; TRIVIAL_LIMIT_AT_INFINITY] THEN
2194   REPEAT GEN_TAC THEN EQ_TAC THENL [MESON_TAC[REAL_LE_REFL]; ALL_TAC] THEN
2195   MESON_TAC[real_ge; REAL_LE_REFL; VECTOR_CHOOSE_SIZE;
2196     REAL_ARITH `&0 <= b \/ (!x. x >= &0 ==> x >= b)`]);;
2197
2198 let ALWAYS_EVENTUALLY = prove
2199  (`(!x. p x) ==> eventually p net`,
2200   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[eventually; trivial_limit] THEN
2201   MESON_TAC[]);;
2202
2203 (* ------------------------------------------------------------------------- *)
2204 (* Combining theorems for "eventually".                                      *)
2205 (* ------------------------------------------------------------------------- *)
2206
2207 let EVENTUALLY_AND = prove
2208  (`!net:(A net) p q.
2209         eventually (\x. p x /\ q x) net <=>
2210         eventually p net /\ eventually q net`,
2211   REPEAT GEN_TAC THEN REWRITE_TAC[eventually] THEN
2212   ASM_CASES_TAC `trivial_limit(net:(A net))` THEN ASM_REWRITE_TAC[] THEN
2213   EQ_TAC THEN SIMP_TAC[NET_DILEMMA] THEN MESON_TAC[]);;
2214
2215 let EVENTUALLY_MONO = prove
2216  (`!net:(A net) p q.
2217         (!x. p x ==> q x) /\ eventually p net
2218         ==> eventually q net`,
2219   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2220
2221 let EVENTUALLY_MP = prove
2222  (`!net:(A net) p q.
2223         eventually (\x. p x ==> q x) net /\ eventually p net
2224         ==> eventually q net`,
2225   REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
2226   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2227
2228 let EVENTUALLY_FALSE = prove
2229  (`!net. eventually (\x. F) net <=> trivial_limit net`,
2230   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2231
2232 let EVENTUALLY_TRUE = prove
2233  (`!net. eventually (\x. T) net <=> T`,
2234   REWRITE_TAC[eventually; trivial_limit] THEN MESON_TAC[]);;
2235
2236 let NOT_EVENTUALLY = prove
2237  (`!net p. (!x. ~(p x)) /\ ~(trivial_limit net) ==> ~(eventually p net)`,
2238   REWRITE_TAC[eventually] THEN MESON_TAC[]);;
2239
2240 let EVENTUALLY_FORALL = prove
2241  (`!net:(A net) p s:B->bool.
2242         FINITE s /\ ~(s = {})
2243         ==> (eventually (\x. !a. a IN s ==> p a x) net <=>
2244              !a. a IN s ==> eventually (p a) net)`,
2245   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
2246   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
2247   REWRITE_TAC[FORALL_IN_INSERT; EVENTUALLY_AND; ETA_AX] THEN
2248   MAP_EVERY X_GEN_TAC [`b:B`; `t:B->bool`] THEN
2249   ASM_CASES_TAC `t:B->bool = {}` THEN
2250   ASM_SIMP_TAC[NOT_IN_EMPTY; EVENTUALLY_TRUE]);;
2251
2252 let FORALL_EVENTUALLY = prove
2253  (`!net:(A net) p s:B->bool.
2254         FINITE s /\ ~(s = {})
2255         ==> ((!a. a IN s ==> eventually (p a) net) <=>
2256              eventually (\x. !a. a IN s ==> p a x) net)`,
2257   SIMP_TAC[EVENTUALLY_FORALL]);;
2258
2259 (* ------------------------------------------------------------------------- *)
2260 (* Limits, defined as vacuously true when the limit is trivial.              *)
2261 (* ------------------------------------------------------------------------- *)
2262
2263 parse_as_infix("-->",(12,"right"));;
2264
2265 let tendsto = new_definition
2266   `(f --> l) net <=> !e. &0 < e ==> eventually (\x. dist(f(x),l) < e) net`;;
2267
2268 let lim = new_definition
2269  `lim net f = @l. (f --> l) net`;;
2270
2271 let LIM = prove
2272  (`(f --> l) net <=>
2273         trivial_limit net \/
2274         !e. &0 < e ==> ?y. (?x. netord(net) x y) /\
2275                            !x. netord(net) x y ==> dist(f(x),l) < e`,
2276   REWRITE_TAC[tendsto; eventually] THEN MESON_TAC[]);;
2277
2278 (* ------------------------------------------------------------------------- *)
2279 (* Show that they yield usual definitions in the various cases.              *)
2280 (* ------------------------------------------------------------------------- *)
2281
2282 let LIM_WITHIN_LE = prove
2283  (`!f:real^M->real^N l a s.
2284         (f --> l)(at a within s) <=>
2285            !e. &0 < e ==> ?d. &0 < d /\
2286                               !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) <= d
2287                                    ==> dist(f(x),l) < e`,
2288   REWRITE_TAC[tendsto; EVENTUALLY_WITHIN_LE]);;
2289
2290 let LIM_WITHIN = prove
2291  (`!f:real^M->real^N l a s.
2292       (f --> l) (at a within s) <=>
2293         !e. &0 < e
2294             ==> ?d. &0 < d /\
2295                     !x. x IN s /\ &0 < dist(x,a) /\ dist(x,a) < d
2296                     ==> dist(f(x),l) < e`,
2297   REWRITE_TAC[tendsto; EVENTUALLY_WITHIN] THEN MESON_TAC[]);;
2298
2299 let LIM_AT = prove
2300  (`!f l:real^N a:real^M.
2301       (f --> l) (at a) <=>
2302               !e. &0 < e
2303                   ==> ?d. &0 < d /\ !x. &0 < dist(x,a) /\ dist(x,a) < d
2304                           ==> dist(f(x),l) < e`,
2305   REWRITE_TAC[tendsto; EVENTUALLY_AT] THEN MESON_TAC[]);;
2306
2307 let LIM_AT_INFINITY = prove
2308  (`!f l. (f --> l) at_infinity <=>
2309                !e. &0 < e ==> ?b. !x. norm(x) >= b ==> dist(f(x),l) < e`,
2310   REWRITE_TAC[tendsto; EVENTUALLY_AT_INFINITY] THEN MESON_TAC[]);;
2311
2312 let LIM_SEQUENTIALLY = prove
2313  (`!s l. (s --> l) sequentially <=>
2314           !e. &0 < e ==> ?N. !n. N <= n ==> dist(s(n),l) < e`,
2315   REWRITE_TAC[tendsto; EVENTUALLY_SEQUENTIALLY] THEN MESON_TAC[]);;
2316
2317 let LIM_EVENTUALLY = prove
2318  (`!net f l. eventually (\x. f x = l) net ==> (f --> l) net`,
2319   REWRITE_TAC[eventually; LIM] THEN MESON_TAC[DIST_REFL]);;
2320
2321 (* ------------------------------------------------------------------------- *)
2322 (* The expected monotonicity property.                                       *)
2323 (* ------------------------------------------------------------------------- *)
2324
2325 let LIM_WITHIN_EMPTY = prove
2326  (`!f l x. (f --> l) (at x within {})`,
2327   REWRITE_TAC[LIM_WITHIN; NOT_IN_EMPTY] THEN MESON_TAC[REAL_LT_01]);;
2328
2329 let LIM_WITHIN_SUBSET = prove
2330  (`!f l a s.
2331     (f --> l) (at a within s) /\ t SUBSET s ==> (f --> l) (at a within t)`,
2332   REWRITE_TAC[LIM_WITHIN; SUBSET] THEN MESON_TAC[]);;
2333
2334 let LIM_UNION = prove
2335  (`!f x l s t.
2336         (f --> l) (at x within s) /\ (f --> l) (at x within t)
2337         ==> (f --> l) (at x within (s UNION t))`,
2338   REPEAT GEN_TAC THEN REWRITE_TAC[LIM_WITHIN; IN_UNION] THEN
2339   REWRITE_TAC[AND_FORALL_THM] THEN MATCH_MP_TAC MONO_FORALL THEN
2340   X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_SIMP_TAC[] THEN
2341   DISCH_THEN(CONJUNCTS_THEN2
2342    (X_CHOOSE_TAC `d1:real`) (X_CHOOSE_TAC `d2:real`)) THEN
2343   EXISTS_TAC `min d1 d2` THEN ASM_MESON_TAC[REAL_LT_MIN]);;
2344
2345 let LIM_UNION_UNIV = prove
2346  (`!f x l s t.
2347         (f --> l) (at x within s) /\ (f --> l) (at x within t) /\
2348         s UNION t = (:real^N)
2349         ==> (f --> l) (at x)`,
2350   MESON_TAC[LIM_UNION; WITHIN_UNIV]);;
2351
2352 (* ------------------------------------------------------------------------- *)
2353 (* Composition of limits.                                                    *)
2354 (* ------------------------------------------------------------------------- *)
2355
2356 let LIM_COMPOSE_WITHIN = prove
2357  (`!net f:real^M->real^N g:real^N->real^P s y z.
2358     (f --> y) net /\
2359     eventually (\w. f w IN s /\ (f w = y ==> g y = z)) net /\
2360     (g --> z) (at y within s)
2361     ==> ((g o f) --> z) net`,
2362   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto; CONJ_ASSOC] THEN
2363   ONCE_REWRITE_TAC[LEFT_AND_FORALL_THM] THEN
2364   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2365   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
2366   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
2367   REWRITE_TAC[EVENTUALLY_WITHIN; GSYM DIST_NZ; o_DEF] THEN
2368   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
2369   FIRST_X_ASSUM(MP_TAC o SPEC `d:real`) THEN
2370   ASM_REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
2371   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2372   ASM_MESON_TAC[DIST_REFL]);;
2373
2374 let LIM_COMPOSE_AT = prove
2375  (`!net f:real^M->real^N g:real^N->real^P y z.
2376     (f --> y) net /\
2377     eventually (\w. f w = y ==> g y = z) net /\
2378     (g --> z) (at y)
2379     ==> ((g o f) --> z) net`,
2380   REPEAT STRIP_TAC THEN
2381   MP_TAC(ISPECL [`net:(real^M)net`; `f:real^M->real^N`; `g:real^N->real^P`;
2382                  `(:real^N)`; `y:real^N`; `z:real^P`]
2383         LIM_COMPOSE_WITHIN) THEN
2384   ASM_REWRITE_TAC[IN_UNIV; WITHIN_UNIV]);;
2385
2386 (* ------------------------------------------------------------------------- *)
2387 (* Interrelations between restricted and unrestricted limits.                *)
2388 (* ------------------------------------------------------------------------- *)
2389
2390 let LIM_AT_WITHIN = prove
2391  (`!f l a s. (f --> l)(at a) ==> (f --> l)(at a within s)`,
2392   REWRITE_TAC[LIM_AT; LIM_WITHIN] THEN MESON_TAC[]);;
2393
2394 let LIM_WITHIN_OPEN = prove
2395  (`!f l a:real^M s.
2396      a IN s /\ open s ==> ((f --> l)(at a within s) <=> (f --> l)(at a))`,
2397   REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[LIM_AT_WITHIN] THEN
2398   REWRITE_TAC[LIM_AT; LIM_WITHIN] THEN
2399   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
2400   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
2401    DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN
2402   FIRST_X_ASSUM(MP_TAC o SPEC `a:real^M` o GEN_REWRITE_RULE I [open_def]) THEN
2403   ASM_REWRITE_TAC[] THEN
2404   DISCH_THEN(X_CHOOSE_THEN `d2:real` STRIP_ASSUME_TAC) THEN
2405   MP_TAC(SPECL [`d1:real`; `d2:real`] REAL_DOWN2) THEN ASM_REWRITE_TAC[] THEN
2406   ASM_MESON_TAC[REAL_LT_TRANS]);;
2407
2408 (* ------------------------------------------------------------------------- *)
2409 (* More limit point characterizations.                                       *)
2410 (* ------------------------------------------------------------------------- *)
2411
2412 let LIMPT_SEQUENTIAL_INJ = prove
2413  (`!x:real^N s.
2414       x limit_point_of s <=>
2415              ?f. (!n. f(n) IN (s DELETE x)) /\
2416                  (!m n. f m = f n <=> m = n) /\
2417                  (f --> x) sequentially`,
2418   REPEAT GEN_TAC THEN
2419   REWRITE_TAC[LIMPT_APPROACHABLE; LIM_SEQUENTIALLY; IN_DELETE] THEN
2420   EQ_TAC THENL [ALL_TAC; MESON_TAC[GE; LE_REFL]] THEN
2421   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
2422   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
2423   X_GEN_TAC `y:real->real^N` THEN DISCH_TAC THEN
2424   (STRIP_ASSUME_TAC o  prove_recursive_functions_exist num_RECURSION)
2425    `(z 0 = y (&1)) /\
2426     (!n. z (SUC n):real^N = y(min (inv(&2 pow (SUC n))) (dist(z n,x))))` THEN
2427   EXISTS_TAC `z:num->real^N` THEN
2428   SUBGOAL_THEN
2429    `!n. z(n) IN s /\ ~(z n:real^N = x) /\ dist(z n,x) < inv(&2 pow n)`
2430   ASSUME_TAC THENL
2431    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
2432     ASM_SIMP_TAC[REAL_LT_01] THEN FIRST_X_ASSUM(MP_TAC o SPEC
2433      `min (inv(&2 pow (SUC n))) (dist(z n:real^N,x))`) THEN
2434     ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_INV_EQ; REAL_LT_POW2; DIST_POS_LT];
2435     ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
2436      [MATCH_MP_TAC WLOG_LT THEN REWRITE_TAC[EQ_SYM_EQ] THEN
2437       SUBGOAL_THEN `!m n:num. m < n ==> dist(z n:real^N,x) < dist(z m,x)`
2438        (fun th -> MESON_TAC[th; REAL_LT_REFL; LT_REFL]) THEN
2439       MATCH_MP_TAC TRANSITIVE_STEPWISE_LT THEN
2440       CONJ_TAC THENL [REAL_ARITH_TAC; GEN_TAC THEN ASM_REWRITE_TAC[]] THEN
2441       FIRST_X_ASSUM(MP_TAC o SPEC
2442        `min (inv(&2 pow (SUC n))) (dist(z n:real^N,x))`) THEN
2443       ASM_SIMP_TAC[REAL_LT_MIN; REAL_LT_INV_EQ; REAL_LT_POW2; DIST_POS_LT];
2444       X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2445       MP_TAC(ISPECL [`inv(&2)`; `e:real`] REAL_ARCH_POW_INV) THEN
2446       ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
2447       X_GEN_TAC `N:num` THEN REWRITE_TAC[REAL_POW_INV] THEN DISCH_TAC THEN
2448       X_GEN_TAC `n:num` THEN DISCH_TAC THEN
2449       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT]
2450         REAL_LT_TRANS)) THEN
2451       MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `inv(&2 pow n)` THEN
2452       ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
2453       ASM_REWRITE_TAC[REAL_LT_POW2] THEN MATCH_MP_TAC REAL_POW_MONO THEN
2454       REWRITE_TAC[REAL_OF_NUM_LE] THEN ASM_ARITH_TAC]]);;
2455
2456 let LIMPT_SEQUENTIAL = prove
2457  (`!x:real^N s.
2458       x limit_point_of s <=>
2459              ?f. (!n. f(n) IN (s DELETE x)) /\ (f --> x) sequentially`,
2460   REPEAT GEN_TAC THEN EQ_TAC THENL
2461    [REWRITE_TAC[LIMPT_SEQUENTIAL_INJ] THEN MESON_TAC[];
2462     REWRITE_TAC[LIMPT_APPROACHABLE; LIM_SEQUENTIALLY; IN_DELETE] THEN
2463     MESON_TAC[GE; LE_REFL]]);;
2464
2465 let [LIMPT_INFINITE_OPEN; LIMPT_INFINITE_BALL; LIMPT_INFINITE_CBALL] =
2466     (CONJUNCTS o prove)
2467  (`(!s x:real^N.
2468         x limit_point_of s <=> !t. x IN t /\ open t ==> INFINITE(s INTER t)) /\
2469    (!s x:real^N.
2470         x limit_point_of s <=> !e. &0 < e ==> INFINITE(s INTER ball(x,e))) /\
2471    (!s x:real^N.
2472         x limit_point_of s <=> !e. &0 < e ==> INFINITE(s INTER cball(x,e)))`,
2473   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
2474    `(q ==> p) /\ (r ==> s) /\ (s ==> q) /\ (p ==> r)
2475     ==> (p <=> q) /\ (p <=> r) /\ (p <=> s)`) THEN
2476   REPEAT CONJ_TAC THENL
2477    [REWRITE_TAC[limit_point_of; INFINITE; SET_RULE
2478      `(?y. ~(y = x) /\ y IN s /\ y IN t) <=> ~(s INTER t SUBSET {x})`] THEN
2479     MESON_TAC[FINITE_SUBSET; FINITE_SING];
2480     MESON_TAC[INFINITE_SUPERSET; BALL_SUBSET_CBALL;
2481               SET_RULE `t SUBSET u ==> s INTER t SUBSET s INTER u`];
2482     MESON_TAC[INFINITE_SUPERSET; OPEN_CONTAINS_CBALL;
2483               SET_RULE `t SUBSET u ==> s INTER t SUBSET s INTER u`];
2484     REWRITE_TAC[LIMPT_SEQUENTIAL_INJ; IN_DELETE; FORALL_AND_THM] THEN
2485     DISCH_THEN(X_CHOOSE_THEN `f:num->real^N` STRIP_ASSUME_TAC) THEN
2486     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2487     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
2488     DISCH_THEN(MP_TAC o SPEC `e:real`) THEN
2489     ASM_REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[DIST_SYM] IN_BALL)] THEN
2490     DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN
2491     MATCH_MP_TAC INFINITE_SUPERSET THEN
2492     EXISTS_TAC `IMAGE (f:num->real^N) (from N)` THEN
2493     ASM_SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_FROM; IN_INTER] THEN
2494     ASM_MESON_TAC[INFINITE_IMAGE_INJ; INFINITE_FROM]]);;
2495
2496 let INFINITE_OPEN_IN = prove
2497  (`!u s:real^N->bool.
2498       open_in (subtopology euclidean u) s /\ (?x. x IN s /\ x limit_point_of u)
2499       ==> INFINITE s`,
2500   REPEAT STRIP_TAC THEN
2501   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
2502   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
2503   FIRST_X_ASSUM(MP_TAC o SPEC `t:real^N->bool` o
2504         GEN_REWRITE_RULE I [LIMPT_INFINITE_OPEN]) THEN
2505   FIRST_X_ASSUM SUBST_ALL_TAC THEN ASM SET_TAC[]);;
2506
2507 (* ------------------------------------------------------------------------- *)
2508 (* Condensation points.                                                      *)
2509 (* ------------------------------------------------------------------------- *)
2510
2511 parse_as_infix ("condensation_point_of",(12,"right"));;
2512
2513 let condensation_point_of = new_definition
2514  `x condensation_point_of s <=>
2515         !t. x IN t /\ open t ==> ~COUNTABLE(s INTER t)`;;
2516
2517 let CONDENSATION_POINT_IMP_LIMPT = prove
2518  (`!x s. x condensation_point_of s ==> x limit_point_of s`,
2519   REWRITE_TAC[condensation_point_of; LIMPT_INFINITE_OPEN; INFINITE] THEN
2520   MESON_TAC[FINITE_IMP_COUNTABLE]);;
2521
2522 let CONDENSATION_POINT_INFINITE_BALL,CONDENSATION_POINT_INFINITE_CBALL =
2523   (CONJ_PAIR o prove)
2524  (`(!s x:real^N.
2525         x condensation_point_of s <=>
2526         !e. &0 < e ==> ~COUNTABLE(s INTER ball(x,e))) /\
2527    (!s x:real^N.
2528         x condensation_point_of s <=>
2529         !e. &0 < e ==> ~COUNTABLE(s INTER cball(x,e)))`,
2530   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
2531    `(p ==> q) /\ (q ==> r) /\ (r ==> p)
2532     ==> (p <=> q) /\ (p <=> r)`) THEN
2533   REWRITE_TAC[condensation_point_of] THEN REPEAT CONJ_TAC THENL
2534    [MESON_TAC[OPEN_BALL; CENTRE_IN_BALL];
2535     MESON_TAC[BALL_SUBSET_CBALL; COUNTABLE_SUBSET;
2536               SET_RULE `t SUBSET u ==> s INTER t SUBSET s INTER u`];
2537     MESON_TAC[COUNTABLE_SUBSET; OPEN_CONTAINS_CBALL;
2538               SET_RULE `t SUBSET u ==> s INTER t SUBSET s INTER u`]]);;
2539
2540 let LIMPT_OF_CONDENSATION_POINTS = prove
2541  (`!x:real^N s.
2542         x limit_point_of {y | y condensation_point_of s}
2543         ==> x condensation_point_of s`,
2544   REWRITE_TAC[LIMPT_APPROACHABLE; CONDENSATION_POINT_INFINITE_BALL] THEN
2545   REPEAT GEN_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN DISCH_TAC THEN
2546   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2547   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
2548   DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN
2549   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
2550   ASM_REWRITE_TAC[REAL_HALF; CONTRAPOS_THM] THEN
2551   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] COUNTABLE_SUBSET) THEN
2552   SIMP_TAC[SUBSET; IN_INTER; IN_BALL] THEN
2553   REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
2554
2555 let CLOSED_CONDENSATION_POINTS = prove
2556  (`!s:real^N->bool. closed {x | x condensation_point_of s}`,
2557   SIMP_TAC[CLOSED_LIMPT; LIMPT_OF_CONDENSATION_POINTS; IN_ELIM_THM]);;
2558
2559 (* ------------------------------------------------------------------------- *)
2560 (* Basic arithmetical combining theorems for limits.                         *)
2561 (* ------------------------------------------------------------------------- *)
2562
2563 let LIM_LINEAR = prove
2564  (`!net:(A)net h f l.
2565         (f --> l) net /\ linear h ==> ((\x. h(f x)) --> h l) net`,
2566   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
2567   ASM_CASES_TAC `trivial_limit (net:(A)net)` THEN ASM_REWRITE_TAC[] THEN
2568   STRIP_TAC THEN FIRST_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o
2569     MATCH_MP LINEAR_BOUNDED_POS) THEN
2570   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2571   FIRST_X_ASSUM(MP_TAC o SPEC `e / B`) THEN
2572   ASM_SIMP_TAC[REAL_LT_DIV; dist; GSYM LINEAR_SUB; REAL_LT_RDIV_EQ] THEN
2573   ASM_MESON_TAC[REAL_LET_TRANS; REAL_MUL_SYM]);;
2574
2575 let LIM_CONST = prove
2576  (`!net a:real^N. ((\x. a) --> a) net`,
2577   SIMP_TAC[LIM; DIST_REFL; trivial_limit] THEN MESON_TAC[]);;
2578
2579 let LIM_CMUL = prove
2580  (`!f l c. (f --> l) net ==> ((\x. c % f x) --> c % l) net`,
2581   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_LINEAR THEN
2582   ASM_REWRITE_TAC[REWRITE_RULE[ETA_AX]
2583     (MATCH_MP LINEAR_COMPOSE_CMUL LINEAR_ID)]);;
2584
2585 let LIM_CMUL_EQ = prove
2586  (`!net f l c.
2587         ~(c = &0) ==> (((\x. c % f x) --> c % l) net <=> (f --> l) net)`,
2588   REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[LIM_CMUL] THEN
2589   DISCH_THEN(MP_TAC o SPEC `inv c:real` o MATCH_MP LIM_CMUL) THEN
2590   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID; ETA_AX]);;
2591
2592 let LIM_NEG = prove
2593  (`!net f l:real^N. (f --> l) net ==> ((\x. --(f x)) --> --l) net`,
2594   REPEAT GEN_TAC THEN REWRITE_TAC[LIM; dist] THEN
2595   REWRITE_TAC[VECTOR_ARITH `--x - --y = --(x - y:real^N)`; NORM_NEG]);;
2596
2597 let LIM_NEG_EQ = prove
2598  (`!net f l:real^N. ((\x. --(f x)) --> --l) net <=> (f --> l) net`,
2599   REPEAT GEN_TAC THEN EQ_TAC THEN
2600   DISCH_THEN(MP_TAC o MATCH_MP LIM_NEG) THEN
2601   REWRITE_TAC[VECTOR_NEG_NEG; ETA_AX]);;
2602
2603 let LIM_ADD = prove
2604  (`!net:(A)net f g l m.
2605     (f --> l) net /\ (g --> m) net ==> ((\x. f(x) + g(x)) --> l + m) net`,
2606   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
2607   ASM_CASES_TAC `trivial_limit (net:(A)net)` THEN
2608   ASM_REWRITE_TAC[AND_FORALL_THM] THEN
2609   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2610   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
2611   DISCH_THEN(MP_TAC o MATCH_MP NET_DILEMMA) THEN MATCH_MP_TAC MONO_EXISTS THEN
2612   MESON_TAC[REAL_HALF; DIST_TRIANGLE_ADD; REAL_LT_ADD2; REAL_LET_TRANS]);;
2613
2614 let LIM_ABS = prove
2615  (`!net:(A)net f:A->real^N l.
2616      (f --> l) net
2617      ==> ((\x. lambda i. (abs(f(x)$i))) --> (lambda i. abs(l$i)):real^N) net`,
2618   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
2619   ASM_CASES_TAC `trivial_limit (net:(A)net)` THEN ASM_REWRITE_TAC[] THEN
2620   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
2621   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
2622   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
2623   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
2624   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
2625   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
2626   MATCH_MP_TAC(NORM_ARITH
2627    `norm(x - y) <= norm(a - b) ==> dist(a,b) < e ==> dist(x,y) < e`) THEN
2628   MATCH_MP_TAC NORM_LE_COMPONENTWISE THEN
2629   SIMP_TAC[LAMBDA_BETA; VECTOR_SUB_COMPONENT] THEN
2630   REAL_ARITH_TAC);;
2631
2632 let LIM_SUB = prove
2633  (`!net:(A)net f g l m.
2634     (f --> l) net /\ (g --> m) net ==> ((\x. f(x) - g(x)) --> l - m) net`,
2635   REWRITE_TAC[real_sub; VECTOR_SUB] THEN ASM_SIMP_TAC[LIM_ADD; LIM_NEG]);;
2636
2637 let LIM_MAX = prove
2638  (`!net:(A)net f g l:real^N m:real^N.
2639     (f --> l) net /\ (g --> m) net
2640     ==> ((\x. lambda i. max (f(x)$i) (g(x)$i))
2641          --> (lambda i. max (l$i) (m$i)):real^N) net`,
2642   REPEAT GEN_TAC THEN DISCH_TAC THEN
2643   FIRST_ASSUM(MP_TAC o MATCH_MP LIM_ADD) THEN
2644   FIRST_ASSUM(MP_TAC o MATCH_MP LIM_SUB) THEN
2645   DISCH_THEN(MP_TAC o MATCH_MP LIM_ABS) THEN
2646   REWRITE_TAC[IMP_IMP] THEN
2647   DISCH_THEN(MP_TAC o MATCH_MP LIM_ADD) THEN
2648   DISCH_THEN(MP_TAC o SPEC `inv(&2)` o MATCH_MP LIM_CMUL) THEN
2649   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN BINOP_TAC THEN
2650   SIMP_TAC[FUN_EQ_THM; CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
2651            VECTOR_SUB_COMPONENT; LAMBDA_BETA] THEN
2652   REAL_ARITH_TAC);;
2653
2654 let LIM_MIN = prove
2655  (`!net:(A)net f g l:real^N m:real^N.
2656     (f --> l) net /\ (g --> m) net
2657     ==> ((\x. lambda i. min (f(x)$i) (g(x)$i))
2658          --> (lambda i. min (l$i) (m$i)):real^N) net`,
2659   REPEAT GEN_TAC THEN
2660   DISCH_THEN(CONJUNCTS_THEN(MP_TAC o MATCH_MP LIM_NEG)) THEN
2661   REWRITE_TAC[IMP_IMP] THEN
2662   DISCH_THEN(MP_TAC o MATCH_MP LIM_NEG o MATCH_MP LIM_MAX) THEN
2663   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN BINOP_TAC THEN
2664   SIMP_TAC[FUN_EQ_THM; CART_EQ; LAMBDA_BETA; VECTOR_NEG_COMPONENT] THEN
2665   REAL_ARITH_TAC);;
2666
2667 let LIM_NORM = prove
2668  (`!net f:A->real^N l.
2669         (f --> l) net ==> ((\x. lift(norm(f x))) --> lift(norm l)) net`,
2670   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto; DIST_LIFT] THEN
2671   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
2672   REWRITE_TAC[] THEN
2673   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2674   REWRITE_TAC[] THEN NORM_ARITH_TAC);;
2675
2676 let LIM_NULL = prove
2677  (`!net f l. (f --> l) net <=> ((\x. f(x) - l) --> vec 0) net`,
2678   REWRITE_TAC[LIM; dist; VECTOR_SUB_RZERO]);;
2679
2680 let LIM_NULL_NORM = prove
2681  (`!net f. (f --> vec 0) net <=> ((\x. lift(norm(f x))) --> vec 0) net`,
2682   REWRITE_TAC[LIM; dist; VECTOR_SUB_RZERO; REAL_ABS_NORM; NORM_LIFT]);;
2683
2684 let LIM_NULL_CMUL_EQ = prove
2685  (`!net f c.
2686         ~(c = &0) ==> (((\x. c % f x) --> vec 0) net <=> (f --> vec 0) net)`,
2687   MESON_TAC[LIM_CMUL_EQ; VECTOR_MUL_RZERO]);;
2688
2689 let LIM_NULL_COMPARISON = prove
2690  (`!net f g. eventually (\x. norm(f x) <= g x) net /\
2691              ((\x. lift(g x)) --> vec 0) net
2692              ==> (f --> vec 0) net`,
2693   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto; RIGHT_AND_FORALL_THM] THEN
2694   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
2695   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
2696   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2697   REWRITE_TAC[dist; VECTOR_SUB_RZERO; NORM_LIFT] THEN REAL_ARITH_TAC);;
2698
2699 let LIM_COMPONENT = prove
2700  (`!net f i l:real^N. (f --> l) net /\ 1 <= i /\ i <= dimindex(:N)
2701                       ==> ((\a. lift(f(a)$i)) --> lift(l$i)) net`,
2702   REWRITE_TAC[LIM; dist; GSYM LIFT_SUB; NORM_LIFT] THEN
2703   SIMP_TAC[GSYM VECTOR_SUB_COMPONENT] THEN
2704   MESON_TAC[COMPONENT_LE_NORM; REAL_LET_TRANS]);;
2705
2706 let LIM_TRANSFORM_BOUND = prove
2707  (`!f g. eventually (\n. norm(f n) <= norm(g n)) net /\ (g --> vec 0) net
2708          ==> (f --> vec 0) net`,
2709   REPEAT GEN_TAC THEN
2710   REWRITE_TAC[tendsto; RIGHT_AND_FORALL_THM] THEN
2711   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
2712   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
2713   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2714   REWRITE_TAC[dist; VECTOR_SUB_RZERO] THEN REAL_ARITH_TAC);;
2715
2716 let LIM_NULL_CMUL_BOUNDED = prove
2717  (`!f g:A->real^N B.
2718         eventually (\a. g a = vec 0 \/ abs(f a) <= B) net /\
2719         (g --> vec 0) net
2720         ==> ((\n. f n % g n) --> vec 0) net`,
2721   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto] THEN STRIP_TAC THEN
2722   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2723   FIRST_X_ASSUM(MP_TAC o SPEC `e / (abs B + &1)`) THEN
2724   ASM_SIMP_TAC[REAL_LT_DIV; REAL_ARITH `&0 < abs x + &1`] THEN
2725   UNDISCH_TAC `eventually (\a. g a:real^N = vec 0 \/ abs(f a) <= B)
2726                            (net:(A net))` THEN
2727   REWRITE_TAC[IMP_IMP; GSYM EVENTUALLY_AND] THEN
2728   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MP) THEN
2729   REWRITE_TAC[dist; VECTOR_SUB_RZERO; o_THM; NORM_LIFT; NORM_MUL] THEN
2730   MATCH_MP_TAC ALWAYS_EVENTUALLY THEN X_GEN_TAC `x:A` THEN REWRITE_TAC[] THEN
2731   ASM_CASES_TAC `(g:A->real^N) x = vec 0` THEN
2732   ASM_REWRITE_TAC[NORM_0; REAL_MUL_RZERO] THEN
2733   STRIP_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN
2734   EXISTS_TAC `B * e / (abs B + &1)` THEN
2735   ASM_SIMP_TAC[REAL_LE_MUL2; REAL_ABS_POS; NORM_POS_LE; REAL_LT_IMP_LE] THEN
2736   REWRITE_TAC[REAL_ARITH `c * (a / b) = (c * a) / b`] THEN
2737   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_ARITH `&0 < abs x + &1`] THEN
2738   MATCH_MP_TAC(REAL_ARITH
2739    `e * B <= e * abs B /\ &0 < e ==> B * e < e * (abs B + &1)`) THEN
2740   ASM_SIMP_TAC[REAL_LE_LMUL_EQ] THEN REAL_ARITH_TAC);;
2741
2742 let LIM_NULL_VMUL_BOUNDED = prove
2743  (`!f g:A->real^N B.
2744         ((lift o f) --> vec 0) net /\
2745         eventually (\a. f a = &0 \/ norm(g a) <= B) net
2746         ==> ((\n. f n % g n) --> vec 0) net`,
2747   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto] THEN STRIP_TAC THEN
2748   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2749   FIRST_X_ASSUM(MP_TAC o SPEC `e / (abs B + &1)`) THEN
2750   ASM_SIMP_TAC[REAL_LT_DIV; REAL_ARITH `&0 < abs x + &1`] THEN
2751   UNDISCH_TAC `eventually(\a. f a = &0 \/ norm((g:A->real^N) a) <= B) net` THEN
2752   REWRITE_TAC[IMP_IMP; GSYM EVENTUALLY_AND] THEN
2753   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MP) THEN
2754   REWRITE_TAC[dist; VECTOR_SUB_RZERO; o_THM; NORM_LIFT; NORM_MUL] THEN
2755   MATCH_MP_TAC ALWAYS_EVENTUALLY THEN X_GEN_TAC `x:A` THEN REWRITE_TAC[] THEN
2756   ASM_CASES_TAC `(f:A->real) x = &0` THEN
2757   ASM_REWRITE_TAC[REAL_ABS_NUM; REAL_MUL_LZERO] THEN
2758   STRIP_TAC THEN MATCH_MP_TAC REAL_LET_TRANS THEN
2759   EXISTS_TAC `e / (abs B + &1) * B` THEN
2760   ASM_SIMP_TAC[REAL_LE_MUL2; REAL_ABS_POS; NORM_POS_LE; REAL_LT_IMP_LE] THEN
2761   REWRITE_TAC[REAL_ARITH `(a / b) * c = (a * c) / b`] THEN
2762   SIMP_TAC[REAL_LT_LDIV_EQ; REAL_ARITH `&0 < abs x + &1`] THEN
2763   MATCH_MP_TAC(REAL_ARITH
2764    `e * B <= e * abs B /\ &0 < e ==> e * B < e * (abs B + &1)`) THEN
2765   ASM_SIMP_TAC[REAL_LE_LMUL_EQ] THEN REAL_ARITH_TAC);;
2766
2767 let LIM_VSUM = prove
2768  (`!f:A->B->real^N s.
2769         FINITE s /\ (!i. i IN s ==> ((f i) --> (l i)) net)
2770         ==> ((\x. vsum s (\i. f i x)) --> vsum s l) net`,
2771   GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
2772   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
2773   SIMP_TAC[VSUM_CLAUSES; LIM_CONST; LIM_ADD; IN_INSERT; ETA_AX]);;
2774
2775 (* ------------------------------------------------------------------------- *)
2776 (* Deducing things about the limit from the elements.                        *)
2777 (* ------------------------------------------------------------------------- *)
2778
2779 let LIM_IN_CLOSED_SET = prove
2780  (`!net f:A->real^N s l.
2781         closed s /\ eventually (\x. f(x) IN s) net /\
2782         ~(trivial_limit net) /\ (f --> l) net
2783         ==> l IN s`,
2784   REWRITE_TAC[closed] THEN REPEAT STRIP_TAC THEN
2785   MATCH_MP_TAC(SET_RULE `~(x IN (UNIV DIFF s)) ==> x IN s`) THEN
2786   DISCH_TAC THEN
2787   FIRST_ASSUM(MP_TAC o SPEC `l:real^N` o GEN_REWRITE_RULE I
2788           [OPEN_CONTAINS_BALL]) THEN
2789   ASM_REWRITE_TAC[SUBSET; IN_BALL; IN_DIFF; IN_UNION] THEN
2790   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
2791   FIRST_X_ASSUM(MP_TAC o SPEC `e:real` o GEN_REWRITE_RULE I [tendsto]) THEN
2792   UNDISCH_TAC `eventually (\x. (f:A->real^N) x IN s) net` THEN
2793   ASM_REWRITE_TAC[GSYM EVENTUALLY_AND; TAUT `a ==> ~b <=> ~(a /\ b)`] THEN
2794   MATCH_MP_TAC NOT_EVENTUALLY THEN ASM_MESON_TAC[DIST_SYM]);;
2795
2796 (* ------------------------------------------------------------------------- *)
2797 (* Need to prove closed(cball(x,e)) before deducing this as a corollary.     *)
2798 (* ------------------------------------------------------------------------- *)
2799
2800 let LIM_NORM_UBOUND = prove
2801  (`!net:(A)net f (l:real^N) b.
2802       ~(trivial_limit net) /\
2803       (f --> l) net /\
2804       eventually (\x. norm(f x) <= b) net
2805       ==> norm(l) <= b`,
2806   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2807   ASM_REWRITE_TAC[LIM] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2808   ASM_REWRITE_TAC[eventually] THEN
2809   STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
2810   ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN DISCH_TAC THEN
2811   SUBGOAL_THEN
2812    `?x:A. dist(f(x):real^N,l) < norm(l:real^N) - b /\ norm(f x) <= b`
2813   (CHOOSE_THEN MP_TAC) THENL [ASM_MESON_TAC[NET]; ALL_TAC] THEN
2814   REWRITE_TAC[REAL_NOT_LT; REAL_LE_SUB_RADD; DE_MORGAN_THM; dist] THEN
2815   NORM_ARITH_TAC);;
2816
2817 let LIM_NORM_LBOUND = prove
2818  (`!net:(A)net f (l:real^N) b.
2819       ~(trivial_limit net) /\ (f --> l) net /\
2820       eventually (\x. b <= norm(f x)) net
2821       ==> b <= norm(l)`,
2822   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2823   ASM_REWRITE_TAC[LIM] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2824   ASM_REWRITE_TAC[eventually] THEN
2825   STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
2826   ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN DISCH_TAC THEN
2827   SUBGOAL_THEN
2828    `?x:A. dist(f(x):real^N,l) < b - norm(l:real^N) /\ b <= norm(f x)`
2829   (CHOOSE_THEN MP_TAC) THENL [ASM_MESON_TAC[NET]; ALL_TAC] THEN
2830   REWRITE_TAC[REAL_NOT_LT; REAL_LE_SUB_RADD; DE_MORGAN_THM; dist] THEN
2831   NORM_ARITH_TAC);;
2832
2833 (* ------------------------------------------------------------------------- *)
2834 (* Uniqueness of the limit, when nontrivial.                                 *)
2835 (* ------------------------------------------------------------------------- *)
2836
2837 let LIM_UNIQUE = prove
2838  (`!net:(A)net f l:real^N l'.
2839       ~(trivial_limit net) /\ (f --> l) net /\ (f --> l') net ==> (l = l')`,
2840   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2841   DISCH_THEN(ASSUME_TAC o REWRITE_RULE[VECTOR_SUB_REFL] o MATCH_MP LIM_SUB) THEN
2842   SUBGOAL_THEN `!e. &0 < e ==> norm(l:real^N - l') <= e` MP_TAC THENL
2843    [GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC LIM_NORM_UBOUND THEN
2844     MAP_EVERY EXISTS_TAC [`net:(A)net`; `\x:A. vec 0 : real^N`] THEN
2845     ASM_SIMP_TAC[NORM_0; REAL_LT_IMP_LE; eventually] THEN
2846     ASM_MESON_TAC[trivial_limit];
2847     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[DIST_NZ; dist] THEN
2848     DISCH_TAC THEN DISCH_THEN(MP_TAC o SPEC `norm(l - l':real^N) / &2`) THEN
2849     ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LE_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
2850     UNDISCH_TAC `&0 < norm(l - l':real^N)` THEN REAL_ARITH_TAC]);;
2851
2852 let TENDSTO_LIM = prove
2853  (`!net f l. ~(trivial_limit net) /\ (f --> l) net ==> lim net f = l`,
2854   REWRITE_TAC[lim] THEN MESON_TAC[LIM_UNIQUE]);;
2855
2856 let LIM_CONST_EQ = prove
2857  (`!net:(A net) c d:real^N.
2858         ((\x. c) --> d) net <=> trivial_limit net \/ c = d`,
2859   REPEAT GEN_TAC THEN
2860   ASM_CASES_TAC `trivial_limit (net:A net)` THEN ASM_REWRITE_TAC[] THENL
2861    [ASM_REWRITE_TAC[LIM]; ALL_TAC] THEN
2862   EQ_TAC THEN SIMP_TAC[LIM_CONST] THEN DISCH_TAC THEN
2863   MATCH_MP_TAC(SPEC `net:A net` LIM_UNIQUE) THEN
2864   EXISTS_TAC `(\x. c):A->real^N` THEN ASM_REWRITE_TAC[LIM_CONST]);;
2865
2866 (* ------------------------------------------------------------------------- *)
2867 (* Some unwieldy but occasionally useful theorems about uniform limits.      *)
2868 (* ------------------------------------------------------------------------- *)
2869
2870 let UNIFORM_LIM_ADD = prove
2871  (`!net:(A)net P f g l m.
2872         (!e. &0 < e
2873              ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
2874         (!e. &0 < e
2875              ==> eventually (\x. !n. P n ==> norm(g n x - m n) < e) net)
2876         ==> !e. &0 < e
2877                 ==> eventually
2878                      (\x. !n. P n
2879                               ==> norm((f n x + g n x) - (l n + m n)) < e)
2880                      net`,
2881   REPEAT GEN_TAC THEN REWRITE_TAC[AND_FORALL_THM] THEN DISCH_TAC THEN
2882   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2883   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
2884   ASM_REWRITE_TAC[REAL_HALF; GSYM EVENTUALLY_AND] THEN
2885   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2886   GEN_TAC THEN REWRITE_TAC[AND_FORALL_THM] THEN
2887   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `n:B` THEN
2888   ASM_CASES_TAC `(P:B->bool) n` THEN ASM_REWRITE_TAC[] THEN
2889   CONV_TAC NORM_ARITH);;
2890
2891 let UNIFORM_LIM_SUB = prove
2892  (`!net:(A)net P f g l m.
2893         (!e. &0 < e
2894              ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
2895         (!e. &0 < e
2896              ==> eventually (\x. !n. P n ==> norm(g n x - m n) < e) net)
2897         ==> !e. &0 < e
2898                 ==> eventually
2899                      (\x. !n. P n
2900                               ==> norm((f n x - g n x) - (l n - m n)) < e)
2901                      net`,
2902   REPEAT GEN_TAC THEN REWRITE_TAC[AND_FORALL_THM] THEN DISCH_TAC THEN
2903   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2904   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
2905   ASM_REWRITE_TAC[REAL_HALF; GSYM EVENTUALLY_AND] THEN
2906   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2907   GEN_TAC THEN REWRITE_TAC[AND_FORALL_THM] THEN
2908   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `n:B` THEN
2909   ASM_CASES_TAC `(P:B->bool) n` THEN ASM_REWRITE_TAC[] THEN
2910   CONV_TAC NORM_ARITH);;
2911
2912 (* ------------------------------------------------------------------------- *)
2913 (* Limit under bilinear function, uniform version first.                     *)
2914 (* ------------------------------------------------------------------------- *)
2915
2916 let UNIFORM_LIM_BILINEAR = prove
2917  (`!net:(A)net P (h:real^M->real^N->real^P) f g l m b1 b2.
2918         bilinear h /\
2919         eventually (\x. !n. P n ==> norm(l n) <= b1) net /\
2920         eventually (\x. !n. P n ==> norm(m n) <= b2) net /\
2921         (!e. &0 < e
2922              ==> eventually (\x. !n:B. P n ==> norm(f n x - l n) < e) net) /\
2923         (!e. &0 < e
2924              ==> eventually (\x. !n. P n ==> norm(g n x - m n) < e) net)
2925         ==> !e. &0 < e
2926                 ==> eventually
2927                      (\x. !n. P n
2928                               ==> norm(h (f n x) (g n x) - h (l n) (m n)) < e)
2929                      net`,
2930   REPEAT GEN_TAC THEN
2931   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
2932   FIRST_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o  MATCH_MP
2933    BILINEAR_BOUNDED_POS) THEN
2934   REWRITE_TAC[AND_FORALL_THM; RIGHT_AND_FORALL_THM] THEN DISCH_TAC THEN
2935   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
2936   FIRST_X_ASSUM(MP_TAC o SPEC
2937    `min (abs b2 + &1) (e / &2 / (B * (abs b1 + abs b2 + &2)))`) THEN
2938   ASM_SIMP_TAC[REAL_HALF; REAL_LT_DIV; REAL_LT_MUL; REAL_LT_MIN;
2939                REAL_ARITH `&0 < abs x + &1`;
2940                REAL_ARITH `&0 < abs x + abs y + &2`] THEN
2941   REWRITE_TAC[GSYM EVENTUALLY_AND] THEN
2942   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
2943   X_GEN_TAC `x:A` THEN REWRITE_TAC[AND_FORALL_THM] THEN
2944   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `n:B` THEN
2945   ASM_CASES_TAC `(P:B->bool) n` THEN ASM_REWRITE_TAC[] THEN
2946   STRIP_TAC THEN
2947   ONCE_REWRITE_TAC[VECTOR_ARITH
2948     `h a b - h c d :real^N = (h a b - h a d) + (h a d - h c d)`] THEN
2949   ASM_SIMP_TAC[GSYM BILINEAR_LSUB; GSYM BILINEAR_RSUB] THEN
2950   MATCH_MP_TAC NORM_TRIANGLE_LT THEN
2951   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP
2952    (MESON[REAL_LE_ADD2; REAL_LET_TRANS]
2953      `(!x y. norm(h x y:real^P) <= B * norm x * norm y)
2954        ==> B * norm a * norm b + B * norm c * norm d < e
2955            ==> norm(h a b) + norm(h c d) < e`)) THEN
2956   MATCH_MP_TAC(REAL_ARITH
2957    `x * B < e / &2 /\ y * B < e / &2 ==> B * x + B * y < e`) THEN
2958   CONJ_TAC THEN ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ] THENL
2959    [ONCE_REWRITE_TAC[REAL_MUL_SYM]; ALL_TAC] THEN
2960   MATCH_MP_TAC REAL_LET_TRANS THEN
2961   EXISTS_TAC `e / &2 / (B * (abs b1 + abs b2 + &2)) *
2962              (abs b1 + abs b2 + &1)` THEN
2963   (CONJ_TAC THENL
2964     [MATCH_MP_TAC REAL_LE_MUL2 THEN
2965      ASM_SIMP_TAC[NORM_POS_LE; REAL_LT_IMP_LE] THEN
2966      ASM_SIMP_TAC[REAL_ARITH `a <= b2 ==> a <= abs b1 + abs b2 + &1`] THEN
2967      ASM_MESON_TAC[NORM_ARITH
2968        `norm(f - l:real^P) < abs b2 + &1 /\ norm(l) <= b1
2969         ==> norm(f) <= abs b1 + abs b2 + &1`];
2970      ONCE_REWRITE_TAC[real_div] THEN
2971      ASM_SIMP_TAC[REAL_LT_LMUL_EQ; REAL_HALF; GSYM REAL_MUL_ASSOC;
2972                   REAL_INV_MUL] THEN
2973      REWRITE_TAC[REAL_ARITH `B * inv x * y < B <=> B * y / x < B * &1`] THEN
2974      ASM_SIMP_TAC[REAL_LT_INV_EQ; REAL_LT_LMUL_EQ; REAL_LT_LDIV_EQ;
2975                   REAL_ARITH `&0 < abs x + abs y + &2`] THEN
2976      REAL_ARITH_TAC]));;
2977
2978 let LIM_BILINEAR = prove
2979  (`!net:(A)net (h:real^M->real^N->real^P) f g l m.
2980         (f --> l) net /\ (g --> m) net /\ bilinear h
2981         ==> ((\x. h (f x) (g x)) --> (h l m)) net`,
2982   REPEAT STRIP_TAC THEN
2983   MP_TAC(ISPECL
2984    [`net:(A)net`; `\x:one. T`; `h:real^M->real^N->real^P`;
2985     `\n:one. (f:A->real^M)`; `\n:one. (g:A->real^N)`;
2986     `\n:one. (l:real^M)`; `\n:one. (m:real^N)`;
2987     `norm(l:real^M)`; `norm(m:real^N)`]
2988    UNIFORM_LIM_BILINEAR) THEN
2989   ASM_REWRITE_TAC[REAL_LE_REFL; EVENTUALLY_TRUE] THEN
2990   ASM_REWRITE_TAC[GSYM dist; GSYM tendsto]);;
2991
2992 (* ------------------------------------------------------------------------- *)
2993 (* These are special for limits out of the same vector space.                *)
2994 (* ------------------------------------------------------------------------- *)
2995
2996 let LIM_WITHIN_ID = prove
2997  (`!a s. ((\x. x) --> a) (at a within s)`,
2998   REWRITE_TAC[LIM_WITHIN] THEN MESON_TAC[]);;
2999
3000 let LIM_AT_ID = prove
3001  (`!a. ((\x. x) --> a) (at a)`,
3002   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN REWRITE_TAC[LIM_WITHIN_ID]);;
3003
3004 let LIM_AT_ZERO = prove
3005  (`!f:real^M->real^N l a.
3006         (f --> l) (at a) <=> ((\x. f(a + x)) --> l) (at(vec 0))`,
3007   REPEAT GEN_TAC THEN REWRITE_TAC[LIM_AT] THEN
3008   AP_TERM_TAC THEN ABS_TAC THEN
3009   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
3010   AP_TERM_TAC THEN ABS_TAC THEN
3011   ASM_CASES_TAC `&0 < d` THEN ASM_REWRITE_TAC[] THEN
3012   EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `x:real^M` THENL
3013    [FIRST_X_ASSUM(MP_TAC o SPEC `a + x:real^M`) THEN
3014     REWRITE_TAC[dist; VECTOR_ADD_SUB; VECTOR_SUB_RZERO];
3015     FIRST_X_ASSUM(MP_TAC o SPEC `x - a:real^M`) THEN
3016     REWRITE_TAC[dist; VECTOR_SUB_RZERO; VECTOR_SUB_ADD2]]);;
3017
3018 (* ------------------------------------------------------------------------- *)
3019 (* It's also sometimes useful to extract the limit point from the net.       *)
3020 (* ------------------------------------------------------------------------- *)
3021
3022 let netlimit = new_definition
3023   `netlimit net = @a. !x. ~(netord net x a)`;;
3024
3025 let NETLIMIT_WITHIN = prove
3026  (`!a:real^N s. ~(trivial_limit (at a within s))
3027                 ==> (netlimit (at a within s) = a)`,
3028   REWRITE_TAC[trivial_limit; netlimit; AT; WITHIN; DE_MORGAN_THM] THEN
3029   REPEAT STRIP_TAC THEN MATCH_MP_TAC SELECT_UNIQUE THEN REWRITE_TAC[] THEN
3030   SUBGOAL_THEN
3031    `!x:real^N. ~(&0 < dist(x,a) /\ dist(x,a) <= dist(a,a) /\ x IN s)`
3032   ASSUME_TAC THENL
3033    [ASM_MESON_TAC[DIST_REFL; REAL_NOT_LT]; ASM_MESON_TAC[]]);;
3034
3035 let NETLIMIT_AT = prove
3036  (`!a. netlimit(at a) = a`,
3037   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
3038   MATCH_MP_TAC NETLIMIT_WITHIN THEN
3039   SIMP_TAC[TRIVIAL_LIMIT_AT; WITHIN_UNIV]);;
3040
3041 (* ------------------------------------------------------------------------- *)
3042 (* Transformation of limit.                                                  *)
3043 (* ------------------------------------------------------------------------- *)
3044
3045 let LIM_TRANSFORM = prove
3046  (`!net f g l.
3047      ((\x. f x - g x) --> vec 0) net /\ (f --> l) net ==> (g --> l) net`,
3048   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP LIM_SUB) THEN
3049   DISCH_THEN(MP_TAC o MATCH_MP LIM_NEG) THEN MATCH_MP_TAC EQ_IMP THEN
3050   AP_THM_TAC THEN BINOP_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN
3051   VECTOR_ARITH_TAC);;
3052
3053 let LIM_TRANSFORM_EVENTUALLY = prove
3054  (`!net f g l.
3055         eventually (\x. f x = g x) net /\ (f --> l) net ==> (g --> l) net`,
3056   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
3057   DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o MATCH_MP LIM_EVENTUALLY) MP_TAC) THEN
3058   MESON_TAC[LIM_TRANSFORM]);;
3059
3060 let LIM_TRANSFORM_WITHIN = prove
3061  (`!f g x s d.
3062         &0 < d /\
3063         (!x'. x' IN s /\ &0 < dist(x',x) /\ dist(x',x) < d ==> f(x') = g(x')) /\
3064         (f --> l) (at x within s)
3065         ==> (g --> l) (at x within s)`,
3066   REPEAT GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
3067   DISCH_TAC THEN DISCH_TAC THEN
3068   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM) THEN
3069   REWRITE_TAC[LIM_WITHIN] THEN REPEAT STRIP_TAC THEN EXISTS_TAC `d:real` THEN
3070   ASM_SIMP_TAC[VECTOR_SUB_REFL; DIST_REFL]);;
3071
3072 let LIM_TRANSFORM_AT = prove
3073  (`!f g x d.
3074         &0 < d /\
3075         (!x'. &0 < dist(x',x) /\ dist(x',x) < d ==> f(x') = g(x')) /\
3076         (f --> l) (at x)
3077         ==> (g --> l) (at x)`,
3078   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN MESON_TAC[LIM_TRANSFORM_WITHIN]);;
3079
3080 let LIM_TRANSFORM_EQ = prove
3081  (`!net f:A->real^N g l.
3082      ((\x. f x - g x) --> vec 0) net ==> ((f --> l) net <=> (g --> l) net)`,
3083   REPEAT STRIP_TAC THEN EQ_TAC THEN
3084   DISCH_TAC THEN MATCH_MP_TAC LIM_TRANSFORM THENL
3085    [EXISTS_TAC `f:A->real^N` THEN ASM_REWRITE_TAC[];
3086     EXISTS_TAC `g:A->real^N` THEN ASM_REWRITE_TAC[] THEN
3087     ONCE_REWRITE_TAC[GSYM LIM_NEG_EQ] THEN
3088     ASM_REWRITE_TAC[VECTOR_NEG_SUB; VECTOR_NEG_0]]);;
3089
3090 let LIM_TRANSFORM_WITHIN_SET = prove
3091  (`!f a s t.
3092         eventually (\x. x IN s <=> x IN t) (at a)
3093         ==> ((f --> l) (at a within s) <=> (f --> l) (at a within t))`,
3094   REPEAT GEN_TAC THEN REWRITE_TAC[EVENTUALLY_AT; LIM_WITHIN] THEN
3095   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
3096   EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3097   FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
3098   DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
3099   EXISTS_TAC `min d k:real` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
3100   ASM_MESON_TAC[]);;
3101
3102 (* ------------------------------------------------------------------------- *)
3103 (* Common case assuming being away from some crucial point like 0.           *)
3104 (* ------------------------------------------------------------------------- *)
3105
3106 let LIM_TRANSFORM_AWAY_WITHIN = prove
3107  (`!f:real^M->real^N g a b s.
3108         ~(a = b) /\
3109         (!x. x IN s /\ ~(x = a) /\ ~(x = b) ==> f(x) = g(x)) /\
3110         (f --> l) (at a within s)
3111         ==> (g --> l) (at a within s)`,
3112   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_TRANSFORM_WITHIN THEN
3113   MAP_EVERY EXISTS_TAC [`f:real^M->real^N`; `dist(a:real^M,b)`] THEN
3114   ASM_REWRITE_TAC[GSYM DIST_NZ] THEN X_GEN_TAC `y:real^M` THEN
3115   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
3116   ASM_MESON_TAC[DIST_SYM; REAL_LT_REFL]);;
3117
3118 let LIM_TRANSFORM_AWAY_AT = prove
3119  (`!f:real^M->real^N g a b.
3120         ~(a = b) /\
3121         (!x. ~(x = a) /\ ~(x = b) ==> f(x) = g(x)) /\
3122         (f --> l) (at a)
3123         ==> (g --> l) (at a)`,
3124   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
3125   MESON_TAC[LIM_TRANSFORM_AWAY_WITHIN]);;
3126
3127 (* ------------------------------------------------------------------------- *)
3128 (* Alternatively, within an open set.                                        *)
3129 (* ------------------------------------------------------------------------- *)
3130
3131 let LIM_TRANSFORM_WITHIN_OPEN = prove
3132  (`!f g:real^M->real^N s a.
3133         open s /\ a IN s /\
3134         (!x. x IN s /\ ~(x = a) ==> f x = g x) /\
3135         (f --> l) (at a)
3136         ==> (g --> l) (at a)`,
3137   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_TRANSFORM_AT THEN
3138   EXISTS_TAC `f:real^M->real^N` THEN ASM_REWRITE_TAC[] THEN
3139   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
3140   DISCH_THEN(MP_TAC o SPEC `a:real^M`) THEN ASM_REWRITE_TAC[] THEN
3141   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[SUBSET; IN_BALL] THEN
3142   ASM_MESON_TAC[DIST_NZ; DIST_SYM]);;
3143
3144 (* ------------------------------------------------------------------------- *)
3145 (* Another quite common idiom of an explicit conditional in a sequence.      *)
3146 (* ------------------------------------------------------------------------- *)
3147
3148 let LIM_CASES_FINITE_SEQUENTIALLY = prove
3149  (`!f g l. FINITE {n | P n}
3150            ==> (((\n. if P n then f n else g n) --> l) sequentially <=>
3151                 (g --> l) sequentially)`,
3152   REPEAT STRIP_TAC THEN EQ_TAC THEN
3153   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LIM_TRANSFORM_EVENTUALLY) THEN
3154   FIRST_ASSUM(MP_TAC o SPEC `\n:num. n` o MATCH_MP UPPER_BOUND_FINITE_SET) THEN
3155   REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
3156   X_GEN_TAC `N:num` THEN DISCH_TAC THEN SIMP_TAC[EVENTUALLY_SEQUENTIALLY] THEN
3157   EXISTS_TAC `N + 1` THEN
3158   ASM_MESON_TAC[ARITH_RULE `~(x <= n /\ n + 1 <= x)`]);;
3159
3160 let LIM_CASES_COFINITE_SEQUENTIALLY = prove
3161  (`!f g l. FINITE {n | ~P n}
3162            ==> (((\n. if P n then f n else g n) --> l) sequentially <=>
3163                 (f --> l) sequentially)`,
3164   ONCE_REWRITE_TAC[TAUT `(if p then x else y) = (if ~p then y else x)`] THEN
3165   REWRITE_TAC[LIM_CASES_FINITE_SEQUENTIALLY]);;
3166
3167 let LIM_CASES_SEQUENTIALLY = prove
3168  (`!f g l m. (((\n. if m <= n then f n else g n) --> l) sequentially <=>
3169               (f --> l) sequentially) /\
3170              (((\n. if m < n then f n else g n) --> l) sequentially <=>
3171               (f --> l) sequentially) /\
3172              (((\n. if n <= m then f n else g n) --> l) sequentially <=>
3173               (g --> l) sequentially) /\
3174              (((\n. if n < m then f n else g n) --> l) sequentially <=>
3175               (g --> l) sequentially)`,
3176   SIMP_TAC[LIM_CASES_FINITE_SEQUENTIALLY; LIM_CASES_COFINITE_SEQUENTIALLY;
3177            NOT_LE; NOT_LT; FINITE_NUMSEG_LT; FINITE_NUMSEG_LE]);;
3178
3179 (* ------------------------------------------------------------------------- *)
3180 (* A congruence rule allowing us to transform limits assuming not at point.  *)
3181 (* ------------------------------------------------------------------------- *)
3182
3183 let LIM_CONG_WITHIN = prove
3184  (`(!x. ~(x = a) ==> f x = g x)
3185    ==> (((\x. f x) --> l) (at a within s) <=> ((g --> l) (at a within s)))`,
3186   REWRITE_TAC[LIM_WITHIN; GSYM DIST_NZ] THEN SIMP_TAC[]);;
3187
3188 let LIM_CONG_AT = prove
3189  (`(!x. ~(x = a) ==> f x = g x)
3190    ==> (((\x. f x) --> l) (at a) <=> ((g --> l) (at a)))`,
3191   REWRITE_TAC[LIM_AT; GSYM DIST_NZ] THEN SIMP_TAC[]);;
3192
3193 extend_basic_congs [LIM_CONG_WITHIN; LIM_CONG_AT];;
3194
3195 (* ------------------------------------------------------------------------- *)
3196 (* Useful lemmas on closure and set of possible sequential limits.           *)
3197 (* ------------------------------------------------------------------------- *)
3198
3199 let CLOSURE_SEQUENTIAL = prove
3200  (`!s l:real^N.
3201      l IN closure(s) <=> ?x. (!n. x(n) IN s) /\ (x --> l) sequentially`,
3202   REWRITE_TAC[closure; IN_UNION; LIMPT_SEQUENTIAL; IN_ELIM_THM; IN_DELETE] THEN
3203   REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
3204     `((b ==> c) /\ (~a /\ c ==> b)) /\ (a ==> c) ==> (a \/ b <=> c)`) THEN
3205   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN DISCH_TAC THEN
3206   EXISTS_TAC `\n:num. l:real^N` THEN
3207   ASM_REWRITE_TAC[LIM_CONST]);;
3208
3209 let CLOSED_CONTAINS_SEQUENTIAL_LIMIT = prove
3210  (`!s x l:real^N.
3211         closed s /\ (!n. x n IN s) /\ (x --> l) sequentially ==> l IN s`,
3212   MESON_TAC[CLOSURE_SEQUENTIAL; CLOSURE_CLOSED]);;
3213
3214 let CLOSED_SEQUENTIAL_LIMITS = prove
3215  (`!s. closed s <=>
3216        !x l. (!n. x(n) IN s) /\ (x --> l) sequentially ==> l IN s`,
3217   MESON_TAC[CLOSURE_SEQUENTIAL; CLOSURE_CLOSED;
3218             CLOSED_LIMPT; LIMPT_SEQUENTIAL; IN_DELETE]);;
3219
3220 let CLOSURE_APPROACHABLE = prove
3221  (`!x s. x IN closure(s) <=> !e. &0 < e ==> ?y. y IN s /\ dist(y,x) < e`,
3222   REWRITE_TAC[closure; LIMPT_APPROACHABLE; IN_UNION; IN_ELIM_THM] THEN
3223   MESON_TAC[DIST_REFL]);;
3224
3225 let CLOSED_APPROACHABLE = prove
3226  (`!x s. closed s
3227          ==> ((!e. &0 < e ==> ?y. y IN s /\ dist(y,x) < e) <=> x IN s)`,
3228   MESON_TAC[CLOSURE_CLOSED; CLOSURE_APPROACHABLE]);;
3229
3230 let IN_CLOSURE_DELETE = prove
3231  (`!s x:real^N. x IN closure(s DELETE x) <=> x limit_point_of s`,
3232   SIMP_TAC[CLOSURE_APPROACHABLE; LIMPT_APPROACHABLE; IN_DELETE; CONJ_ASSOC]);;
3233
3234 (* ------------------------------------------------------------------------- *)
3235 (* Some other lemmas about sequences.                                        *)
3236 (* ------------------------------------------------------------------------- *)
3237
3238 let SEQ_OFFSET = prove
3239  (`!f l k. (f --> l) sequentially ==> ((\i. f(i + k)) --> l) sequentially`,
3240   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
3241   MESON_TAC[ARITH_RULE `N <= n ==> N <= n + k:num`]);;
3242
3243 let SEQ_OFFSET_NEG = prove
3244  (`!f l k. (f --> l) sequentially ==> ((\i. f(i - k)) --> l) sequentially`,
3245   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
3246   MESON_TAC[ARITH_RULE `N + k <= n ==> N <= n - k:num`]);;
3247
3248 let SEQ_OFFSET_REV = prove
3249  (`!f l k. ((\i. f(i + k)) --> l) sequentially ==> (f --> l) sequentially`,
3250   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
3251   MESON_TAC[ARITH_RULE `N + k <= n ==> N <= n - k /\ (n - k) + k = n:num`]);;
3252
3253 let SEQ_HARMONIC = prove
3254  (`((\n. lift(inv(&n))) --> vec 0) sequentially`,
3255   REWRITE_TAC[LIM_SEQUENTIALLY] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3256   FIRST_ASSUM(X_CHOOSE_THEN `N:num` STRIP_ASSUME_TAC o
3257     GEN_REWRITE_RULE I [REAL_ARCH_INV]) THEN
3258   EXISTS_TAC `N:num` THEN REPEAT STRIP_TAC THEN
3259   REWRITE_TAC[dist; VECTOR_SUB_RZERO; NORM_LIFT] THEN
3260   ASM_REWRITE_TAC[REAL_ABS_INV; REAL_ABS_NUM] THEN
3261   MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&N)` THEN
3262   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
3263   ASM_REWRITE_TAC[REAL_OF_NUM_LT; REAL_OF_NUM_LE; LT_NZ]);;
3264
3265 (* ------------------------------------------------------------------------- *)
3266 (* More properties of closed balls.                                          *)
3267 (* ------------------------------------------------------------------------- *)
3268
3269 let CLOSED_CBALL = prove
3270  (`!x:real^N e. closed(cball(x,e))`,
3271   REWRITE_TAC[CLOSED_SEQUENTIAL_LIMITS; IN_CBALL; dist] THEN
3272   GEN_TAC THEN GEN_TAC THEN X_GEN_TAC `s:num->real^N` THEN
3273   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
3274   MATCH_MP_TAC(ISPEC `sequentially` LIM_NORM_UBOUND) THEN
3275   EXISTS_TAC `\n. x - (s:num->real^N) n` THEN
3276   REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; EVENTUALLY_SEQUENTIALLY] THEN
3277   ASM_SIMP_TAC[LIM_SUB; LIM_CONST; SEQUENTIALLY] THEN MESON_TAC[GE_REFL]);;
3278
3279 let IN_INTERIOR_CBALL = prove
3280  (`!x s. x IN interior s <=> ?e. &0 < e /\ cball(x,e) SUBSET s`,
3281   REWRITE_TAC[interior; IN_ELIM_THM] THEN
3282   MESON_TAC[OPEN_CONTAINS_CBALL; SUBSET_TRANS;
3283             BALL_SUBSET_CBALL; CENTRE_IN_BALL; OPEN_BALL]);;
3284
3285 let LIMPT_BALL = prove
3286  (`!x:real^N y e. y limit_point_of ball(x,e) <=> &0 < e /\ y IN cball(x,e)`,
3287   REPEAT GEN_TAC THEN ASM_CASES_TAC `&0 < e` THENL
3288    [ALL_TAC; ASM_MESON_TAC[LIMPT_EMPTY; REAL_NOT_LT; BALL_EQ_EMPTY]] THEN
3289   ASM_REWRITE_TAC[] THEN EQ_TAC THENL
3290    [MESON_TAC[CLOSED_CBALL; CLOSED_LIMPT; LIMPT_SUBSET; BALL_SUBSET_CBALL];
3291     REWRITE_TAC[IN_CBALL; LIMPT_APPROACHABLE; IN_BALL]] THEN
3292   DISCH_TAC THEN X_GEN_TAC `d:real` THEN DISCH_TAC THEN
3293   ASM_CASES_TAC `y:real^N = x` THEN ASM_REWRITE_TAC[DIST_NZ] THENL
3294    [MP_TAC(SPECL [`d:real`; `e:real`] REAL_DOWN2) THEN
3295     ASM_REWRITE_TAC[] THEN
3296     GEN_MESON_TAC 0 40 1 [VECTOR_CHOOSE_DIST; DIST_SYM; REAL_LT_IMP_LE];
3297     ALL_TAC] THEN
3298   MP_TAC(SPECL [`norm(y:real^N - x)`; `d:real`] REAL_DOWN2) THEN
3299   RULE_ASSUM_TAC(REWRITE_RULE[DIST_NZ; dist]) THEN ASM_REWRITE_TAC[] THEN
3300   DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
3301   EXISTS_TAC `(y:real^N) - (k / dist(y,x)) % (y - x)` THEN
3302   REWRITE_TAC[dist; VECTOR_ARITH `(y - c % z) - y = --c % z`] THEN
3303   REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_ABS_NEG] THEN
3304   ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_LT_IMP_NZ] THEN
3305   REWRITE_TAC[VECTOR_ARITH `x - (y - k % (y - x)) = (&1 - k) % (x - y)`] THEN
3306   ASM_SIMP_TAC[REAL_ARITH `&0 < k ==> &0 < abs k`; NORM_MUL] THEN
3307   ASM_SIMP_TAC[REAL_ARITH `&0 < k /\ k < d ==> abs k < d`] THEN
3308   MATCH_MP_TAC REAL_LTE_TRANS THEN EXISTS_TAC `norm(x:real^N - y)` THEN
3309   ASM_REWRITE_TAC[] THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN
3310   MATCH_MP_TAC REAL_LT_RMUL THEN CONJ_TAC THENL
3311    [ALL_TAC; ASM_MESON_TAC[NORM_SUB]] THEN
3312   MATCH_MP_TAC(REAL_ARITH `&0 < k /\ k < &1 ==> abs(&1 - k) < &1`) THEN
3313   ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_MUL_LZERO;
3314                REAL_MUL_LID]);;
3315
3316 let CLOSURE_BALL = prove
3317  (`!x:real^N e. &0 < e ==> (closure(ball(x,e)) = cball(x,e))`,
3318   SIMP_TAC[EXTENSION; closure; IN_ELIM_THM; IN_UNION; LIMPT_BALL] THEN
3319   REWRITE_TAC[IN_BALL; IN_CBALL] THEN REAL_ARITH_TAC);;
3320
3321 let INTERIOR_CBALL = prove
3322  (`!x:real^N e. interior(cball(x,e)) = ball(x,e)`,
3323   REPEAT GEN_TAC THEN ASM_CASES_TAC `&0 <= e` THENL
3324    [ALL_TAC;
3325     SUBGOAL_THEN `cball(x:real^N,e) = {} /\ ball(x:real^N,e) = {}`
3326      (fun th -> REWRITE_TAC[th; INTERIOR_EMPTY]) THEN
3327     REWRITE_TAC[IN_BALL; IN_CBALL; EXTENSION; NOT_IN_EMPTY] THEN
3328     CONJ_TAC THEN X_GEN_TAC `y:real^N` THEN
3329     MP_TAC(ISPECL [`x:real^N`; `y:real^N`] DIST_POS_LE) THEN
3330     POP_ASSUM MP_TAC THEN REAL_ARITH_TAC] THEN
3331   MATCH_MP_TAC INTERIOR_UNIQUE THEN
3332   REWRITE_TAC[BALL_SUBSET_CBALL; OPEN_BALL] THEN
3333   X_GEN_TAC `t:real^N->bool` THEN
3334   SIMP_TAC[SUBSET; IN_CBALL; IN_BALL; REAL_LT_LE] THEN STRIP_TAC THEN
3335   X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
3336   FIRST_X_ASSUM(MP_TAC o SPEC `z:real^N` o GEN_REWRITE_RULE I [open_def]) THEN
3337   ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` MP_TAC) THEN
3338   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
3339   ASM_CASES_TAC `z:real^N = x` THENL
3340    [FIRST_X_ASSUM SUBST_ALL_TAC THEN
3341     FIRST_X_ASSUM(X_CHOOSE_TAC `k:real` o MATCH_MP REAL_DOWN) THEN
3342     SUBGOAL_THEN `?w:real^N. dist(w,x) = k` STRIP_ASSUME_TAC THENL
3343      [ASM_MESON_TAC[VECTOR_CHOOSE_DIST; DIST_SYM; REAL_LT_IMP_LE];
3344       ASM_MESON_TAC[REAL_NOT_LE; DIST_REFL; DIST_SYM]];
3345     RULE_ASSUM_TAC(REWRITE_RULE[DIST_NZ]) THEN
3346     DISCH_THEN(MP_TAC o SPEC `z + ((d / &2) / dist(z,x)) % (z - x:real^N)`) THEN
3347     REWRITE_TAC[dist; VECTOR_ADD_SUB; NORM_MUL; REAL_ABS_DIV;
3348                 REAL_ABS_NORM; REAL_ABS_NUM] THEN
3349     ASM_SIMP_TAC[REAL_DIV_RMUL; GSYM dist; REAL_LT_IMP_NZ] THEN
3350     ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
3351     ASM_REWRITE_TAC[REAL_ARITH `abs d < d * &2 <=> &0 < d`] THEN
3352     DISCH_THEN(ANTE_RES_THEN MP_TAC) THEN REWRITE_TAC[dist] THEN
3353     REWRITE_TAC[VECTOR_ARITH `x - (z + k % (z - x)) = (&1 + k) % (x - z)`] THEN
3354     REWRITE_TAC[REAL_NOT_LE; NORM_MUL] THEN
3355     GEN_REWRITE_TAC LAND_CONV [GSYM REAL_MUL_LID] THEN
3356     ONCE_REWRITE_TAC[NORM_SUB] THEN
3357     ASM_SIMP_TAC[REAL_LT_RMUL_EQ; GSYM dist] THEN
3358     MATCH_MP_TAC(REAL_ARITH `&0 < x ==> &1 < abs(&1 + x)`) THEN
3359     ONCE_REWRITE_TAC[DIST_SYM] THEN
3360     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH]]);;
3361
3362 let FRONTIER_BALL = prove
3363  (`!a e. &0 < e ==> frontier(ball(a,e)) = sphere(a,e)`,
3364   SIMP_TAC[frontier; sphere; CLOSURE_BALL; INTERIOR_OPEN; OPEN_BALL;
3365            REAL_LT_IMP_LE] THEN
3366   REWRITE_TAC[EXTENSION; IN_DIFF; IN_ELIM_THM; IN_BALL; IN_CBALL] THEN
3367   REAL_ARITH_TAC);;
3368
3369 let FRONTIER_CBALL = prove
3370  (`!a e. frontier(cball(a,e)) = sphere(a,e)`,
3371   SIMP_TAC[frontier; sphere; INTERIOR_CBALL; CLOSED_CBALL; CLOSURE_CLOSED;
3372            REAL_LT_IMP_LE] THEN
3373   REWRITE_TAC[EXTENSION; IN_DIFF; IN_ELIM_THM; IN_BALL; IN_CBALL] THEN
3374   REAL_ARITH_TAC);;
3375
3376 let CBALL_EQ_EMPTY = prove
3377  (`!x e. (cball(x,e) = {}) <=> e < &0`,
3378   REWRITE_TAC[EXTENSION; IN_CBALL; NOT_IN_EMPTY; REAL_NOT_LE] THEN
3379   MESON_TAC[DIST_POS_LE; DIST_REFL; REAL_LTE_TRANS]);;
3380
3381 let CBALL_EMPTY = prove
3382  (`!x e. e < &0 ==> cball(x,e) = {}`,
3383   REWRITE_TAC[CBALL_EQ_EMPTY]);;
3384
3385 let CBALL_EQ_SING = prove
3386  (`!x:real^N e. (cball(x,e) = {x}) <=> e = &0`,
3387   REPEAT GEN_TAC THEN REWRITE_TAC[EXTENSION; IN_CBALL; IN_SING] THEN
3388   EQ_TAC THENL [ALL_TAC; MESON_TAC[DIST_LE_0]] THEN
3389   DISCH_THEN(fun th -> MP_TAC(SPEC `x + (e / &2) % basis 1:real^N` th) THEN
3390                        MP_TAC(SPEC `x:real^N` th)) THEN
3391   REWRITE_TAC[dist; VECTOR_ARITH `x - (x + e):real^N = --e`;
3392               VECTOR_ARITH `x + e = x <=> e:real^N = vec 0`] THEN
3393   REWRITE_TAC[NORM_NEG; NORM_MUL; VECTOR_MUL_EQ_0; NORM_0; VECTOR_SUB_REFL] THEN
3394   SIMP_TAC[NORM_BASIS; BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1] THEN
3395   REAL_ARITH_TAC);;
3396
3397 let CBALL_SING = prove
3398  (`!x e. e = &0 ==> cball(x,e) = {x}`,
3399   REWRITE_TAC[CBALL_EQ_SING]);;
3400
3401 let SPHERE_SING = prove
3402  (`!x e. e = &0 ==> sphere(x,e) = {x}`,
3403   SIMP_TAC[sphere; DIST_EQ_0; SING_GSPEC]);;
3404
3405 let SPHERE_EQ_SING = prove
3406  (`!a:real^N r x. sphere(a,r) = {x} <=> x = a /\ r = &0`,
3407   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[SPHERE_SING] THEN
3408   ASM_CASES_TAC `r < &0` THEN ASM_SIMP_TAC[SPHERE_EMPTY; NOT_INSERT_EMPTY] THEN
3409   ASM_CASES_TAC `r = &0` THEN ASM_SIMP_TAC[SPHERE_SING] THENL
3410    [ASM SET_TAC[]; ALL_TAC] THEN
3411   MATCH_MP_TAC(SET_RULE
3412    `!y. (x IN s ==> y IN s /\ ~(y = x)) ==> ~(s = {x})`) THEN
3413   EXISTS_TAC `a - (x - a):real^N` THEN REWRITE_TAC[IN_SPHERE] THEN
3414   REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC NORM_ARITH);;
3415
3416 (* ------------------------------------------------------------------------- *)
3417 (* For points in the interior, localization of limits makes no difference.   *)
3418 (* ------------------------------------------------------------------------- *)
3419
3420 let EVENTUALLY_WITHIN_INTERIOR = prove
3421  (`!p s x.
3422         x IN interior s
3423         ==> (eventually p (at x within s) <=> eventually p (at x))`,
3424   REWRITE_TAC[EVENTUALLY_WITHIN; EVENTUALLY_AT; IN_INTERIOR] THEN
3425   REPEAT GEN_TAC THEN SIMP_TAC[SUBSET; IN_BALL; LEFT_IMP_FORALL_THM] THEN
3426   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
3427   EQ_TAC THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
3428   EXISTS_TAC `min (d:real) e` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
3429   ASM_MESON_TAC[DIST_SYM]);;
3430
3431 let LIM_WITHIN_INTERIOR = prove
3432  (`!f l s x.
3433         x IN interior s
3434         ==> ((f --> l) (at x within s) <=> (f --> l) (at x))`,
3435   SIMP_TAC[tendsto; EVENTUALLY_WITHIN_INTERIOR]);;
3436
3437 let NETLIMIT_WITHIN_INTERIOR = prove
3438  (`!s x:real^N. x IN interior s ==> netlimit(at x within s) = x`,
3439   REPEAT STRIP_TAC THEN MATCH_MP_TAC NETLIMIT_WITHIN THEN
3440   REWRITE_TAC[TRIVIAL_LIMIT_WITHIN] THEN
3441   FIRST_ASSUM(MP_TAC o MATCH_MP(REWRITE_RULE[OPEN_CONTAINS_BALL]
3442    (SPEC_ALL OPEN_INTERIOR))) THEN
3443   ASM_MESON_TAC[LIMPT_SUBSET; LIMPT_BALL; CENTRE_IN_CBALL; REAL_LT_IMP_LE;
3444                 SUBSET_TRANS; INTERIOR_SUBSET]);;
3445
3446 (* ------------------------------------------------------------------------- *)
3447 (* A non-singleton connected set is perfect (i.e. has no isolated points).   *)
3448 (* ------------------------------------------------------------------------- *)
3449
3450 let CONNECTED_IMP_PERFECT = prove
3451  (`!s x:real^N.
3452         connected s /\ ~(?a. s = {a}) /\ x IN s ==> x limit_point_of s`,
3453   REPEAT STRIP_TAC THEN REWRITE_TAC[limit_point_of] THEN
3454   X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
3455   MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
3456   FIRST_ASSUM(MP_TAC o SPEC `x:real^N` o GEN_REWRITE_RULE I
3457    [OPEN_CONTAINS_CBALL]) THEN
3458   ASM_REWRITE_TAC[] THEN
3459   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
3460   FIRST_X_ASSUM(MP_TAC o SPEC `{x:real^N}` o
3461     GEN_REWRITE_RULE I [CONNECTED_CLOPEN]) THEN
3462   REWRITE_TAC[NOT_IMP] THEN REPEAT CONJ_TAC THENL
3463    [REWRITE_TAC[OPEN_IN_OPEN] THEN EXISTS_TAC `t:real^N->bool` THEN
3464     ASM SET_TAC[];
3465     REWRITE_TAC[CLOSED_IN_CLOSED] THEN
3466     EXISTS_TAC `cball(x:real^N,e)` THEN REWRITE_TAC[CLOSED_CBALL] THEN
3467     REWRITE_TAC[EXTENSION; IN_INTER; IN_SING] THEN
3468     ASM_MESON_TAC[CENTRE_IN_CBALL; SUBSET; REAL_LT_IMP_LE];
3469     ASM SET_TAC[]]);;
3470
3471 (* ------------------------------------------------------------------------- *)
3472 (* Boundedness.                                                              *)
3473 (* ------------------------------------------------------------------------- *)
3474
3475 let bounded = new_definition
3476   `bounded s <=> ?a. !x:real^N. x IN s ==> norm(x) <= a`;;
3477
3478 let BOUNDED_EMPTY = prove
3479  (`bounded {}`,
3480   REWRITE_TAC[bounded; NOT_IN_EMPTY]);;
3481
3482 let BOUNDED_SUBSET = prove
3483  (`!s t. bounded t /\ s SUBSET t ==> bounded s`,
3484   MESON_TAC[bounded; SUBSET]);;
3485
3486 let BOUNDED_INTERIOR = prove
3487  (`!s:real^N->bool. bounded s ==> bounded(interior s)`,
3488   MESON_TAC[BOUNDED_SUBSET; INTERIOR_SUBSET]);;
3489
3490 let BOUNDED_CLOSURE = prove
3491  (`!s:real^N->bool. bounded s ==> bounded(closure s)`,
3492   REWRITE_TAC[bounded; CLOSURE_SEQUENTIAL] THEN
3493   GEN_TAC THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
3494   MESON_TAC[REWRITE_RULE[eventually] LIM_NORM_UBOUND;
3495             TRIVIAL_LIMIT_SEQUENTIALLY; trivial_limit]);;
3496
3497 let BOUNDED_CLOSURE_EQ = prove
3498  (`!s:real^N->bool. bounded(closure s) <=> bounded s`,
3499   GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[BOUNDED_CLOSURE] THEN
3500   MESON_TAC[BOUNDED_SUBSET; CLOSURE_SUBSET]);;
3501
3502 let BOUNDED_CBALL = prove
3503  (`!x:real^N e. bounded(cball(x,e))`,
3504   REPEAT GEN_TAC THEN REWRITE_TAC[bounded] THEN
3505   EXISTS_TAC `norm(x:real^N) + e` THEN REWRITE_TAC[IN_CBALL; dist] THEN
3506   NORM_ARITH_TAC);;
3507
3508 let BOUNDED_BALL = prove
3509  (`!x e. bounded(ball(x,e))`,
3510   MESON_TAC[BALL_SUBSET_CBALL; BOUNDED_CBALL; BOUNDED_SUBSET]);;
3511
3512 let FINITE_IMP_BOUNDED = prove
3513  (`!s:real^N->bool. FINITE s ==> bounded s`,
3514   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN REWRITE_TAC[BOUNDED_EMPTY] THEN
3515   REWRITE_TAC[bounded; IN_INSERT] THEN X_GEN_TAC `x:real^N` THEN GEN_TAC THEN
3516   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `B:real`) STRIP_ASSUME_TAC) THEN
3517   EXISTS_TAC `norm(x:real^N) + abs B` THEN REPEAT STRIP_TAC THEN
3518   ASM_MESON_TAC[NORM_POS_LE; REAL_ARITH
3519    `(y <= b /\ &0 <= x ==> y <= x + abs b) /\ x <= x + abs b`]);;
3520
3521 let BOUNDED_UNION = prove
3522  (`!s t. bounded (s UNION t) <=> bounded s /\ bounded t`,
3523   REWRITE_TAC[bounded; IN_UNION] THEN MESON_TAC[REAL_LE_MAX]);;
3524
3525 let BOUNDED_UNIONS = prove
3526  (`!f. FINITE f /\ (!s. s IN f ==> bounded s) ==> bounded(UNIONS f)`,
3527   REWRITE_TAC[IMP_CONJ] THEN
3528   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
3529   REWRITE_TAC[UNIONS_0; BOUNDED_EMPTY; IN_INSERT; UNIONS_INSERT] THEN
3530   MESON_TAC[BOUNDED_UNION]);;
3531
3532 let BOUNDED_POS = prove
3533  (`!s. bounded s <=> ?b. &0 < b /\ !x. x IN s ==> norm(x) <= b`,
3534   REWRITE_TAC[bounded] THEN
3535   MESON_TAC[REAL_ARITH `&0 < &1 + abs(y) /\ (x <= y ==> x <= &1 + abs(y))`]);;
3536
3537 let BOUNDED_POS_LT = prove
3538  (`!s. bounded s <=> ?b. &0 < b /\ !x. x IN s ==> norm(x) < b`,
3539   REWRITE_TAC[bounded] THEN
3540   MESON_TAC[REAL_LT_IMP_LE;
3541             REAL_ARITH `&0 < &1 + abs(y) /\ (x <= y ==> x < &1 + abs(y))`]);;
3542
3543 let BOUNDED_INTER = prove
3544  (`!s t. bounded s \/ bounded t ==> bounded (s INTER t)`,
3545   MESON_TAC[BOUNDED_SUBSET; INTER_SUBSET]);;
3546
3547 let BOUNDED_DIFF = prove
3548  (`!s t. bounded s ==> bounded (s DIFF t)`,
3549   MESON_TAC[BOUNDED_SUBSET; SUBSET_DIFF]);;
3550
3551 let BOUNDED_INSERT = prove
3552  (`!x s. bounded(x INSERT s) <=> bounded s`,
3553   ONCE_REWRITE_TAC[SET_RULE `x INSERT s = {x} UNION s`] THEN
3554   SIMP_TAC[BOUNDED_UNION; FINITE_IMP_BOUNDED; FINITE_RULES]);;
3555
3556 let BOUNDED_SING = prove
3557  (`!a. bounded {a}`,
3558   REWRITE_TAC[BOUNDED_INSERT; BOUNDED_EMPTY]);;
3559
3560 let BOUNDED_INTERS = prove
3561  (`!f:(real^N->bool)->bool.
3562         (?s:real^N->bool. s IN f /\ bounded s) ==> bounded(INTERS f)`,
3563   REWRITE_TAC[LEFT_IMP_EXISTS_THM; IMP_CONJ] THEN REPEAT GEN_TAC THEN
3564   DISCH_TAC THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] BOUNDED_SUBSET) THEN
3565   ASM SET_TAC[]);;
3566
3567 let NOT_BOUNDED_UNIV = prove
3568  (`~(bounded (:real^N))`,
3569   REWRITE_TAC[BOUNDED_POS; NOT_FORALL_THM; NOT_EXISTS_THM; IN_UNIV;
3570               DE_MORGAN_THM; REAL_NOT_LE] THEN
3571   X_GEN_TAC `B:real` THEN ASM_CASES_TAC `&0 < B` THEN ASM_REWRITE_TAC[] THEN
3572   MP_TAC(SPEC `B + &1` VECTOR_CHOOSE_SIZE) THEN
3573   ASM_SIMP_TAC[REAL_ARITH `&0 < B ==> &0 <= B + &1`] THEN
3574   MATCH_MP_TAC MONO_EXISTS THEN REAL_ARITH_TAC);;
3575
3576 let COBOUNDED_IMP_UNBOUNDED = prove
3577  (`!s. bounded((:real^N) DIFF s) ==> ~bounded s`,
3578   GEN_TAC THEN REWRITE_TAC[TAUT `a ==> ~b <=> ~(a /\ b)`] THEN
3579   REWRITE_TAC[GSYM BOUNDED_UNION; SET_RULE `UNIV DIFF s UNION s = UNIV`] THEN
3580   REWRITE_TAC[NOT_BOUNDED_UNIV]);;
3581
3582 let BOUNDED_LINEAR_IMAGE = prove
3583  (`!f:real^M->real^N s. bounded s /\ linear f ==> bounded(IMAGE f s)`,
3584   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS] THEN
3585   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `B1:real`) MP_TAC) THEN
3586   DISCH_THEN(X_CHOOSE_TAC `B2:real` o MATCH_MP LINEAR_BOUNDED_POS) THEN
3587   EXISTS_TAC `B2 * B1` THEN ASM_SIMP_TAC[REAL_LT_MUL; FORALL_IN_IMAGE] THEN
3588   X_GEN_TAC `x:real^M` THEN STRIP_TAC THEN
3589   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `B2 * norm(x:real^M)` THEN
3590   ASM_SIMP_TAC[REAL_LE_LMUL_EQ]);;
3591
3592 let BOUNDED_LINEAR_IMAGE_EQ = prove
3593  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
3594          ==> (bounded (IMAGE f s) <=> bounded s)`,
3595   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE BOUNDED_LINEAR_IMAGE));;
3596
3597 add_linear_invariants [BOUNDED_LINEAR_IMAGE_EQ];;
3598
3599 let BOUNDED_SCALING = prove
3600  (`!c s. bounded s ==> bounded (IMAGE (\x. c % x) s)`,
3601   REPEAT STRIP_TAC THEN MATCH_MP_TAC BOUNDED_LINEAR_IMAGE THEN
3602   ASM_SIMP_TAC[LINEAR_COMPOSE_CMUL; LINEAR_ID]);;
3603
3604 let BOUNDED_NEGATIONS = prove
3605  (`!s. bounded s ==> bounded (IMAGE (--) s)`,
3606   GEN_TAC THEN
3607   DISCH_THEN(MP_TAC o SPEC `-- &1` o MATCH_MP BOUNDED_SCALING) THEN
3608   REWRITE_TAC[bounded; IN_IMAGE; VECTOR_MUL_LNEG; VECTOR_MUL_LID]);;
3609
3610 let BOUNDED_TRANSLATION = prove
3611  (`!a:real^N s. bounded s ==> bounded (IMAGE (\x. a + x) s)`,
3612   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE] THEN
3613   DISCH_THEN(X_CHOOSE_TAC `B:real`) THEN
3614   EXISTS_TAC `B + norm(a:real^N)` THEN POP_ASSUM MP_TAC THEN
3615   MATCH_MP_TAC MONO_AND THEN CONJ_TAC THENL [NORM_ARITH_TAC; ALL_TAC] THEN
3616   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
3617   REWRITE_TAC[] THEN NORM_ARITH_TAC);;
3618
3619 let BOUNDED_TRANSLATION_EQ = prove
3620  (`!a s. bounded (IMAGE (\x:real^N. a + x) s) <=> bounded s`,
3621   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[BOUNDED_TRANSLATION] THEN
3622   DISCH_THEN(MP_TAC o SPEC `--a:real^N` o MATCH_MP BOUNDED_TRANSLATION) THEN
3623   REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID;
3624               VECTOR_ARITH `--a + a + x:real^N = x`]);;
3625
3626 add_translation_invariants [BOUNDED_TRANSLATION_EQ];;
3627
3628 let BOUNDED_DIFFS = prove
3629  (`!s t:real^N->bool.
3630         bounded s /\ bounded t ==> bounded {x - y | x IN s /\ y IN t}`,
3631   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS] THEN
3632   DISCH_THEN(CONJUNCTS_THEN2
3633    (X_CHOOSE_TAC `B:real`) (X_CHOOSE_TAC `C:real`)) THEN
3634   EXISTS_TAC `B + C:real` THEN REWRITE_TAC[IN_ELIM_THM] THEN
3635   CONJ_TAC THENL [ASM_REAL_ARITH_TAC; REPEAT STRIP_TAC] THEN
3636   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(NORM_ARITH
3637    `norm x <= a /\ norm y <= b ==> norm(x - y) <= a + b`) THEN
3638   ASM_SIMP_TAC[]);;
3639
3640 let BOUNDED_SUMS = prove
3641  (`!s t:real^N->bool.
3642         bounded s /\ bounded t ==> bounded {x + y | x IN s /\ y IN t}`,
3643   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS] THEN
3644   DISCH_THEN(CONJUNCTS_THEN2
3645    (X_CHOOSE_TAC `B:real`) (X_CHOOSE_TAC `C:real`)) THEN
3646   EXISTS_TAC `B + C:real` THEN REWRITE_TAC[IN_ELIM_THM] THEN
3647   CONJ_TAC THENL [ASM_REAL_ARITH_TAC; REPEAT STRIP_TAC] THEN
3648   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(NORM_ARITH
3649    `norm x <= a /\ norm y <= b ==> norm(x + y) <= a + b`) THEN
3650   ASM_SIMP_TAC[]);;
3651
3652 let BOUNDED_SUMS_IMAGE = prove
3653  (`!f g t. bounded {f x | x IN t} /\ bounded {g x | x IN t}
3654            ==> bounded {f x + g x | x IN t}`,
3655   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP BOUNDED_SUMS) THEN
3656   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] BOUNDED_SUBSET) THEN
3657   SET_TAC[]);;
3658
3659 let BOUNDED_SUMS_IMAGES = prove
3660  (`!f:A->B->real^N t s.
3661         FINITE s /\
3662         (!a. a IN s ==> bounded {f x a | x IN t})
3663         ==> bounded { vsum s (f x) | x IN t}`,
3664   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
3665   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
3666   SIMP_TAC[VSUM_CLAUSES] THEN CONJ_TAC THENL
3667    [DISCH_THEN(K ALL_TAC) THEN MATCH_MP_TAC BOUNDED_SUBSET THEN
3668     EXISTS_TAC `{vec 0:real^N}` THEN
3669     SIMP_TAC[FINITE_IMP_BOUNDED; FINITE_RULES] THEN SET_TAC[];
3670     ALL_TAC] THEN
3671   REPEAT STRIP_TAC THEN MATCH_MP_TAC BOUNDED_SUMS_IMAGE THEN
3672   ASM_SIMP_TAC[IN_INSERT]);;
3673
3674 let BOUNDED_SUBSET_BALL = prove
3675  (`!s x:real^N. bounded(s) ==> ?r. &0 < r /\ s SUBSET ball(x,r)`,
3676   REPEAT GEN_TAC THEN REWRITE_TAC[BOUNDED_POS] THEN
3677   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
3678   EXISTS_TAC `&2 * B + norm(x:real^N)` THEN
3679   ASM_SIMP_TAC[NORM_POS_LE; REAL_ARITH
3680     `&0 < B /\ &0 <= x ==> &0 < &2 * B + x`] THEN
3681   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
3682   FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[IN_BALL] THEN
3683   UNDISCH_TAC `&0 < B` THEN NORM_ARITH_TAC);;
3684
3685 let BOUNDED_SUBSET_CBALL = prove
3686  (`!s x:real^N. bounded(s) ==> ?r. &0 < r /\ s SUBSET cball(x,r)`,
3687   MESON_TAC[BOUNDED_SUBSET_BALL; SUBSET_TRANS; BALL_SUBSET_CBALL]);;
3688
3689 let UNBOUNDED_INTER_COBOUNDED = prove
3690  (`!s t. ~bounded s /\ bounded((:real^N) DIFF t) ==> ~(s INTER t = {})`,
3691   REWRITE_TAC[SET_RULE `s INTER t = {} <=> s SUBSET (:real^N) DIFF t`] THEN
3692   MESON_TAC[BOUNDED_SUBSET]);;
3693
3694 let COBOUNDED_INTER_UNBOUNDED = prove
3695  (`!s t. bounded((:real^N) DIFF s) /\ ~bounded t ==> ~(s INTER t = {})`,
3696   REWRITE_TAC[SET_RULE `s INTER t = {} <=> t SUBSET (:real^N) DIFF s`] THEN
3697   MESON_TAC[BOUNDED_SUBSET]);;
3698
3699 let SUBSPACE_BOUNDED_EQ_TRIVIAL = prove
3700  (`!s:real^N->bool. subspace s ==> (bounded s <=> s = {vec 0})`,
3701   REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[BOUNDED_SING] THEN
3702   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
3703   DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
3704    `~(s = {a}) ==> a IN s ==> ?b. b IN s /\ ~(b = a)`)) THEN
3705   ASM_SIMP_TAC[SUBSPACE_0] THEN
3706   DISCH_THEN(X_CHOOSE_THEN `v:real^N` STRIP_ASSUME_TAC) THEN
3707   REWRITE_TAC[bounded; NOT_EXISTS_THM] THEN X_GEN_TAC `B:real` THEN
3708   DISCH_THEN(MP_TAC o SPEC `(B + &1) / norm v % v:real^N`) THEN
3709   ASM_SIMP_TAC[SUBSPACE_MUL; NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
3710   ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN REAL_ARITH_TAC);;
3711
3712 let BOUNDED_COMPONENTWISE = prove
3713  (`!s:real^N->bool.
3714         bounded s <=> !i. 1 <= i /\ i <= dimindex(:N)
3715                           ==> bounded (IMAGE (\x. lift(x$i)) s)`,
3716   GEN_TAC THEN REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE; NORM_LIFT] THEN
3717   EQ_TAC THENL [ASM_MESON_TAC[COMPONENT_LE_NORM; REAL_LE_TRANS]; ALL_TAC] THEN
3718   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
3719   SIMP_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `b:num->real` THEN
3720   DISCH_TAC THEN EXISTS_TAC `sum(1..dimindex(:N)) b` THEN CONJ_TAC THENL
3721    [MATCH_MP_TAC REAL_LET_TRANS THEN
3722     EXISTS_TAC `sum(1..dimindex(:N)) (\i. &0)` THEN
3723     SIMP_TAC[SUM_POS_LE_NUMSEG; REAL_POS] THEN
3724     MATCH_MP_TAC SUM_LT_ALL THEN
3725     ASM_SIMP_TAC[IN_NUMSEG; FINITE_NUMSEG; NUMSEG_EMPTY] THEN
3726     REWRITE_TAC[NOT_LT; DIMINDEX_GE_1];
3727     REPEAT STRIP_TAC THEN
3728     W(MP_TAC o PART_MATCH lhand NORM_LE_L1 o lhand o snd) THEN
3729     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
3730     MATCH_MP_TAC SUM_LE THEN ASM_SIMP_TAC[IN_NUMSEG; FINITE_NUMSEG]]);;
3731
3732 (* ------------------------------------------------------------------------- *)
3733 (* Some theorems on sups and infs using the notion "bounded".                *)
3734 (* ------------------------------------------------------------------------- *)
3735
3736 let BOUNDED_LIFT = prove
3737  (`!s. bounded(IMAGE lift s) <=>  ?a. !x. x IN s ==> abs(x) <= a`,
3738   REWRITE_TAC[bounded; FORALL_LIFT; NORM_LIFT; LIFT_IN_IMAGE_LIFT]);;
3739
3740 let BOUNDED_HAS_SUP = prove
3741  (`!s. bounded(IMAGE lift s) /\ ~(s = {})
3742        ==> (!x. x IN s ==> x <= sup s) /\
3743            (!b. (!x. x IN s ==> x <= b) ==> sup s <= b)`,
3744   REWRITE_TAC[BOUNDED_LIFT; IMAGE_EQ_EMPTY] THEN
3745   MESON_TAC[SUP; REAL_ARITH `abs(x) <= a ==> x <= a`]);;
3746
3747 let SUP_INSERT = prove
3748  (`!x s. bounded (IMAGE lift s)
3749          ==> sup(x INSERT s) = if s = {} then x else max x (sup s)`,
3750   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_SUP_UNIQUE THEN
3751   COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_SING] THENL
3752    [MESON_TAC[REAL_LE_REFL]; ALL_TAC] THEN
3753   REWRITE_TAC[REAL_LE_MAX; REAL_LT_MAX; IN_INSERT] THEN
3754   MP_TAC(ISPEC `s:real->bool` BOUNDED_HAS_SUP) THEN ASM_REWRITE_TAC[] THEN
3755   REPEAT STRIP_TAC THEN ASM_MESON_TAC[REAL_LE_REFL; REAL_NOT_LT]);;
3756
3757 let BOUNDED_HAS_INF = prove
3758  (`!s. bounded(IMAGE lift s) /\ ~(s = {})
3759        ==> (!x. x IN s ==> inf s <= x) /\
3760            (!b. (!x. x IN s ==> b <= x) ==> b <= inf s)`,
3761   REWRITE_TAC[BOUNDED_LIFT; IMAGE_EQ_EMPTY] THEN
3762   MESON_TAC[INF; REAL_ARITH `abs(x) <= a ==> --a <= x`]);;
3763
3764 let INF_INSERT = prove
3765  (`!x s. bounded (IMAGE lift s)
3766          ==> inf(x INSERT s) = if s = {} then x else min x (inf s)`,
3767   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_INF_UNIQUE THEN
3768   COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_SING] THENL
3769    [MESON_TAC[REAL_LE_REFL]; ALL_TAC] THEN
3770   REWRITE_TAC[REAL_MIN_LE; REAL_MIN_LT; IN_INSERT] THEN
3771   MP_TAC(ISPEC `s:real->bool` BOUNDED_HAS_INF) THEN ASM_REWRITE_TAC[] THEN
3772   REPEAT STRIP_TAC THEN ASM_MESON_TAC[REAL_LE_REFL; REAL_NOT_LT]);;
3773
3774 (* ------------------------------------------------------------------------- *)
3775 (* Subset relation on balls.                                                 *)
3776 (* ------------------------------------------------------------------------- *)
3777
3778 let SUBSET_BALLS = prove
3779  (`(!a a':real^N r r'.
3780       ball(a,r) SUBSET ball(a',r') <=> dist(a,a') + r <= r' \/ r <= &0) /\
3781    (!a a':real^N r r'.
3782       ball(a,r) SUBSET cball(a',r') <=> dist(a,a') + r <= r' \/ r <= &0) /\
3783    (!a a':real^N r r'.
3784       cball(a,r) SUBSET ball(a',r') <=> dist(a,a') + r < r' \/ r < &0) /\
3785    (!a a':real^N r r'.
3786       cball(a,r) SUBSET cball(a',r') <=> dist(a,a') + r <= r' \/ r < &0)`,
3787   let lemma = prove
3788    (`(!a':real^N r r'.
3789        cball(a,r) SUBSET cball(a',r') <=> dist(a,a') + r <= r' \/ r < &0) /\
3790      (!a':real^N r r'.
3791        cball(a,r) SUBSET ball(a',r') <=> dist(a,a') + r < r' \/ r < &0)`,
3792     CONJ_TAC THEN
3793     (GEOM_ORIGIN_TAC `a':real^N` THEN
3794     REPEAT GEN_TAC THEN REWRITE_TAC[SUBSET; IN_CBALL; IN_BALL] THEN
3795     EQ_TAC THENL [REWRITE_TAC[DIST_0]; NORM_ARITH_TAC] THEN
3796     DISJ_CASES_TAC(REAL_ARITH `r < &0 \/ &0 <= r`) THEN
3797     ASM_REWRITE_TAC[] THEN DISCH_TAC THEN DISJ1_TAC THEN
3798     ASM_CASES_TAC `a:real^N = vec 0` THENL
3799      [FIRST_X_ASSUM(MP_TAC o SPEC `r % basis 1:real^N`) THEN
3800       ASM_SIMP_TAC[DIST_0; NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL];
3801       FIRST_X_ASSUM(MP_TAC o SPEC `(&1 + r / norm(a)) % a:real^N`) THEN
3802       SIMP_TAC[dist; VECTOR_ARITH `a - (&1 + x) % a:real^N = --(x % a)`] THEN
3803       ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; NORM_NEG; REAL_POS;
3804                    REAL_LE_DIV; NORM_POS_LE; REAL_ADD_RDISTRIB; REAL_DIV_RMUL;
3805                NORM_EQ_0; REAL_ARITH `&0 <= x ==> abs(&1 + x) = &1 + x`]] THEN
3806     UNDISCH_TAC `&0 <= r` THEN NORM_ARITH_TAC))
3807   and tac = DISCH_THEN(MP_TAC o MATCH_MP SUBSET_CLOSURE) THEN
3808             ASM_SIMP_TAC[CLOSED_CBALL; CLOSURE_CLOSED; CLOSURE_BALL] in
3809   REWRITE_TAC[AND_FORALL_THM] THEN GEOM_ORIGIN_TAC `a':real^N` THEN
3810   REPEAT STRIP_TAC THEN
3811   (EQ_TAC THENL
3812     [ALL_TAC; REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL] THEN NORM_ARITH_TAC]) THEN
3813   MATCH_MP_TAC(SET_RULE
3814    `(s = {} <=> q) /\ (s SUBSET t /\ ~(s = {}) /\ ~(t = {}) ==> p)
3815     ==> s SUBSET t ==> p \/ q`) THEN
3816   REWRITE_TAC[BALL_EQ_EMPTY; CBALL_EQ_EMPTY; REAL_NOT_LE; REAL_NOT_LT] THEN
3817   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THENL
3818    [tac; tac; ALL_TAC; ALL_TAC] THEN REWRITE_TAC[lemma] THEN
3819   REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
3820
3821 (* ------------------------------------------------------------------------- *)
3822 (* Compactness (the definition is the one based on convegent subsequences).  *)
3823 (* ------------------------------------------------------------------------- *)
3824
3825 let compact = new_definition
3826   `compact s <=>
3827         !f:num->real^N.
3828             (!n. f(n) IN s)
3829             ==> ?l r. l IN s /\ (!m n:num. m < n ==> r(m) < r(n)) /\
3830                       ((f o r) --> l) sequentially`;;
3831
3832 let MONOTONE_BIGGER = prove
3833  (`!r. (!m n. m < n ==> r(m) < r(n)) ==> !n:num. n <= r(n)`,
3834   GEN_TAC THEN DISCH_TAC THEN INDUCT_TAC THEN
3835   ASM_MESON_TAC[LE_0; ARITH_RULE `n <= m /\ m < p ==> SUC n <= p`; LT]);;
3836
3837 let LIM_SUBSEQUENCE = prove
3838  (`!s r l. (!m n. m < n ==> r(m) < r(n)) /\ (s --> l) sequentially
3839            ==> (s o r --> l) sequentially`,
3840   REWRITE_TAC[LIM_SEQUENTIALLY; o_THM] THEN
3841   MESON_TAC[MONOTONE_BIGGER; LE_TRANS]);;
3842
3843 let MONOTONE_SUBSEQUENCE = prove
3844  (`!s:num->real. ?r:num->num.
3845            (!m n. m < n ==> r(m) < r(n)) /\
3846            ((!m n. m <= n ==> s(r(m)) <= s(r(n))) \/
3847             (!m n. m <= n ==> s(r(n)) <= s(r(m))))`,
3848   GEN_TAC THEN
3849   ASM_CASES_TAC `!n:num. ?p. n < p /\ !m. p <= m ==> s(m) <= s(p)` THEN
3850   POP_ASSUM MP_TAC THEN
3851   REWRITE_TAC[NOT_FORALL_THM; NOT_EXISTS_THM; NOT_IMP; DE_MORGAN_THM] THEN
3852   REWRITE_TAC[RIGHT_OR_EXISTS_THM; SKOLEM_THM; REAL_NOT_LE; REAL_NOT_LT] THENL
3853    [ABBREV_TAC `N = 0`; DISCH_THEN(X_CHOOSE_THEN `N:num` MP_TAC)] THEN
3854   DISCH_THEN(X_CHOOSE_THEN `next:num->num` STRIP_ASSUME_TAC) THEN
3855   (MP_TAC o prove_recursive_functions_exist num_RECURSION)
3856    `(r 0 = next(SUC N)) /\ (!n. r(SUC n) = next(r n))` THEN
3857   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN STRIP_TAC THENL
3858    [SUBGOAL_THEN `!m:num n:num. r n <= m ==> s(m) <= s(r n):real`
3859     ASSUME_TAC THEN TRY CONJ_TAC THEN TRY DISJ2_TAC THEN
3860     GEN_TAC THEN INDUCT_TAC THEN ASM_REWRITE_TAC[LT; LE] THEN
3861     ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_REFL; LT_IMP_LE; LT_TRANS];
3862     SUBGOAL_THEN `!n. N < (r:num->num) n` ASSUME_TAC THEN
3863     TRY(CONJ_TAC THENL [GEN_TAC; DISJ1_TAC THEN GEN_TAC]) THEN
3864     INDUCT_TAC THEN ASM_REWRITE_TAC[LT; LE] THEN
3865     TRY STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
3866     ASM_MESON_TAC[REAL_LT_REFL; LT_LE; LTE_TRANS; REAL_LE_REFL;
3867                   REAL_LT_LE; REAL_LE_TRANS; LT]]);;
3868
3869 let CONVERGENT_BOUNDED_INCREASING = prove
3870  (`!s:num->real b. (!m n. m <= n ==> s m <= s n) /\ (!n. abs(s n) <= b)
3871                    ==> ?l. !e. &0 < e ==> ?N. !n. N <= n ==> abs(s n - l) < e`,
3872   REPEAT STRIP_TAC THEN
3873   MP_TAC(SPEC `\x. ?n. (s:num->real) n = x` REAL_COMPLETE) THEN
3874   REWRITE_TAC[] THEN ANTS_TAC THENL
3875    [ASM_MESON_TAC[REAL_ARITH `abs(x) <= b ==> x <= b`]; ALL_TAC] THEN
3876   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real` THEN STRIP_TAC THEN
3877   X_GEN_TAC `e:real` THEN STRIP_TAC THEN
3878   FIRST_X_ASSUM(MP_TAC o SPEC `l - e`) THEN
3879   ASM_MESON_TAC[REAL_ARITH `&0 < e ==> ~(l <= l - e)`;
3880       REAL_ARITH `x <= y /\ y <= l /\ ~(x <= l - e) ==> abs(y - l) < e`]);;
3881
3882 let CONVERGENT_BOUNDED_MONOTONE = prove
3883  (`!s:num->real b. (!n. abs(s n) <= b) /\
3884                    ((!m n. m <= n ==> s m <= s n) \/
3885                     (!m n. m <= n ==> s n <= s m))
3886                    ==> ?l. !e. &0 < e ==> ?N. !n. N <= n ==> abs(s n - l) < e`,
3887   REPEAT STRIP_TAC THENL
3888    [ASM_MESON_TAC[CONVERGENT_BOUNDED_INCREASING]; ALL_TAC] THEN
3889   MP_TAC(SPEC `\n. --((s:num->real) n)` CONVERGENT_BOUNDED_INCREASING) THEN
3890   ASM_REWRITE_TAC[REAL_LE_NEG2; REAL_ABS_NEG] THEN
3891   ASM_MESON_TAC[REAL_ARITH `abs(x - --l) = abs(--x - l)`]);;
3892
3893 let COMPACT_REAL_LEMMA = prove
3894  (`!s b. (!n:num. abs(s n) <= b)
3895          ==> ?l r. (!m n:num. m < n ==> r(m) < r(n)) /\
3896                    !e. &0 < e ==> ?N. !n. N <= n ==> abs(s(r n) - l) < e`,
3897   REPEAT GEN_TAC THEN DISCH_TAC THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
3898   MP_TAC(SPEC `s:num->real` MONOTONE_SUBSEQUENCE) THEN
3899   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN DISCH_TAC THEN ASM_SIMP_TAC[] THEN
3900   MATCH_MP_TAC CONVERGENT_BOUNDED_MONOTONE THEN ASM_MESON_TAC[]);;
3901
3902 let COMPACT_LEMMA = prove
3903  (`!s. bounded s /\ (!n. (x:num->real^N) n IN s)
3904        ==> !d. d <= dimindex(:N)
3905                ==> ?l:real^N r. (!m n. m < n ==> r m < (r:num->num) n) /\
3906                          !e. &0 < e
3907                              ==> ?N. !n i. 1 <= i /\ i <= d
3908                                            ==> N <= n
3909                                                ==> abs(x(r n)$i - l$i) < e`,
3910   GEN_TAC THEN REWRITE_TAC[bounded] THEN
3911   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `b:real`) ASSUME_TAC) THEN
3912   INDUCT_TAC THENL
3913    [REWRITE_TAC[ARITH_RULE `1 <= i /\ i <= 0 <=> F`; CONJ_ASSOC] THEN
3914     DISCH_TAC THEN EXISTS_TAC `\n:num. n` THEN REWRITE_TAC[];
3915     ALL_TAC] THEN
3916   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o check (is_imp o concl)) THEN
3917   ASM_SIMP_TAC[ARITH_RULE `SUC d <= n ==> d <= n`] THEN STRIP_TAC THEN
3918   MP_TAC(SPECL [`\n:num. (x:num->real^N) (r n) $ (SUC d)`; `b:real`]
3919          COMPACT_REAL_LEMMA) THEN
3920   REWRITE_TAC[] THEN ANTS_TAC THENL
3921    [ASM_MESON_TAC[REAL_LE_TRANS; COMPONENT_LE_NORM; ARITH_RULE `1 <= SUC n`];
3922     ALL_TAC] THEN
3923   DISCH_THEN(X_CHOOSE_THEN `y:real` (X_CHOOSE_THEN `s:num->num`
3924         STRIP_ASSUME_TAC)) THEN
3925   MAP_EVERY EXISTS_TAC
3926    [`(lambda k. if k = SUC d then y else (l:real^N)$k):real^N`;
3927     `(r:num->num) o (s:num->num)`] THEN
3928   ASM_SIMP_TAC[o_THM] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3929   REPEAT(FIRST_ASSUM(C UNDISCH_THEN (MP_TAC o SPEC `e:real`) o concl)) THEN
3930   ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_TAC `N1:num`) THEN
3931   DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN EXISTS_TAC `N1 + N2:num` THEN
3932   FIRST_ASSUM(fun th -> SIMP_TAC[LAMBDA_BETA; MATCH_MP(ARITH_RULE
3933    `SUC d <= n ==> !i. 1 <= i /\ i <= SUC d ==> 1 <= i /\ i <= n`) th]) THEN
3934   REWRITE_TAC[LE] THEN REPEAT STRIP_TAC THEN
3935   ASM_REWRITE_TAC[] THEN TRY COND_CASES_TAC THEN
3936   ASM_MESON_TAC[MONOTONE_BIGGER; LE_TRANS;
3937     ARITH_RULE `N1 + N2 <= n ==> N2 <= n:num /\ N1 <= n`;
3938     ARITH_RULE `1 <= i /\ i <= d /\ SUC d <= n
3939                 ==> ~(i = SUC d) /\ 1 <= SUC d /\ d <= n /\ i <= n`]);;
3940
3941 let BOUNDED_CLOSED_IMP_COMPACT = prove
3942  (`!s:real^N->bool. bounded s /\ closed s ==> compact s`,
3943   REPEAT STRIP_TAC THEN REWRITE_TAC[compact] THEN
3944   X_GEN_TAC `x:num->real^N` THEN DISCH_TAC THEN
3945   MP_TAC(ISPEC `s:real^N->bool` COMPACT_LEMMA) THEN
3946   ASM_REWRITE_TAC[] THEN
3947   DISCH_THEN(MP_TAC o SPEC `dimindex(:N)`) THEN
3948   REWRITE_TAC[LE_REFL] THEN
3949   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real^N` THEN
3950   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `r:num->num` THEN ASM_SIMP_TAC[] THEN
3951   STRIP_TAC THEN MATCH_MP_TAC(TAUT `(b ==> a) /\ b ==> a /\ b`) THEN
3952   REPEAT STRIP_TAC THENL
3953    [FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[CLOSED_SEQUENTIAL_LIMITS]) THEN
3954     EXISTS_TAC `(x:num->real^N) o (r:num->num)` THEN
3955     ASM_REWRITE_TAC[o_THM];
3956     ALL_TAC] THEN
3957   REWRITE_TAC[LIM_SEQUENTIALLY] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3958   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2 / &(dimindex(:N))`) THEN
3959   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; DIMINDEX_NONZERO;
3960                REAL_HALF; ARITH_RULE `0 < n <=> ~(n = 0)`] THEN
3961   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
3962   REWRITE_TAC[dist] THEN REPEAT STRIP_TAC THEN
3963   MATCH_MP_TAC(MATCH_MP (REAL_ARITH `a <= b ==> b < e ==> a < e`)
3964                         (SPEC_ALL NORM_LE_L1)) THEN
3965   MATCH_MP_TAC REAL_LET_TRANS THEN
3966   EXISTS_TAC `sum (1..dimindex(:N))
3967                   (\k. e / &2 / &(dimindex(:N)))` THEN
3968   CONJ_TAC THENL
3969    [MATCH_MP_TAC SUM_LE_NUMSEG THEN
3970     SIMP_TAC[o_THM; LAMBDA_BETA; vector_sub] THEN
3971     ASM_MESON_TAC[REAL_LT_IMP_LE; LE_TRANS];
3972     ASM_SIMP_TAC[SUM_CONST_NUMSEG; ADD_SUB; REAL_DIV_LMUL; REAL_OF_NUM_EQ;
3973                  DIMINDEX_NONZERO; REAL_LE_REFL; REAL_LT_LDIV_EQ; ARITH;
3974                  REAL_OF_NUM_LT; REAL_ARITH `x < x * &2 <=> &0 < x`]]);;
3975
3976 (* ------------------------------------------------------------------------- *)
3977 (* Completeness.                                                             *)
3978 (* ------------------------------------------------------------------------- *)
3979
3980 let cauchy = new_definition
3981   `cauchy (s:num->real^N) <=>
3982      !e. &0 < e ==> ?N. !m n. m >= N /\ n >= N ==> dist(s m,s n) < e`;;
3983
3984 let complete = new_definition
3985   `complete s <=>
3986      !f:num->real^N. (!n. f n IN s) /\ cauchy f
3987                       ==> ?l. l IN s /\ (f --> l) sequentially`;;
3988
3989 let CAUCHY = prove
3990  (`!s:num->real^N.
3991       cauchy s <=> !e. &0 < e ==> ?N. !n. n >= N ==> dist(s n,s N) < e`,
3992   REPEAT GEN_TAC THEN REWRITE_TAC[cauchy; GE] THEN EQ_TAC THENL
3993    [MESON_TAC[LE_REFL]; DISCH_TAC] THEN
3994   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
3995   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
3996   MESON_TAC[DIST_TRIANGLE_HALF_L]);;
3997
3998 let CONVERGENT_IMP_CAUCHY = prove
3999  (`!s l. (s --> l) sequentially ==> cauchy s`,
4000   REWRITE_TAC[LIM_SEQUENTIALLY; cauchy] THEN
4001   REPEAT GEN_TAC THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
4002   FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
4003   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
4004   ASM_MESON_TAC[GE; LE_REFL; DIST_TRIANGLE_HALF_L]);;
4005
4006 let CAUCHY_IMP_BOUNDED = prove
4007  (`!s:num->real^N. cauchy s ==> bounded {y | ?n. y = s n}`,
4008   REWRITE_TAC[cauchy; bounded; IN_ELIM_THM] THEN GEN_TAC THEN
4009   DISCH_THEN(MP_TAC o SPEC `&1`) THEN REWRITE_TAC[REAL_LT_01] THEN
4010   DISCH_THEN(X_CHOOSE_THEN `N:num` (MP_TAC o SPEC `N:num`)) THEN
4011   REWRITE_TAC[GE_REFL] THEN DISCH_TAC THEN
4012   SUBGOAL_THEN `!n:num. N <= n ==> norm(s n :real^N) <= norm(s N) + &1`
4013   ASSUME_TAC THENL
4014    [ASM_MESON_TAC[GE; dist; DIST_SYM; NORM_TRIANGLE_SUB;
4015                   REAL_ARITH `a <= b + c /\ c < &1 ==> a <= b + &1`];
4016     MP_TAC(ISPECL [`\n:num. norm(s n :real^N)`; `0..N`]
4017                   UPPER_BOUND_FINITE_SET_REAL) THEN
4018     SIMP_TAC[FINITE_NUMSEG; IN_NUMSEG; LE_0; LEFT_IMP_EXISTS_THM] THEN
4019     ASM_MESON_TAC[LE_CASES;
4020                   REAL_ARITH `x <= a \/ x <= b ==> x <= abs a + abs b`]]);;
4021
4022 let COMPACT_IMP_COMPLETE = prove
4023  (`!s:real^N->bool. compact s ==> complete s`,
4024   GEN_TAC THEN REWRITE_TAC[complete; compact] THEN
4025   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `f:num->real^N` THEN
4026   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
4027   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
4028   DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN
4029   FIRST_X_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] LIM_ADD)) THEN
4030   DISCH_THEN(MP_TAC o SPEC `\n. (f:num->real^N)(n) - f(r n)`) THEN
4031   DISCH_THEN(MP_TAC o SPEC `vec 0: real^N`) THEN ASM_REWRITE_TAC[o_THM] THEN
4032   REWRITE_TAC[VECTOR_ADD_RID; VECTOR_SUB_ADD2; ETA_AX] THEN
4033   DISCH_THEN MATCH_MP_TAC THEN
4034   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [cauchy]) THEN
4035   REWRITE_TAC[GE; LIM; SEQUENTIALLY; dist; VECTOR_SUB_RZERO] THEN
4036   SUBGOAL_THEN `!n:num. n <= r(n)` MP_TAC THENL [INDUCT_TAC; ALL_TAC] THEN
4037   ASM_MESON_TAC[ LE_TRANS; LE_REFL; LT; LET_TRANS; LE_0; LE_SUC_LT]);;
4038
4039 let COMPLETE_UNIV = prove
4040  (`complete(:real^N)`,
4041   REWRITE_TAC[complete; IN_UNIV] THEN X_GEN_TAC `x:num->real^N` THEN
4042   DISCH_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP CAUCHY_IMP_BOUNDED) THEN
4043   DISCH_THEN(ASSUME_TAC o MATCH_MP BOUNDED_CLOSURE) THEN
4044   MP_TAC(ISPEC `closure {y:real^N | ?n:num. y = x n}`
4045                COMPACT_IMP_COMPLETE) THEN
4046   ASM_SIMP_TAC[BOUNDED_CLOSED_IMP_COMPACT; CLOSED_CLOSURE; complete] THEN
4047   DISCH_THEN(MP_TAC o SPEC `x:num->real^N`) THEN
4048   ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
4049   ASM_REWRITE_TAC[closure; IN_ELIM_THM; IN_UNION] THEN MESON_TAC[]);;
4050
4051 let COMPLETE_EQ_CLOSED = prove
4052  (`!s:real^N->bool. complete s <=> closed s`,
4053   GEN_TAC THEN EQ_TAC THENL
4054    [REWRITE_TAC[complete; CLOSED_LIMPT; LIMPT_SEQUENTIAL] THEN
4055     REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN GEN_TAC THEN
4056     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MATCH_MP_TAC MONO_FORALL THEN
4057     MESON_TAC[CONVERGENT_IMP_CAUCHY; IN_DELETE; LIM_UNIQUE;
4058               TRIVIAL_LIMIT_SEQUENTIALLY];
4059     REWRITE_TAC[complete; CLOSED_SEQUENTIAL_LIMITS] THEN DISCH_TAC THEN
4060     X_GEN_TAC `f:num->real^N` THEN STRIP_TAC THEN
4061     MP_TAC(REWRITE_RULE[complete] COMPLETE_UNIV) THEN
4062     DISCH_THEN(MP_TAC o SPEC `f:num->real^N`) THEN
4063     ASM_REWRITE_TAC[IN_UNIV] THEN ASM_MESON_TAC[]]);;
4064
4065 let CONVERGENT_EQ_CAUCHY = prove
4066  (`!s. (?l. (s --> l) sequentially) <=> cauchy s`,
4067   GEN_TAC THEN EQ_TAC THENL
4068    [REWRITE_TAC[LEFT_IMP_EXISTS_THM; CONVERGENT_IMP_CAUCHY];
4069     REWRITE_TAC[REWRITE_RULE[complete; IN_UNIV] COMPLETE_UNIV]]);;
4070
4071 let CONVERGENT_IMP_BOUNDED = prove
4072  (`!s l. (s --> l) sequentially ==> bounded (IMAGE s (:num))`,
4073   REWRITE_TAC[LEFT_FORALL_IMP_THM; CONVERGENT_EQ_CAUCHY] THEN
4074   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CAUCHY_IMP_BOUNDED) THEN
4075   REWRITE_TAC[IMAGE; IN_UNIV]);;
4076
4077 (* ------------------------------------------------------------------------- *)
4078 (* Total boundedness.                                                        *)
4079 (* ------------------------------------------------------------------------- *)
4080
4081 let COMPACT_IMP_TOTALLY_BOUNDED = prove
4082  (`!s:real^N->bool.
4083         compact s
4084         ==> !e. &0 < e ==> ?k. FINITE k /\ k SUBSET s /\
4085                                s SUBSET (UNIONS(IMAGE (\x. ball(x,e)) k))`,
4086   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4087   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
4088   REWRITE_TAC[TAUT `~(a /\ b /\ c) <=> a /\ b ==> ~c`; SUBSET] THEN
4089   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
4090   SUBGOAL_THEN
4091    `?x:num->real^N. !n. x(n) IN s /\ !m. m < n ==> ~(dist(x(m),x(n)) < e)`
4092   MP_TAC THENL
4093    [SUBGOAL_THEN
4094      `?x:num->real^N.
4095           !n. x(n) = @y. y IN s /\ !m. m < n ==> ~(dist(x(m),y) < e)`
4096     MP_TAC THENL
4097      [MATCH_MP_TAC(MATCH_MP WF_REC WF_num) THEN SIMP_TAC[]; ALL_TAC] THEN
4098     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:num->real^N` THEN
4099     DISCH_TAC THEN MATCH_MP_TAC num_WF THEN X_GEN_TAC `n:num` THEN
4100     FIRST_X_ASSUM(SUBST1_TAC o SPEC `n:num`) THEN STRIP_TAC THEN
4101     CONV_TAC SELECT_CONV THEN
4102     FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (x:num->real^N) {m | m < n}`) THEN
4103     SIMP_TAC[FINITE_IMAGE; FINITE_NUMSEG_LT; NOT_FORALL_THM; NOT_IMP] THEN
4104     REWRITE_TAC[IN_UNIONS; IN_IMAGE; IN_ELIM_THM] THEN ASM_MESON_TAC[IN_BALL];
4105     ALL_TAC] THEN
4106   REWRITE_TAC[compact; NOT_FORALL_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
4107   X_GEN_TAC `x:num->real^N` THEN  REWRITE_TAC[NOT_IMP; FORALL_AND_THM] THEN
4108   STRIP_TAC THEN ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN REPEAT STRIP_TAC THEN
4109   FIRST_X_ASSUM(MP_TAC o MATCH_MP CONVERGENT_IMP_CAUCHY) THEN
4110   REWRITE_TAC[cauchy] THEN DISCH_THEN(MP_TAC o SPEC `e:real`) THEN
4111   ASM_REWRITE_TAC[o_THM; NOT_EXISTS_THM; NOT_IMP; NOT_FORALL_THM; NOT_IMP] THEN
4112   X_GEN_TAC `N:num` THEN MAP_EVERY EXISTS_TAC [`N:num`; `SUC N`] THEN
4113   CONJ_TAC THENL [ARITH_TAC; ASM_MESON_TAC[LT]]);;
4114
4115 (* ------------------------------------------------------------------------- *)
4116 (* Heine-Borel theorem (following Burkill & Burkill vol. 2)                  *)
4117 (* ------------------------------------------------------------------------- *)
4118
4119 let HEINE_BOREL_LEMMA = prove
4120  (`!s:real^N->bool.
4121       compact s
4122       ==> !t. s SUBSET (UNIONS t) /\ (!b. b IN t ==> open b)
4123               ==> ?e. &0 < e /\
4124                       !x. x IN s ==> ?b. b IN t /\ ball(x,e) SUBSET b`,
4125   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4126   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
4127   DISCH_THEN(CHOOSE_THEN (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
4128   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC `&1 / (&n + &1)`) THEN
4129   SIMP_TAC[REAL_LT_DIV; REAL_LT_01; REAL_ARITH `x <= y ==> x < y + &1`;
4130    FORALL_AND_THM; REAL_POS; NOT_FORALL_THM; NOT_IMP; SKOLEM_THM; compact] THEN
4131   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN REWRITE_TAC[NOT_EXISTS_THM] THEN
4132   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN ASM_REWRITE_TAC[] THEN
4133   DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`l:real^N`; `r:num->num`] THEN
4134   STRIP_TAC THEN
4135   SUBGOAL_THEN `?b:real^N->bool. l IN b /\ b IN t` STRIP_ASSUME_TAC THENL
4136    [ASM_MESON_TAC[SUBSET; IN_UNIONS]; ALL_TAC] THEN
4137   SUBGOAL_THEN `?e. &0 < e /\ !z:real^N. dist(z,l) < e ==> z IN b`
4138   STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[open_def]; ALL_TAC] THEN
4139   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
4140   DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN
4141   SUBGOAL_THEN `&0 < e / &2` (fun th ->
4142     REWRITE_TAC[th; o_THM] THEN MP_TAC(GEN_REWRITE_RULE I [REAL_ARCH_INV] th))
4143   THENL [ASM_REWRITE_TAC[REAL_HALF]; ALL_TAC] THEN
4144   DISCH_THEN(X_CHOOSE_THEN `N1:num` STRIP_ASSUME_TAC) THEN
4145   DISCH_THEN(X_CHOOSE_THEN `N2:num` STRIP_ASSUME_TAC) THEN
4146   FIRST_X_ASSUM(MP_TAC o SPECL
4147    [`(r:num->num)(N1 + N2)`; `b:real^N->bool`]) THEN
4148   ASM_REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4149   FIRST_X_ASSUM MATCH_MP_TAC THEN MATCH_MP_TAC DIST_TRIANGLE_HALF_R THEN
4150   EXISTS_TAC `(f:num->real^N)(r(N1 + N2:num))` THEN CONJ_TAC THENL
4151    [ALL_TAC; FIRST_X_ASSUM MATCH_MP_TAC THEN ARITH_TAC] THEN
4152   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_BALL]) THEN
4153   MATCH_MP_TAC(REAL_ARITH `a <= b ==> x < a ==> x < b`) THEN
4154   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `inv(&N1)` THEN
4155   ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN REWRITE_TAC[real_div; REAL_MUL_LID] THEN
4156   MATCH_MP_TAC REAL_LE_INV2 THEN
4157   REWRITE_TAC[REAL_OF_NUM_ADD; REAL_OF_NUM_LE; REAL_OF_NUM_LT] THEN
4158   ASM_MESON_TAC[ARITH_RULE `(~(n = 0) ==> 0 < n)`; LE_ADD; MONOTONE_BIGGER;
4159                 LT_IMP_LE; LE_TRANS]);;
4160
4161 let COMPACT_IMP_HEINE_BOREL = prove
4162  (`!s. compact (s:real^N->bool)
4163        ==> !f. (!t. t IN f ==> open t) /\ s SUBSET (UNIONS f)
4164                ==> ?f'. f' SUBSET f /\ FINITE f' /\ s SUBSET (UNIONS f')`,
4165   REPEAT STRIP_TAC THEN
4166   FIRST_ASSUM(MP_TAC o SPEC `f:(real^N->bool)->bool` o
4167     MATCH_MP HEINE_BOREL_LEMMA) THEN ASM_REWRITE_TAC[] THEN
4168   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
4169   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4170   REWRITE_TAC[SKOLEM_THM; SUBSET; IN_BALL] THEN
4171   DISCH_THEN(X_CHOOSE_TAC `B:real^N->real^N->bool`) THEN
4172   FIRST_ASSUM(MP_TAC o SPEC `e:real` o
4173     MATCH_MP COMPACT_IMP_TOTALLY_BOUNDED) THEN
4174   ASM_REWRITE_TAC[UNIONS_IMAGE; SUBSET; IN_ELIM_THM] THEN
4175   REWRITE_TAC[IN_UNIONS; IN_BALL] THEN
4176   DISCH_THEN(X_CHOOSE_THEN `k:real^N->bool` STRIP_ASSUME_TAC) THEN
4177   EXISTS_TAC `IMAGE (B:real^N->real^N->bool) k` THEN
4178   ASM_SIMP_TAC[FINITE_IMAGE; SUBSET; IN_IMAGE; LEFT_IMP_EXISTS_THM] THEN
4179   ASM_MESON_TAC[IN_BALL]);;
4180
4181 (* ------------------------------------------------------------------------- *)
4182 (* Bolzano-Weierstrass property.                                             *)
4183 (* ------------------------------------------------------------------------- *)
4184
4185 let HEINE_BOREL_IMP_BOLZANO_WEIERSTRASS = prove
4186  (`!s:real^N->bool.
4187         (!f. (!t. t IN f ==> open t) /\ s SUBSET (UNIONS f)
4188              ==> ?f'. f' SUBSET f /\ FINITE f' /\ s SUBSET (UNIONS f'))
4189         ==> !t. INFINITE t /\ t SUBSET s ==> ?x. x IN s /\ x limit_point_of t`,
4190   REWRITE_TAC[RIGHT_IMP_FORALL_THM; limit_point_of] THEN REPEAT GEN_TAC THEN
4191   ONCE_REWRITE_TAC[TAUT `a ==> b /\ c ==> d <=> c ==> ~d ==> a ==> ~b`] THEN
4192   REWRITE_TAC[NOT_FORALL_THM; NOT_EXISTS_THM; RIGHT_AND_FORALL_THM] THEN
4193   DISCH_TAC THEN REWRITE_TAC[SKOLEM_THM] THEN
4194   DISCH_THEN(X_CHOOSE_TAC `f:real^N->real^N->bool`) THEN
4195   DISCH_THEN(MP_TAC o SPEC
4196    `{t:real^N->bool | ?x:real^N. x IN s /\ (t = f x)}`) THEN
4197   REWRITE_TAC[INFINITE; SUBSET; IN_ELIM_THM; IN_UNIONS; NOT_IMP] THEN
4198   ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
4199   DISCH_THEN(X_CHOOSE_THEN `g:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
4200   MATCH_MP_TAC FINITE_SUBSET THEN
4201   EXISTS_TAC `{x:real^N | x IN t /\ (f(x):real^N->bool) IN g}` THEN
4202   CONJ_TAC THENL
4203    [MATCH_MP_TAC FINITE_IMAGE_INJ_GENERAL THEN ASM_MESON_TAC[SUBSET];
4204     SIMP_TAC[SUBSET; IN_ELIM_THM] THEN X_GEN_TAC `u:real^N` THEN
4205     DISCH_TAC THEN SUBGOAL_THEN `(u:real^N) IN s` ASSUME_TAC THEN
4206     ASM_MESON_TAC[SUBSET]]);;
4207
4208 (* ------------------------------------------------------------------------- *)
4209 (* Complete the chain of compactness variants.                               *)
4210 (* ------------------------------------------------------------------------- *)
4211
4212 let BOLZANO_WEIERSTRASS_IMP_BOUNDED = prove
4213  (`!s:real^N->bool.
4214         (!t. INFINITE t /\ t SUBSET s ==> ?x. x IN s /\ x limit_point_of t)
4215         ==> bounded s`,
4216   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
4217   SIMP_TAC[compact; bounded] THEN
4218   REWRITE_TAC[NOT_FORALL_THM; NOT_EXISTS_THM; SKOLEM_THM; NOT_IMP] THEN
4219   REWRITE_TAC[REAL_NOT_LE] THEN
4220   DISCH_THEN(X_CHOOSE_TAC `beyond:real->real^N`) THEN
4221   (MP_TAC o prove_recursive_functions_exist num_RECURSION)
4222    `(f(0) = beyond(&0)) /\
4223     (!n. f(SUC n) = beyond(norm(f n) + &1):real^N)` THEN
4224   DISCH_THEN(X_CHOOSE_THEN `x:num->real^N` STRIP_ASSUME_TAC) THEN
4225   EXISTS_TAC `IMAGE (x:num->real^N) UNIV` THEN
4226   SUBGOAL_THEN
4227    `!m n. m < n ==> norm((x:num->real^N) m) + &1 < norm(x n)`
4228   ASSUME_TAC THENL
4229    [GEN_TAC THEN INDUCT_TAC THEN ASM_REWRITE_TAC[LT] THEN
4230     ASM_MESON_TAC[REAL_LT_TRANS; REAL_ARITH `b < b + &1`];
4231     ALL_TAC] THEN
4232   SUBGOAL_THEN `!m n. ~(m = n) ==> &1 < dist((x:num->real^N) m,x n)`
4233   ASSUME_TAC THENL
4234    [REPEAT GEN_TAC THEN REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC
4235      (SPECL [`m:num`; `n:num`] LT_CASES) THEN
4236     ASM_MESON_TAC[dist; LT_CASES; NORM_TRIANGLE_SUB; NORM_SUB;
4237                   REAL_ARITH `x + &1 < y /\ y <= x + d ==> &1 < d`];
4238     ALL_TAC] THEN
4239   REPEAT CONJ_TAC THENL
4240    [ASM_MESON_TAC[INFINITE_IMAGE_INJ; num_INFINITE; DIST_REFL;
4241                   REAL_ARITH `~(&1 < &0)`];
4242     REWRITE_TAC[SUBSET; IN_IMAGE; IN_UNIV; LEFT_IMP_EXISTS_THM] THEN
4243     GEN_TAC THEN INDUCT_TAC THEN ASM_MESON_TAC[];
4244     ALL_TAC] THEN
4245   X_GEN_TAC `l:real^N` THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN
4246   REWRITE_TAC[IN_IMAGE; IN_UNIV; LEFT_AND_EXISTS_THM] THEN
4247   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[UNWIND_THM2] THEN
4248   STRIP_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `&1 / &2`) THEN
4249   CONV_TAC REAL_RAT_REDUCE_CONV THEN
4250   DISCH_THEN(X_CHOOSE_THEN `k:num` STRIP_ASSUME_TAC) THEN
4251   FIRST_X_ASSUM(MP_TAC o SPEC `dist((x:num->real^N) k,l)`) THEN
4252   ASM_SIMP_TAC[DIST_POS_LT] THEN
4253   DISCH_THEN(X_CHOOSE_THEN `m:num` STRIP_ASSUME_TAC) THEN
4254   ASM_CASES_TAC `m:num = k` THEN
4255   ASM_MESON_TAC[DIST_TRIANGLE_HALF_L; REAL_LT_TRANS; REAL_LT_REFL]);;
4256
4257 let SEQUENCE_INFINITE_LEMMA = prove
4258  (`!f l. (!n. ~(f(n) = l)) /\ (f --> l) sequentially
4259          ==> INFINITE {y:real^N | ?n. y = f n}`,
4260   REWRITE_TAC[INFINITE] THEN REPEAT STRIP_TAC THEN MP_TAC(ISPEC
4261    `IMAGE (\y:real^N. dist(y,l)) {y | ?n:num. y = f n}` INF_FINITE) THEN
4262   ASM_SIMP_TAC[GSYM MEMBER_NOT_EMPTY; IN_IMAGE; FINITE_IMAGE; IN_ELIM_THM] THEN
4263   ASM_MESON_TAC[LIM_SEQUENTIALLY; LE_REFL; REAL_NOT_LE; DIST_POS_LT]);;
4264
4265 let LIMPT_OF_SEQUENCE_SUBSEQUENCE = prove
4266  (`!f:num->real^N l.
4267         l limit_point_of (IMAGE f (:num))
4268         ==> ?r. (!m n. m < n ==> r(m) < r(n)) /\ ((f o r) --> l) sequentially`,
4269   REPEAT STRIP_TAC THEN
4270   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIMPT_APPROACHABLE]) THEN
4271   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC
4272    `inf((inv(&n + &1)) INSERT
4273     IMAGE (\k. dist((f:num->real^N) k,l))
4274           {k | k IN 0..n /\ ~(f k = l)})`) THEN
4275   SIMP_TAC[REAL_LT_INF_FINITE; FINITE_INSERT; NOT_INSERT_EMPTY;
4276            FINITE_RESTRICT; FINITE_NUMSEG; FINITE_IMAGE] THEN
4277   REWRITE_TAC[FORALL_IN_INSERT; EXISTS_IN_IMAGE; FORALL_IN_IMAGE; IN_UNIV] THEN
4278   REWRITE_TAC[REAL_LT_INV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
4279   SIMP_TAC[FORALL_AND_THM; FORALL_IN_GSPEC; GSYM DIST_NZ; SKOLEM_THM] THEN
4280   DISCH_THEN(X_CHOOSE_THEN `nn:num->num` STRIP_ASSUME_TAC) THEN
4281   (MP_TAC o prove_recursive_functions_exist num_RECURSION)
4282    `r 0 = nn 0 /\ (!n. r (SUC n) = nn(r n))` THEN
4283   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `r:num->num` THEN
4284   STRIP_TAC THEN
4285   MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
4286    [MATCH_MP_TAC TRANSITIVE_STEPWISE_LT THEN REWRITE_TAC[LT_TRANS] THEN
4287     X_GEN_TAC `n:num` THEN ASM_REWRITE_TAC[] THEN
4288     FIRST_X_ASSUM(MP_TAC o SPECL
4289      [`(r:num->num) n`; `(nn:num->num)(r(n:num))`]) THEN
4290     ASM_REWRITE_TAC[IN_NUMSEG; LE_0; REAL_LT_REFL] THEN ARITH_TAC;
4291     DISCH_THEN(ASSUME_TAC o MATCH_MP MONOTONE_BIGGER)] THEN
4292   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
4293   X_GEN_TAC `e:real` THEN GEN_REWRITE_TAC LAND_CONV [REAL_ARCH_INV] THEN
4294   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN STRIP_TAC THEN
4295   MATCH_MP_TAC num_INDUCTION THEN ASM_REWRITE_TAC[CONJUNCT1 LE] THEN
4296   X_GEN_TAC `n:num` THEN DISCH_THEN(K ALL_TAC) THEN DISCH_TAC THEN
4297   ASM_REWRITE_TAC[o_THM] THEN MATCH_MP_TAC REAL_LT_TRANS THEN
4298   EXISTS_TAC `inv(&((r:num->num) n) + &1)` THEN ASM_REWRITE_TAC[] THEN
4299   MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&N)` THEN
4300   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_LE_INV2 THEN
4301   ASM_SIMP_TAC[REAL_OF_NUM_LE; REAL_OF_NUM_LT; LE_1; REAL_OF_NUM_ADD] THEN
4302   MATCH_MP_TAC(ARITH_RULE `N <= SUC n /\ n <= r n ==> N <= r n + 1`) THEN
4303   ASM_REWRITE_TAC[]);;
4304
4305 let SEQUENCE_UNIQUE_LIMPT = prove
4306  (`!f l l':real^N.
4307         (f --> l) sequentially /\ l' limit_point_of {y | ?n. y = f n}
4308         ==> l' = l`,
4309   REWRITE_TAC[SET_RULE `{y | ?n. y = f n} = IMAGE f (:num)`] THEN
4310   REPEAT STRIP_TAC THEN
4311   FIRST_X_ASSUM(MP_TAC o MATCH_MP LIMPT_OF_SEQUENCE_SUBSEQUENCE) THEN
4312   DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN
4313   MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
4314   EXISTS_TAC `(f:num->real^N) o (r:num->num)` THEN
4315   ASM_SIMP_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; LIM_SUBSEQUENCE]);;
4316
4317 let BOLZANO_WEIERSTRASS_IMP_CLOSED = prove
4318  (`!s:real^N->bool.
4319         (!t. INFINITE t /\ t SUBSET s ==> ?x. x IN s /\ x limit_point_of t)
4320         ==> closed s`,
4321   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSED_SEQUENTIAL_LIMITS] THEN
4322   MAP_EVERY X_GEN_TAC [`f:num->real^N`; `l:real^N`] THEN
4323   DISCH_TAC THEN
4324   MAP_EVERY (MP_TAC o ISPECL [`f:num->real^N`; `l:real^N`])
4325    [SEQUENCE_UNIQUE_LIMPT; SEQUENCE_INFINITE_LEMMA] THEN
4326   MATCH_MP_TAC(TAUT
4327    `(~d ==> a /\ ~(b /\ c)) ==> (a ==> b) ==> c ==> d`) THEN
4328   DISCH_TAC THEN CONJ_TAC THENL [ASM_MESON_TAC[]; STRIP_TAC] THEN
4329   FIRST_X_ASSUM(MP_TAC o SPEC `{y:real^N | ?n:num. y = f n}`) THEN
4330   ASM_REWRITE_TAC[NOT_IMP] THEN CONJ_TAC THENL
4331    [REWRITE_TAC[SUBSET; IN_ELIM_THM];
4332     ABBREV_TAC `t = {y:real^N | ?n:num. y = f n}`] THEN
4333   ASM_MESON_TAC[]);;
4334
4335 (* ------------------------------------------------------------------------- *)
4336 (* Hence express everything as an equivalence.                               *)
4337 (* ------------------------------------------------------------------------- *)
4338
4339 let COMPACT_EQ_HEINE_BOREL = prove
4340  (`!s:real^N->bool.
4341         compact s <=>
4342            !f. (!t. t IN f ==> open t) /\ s SUBSET (UNIONS f)
4343                ==> ?f'. f' SUBSET f /\ FINITE f' /\ s SUBSET (UNIONS f')`,
4344   GEN_TAC THEN EQ_TAC THEN SIMP_TAC[COMPACT_IMP_HEINE_BOREL] THEN
4345   DISCH_THEN(MP_TAC o MATCH_MP HEINE_BOREL_IMP_BOLZANO_WEIERSTRASS) THEN
4346   DISCH_TAC THEN MATCH_MP_TAC BOUNDED_CLOSED_IMP_COMPACT THEN
4347   ASM_SIMP_TAC[BOLZANO_WEIERSTRASS_IMP_BOUNDED;
4348                BOLZANO_WEIERSTRASS_IMP_CLOSED]);;
4349
4350 let COMPACT_EQ_BOLZANO_WEIERSTRASS = prove
4351  (`!s:real^N->bool.
4352         compact s <=>
4353            !t. INFINITE t /\ t SUBSET s ==> ?x. x IN s /\ x limit_point_of t`,
4354   GEN_TAC THEN EQ_TAC THENL
4355    [SIMP_TAC[COMPACT_EQ_HEINE_BOREL; HEINE_BOREL_IMP_BOLZANO_WEIERSTRASS];
4356     SIMP_TAC[BOLZANO_WEIERSTRASS_IMP_BOUNDED; BOLZANO_WEIERSTRASS_IMP_CLOSED;
4357              BOUNDED_CLOSED_IMP_COMPACT]]);;
4358
4359 let COMPACT_EQ_BOUNDED_CLOSED = prove
4360  (`!s:real^N->bool. compact s <=> bounded s /\ closed s`,
4361   GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[BOUNDED_CLOSED_IMP_COMPACT] THEN
4362   SIMP_TAC[COMPACT_EQ_BOLZANO_WEIERSTRASS; BOLZANO_WEIERSTRASS_IMP_BOUNDED;
4363            BOLZANO_WEIERSTRASS_IMP_CLOSED]);;
4364
4365 let COMPACT_IMP_BOUNDED = prove
4366  (`!s. compact s ==> bounded s`,
4367   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED]);;
4368
4369 let COMPACT_IMP_CLOSED = prove
4370  (`!s. compact s ==> closed s`,
4371   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED]);;
4372
4373 let COMPACT_SEQUENCE_WITH_LIMIT = prove
4374  (`!f l:real^N.
4375         (f --> l) sequentially ==> compact (l INSERT IMAGE f (:num))`,
4376   REPEAT STRIP_TAC THEN REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4377   REWRITE_TAC[BOUNDED_INSERT] THEN CONJ_TAC THENL
4378    [ASM_MESON_TAC[CONVERGENT_IMP_BOUNDED];
4379     SIMP_TAC[CLOSED_LIMPT; LIMPT_INSERT; IN_INSERT] THEN
4380     REWRITE_TAC[IMAGE; IN_UNIV] THEN REPEAT STRIP_TAC THEN DISJ1_TAC THEN
4381     MATCH_MP_TAC SEQUENCE_UNIQUE_LIMPT THEN ASM_MESON_TAC[]]);;
4382
4383 let CLOSED_IN_COMPACT = prove
4384  (`!s t:real^N->bool.
4385         compact s /\ closed_in (subtopology euclidean s) t
4386         ==> compact t`,
4387   SIMP_TAC[IMP_CONJ; COMPACT_EQ_BOUNDED_CLOSED; CLOSED_IN_CLOSED_EQ] THEN
4388   MESON_TAC[BOUNDED_SUBSET]);;
4389
4390 (* ------------------------------------------------------------------------- *)
4391 (* A version of Heine-Borel for subtopology.                                 *)
4392 (* ------------------------------------------------------------------------- *)
4393
4394 let COMPACT_EQ_HEINE_BOREL_SUBTOPOLOGY = prove
4395  (`!s:real^N->bool.
4396         compact s <=>
4397         (!f. (!t. t IN f ==> open_in(subtopology euclidean s) t) /\
4398              s SUBSET UNIONS f
4399              ==> ?f'. f' SUBSET f /\ FINITE f' /\ s SUBSET UNIONS f')`,
4400   GEN_TAC THEN REWRITE_TAC[COMPACT_EQ_HEINE_BOREL] THEN EQ_TAC THEN
4401   DISCH_TAC THEN X_GEN_TAC `f:(real^N->bool)->bool` THENL
4402    [REWRITE_TAC[OPEN_IN_OPEN] THEN
4403     GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4404     REWRITE_TAC[SKOLEM_THM] THEN
4405     DISCH_THEN(CONJUNCTS_THEN2
4406      (X_CHOOSE_TAC `m:(real^N->bool)->(real^N->bool)`) ASSUME_TAC) THEN
4407     FIRST_X_ASSUM(MP_TAC o SPEC
4408      `IMAGE (m:(real^N->bool)->(real^N->bool)) f`) THEN
4409     ASM_SIMP_TAC[FORALL_IN_IMAGE] THEN
4410     ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4411     DISCH_THEN(X_CHOOSE_THEN `f':(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
4412     EXISTS_TAC `IMAGE (\t:real^N->bool. s INTER t) f'` THEN
4413     ASM_SIMP_TAC[FINITE_IMAGE; UNIONS_IMAGE; SUBSET; FORALL_IN_IMAGE] THEN
4414     CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
4415     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET_IMAGE]) THEN
4416     STRIP_TAC THEN ASM_REWRITE_TAC[FORALL_IN_IMAGE] THEN ASM_MESON_TAC[SUBSET];
4417     DISCH_TAC THEN
4418     FIRST_X_ASSUM(MP_TAC o SPEC `{s INTER t:real^N->bool | t IN f}`) THEN
4419     REWRITE_TAC[SIMPLE_IMAGE; FORALL_IN_IMAGE; OPEN_IN_OPEN; UNIONS_IMAGE] THEN
4420     ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4421     ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`] THEN
4422     REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE; UNIONS_IMAGE] THEN
4423     MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]]);;
4424
4425 (* ------------------------------------------------------------------------- *)
4426 (* More easy lemmas.                                                         *)
4427 (* ------------------------------------------------------------------------- *)
4428
4429 let COMPACT_CLOSURE = prove
4430  (`!s. compact(closure s) <=> bounded s`,
4431   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_CLOSURE; BOUNDED_CLOSURE_EQ]);;
4432
4433 let BOLZANO_WEIERSTRASS_CONTRAPOS = prove
4434  (`!s t:real^N->bool.
4435         compact s /\ t SUBSET s /\
4436         (!x. x IN s ==> ~(x limit_point_of t))
4437         ==> FINITE t`,
4438   REWRITE_TAC[COMPACT_EQ_BOLZANO_WEIERSTRASS; INFINITE] THEN MESON_TAC[]);;
4439
4440 let DISCRETE_BOUNDED_IMP_FINITE = prove
4441  (`!s:real^N->bool e.
4442         &0 < e /\
4443         (!x y. x IN s /\ y IN s /\ norm(y - x) < e ==> y = x) /\
4444         bounded s
4445         ==> FINITE s`,
4446   REPEAT STRIP_TAC THEN
4447   SUBGOAL_THEN `compact(s:real^N->bool)` MP_TAC THENL
4448    [ASM_REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4449     ASM_MESON_TAC[DISCRETE_IMP_CLOSED];
4450     DISCH_THEN(MP_TAC o MATCH_MP COMPACT_IMP_HEINE_BOREL)] THEN
4451   DISCH_THEN(MP_TAC o SPEC `IMAGE (\x:real^N. ball(x,e)) s`) THEN
4452   REWRITE_TAC[FORALL_IN_IMAGE; OPEN_BALL; UNIONS_IMAGE; IN_ELIM_THM] THEN
4453   ANTS_TAC THENL
4454    [REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN ASM_MESON_TAC[CENTRE_IN_BALL];
4455     ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`]] THEN
4456   REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE] THEN
4457   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
4458   SUBGOAL_THEN `s:real^N->bool = t` (fun th -> ASM_REWRITE_TAC[th]) THEN
4459   MATCH_MP_TAC SUBSET_ANTISYM THEN ASM_REWRITE_TAC[] THEN
4460   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4461   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [UNIONS_IMAGE]) THEN
4462   DISCH_THEN(MP_TAC o SPEC `x:real^N` o GEN_REWRITE_RULE I [SUBSET]) THEN
4463   ASM_REWRITE_TAC[IN_ELIM_THM; IN_BALL; dist] THEN ASM_MESON_TAC[SUBSET]);;
4464
4465 let BOLZANO_WEIERSTRASS = prove
4466  (`!s:real^N->bool. bounded s /\ INFINITE s ==> ?x. x limit_point_of s`,
4467   GEN_TAC THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
4468   FIRST_ASSUM(ASSUME_TAC o MATCH_MP NO_LIMIT_POINT_IMP_CLOSED) THEN
4469   STRIP_TAC THEN
4470   MP_TAC(ISPEC `s:real^N->bool` COMPACT_EQ_BOLZANO_WEIERSTRASS) THEN
4471   ASM_REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4472   DISCH_THEN(MP_TAC o SPEC `s:real^N->bool`) THEN
4473   ASM_REWRITE_TAC[SUBSET_REFL] THEN ASM_MESON_TAC[]);;
4474
4475 (* ------------------------------------------------------------------------- *)
4476 (* In particular, some common special cases.                                 *)
4477 (* ------------------------------------------------------------------------- *)
4478
4479 let COMPACT_EMPTY = prove
4480  (`compact {}`,
4481   REWRITE_TAC[compact; NOT_IN_EMPTY]);;
4482
4483 let COMPACT_UNION = prove
4484  (`!s t. compact s /\ compact t ==> compact (s UNION t)`,
4485   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_UNION; CLOSED_UNION]);;
4486
4487 let COMPACT_INTER = prove
4488  (`!s t. compact s /\ compact t ==> compact (s INTER t)`,
4489   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_INTER; CLOSED_INTER]);;
4490
4491 let COMPACT_INTER_CLOSED = prove
4492  (`!s t. compact s /\ closed t ==> compact (s INTER t)`,
4493   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_INTER] THEN
4494   MESON_TAC[BOUNDED_SUBSET; INTER_SUBSET]);;
4495
4496 let CLOSED_INTER_COMPACT = prove
4497  (`!s t. closed s /\ compact t ==> compact (s INTER t)`,
4498   MESON_TAC[COMPACT_INTER_CLOSED; INTER_COMM]);;
4499
4500 let COMPACT_INTERS = prove
4501  (`!f:(real^N->bool)->bool.
4502         (!s. s IN f ==> compact s) /\ ~(f = {})
4503         ==> compact(INTERS f)`,
4504   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_INTERS] THEN
4505   REPEAT STRIP_TAC THEN MATCH_MP_TAC BOUNDED_INTERS THEN ASM SET_TAC[]);;
4506
4507 let FINITE_IMP_CLOSED = prove
4508  (`!s. FINITE s ==> closed s`,
4509   MESON_TAC[BOLZANO_WEIERSTRASS_IMP_CLOSED; INFINITE; FINITE_SUBSET]);;
4510
4511 let FINITE_IMP_CLOSED_IN = prove
4512  (`!s t. FINITE s /\ s SUBSET t ==> closed_in (subtopology euclidean t) s`,
4513   SIMP_TAC[CLOSED_SUBSET_EQ; FINITE_IMP_CLOSED]);;
4514
4515 let FINITE_IMP_COMPACT = prove
4516  (`!s. FINITE s ==> compact s`,
4517   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; FINITE_IMP_CLOSED; FINITE_IMP_BOUNDED]);;
4518
4519 let COMPACT_SING = prove
4520  (`!a. compact {a}`,
4521   SIMP_TAC[FINITE_IMP_COMPACT; FINITE_RULES]);;
4522
4523 let COMPACT_INSERT = prove
4524  (`!a s. compact s ==> compact(a INSERT s)`,
4525   ONCE_REWRITE_TAC[SET_RULE `a INSERT s = {a} UNION s`] THEN
4526   SIMP_TAC[COMPACT_UNION; COMPACT_SING]);;
4527
4528 let CLOSED_SING = prove
4529  (`!a. closed {a}`,
4530   MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; COMPACT_SING]);;
4531
4532 let CLOSED_IN_SING = prove
4533  (`!u x:real^N. closed_in (subtopology euclidean u) {x} <=> x IN u`,
4534   SIMP_TAC[CLOSED_SUBSET_EQ; CLOSED_SING] THEN SET_TAC[]);;
4535
4536 let CLOSURE_SING = prove
4537  (`!x:real^N. closure {x} = {x}`,
4538   SIMP_TAC[CLOSURE_CLOSED; CLOSED_SING]);;
4539
4540 let CLOSED_INSERT = prove
4541  (`!a s. closed s ==> closed(a INSERT s)`,
4542   ONCE_REWRITE_TAC[SET_RULE `a INSERT s = {a} UNION s`] THEN
4543   SIMP_TAC[CLOSED_UNION; CLOSED_SING]);;
4544
4545 let COMPACT_CBALL = prove
4546  (`!x e. compact(cball(x,e))`,
4547   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_CBALL; CLOSED_CBALL]);;
4548
4549 let COMPACT_FRONTIER_BOUNDED = prove
4550  (`!s. bounded s ==> compact(frontier s)`,
4551   SIMP_TAC[frontier; COMPACT_EQ_BOUNDED_CLOSED;
4552            CLOSED_DIFF; OPEN_INTERIOR; CLOSED_CLOSURE] THEN
4553   MESON_TAC[SUBSET_DIFF; BOUNDED_SUBSET; BOUNDED_CLOSURE]);;
4554
4555 let COMPACT_FRONTIER = prove
4556  (`!s. compact s ==> compact (frontier s)`,
4557   MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; COMPACT_FRONTIER_BOUNDED]);;
4558
4559 let BOUNDED_FRONTIER = prove
4560  (`!s:real^N->bool. bounded s ==> bounded(frontier s)`,
4561   MESON_TAC[COMPACT_FRONTIER_BOUNDED; COMPACT_IMP_BOUNDED]);;
4562
4563 let FRONTIER_SUBSET_COMPACT = prove
4564  (`!s. compact s ==> frontier s SUBSET s`,
4565   MESON_TAC[FRONTIER_SUBSET_CLOSED; COMPACT_EQ_BOUNDED_CLOSED]);;
4566
4567 let OPEN_DELETE = prove
4568  (`!s x. open s ==> open(s DELETE x)`,
4569   let lemma = prove(`s DELETE x = s DIFF {x}`,SET_TAC[]) in
4570   SIMP_TAC[lemma; OPEN_DIFF; CLOSED_SING]);;
4571
4572 let OPEN_IN_DELETE = prove
4573  (`!u s a:real^N.
4574         open_in (subtopology euclidean u) s
4575         ==> open_in (subtopology euclidean u) (s DELETE a)`,
4576   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(a:real^N) IN s` THENL
4577    [ONCE_REWRITE_TAC[SET_RULE `s DELETE a = s DIFF {a}`] THEN
4578     MATCH_MP_TAC OPEN_IN_DIFF THEN ASM_REWRITE_TAC[CLOSED_IN_SING] THEN
4579     FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN ASM SET_TAC[];
4580     ASM_SIMP_TAC[SET_RULE `~(a IN s) ==> s DELETE a = s`]]);;
4581
4582 let CLOSED_INTERS_COMPACT = prove
4583  (`!s:real^N->bool.
4584         closed s <=> !e. compact(cball(vec 0,e) INTER s)`,
4585   GEN_TAC THEN EQ_TAC THENL
4586    [SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_INTER; CLOSED_CBALL;
4587              BOUNDED_INTER; BOUNDED_CBALL];
4588     ALL_TAC] THEN
4589   STRIP_TAC THEN REWRITE_TAC[CLOSED_LIMPT] THEN
4590   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
4591   FIRST_X_ASSUM(MP_TAC o SPEC `norm(x:real^N) + &1`) THEN
4592   DISCH_THEN(MP_TAC o MATCH_MP COMPACT_IMP_CLOSED) THEN
4593   REWRITE_TAC[CLOSED_LIMPT] THEN DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
4594   REWRITE_TAC[IN_INTER] THEN ANTS_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
4595   POP_ASSUM MP_TAC THEN REWRITE_TAC[LIMPT_APPROACHABLE] THEN
4596   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
4597   FIRST_X_ASSUM(MP_TAC o SPEC `min e (&1 / &2)`) THEN
4598   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
4599   X_GEN_TAC `y:real^N` THEN SIMP_TAC[IN_INTER; IN_CBALL] THEN NORM_ARITH_TAC);;
4600
4601 let COMPACT_UNIONS = prove
4602  (`!s. FINITE s /\ (!t. t IN s ==> compact t) ==> compact(UNIONS s)`,
4603   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_UNIONS; BOUNDED_UNIONS]);;
4604
4605 let COMPACT_DIFF = prove
4606  (`!s t. compact s /\ open t ==> compact(s DIFF t)`,
4607   ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s INTER (UNIV DIFF t)`] THEN
4608   SIMP_TAC[COMPACT_INTER_CLOSED; GSYM OPEN_CLOSED]);;
4609
4610 let COMPACT_SPHERE = prove
4611  (`!a:real^N r. compact(sphere(a,r))`,
4612   REPEAT GEN_TAC THEN
4613   REWRITE_TAC[GSYM FRONTIER_CBALL] THEN MATCH_MP_TAC COMPACT_FRONTIER THEN
4614   REWRITE_TAC[COMPACT_CBALL]);;
4615
4616 let BOUNDED_SPHERE = prove
4617  (`!a:real^N r. bounded(sphere(a,r))`,
4618   SIMP_TAC[COMPACT_SPHERE; COMPACT_IMP_BOUNDED]);;
4619
4620 let CLOSED_SPHERE = prove
4621  (`!a r. closed(sphere(a,r))`,
4622   SIMP_TAC[COMPACT_SPHERE; COMPACT_IMP_CLOSED]);;
4623
4624 let FRONTIER_SING = prove
4625  (`!a:real^N. frontier {a} = {a}`,
4626   REWRITE_TAC[frontier; CLOSURE_SING; INTERIOR_SING; DIFF_EMPTY]);;
4627
4628 (* ------------------------------------------------------------------------- *)
4629 (* Finite intersection property. I could make it an equivalence in fact.     *)
4630 (* ------------------------------------------------------------------------- *)
4631
4632 let COMPACT_IMP_FIP = prove
4633  (`!s:real^N->bool f.
4634         compact s /\
4635         (!t. t IN f ==> closed t) /\
4636         (!f'. FINITE f' /\ f' SUBSET f ==> ~(s INTER (INTERS f') = {}))
4637         ==> ~(s INTER (INTERS f) = {})`,
4638   let lemma = prove(`(s = UNIV DIFF t) <=> (UNIV DIFF s = t)`,SET_TAC[]) in
4639   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4640   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL]) THEN
4641   DISCH_THEN(MP_TAC o SPEC `IMAGE (\t:real^N->bool. UNIV DIFF t) f`) THEN
4642   ASM_SIMP_TAC[FORALL_IN_IMAGE] THEN
4643   DISCH_THEN(fun th -> REPEAT STRIP_TAC THEN MP_TAC th) THEN
4644   ASM_SIMP_TAC[OPEN_DIFF; CLOSED_DIFF; OPEN_UNIV; CLOSED_UNIV; NOT_IMP] THEN
4645   CONJ_TAC THENL
4646    [UNDISCH_TAC `(s:real^N->bool) INTER INTERS f = {}` THEN
4647     ONCE_REWRITE_TAC[SUBSET; EXTENSION] THEN
4648     REWRITE_TAC[IN_UNIONS; EXISTS_IN_IMAGE] THEN SET_TAC[];
4649     DISCH_THEN(X_CHOOSE_THEN `g:(real^N->bool)->bool` MP_TAC) THEN
4650     FIRST_X_ASSUM(MP_TAC o SPEC `IMAGE (\t:real^N->bool. UNIV DIFF t) g`) THEN
4651     ASM_CASES_TAC `FINITE(g:(real^N->bool)->bool)` THEN
4652     ASM_SIMP_TAC[FINITE_IMAGE] THEN ONCE_REWRITE_TAC[SUBSET; EXTENSION] THEN
4653     REWRITE_TAC[FORALL_IN_IMAGE; IN_INTER; IN_INTERS; IN_IMAGE; IN_DIFF;
4654                 IN_UNIV; NOT_IN_EMPTY; lemma; UNWIND_THM1; IN_UNIONS] THEN
4655     SET_TAC[]]);;
4656
4657 let CLOSED_FIP = prove
4658  (`!f. (!t:real^N->bool. t IN f ==> closed t) /\ (?t. t IN f /\ bounded t) /\
4659        (!f'. FINITE f' /\ f' SUBSET f ==> ~(INTERS f' = {}))
4660        ==> ~(INTERS f = {})`,
4661   GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4662   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC)
4663         ASSUME_TAC) THEN
4664   MATCH_MP_TAC(SET_RULE `!s. ~(s INTER f = {}) ==> ~(f = {})`) THEN
4665   EXISTS_TAC `s:real^N->bool` THEN MATCH_MP_TAC COMPACT_IMP_FIP THEN
4666   ASM_SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4667   GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC COMPACT_IMP_FIP THEN
4668   ASM_SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4669   CONJ_TAC THENL [ASM_MESON_TAC[SUBSET]; ALL_TAC] THEN
4670   GEN_TAC THEN STRIP_TAC THEN REWRITE_TAC[GSYM INTERS_INSERT] THEN
4671   FIRST_X_ASSUM MATCH_MP_TAC THEN
4672   ASM_REWRITE_TAC[FINITE_INSERT] THEN ASM SET_TAC[]);;
4673
4674 let COMPACT_FIP = prove
4675  (`!f. (!t:real^N->bool. t IN f ==> compact t) /\
4676        (!f'. FINITE f' /\ f' SUBSET f ==> ~(INTERS f' = {}))
4677        ==> ~(INTERS f = {})`,
4678   GEN_TAC THEN STRIP_TAC THEN
4679   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THEN
4680   ASM_REWRITE_TAC[INTERS_0; UNIV_NOT_EMPTY] THEN
4681   MATCH_MP_TAC CLOSED_FIP THEN
4682   ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN
4683   ASM_MESON_TAC[MEMBER_NOT_EMPTY; COMPACT_IMP_BOUNDED]);;
4684
4685 (* ------------------------------------------------------------------------- *)
4686 (* Bounded closed nest property (proof does not use Heine-Borel).            *)
4687 (* ------------------------------------------------------------------------- *)
4688
4689 let BOUNDED_CLOSED_NEST = prove
4690  (`!s. (!n. closed(s n)) /\ (!n. ~(s n = {})) /\
4691        (!m n. m <= n ==> s(n) SUBSET s(m)) /\
4692        bounded(s 0)
4693        ==> ?a:real^N. !n:num. a IN s(n)`,
4694   GEN_TAC THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; SKOLEM_THM] THEN
4695   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4696   DISCH_THEN(CONJUNCTS_THEN2
4697      (X_CHOOSE_TAC `a:num->real^N`) STRIP_ASSUME_TAC) THEN
4698   SUBGOAL_THEN `compact(s 0:real^N->bool)` MP_TAC THENL
4699    [ASM_MESON_TAC[BOUNDED_CLOSED_IMP_COMPACT]; ALL_TAC] THEN
4700   REWRITE_TAC[compact] THEN
4701   DISCH_THEN(MP_TAC o SPEC `a:num->real^N`) THEN
4702   ANTS_TAC THENL [ASM_MESON_TAC[SUBSET; LE_0]; ALL_TAC] THEN
4703   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `l:real^N` THEN
4704   REWRITE_TAC[LIM_SEQUENTIALLY; o_THM] THEN
4705   DISCH_THEN(X_CHOOSE_THEN `r:num->num` STRIP_ASSUME_TAC) THEN
4706   GEN_REWRITE_TAC I [TAUT `p <=> ~(~p)`] THEN
4707   GEN_REWRITE_TAC RAND_CONV [NOT_FORALL_THM] THEN
4708   DISCH_THEN(X_CHOOSE_THEN `N:num` MP_TAC) THEN
4709   MP_TAC(ISPECL [`l:real^N`; `(s:num->real^N->bool) N`]
4710                 CLOSED_APPROACHABLE) THEN
4711   ASM_MESON_TAC[SUBSET; LE_REFL; LE_TRANS; LE_CASES; MONOTONE_BIGGER]);;
4712
4713 (* ------------------------------------------------------------------------- *)
4714 (* Decreasing case does not even need compactness, just completeness.        *)
4715 (* ------------------------------------------------------------------------- *)
4716
4717 let DECREASING_CLOSED_NEST = prove
4718  (`!s. (!n. closed(s n)) /\ (!n. ~(s n = {})) /\
4719        (!m n. m <= n ==> s(n) SUBSET s(m)) /\
4720        (!e. &0 < e ==> ?n. !x y. x IN s(n) /\ y IN s(n) ==> dist(x,y) < e)
4721        ==> ?a:real^N. !n:num. a IN s(n)`,
4722   GEN_TAC THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; SKOLEM_THM] THEN
4723   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
4724   DISCH_THEN(CONJUNCTS_THEN2
4725      (X_CHOOSE_TAC `a:num->real^N`) STRIP_ASSUME_TAC) THEN
4726   SUBGOAL_THEN `?l:real^N. (a --> l) sequentially` MP_TAC THENL
4727    [ASM_MESON_TAC[cauchy; GE; SUBSET; LE_TRANS; LE_REFL;
4728                   complete; COMPLETE_UNIV; IN_UNIV];
4729     ASM_MESON_TAC[LIM_SEQUENTIALLY; CLOSED_APPROACHABLE;
4730                   SUBSET; LE_REFL; LE_TRANS; LE_CASES]]);;
4731
4732 (* ------------------------------------------------------------------------- *)
4733 (* Strengthen it to the intersection actually being a singleton.             *)
4734 (* ------------------------------------------------------------------------- *)
4735
4736 let DECREASING_CLOSED_NEST_SING = prove
4737  (`!s. (!n. closed(s n)) /\ (!n. ~(s n = {})) /\
4738        (!m n. m <= n ==> s(n) SUBSET s(m)) /\
4739        (!e. &0 < e ==> ?n. !x y. x IN s(n) /\ y IN s(n) ==> dist(x,y) < e)
4740        ==> ?a:real^N. INTERS {t | ?n:num. t = s n} = {a}`,
4741   GEN_TAC THEN DISCH_TAC THEN
4742   FIRST_ASSUM(MP_TAC o MATCH_MP DECREASING_CLOSED_NEST) THEN
4743   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
4744   DISCH_TAC THEN REWRITE_TAC[EXTENSION; IN_INTERS; IN_SING; IN_ELIM_THM] THEN
4745   ASM_MESON_TAC[DIST_POS_LT; REAL_LT_REFL; SUBSET; LE_CASES]);;
4746
4747 (* ------------------------------------------------------------------------- *)
4748 (* A version for a more general chain, not indexed by N.                     *)
4749 (* ------------------------------------------------------------------------- *)
4750
4751 let BOUNDED_CLOSED_CHAIN = prove
4752  (`!f b:real^N->bool.
4753         (!s. s IN f ==> closed s /\ ~(s = {})) /\
4754         (!s t. s IN f /\ t IN f ==> s SUBSET t \/ t SUBSET s) /\
4755          b IN f /\ bounded b
4756          ==> ~(INTERS f = {})`,
4757   REPEAT GEN_TAC THEN STRIP_TAC THEN
4758   SUBGOAL_THEN `~(b INTER (INTERS f):real^N->bool = {})` MP_TAC THENL
4759    [ALL_TAC; SET_TAC[]] THEN
4760   MATCH_MP_TAC COMPACT_IMP_FIP THEN
4761   ASM_SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN
4762   X_GEN_TAC `u:(real^N->bool)->bool` THEN STRIP_TAC THEN
4763   SUBGOAL_THEN `?s:real^N->bool. s IN f /\ !t. t IN u ==> s SUBSET t`
4764   MP_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
4765   UNDISCH_TAC `(u:(real^N->bool)->bool) SUBSET f` THEN
4766   UNDISCH_TAC `FINITE(u:(real^N->bool)->bool)` THEN
4767   SPEC_TAC(`u:(real^N->bool)->bool`,`u:(real^N->bool)->bool`) THEN
4768   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
4769   CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
4770   MAP_EVERY X_GEN_TAC [`t:real^N->bool`; `u:(real^N->bool)->bool`] THEN
4771   REWRITE_TAC[INSERT_SUBSET] THEN
4772   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
4773   ASM_REWRITE_TAC[] THEN
4774   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
4775   DISCH_THEN(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
4776   FIRST_X_ASSUM(MP_TAC o SPECL [`s:real^N->bool`; `t:real^N->bool`]) THEN
4777   ASM SET_TAC[]);;
4778
4779 (* ------------------------------------------------------------------------- *)
4780 (* Analogous things directly for compactness.                                *)
4781 (* ------------------------------------------------------------------------- *)
4782
4783 let COMPACT_CHAIN = prove
4784  (`!f:(real^N->bool)->bool.
4785         (!s. s IN f ==> compact s /\ ~(s = {})) /\
4786         (!s t. s IN f /\ t IN f ==> s SUBSET t \/ t SUBSET s)
4787         ==> ~(INTERS f = {})`,
4788   GEN_TAC THEN REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN STRIP_TAC THEN
4789   ASM_CASES_TAC `f:(real^N->bool)->bool = {}` THENL
4790    [ASM_REWRITE_TAC[INTERS_0] THEN SET_TAC[];
4791     MATCH_MP_TAC BOUNDED_CLOSED_CHAIN THEN ASM SET_TAC[]]);;
4792
4793 let COMPACT_NEST = prove
4794  (`!s. (!n. compact(s n) /\ ~(s n = {})) /\
4795        (!m n. m <= n ==> s n SUBSET s m)
4796        ==> ~(INTERS {s n | n IN (:num)} = {})`,
4797   GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC COMPACT_CHAIN THEN
4798   ASM_SIMP_TAC[FORALL_IN_GSPEC; IN_UNIV; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
4799   MATCH_MP_TAC WLOG_LE THEN ASM_MESON_TAC[]);;
4800
4801 (* ------------------------------------------------------------------------- *)
4802 (* Cauchy-type criteria for *uniform* convergence.                           *)
4803 (* ------------------------------------------------------------------------- *)
4804
4805 let UNIFORMLY_CONVERGENT_EQ_CAUCHY = prove
4806  (`!P s:num->A->real^N.
4807          (?l. !e. &0 < e
4808                   ==> ?N. !n x. N <= n /\ P x ==> dist(s n x,l x) < e) <=>
4809          (!e. &0 < e
4810               ==> ?N. !m n x. N <= m /\ N <= n /\ P x
4811                               ==> dist(s m x,s n x) < e)`,
4812   REPEAT GEN_TAC THEN EQ_TAC THENL
4813    [DISCH_THEN(X_CHOOSE_TAC `l:A->real^N`) THEN X_GEN_TAC `e:real` THEN
4814     DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
4815     ASM_REWRITE_TAC[REAL_HALF] THEN MESON_TAC[DIST_TRIANGLE_HALF_L];
4816     ALL_TAC] THEN
4817   DISCH_TAC THEN
4818   SUBGOAL_THEN `!x:A. P x ==> cauchy (\n. s n x :real^N)` MP_TAC THENL
4819    [REWRITE_TAC[cauchy; GE] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
4820   REWRITE_TAC[GSYM CONVERGENT_EQ_CAUCHY; LIM_SEQUENTIALLY] THEN
4821   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
4822   REWRITE_TAC[SKOLEM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
4823   X_GEN_TAC `l:A->real^N` THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN
4824   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
4825   ASM_REWRITE_TAC[REAL_HALF] THEN MATCH_MP_TAC MONO_EXISTS THEN
4826   X_GEN_TAC `N:num` THEN STRIP_TAC THEN
4827   MAP_EVERY X_GEN_TAC [`n:num`; `x:A`] THEN STRIP_TAC THEN
4828   FIRST_X_ASSUM(MP_TAC o SPEC `x:A`) THEN ASM_REWRITE_TAC[] THEN
4829   DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
4830   DISCH_THEN(X_CHOOSE_TAC `M:num`) THEN
4831   FIRST_X_ASSUM(MP_TAC o SPECL [`n:num`; `N + M:num`; `x:A`]) THEN
4832   ASM_REWRITE_TAC[LE_ADD] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN
4833   FIRST_X_ASSUM(MP_TAC o SPEC `M + N:num`) THEN REWRITE_TAC[LE_ADD] THEN
4834   ASM_MESON_TAC[DIST_TRIANGLE_HALF_L; DIST_SYM]);;
4835
4836 let UNIFORMLY_CAUCHY_IMP_UNIFORMLY_CONVERGENT = prove
4837  (`!P (s:num->A->real^N) l.
4838     (!e. &0 < e
4839          ==> ?N. !m n x. N <= m /\ N <= n /\ P x ==> dist(s m x,s n x) < e) /\
4840     (!x. P x ==> !e. &0 < e ==> ?N. !n. N <= n ==> dist(s n x,l x) < e)
4841     ==> (!e. &0 < e ==> ?N. !n x. N <= n /\ P x ==> dist(s n x,l x) < e)`,
4842   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM UNIFORMLY_CONVERGENT_EQ_CAUCHY] THEN
4843   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `l':A->real^N`) ASSUME_TAC) THEN
4844   SUBGOAL_THEN `!x. P x ==> (l:A->real^N) x = l' x` MP_TAC THENL
4845    [ALL_TAC; ASM_MESON_TAC[]] THEN
4846   REPEAT STRIP_TAC THEN MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
4847   EXISTS_TAC `\n. (s:num->A->real^N) n x` THEN
4848   REWRITE_TAC[LIM_SEQUENTIALLY; TRIVIAL_LIMIT_SEQUENTIALLY] THEN
4849   ASM_MESON_TAC[]);;
4850
4851 (* ------------------------------------------------------------------------- *)
4852 (* Define continuity over a net to take in restrictions of the set.          *)
4853 (* ------------------------------------------------------------------------- *)
4854
4855 parse_as_infix ("continuous",(12,"right"));;
4856
4857 let continuous = new_definition
4858   `f continuous net <=> (f --> f(netlimit net)) net`;;
4859
4860 let CONTINUOUS_TRIVIAL_LIMIT = prove
4861  (`!f net. trivial_limit net ==> f continuous net`,
4862   SIMP_TAC[continuous; LIM]);;
4863
4864 let CONTINUOUS_WITHIN = prove
4865  (`!f x:real^M. f continuous (at x within s) <=> (f --> f(x)) (at x within s)`,
4866   REPEAT GEN_TAC THEN REWRITE_TAC[continuous] THEN
4867   ASM_CASES_TAC `trivial_limit(at (x:real^M) within s)` THENL
4868    [ASM_REWRITE_TAC[LIM]; ASM_SIMP_TAC[NETLIMIT_WITHIN]]);;
4869
4870 let CONTINUOUS_AT = prove
4871  (`!f (x:real^N). f continuous (at x) <=> (f --> f(x)) (at x)`,
4872   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
4873   REWRITE_TAC[CONTINUOUS_WITHIN; IN_UNIV]);;
4874
4875 let CONTINUOUS_AT_WITHIN = prove
4876  (`!f:real^M->real^N x s.
4877         f continuous (at x) ==> f continuous (at x within s)`,
4878   SIMP_TAC[LIM_AT_WITHIN; CONTINUOUS_AT; CONTINUOUS_WITHIN]);;
4879
4880 let CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL = prove
4881  (`!a s. closed s /\ ~(a IN s) ==> f continuous (at a within s)`,
4882   ASM_SIMP_TAC[continuous; LIM; LIM_WITHIN_CLOSED_TRIVIAL]);;
4883
4884 let CONTINUOUS_TRANSFORM_WITHIN = prove
4885  (`!f g:real^M->real^N s x d.
4886         &0 < d /\ x IN s /\
4887         (!x'. x' IN s /\ dist(x',x) < d ==> f(x') = g(x')) /\
4888         f continuous (at x within s)
4889         ==> g continuous (at x within s)`,
4890   REWRITE_TAC[CONTINUOUS_WITHIN] THEN
4891   MESON_TAC[LIM_TRANSFORM_WITHIN; DIST_REFL]);;
4892
4893 let CONTINUOUS_TRANSFORM_AT = prove
4894  (`!f g:real^M->real^N x d.
4895         &0 < d /\ (!x'. dist(x',x) < d ==> f(x') = g(x')) /\
4896         f continuous (at x)
4897         ==> g continuous (at x)`,
4898   REWRITE_TAC[CONTINUOUS_AT] THEN
4899   MESON_TAC[LIM_TRANSFORM_AT; DIST_REFL]);;
4900
4901 (* ------------------------------------------------------------------------- *)
4902 (* Derive the epsilon-delta forms, which we often use as "definitions"       *)
4903 (* ------------------------------------------------------------------------- *)
4904
4905 let continuous_within = prove
4906  (`f continuous (at x within s) <=>
4907         !e. &0 < e
4908             ==> ?d. &0 < d /\
4909                     !x'. x' IN s /\ dist(x',x) < d ==> dist(f(x'),f(x)) < e`,
4910   REWRITE_TAC[CONTINUOUS_WITHIN; LIM_WITHIN] THEN
4911   REWRITE_TAC[GSYM DIST_NZ] THEN MESON_TAC[DIST_REFL]);;
4912
4913 let continuous_at = prove
4914  (`f continuous (at x) <=>
4915         !e. &0 < e ==> ?d. &0 < d /\
4916                            !x'. dist(x',x) < d ==> dist(f(x'),f(x)) < e`,
4917   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
4918   REWRITE_TAC[continuous_within; IN_UNIV]);;
4919
4920 (* ------------------------------------------------------------------------- *)
4921 (* Versions in terms of open balls.                                          *)
4922 (* ------------------------------------------------------------------------- *)
4923
4924 let CONTINUOUS_WITHIN_BALL = prove
4925  (`!f s x. f continuous (at x within s) <=>
4926                 !e. &0 < e
4927                     ==> ?d. &0 < d /\
4928                             IMAGE f (ball(x,d) INTER s) SUBSET ball(f x,e)`,
4929   SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_BALL; continuous_within; IN_INTER] THEN
4930   MESON_TAC[DIST_SYM]);;
4931
4932 let CONTINUOUS_AT_BALL = prove
4933  (`!f x. f continuous (at x) <=>
4934                 !e. &0 < e
4935                     ==> ?d. &0 < d /\
4936                             IMAGE f (ball(x,d)) SUBSET ball(f x,e)`,
4937   SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_BALL; continuous_at] THEN
4938   MESON_TAC[DIST_SYM]);;
4939
4940 (* ------------------------------------------------------------------------- *)
4941 (* For setwise continuity, just start from the epsilon-delta definitions.    *)
4942 (* ------------------------------------------------------------------------- *)
4943
4944 parse_as_infix ("continuous_on",(12,"right"));;
4945 parse_as_infix ("uniformly_continuous_on",(12,"right"));;
4946
4947 let continuous_on = new_definition
4948   `f continuous_on s <=>
4949         !x. x IN s ==> !e. &0 < e
4950                            ==> ?d. &0 < d /\
4951                                    !x'. x' IN s /\ dist(x',x) < d
4952                                         ==> dist(f(x'),f(x)) < e`;;
4953
4954 let uniformly_continuous_on = new_definition
4955   `f uniformly_continuous_on s <=>
4956         !e. &0 < e
4957             ==> ?d. &0 < d /\
4958                     !x x'. x IN s /\ x' IN s /\ dist(x',x) < d
4959                            ==> dist(f(x'),f(x)) < e`;;
4960
4961 (* ------------------------------------------------------------------------- *)
4962 (* Some simple consequential lemmas.                                         *)
4963 (* ------------------------------------------------------------------------- *)
4964
4965 let UNIFORMLY_CONTINUOUS_IMP_CONTINUOUS = prove
4966  (`!f s. f uniformly_continuous_on s ==> f continuous_on s`,
4967   REWRITE_TAC[uniformly_continuous_on; continuous_on] THEN MESON_TAC[]);;
4968
4969 let CONTINUOUS_AT_IMP_CONTINUOUS_ON = prove
4970  (`!f s. (!x. x IN s ==> f continuous (at x)) ==> f continuous_on s`,
4971   REWRITE_TAC[continuous_at; continuous_on] THEN MESON_TAC[]);;
4972
4973 let CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN = prove
4974  (`!f s. f continuous_on s <=> !x. x IN s ==> f continuous (at x within s)`,
4975   REWRITE_TAC[continuous_on; continuous_within]);;
4976
4977 let CONTINUOUS_ON = prove
4978  (`!f (s:real^N->bool).
4979         f continuous_on s <=> !x. x IN s ==> (f --> f(x)) (at x within s)`,
4980   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_WITHIN]);;
4981
4982 let CONTINUOUS_ON_EQ_CONTINUOUS_AT = prove
4983  (`!f:real^M->real^N s.
4984       open s ==> (f continuous_on s <=> (!x. x IN s ==> f continuous (at x)))`,
4985   SIMP_TAC[CONTINUOUS_ON; CONTINUOUS_AT; LIM_WITHIN_OPEN]);;
4986
4987 let CONTINUOUS_WITHIN_SUBSET = prove
4988  (`!f s t x. f continuous (at x within s) /\ t SUBSET s
4989              ==> f continuous (at x within t)`,
4990    REWRITE_TAC[CONTINUOUS_WITHIN] THEN MESON_TAC[LIM_WITHIN_SUBSET]);;
4991
4992 let CONTINUOUS_ON_SUBSET = prove
4993  (`!f s t. f continuous_on s /\ t SUBSET s ==> f continuous_on t`,
4994   REWRITE_TAC[CONTINUOUS_ON] THEN MESON_TAC[SUBSET; LIM_WITHIN_SUBSET]);;
4995
4996 let UNIFORMLY_CONTINUOUS_ON_SUBSET = prove
4997  (`!f s t. f uniformly_continuous_on s /\ t SUBSET s
4998            ==> f uniformly_continuous_on t`,
4999   REWRITE_TAC[uniformly_continuous_on] THEN
5000   MESON_TAC[SUBSET; LIM_WITHIN_SUBSET]);;
5001
5002 let CONTINUOUS_ON_INTERIOR = prove
5003  (`!f:real^M->real^N s x.
5004         f continuous_on s /\ x IN interior(s) ==> f continuous at x`,
5005   REWRITE_TAC[interior; IN_ELIM_THM] THEN
5006   MESON_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT; CONTINUOUS_ON_SUBSET]);;
5007
5008 let CONTINUOUS_ON_EQ = prove
5009  (`!f g s. (!x. x IN s ==> f(x) = g(x)) /\ f continuous_on s
5010            ==> g continuous_on s`,
5011   SIMP_TAC[continuous_on; IMP_CONJ]);;
5012
5013 let UNIFORMLY_CONTINUOUS_ON_EQ = prove
5014  (`!f g s.
5015         (!x. x IN s ==> f x = g x) /\ f uniformly_continuous_on s
5016         ==> g uniformly_continuous_on s`,
5017   SIMP_TAC[uniformly_continuous_on; IMP_CONJ]);;
5018
5019 let CONTINUOUS_ON_SING = prove
5020  (`!f:real^M->real^N a. f continuous_on {a}`,
5021   SIMP_TAC[continuous_on; IN_SING; FORALL_UNWIND_THM2; DIST_REFL] THEN
5022   MESON_TAC[]);;
5023
5024 let CONTINUOUS_ON_EMPTY = prove
5025  (`!f:real^M->real^N. f continuous_on {}`,
5026   MESON_TAC[CONTINUOUS_ON_SING; EMPTY_SUBSET; CONTINUOUS_ON_SUBSET]);;
5027
5028 let CONTINUOUS_ON_NO_LIMPT = prove
5029  (`!f:real^M->real^N s.
5030      ~(?x. x limit_point_of s) ==> f continuous_on s`,
5031   REWRITE_TAC[continuous_on; LIMPT_APPROACHABLE] THEN MESON_TAC[DIST_REFL]);;
5032
5033 let CONTINUOUS_ON_FINITE = prove
5034  (`!f:real^M->real^N s. FINITE s ==> f continuous_on s`,
5035   MESON_TAC[CONTINUOUS_ON_NO_LIMPT; LIMIT_POINT_FINITE]);;
5036
5037 let CONTRACTION_IMP_CONTINUOUS_ON = prove
5038  (`!f:real^M->real^N.
5039         (!x y. x IN s /\ y IN s ==> dist(f x,f y) <= dist(x,y))
5040         ==> f continuous_on s`,
5041   SIMP_TAC[continuous_on] THEN MESON_TAC[REAL_LET_TRANS]);;
5042
5043 let ISOMETRY_ON_IMP_CONTINUOUS_ON = prove
5044  (`!f:real^M->real^N.
5045         (!x y. x IN s /\ y IN s ==> dist(f x,f y) = dist(x,y))
5046         ==> f continuous_on s`,
5047   SIMP_TAC[CONTRACTION_IMP_CONTINUOUS_ON; REAL_LE_REFL]);;
5048
5049 (* ------------------------------------------------------------------------- *)
5050 (* Characterization of various kinds of continuity in terms of sequences.    *)
5051 (* ------------------------------------------------------------------------- *)
5052
5053 let CONTINUOUS_WITHIN_SEQUENTIALLY = prove
5054  (`!f a:real^N.
5055         f continuous (at a within s) <=>
5056                 !x. (!n. x(n) IN s) /\ (x --> a) sequentially
5057                      ==> ((f o x) --> f(a)) sequentially`,
5058   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_within] THEN EQ_TAC THENL
5059    [REWRITE_TAC[LIM_SEQUENTIALLY; o_THM] THEN MESON_TAC[]; ALL_TAC] THEN
5060   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
5061   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
5062   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5063   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC `&1 / (&n + &1)`) THEN
5064   SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; REAL_OF_NUM_LE; REAL_POS; ARITH;
5065        REAL_ARITH `&0 <= n ==> &0 < n + &1`; NOT_FORALL_THM; SKOLEM_THM] THEN
5066   MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[NOT_IMP; FORALL_AND_THM] THEN
5067   X_GEN_TAC `y:num->real^N` THEN REWRITE_TAC[LIM_SEQUENTIALLY; o_THM] THEN
5068   STRIP_TAC THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[LE_REFL]] THEN
5069   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC FORALL_POS_MONO_1 THEN
5070   CONJ_TAC THENL [ASM_MESON_TAC[REAL_LT_TRANS]; ALL_TAC] THEN
5071   X_GEN_TAC `n:num` THEN EXISTS_TAC `n:num` THEN X_GEN_TAC `m:num` THEN
5072   DISCH_TAC THEN MATCH_MP_TAC REAL_LTE_TRANS THEN
5073   EXISTS_TAC `&1 / (&m + &1)` THEN ASM_REWRITE_TAC[] THEN
5074   ASM_SIMP_TAC[REAL_LE_INV2; real_div; REAL_ARITH `&0 <= x ==> &0 < x + &1`;
5075                REAL_POS; REAL_MUL_LID; REAL_LE_RADD; REAL_OF_NUM_LE]);;
5076
5077 let CONTINUOUS_AT_SEQUENTIALLY = prove
5078  (`!f a:real^N.
5079         f continuous (at a) <=>
5080               !x. (x --> a) sequentially
5081                   ==> ((f o x) --> f(a)) sequentially`,
5082   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
5083   REWRITE_TAC[CONTINUOUS_WITHIN_SEQUENTIALLY; IN_UNIV]);;
5084
5085 let CONTINUOUS_ON_SEQUENTIALLY = prove
5086  (`!f s:real^N->bool.
5087         f continuous_on s <=>
5088               !x a. a IN s /\ (!n. x(n) IN s) /\ (x --> a) sequentially
5089                     ==> ((f o x) --> f(a)) sequentially`,
5090   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
5091               CONTINUOUS_WITHIN_SEQUENTIALLY] THEN MESON_TAC[]);;
5092
5093 let UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY = prove
5094  (`!f s:real^N->bool.
5095         f uniformly_continuous_on s <=>
5096               !x y. (!n. x(n) IN s) /\ (!n. y(n) IN s) /\
5097                     ((\n. x(n) - y(n)) --> vec 0) sequentially
5098                     ==> ((\n. f(x(n)) - f(y(n))) --> vec 0) sequentially`,
5099   REPEAT GEN_TAC THEN REWRITE_TAC[uniformly_continuous_on] THEN
5100   REWRITE_TAC[LIM_SEQUENTIALLY; dist; VECTOR_SUB_RZERO] THEN
5101   EQ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
5102   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
5103   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; NOT_EXISTS_THM] THEN
5104   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
5105   DISCH_THEN(MP_TAC o GEN `n:num` o SPEC `&1 / (&n + &1)`) THEN
5106   SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; REAL_OF_NUM_LE; REAL_POS; ARITH;
5107        REAL_ARITH `&0 <= n ==> &0 < n + &1`; NOT_FORALL_THM; SKOLEM_THM] THEN
5108   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:num->real^N` THEN
5109   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:num->real^N` THEN
5110   REWRITE_TAC[NOT_IMP; FORALL_AND_THM] THEN STRIP_TAC THEN
5111   ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN CONJ_TAC THENL
5112    [MATCH_MP_TAC FORALL_POS_MONO_1 THEN
5113     CONJ_TAC THENL [ASM_MESON_TAC[REAL_LT_TRANS]; ALL_TAC] THEN
5114     X_GEN_TAC `n:num` THEN EXISTS_TAC `n:num` THEN X_GEN_TAC `m:num` THEN
5115     DISCH_TAC THEN MATCH_MP_TAC REAL_LTE_TRANS THEN
5116     EXISTS_TAC `&1 / (&m + &1)` THEN ASM_REWRITE_TAC[] THEN
5117     ASM_SIMP_TAC[REAL_LE_INV2; real_div; REAL_ARITH `&0 <= x ==> &0 < x + &1`;
5118                  REAL_POS; REAL_MUL_LID; REAL_LE_RADD; REAL_OF_NUM_LE];
5119     EXISTS_TAC `e:real` THEN ASM_REWRITE_TAC[] THEN
5120     EXISTS_TAC `\x:num. x` THEN ASM_REWRITE_TAC[LE_REFL]]);;
5121
5122 let LIM_CONTINUOUS_FUNCTION = prove
5123  (`!f net g l.
5124         f continuous (at l) /\ (g --> l) net ==> ((\x. f(g x)) --> f l) net`,
5125   REWRITE_TAC[tendsto; continuous_at; eventually] THEN MESON_TAC[]);;
5126
5127 (* ------------------------------------------------------------------------- *)
5128 (* Combination results for pointwise continuity.                             *)
5129 (* ------------------------------------------------------------------------- *)
5130
5131 let CONTINUOUS_CONST = prove
5132  (`!net c. (\x. c) continuous net`,
5133   REWRITE_TAC[continuous; LIM_CONST]);;
5134
5135 let CONTINUOUS_CMUL = prove
5136  (`!f c net. f continuous net ==> (\x. c % f(x)) continuous net`,
5137   REWRITE_TAC[continuous; LIM_CMUL]);;
5138
5139 let CONTINUOUS_NEG = prove
5140  (`!f net. f continuous net ==> (\x. --(f x)) continuous net`,
5141   REWRITE_TAC[continuous; LIM_NEG]);;
5142
5143 let CONTINUOUS_ADD = prove
5144  (`!f g net. f continuous net /\ g continuous net
5145            ==> (\x. f(x) + g(x)) continuous net`,
5146   REWRITE_TAC[continuous; LIM_ADD]);;
5147
5148 let CONTINUOUS_SUB = prove
5149  (`!f g net. f continuous net /\ g continuous net
5150            ==> (\x. f(x) - g(x)) continuous net`,
5151   REWRITE_TAC[continuous; LIM_SUB]);;
5152
5153 let CONTINUOUS_ABS = prove
5154  (`!(f:A->real^N) net.
5155         f continuous net
5156         ==> (\x. (lambda i. abs(f(x)$i)):real^N) continuous net`,
5157   REWRITE_TAC[continuous; LIM_ABS]);;
5158
5159 let CONTINUOUS_MAX = prove
5160  (`!(f:A->real^N) (g:A->real^N) net.
5161         f continuous net /\ g continuous net
5162         ==> (\x. (lambda i. max (f(x)$i) (g(x)$i)):real^N) continuous net`,
5163   REWRITE_TAC[continuous; LIM_MAX]);;
5164
5165 let CONTINUOUS_MIN = prove
5166  (`!(f:A->real^N) (g:A->real^N) net.
5167         f continuous net /\ g continuous net
5168         ==> (\x. (lambda i. min (f(x)$i) (g(x)$i)):real^N) continuous net`,
5169   REWRITE_TAC[continuous; LIM_MIN]);;
5170
5171 let CONTINUOUS_VSUM = prove
5172  (`!net f s. FINITE s /\ (!a. a IN s ==> (f a) continuous net)
5173              ==> (\x. vsum s (\a. f a x)) continuous net`,
5174   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
5175   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5176   SIMP_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY; VSUM_CLAUSES;
5177            CONTINUOUS_CONST; CONTINUOUS_ADD; ETA_AX]);;
5178
5179 (* ------------------------------------------------------------------------- *)
5180 (* Same thing for setwise continuity.                                        *)
5181 (* ------------------------------------------------------------------------- *)
5182
5183 let CONTINUOUS_ON_CONST = prove
5184  (`!s c. (\x. c) continuous_on s`,
5185   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_CONST]);;
5186
5187 let CONTINUOUS_ON_CMUL = prove
5188  (`!f c s. f continuous_on s ==> (\x. c % f(x)) continuous_on s`,
5189   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_CMUL]);;
5190
5191 let CONTINUOUS_ON_NEG = prove
5192  (`!f s. f continuous_on s
5193          ==> (\x. --(f x)) continuous_on s`,
5194   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_NEG]);;
5195
5196 let CONTINUOUS_ON_ADD = prove
5197  (`!f g s. f continuous_on s /\ g continuous_on s
5198            ==> (\x. f(x) + g(x)) continuous_on s`,
5199   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_ADD]);;
5200
5201 let CONTINUOUS_ON_SUB = prove
5202  (`!f g s. f continuous_on s /\ g continuous_on s
5203            ==> (\x. f(x) - g(x)) continuous_on s`,
5204   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_SUB]);;
5205
5206 let CONTINUOUS_ON_ABS = prove
5207  (`!f:real^M->real^N s.
5208         f continuous_on s
5209         ==> (\x. (lambda i. abs(f(x)$i)):real^N) continuous_on s`,
5210   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_ABS]);;
5211
5212 let CONTINUOUS_ON_MAX = prove
5213  (`!f:real^M->real^N g:real^M->real^N s.
5214         f continuous_on s /\ g continuous_on s
5215         ==> (\x. (lambda i. max (f(x)$i) (g(x)$i)):real^N)
5216             continuous_on s`,
5217   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_MAX]);;
5218
5219 let CONTINUOUS_ON_MIN = prove
5220  (`!f:real^M->real^N g:real^M->real^N s.
5221         f continuous_on s /\ g continuous_on s
5222         ==> (\x. (lambda i. min (f(x)$i) (g(x)$i)):real^N)
5223             continuous_on s`,
5224   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_MIN]);;
5225
5226 let CONTINUOUS_ON_VSUM = prove
5227  (`!t f s. FINITE s /\ (!a. a IN s ==> (f a) continuous_on t)
5228              ==> (\x. vsum s (\a. f a x)) continuous_on t`,
5229   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_VSUM]);;
5230
5231 (* ------------------------------------------------------------------------- *)
5232 (* Same thing for uniform continuity, using sequential formulations.         *)
5233 (* ------------------------------------------------------------------------- *)
5234
5235 let UNIFORMLY_CONTINUOUS_ON_CONST = prove
5236  (`!s c. (\x. c) uniformly_continuous_on s`,
5237   REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY; o_DEF;
5238               VECTOR_SUB_REFL; LIM_CONST]);;
5239
5240 let LINEAR_UNIFORMLY_CONTINUOUS_ON = prove
5241  (`!f:real^M->real^N s. linear f ==> f uniformly_continuous_on s`,
5242   REPEAT STRIP_TAC THEN
5243   ASM_SIMP_TAC[uniformly_continuous_on; dist; GSYM LINEAR_SUB] THEN
5244   FIRST_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o
5245         MATCH_MP LINEAR_BOUNDED_POS) THEN
5246   X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `e / B:real` THEN
5247   ASM_SIMP_TAC[REAL_LT_DIV] THEN
5248   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^M`] THEN STRIP_TAC THEN
5249   MATCH_MP_TAC REAL_LET_TRANS THEN
5250   EXISTS_TAC `B * norm(y - x:real^M)` THEN ASM_REWRITE_TAC[] THEN
5251   ASM_MESON_TAC[REAL_LT_RDIV_EQ; REAL_MUL_SYM]);;
5252
5253 let UNIFORMLY_CONTINUOUS_ON_COMPOSE = prove
5254  (`!f g s. f uniformly_continuous_on s /\
5255            g uniformly_continuous_on (IMAGE f s)
5256            ==> (g o f) uniformly_continuous_on s`,
5257   let lemma = prove
5258    (`(!y. ((?x. (y = f x) /\ P x) /\ Q y ==> R y)) <=>
5259      (!x. P x /\ Q (f x) ==> R (f x))`,
5260     MESON_TAC[]) in
5261   REPEAT GEN_TAC THEN
5262   REWRITE_TAC[uniformly_continuous_on; o_THM; IN_IMAGE] THEN
5263   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN REWRITE_TAC[lemma] THEN
5264   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`] THEN
5265   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN REWRITE_TAC[lemma] THEN
5266   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5267   MATCH_MP_TAC MONO_FORALL THEN
5268   X_GEN_TAC `e:real` THEN ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
5269   ASM_MESON_TAC[]);;
5270
5271 let BILINEAR_UNIFORMLY_CONTINUOUS_ON_COMPOSE = prove
5272  (`!f:real^M->real^N g (h:real^N->real^P->real^Q) s.
5273            f uniformly_continuous_on s /\ g uniformly_continuous_on s /\
5274            bilinear h /\ bounded(IMAGE f s) /\ bounded(IMAGE g s)
5275            ==> (\x. h (f x) (g x)) uniformly_continuous_on s`,
5276   REPEAT STRIP_TAC THEN REWRITE_TAC[uniformly_continuous_on; dist] THEN
5277   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5278   SUBGOAL_THEN
5279    `!a b c d. (h:real^N->real^P->real^Q) a b - h c d =
5280               h (a - c) b + h c (b - d)`
5281    (fun th -> ONCE_REWRITE_TAC[th])
5282   THENL
5283    [FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP BILINEAR_LSUB th]) THEN
5284     FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP BILINEAR_RSUB th]) THEN
5285     VECTOR_ARITH_TAC;
5286     ALL_TAC] THEN
5287   FIRST_X_ASSUM(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC o
5288     MATCH_MP BILINEAR_BOUNDED_POS) THEN
5289   UNDISCH_TAC `bounded(IMAGE (g:real^M->real^P) s)` THEN
5290   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
5291   REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE] THEN
5292   DISCH_THEN(X_CHOOSE_THEN `B1:real` STRIP_ASSUME_TAC) THEN
5293   DISCH_THEN(X_CHOOSE_THEN `B2:real` STRIP_ASSUME_TAC) THEN
5294   UNDISCH_TAC `(g:real^M->real^P) uniformly_continuous_on s` THEN
5295   UNDISCH_TAC `(f:real^M->real^N) uniformly_continuous_on s` THEN
5296   REWRITE_TAC[uniformly_continuous_on] THEN
5297   DISCH_THEN(MP_TAC o SPEC `e / &2 / &2 / B / B2`) THEN
5298   ASM_SIMP_TAC[REAL_LT_DIV; REAL_HALF; dist] THEN
5299   DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN
5300   DISCH_THEN(MP_TAC o SPEC `e / &2 / &2 / B / B1`) THEN
5301   ASM_SIMP_TAC[REAL_LT_DIV; REAL_HALF; dist] THEN
5302   DISCH_THEN(X_CHOOSE_THEN `d2:real` STRIP_ASSUME_TAC) THEN
5303   EXISTS_TAC `min d1 d2` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
5304   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^M`] THEN STRIP_TAC THEN
5305   REPEAT(FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^M`; `y:real^M`])) THEN
5306   ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
5307   MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC
5308    `B * e / &2 / &2 / B / B2 * B2 + B * B1 * e / &2 / &2 / B / B1` THEN
5309   CONJ_TAC THENL
5310    [MATCH_MP_TAC(NORM_ARITH
5311      `norm(x) <= a /\ norm(y) <= b ==> norm(x + y:real^N) <= a + b`) THEN
5312     CONJ_TAC THEN
5313     FIRST_X_ASSUM(fun th -> W(MP_TAC o PART_MATCH lhand th o lhand o snd)) THEN
5314     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN
5315     MATCH_MP_TAC REAL_LE_LMUL THEN ASM_SIMP_TAC[REAL_LT_IMP_LE] THEN
5316     MATCH_MP_TAC REAL_LE_MUL2 THEN
5317     ASM_SIMP_TAC[REAL_LT_IMP_LE; NORM_POS_LE];
5318     ASM_SIMP_TAC[REAL_DIV_RMUL; REAL_DIV_LMUL; REAL_LT_IMP_NZ] THEN
5319     ASM_REAL_ARITH_TAC]);;
5320
5321 let UNIFORMLY_CONTINUOUS_ON_MUL = prove
5322  (`!f g:real^M->real^N s.
5323         (lift o f) uniformly_continuous_on s /\ g uniformly_continuous_on s /\
5324         bounded(IMAGE (lift o f) s) /\ bounded(IMAGE g s)
5325         ==>  (\x. f x % g x) uniformly_continuous_on s`,
5326   REPEAT STRIP_TAC THEN
5327   MP_TAC(ISPECL
5328    [`lift o (f:real^M->real)`; `g:real^M->real^N`;
5329     `\c (v:real^N). drop c % v`; `s:real^M->bool`]
5330         BILINEAR_UNIFORMLY_CONTINUOUS_ON_COMPOSE) THEN
5331   ASM_REWRITE_TAC[o_THM; LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN
5332   REWRITE_TAC[bilinear; linear; DROP_ADD; DROP_CMUL] THEN VECTOR_ARITH_TAC);;
5333
5334 let UNIFORMLY_CONTINUOUS_ON_CMUL = prove
5335  (`!f c s. f uniformly_continuous_on s
5336            ==> (\x. c % f(x)) uniformly_continuous_on s`,
5337   REPEAT GEN_TAC THEN REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY] THEN
5338   REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
5339   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
5340   ASM_REWRITE_TAC[] THEN
5341   DISCH_THEN(MP_TAC o MATCH_MP LIM_CMUL) THEN
5342   ASM_SIMP_TAC[VECTOR_SUB_LDISTRIB; VECTOR_MUL_RZERO]);;
5343
5344 let UNIFORMLY_CONTINUOUS_ON_VMUL = prove
5345  (`!s:real^M->bool c v:real^N.
5346       (lift o c) uniformly_continuous_on s
5347       ==> (\x. c x % v) uniformly_continuous_on s`,
5348   REPEAT GEN_TAC THEN
5349   DISCH_THEN(MP_TAC o ISPEC `\x. (drop x % v:real^N)` o MATCH_MP
5350    (REWRITE_RULE[IMP_CONJ] UNIFORMLY_CONTINUOUS_ON_COMPOSE)) THEN
5351   REWRITE_TAC[o_DEF; LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN
5352   MATCH_MP_TAC LINEAR_UNIFORMLY_CONTINUOUS_ON THEN
5353   MATCH_MP_TAC LINEAR_VMUL_DROP THEN REWRITE_TAC[LINEAR_ID]);;
5354
5355 let UNIFORMLY_CONTINUOUS_ON_NEG = prove
5356  (`!f s. f uniformly_continuous_on s
5357          ==> (\x. --(f x)) uniformly_continuous_on s`,
5358   ONCE_REWRITE_TAC[VECTOR_NEG_MINUS1] THEN
5359   REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_CMUL]);;
5360
5361 let UNIFORMLY_CONTINUOUS_ON_ADD = prove
5362  (`!f g s. f uniformly_continuous_on s /\ g uniformly_continuous_on s
5363            ==> (\x. f(x) + g(x)) uniformly_continuous_on s`,
5364   REPEAT GEN_TAC THEN REWRITE_TAC[UNIFORMLY_CONTINUOUS_ON_SEQUENTIALLY] THEN
5365   REWRITE_TAC[AND_FORALL_THM] THEN
5366   REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
5367   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
5368   ASM_REWRITE_TAC[o_DEF] THEN DISCH_THEN(MP_TAC o MATCH_MP LIM_ADD) THEN
5369   MATCH_MP_TAC EQ_IMP THEN
5370   REWRITE_TAC[VECTOR_ADD_LID] THEN AP_THM_TAC THEN BINOP_TAC THEN
5371   REWRITE_TAC[FUN_EQ_THM] THEN VECTOR_ARITH_TAC);;
5372
5373 let UNIFORMLY_CONTINUOUS_ON_SUB = prove
5374  (`!f g s. f uniformly_continuous_on s /\ g uniformly_continuous_on s
5375            ==> (\x. f(x) - g(x)) uniformly_continuous_on s`,
5376   REWRITE_TAC[VECTOR_SUB] THEN
5377   SIMP_TAC[UNIFORMLY_CONTINUOUS_ON_NEG; UNIFORMLY_CONTINUOUS_ON_ADD]);;
5378
5379 let UNIFORMLY_CONTINUOUS_ON_VSUM = prove
5380  (`!t f s. FINITE s /\ (!a. a IN s ==> (f a) uniformly_continuous_on t)
5381              ==> (\x. vsum s (\a. f a x)) uniformly_continuous_on t`,
5382   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
5383   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
5384   SIMP_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY; VSUM_CLAUSES;
5385        UNIFORMLY_CONTINUOUS_ON_CONST; UNIFORMLY_CONTINUOUS_ON_ADD; ETA_AX]);;
5386
5387 (* ------------------------------------------------------------------------- *)
5388 (* Identity function is continuous in every sense.                           *)
5389 (* ------------------------------------------------------------------------- *)
5390
5391 let CONTINUOUS_WITHIN_ID = prove
5392  (`!a s. (\x. x) continuous (at a within s)`,
5393   REWRITE_TAC[continuous_within] THEN MESON_TAC[]);;
5394
5395 let CONTINUOUS_AT_ID = prove
5396  (`!a. (\x. x) continuous (at a)`,
5397   REWRITE_TAC[continuous_at] THEN MESON_TAC[]);;
5398
5399 let CONTINUOUS_ON_ID = prove
5400  (`!s. (\x. x) continuous_on s`,
5401   REWRITE_TAC[continuous_on] THEN MESON_TAC[]);;
5402
5403 let UNIFORMLY_CONTINUOUS_ON_ID = prove
5404  (`!s. (\x. x) uniformly_continuous_on s`,
5405   REWRITE_TAC[uniformly_continuous_on] THEN MESON_TAC[]);;
5406
5407 (* ------------------------------------------------------------------------- *)
5408 (* Continuity of all kinds is preserved under composition.                   *)
5409 (* ------------------------------------------------------------------------- *)
5410
5411 let CONTINUOUS_WITHIN_COMPOSE = prove
5412  (`!f g x s. f continuous (at x within s) /\
5413              g continuous (at (f x) within IMAGE f s)
5414              ==> (g o f) continuous (at x within s)`,
5415   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_within; o_THM; IN_IMAGE] THEN
5416   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5417   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
5418   ASM_MESON_TAC[]);;
5419
5420 let CONTINUOUS_AT_COMPOSE = prove
5421  (`!f g x. f continuous (at x) /\ g continuous (at (f x))
5422            ==> (g o f) continuous (at x)`,
5423   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
5424   MESON_TAC[CONTINUOUS_WITHIN_COMPOSE; IN_IMAGE; CONTINUOUS_WITHIN_SUBSET;
5425             SUBSET_UNIV; IN_UNIV]);;
5426
5427 let CONTINUOUS_ON_COMPOSE = prove
5428  (`!f g s. f continuous_on s /\ g continuous_on (IMAGE f s)
5429            ==> (g o f) continuous_on s`,
5430   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
5431   MESON_TAC[IN_IMAGE; CONTINUOUS_WITHIN_COMPOSE]);;
5432
5433 (* ------------------------------------------------------------------------- *)
5434 (* Continuity in terms of open preimages.                                    *)
5435 (* ------------------------------------------------------------------------- *)
5436
5437 let CONTINUOUS_WITHIN_OPEN = prove
5438  (`!f:real^M->real^N x u.
5439      f continuous (at x within u) <=>
5440         !t. open t /\ f(x) IN t
5441             ==> ?s. open s /\ x IN s /\
5442                     !x'. x' IN s /\ x' IN u ==> f(x') IN t`,
5443   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_within] THEN EQ_TAC THENL
5444    [DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN
5445     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
5446     GEN_REWRITE_TAC LAND_CONV [open_def] THEN
5447     DISCH_THEN(MP_TAC o SPEC `(f:real^M->real^N) x`) THEN
5448     ASM_MESON_TAC[IN_BALL; DIST_SYM; OPEN_BALL; CENTRE_IN_BALL; DIST_SYM];
5449     DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5450     FIRST_X_ASSUM(MP_TAC o SPEC `ball((f:real^M->real^N) x,e)`) THEN
5451     ASM_SIMP_TAC[OPEN_BALL; CENTRE_IN_BALL] THEN
5452     MESON_TAC[open_def; IN_BALL; REAL_LT_TRANS; DIST_SYM]]);;
5453
5454 let CONTINUOUS_AT_OPEN = prove
5455  (`!f:real^M->real^N x.
5456      f continuous (at x) <=>
5457         !t. open t /\ f(x) IN t
5458             ==> ?s. open s /\ x IN s /\
5459                     !x'. x' IN s ==> f(x') IN t`,
5460   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_at] THEN EQ_TAC THENL
5461    [DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN
5462     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
5463     GEN_REWRITE_TAC LAND_CONV [open_def] THEN
5464     DISCH_THEN(MP_TAC o SPEC `(f:real^M->real^N) x`) THEN
5465     ASM_MESON_TAC[IN_BALL; DIST_SYM; OPEN_BALL; CENTRE_IN_BALL];
5466     DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5467     FIRST_X_ASSUM(MP_TAC o SPEC `ball((f:real^M->real^N) x,e)`) THEN
5468     ASM_SIMP_TAC[OPEN_BALL; CENTRE_IN_BALL] THEN
5469     MESON_TAC[open_def; IN_BALL; REAL_LT_TRANS; DIST_SYM]]);;
5470
5471 let CONTINUOUS_ON_OPEN_GEN = prove
5472  (`!f:real^M->real^N s t.
5473     IMAGE f s SUBSET t
5474     ==> (f continuous_on s <=>
5475          !u. open_in (subtopology euclidean t) u
5476              ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN u})`,
5477   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_on] THEN EQ_TAC THENL
5478    [REWRITE_TAC[open_in; SUBSET; IN_ELIM_THM] THEN
5479     DISCH_TAC THEN X_GEN_TAC `u:real^N->bool` THEN STRIP_TAC THEN
5480     CONJ_TAC THENL [ASM_MESON_TAC[DIST_REFL]; ALL_TAC] THEN
5481     X_GEN_TAC `x:real^M` THEN STRIP_TAC THEN
5482     FIRST_X_ASSUM(MP_TAC o SPEC `(f:real^M->real^N) x`) THEN ASM SET_TAC[];
5483     DISCH_TAC THEN X_GEN_TAC `x:real^M` THEN
5484     DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
5485     FIRST_X_ASSUM(MP_TAC o
5486       SPEC `ball((f:real^M->real^N) x,e) INTER t`) THEN
5487     ANTS_TAC THENL
5488      [ASM_MESON_TAC[OPEN_IN_OPEN; INTER_COMM; OPEN_BALL]; ALL_TAC] THEN
5489     REWRITE_TAC[open_in; SUBSET; IN_INTER; IN_ELIM_THM; IN_BALL; IN_IMAGE] THEN
5490     REWRITE_TAC[AND_FORALL_THM] THEN DISCH_THEN(MP_TAC o SPEC `x:real^M`) THEN
5491     RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; FORALL_IN_IMAGE]) THEN
5492     ASM_MESON_TAC[DIST_REFL; DIST_SYM]]);;
5493
5494 let CONTINUOUS_ON_OPEN = prove
5495  (`!f:real^M->real^N s.
5496       f continuous_on s <=>
5497         !t. open_in (subtopology euclidean (IMAGE f s)) t
5498             ==> open_in (subtopology euclidean s) {x | x IN s /\ f(x) IN t}`,
5499   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_OPEN_GEN THEN
5500   REWRITE_TAC[SUBSET_REFL]);;
5501
5502 let CONTINUOUS_OPEN_IN_PREIMAGE_GEN = prove
5503  (`!f:real^M->real^N s t u.
5504         f continuous_on s /\ IMAGE f s SUBSET t /\
5505         open_in (subtopology euclidean t) u
5506         ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN u}`,
5507   MESON_TAC[CONTINUOUS_ON_OPEN_GEN]);;
5508
5509 let CONTINUOUS_ON_IMP_OPEN_IN = prove
5510  (`!f:real^M->real^N s t.
5511         f continuous_on s /\
5512         open_in (subtopology euclidean (IMAGE f s)) t
5513         ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
5514   MESON_TAC[CONTINUOUS_ON_OPEN]);;
5515
5516 (* ------------------------------------------------------------------------- *)
5517 (* Similarly in terms of closed sets.                                        *)
5518 (* ------------------------------------------------------------------------- *)
5519
5520 let CONTINUOUS_ON_CLOSED_GEN = prove
5521  (`!f:real^M->real^N s t.
5522     IMAGE f s SUBSET t
5523     ==> (f continuous_on s <=>
5524          !u. closed_in (subtopology euclidean t) u
5525              ==> closed_in (subtopology euclidean s)
5526                            {x | x IN s /\ f x IN u})`,
5527   REPEAT STRIP_TAC THEN FIRST_ASSUM(fun th ->
5528     ONCE_REWRITE_TAC[MATCH_MP CONTINUOUS_ON_OPEN_GEN th]) THEN
5529   EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `u:real^N->bool` THEN
5530   FIRST_X_ASSUM(MP_TAC o SPEC `t DIFF u:real^N->bool`) THENL
5531    [REWRITE_TAC[closed_in]; REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ]] THEN
5532   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
5533   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
5534   ASM_REWRITE_TAC[SUBSET_RESTRICT] THEN
5535   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
5536
5537 let CONTINUOUS_ON_CLOSED = prove
5538  (`!f:real^M->real^N s.
5539       f continuous_on s <=>
5540         !t. closed_in (subtopology euclidean (IMAGE f s)) t
5541             ==> closed_in (subtopology euclidean s) {x | x IN s /\ f(x) IN t}`,
5542   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_CLOSED_GEN THEN
5543   REWRITE_TAC[SUBSET_REFL]);;
5544
5545 let CONTINUOUS_CLOSED_IN_PREIMAGE_GEN = prove
5546  (`!f:real^M->real^N s t u.
5547         f continuous_on s /\ IMAGE f s SUBSET t /\
5548         closed_in (subtopology euclidean t) u
5549         ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x IN u}`,
5550   MESON_TAC[CONTINUOUS_ON_CLOSED_GEN]);;
5551
5552 let CONTINUOUS_ON_IMP_CLOSED_IN = prove
5553  (`!f:real^M->real^N s t.
5554         f continuous_on s /\
5555         closed_in (subtopology euclidean (IMAGE f s)) t
5556         ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
5557   MESON_TAC[CONTINUOUS_ON_CLOSED]);;
5558
5559 (* ------------------------------------------------------------------------- *)
5560 (* Half-global and completely global cases.                                  *)
5561 (* ------------------------------------------------------------------------- *)
5562
5563 let CONTINUOUS_OPEN_IN_PREIMAGE = prove
5564  (`!f s t.
5565          f continuous_on s /\ open t
5566          ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
5567   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[SET_RULE
5568    `x IN s /\ f x IN t <=> x IN s /\ f x IN (t INTER IMAGE f s)`] THEN
5569   FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[CONTINUOUS_ON_OPEN]) THEN
5570   ONCE_REWRITE_TAC[INTER_COMM] THEN MATCH_MP_TAC OPEN_IN_OPEN_INTER THEN
5571   ASM_REWRITE_TAC[]);;
5572
5573 let CONTINUOUS_CLOSED_IN_PREIMAGE = prove
5574  (`!f s t.
5575          f continuous_on s /\ closed t
5576          ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
5577   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[SET_RULE
5578    `x IN s /\ f x IN t <=> x IN s /\ f x IN (t INTER IMAGE f s)`] THEN
5579   FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[CONTINUOUS_ON_CLOSED]) THEN
5580   ONCE_REWRITE_TAC[INTER_COMM] THEN MATCH_MP_TAC CLOSED_IN_CLOSED_INTER THEN
5581   ASM_REWRITE_TAC[]);;
5582
5583 let CONTINUOUS_OPEN_PREIMAGE = prove
5584  (`!f:real^M->real^N s t.
5585      f continuous_on s /\ open s /\ open t
5586      ==> open {x | x IN s /\ f(x) IN t}`,
5587   REPEAT STRIP_TAC THEN
5588   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONTINUOUS_ON_OPEN]) THEN
5589   REWRITE_TAC [OPEN_IN_OPEN] THEN
5590   DISCH_THEN(MP_TAC o SPEC `IMAGE (f:real^M->real^N) s INTER t`) THEN
5591   ANTS_TAC THENL
5592    [EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC [];
5593     STRIP_TAC THEN
5594     SUBGOAL_THEN `{x | x IN s /\ (f:real^M->real^N) x IN t} =
5595                  s INTER t'` SUBST1_TAC THENL
5596     [ASM SET_TAC []; ASM_MESON_TAC [OPEN_INTER]]]);;
5597
5598 let CONTINUOUS_CLOSED_PREIMAGE = prove
5599  (`!f:real^M->real^N s t.
5600      f continuous_on s /\ closed s /\ closed t
5601      ==> closed {x | x IN s /\ f(x) IN t}`,
5602   REPEAT STRIP_TAC THEN
5603   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONTINUOUS_ON_CLOSED]) THEN
5604   REWRITE_TAC [CLOSED_IN_CLOSED] THEN
5605   DISCH_THEN(MP_TAC o SPEC `IMAGE (f:real^M->real^N) s INTER t`) THEN
5606   ANTS_TAC THENL
5607    [EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC [];
5608     STRIP_TAC THEN
5609     SUBGOAL_THEN `{x | x IN s /\ (f:real^M->real^N) x IN t} =
5610                  s INTER t'` SUBST1_TAC THENL
5611     [ASM SET_TAC []; ASM_MESON_TAC [CLOSED_INTER]]]);;
5612
5613 let CONTINUOUS_OPEN_PREIMAGE_UNIV = prove
5614  (`!f:real^M->real^N s.
5615         (!x. f continuous (at x)) /\ open s ==> open {x | f(x) IN s}`,
5616   REPEAT STRIP_TAC THEN
5617   MP_TAC(SPECL [`f:real^M->real^N`; `(:real^M)`; `s:real^N->bool`]
5618     CONTINUOUS_OPEN_PREIMAGE) THEN
5619   ASM_SIMP_TAC[OPEN_UNIV; IN_UNIV; CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
5620
5621 let CONTINUOUS_CLOSED_PREIMAGE_UNIV = prove
5622  (`!f:real^M->real^N s.
5623         (!x. f continuous (at x)) /\ closed s ==> closed {x | f(x) IN s}`,
5624   REPEAT STRIP_TAC THEN
5625   MP_TAC(SPECL [`f:real^M->real^N`; `(:real^M)`; `s:real^N->bool`]
5626     CONTINUOUS_CLOSED_PREIMAGE) THEN
5627   ASM_SIMP_TAC[CLOSED_UNIV; IN_UNIV; CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
5628
5629 let CONTINUOUS_OPEN_IN_PREIMAGE_EQ = prove
5630  (`!f:real^M->real^N s.
5631     f continuous_on s <=>
5632     !t. open t ==> open_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
5633   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CONTINUOUS_OPEN_IN_PREIMAGE] THEN
5634   REWRITE_TAC[CONTINUOUS_ON_OPEN] THEN DISCH_TAC THEN
5635   X_GEN_TAC `t:real^N->bool` THEN GEN_REWRITE_TAC LAND_CONV [OPEN_IN_OPEN] THEN
5636   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
5637   FIRST_X_ASSUM(MP_TAC o SPEC `u:real^N->bool`) THEN
5638   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN SET_TAC[]);;
5639
5640 let CONTINUOUS_CLOSED_IN_PREIMAGE_EQ = prove
5641  (`!f:real^M->real^N s.
5642     f continuous_on s <=>
5643     !t. closed t
5644         ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x IN t}`,
5645   REPEAT GEN_TAC THEN EQ_TAC THEN SIMP_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE] THEN
5646   REWRITE_TAC[CONTINUOUS_ON_CLOSED] THEN DISCH_TAC THEN
5647   X_GEN_TAC `t:real^N->bool` THEN
5648   GEN_REWRITE_TAC LAND_CONV [CLOSED_IN_CLOSED] THEN
5649   DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
5650   FIRST_X_ASSUM(MP_TAC o SPEC `u:real^N->bool`) THEN
5651   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN SET_TAC[]);;
5652
5653 (* ------------------------------------------------------------------------- *)
5654 (* Quotient maps are occasionally useful.                                    *)
5655 (* ------------------------------------------------------------------------- *)
5656
5657 let OPEN_MAP_IMP_QUOTIENT_MAP = prove
5658  (`!f:real^M->real^N s.
5659     f continuous_on s /\
5660     (!t. open_in (subtopology euclidean s) t
5661          ==> open_in (subtopology euclidean (IMAGE f s)) (IMAGE f t))
5662     ==> !t. t SUBSET IMAGE f s
5663             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN t} <=>
5664                  open_in (subtopology euclidean (IMAGE f s)) t)`,
5665   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
5666    [SUBGOAL_THEN
5667      `t = IMAGE f {x | x IN s /\ (f:real^M->real^N) x IN t}`
5668     SUBST1_TAC THENL [ASM SET_TAC[]; ASM_SIMP_TAC[]];
5669     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONTINUOUS_ON_OPEN]) THEN
5670     ASM_SIMP_TAC[]]);;
5671
5672 let CLOSED_MAP_IMP_QUOTIENT_MAP = prove
5673  (`!f:real^M->real^N s.
5674     f continuous_on s /\
5675     (!t. closed_in (subtopology euclidean s) t
5676          ==> closed_in (subtopology euclidean (IMAGE f s)) (IMAGE f t))
5677     ==> !t. t SUBSET IMAGE f s
5678             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN t} <=>
5679                  open_in (subtopology euclidean (IMAGE f s)) t)`,
5680   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
5681    [FIRST_X_ASSUM(MP_TAC o SPEC
5682      `s DIFF {x | x IN s /\ (f:real^M->real^N) x IN t}`) THEN
5683     ANTS_TAC THENL
5684      [MATCH_MP_TAC CLOSED_IN_DIFF THEN
5685       ASM_SIMP_TAC[CLOSED_IN_SUBTOPOLOGY_REFL;
5686                    TOPSPACE_EUCLIDEAN; SUBSET_UNIV];
5687       REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
5688       DISCH_THEN(MP_TAC o CONJUNCT2) THEN MATCH_MP_TAC EQ_IMP THEN
5689       AP_TERM_TAC THEN ASM SET_TAC[]];
5690     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CONTINUOUS_ON_OPEN]) THEN
5691     ASM_SIMP_TAC[]]);;
5692
5693 let CONTINUOUS_RIGHT_INVERSE_IMP_QUOTIENT_MAP = prove
5694  (`!f:real^M->real^N g s t.
5695         f continuous_on s /\ IMAGE f s SUBSET t /\
5696         g continuous_on t /\ IMAGE g t SUBSET s /\
5697         (!y. y IN t ==> f(g y) = y)
5698         ==> (!u. u SUBSET t
5699             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
5700                  open_in (subtopology euclidean t) u))`,
5701   REWRITE_TAC[CONTINUOUS_ON_OPEN] THEN REPEAT STRIP_TAC THEN EQ_TAC THENL
5702    [DISCH_TAC THEN FIRST_ASSUM(MP_TAC o SPEC `(IMAGE (g:real^N->real^M) t)
5703        INTER
5704        {x | x IN s /\ (f:real^M->real^N) x IN u}`) THEN
5705     ANTS_TAC THENL
5706      [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
5707       REWRITE_TAC[OPEN_IN_OPEN] THEN MATCH_MP_TAC MONO_EXISTS THEN
5708       ASM SET_TAC[];
5709       MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]];
5710     DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
5711     SUBGOAL_THEN `IMAGE (f:real^M->real^N) s = t`
5712      (fun th -> ASM_REWRITE_TAC[th]) THEN
5713     ASM SET_TAC[]]);;
5714
5715 let CONTINUOUS_LEFT_INVERSE_IMP_QUOTIENT_MAP = prove
5716  (`!f:real^M->real^N g s.
5717         f continuous_on s /\ g continuous_on (IMAGE f s) /\
5718         (!x. x IN s ==> g(f x) = x)
5719         ==> (!u. u SUBSET (IMAGE f s)
5720             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
5721                  open_in (subtopology euclidean (IMAGE f s)) u))`,
5722   REPEAT GEN_TAC THEN STRIP_TAC THEN
5723   MATCH_MP_TAC CONTINUOUS_RIGHT_INVERSE_IMP_QUOTIENT_MAP THEN
5724   EXISTS_TAC `g:real^N->real^M` THEN
5725   ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;
5726
5727 let QUOTIENT_MAP_OPEN_CLOSED = prove
5728  (`!f:real^M->real^N s t.
5729     IMAGE f s SUBSET t
5730     ==> ((!u. u SUBSET t
5731               ==> (open_in (subtopology euclidean s)
5732                            {x | x IN s /\ f x IN u} <=>
5733                    open_in (subtopology euclidean t) u)) <=>
5734          (!u. u SUBSET t
5735               ==> (closed_in (subtopology euclidean s)
5736                              {x | x IN s /\ f x IN u} <=>
5737                    closed_in (subtopology euclidean t) u)))`,
5738   SIMP_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
5739   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN
5740   X_GEN_TAC `u:real^N->bool` THEN
5741   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `t DIFF u:real^N->bool`) THEN
5742   ASM_SIMP_TAC[SET_RULE `u SUBSET t ==> t DIFF (t DIFF u) = u`] THEN
5743   (ANTS_TAC THENL [SET_TAC[]; DISCH_THEN(SUBST1_TAC o SYM)]) THEN
5744   REWRITE_TAC[SUBSET_RESTRICT] THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
5745
5746 (* ------------------------------------------------------------------------- *)
5747 (* More properties of open and closed maps.                                  *)
5748 (* ------------------------------------------------------------------------- *)
5749
5750 let CLOSED_MAP_IMP_OPEN_MAP = prove
5751  (`!f:real^M->real^N s t.
5752
5753         IMAGE f s = t /\
5754         (!u. closed_in (subtopology euclidean s) u
5755                 ==> closed_in (subtopology euclidean t) (IMAGE f u)) /\
5756         (!u. open_in (subtopology euclidean s) u
5757              ==> open_in (subtopology euclidean s)
5758                          {x | x IN s /\ f x IN IMAGE f u})
5759         ==> (!u. open_in (subtopology euclidean s) u
5760                  ==> open_in (subtopology euclidean t) (IMAGE f u))`,
5761   REPEAT STRIP_TAC THEN
5762   SUBGOAL_THEN
5763     `IMAGE (f:real^M->real^N) u =
5764      t DIFF IMAGE f (s DIFF {x | x IN s /\ f x IN IMAGE f u})`
5765   SUBST1_TAC THENL
5766    [FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN ASM SET_TAC[];
5767     MATCH_MP_TAC OPEN_IN_DIFF THEN REWRITE_TAC[OPEN_IN_REFL] THEN
5768     FIRST_X_ASSUM MATCH_MP_TAC THEN
5769     MATCH_MP_TAC CLOSED_IN_DIFF THEN REWRITE_TAC[OPEN_IN_REFL] THEN
5770     ASM_SIMP_TAC[CLOSED_IN_REFL]]);;
5771
5772 let OPEN_MAP_IMP_CLOSED_MAP = prove
5773  (`!f:real^M->real^N s t.
5774         IMAGE f s = t /\
5775         (!u. open_in (subtopology euclidean s) u
5776                 ==> open_in (subtopology euclidean t) (IMAGE f u)) /\
5777         (!u. closed_in (subtopology euclidean s) u
5778              ==> closed_in (subtopology euclidean s)
5779                          {x | x IN s /\ f x IN IMAGE f u})
5780         ==> (!u. closed_in (subtopology euclidean s) u
5781                  ==> closed_in (subtopology euclidean t) (IMAGE f u))`,
5782   REPEAT STRIP_TAC THEN
5783   SUBGOAL_THEN
5784     `IMAGE (f:real^M->real^N) u =
5785      t DIFF IMAGE f (s DIFF {x | x IN s /\ f x IN IMAGE f u})`
5786   SUBST1_TAC THENL
5787    [FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN ASM SET_TAC[];
5788     MATCH_MP_TAC CLOSED_IN_DIFF THEN REWRITE_TAC[CLOSED_IN_REFL] THEN
5789     FIRST_X_ASSUM MATCH_MP_TAC THEN
5790     MATCH_MP_TAC OPEN_IN_DIFF THEN REWRITE_TAC[CLOSED_IN_REFL] THEN
5791     ASM_SIMP_TAC[OPEN_IN_REFL]]);;
5792
5793 let OPEN_MAP_FROM_COMPOSITION_SURJECTIVE = prove
5794  (`!f:real^M->real^N g:real^N->real^P s t u.
5795         f continuous_on s /\ IMAGE f s = t /\ IMAGE g t SUBSET u /\
5796         (!k. open_in (subtopology euclidean s) k
5797              ==> open_in (subtopology euclidean u) (IMAGE (g o f) k))
5798         ==> (!k. open_in (subtopology euclidean t) k
5799                  ==> open_in (subtopology euclidean u) (IMAGE g k))`,
5800   REPEAT STRIP_TAC THEN SUBGOAL_THEN
5801    `IMAGE g k = IMAGE ((g:real^N->real^P) o (f:real^M->real^N))
5802                       {x | x IN s /\ f(x) IN k}`
5803   SUBST1_TAC THENL
5804    [FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
5805     REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[];
5806     FIRST_X_ASSUM MATCH_MP_TAC THEN
5807     MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE_GEN THEN
5808     EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[SUBSET_REFL]]);;
5809
5810 let CLOSED_MAP_FROM_COMPOSITION_SURJECTIVE = prove
5811  (`!f:real^M->real^N g:real^N->real^P s t u.
5812         f continuous_on s /\ IMAGE f s = t /\ IMAGE g t SUBSET u /\
5813         (!k. closed_in (subtopology euclidean s) k
5814              ==> closed_in (subtopology euclidean u) (IMAGE (g o f) k))
5815         ==> (!k. closed_in (subtopology euclidean t) k
5816                  ==> closed_in (subtopology euclidean u) (IMAGE g k))`,
5817   REPEAT STRIP_TAC THEN SUBGOAL_THEN
5818    `IMAGE g k = IMAGE ((g:real^N->real^P) o (f:real^M->real^N))
5819                       {x | x IN s /\ f(x) IN k}`
5820   SUBST1_TAC THENL
5821    [FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
5822     REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[];
5823     FIRST_X_ASSUM MATCH_MP_TAC THEN
5824     MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE_GEN THEN
5825     EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[SUBSET_REFL]]);;
5826
5827 let OPEN_MAP_FROM_COMPOSITION_INJECTIVE = prove
5828  (`!f:real^M->real^N g:real^N->real^P s t u.
5829         IMAGE f s SUBSET t /\ IMAGE g t SUBSET u /\
5830         g continuous_on t /\ (!x y. x IN t /\ y IN t /\ g x = g y ==> x = y) /\
5831         (!k. open_in (subtopology euclidean s) k
5832              ==> open_in (subtopology euclidean u) (IMAGE (g o f) k))
5833         ==> (!k. open_in (subtopology euclidean s) k
5834                  ==> open_in (subtopology euclidean t) (IMAGE f k))`,
5835   REPEAT STRIP_TAC THEN SUBGOAL_THEN
5836    `IMAGE f k = {x | x IN t /\
5837                     g(x) IN IMAGE ((g:real^N->real^P) o (f:real^M->real^N)) k}`
5838   SUBST1_TAC THENL
5839    [FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN
5840     REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[];
5841     MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE_GEN THEN
5842     EXISTS_TAC `u:real^P->bool` THEN ASM_SIMP_TAC[]]);;
5843
5844 let CLOSED_MAP_FROM_COMPOSITION_INJECTIVE = prove
5845  (`!f:real^M->real^N g:real^N->real^P s t u.
5846         IMAGE f s SUBSET t /\ IMAGE g t SUBSET u /\
5847         g continuous_on t /\ (!x y. x IN t /\ y IN t /\ g x = g y ==> x = y) /\
5848         (!k. closed_in (subtopology euclidean s) k
5849              ==> closed_in (subtopology euclidean u) (IMAGE (g o f) k))
5850         ==> (!k. closed_in (subtopology euclidean s) k
5851                  ==> closed_in (subtopology euclidean t) (IMAGE f k))`,
5852   REPEAT STRIP_TAC THEN SUBGOAL_THEN
5853    `IMAGE f k = {x | x IN t /\
5854                     g(x) IN IMAGE ((g:real^N->real^P) o (f:real^M->real^N)) k}`
5855   SUBST1_TAC THENL
5856    [FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
5857     REWRITE_TAC[IMAGE_o] THEN ASM SET_TAC[];
5858     MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE_GEN THEN
5859     EXISTS_TAC `u:real^P->bool` THEN ASM_SIMP_TAC[]]);;
5860
5861 (* ------------------------------------------------------------------------- *)
5862 (* Two equivalent characterizations of a proper/perfect map.                 *)
5863 (* ------------------------------------------------------------------------- *)
5864
5865 let PROPER_MAP = prove
5866  (`!f:real^M->real^N s t.
5867     IMAGE f s SUBSET t
5868     ==> ((!k. k SUBSET t /\ compact k ==> compact {x | x IN s /\ f x IN k}) <=>
5869          (!k. closed_in (subtopology euclidean s) k
5870               ==> closed_in (subtopology euclidean t) (IMAGE f k)) /\
5871          (!a. a IN t ==> compact {x | x IN s /\ f x = a}))`,
5872   REPEAT STRIP_TAC THEN EQ_TAC THENL
5873    [REPEAT STRIP_TAC THENL
5874      [ALL_TAC;
5875       ONCE_REWRITE_TAC[SET_RULE `x = a <=> x IN {a}`] THEN
5876       FIRST_X_ASSUM MATCH_MP_TAC THEN
5877       ASM_REWRITE_TAC[SING_SUBSET; COMPACT_SING]] THEN
5878     FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
5879     REWRITE_TAC[CLOSED_IN_LIMPT] THEN
5880     CONJ_TAC THENL [ASM SET_TAC[]; X_GEN_TAC `y:real^N`] THEN
5881     REWRITE_TAC[LIMPT_SEQUENTIAL_INJ; IN_DELETE] THEN
5882     REWRITE_TAC[IN_IMAGE; LEFT_AND_EXISTS_THM; SKOLEM_THM] THEN
5883     ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN
5884     REWRITE_TAC[GSYM CONJ_ASSOC; FORALL_AND_THM] THEN
5885     ONCE_REWRITE_TAC[GSYM FUN_EQ_THM] THEN
5886     REWRITE_TAC[UNWIND_THM2; FUN_EQ_THM] THEN
5887     DISCH_THEN(X_CHOOSE_THEN `x:num->real^M` STRIP_ASSUME_TAC) THEN
5888     SUBGOAL_THEN
5889      `~(INTERS {{a | a IN k /\
5890                      (f:real^M->real^N) a IN
5891                      (y INSERT IMAGE (\i. f(x(n + i))) (:num))} |
5892                 n IN (:num)} = {})`
5893     MP_TAC THENL
5894      [MATCH_MP_TAC COMPACT_FIP THEN CONJ_TAC THENL
5895        [REWRITE_TAC[FORALL_IN_GSPEC; IN_UNIV] THEN X_GEN_TAC `n:num` THEN
5896         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [CLOSED_IN_CLOSED]) THEN
5897         DISCH_THEN(X_CHOOSE_THEN `c:real^M->bool` STRIP_ASSUME_TAC) THEN
5898         ASM_REWRITE_TAC[SET_RULE
5899          `{x | x IN s INTER k /\ P x} = k INTER {x | x IN s /\ P x}`] THEN
5900         MATCH_MP_TAC CLOSED_INTER_COMPACT THEN ASM_REWRITE_TAC[] THEN
5901         FIRST_X_ASSUM MATCH_MP_TAC THEN
5902         CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5903         MATCH_MP_TAC COMPACT_SEQUENCE_WITH_LIMIT THEN
5904         FIRST_ASSUM(MP_TAC o SPEC `n:num` o MATCH_MP SEQ_OFFSET) THEN
5905         REWRITE_TAC[ADD_SYM];
5906         REWRITE_TAC[SIMPLE_IMAGE; FORALL_FINITE_SUBSET_IMAGE] THEN
5907         X_GEN_TAC `i:num->bool` THEN STRIP_TAC THEN
5908         FIRST_ASSUM(MP_TAC o ISPEC `\n:num. n` o MATCH_MP
5909           UPPER_BOUND_FINITE_SET) THEN
5910         REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_TAC `m:num`) THEN
5911         REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; INTERS_IMAGE; IN_ELIM_THM] THEN
5912         EXISTS_TAC `(x:num->real^M) m` THEN
5913         X_GEN_TAC `p:num` THEN DISCH_TAC THEN
5914         CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
5915         REWRITE_TAC[IN_INSERT; IN_IMAGE; IN_UNIV] THEN DISJ2_TAC THEN
5916         EXISTS_TAC `m - p:num` THEN
5917         ASM_MESON_TAC[ARITH_RULE `p <= m ==> p + m - p:num = m`]];
5918       REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN MATCH_MP_TAC MONO_EXISTS THEN
5919       X_GEN_TAC `x:real^M` THEN
5920       REWRITE_TAC[INTERS_GSPEC; IN_ELIM_THM; IN_UNIV] THEN
5921       DISCH_THEN(fun th -> LABEL_TAC "*" th THEN MP_TAC(SPEC `0` th)) THEN
5922       REWRITE_TAC[ADD_CLAUSES; IN_INSERT; IN_IMAGE; IN_UNIV] THEN
5923       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (DISJ_CASES_THEN MP_TAC)) THEN
5924       ASM_SIMP_TAC[] THEN DISCH_THEN(X_CHOOSE_TAC `i:num`) THEN
5925       REMOVE_THEN "*" (MP_TAC o SPEC `i + 1`) THEN
5926       ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
5927       ASM_REWRITE_TAC[IN_INSERT; IN_IMAGE; IN_UNIV] THEN ARITH_TAC];
5928     STRIP_TAC THEN X_GEN_TAC `k:real^N->bool` THEN STRIP_TAC THEN
5929     REWRITE_TAC[COMPACT_EQ_HEINE_BOREL] THEN
5930     X_GEN_TAC `c:(real^M->bool)->bool` THEN STRIP_TAC THEN
5931     SUBGOAL_THEN
5932      `!a. a IN k
5933           ==> ?g. g SUBSET c /\ FINITE g /\
5934                   {x | x IN s /\ (f:real^M->real^N) x = a} SUBSET UNIONS g`
5935     MP_TAC THENL
5936      [X_GEN_TAC `a:real^N` THEN DISCH_TAC THEN UNDISCH_THEN
5937        `!a. a IN t ==> compact {x | x IN s /\ (f:real^M->real^N) x = a}`
5938        (MP_TAC o SPEC `a:real^N`) THEN
5939       ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[COMPACT_EQ_HEINE_BOREL]] THEN
5940       DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[];
5941       GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
5942       REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
5943       X_GEN_TAC `uu:real^N->(real^M->bool)->bool` THEN
5944       DISCH_THEN(LABEL_TAC "*")] THEN
5945     SUBGOAL_THEN
5946      `!a. a IN k
5947           ==> ?v. open v /\ a IN v /\
5948                  {x | x IN s /\ (f:real^M->real^N) x IN v} SUBSET UNIONS(uu a)`
5949     MP_TAC THENL
5950      [REPEAT STRIP_TAC THEN
5951       UNDISCH_THEN
5952        `!k. closed_in (subtopology euclidean s) k
5953             ==> closed_in (subtopology euclidean t)
5954                           (IMAGE (f:real^M->real^N) k)`
5955        (MP_TAC o SPEC `(s:real^M->bool) DIFF UNIONS(uu(a:real^N))`) THEN
5956       SIMP_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN ANTS_TAC THENL
5957        [CONJ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
5958         REWRITE_TAC[SET_RULE `s DIFF (s DIFF t) = s INTER t`] THEN
5959         MATCH_MP_TAC OPEN_IN_OPEN_INTER THEN
5960         MATCH_MP_TAC OPEN_UNIONS THEN ASM SET_TAC[];
5961         DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
5962         REWRITE_TAC[OPEN_IN_OPEN] THEN MATCH_MP_TAC MONO_EXISTS THEN
5963         X_GEN_TAC `v:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
5964         REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N`)) THEN
5965         ASM_REWRITE_TAC[] THEN REPEAT
5966          ((ANTS_TAC THENL [ASM SET_TAC[]; DISCH_TAC]) ORELSE STRIP_TAC)
5967         THENL [ALL_TAC; ASM SET_TAC[]] THEN
5968         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
5969         DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN ASM SET_TAC[]];
5970       GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
5971       REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
5972       X_GEN_TAC `vv:real^N->(real^N->bool)` THEN
5973       DISCH_THEN(LABEL_TAC "+")] THEN
5974     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL]) THEN
5975     DISCH_THEN(MP_TAC o SPEC `IMAGE (vv:real^N->(real^N->bool)) k`) THEN
5976     ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN
5977     ONCE_REWRITE_TAC[TAUT `p /\ q /\ r ==> s <=> q /\ p ==> r ==> s`] THEN
5978     REWRITE_TAC[FORALL_FINITE_SUBSET_IMAGE] THEN
5979     X_GEN_TAC `j:real^N->bool` THEN REPEAT STRIP_TAC THEN
5980     EXISTS_TAC `UNIONS(IMAGE (uu:real^N->(real^M->bool)->bool) j)` THEN
5981     REPEAT CONJ_TAC THENL
5982      [ASM SET_TAC[];
5983       ASM_SIMP_TAC[FINITE_UNIONS; FORALL_IN_IMAGE; FINITE_IMAGE] THEN
5984       ASM SET_TAC[];
5985       REWRITE_TAC[UNIONS_IMAGE; SUBSET; IN_UNIONS; IN_ELIM_THM] THEN
5986       ASM SET_TAC[]]]);;
5987
5988 let PROPER_MAP_FROM_COMPACT = prove
5989  (`!f:real^M->real^N s k.
5990         f continuous_on s /\ IMAGE f s SUBSET t /\ compact s /\
5991         closed_in (subtopology euclidean t) k
5992         ==> compact {x | x IN s /\ f x IN k}`,
5993   REPEAT STRIP_TAC THEN
5994   MATCH_MP_TAC CLOSED_IN_COMPACT THEN EXISTS_TAC `s:real^M->bool` THEN
5995   ASM_MESON_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE_GEN]);;
5996
5997 (* ------------------------------------------------------------------------- *)
5998 (* Pasting functions together on open sets.                                  *)
5999 (* ------------------------------------------------------------------------- *)
6000
6001 let PASTING_LEMMA = prove
6002  (`!f:A->real^M->real^N g t s k.
6003         (!i. i IN k
6004              ==> open_in (subtopology euclidean s) (t i) /\
6005                  (f i) continuous_on (t i)) /\
6006         (!i j x. i IN k /\ j IN k /\ x IN s INTER t i INTER t j
6007                  ==> f i x = f j x) /\
6008         (!x. x IN s ==> ?j. j IN k /\ x IN t j /\ g x = f j x)
6009         ==> g continuous_on s`,
6010   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_OPEN_IN_PREIMAGE_EQ] THEN
6011   STRIP_TAC THEN X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
6012   SUBGOAL_THEN
6013    `{x | x IN s /\ g x IN u} =
6014     UNIONS {{x | x IN (t i) /\ ((f:A->real^M->real^N) i x) IN u} |
6015             i IN k}`
6016   SUBST1_TAC THENL
6017    [SUBGOAL_THEN `!i. i IN k ==> ((t:A->real^M->bool) i) SUBSET s`
6018     ASSUME_TAC THENL
6019      [ASM_MESON_TAC[OPEN_IN_SUBSET; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY];
6020       REWRITE_TAC[UNIONS_GSPEC] THEN ASM SET_TAC[]];
6021     MATCH_MP_TAC OPEN_IN_UNIONS THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
6022     ASM_MESON_TAC[OPEN_IN_TRANS]]);;
6023
6024 let PASTING_LEMMA_EXISTS = prove
6025  (`!f:A->real^M->real^N t s k.
6026         s SUBSET UNIONS {t i | i IN k} /\
6027         (!i. i IN k
6028              ==> open_in (subtopology euclidean s) (t i) /\
6029                  (f i) continuous_on (t i)) /\
6030         (!i j x. i IN k /\ j IN k /\ x IN s INTER t i INTER t j
6031                  ==> f i x = f j x)
6032         ==> ?g. g continuous_on s /\
6033                 (!x i. i IN k /\ x IN s INTER t i ==> g x = f i x)`,
6034   REPEAT STRIP_TAC THEN
6035   EXISTS_TAC `\x. (f:A->real^M->real^N)(@i. i IN k /\ x IN t i) x` THEN
6036   CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN MATCH_MP_TAC PASTING_LEMMA THEN
6037   MAP_EVERY EXISTS_TAC
6038    [`f:A->real^M->real^N`; `t:A->real^M->bool`; `k:A->bool`] THEN
6039   ASM SET_TAC[]);;
6040
6041 let CONTINUOUS_ON_UNION_LOCAL_OPEN = prove
6042  (`!f:real^M->real^N s.
6043         open_in (subtopology euclidean (s UNION t)) s /\
6044         open_in (subtopology euclidean (s UNION t)) t /\
6045         f continuous_on s /\ f continuous_on t
6046         ==> f continuous_on (s UNION t)`,
6047   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
6048    [`\i:(real^M->bool). (f:real^M->real^N)`; `f:real^M->real^N`;
6049     `\i:(real^M->bool). i`; `s UNION t:real^M->bool`; `{s:real^M->bool,t}`]
6050    PASTING_LEMMA) THEN DISCH_THEN MATCH_MP_TAC THEN
6051   ASM_REWRITE_TAC[FORALL_IN_INSERT; EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN
6052   REWRITE_TAC[IN_UNION]);;
6053
6054 let CONTINUOUS_ON_UNION_OPEN = prove
6055  (`!f s t. open s /\ open t /\ f continuous_on s /\ f continuous_on t
6056            ==> f continuous_on (s UNION t)`,
6057   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_UNION_LOCAL_OPEN THEN
6058   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC OPEN_OPEN_IN_TRANS THEN
6059   ASM_SIMP_TAC[OPEN_UNION] THEN SET_TAC[]);;
6060
6061 let CONTINUOUS_ON_CASES_LOCAL_OPEN = prove
6062  (`!P f g:real^M->real^N s t.
6063         open_in (subtopology euclidean (s UNION t)) s /\
6064         open_in (subtopology euclidean (s UNION t)) t /\
6065         f continuous_on s /\ g continuous_on t /\
6066         (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x)
6067         ==> (\x. if P x then f x else g x) continuous_on (s UNION t)`,
6068   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_UNION_LOCAL_OPEN THEN
6069   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THENL
6070    [EXISTS_TAC `f:real^M->real^N`; EXISTS_TAC `g:real^M->real^N`] THEN
6071   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
6072
6073 let CONTINUOUS_ON_CASES_OPEN = prove
6074  (`!P f g s t.
6075            open s /\
6076            open t /\
6077            f continuous_on s /\
6078            g continuous_on t /\
6079            (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x)
6080            ==> (\x. if P x then f x else g x) continuous_on s UNION t`,
6081   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL_OPEN THEN
6082   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC OPEN_OPEN_IN_TRANS THEN
6083   ASM_SIMP_TAC[OPEN_UNION] THEN SET_TAC[]);;
6084
6085 (* ------------------------------------------------------------------------- *)
6086 (* Likewise on closed sets, with a finiteness assumption.                    *)
6087 (* ------------------------------------------------------------------------- *)
6088
6089 let PASTING_LEMMA_CLOSED = prove
6090  (`!f:A->real^M->real^N g t s k.
6091         FINITE k /\
6092         (!i. i IN k
6093              ==> closed_in (subtopology euclidean s) (t i) /\
6094                  (f i) continuous_on (t i)) /\
6095         (!i j x. i IN k /\ j IN k /\ x IN s INTER t i INTER t j
6096                  ==> f i x = f j x) /\
6097         (!x. x IN s ==> ?j. j IN k /\ x IN t j /\ g x = f j x)
6098         ==> g continuous_on s`,
6099   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE_EQ] THEN
6100   STRIP_TAC THEN X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
6101   SUBGOAL_THEN
6102    `{x | x IN s /\ g x IN u} =
6103     UNIONS {{x | x IN (t i) /\ ((f:A->real^M->real^N) i x) IN u} |
6104             i IN k}`
6105   SUBST1_TAC THENL
6106    [SUBGOAL_THEN `!i. i IN k ==> ((t:A->real^M->bool) i) SUBSET s`
6107     ASSUME_TAC THENL
6108      [ASM_MESON_TAC[CLOSED_IN_SUBSET; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY];
6109       REWRITE_TAC[UNIONS_GSPEC] THEN ASM SET_TAC[]];
6110     MATCH_MP_TAC CLOSED_IN_UNIONS THEN
6111     ASM_SIMP_TAC[SIMPLE_IMAGE; FINITE_IMAGE; FORALL_IN_IMAGE] THEN
6112     ASM_MESON_TAC[CLOSED_IN_TRANS]]);;
6113
6114 let PASTING_LEMMA_EXISTS_CLOSED = prove
6115  (`!f:A->real^M->real^N t s k.
6116         FINITE k /\
6117         s SUBSET UNIONS {t i | i IN k} /\
6118         (!i. i IN k
6119              ==> closed_in (subtopology euclidean s) (t i) /\
6120                  (f i) continuous_on (t i)) /\
6121         (!i j x. i IN k /\ j IN k /\ x IN s INTER t i INTER t j
6122                  ==> f i x = f j x)
6123         ==> ?g. g continuous_on s /\
6124                 (!x i. i IN k /\ x IN s INTER t i ==> g x = f i x)`,
6125   REPEAT STRIP_TAC THEN
6126   EXISTS_TAC `\x. (f:A->real^M->real^N)(@i. i IN k /\ x IN t i) x` THEN
6127   CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
6128   MATCH_MP_TAC PASTING_LEMMA_CLOSED THEN
6129   MAP_EVERY EXISTS_TAC
6130    [`f:A->real^M->real^N`; `t:A->real^M->bool`; `k:A->bool`] THEN
6131   ASM SET_TAC[]);;
6132
6133 (* ------------------------------------------------------------------------- *)
6134 (* Closure of halflines, halfspaces and hyperplanes.                         *)
6135 (* ------------------------------------------------------------------------- *)
6136
6137 let LIM_LIFT_DOT = prove
6138  (`!f:real^M->real^N a.
6139         (f --> l) net ==> ((lift o (\y. a dot f(y))) --> lift(a dot l)) net`,
6140   REPEAT GEN_TAC THEN ASM_CASES_TAC `a = vec 0:real^N` THENL
6141    [ASM_REWRITE_TAC[DOT_LZERO; LIFT_NUM; o_DEF; LIM_CONST]; ALL_TAC] THEN
6142   REWRITE_TAC[LIM] THEN MATCH_MP_TAC MONO_OR THEN REWRITE_TAC[] THEN
6143   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
6144   FIRST_X_ASSUM(MP_TAC o SPEC `e / norm(a:real^N)`) THEN
6145   ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; REAL_LT_RDIV_EQ] THEN
6146   REWRITE_TAC[dist; o_THM; GSYM LIFT_SUB; GSYM DOT_RSUB; NORM_LIFT] THEN
6147   ONCE_REWRITE_TAC[DOT_SYM] THEN
6148   MESON_TAC[NORM_CAUCHY_SCHWARZ_ABS; REAL_MUL_SYM; REAL_LET_TRANS]);;
6149
6150 let CONTINUOUS_AT_LIFT_DOT = prove
6151  (`!a:real^N x. (lift o (\y. a dot y)) continuous at x`,
6152   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_AT; o_THM] THEN
6153   MATCH_MP_TAC LIM_LIFT_DOT THEN REWRITE_TAC[LIM_AT] THEN MESON_TAC[]);;
6154
6155 let CONTINUOUS_ON_LIFT_DOT = prove
6156  (`!s. (lift o (\y. a dot y)) continuous_on s`,
6157   SIMP_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON; CONTINUOUS_AT_LIFT_DOT]);;
6158
6159 let CLOSED_INTERVAL_LEFT = prove
6160  (`!b:real^N.
6161      closed
6162         {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> x$i <= b$i}`,
6163   REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE; IN_ELIM_THM] THEN
6164   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
6165   FIRST_X_ASSUM(MP_TAC o SPEC `(x:real^N)$i - (b:real^N)$i`) THEN
6166   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
6167   DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
6168   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6169   REWRITE_TAC[dist; REAL_NOT_LT] THEN
6170   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs((z - x :real^N)$i)` THEN
6171   ASM_SIMP_TAC[COMPONENT_LE_NORM] THEN
6172   ASM_SIMP_TAC[VECTOR_SUB_COMPONENT] THEN
6173   ASM_SIMP_TAC[REAL_ARITH `z <= b /\ b < x ==> x - b <= abs(z - x)`]);;
6174
6175 let CLOSED_INTERVAL_RIGHT = prove
6176  (`!a:real^N.
6177      closed
6178         {x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= x$i}`,
6179   REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE; IN_ELIM_THM] THEN
6180   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
6181   FIRST_X_ASSUM(MP_TAC o SPEC `(a:real^N)$i - (x:real^N)$i`) THEN
6182   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
6183   DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
6184   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6185   REWRITE_TAC[dist; REAL_NOT_LT] THEN
6186   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs((z - x :real^N)$i)` THEN
6187   ASM_SIMP_TAC[COMPONENT_LE_NORM] THEN
6188   ASM_SIMP_TAC[VECTOR_SUB_COMPONENT] THEN
6189   ASM_SIMP_TAC[REAL_ARITH `x < a /\ a <= z ==> a - x <= abs(z - x)`]);;
6190
6191 let CLOSED_HALFSPACE_LE = prove
6192  (`!a:real^N b. closed {x | a dot x <= b}`,
6193   REPEAT GEN_TAC THEN
6194   MP_TAC(ISPEC `(:real^N)` CONTINUOUS_ON_LIFT_DOT) THEN
6195   REWRITE_TAC[CONTINUOUS_ON_CLOSED; GSYM CLOSED_IN; SUBTOPOLOGY_UNIV] THEN
6196   DISCH_THEN(MP_TAC o SPEC
6197    `IMAGE lift {r | ?x:real^N. (a dot x = r) /\ r <= b}`) THEN
6198   ANTS_TAC THENL
6199    [ALL_TAC;
6200     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
6201     REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; IN_UNIV] THEN
6202     REWRITE_TAC[o_DEF] THEN MESON_TAC[LIFT_DROP]] THEN
6203   REWRITE_TAC[CLOSED_IN_CLOSED] THEN
6204   EXISTS_TAC `{x | !i. 1 <= i /\ i <= dimindex(:1)
6205                        ==> (x:real^1)$i <= (lift b)$i}` THEN
6206   REWRITE_TAC[CLOSED_INTERVAL_LEFT] THEN
6207   SIMP_TAC[EXTENSION; IN_IMAGE; IN_UNIV; IN_ELIM_THM; IN_INTER;
6208     VEC_COMPONENT; DIMINDEX_1; LAMBDA_BETA; o_THM] THEN
6209   SIMP_TAC[ARITH_RULE `1 <= i /\ i <= 1 <=> (i = 1)`] THEN
6210   REWRITE_TAC[GSYM drop; LEFT_FORALL_IMP_THM; EXISTS_REFL] THEN
6211   MESON_TAC[LIFT_DROP]);;
6212
6213 let CLOSED_HALFSPACE_GE = prove
6214  (`!a:real^N b. closed {x | a dot x >= b}`,
6215   REWRITE_TAC[REAL_ARITH `a >= b <=> --a <= --b`] THEN
6216   REWRITE_TAC[GSYM DOT_LNEG; CLOSED_HALFSPACE_LE]);;
6217
6218 let CLOSED_HYPERPLANE = prove
6219  (`!a b. closed {x | a dot x = b}`,
6220   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
6221   REWRITE_TAC[REAL_ARITH `b <= a dot x <=> a dot x >= b`] THEN
6222   REWRITE_TAC[SET_RULE `{x | P x /\ Q x} = {x | P x} INTER {x | Q x}`] THEN
6223   SIMP_TAC[CLOSED_INTER; CLOSED_HALFSPACE_LE; CLOSED_HALFSPACE_GE]);;
6224
6225 let CLOSED_STANDARD_HYPERPLANE = prove
6226  (`!k a. closed {x:real^N | x$k = a}`,
6227   REPEAT GEN_TAC THEN
6228   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6229   CHOOSE_TAC THENL
6230    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6231   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSED_HYPERPLANE) THEN
6232   ASM_SIMP_TAC[DOT_BASIS]);;
6233
6234 let CLOSED_HALFSPACE_COMPONENT_LE = prove
6235  (`!a k. closed {x:real^N | x$k <= a}`,
6236   REPEAT GEN_TAC THEN
6237   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6238   CHOOSE_TAC THENL
6239    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6240   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSED_HALFSPACE_LE) THEN
6241   ASM_SIMP_TAC[DOT_BASIS]);;
6242
6243 let CLOSED_HALFSPACE_COMPONENT_GE = prove
6244  (`!a k. closed {x:real^N | x$k >= a}`,
6245   REPEAT GEN_TAC THEN
6246   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6247   CHOOSE_TAC THENL
6248    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6249   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSED_HALFSPACE_GE) THEN
6250   ASM_SIMP_TAC[DOT_BASIS]);;
6251
6252 (* ------------------------------------------------------------------------- *)
6253 (* Openness of halfspaces.                                                   *)
6254 (* ------------------------------------------------------------------------- *)
6255
6256 let OPEN_HALFSPACE_LT = prove
6257  (`!a b. open {x | a dot x < b}`,
6258   REWRITE_TAC[GSYM REAL_NOT_LE] THEN
6259   REWRITE_TAC[SET_RULE `{x | ~p x} = UNIV DIFF {x | p x}`] THEN
6260   REWRITE_TAC[GSYM closed; GSYM real_ge; CLOSED_HALFSPACE_GE]);;
6261
6262 let OPEN_HALFSPACE_COMPONENT_LT = prove
6263  (`!a k. open {x:real^N | x$k < a}`,
6264   REPEAT GEN_TAC THEN
6265   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6266   CHOOSE_TAC THENL
6267    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6268   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] OPEN_HALFSPACE_LT) THEN
6269   ASM_SIMP_TAC[DOT_BASIS]);;
6270
6271 let OPEN_HALFSPACE_GT = prove
6272  (`!a b. open {x | a dot x > b}`,
6273   REWRITE_TAC[REAL_ARITH `x > y <=> ~(x <= y)`] THEN
6274   REWRITE_TAC[SET_RULE `{x | ~p x} = UNIV DIFF {x | p x}`] THEN
6275   REWRITE_TAC[GSYM closed; CLOSED_HALFSPACE_LE]);;
6276
6277 let OPEN_HALFSPACE_COMPONENT_GT = prove
6278  (`!a k. open {x:real^N | x$k > a}`,
6279   REPEAT GEN_TAC THEN
6280   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6281   CHOOSE_TAC THENL
6282    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6283   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] OPEN_HALFSPACE_GT) THEN
6284   ASM_SIMP_TAC[DOT_BASIS]);;
6285
6286 let OPEN_POSITIVE_MULTIPLES = prove
6287  (`!s:real^N->bool. open s ==> open {c % x | &0 < c /\ x IN s}`,
6288   REWRITE_TAC[open_def; FORALL_IN_GSPEC] THEN GEN_TAC THEN DISCH_TAC THEN
6289   MAP_EVERY X_GEN_TAC [`c:real`; `x:real^N`] THEN STRIP_TAC THEN
6290   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
6291   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
6292   EXISTS_TAC `c * e:real` THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
6293   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
6294   FIRST_X_ASSUM(MP_TAC o SPEC `inv(c) % y:real^N`) THEN ANTS_TAC THENL
6295    [SUBGOAL_THEN `x:real^N = inv c % c % x` SUBST1_TAC THENL
6296      [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID;
6297                    REAL_LT_IMP_NZ];
6298       ASM_SIMP_TAC[DIST_MUL; real_abs; REAL_LT_INV_EQ; REAL_LT_IMP_LE] THEN
6299       ONCE_REWRITE_TAC[REAL_ARITH `inv c * x:real = x / c`] THEN
6300       ASM_MESON_TAC[REAL_LT_LDIV_EQ; REAL_MUL_SYM]];
6301     DISCH_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN
6302     EXISTS_TAC `c:real` THEN EXISTS_TAC `inv(c) % y:real^N` THEN
6303     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; REAL_LT_IMP_NZ] THEN
6304     VECTOR_ARITH_TAC]);;
6305
6306 (* ------------------------------------------------------------------------- *)
6307 (* Closures and interiors of halfspaces.                                     *)
6308 (* ------------------------------------------------------------------------- *)
6309
6310 let INTERIOR_HALFSPACE_LE = prove
6311  (`!a:real^N b.
6312         ~(a = vec 0) ==> interior {x | a dot x <= b} = {x | a dot x < b}`,
6313   REPEAT STRIP_TAC THEN MATCH_MP_TAC INTERIOR_UNIQUE THEN
6314   SIMP_TAC[OPEN_HALFSPACE_LT; SUBSET; IN_ELIM_THM; REAL_LT_IMP_LE] THEN
6315   X_GEN_TAC `s:real^N->bool` THEN STRIP_TAC THEN
6316   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN ASM_SIMP_TAC[REAL_LT_LE] THEN
6317   DISCH_TAC THEN
6318   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
6319   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
6320   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6321   REWRITE_TAC[SUBSET; IN_CBALL] THEN
6322   DISCH_THEN(MP_TAC o SPEC `x + e / norm(a) % a:real^N`) THEN
6323   REWRITE_TAC[NORM_ARITH `dist(x:real^N,x + y) = norm y`] THEN
6324   ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL;
6325                NORM_EQ_0; REAL_ARITH `&0 < x ==> abs x <= x`] THEN
6326   DISCH_TAC THEN
6327   FIRST_X_ASSUM(MP_TAC o SPEC  `x + e / norm(a) % a:real^N`) THEN
6328   ASM_REWRITE_TAC[DOT_RADD; DOT_RMUL] THEN
6329   MATCH_MP_TAC(REAL_ARITH `&0 < e ==> ~(b + e <= b)`) THEN
6330   ASM_SIMP_TAC[REAL_LT_MUL; REAL_LT_DIV; NORM_POS_LT; DOT_POS_LT]);;
6331
6332 let INTERIOR_HALFSPACE_GE = prove
6333  (`!a:real^N b.
6334         ~(a = vec 0) ==> interior {x | a dot x >= b} = {x | a dot x > b}`,
6335   REPEAT STRIP_TAC THEN
6336   ONCE_REWRITE_TAC[REAL_ARITH `a >= b <=> --a <= --b`;
6337                    REAL_ARITH `a > b <=> --a < --b`] THEN
6338   ASM_SIMP_TAC[GSYM DOT_LNEG; INTERIOR_HALFSPACE_LE; VECTOR_NEG_EQ_0]);;
6339
6340 let INTERIOR_HALFSPACE_COMPONENT_LE = prove
6341  (`!a k. interior {x:real^N | x$k <= a} = {x | x$k < a}`,
6342   REPEAT GEN_TAC THEN
6343   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6344   CHOOSE_TAC THENL
6345    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6346   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] INTERIOR_HALFSPACE_LE) THEN
6347   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
6348
6349 let INTERIOR_HALFSPACE_COMPONENT_GE = prove
6350  (`!a k. interior {x:real^N | x$k >= a} = {x | x$k > a}`,
6351   REPEAT GEN_TAC THEN
6352   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6353   CHOOSE_TAC THENL
6354    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6355   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] INTERIOR_HALFSPACE_GE) THEN
6356   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
6357
6358 let CLOSURE_HALFSPACE_LT = prove
6359  (`!a:real^N b.
6360         ~(a = vec 0) ==> closure {x | a dot x < b} = {x | a dot x <= b}`,
6361   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSURE_INTERIOR] THEN
6362   REWRITE_TAC[SET_RULE `UNIV DIFF {x | P x} = {x | ~P x}`] THEN
6363   ASM_SIMP_TAC[REAL_ARITH `~(x < b) <=> x >= b`; INTERIOR_HALFSPACE_GE] THEN
6364   REWRITE_TAC[EXTENSION; IN_DIFF; IN_UNIV; IN_ELIM_THM] THEN REAL_ARITH_TAC);;
6365
6366 let CLOSURE_HALFSPACE_GT = prove
6367  (`!a:real^N b.
6368         ~(a = vec 0) ==> closure {x | a dot x > b} = {x | a dot x >= b}`,
6369   REPEAT STRIP_TAC THEN
6370   ONCE_REWRITE_TAC[REAL_ARITH `a >= b <=> --a <= --b`;
6371                    REAL_ARITH `a > b <=> --a < --b`] THEN
6372   ASM_SIMP_TAC[GSYM DOT_LNEG; CLOSURE_HALFSPACE_LT; VECTOR_NEG_EQ_0]);;
6373
6374 let CLOSURE_HALFSPACE_COMPONENT_LT = prove
6375  (`!a k. closure {x:real^N | x$k < a} = {x | x$k <= a}`,
6376   REPEAT GEN_TAC THEN
6377   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6378   CHOOSE_TAC THENL
6379    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6380   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSURE_HALFSPACE_LT) THEN
6381   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
6382
6383 let CLOSURE_HALFSPACE_COMPONENT_GT = prove
6384  (`!a k. closure {x:real^N | x$k > a} = {x | x$k >= a}`,
6385   REPEAT GEN_TAC THEN
6386   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6387   CHOOSE_TAC THENL
6388    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6389   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] CLOSURE_HALFSPACE_GT) THEN
6390   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
6391
6392 let INTERIOR_HYPERPLANE = prove
6393  (`!a b. ~(a = vec 0) ==> interior {x | a dot x = b} = {}`,
6394   REWRITE_TAC[REAL_ARITH `x = y <=> x <= y /\ x >= y`] THEN
6395   REWRITE_TAC[SET_RULE `{x | p x /\ q x} = {x | p x} INTER {x | q x}`] THEN
6396   REWRITE_TAC[INTERIOR_INTER] THEN
6397   ASM_SIMP_TAC[INTERIOR_HALFSPACE_LE; INTERIOR_HALFSPACE_GE] THEN
6398   REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM; NOT_IN_EMPTY] THEN
6399   REAL_ARITH_TAC);;
6400
6401 let FRONTIER_HALFSPACE_LE = prove
6402  (`!a:real^N b. ~(a = vec 0 /\ b = &0)
6403                 ==> frontier {x | a dot x <= b} = {x | a dot x = b}`,
6404   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
6405   ASM_SIMP_TAC[DOT_LZERO] THENL
6406    [ASM_CASES_TAC `&0 <= b` THEN
6407     ASM_REWRITE_TAC[UNIV_GSPEC; FRONTIER_UNIV; EMPTY_GSPEC; FRONTIER_EMPTY];
6408     ASM_SIMP_TAC[frontier; INTERIOR_HALFSPACE_LE; CLOSURE_CLOSED;
6409                  CLOSED_HALFSPACE_LE] THEN
6410     REWRITE_TAC[EXTENSION; IN_DIFF; IN_ELIM_THM] THEN REAL_ARITH_TAC]);;
6411
6412 let FRONTIER_HALFSPACE_GE = prove
6413  (`!a:real^N b. ~(a = vec 0 /\ b = &0)
6414                 ==> frontier {x | a dot x >= b} = {x | a dot x = b}`,
6415   REPEAT STRIP_TAC THEN
6416   MP_TAC(ISPECL [`--a:real^N`; `--b:real`] FRONTIER_HALFSPACE_LE) THEN
6417   ASM_REWRITE_TAC[VECTOR_NEG_EQ_0; REAL_NEG_EQ_0; DOT_LNEG] THEN
6418   REWRITE_TAC[REAL_LE_NEG2; REAL_EQ_NEG2; real_ge]);;
6419
6420 let FRONTIER_HALFSPACE_LT = prove
6421  (`!a:real^N b. ~(a = vec 0 /\ b = &0)
6422                 ==> frontier {x | a dot x < b} = {x | a dot x = b}`,
6423   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
6424   ASM_SIMP_TAC[DOT_LZERO] THENL
6425    [ASM_CASES_TAC `&0 < b` THEN
6426     ASM_REWRITE_TAC[UNIV_GSPEC; FRONTIER_UNIV; EMPTY_GSPEC; FRONTIER_EMPTY];
6427     ASM_SIMP_TAC[frontier; CLOSURE_HALFSPACE_LT; INTERIOR_OPEN;
6428                  OPEN_HALFSPACE_LT] THEN
6429     REWRITE_TAC[EXTENSION; IN_DIFF; IN_ELIM_THM] THEN REAL_ARITH_TAC]);;
6430
6431 let FRONTIER_HALFSPACE_GT = prove
6432  (`!a:real^N b. ~(a = vec 0 /\ b = &0)
6433                 ==> frontier {x | a dot x > b} = {x | a dot x = b}`,
6434   REPEAT STRIP_TAC THEN
6435   MP_TAC(ISPECL [`--a:real^N`; `--b:real`] FRONTIER_HALFSPACE_LT) THEN
6436   ASM_REWRITE_TAC[VECTOR_NEG_EQ_0; REAL_NEG_EQ_0; DOT_LNEG] THEN
6437   REWRITE_TAC[REAL_LT_NEG2; REAL_EQ_NEG2; real_gt]);;
6438
6439 let INTERIOR_STANDARD_HYPERPLANE = prove
6440  (`!k a. interior {x:real^N | x$k = a} = {}`,
6441   REPEAT GEN_TAC THEN
6442   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !x:real^N. x$k = x$i`
6443   CHOOSE_TAC THENL
6444    [ASM_REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6445   MP_TAC(ISPECL [`basis i:real^N`; `a:real`] INTERIOR_HYPERPLANE) THEN
6446   ASM_SIMP_TAC[DOT_BASIS; BASIS_NONZERO]);;
6447
6448 let EMPTY_INTERIOR_LOWDIM = prove
6449  (`!s:real^N->bool. dim(s) < dimindex(:N) ==> interior s = {}`,
6450   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP LOWDIM_SUBSET_HYPERPLANE) THEN
6451   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
6452   MATCH_MP_TAC(SET_RULE
6453    `!t u. s SUBSET t /\ t SUBSET u /\ u = {} ==> s = {}`) THEN
6454   MAP_EVERY EXISTS_TAC
6455    [`interior(span(s):real^N->bool)`;
6456     `interior({x:real^N | a dot x = &0})`] THEN
6457   ASM_SIMP_TAC[SUBSET_INTERIOR; SPAN_INC; INTERIOR_HYPERPLANE]);;
6458
6459 (* ------------------------------------------------------------------------- *)
6460 (* Unboundedness of halfspaces.                                              *)
6461 (* ------------------------------------------------------------------------- *)
6462
6463 let UNBOUNDED_HALFSPACE_COMPONENT_LE = prove
6464  (`!a k. ~bounded {x:real^N | x$k <= a}`,
6465   REPEAT GEN_TAC THEN
6466   SUBGOAL_THEN `?i. 1 <= i /\ i <= dimindex(:N) /\ !z:real^N. z$k = z$i`
6467   CHOOSE_TAC THENL [REWRITE_TAC[FINITE_INDEX_INRANGE]; ALL_TAC] THEN
6468   ASM_REWRITE_TAC[bounded; FORALL_IN_GSPEC] THEN
6469   DISCH_THEN(X_CHOOSE_THEN `B:real` MP_TAC) THEN
6470   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP] THEN
6471   EXISTS_TAC `--(&1 + max (abs B) (abs a)) % basis i:real^N` THEN
6472   ASM_SIMP_TAC[NORM_MUL; NORM_BASIS; BASIS_COMPONENT;
6473                VECTOR_MUL_COMPONENT] THEN
6474   REAL_ARITH_TAC);;
6475
6476 let UNBOUNDED_HALFSPACE_COMPONENT_GE = prove
6477  (`!a k. ~bounded {x:real^N | x$k >= a}`,
6478   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP BOUNDED_NEGATIONS) THEN
6479   MP_TAC(SPECL [`--a:real`; `k:num`] UNBOUNDED_HALFSPACE_COMPONENT_LE) THEN
6480   REWRITE_TAC[CONTRAPOS_THM] THEN MATCH_MP_TAC EQ_IMP THEN
6481   AP_TERM_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN CONJ_TAC THENL
6482    [MESON_TAC[VECTOR_NEG_NEG];
6483     REWRITE_TAC[IN_ELIM_THM; VECTOR_NEG_COMPONENT] THEN REAL_ARITH_TAC]);;
6484
6485 let UNBOUNDED_HALFSPACE_COMPONENT_LT = prove
6486  (`!a k. ~bounded {x:real^N | x$k < a}`,
6487   ONCE_REWRITE_TAC[GSYM BOUNDED_CLOSURE_EQ] THEN
6488   REWRITE_TAC[CLOSURE_HALFSPACE_COMPONENT_LT;
6489               UNBOUNDED_HALFSPACE_COMPONENT_LE]);;
6490
6491 let UNBOUNDED_HALFSPACE_COMPONENT_GT = prove
6492  (`!a k. ~bounded {x:real^N | x$k > a}`,
6493   ONCE_REWRITE_TAC[GSYM BOUNDED_CLOSURE_EQ] THEN
6494   REWRITE_TAC[CLOSURE_HALFSPACE_COMPONENT_GT;
6495               UNBOUNDED_HALFSPACE_COMPONENT_GE]);;
6496
6497 let BOUNDED_HALFSPACE_LE = prove
6498  (`!a:real^N b. bounded {x | a dot x <= b} <=> a = vec 0 /\ b < &0`,
6499   GEOM_BASIS_MULTIPLE_TAC 1 `a:real^N` THEN
6500   SIMP_TAC[DOT_LMUL; DOT_BASIS; VECTOR_MUL_EQ_0; DIMINDEX_GE_1; LE_REFL;
6501            BASIS_NONZERO] THEN
6502   X_GEN_TAC `a:real` THEN ASM_CASES_TAC `a = &0` THEN ASM_REWRITE_TAC[] THEN
6503   DISCH_TAC THEN X_GEN_TAC `b:real` THENL
6504    [REWRITE_TAC[REAL_MUL_LZERO; DOT_LZERO; GSYM REAL_NOT_LE] THEN
6505     ASM_CASES_TAC `&0 <= b` THEN
6506     ASM_REWRITE_TAC[BOUNDED_EMPTY; NOT_BOUNDED_UNIV;
6507                     SET_RULE `{x | T} = UNIV`; EMPTY_GSPEC];
6508     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
6509     ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; REAL_LT_LE;
6510                  UNBOUNDED_HALFSPACE_COMPONENT_LE]]);;
6511
6512 let BOUNDED_HALFSPACE_GE = prove
6513  (`!a:real^N b. bounded {x | a dot x >= b} <=> a = vec 0 /\ &0 < b`,
6514   REWRITE_TAC[REAL_ARITH `a >= b <=> --a <= --b`] THEN
6515   REWRITE_TAC[GSYM DOT_LNEG; BOUNDED_HALFSPACE_LE] THEN
6516   REWRITE_TAC[VECTOR_NEG_EQ_0; REAL_ARITH `--b < &0 <=> &0 < b`]);;
6517
6518 let BOUNDED_HALFSPACE_LT = prove
6519  (`!a:real^N b. bounded {x | a dot x < b} <=> a = vec 0 /\ b <= &0`,
6520   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = vec 0` THEN
6521   ASM_REWRITE_TAC[] THENL
6522    [REWRITE_TAC[DOT_LZERO; GSYM REAL_NOT_LE] THEN ASM_CASES_TAC `b <= &0` THEN
6523     ASM_REWRITE_TAC[BOUNDED_EMPTY; NOT_BOUNDED_UNIV;
6524                     SET_RULE `{x | T} = UNIV`; EMPTY_GSPEC];
6525     ONCE_REWRITE_TAC[GSYM BOUNDED_CLOSURE_EQ] THEN
6526     ASM_SIMP_TAC[CLOSURE_HALFSPACE_LT; BOUNDED_HALFSPACE_LE]]);;
6527
6528 let BOUNDED_HALFSPACE_GT = prove
6529  (`!a:real^N b. bounded {x | a dot x > b} <=> a = vec 0 /\ &0 <= b`,
6530   REWRITE_TAC[REAL_ARITH `a > b <=> --a < --b`] THEN
6531   REWRITE_TAC[GSYM DOT_LNEG; BOUNDED_HALFSPACE_LT] THEN
6532   REWRITE_TAC[VECTOR_NEG_EQ_0; REAL_ARITH `--b <= &0 <=> &0 <= b`]);;
6533
6534 (* ------------------------------------------------------------------------- *)
6535 (* Equality of continuous functions on closure and related results.          *)
6536 (* ------------------------------------------------------------------------- *)
6537
6538 let FORALL_IN_CLOSURE = prove
6539  (`!f:real^M->real^N s t.
6540         closed t /\ f continuous_on (closure s) /\
6541         (!x. x IN s ==> f x IN t)
6542         ==> (!x. x IN closure s ==> f x IN t)`,
6543   REWRITE_TAC[SET_RULE `(!x. x IN s ==> f x IN t) <=>
6544                         s SUBSET {x | x IN s /\ f x IN t}`] THEN
6545   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_MINIMAL THEN
6546   ASM_REWRITE_TAC[CLOSED_CLOSURE] THEN CONJ_TAC THENL
6547    [MP_TAC(ISPEC `s:real^M->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[];
6548     MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE THEN
6549     ASM_REWRITE_TAC[CLOSED_CLOSURE]]);;
6550
6551 let CONTINUOUS_LE_ON_CLOSURE = prove
6552  (`!f:real^M->real s a.
6553         (lift o f) continuous_on closure(s) /\ (!x. x IN s ==> f(x) <= a)
6554         ==> !x. x IN closure(s) ==> f(x) <= a`,
6555   let lemma = prove
6556    (`x IN s ==> f x <= a <=> x IN s ==> (lift o f) x IN {y | y$1 <= a}`,
6557     REWRITE_TAC[IN_ELIM_THM; o_THM; GSYM drop; LIFT_DROP]) in
6558   REWRITE_TAC[lemma] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
6559   MATCH_MP_TAC FORALL_IN_CLOSURE THEN
6560   ASM_REWRITE_TAC[ETA_AX; CLOSED_HALFSPACE_COMPONENT_LE]);;
6561
6562 let CONTINUOUS_GE_ON_CLOSURE = prove
6563  (`!f:real^M->real s a.
6564         (lift o f) continuous_on closure(s) /\ (!x. x IN s ==> a <= f(x))
6565         ==> !x. x IN closure(s) ==> a <= f(x)`,
6566   let lemma = prove
6567    (`x IN s ==> a <= f x <=> x IN s ==> (lift o f) x IN {y | y$1 >= a}`,
6568     REWRITE_TAC[IN_ELIM_THM; o_THM; GSYM drop; real_ge; LIFT_DROP]) in
6569   REWRITE_TAC[lemma] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
6570   MATCH_MP_TAC FORALL_IN_CLOSURE THEN
6571   ASM_REWRITE_TAC[ETA_AX; CLOSED_HALFSPACE_COMPONENT_GE]);;
6572
6573 let CONTINUOUS_CONSTANT_ON_CLOSURE = prove
6574  (`!f:real^M->real^N s a.
6575         f continuous_on closure(s) /\ (!x. x IN s ==> f(x) = a)
6576         ==> !x. x IN closure(s) ==> f(x) = a`,
6577   REWRITE_TAC[SET_RULE
6578    `x IN s ==> f x = a <=> x IN s ==> f x IN {a}`] THEN
6579   REPEAT GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC FORALL_IN_CLOSURE THEN
6580   ASM_REWRITE_TAC[CLOSED_SING]);;
6581
6582 let CONTINUOUS_AGREE_ON_CLOSURE = prove
6583  (`!g h:real^M->real^N.
6584         g continuous_on closure s /\ h continuous_on closure s /\
6585         (!x. x IN s ==> g x = h x)
6586         ==> !x. x IN closure s ==> g x = h x`,
6587   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN STRIP_TAC THEN
6588   MATCH_MP_TAC CONTINUOUS_CONSTANT_ON_CLOSURE THEN
6589   ASM_SIMP_TAC[CONTINUOUS_ON_SUB]);;
6590
6591 let CONTINUOUS_CLOSED_IN_PREIMAGE_CONSTANT = prove
6592  (`!f:real^M->real^N s a.
6593         f continuous_on s
6594         ==> closed_in (subtopology euclidean s) {x | x IN s /\ f x = a}`,
6595   REPEAT STRIP_TAC THEN
6596   ONCE_REWRITE_TAC[SET_RULE
6597    `{x | x IN s /\ f(x) = a} = {x | x IN s /\ f(x) IN {a}}`] THEN
6598   MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
6599   ASM_REWRITE_TAC[CLOSED_SING]);;
6600
6601 let CONTINUOUS_CLOSED_PREIMAGE_CONSTANT = prove
6602  (`!f:real^M->real^N s.
6603       f continuous_on s /\ closed s ==> closed {x | x IN s /\ f(x) = a}`,
6604   REPEAT STRIP_TAC THEN
6605   ASM_CASES_TAC `{x | x IN s /\ (f:real^M->real^N)(x) = a} = {}` THEN
6606   ASM_REWRITE_TAC[CLOSED_EMPTY] THEN ONCE_REWRITE_TAC[SET_RULE
6607    `{x | x IN s /\ f(x) = a} = {x | x IN s /\ f(x) IN {a}}`] THEN
6608   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE THEN
6609   ASM_REWRITE_TAC[CLOSED_SING] THEN ASM SET_TAC[]);;
6610
6611 (* ------------------------------------------------------------------------- *)
6612 (* Theorems relating continuity and uniform continuity to closures.          *)
6613 (* ------------------------------------------------------------------------- *)
6614
6615 let CONTINUOUS_ON_CLOSURE = prove
6616  (`!f:real^M->real^N s.
6617         f continuous_on closure s <=>
6618         !x e. x IN closure s /\ &0 < e
6619               ==> ?d. &0 < d /\
6620                       !y. y IN s /\ dist(y,x) < d ==> dist(f y,f x) < e`,
6621   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_on] THEN
6622   EQ_TAC THENL [MESON_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET]; ALL_TAC] THEN
6623   DISCH_TAC THEN X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
6624   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
6625   FIRST_ASSUM(MP_TAC o SPECL [`x:real^M`; `e / &2`]) THEN
6626   ANTS_TAC THENL [ASM_REWRITE_TAC[REAL_HALF]; ALL_TAC] THEN
6627   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
6628   EXISTS_TAC `d / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
6629   X_GEN_TAC `y:real^M` THEN STRIP_TAC THEN
6630   FIRST_X_ASSUM(MP_TAC o SPECL [`y:real^M`; `e / &2`]) THEN
6631   ASM_REWRITE_TAC[REAL_HALF] THEN
6632   DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN
6633   MP_TAC(ISPECL [`y:real^M`; `s:real^M->bool`] CLOSURE_APPROACHABLE) THEN
6634   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `min k (d / &2)`) THEN
6635   ASM_REWRITE_TAC[REAL_HALF; REAL_LT_MIN] THEN
6636   ASM_MESON_TAC[DIST_SYM; NORM_ARITH
6637     `dist(a,b) < e / &2 /\ dist(b,c) < e / &2 ==> dist(a,c) < e`]);;
6638
6639 let CONTINUOUS_ON_CLOSURE_SEQUENTIALLY = prove
6640  (`!f:real^M->real^N s.
6641         f continuous_on closure s <=>
6642         !x a. a IN closure s /\ (!n. x n IN s) /\ (x --> a) sequentially
6643               ==> ((f o x) --> f a) sequentially`,
6644   REWRITE_TAC[CONTINUOUS_ON_CLOSURE] THEN
6645   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
6646   REWRITE_TAC[IMP_IMP; GSYM continuous_within] THEN
6647   REWRITE_TAC[CONTINUOUS_WITHIN_SEQUENTIALLY] THEN MESON_TAC[]);;
6648
6649 let UNIFORMLY_CONTINUOUS_ON_CLOSURE = prove
6650  (`!f:real^M->real^N s.
6651         f uniformly_continuous_on s /\ f continuous_on closure s
6652         ==> f uniformly_continuous_on closure s`,
6653   REPEAT GEN_TAC THEN
6654   REWRITE_TAC[uniformly_continuous_on] THEN STRIP_TAC THEN
6655   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
6656   FIRST_X_ASSUM(MP_TAC o SPEC `e / &3`) THEN
6657   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
6658   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
6659   EXISTS_TAC `d / &3` THEN CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
6660   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^M`] THEN STRIP_TAC THEN
6661   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [continuous_on]) THEN
6662   DISCH_THEN(fun th ->
6663     MP_TAC(SPEC `y:real^M` th) THEN MP_TAC(SPEC `x:real^M` th)) THEN
6664   ASM_REWRITE_TAC[] THEN
6665   DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
6666   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
6667   DISCH_THEN(X_CHOOSE_THEN `d1:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6668   MP_TAC(ISPECL [`x:real^M`; `s:real^M->bool`] CLOSURE_APPROACHABLE) THEN
6669   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `min d1 (d / &3)`) THEN
6670   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[REAL_LT_MIN]] THEN
6671   DISCH_THEN(X_CHOOSE_THEN `x':real^M` STRIP_ASSUME_TAC) THEN
6672   DISCH_THEN(MP_TAC o SPEC `x':real^M`) THEN
6673   ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN DISCH_TAC THEN
6674   DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
6675   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
6676   DISCH_THEN(X_CHOOSE_THEN `d2:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
6677   MP_TAC(ISPECL [`y:real^M`; `s:real^M->bool`] CLOSURE_APPROACHABLE) THEN
6678   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `min d2 (d / &3)`) THEN
6679   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[REAL_LT_MIN]] THEN
6680   DISCH_THEN(X_CHOOSE_THEN `y':real^M` STRIP_ASSUME_TAC) THEN
6681   DISCH_THEN(MP_TAC o SPEC `y':real^M`) THEN
6682   ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN DISCH_TAC THEN
6683   FIRST_X_ASSUM(MP_TAC o SPECL [`x':real^M`; `y':real^M`]) THEN
6684   ASM_MESON_TAC[DIST_SYM; NORM_ARITH
6685    `dist(y,x) < d / &3 /\ dist(x',x) < d / &3 /\ dist(y',y) < d / &3
6686     ==> dist(y',x') < d`]);;
6687
6688 (* ------------------------------------------------------------------------- *)
6689 (* Continuity properties for square roots. We get other forms of this        *)
6690 (* later (transcendentals.ml and realanalysis.ml) but it's nice to have      *)
6691 (* them around earlier.                                                      *)
6692 (* ------------------------------------------------------------------------- *)
6693
6694 let CONTINUOUS_AT_SQRT = prove
6695  (`!a s. &0 < drop a ==>  (lift o sqrt o drop) continuous (at a)`,
6696   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_at; o_THM; DIST_LIFT] THEN
6697   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
6698   EXISTS_TAC `min (drop a) (e * sqrt(drop a))` THEN
6699   ASM_SIMP_TAC[REAL_LT_MIN; SQRT_POS_LT; REAL_LT_MUL; DIST_REAL] THEN
6700   X_GEN_TAC `b:real^1` THEN REWRITE_TAC[GSYM drop] THEN STRIP_TAC THEN
6701   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REAL_ARITH
6702    `abs(b - a) < a ==> &0 < b`)) THEN
6703   SUBGOAL_THEN
6704    `sqrt(drop b) - sqrt(drop a) =
6705     (drop b - drop a) / (sqrt(drop a) + sqrt(drop b))`
6706   SUBST1_TAC THENL
6707    [MATCH_MP_TAC(REAL_FIELD
6708      `sa pow 2 = a /\ sb pow 2 = b /\ &0 < sa /\ &0 < sb
6709       ==> sb - sa = (b - a) / (sa + sb)`) THEN
6710     ASM_SIMP_TAC[SQRT_POS_LT; SQRT_POW_2; REAL_LT_IMP_LE];
6711     ASM_SIMP_TAC[REAL_ABS_DIV; SQRT_POS_LT; REAL_LT_ADD; REAL_LT_LDIV_EQ;
6712                  REAL_ARITH `&0 < x ==> abs x = x`] THEN
6713     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
6714         REAL_LTE_TRANS)) THEN
6715     ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_LE_ADDR; SQRT_POS_LE;
6716                  REAL_LT_IMP_LE]]);;
6717
6718 let CONTINUOUS_WITHIN_LIFT_SQRT = prove
6719  (`!a s. (!x. x IN s ==> &0 <= drop x)
6720          ==> (lift o sqrt o drop) continuous (at a within s)`,
6721   REPEAT STRIP_TAC THEN
6722   REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC
6723    (REAL_ARITH `drop a < &0 \/ drop a = &0 \/ &0 < drop a`)
6724   THENL
6725    [MATCH_MP_TAC CONTINUOUS_WITHIN_SUBSET THEN
6726     EXISTS_TAC `{x | &0 <= drop x}` THEN
6727     ASM_SIMP_TAC[SUBSET; IN_ELIM_THM] THEN
6728     MATCH_MP_TAC CONTINUOUS_WITHIN_CLOSED_NONTRIVIAL THEN
6729     ASM_REWRITE_TAC[IN_ELIM_THM; REAL_NOT_LE] THEN
6730     REWRITE_TAC[drop; REWRITE_RULE[real_ge] CLOSED_HALFSPACE_COMPONENT_GE];
6731     RULE_ASSUM_TAC(REWRITE_RULE[GSYM LIFT_EQ; LIFT_DROP; LIFT_NUM]) THEN
6732     ASM_REWRITE_TAC[continuous_within; o_THM; DROP_VEC; SQRT_0; LIFT_NUM] THEN
6733     REWRITE_TAC[DIST_0; NORM_LIFT; NORM_REAL; GSYM drop] THEN
6734     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
6735     EXISTS_TAC `(e:real) pow 2` THEN ASM_SIMP_TAC[REAL_POW_LT] THEN
6736     X_GEN_TAC `x:real^1` THEN STRIP_TAC THEN
6737     ASM_SIMP_TAC[real_abs; SQRT_POS_LE] THEN
6738     SUBGOAL_THEN `e = sqrt(e pow 2)` SUBST1_TAC THENL
6739      [ASM_SIMP_TAC[POW_2_SQRT; REAL_LT_IMP_LE];
6740       MATCH_MP_TAC SQRT_MONO_LT THEN ASM_SIMP_TAC[] THEN ASM_REAL_ARITH_TAC];
6741     MATCH_MP_TAC CONTINUOUS_AT_WITHIN THEN
6742     MATCH_MP_TAC CONTINUOUS_AT_SQRT THEN ASM_REWRITE_TAC[]]);;
6743
6744 let CONTINUOUS_WITHIN_SQRT_COMPOSE = prove
6745  (`!f s a:real^N.
6746         (\x. lift(f x)) continuous (at a within s) /\
6747         (&0 < f a \/ !x. x IN s ==> &0 <= f x)
6748         ==> (\x. lift(sqrt(f x))) continuous (at a within s)`,
6749   REPEAT GEN_TAC THEN
6750   SUBGOAL_THEN
6751    `(\x:real^N. lift(sqrt(f x))) = (lift o sqrt o drop) o (lift o f)`
6752   SUBST1_TAC THENL [REWRITE_TAC[o_DEF; LIFT_DROP]; ALL_TAC] THEN
6753   REPEAT STRIP_TAC THEN
6754   (MATCH_MP_TAC CONTINUOUS_WITHIN_COMPOSE THEN
6755    CONJ_TAC THENL [ASM_REWRITE_TAC[o_DEF]; ALL_TAC])
6756   THENL
6757    [MATCH_MP_TAC CONTINUOUS_AT_WITHIN THEN
6758     MATCH_MP_TAC CONTINUOUS_AT_SQRT THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP];
6759     MATCH_MP_TAC CONTINUOUS_WITHIN_LIFT_SQRT THEN
6760     ASM_REWRITE_TAC[FORALL_IN_IMAGE; o_DEF; LIFT_DROP]]);;
6761
6762 let CONTINUOUS_AT_SQRT_COMPOSE = prove
6763  (`!f a:real^N.
6764         (\x. lift(f x)) continuous (at a) /\ (&0 < f a \/ !x. &0 <= f x)
6765         ==> (\x. lift(sqrt(f x))) continuous (at a)`,
6766   REPEAT GEN_TAC THEN
6767   MP_TAC(ISPECL [`f:real^N->real`; `(:real^N)`; `a:real^N`]
6768         CONTINUOUS_WITHIN_SQRT_COMPOSE) THEN
6769   REWRITE_TAC[WITHIN_UNIV; IN_UNIV]);;
6770
6771 let CONTINUOUS_ON_LIFT_SQRT = prove
6772  (`!s. (!x. x IN s ==> &0 <= drop x)
6773        ==> (lift o sqrt o drop) continuous_on s`,
6774   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_WITHIN_LIFT_SQRT]);;
6775
6776 let CONTINUOUS_ON_LIFT_SQRT_COMPOSE = prove
6777  (`!f:real^N->real s.
6778         (lift o f) continuous_on s /\ (!x. x IN s ==> &0 <= f x)
6779         ==> (\x. lift(sqrt(f x))) continuous_on s`,
6780   REPEAT STRIP_TAC THEN
6781   SUBGOAL_THEN
6782    `(\x:real^N. lift(sqrt(f x))) = (lift o sqrt o drop) o (lift o f)`
6783   SUBST1_TAC THENL
6784    [REWRITE_TAC[o_DEF; LIFT_DROP];
6785     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN
6786     MATCH_MP_TAC CONTINUOUS_ON_LIFT_SQRT THEN
6787     ASM_REWRITE_TAC[FORALL_IN_IMAGE; o_THM; LIFT_DROP]]);;
6788
6789 (* ------------------------------------------------------------------------- *)
6790 (* Cauchy continuity, and the extension of functions to closures.            *)
6791 (* ------------------------------------------------------------------------- *)
6792
6793 let UNIFORMLY_CONTINUOUS_IMP_CAUCHY_CONTINUOUS = prove
6794  (`!f:real^M->real^N s.
6795         f uniformly_continuous_on s
6796         ==> (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))`,
6797   REPEAT GEN_TAC THEN REWRITE_TAC[uniformly_continuous_on; cauchy; o_DEF] THEN
6798   MESON_TAC[]);;
6799
6800 let CONTINUOUS_CLOSED_IMP_CAUCHY_CONTINUOUS = prove
6801  (`!f:real^M->real^N s.
6802         f continuous_on s /\ closed s
6803         ==> (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))`,
6804   REWRITE_TAC[GSYM COMPLETE_EQ_CLOSED; CONTINUOUS_ON_SEQUENTIALLY] THEN
6805   REWRITE_TAC[complete] THEN MESON_TAC[CONVERGENT_IMP_CAUCHY]);;
6806
6807 let CAUCHY_CONTINUOUS_UNIQUENESS_LEMMA = prove
6808  (`!f:real^M->real^N s.
6809         (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))
6810         ==> !a x. (!n. (x n) IN s) /\ (x --> a) sequentially
6811                   ==> ?l. ((f o x) --> l) sequentially /\
6812                           !y. (!n. (y n) IN s) /\ (y --> a) sequentially
6813                               ==> ((f o y) --> l) sequentially`,
6814   REPEAT STRIP_TAC THEN
6815   FIRST_ASSUM(MP_TAC o SPEC `x:num->real^M`) THEN
6816   ANTS_TAC THENL [ASM_MESON_TAC[CONVERGENT_IMP_CAUCHY]; ALL_TAC] THEN
6817   REWRITE_TAC[GSYM CONVERGENT_EQ_CAUCHY] THEN MATCH_MP_TAC MONO_EXISTS THEN
6818   X_GEN_TAC `l:real^N` THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
6819   X_GEN_TAC `y:num->real^M` THEN STRIP_TAC THEN
6820   FIRST_ASSUM(MP_TAC o SPEC `y:num->real^M`) THEN
6821   ANTS_TAC THENL [ASM_MESON_TAC[CONVERGENT_IMP_CAUCHY]; ALL_TAC] THEN
6822   REWRITE_TAC[GSYM CONVERGENT_EQ_CAUCHY] THEN
6823   DISCH_THEN(X_CHOOSE_THEN `m:real^N` STRIP_ASSUME_TAC) THEN
6824   SUBGOAL_THEN `l:real^N = m` (fun th -> ASM_REWRITE_TAC[th]) THEN
6825   ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
6826   MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
6827   EXISTS_TAC `\n:num. (f:real^M->real^N)(x n) - f(y n)` THEN
6828   RULE_ASSUM_TAC(REWRITE_RULE[o_DEF]) THEN
6829   ASM_SIMP_TAC[LIM_SUB; TRIVIAL_LIMIT_SEQUENTIALLY] THEN
6830   FIRST_X_ASSUM(MP_TAC o SPEC
6831    `\n. if EVEN n then x(n DIV 2):real^M else y(n DIV 2)`) THEN
6832   REWRITE_TAC[cauchy; o_THM; LIM_SEQUENTIALLY] THEN ANTS_TAC THENL
6833    [CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
6834     X_GEN_TAC `e:real` THEN DISCH_TAC THEN MAP_EVERY UNDISCH_TAC
6835      [`((y:num->real^M) --> a) sequentially`;
6836       `((x:num->real^M) --> a) sequentially`] THEN
6837     REPEAT(FIRST_X_ASSUM(K ALL_TAC o check (is_forall o concl))) THEN
6838     REWRITE_TAC[LIM_SEQUENTIALLY] THEN
6839     DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
6840     DISCH_THEN(X_CHOOSE_TAC `N1:num`) THEN
6841     DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
6842     DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN
6843     EXISTS_TAC `2 * (N1 + N2)` THEN
6844     MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
6845     REPEAT(FIRST_X_ASSUM(fun th ->
6846       MP_TAC(SPEC `m DIV 2` th) THEN MP_TAC(SPEC `n DIV 2` th))) THEN
6847     REPEAT(ANTS_TAC THENL [ASM_ARITH_TAC; DISCH_TAC]) THEN
6848     REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
6849     REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_NOT_LE])) THEN
6850     CONV_TAC NORM_ARITH;
6851     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
6852     ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
6853     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN DISCH_TAC THEN
6854     X_GEN_TAC `n:num` THEN DISCH_TAC THEN
6855     FIRST_X_ASSUM(MP_TAC o SPECL [`2 * n`; `2 * n + 1`]) THEN
6856     ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
6857     REWRITE_TAC[EVEN_ADD; EVEN_MULT; ARITH_EVEN] THEN
6858     REWRITE_TAC[ARITH_RULE `(2 * n) DIV 2 = n /\ (2 * n + 1) DIV 2 = n`] THEN
6859     REWRITE_TAC[dist; VECTOR_SUB_RZERO]]);;
6860
6861 let CAUCHY_CONTINUOUS_EXTENDS_TO_CLOSURE = prove
6862  (`!f:real^M->real^N s.
6863         (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))
6864         ==> ?g. g continuous_on closure s /\ (!x. x IN s ==> g x = f x)`,
6865   REPEAT STRIP_TAC THEN
6866   SUBGOAL_THEN
6867    `!a:real^M. ?x.
6868        a IN closure s ==> (!n. x n IN s) /\ (x --> a) sequentially`
6869   MP_TAC THENL [MESON_TAC[CLOSURE_SEQUENTIAL]; ALL_TAC] THEN
6870   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
6871   X_GEN_TAC `X:real^M->num->real^M` THEN DISCH_TAC THEN
6872   FIRST_ASSUM(MP_TAC o MATCH_MP CAUCHY_CONTINUOUS_UNIQUENESS_LEMMA) THEN
6873   DISCH_THEN(MP_TAC o GEN `a:real^M` o
6874    SPECL [`a:real^M`; `(X:real^M->num->real^M) a`]) THEN
6875   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
6876    `(!a. P a ==> Q a) ==> ((!a. P a ==> R a) ==> p)
6877     ==> ((!a. Q a ==> R a) ==> p)`)) THEN
6878   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
6879   REWRITE_TAC[SKOLEM_THM] THEN
6880   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^M->real^N` THEN
6881   STRIP_TAC THEN
6882   MATCH_MP_TAC(TAUT `b /\ (b ==> a) ==> a /\ b`) THEN CONJ_TAC THENL
6883    [X_GEN_TAC `a:real^M` THEN DISCH_TAC THEN
6884     FIRST_X_ASSUM(MP_TAC o SPEC `a:real^M`) THEN
6885     ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN
6886     DISCH_THEN(MP_TAC o SPEC `(\n. a):num->real^M` o CONJUNCT2) THEN
6887     ASM_SIMP_TAC[LIM_CONST_EQ; o_DEF; TRIVIAL_LIMIT_SEQUENTIALLY];
6888     STRIP_TAC] THEN
6889   ASM_SIMP_TAC[CONTINUOUS_ON_CLOSURE_SEQUENTIALLY] THEN
6890   MAP_EVERY X_GEN_TAC [`x:num->real^M`; `a:real^M`] THEN STRIP_TAC THEN
6891   MATCH_MP_TAC LIM_TRANSFORM_EVENTUALLY THEN
6892   EXISTS_TAC `(f:real^M->real^N) o (x:num->real^M)` THEN ASM_SIMP_TAC[] THEN
6893   MATCH_MP_TAC ALWAYS_EVENTUALLY THEN ASM_SIMP_TAC[o_THM]);;
6894
6895 let UNIFORMLY_CONTINUOUS_EXTENDS_TO_CLOSURE = prove
6896  (`!f:real^M->real^N s.
6897    f uniformly_continuous_on s
6898    ==> ?g. g uniformly_continuous_on closure s /\ (!x. x IN s ==> g x = f x) /\
6899            !h. h continuous_on closure s /\ (!x. x IN s ==> h x = f x)
6900                ==> !x. x IN closure s ==> h x = g x`,
6901   REPEAT STRIP_TAC THEN
6902   FIRST_ASSUM(MP_TAC o MATCH_MP CAUCHY_CONTINUOUS_EXTENDS_TO_CLOSURE o
6903    MATCH_MP UNIFORMLY_CONTINUOUS_IMP_CAUCHY_CONTINUOUS) THEN
6904   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^M->real^N` THEN
6905   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
6906    [ASM_MESON_TAC[UNIFORMLY_CONTINUOUS_ON_CLOSURE; UNIFORMLY_CONTINUOUS_ON_EQ];
6907     ASM_MESON_TAC[CONTINUOUS_AGREE_ON_CLOSURE]]);;
6908
6909 let CAUCHY_CONTINUOUS_IMP_CONTINUOUS = prove
6910  (`!f:real^M->real^N s.
6911         (!x. cauchy x /\ (!n. (x n) IN s) ==> cauchy(f o x))
6912         ==> f continuous_on s`,
6913   REPEAT STRIP_TAC THEN
6914   FIRST_ASSUM(CHOOSE_TAC o MATCH_MP CAUCHY_CONTINUOUS_EXTENDS_TO_CLOSURE) THEN
6915   ASM_MESON_TAC[CONTINUOUS_ON_SUBSET; CLOSURE_SUBSET; CONTINUOUS_ON_EQ]);;
6916
6917 (* ------------------------------------------------------------------------- *)
6918 (* Linear functions are (uniformly) continuous on any set.                   *)
6919 (* ------------------------------------------------------------------------- *)
6920
6921 let LINEAR_LIM_0 = prove
6922  (`!f. linear f ==> (f --> vec 0) (at (vec 0))`,
6923   REPEAT STRIP_TAC THEN REWRITE_TAC[LIM_AT] THEN
6924   FIRST_X_ASSUM(MP_TAC o MATCH_MP LINEAR_BOUNDED_POS) THEN
6925   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
6926   X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `e / B` THEN
6927   ASM_SIMP_TAC[REAL_LT_DIV] THEN REWRITE_TAC[dist; VECTOR_SUB_RZERO] THEN
6928   ASM_MESON_TAC[REAL_MUL_SYM; REAL_LET_TRANS; REAL_LT_RDIV_EQ]);;
6929
6930 let LINEAR_CONTINUOUS_AT = prove
6931  (`!f:real^M->real^N a. linear f ==> f continuous (at a)`,
6932   REPEAT STRIP_TAC THEN
6933   MP_TAC(ISPEC `\x. (f:real^M->real^N) (a + x) - f(a)` LINEAR_LIM_0) THEN
6934   ANTS_TAC THENL
6935    [POP_ASSUM MP_TAC THEN SIMP_TAC[linear] THEN
6936     REPEAT STRIP_TAC THEN VECTOR_ARITH_TAC;
6937     ALL_TAC] THEN
6938   REWRITE_TAC[GSYM LIM_NULL; CONTINUOUS_AT] THEN
6939   GEN_REWRITE_TAC RAND_CONV [LIM_AT_ZERO] THEN SIMP_TAC[]);;
6940
6941 let LINEAR_CONTINUOUS_WITHIN = prove
6942  (`!f:real^M->real^N s x. linear f ==> f continuous (at x within s)`,
6943   SIMP_TAC[CONTINUOUS_AT_WITHIN; LINEAR_CONTINUOUS_AT]);;
6944
6945 let LINEAR_CONTINUOUS_ON = prove
6946  (`!f:real^M->real^N s. linear f ==> f continuous_on s`,
6947   MESON_TAC[LINEAR_CONTINUOUS_AT; CONTINUOUS_AT_IMP_CONTINUOUS_ON]);;
6948
6949 let LINEAR_CONTINUOUS_COMPOSE = prove
6950  (`!net f:A->real^N g:real^N->real^P.
6951         f continuous net /\ linear g ==> (\x. g(f x)) continuous net`,
6952   REWRITE_TAC[continuous; LIM_LINEAR]);;
6953
6954 let LINEAR_CONTINUOUS_ON_COMPOSE = prove
6955  (`!f:real^M->real^N g:real^N->real^P s.
6956         f continuous_on s /\ linear g ==> (\x. g(f x)) continuous_on s`,
6957   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
6958            LINEAR_CONTINUOUS_COMPOSE]);;
6959
6960 let CONTINUOUS_LIFT_COMPONENT_COMPOSE = prove
6961  (`!net f:A->real^N i. f continuous net ==> (\x. lift(f x$i)) continuous net`,
6962   REPEAT GEN_TAC THEN
6963   SUBGOAL_THEN `linear(\x:real^N. lift (x$i))` MP_TAC THENL
6964    [REWRITE_TAC[LINEAR_LIFT_COMPONENT]; REWRITE_TAC[GSYM IMP_CONJ_ALT]] THEN
6965   REWRITE_TAC[LINEAR_CONTINUOUS_COMPOSE]);;
6966
6967 let CONTINUOUS_ON_LIFT_COMPONENT_COMPOSE = prove
6968  (`!f:real^M->real^N s.
6969         f continuous_on s
6970         ==> (\x. lift (f x$i)) continuous_on s`,
6971   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
6972            CONTINUOUS_LIFT_COMPONENT_COMPOSE]);;
6973
6974 (* ------------------------------------------------------------------------- *)
6975 (* Also bilinear functions, in composition form.                             *)
6976 (* ------------------------------------------------------------------------- *)
6977
6978 let BILINEAR_CONTINUOUS_COMPOSE = prove
6979  (`!net f:A->real^M g:A->real^N h:real^M->real^N->real^P.
6980         f continuous net /\ g continuous net /\ bilinear h
6981         ==> (\x. h (f x) (g x)) continuous net`,
6982   REWRITE_TAC[continuous; LIM_BILINEAR]);;
6983
6984 let BILINEAR_CONTINUOUS_ON_COMPOSE = prove
6985  (`!f g h s. f continuous_on s /\ g continuous_on s /\ bilinear h
6986              ==> (\x. h (f x) (g x)) continuous_on s`,
6987   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN;
6988            BILINEAR_CONTINUOUS_COMPOSE]);;
6989
6990 let BILINEAR_DOT = prove
6991  (`bilinear (\x y:real^N. lift(x dot y))`,
6992   REWRITE_TAC[bilinear; linear; DOT_LADD; DOT_RADD; DOT_LMUL; DOT_RMUL] THEN
6993   REWRITE_TAC[LIFT_ADD; LIFT_CMUL]);;
6994
6995 let CONTINUOUS_LIFT_DOT2 = prove
6996  (`!net f g:A->real^N.
6997         f continuous net /\ g continuous net
6998         ==> (\x. lift(f x dot g x)) continuous net`,
6999   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP (MATCH_MP (REWRITE_RULE
7000    [TAUT `p /\ q /\ r ==> s <=> r ==> p /\ q ==> s`]
7001   BILINEAR_CONTINUOUS_COMPOSE) BILINEAR_DOT)) THEN REWRITE_TAC[]);;
7002
7003 let CONTINUOUS_ON_LIFT_DOT2 = prove
7004  (`!f:real^M->real^N g s.
7005         f continuous_on s /\ g continuous_on s
7006         ==> (\x. lift(f x dot g x)) continuous_on s`,
7007   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP (MATCH_MP (REWRITE_RULE
7008    [TAUT `p /\ q /\ r ==> s <=> r ==> p /\ q ==> s`]
7009   BILINEAR_CONTINUOUS_ON_COMPOSE) BILINEAR_DOT)) THEN REWRITE_TAC[]);;
7010
7011 (* ------------------------------------------------------------------------- *)
7012 (* Occasionally useful invariance properties.                                *)
7013 (* ------------------------------------------------------------------------- *)
7014
7015 let CONTINUOUS_AT_COMPOSE_EQ = prove
7016  (`!f:real^M->real^N g:real^M->real^M h:real^M->real^M.
7017         g continuous at x /\ h continuous at (g x) /\
7018         (!y. g(h y) = y) /\ h(g x) = x
7019         ==> (f continuous at (g x) <=> (\x. f(g x)) continuous at x)`,
7020   REPEAT STRIP_TAC THEN EQ_TAC THEN
7021   ASM_SIMP_TAC[REWRITE_RULE[o_DEF] CONTINUOUS_AT_COMPOSE] THEN
7022   DISCH_TAC THEN
7023   SUBGOAL_THEN
7024    `((f:real^M->real^N) o (g:real^M->real^M) o (h:real^M->real^M))
7025      continuous at (g(x:real^M))`
7026   MP_TAC THENL
7027    [REWRITE_TAC[o_ASSOC] THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN
7028     ASM_REWRITE_TAC[o_DEF];
7029
7030     ASM_REWRITE_TAC[o_DEF; ETA_AX]]);;
7031
7032 let CONTINUOUS_AT_TRANSLATION = prove
7033  (`!a z f:real^M->real^N.
7034       f continuous at (a + z) <=> (\x. f(a + x)) continuous at z`,
7035   REPEAT GEN_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE_EQ THEN
7036   EXISTS_TAC `\x:real^M. x - a` THEN
7037   SIMP_TAC[CONTINUOUS_ADD; CONTINUOUS_SUB;
7038            CONTINUOUS_AT_ID; CONTINUOUS_CONST] THEN
7039   VECTOR_ARITH_TAC);;
7040
7041 add_translation_invariants [CONTINUOUS_AT_TRANSLATION];;
7042
7043 let CONTINUOUS_AT_LINEAR_IMAGE = prove
7044  (`!h:real^M->real^M z f:real^M->real^N.
7045         linear h /\ (!x. norm(h x) = norm x)
7046         ==> (f continuous at (h z) <=> (\x. f(h x)) continuous at z)`,
7047   REPEAT GEN_TAC THEN DISCH_TAC THEN
7048   FIRST_ASSUM(ASSUME_TAC o GEN_REWRITE_RULE I
7049    [GSYM ORTHOGONAL_TRANSFORMATION]) THEN
7050   FIRST_ASSUM(X_CHOOSE_TAC `g:real^M->real^M` o MATCH_MP
7051     ORTHOGONAL_TRANSFORMATION_INVERSE) THEN
7052   MATCH_MP_TAC CONTINUOUS_AT_COMPOSE_EQ THEN
7053   EXISTS_TAC `g:real^M->real^M` THEN
7054   RULE_ASSUM_TAC(REWRITE_RULE[ORTHOGONAL_TRANSFORMATION]) THEN
7055   ASM_SIMP_TAC[LINEAR_CONTINUOUS_AT]);;
7056
7057 add_linear_invariants [CONTINUOUS_AT_LINEAR_IMAGE];;
7058
7059 (* ------------------------------------------------------------------------- *)
7060 (* Interior of an injective image.                                           *)
7061 (* ------------------------------------------------------------------------- *)
7062
7063 let INTERIOR_IMAGE_SUBSET = prove
7064  (`!f:real^M->real^N s.
7065        (!x. f continuous at x) /\ (!x y. f x = f y ==> x = y)
7066        ==> interior(IMAGE f s) SUBSET IMAGE f (interior s)`,
7067   REPEAT STRIP_TAC THEN REWRITE_TAC[SUBSET] THEN
7068   REWRITE_TAC[interior; IN_ELIM_THM] THEN
7069   X_GEN_TAC `y:real^N` THEN
7070   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
7071   REWRITE_TAC[IN_IMAGE; IN_ELIM_THM] THEN
7072   SUBGOAL_THEN `y IN IMAGE (f:real^M->real^N) s` MP_TAC THENL
7073    [ASM SET_TAC[]; ALL_TAC] THEN
7074   REWRITE_TAC[IN_IMAGE] THEN
7075   MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN
7076   ASM_REWRITE_TAC[IN_ELIM_THM] THEN FIRST_X_ASSUM SUBST_ALL_TAC THEN
7077   EXISTS_TAC `{x | (f:real^M->real^N)(x) IN t}` THEN
7078   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN CONJ_TAC THENL
7079    [MATCH_MP_TAC CONTINUOUS_OPEN_PREIMAGE_UNIV THEN ASM_MESON_TAC[];
7080     ASM SET_TAC[]]);;
7081
7082 (* ------------------------------------------------------------------------- *)
7083 (* Making a continuous function avoid some value in a neighbourhood.         *)
7084 (* ------------------------------------------------------------------------- *)
7085
7086 let CONTINUOUS_WITHIN_AVOID = prove
7087  (`!f:real^M->real^N x s a.
7088         f continuous (at x within s) /\ x IN s /\  ~(f x = a)
7089         ==> ?e. &0 < e /\ !y. y IN s /\ dist(x,y) < e ==> ~(f y = a)`,
7090   REPEAT STRIP_TAC THEN
7091   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [continuous_within]) THEN
7092   DISCH_THEN(MP_TAC o SPEC `norm((f:real^M->real^N) x - a)`) THEN
7093   ASM_REWRITE_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
7094   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_AND THEN
7095   REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN
7096   GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN SIMP_TAC[] THEN NORM_ARITH_TAC);;
7097
7098 let CONTINUOUS_AT_AVOID = prove
7099  (`!f:real^M->real^N x a.
7100         f continuous (at x) /\ ~(f x = a)
7101         ==> ?e. &0 < e /\ !y. dist(x,y) < e ==> ~(f y = a)`,
7102   MP_TAC CONTINUOUS_WITHIN_AVOID THEN
7103   REPLICATE_TAC 2 (MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
7104   DISCH_THEN(MP_TAC o SPEC `(:real^M)`) THEN
7105   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
7106   REWRITE_TAC[WITHIN_UNIV; IN_UNIV]);;
7107
7108 let CONTINUOUS_ON_AVOID = prove
7109  (`!f:real^M->real^N x s a.
7110         f continuous_on s /\ x IN s /\ ~(f x = a)
7111         ==> ?e. &0 < e /\ !y. y IN s /\ dist(x,y) < e ==> ~(f y = a)`,
7112   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
7113   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_WITHIN_AVOID THEN
7114   ASM_SIMP_TAC[]);;
7115
7116 let CONTINUOUS_ON_OPEN_AVOID = prove
7117  (`!f:real^M->real^N x s a.
7118         f continuous_on s /\ open s /\ x IN s /\ ~(f x = a)
7119         ==> ?e. &0 < e /\ !y. dist(x,y) < e ==> ~(f y = a)`,
7120   REPEAT GEN_TAC THEN ASM_CASES_TAC `open(s:real^M->bool)` THEN
7121   ASM_SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT] THEN
7122   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_AVOID THEN
7123   ASM_SIMP_TAC[]);;
7124
7125 (* ------------------------------------------------------------------------- *)
7126 (* Proving a function is constant by proving open-ness of level set.         *)
7127 (* ------------------------------------------------------------------------- *)
7128
7129 let CONTINUOUS_LEVELSET_OPEN_IN_CASES = prove
7130  (`!f:real^M->real^N s a.
7131         connected s /\
7132         f continuous_on s /\
7133         open_in (subtopology euclidean s) {x | x IN s /\ f x = a}
7134         ==> (!x. x IN s ==> ~(f x = a)) \/ (!x. x IN s ==> f x = a)`,
7135   REWRITE_TAC[SET_RULE `(!x. x IN s ==> ~(f x = a)) <=>
7136                         {x | x IN s /\ f x = a} = {}`;
7137               SET_RULE `(!x. x IN s ==> f x = a) <=>
7138                         {x | x IN s /\ f x = a} = s`] THEN
7139   REWRITE_TAC[CONNECTED_CLOPEN] THEN REPEAT STRIP_TAC THEN
7140   FIRST_X_ASSUM MATCH_MP_TAC THEN
7141   ASM_SIMP_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE_CONSTANT]);;
7142
7143 let CONTINUOUS_LEVELSET_OPEN_IN = prove
7144  (`!f:real^M->real^N s a.
7145         connected s /\
7146         f continuous_on s /\
7147         open_in (subtopology euclidean s) {x | x IN s /\ f x = a} /\
7148         (?x. x IN s /\ f x = a)
7149         ==> (!x. x IN s ==> f x = a)`,
7150   MESON_TAC[CONTINUOUS_LEVELSET_OPEN_IN_CASES]);;
7151
7152 let CONTINUOUS_LEVELSET_OPEN = prove
7153  (`!f:real^M->real^N s a.
7154         connected s /\
7155         f continuous_on s /\
7156         open {x | x IN s /\ f x = a} /\
7157         (?x. x IN s /\ f x = a)
7158         ==> (!x. x IN s ==> f x = a)`,
7159   REPEAT GEN_TAC THEN DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
7160   MATCH_MP_TAC CONTINUOUS_LEVELSET_OPEN_IN THEN
7161   ASM_REWRITE_TAC[OPEN_IN_OPEN] THEN
7162   EXISTS_TAC `{x | x IN s /\ (f:real^M->real^N) x = a}` THEN
7163   ASM_REWRITE_TAC[] THEN SET_TAC[]);;
7164
7165 (* ------------------------------------------------------------------------- *)
7166 (* Some arithmetical combinations (more to prove).                           *)
7167 (* ------------------------------------------------------------------------- *)
7168
7169 let OPEN_SCALING = prove
7170  (`!s:real^N->bool c. ~(c = &0) /\ open s ==> open(IMAGE (\x. c % x) s)`,
7171   REPEAT GEN_TAC THEN REWRITE_TAC[open_def; FORALL_IN_IMAGE] THEN
7172   STRIP_TAC THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
7173   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
7174   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
7175   EXISTS_TAC `e * abs(c)` THEN ASM_SIMP_TAC[REAL_LT_MUL; GSYM REAL_ABS_NZ] THEN
7176   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_IMAGE] THEN
7177   EXISTS_TAC `inv(c) % y:real^N` THEN
7178   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; VECTOR_MUL_LID] THEN
7179   FIRST_X_ASSUM MATCH_MP_TAC THEN
7180   SUBGOAL_THEN `x = inv(c) % c % x:real^N` SUBST1_TAC THENL
7181    [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID];
7182     REWRITE_TAC[dist; GSYM VECTOR_SUB_LDISTRIB; NORM_MUL] THEN
7183     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[REAL_ABS_INV] THEN
7184     ASM_SIMP_TAC[GSYM real_div; REAL_LT_LDIV_EQ; GSYM REAL_ABS_NZ] THEN
7185     ASM_REWRITE_TAC[GSYM dist]]);;
7186
7187 let OPEN_NEGATIONS = prove
7188  (`!s:real^N->bool. open s ==> open (IMAGE (--) s)`,
7189   SUBGOAL_THEN `(--) = \x:real^N. --(&1) % x`
7190    (fun th -> SIMP_TAC[th; OPEN_SCALING; REAL_ARITH `~(--(&1) = &0)`]) THEN
7191   REWRITE_TAC[FUN_EQ_THM] THEN VECTOR_ARITH_TAC);;
7192
7193 let OPEN_TRANSLATION = prove
7194  (`!s a:real^N. open s ==> open(IMAGE (\x. a + x) s)`,
7195   REPEAT STRIP_TAC THEN
7196   MP_TAC(ISPECL [`\x:real^N. x - a`; `s:real^N->bool`]
7197          CONTINUOUS_OPEN_PREIMAGE_UNIV) THEN
7198   ASM_SIMP_TAC[CONTINUOUS_SUB; CONTINUOUS_AT_ID; CONTINUOUS_CONST] THEN
7199   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
7200   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; IN_UNIV] THEN
7201   ASM_MESON_TAC[VECTOR_ARITH `(a + x) - a = x:real^N`;
7202                 VECTOR_ARITH `a + (x - a) = x:real^N`]);;
7203
7204 let OPEN_TRANSLATION_EQ = prove
7205  (`!a s. open (IMAGE (\x:real^N. a + x) s) <=> open s`,
7206   REWRITE_TAC[open_def] THEN GEOM_TRANSLATE_TAC[]);;
7207
7208 add_translation_invariants [OPEN_TRANSLATION_EQ];;
7209
7210 let OPEN_AFFINITY = prove
7211  (`!s a:real^N c.
7212         open s /\ ~(c = &0) ==> open (IMAGE (\x. a + c % x) s)`,
7213   REPEAT STRIP_TAC THEN
7214   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
7215   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
7216   ASM_SIMP_TAC[IMAGE_o; OPEN_TRANSLATION; OPEN_SCALING]);;
7217
7218 let INTERIOR_TRANSLATION = prove
7219  (`!a:real^N s.
7220     interior (IMAGE (\x. a + x) s) = IMAGE (\x. a + x) (interior s)`,
7221   REWRITE_TAC[interior] THEN GEOM_TRANSLATE_TAC[]);;
7222
7223 add_translation_invariants [INTERIOR_TRANSLATION];;
7224
7225 let OPEN_SUMS = prove
7226  (`!s t:real^N->bool.
7227         open s \/ open t ==> open {x + y | x IN s /\ y IN t}`,
7228   REPEAT GEN_TAC THEN REWRITE_TAC[open_def] THEN STRIP_TAC THEN
7229   REWRITE_TAC[FORALL_IN_GSPEC] THEN
7230   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THENL
7231    [FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`);
7232     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`)] THEN
7233   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN
7234   X_GEN_TAC `e:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
7235   X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN
7236   ASM_MESON_TAC[VECTOR_ADD_SYM; VECTOR_ARITH `(z - y) + y:real^N = z`;
7237                 NORM_ARITH `dist(z:real^N,x + y) < e ==> dist(z - y,x) < e`]);;
7238
7239 (* ------------------------------------------------------------------------- *)
7240 (* Preservation of compactness and connectedness under continuous function.  *)
7241 (* ------------------------------------------------------------------------- *)
7242
7243 let COMPACT_CONTINUOUS_IMAGE = prove
7244  (`!f:real^M->real^N s.
7245         f continuous_on s /\ compact s ==> compact(IMAGE f s)`,
7246   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_on; compact] THEN
7247   STRIP_TAC THEN X_GEN_TAC `y:num->real^N` THEN
7248   REWRITE_TAC[IN_IMAGE; SKOLEM_THM; FORALL_AND_THM] THEN
7249   DISCH_THEN(X_CHOOSE_THEN `x:num->real^M` STRIP_ASSUME_TAC) THEN
7250   FIRST_X_ASSUM(MP_TAC o SPEC `x:num->real^M`) THEN ASM_REWRITE_TAC[] THEN
7251   ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
7252   X_GEN_TAC `r:num->num` THEN
7253   DISCH_THEN(X_CHOOSE_THEN `l:real^M` STRIP_ASSUME_TAC) THEN
7254   EXISTS_TAC `(f:real^M->real^N) l` THEN ASM_REWRITE_TAC[] THEN
7255   CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
7256   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
7257   FIRST_X_ASSUM(MP_TAC o SPEC `l:real^M`) THEN
7258   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
7259   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
7260   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
7261   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
7262   DISCH_THEN(MP_TAC o SPEC `d:real`) THEN ASM_REWRITE_TAC[o_THM] THEN
7263   ASM_MESON_TAC[]);;
7264
7265 let COMPACT_CONTINUOUS_IMAGE_EQ = prove
7266  (`!f:real^M->real^N s.
7267         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
7268         ==> (f continuous_on s <=>
7269              !t. compact t /\ t SUBSET s ==> compact(IMAGE f t))`,
7270   REPEAT STRIP_TAC THEN EQ_TAC THENL
7271    [MESON_TAC[COMPACT_CONTINUOUS_IMAGE; CONTINUOUS_ON_SUBSET]; DISCH_TAC] THEN
7272   FIRST_X_ASSUM(X_CHOOSE_TAC `g:real^N->real^M` o
7273     GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
7274   REWRITE_TAC[CONTINUOUS_ON_CLOSED] THEN
7275   X_GEN_TAC `u:real^N->bool` THEN DISCH_TAC THEN
7276   MP_TAC(ISPECL [`g:real^N->real^M`; `IMAGE (f:real^M->real^N) s`;
7277                  `s:real^M->bool`] PROPER_MAP) THEN
7278   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7279   MATCH_MP_TAC(TAUT `(q ==> s) /\ p ==> (p <=> q /\ r) ==> s`) THEN
7280   REPEAT STRIP_TAC THENL
7281    [SUBGOAL_THEN
7282      `{x | x IN s /\ (f:real^M->real^N) x IN u} = IMAGE g u`
7283      (fun th -> ASM_MESON_TAC[th]);
7284     SUBGOAL_THEN
7285      `{x | x IN IMAGE f s /\ (g:real^N->real^M) x IN k} = IMAGE f k`
7286      (fun th -> ASM_SIMP_TAC[th])] THEN
7287   FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN ASM SET_TAC[]);;
7288
7289 let COMPACT_LINEAR_IMAGE = prove
7290  (`!f:real^M->real^N s. compact s /\ linear f ==> compact(IMAGE f s)`,
7291   SIMP_TAC[LINEAR_CONTINUOUS_ON; COMPACT_CONTINUOUS_IMAGE]);;
7292
7293 let COMPACT_LINEAR_IMAGE_EQ = prove
7294  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
7295          ==> (compact (IMAGE f s) <=> compact s)`,
7296   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE COMPACT_LINEAR_IMAGE));;
7297
7298 add_linear_invariants [COMPACT_LINEAR_IMAGE_EQ];;
7299
7300 let CONNECTED_CONTINUOUS_IMAGE = prove
7301  (`!f:real^M->real^N s.
7302         f continuous_on s /\ connected s ==> connected(IMAGE f s)`,
7303   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_ON_OPEN] THEN
7304   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
7305   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
7306   REWRITE_TAC[CONNECTED_CLOPEN; NOT_FORALL_THM; NOT_IMP; DE_MORGAN_THM] THEN
7307   REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
7308   DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
7309   FIRST_X_ASSUM(fun th -> MP_TAC(SPEC `t:real^N->bool` th) THEN
7310     MP_TAC(SPEC `IMAGE (f:real^M->real^N) s DIFF t` th)) THEN
7311   ASM_REWRITE_TAC[] THEN
7312   SUBGOAL_THEN `{x | x IN s /\ (f:real^M->real^N) x IN IMAGE f s DIFF t} =
7313                 s DIFF {x | x IN s /\ f x IN t}`
7314   SUBST1_TAC THENL
7315    [UNDISCH_TAC `t SUBSET IMAGE (f:real^M->real^N) s` THEN
7316     REWRITE_TAC[EXTENSION; IN_IMAGE; IN_DIFF; IN_ELIM_THM; SUBSET] THEN
7317     MESON_TAC[];
7318     REPEAT STRIP_TAC THEN
7319     EXISTS_TAC `{x | x IN s /\ (f:real^M->real^N) x IN t}` THEN
7320     ASM_REWRITE_TAC[] THEN POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN
7321     REWRITE_TAC[IN_IMAGE; SUBSET; IN_ELIM_THM; NOT_IN_EMPTY; EXTENSION] THEN
7322     MESON_TAC[]]);;
7323
7324 let CONNECTED_TRANSLATION = prove
7325  (`!a s. connected s ==> connected (IMAGE (\x:real^N. a + x) s)`,
7326   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN
7327   ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST]);;
7328
7329 let CONNECTED_TRANSLATION_EQ = prove
7330  (`!a s. connected (IMAGE (\x:real^N. a + x) s) <=> connected s`,
7331   REWRITE_TAC[connected] THEN GEOM_TRANSLATE_TAC[]);;
7332
7333 add_translation_invariants [CONNECTED_TRANSLATION_EQ];;
7334
7335 let CONNECTED_LINEAR_IMAGE = prove
7336  (`!f:real^M->real^N s. connected s /\ linear f ==> connected(IMAGE f s)`,
7337   SIMP_TAC[LINEAR_CONTINUOUS_ON; CONNECTED_CONTINUOUS_IMAGE]);;
7338
7339 let CONNECTED_LINEAR_IMAGE_EQ = prove
7340  (`!f s. linear f /\ (!x y. f x = f y ==> x = y)
7341          ==> (connected (IMAGE f s) <=> connected s)`,
7342   MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE CONNECTED_LINEAR_IMAGE));;
7343
7344 add_linear_invariants [CONNECTED_LINEAR_IMAGE_EQ];;
7345
7346 let BOUNDED_UNIFORMLY_CONTINUOUS_IMAGE = prove
7347  (`!f:real^M->real^N s.
7348         f uniformly_continuous_on s /\ bounded s ==> bounded(IMAGE f s)`,
7349   REPEAT STRIP_TAC THEN FIRST_ASSUM
7350    (MP_TAC o MATCH_MP UNIFORMLY_CONTINUOUS_EXTENDS_TO_CLOSURE) THEN
7351   DISCH_THEN(X_CHOOSE_THEN `g:real^M->real^N` STRIP_ASSUME_TAC) THEN
7352   MATCH_MP_TAC BOUNDED_SUBSET THEN
7353   EXISTS_TAC `IMAGE (g:real^M->real^N) (closure s)` THEN CONJ_TAC THENL
7354    [ASM_MESON_TAC[COMPACT_CLOSURE; UNIFORMLY_CONTINUOUS_IMP_CONTINUOUS;
7355                   COMPACT_IMP_BOUNDED; COMPACT_CONTINUOUS_IMAGE];
7356     MP_TAC(ISPEC `s:real^M->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[]]);;
7357
7358 (* ------------------------------------------------------------------------- *)
7359 (* Connected components, considered as a "connectedness" relation or a set.  *)
7360 (* ------------------------------------------------------------------------- *)
7361
7362 let connected_component = new_definition
7363  `connected_component s x y <=>
7364         ?t. connected t /\ t SUBSET s /\ x IN t /\ y IN t`;;
7365
7366 let CONNECTED_COMPONENT_IN = prove
7367  (`!s x y. connected_component s x y ==> x IN s /\ y IN s`,
7368   REWRITE_TAC[connected_component] THEN SET_TAC[]);;
7369
7370 let CONNECTED_COMPONENT_REFL = prove
7371  (`!s x:real^N. x IN s ==> connected_component s x x`,
7372   REWRITE_TAC[connected_component] THEN REPEAT STRIP_TAC THEN
7373   EXISTS_TAC `{x:real^N}` THEN REWRITE_TAC[CONNECTED_SING] THEN
7374   ASM SET_TAC[]);;
7375
7376 let CONNECTED_COMPONENT_REFL_EQ = prove
7377  (`!s x:real^N. connected_component s x x <=> x IN s`,
7378   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[CONNECTED_COMPONENT_REFL] THEN
7379   REWRITE_TAC[connected_component] THEN SET_TAC[]);;
7380
7381 let CONNECTED_COMPONENT_SYM = prove
7382  (`!s x y:real^N. connected_component s x y ==> connected_component s y x`,
7383   REWRITE_TAC[connected_component] THEN MESON_TAC[]);;
7384
7385 let CONNECTED_COMPONENT_TRANS = prove
7386  (`!s x y:real^N.
7387     connected_component s x y /\ connected_component s y z
7388     ==> connected_component s x z`,
7389   REPEAT GEN_TAC THEN REWRITE_TAC[connected_component] THEN
7390   DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `t:real^N->bool`)
7391                              (X_CHOOSE_TAC `u:real^N->bool`)) THEN
7392   EXISTS_TAC `t UNION u:real^N->bool` THEN
7393   ASM_REWRITE_TAC[IN_UNION; UNION_SUBSET] THEN
7394   MATCH_MP_TAC CONNECTED_UNION THEN ASM SET_TAC[]);;
7395
7396 let CONNECTED_COMPONENT_OF_SUBSET = prove
7397  (`!s t x. s SUBSET t /\ connected_component s x y
7398            ==> connected_component t x y`,
7399   REWRITE_TAC[connected_component] THEN SET_TAC[]);;
7400
7401 let CONNECTED_COMPONENT_SET = prove
7402  (`!s x. connected_component s x =
7403             { y | ?t. connected t /\ t SUBSET s /\ x IN t /\ y IN t}`,
7404   REWRITE_TAC[IN_ELIM_THM; EXTENSION] THEN
7405   REWRITE_TAC[IN; connected_component] THEN MESON_TAC[]);;
7406
7407 let CONNECTED_COMPONENT_UNIONS = prove
7408  (`!s x. connected_component s x =
7409                 UNIONS {t | connected t /\ x IN t /\ t SUBSET s}`,
7410   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]);;
7411
7412 let CONNECTED_COMPONENT_SUBSET = prove
7413  (`!s x. (connected_component s x) SUBSET s`,
7414   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]);;
7415
7416 let CONNECTED_CONNECTED_COMPONENT_SET = prove
7417  (`!s. connected s <=> !x:real^N. x IN s ==> connected_component s x = s`,
7418   GEN_TAC THEN REWRITE_TAC[CONNECTED_COMPONENT_UNIONS] THEN EQ_TAC THENL
7419    [SET_TAC[]; ALL_TAC] THEN
7420   ASM_CASES_TAC `s:real^N->bool = {}` THEN
7421   ASM_REWRITE_TAC[CONNECTED_EMPTY] THEN
7422   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
7423   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
7424   DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN ASM_REWRITE_TAC[] THEN
7425   DISCH_THEN(SUBST1_TAC o SYM) THEN MATCH_MP_TAC CONNECTED_UNIONS THEN
7426   ASM SET_TAC[]);;
7427
7428 let CONNECTED_COMPONENT_EQ_SELF = prove
7429  (`!s x. connected s /\ x IN s ==> connected_component s x = s`,
7430   MESON_TAC[CONNECTED_CONNECTED_COMPONENT_SET]);;
7431
7432 let CONNECTED_IFF_CONNECTED_COMPONENT = prove
7433  (`!s. connected s <=>
7434           !x y. x IN s /\ y IN s ==> connected_component s x y`,
7435   REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT_SET] THEN
7436   REWRITE_TAC[EXTENSION] THEN MESON_TAC[IN; CONNECTED_COMPONENT_IN]);;
7437
7438 let CONNECTED_COMPONENT_MAXIMAL = prove
7439  (`!s t x:real^N.
7440         x IN t /\ connected t /\ t SUBSET s
7441         ==> t SUBSET (connected_component s x)`,
7442   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]);;
7443
7444 let CONNECTED_COMPONENT_MONO = prove
7445  (`!s t x. s SUBSET t
7446            ==> (connected_component s x) SUBSET (connected_component t x)`,
7447   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]);;
7448
7449 let CONNECTED_CONNECTED_COMPONENT = prove
7450  (`!s x. connected(connected_component s x)`,
7451   REWRITE_TAC[CONNECTED_COMPONENT_UNIONS] THEN
7452   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_UNIONS THEN SET_TAC[]);;
7453
7454 let CONNECTED_COMPONENT_EQ_EMPTY = prove
7455  (`!s x:real^N. connected_component s x = {} <=> ~(x IN s)`,
7456   REPEAT GEN_TAC THEN EQ_TAC THENL
7457    [REWRITE_TAC[EXTENSION; NOT_IN_EMPTY] THEN
7458     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
7459     REWRITE_TAC[IN; CONNECTED_COMPONENT_REFL_EQ];
7460     REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SET_TAC[]]);;
7461
7462 let CONNECTED_COMPONENT_EMPTY = prove
7463  (`!x. connected_component {} x = {}`,
7464   REWRITE_TAC[CONNECTED_COMPONENT_EQ_EMPTY; NOT_IN_EMPTY]);;
7465
7466 let CONNECTED_COMPONENT_EQ = prove
7467  (`!s x y. y IN connected_component s x
7468            ==> (connected_component s y = connected_component s x)`,
7469   REWRITE_TAC[EXTENSION; IN] THEN
7470   MESON_TAC[CONNECTED_COMPONENT_SYM; CONNECTED_COMPONENT_TRANS]);;
7471
7472 let CLOSED_CONNECTED_COMPONENT = prove
7473  (`!s x:real^N. closed s ==> closed(connected_component s x)`,
7474   REPEAT STRIP_TAC THEN
7475   ASM_CASES_TAC `(x:real^N) IN s` THENL
7476    [ALL_TAC; ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY; CLOSED_EMPTY]] THEN
7477   REWRITE_TAC[GSYM CLOSURE_EQ] THEN
7478   MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[CLOSURE_SUBSET] THEN
7479   MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
7480   SIMP_TAC[CONNECTED_CLOSURE; CONNECTED_CONNECTED_COMPONENT] THEN
7481   CONJ_TAC THENL
7482    [MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN
7483     ASM_REWRITE_TAC[IN; CONNECTED_COMPONENT_REFL_EQ];
7484     MATCH_MP_TAC CLOSURE_MINIMAL THEN
7485     ASM_REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]]);;
7486
7487 let CONNECTED_COMPONENT_DISJOINT = prove
7488  (`!s a b. DISJOINT (connected_component s a) (connected_component s b) <=>
7489              ~(a IN connected_component s b)`,
7490   REWRITE_TAC[DISJOINT; EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN
7491   REWRITE_TAC[IN] THEN
7492   MESON_TAC[CONNECTED_COMPONENT_SYM; CONNECTED_COMPONENT_TRANS]);;
7493
7494 let CONNECTED_COMPONENT_NONOVERLAP = prove
7495  (`!s a b:real^N.
7496         (connected_component s a) INTER (connected_component s b) = {} <=>
7497         ~(a IN s) \/ ~(b IN s) \/
7498         ~(connected_component s a = connected_component s b)`,
7499   REPEAT GEN_TAC THEN
7500   ASM_CASES_TAC `(a:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
7501   RULE_ASSUM_TAC(REWRITE_RULE[GSYM CONNECTED_COMPONENT_EQ_EMPTY]) THEN
7502   ASM_REWRITE_TAC[INTER_EMPTY] THEN
7503   ASM_CASES_TAC `(b:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
7504   RULE_ASSUM_TAC(REWRITE_RULE[GSYM CONNECTED_COMPONENT_EQ_EMPTY]) THEN
7505   ASM_REWRITE_TAC[INTER_EMPTY] THEN ASM_CASES_TAC
7506    `connected_component s (a:real^N) = connected_component s b` THEN
7507   ASM_REWRITE_TAC[INTER_IDEMPOT; CONNECTED_COMPONENT_EQ_EMPTY] THEN
7508   FIRST_X_ASSUM(MP_TAC o check(is_neg o concl)) THEN
7509   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
7510   REWRITE_TAC[] THEN MATCH_MP_TAC CONNECTED_COMPONENT_EQ THEN
7511   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [GSYM DISJOINT]) THEN
7512   REWRITE_TAC[CONNECTED_COMPONENT_DISJOINT]);;
7513
7514 let CONNECTED_COMPONENT_OVERLAP = prove
7515  (`!s a b:real^N.
7516         ~((connected_component s a) INTER (connected_component s b) = {}) <=>
7517         a IN s /\ b IN s /\
7518         connected_component s a = connected_component s b`,
7519   REWRITE_TAC[CONNECTED_COMPONENT_NONOVERLAP; DE_MORGAN_THM]);;
7520
7521 let CONNECTED_COMPONENT_SYM_EQ = prove
7522  (`!s x y. connected_component s x y <=> connected_component s y x`,
7523   MESON_TAC[CONNECTED_COMPONENT_SYM]);;
7524
7525 let CONNECTED_COMPONENT_EQ_EQ = prove
7526  (`!s x y:real^N.
7527         connected_component s x = connected_component s y <=>
7528            ~(x IN s) /\ ~(y IN s) \/
7529            x IN s /\ y IN s /\ connected_component s x y`,
7530   REPEAT GEN_TAC THEN ASM_CASES_TAC `(y:real^N) IN s` THENL
7531    [ASM_CASES_TAC `(x:real^N) IN s` THEN ASM_REWRITE_TAC[] THENL
7532      [REWRITE_TAC[FUN_EQ_THM] THEN
7533       ASM_MESON_TAC[CONNECTED_COMPONENT_TRANS; CONNECTED_COMPONENT_REFL;
7534                     CONNECTED_COMPONENT_SYM];
7535       ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY]];
7536     RULE_ASSUM_TAC(REWRITE_RULE[GSYM CONNECTED_COMPONENT_EQ_EMPTY]) THEN
7537     ASM_REWRITE_TAC[CONNECTED_COMPONENT_EQ_EMPTY] THEN
7538     ONCE_REWRITE_TAC[CONNECTED_COMPONENT_SYM_EQ] THEN
7539     ASM_REWRITE_TAC[EMPTY] THEN ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY]]);;
7540
7541 let CONNECTED_EQ_CONNECTED_COMPONENT_EQ = prove
7542  (`!s. connected s <=>
7543        !x y. x IN s /\ y IN s
7544              ==> connected_component s x = connected_component s y`,
7545   SIMP_TAC[CONNECTED_COMPONENT_EQ_EQ] THEN
7546   REWRITE_TAC[CONNECTED_IFF_CONNECTED_COMPONENT]);;
7547
7548 let CONNECTED_COMPONENT_IDEMP = prove
7549  (`!s x:real^N. connected_component (connected_component s x) x =
7550                 connected_component s x`,
7551   REWRITE_TAC[FUN_EQ_THM; connected_component] THEN
7552   REPEAT GEN_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN EQ_TAC THEN
7553   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
7554   ASM_MESON_TAC[CONNECTED_COMPONENT_MAXIMAL; SUBSET_TRANS;
7555                 CONNECTED_COMPONENT_SUBSET]);;
7556
7557 let CONNECTED_COMPONENT_UNIQUE = prove
7558  (`!s c x:real^N.
7559         x IN c /\ c SUBSET s /\ connected c /\
7560         (!c'. x IN c' /\ c' SUBSET s /\ connected c'
7561               ==> c' SUBSET c)
7562         ==> connected_component s x = c`,
7563   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
7564    [FIRST_X_ASSUM MATCH_MP_TAC THEN
7565     REWRITE_TAC[CONNECTED_COMPONENT_SUBSET; CONNECTED_CONNECTED_COMPONENT] THEN
7566     REWRITE_TAC[IN] THEN ASM_REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ] THEN
7567     ASM SET_TAC[];
7568     MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[]]);;
7569
7570 let JOINABLE_CONNECTED_COMPONENT_EQ = prove
7571  (`!s t x y:real^N.
7572         connected t /\ t SUBSET s /\
7573         ~(connected_component s x INTER t = {}) /\
7574         ~(connected_component s y INTER t = {})
7575         ==> connected_component s x = connected_component s y`,
7576   REPEAT GEN_TAC THEN
7577   REPLICATE_TAC 2 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
7578   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN DISCH_THEN(CONJUNCTS_THEN2
7579    (X_CHOOSE_THEN `w:real^N` STRIP_ASSUME_TAC)
7580    (X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC)) THEN
7581   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_COMPONENT_EQ THEN
7582   REWRITE_TAC[IN] THEN
7583   MATCH_MP_TAC CONNECTED_COMPONENT_TRANS THEN
7584   EXISTS_TAC `z:real^N` THEN CONJ_TAC THENL [ASM_MESON_TAC[IN]; ALL_TAC] THEN
7585   MATCH_MP_TAC CONNECTED_COMPONENT_TRANS THEN
7586   EXISTS_TAC `w:real^N` THEN CONJ_TAC THENL
7587    [REWRITE_TAC[connected_component] THEN
7588     EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[];
7589     ASM_MESON_TAC[IN; CONNECTED_COMPONENT_SYM]]);;
7590
7591 let CONNECTED_COMPONENT_TRANSLATION = prove
7592  (`!a s x. connected_component (IMAGE (\x. a + x) s) (a + x) =
7593                 IMAGE (\x. a + x) (connected_component s x)`,
7594   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN GEOM_TRANSLATE_TAC[]);;
7595
7596 add_translation_invariants [CONNECTED_COMPONENT_TRANSLATION];;
7597
7598 let CONNECTED_COMPONENT_LINEAR_IMAGE = prove
7599  (`!f s x. linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
7600            ==> connected_component (IMAGE f s) (f x) =
7601                IMAGE f (connected_component s x)`,
7602   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN
7603   GEOM_TRANSFORM_TAC[]);;
7604
7605 add_linear_invariants [CONNECTED_COMPONENT_LINEAR_IMAGE];;
7606
7607 let UNIONS_CONNECTED_COMPONENT = prove
7608  (`!s:real^N->bool. UNIONS {connected_component s x |x| x IN s} = s`,
7609   GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
7610   REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC; CONNECTED_COMPONENT_SUBSET] THEN
7611   REWRITE_TAC[SUBSET; UNIONS_GSPEC; IN_ELIM_THM] THEN
7612   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN EXISTS_TAC `x:real^N` THEN
7613   ASM_REWRITE_TAC[] THEN REWRITE_TAC[IN] THEN
7614   ASM_REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ]);;
7615
7616 let CLOSED_IN_CONNECTED_COMPONENT = prove
7617  (`!s x:real^N. closed_in (subtopology euclidean s) (connected_component s x)`,
7618   REPEAT GEN_TAC THEN
7619   ASM_CASES_TAC `connected_component s (x:real^N) = {}` THEN
7620   ASM_REWRITE_TAC[CLOSED_IN_EMPTY] THEN
7621   RULE_ASSUM_TAC(REWRITE_RULE[CONNECTED_COMPONENT_EQ_EMPTY]) THEN
7622   REWRITE_TAC[CLOSED_IN_CLOSED] THEN
7623   EXISTS_TAC `closure(connected_component s x):real^N->bool` THEN
7624   REWRITE_TAC[CLOSED_CLOSURE] THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
7625   REWRITE_TAC[SUBSET_INTER; CONNECTED_COMPONENT_SUBSET; CLOSURE_SUBSET] THEN
7626   MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN REWRITE_TAC[INTER_SUBSET] THEN
7627   CONJ_TAC THENL
7628    [ASM_REWRITE_TAC[IN_INTER] THEN
7629     MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN
7630     ASM_REWRITE_TAC[IN; CONNECTED_COMPONENT_REFL_EQ];
7631     MATCH_MP_TAC CONNECTED_INTERMEDIATE_CLOSURE THEN
7632     EXISTS_TAC `connected_component s (x:real^N)` THEN
7633     REWRITE_TAC[INTER_SUBSET; CONNECTED_CONNECTED_COMPONENT;
7634                 SUBSET_INTER; CONNECTED_COMPONENT_SUBSET; CLOSURE_SUBSET]]);;
7635
7636 let OPEN_IN_CONNECTED_COMPONENT = prove
7637  (`!s x:real^N.
7638         FINITE {connected_component s x |x| x IN s}
7639         ==> open_in (subtopology euclidean s) (connected_component s x)`,
7640   REPEAT STRIP_TAC THEN
7641   SUBGOAL_THEN
7642    `connected_component s (x:real^N) =
7643         s DIFF (UNIONS {connected_component s y |y| y IN s} DIFF
7644                 connected_component s x)`
7645   SUBST1_TAC THENL
7646    [REWRITE_TAC[UNIONS_CONNECTED_COMPONENT] THEN
7647     MATCH_MP_TAC(SET_RULE `t SUBSET s ==> t = s DIFF (s DIFF t)`) THEN
7648     REWRITE_TAC[CONNECTED_COMPONENT_SUBSET];
7649     MATCH_MP_TAC OPEN_IN_DIFF THEN
7650     REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_REFL; TOPSPACE_EUCLIDEAN; SUBSET_UNIV] THEN
7651     REWRITE_TAC[UNIONS_DIFF] THEN
7652     MATCH_MP_TAC CLOSED_IN_UNIONS THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
7653     ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN ASM_SIMP_TAC[FINITE_IMAGE] THEN
7654     X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
7655     SUBGOAL_THEN
7656      `connected_component s y DIFF connected_component s x =
7657       connected_component s y \/
7658       connected_component s (y:real^N) DIFF connected_component s x = {}`
7659      (DISJ_CASES_THEN SUBST1_TAC)
7660     THENL
7661      [MATCH_MP_TAC(SET_RULE
7662        `(~(s INTER t = {}) ==> s = t) ==> s DIFF t = s \/ s DIFF t = {}`) THEN
7663       SIMP_TAC[CONNECTED_COMPONENT_OVERLAP];
7664       REWRITE_TAC[CLOSED_IN_CONNECTED_COMPONENT];
7665       REWRITE_TAC[CLOSED_IN_EMPTY]]]);;
7666
7667 let CONNECTED_COMPONENT_EQUIVALENCE_RELATION = prove
7668  (`!R s:real^N->bool.
7669         (!x y. R x y ==> R y x) /\
7670         (!x y z. R x y /\ R y z ==> R x z) /\
7671         (!a. a IN s
7672              ==> ?t. open_in (subtopology euclidean s) t /\ a IN t /\
7673                      !x. x IN t ==> R a x)
7674         ==> !a b. connected_component s a b ==> R a b`,
7675   REPEAT STRIP_TAC THEN
7676   MP_TAC(ISPECL [`R:real^N->real^N->bool`; `connected_component s (a:real^N)`]
7677     CONNECTED_EQUIVALENCE_RELATION) THEN
7678   ASM_REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT] THEN ANTS_TAC THENL
7679    [X_GEN_TAC `c:real^N` THEN DISCH_TAC THEN
7680     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N`) THEN ANTS_TAC THENL
7681      [ASM_MESON_TAC[CONNECTED_COMPONENT_SUBSET; SUBSET]; ALL_TAC] THEN
7682     DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN
7683     EXISTS_TAC `t INTER connected_component s (a:real^N)` THEN
7684     ASM_SIMP_TAC[IN_INTER; OPEN_IN_OPEN] THEN
7685     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN
7686     MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN
7687     MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`]
7688         CONNECTED_COMPONENT_SUBSET) THEN
7689     SET_TAC[];
7690     DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[IN] THEN
7691     REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ] THEN
7692     ASM_MESON_TAC[CONNECTED_COMPONENT_IN]]);;
7693
7694 (* ------------------------------------------------------------------------- *)
7695 (* The set of connected components of a set.                                 *)
7696 (* ------------------------------------------------------------------------- *)
7697
7698 let components = new_definition
7699   `components s = {connected_component s x | x | x:real^N IN s}`;;
7700
7701 let COMPONENTS_TRANSLATION = prove
7702  (`!a s. components(IMAGE (\x. a + x) s) =
7703    IMAGE (IMAGE (\x. a + x)) (components s)`,
7704   REWRITE_TAC[components] THEN GEOM_TRANSLATE_TAC[] THEN SET_TAC[]);;
7705
7706 add_translation_invariants [COMPONENTS_TRANSLATION];;
7707
7708 let COMPONENTS_LINEAR_IMAGE = prove
7709  (`!f s. linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
7710            ==> components(IMAGE f s) = IMAGE (IMAGE f) (components s)`,
7711   REWRITE_TAC[components] THEN GEOM_TRANSFORM_TAC[] THEN SET_TAC[]);;
7712
7713 add_linear_invariants [COMPONENTS_LINEAR_IMAGE];;
7714
7715 let IN_COMPONENTS = prove
7716  (`!u:real^N->bool s. s IN components u
7717     <=> ?x. x IN u /\ s = connected_component u x`,
7718   REPEAT GEN_TAC THEN REWRITE_TAC[components] THEN EQ_TAC
7719   THENL [SET_TAC[];STRIP_TAC THEN ASM_SIMP_TAC[] THEN
7720   UNDISCH_TAC `x:real^N IN u` THEN SET_TAC[]]);;
7721
7722 let UNIONS_COMPONENTS = prove
7723  (`!u:real^N->bool. u = UNIONS (components u)`,
7724   REWRITE_TAC[EXTENSION] THEN REPEAT GEN_TAC THEN EQ_TAC
7725   THENL[DISCH_TAC THEN REWRITE_TAC[IN_UNIONS] THEN
7726   EXISTS_TAC `connected_component (u:real^N->bool) x` THEN CONJ_TAC THENL
7727   [REWRITE_TAC[components] THEN SET_TAC[ASSUME `x:real^N IN u`];
7728   REWRITE_TAC[CONNECTED_COMPONENT_SET] THEN SUBGOAL_THEN
7729   `?s:real^N->bool. connected s /\ s SUBSET u /\ x IN s` MP_TAC
7730   THENL[EXISTS_TAC `{x:real^N}` THEN ASM_REWRITE_TAC[CONNECTED_SING] THEN
7731   POP_ASSUM MP_TAC THEN SET_TAC[]; SET_TAC[]]];
7732   REWRITE_TAC[IN_UNIONS] THEN STRIP_TAC THEN
7733   MATCH_MP_TAC (SET_RULE `!x:real^N s u. x IN s /\ s SUBSET u ==> x IN u`) THEN
7734   EXISTS_TAC `t:real^N->bool` THEN ASM_REWRITE_TAC[] THEN STRIP_ASSUME_TAC
7735   (MESON[IN_COMPONENTS;ASSUME `t:real^N->bool IN components u`]
7736   `?y. t:real^N->bool = connected_component u y`) THEN
7737    ASM_REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]]);;
7738
7739 let PAIRWISE_DISJOINT_COMPONENTS = prove
7740  (`!u:real^N->bool. pairwise DISJOINT (components u)`,
7741   GEN_TAC THEN REWRITE_TAC[pairwise;DISJOINT] THEN
7742   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `t:real^N->bool`] THEN STRIP_TAC THEN
7743   ASSERT_TAC `(?a. s:real^N->bool = connected_component u a) /\
7744   ?b. t:real^N->bool = connected_component u b`
7745   THENL [ASM_MESON_TAC[IN_COMPONENTS];
7746   ASM_MESON_TAC[CONNECTED_COMPONENT_NONOVERLAP]]);;
7747
7748 let IN_COMPONENTS_NONEMPTY = prove
7749  (`!s c. c IN components s ==> ~(c = {})`,
7750   REPEAT GEN_TAC THEN REWRITE_TAC[components; IN_ELIM_THM] THEN
7751   STRIP_TAC THEN ASM_REWRITE_TAC[CONNECTED_COMPONENT_EQ_EMPTY]);;
7752
7753 let IN_COMPONENTS_SUBSET = prove
7754  (`!s c. c IN components s ==> c SUBSET s`,
7755   REPEAT GEN_TAC THEN REWRITE_TAC[components; IN_ELIM_THM] THEN
7756   STRIP_TAC THEN ASM_REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]);;
7757
7758 let IN_COMPONENTS_CONNECTED = prove
7759  (`!s c. c IN components s ==> connected c`,
7760   REPEAT GEN_TAC THEN REWRITE_TAC[components; IN_ELIM_THM] THEN
7761   STRIP_TAC THEN ASM_REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT]);;
7762
7763 let IN_COMPONENTS_MAXIMAL = prove
7764  (`!s c:real^N->bool.
7765         c IN components s <=>
7766         ~(c = {}) /\ c SUBSET s /\ connected c /\
7767         !c'. ~(c' = {}) /\ c SUBSET c' /\ c' SUBSET s /\ connected c'
7768              ==> c' = c`,
7769   REPEAT GEN_TAC THEN REWRITE_TAC[components; IN_ELIM_THM] THEN EQ_TAC THENL
7770    [DISCH_THEN(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
7771     ASM_REWRITE_TAC[CONNECTED_COMPONENT_EQ_EMPTY; CONNECTED_COMPONENT_SUBSET;
7772                     CONNECTED_CONNECTED_COMPONENT] THEN
7773     REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
7774     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
7775     ASM_MESON_TAC[CONNECTED_COMPONENT_REFL; IN; SUBSET];
7776     STRIP_TAC THEN
7777     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
7778     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN
7779     DISCH_TAC THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7780     MATCH_MP_TAC(GSYM CONNECTED_COMPONENT_UNIQUE) THEN
7781     ASM_REWRITE_TAC[] THEN X_GEN_TAC `c':real^N->bool` THEN STRIP_TAC THEN
7782     REWRITE_TAC[SET_RULE `c' SUBSET c <=> c' UNION c = c`] THEN
7783     FIRST_X_ASSUM MATCH_MP_TAC THEN
7784     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
7785     MATCH_MP_TAC CONNECTED_UNION THEN ASM SET_TAC[]]);;
7786
7787 let JOINABLE_COMPONENTS_EQ = prove
7788  (`!s t c1 c2.
7789         connected t /\ t SUBSET s /\
7790         c1 IN components s /\ c2 IN components s /\
7791         ~(c1 INTER t = {}) /\ ~(c2 INTER t = {})
7792         ==> c1 = c2`,
7793   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; components; FORALL_IN_GSPEC] THEN
7794   MESON_TAC[JOINABLE_CONNECTED_COMPONENT_EQ]);;
7795
7796 let CLOSED_COMPONENTS = prove
7797  (`!s c. closed s /\ c IN components s ==> closed c`,
7798   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; components; FORALL_IN_GSPEC] THEN
7799   SIMP_TAC[CLOSED_CONNECTED_COMPONENT]);;
7800
7801 let CONTINUOUS_ON_COMPONENTS_GEN = prove
7802  (`!f:real^M->real^N s.
7803         (!c. c IN components s
7804              ==> open_in (subtopology euclidean s) c /\ f continuous_on c)
7805         ==> f continuous_on s`,
7806   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_OPEN_IN_PREIMAGE_EQ] THEN
7807   DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN DISCH_TAC THEN
7808   SUBGOAL_THEN
7809    `{x | x IN s /\ (f:real^M->real^N) x IN t} =
7810     UNIONS {{x | x IN c /\ f x IN t} | c IN components s}`
7811   SUBST1_TAC THENL
7812    [CONV_TAC(LAND_CONV(SUBS_CONV
7813      [ISPEC `s:real^M->bool` UNIONS_COMPONENTS])) THEN
7814     REWRITE_TAC[UNIONS_GSPEC; IN_UNIONS] THEN SET_TAC[];
7815     MATCH_MP_TAC OPEN_IN_UNIONS THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
7816     ASM_MESON_TAC[OPEN_IN_TRANS]]);;
7817
7818 let CONTINUOUS_ON_COMPONENTS_CLOSED_GEN = prove
7819  (`!f:real^M->real^N s.
7820         FINITE(components s) /\
7821         (!c. c IN components s
7822              ==> closed_in (subtopology euclidean s) c /\ f continuous_on c)
7823         ==> f continuous_on s`,
7824   REPEAT GEN_TAC THEN REWRITE_TAC[CONTINUOUS_CLOSED_IN_PREIMAGE_EQ] THEN
7825   DISCH_TAC THEN X_GEN_TAC `t:real^N->bool` THEN DISCH_TAC THEN
7826   SUBGOAL_THEN
7827    `{x | x IN s /\ (f:real^M->real^N) x IN t} =
7828     UNIONS {{x | x IN c /\ f x IN t} | c IN components s}`
7829   SUBST1_TAC THENL
7830    [CONV_TAC(LAND_CONV(SUBS_CONV
7831      [ISPEC `s:real^M->bool` UNIONS_COMPONENTS])) THEN
7832     REWRITE_TAC[UNIONS_GSPEC; IN_UNIONS] THEN SET_TAC[];
7833     MATCH_MP_TAC CLOSED_IN_UNIONS THEN
7834     ASM_SIMP_TAC[SIMPLE_IMAGE; FINITE_IMAGE; FORALL_IN_IMAGE] THEN
7835     ASM_MESON_TAC[CLOSED_IN_TRANS]]);;
7836
7837 let CONTINUOUS_ON_COMPONENTS_CLOSED = prove
7838  (`!f:real^M->real^N s.
7839         closed s /\ FINITE(components s) /\
7840         (!c. c IN components s ==> f continuous_on c)
7841         ==> f continuous_on s`,
7842   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_COMPONENTS_CLOSED_GEN THEN
7843   ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSED_SUBSET THEN
7844   ASM_MESON_TAC[CLOSED_COMPONENTS; IN_COMPONENTS_SUBSET]);;
7845
7846 let COMPONENTS_NONOVERLAP = prove
7847  (`!s c c'. c IN components s /\ c' IN components s
7848             ==> (c INTER c' = {} <=> ~(c = c'))`,
7849   REWRITE_TAC[components; IN_ELIM_THM] THEN REPEAT STRIP_TAC THEN
7850   ASM_SIMP_TAC[CONNECTED_COMPONENT_NONOVERLAP]);;
7851
7852 let COMPONENTS_EQ = prove
7853  (`!s c c'. c IN components s /\ c' IN components s
7854             ==> (c = c' <=> ~(c INTER c' = {}))`,
7855   MESON_TAC[COMPONENTS_NONOVERLAP]);;
7856
7857 let COMPONENTS_EQ_EMPTY = prove
7858  (`!s. components s = {} <=> s = {}`,
7859   GEN_TAC THEN REWRITE_TAC[EXTENSION] THEN
7860   REWRITE_TAC[components; connected_component; IN_ELIM_THM] THEN
7861   SET_TAC[]);;
7862
7863 let CONNECTED_EQ_CONNECTED_COMPONENTS_EQ = prove
7864  (`!s. connected s <=>
7865        !c c'. c IN components s /\ c' IN components s ==> c = c'`,
7866   REWRITE_TAC[components; IN_ELIM_THM] THEN
7867   MESON_TAC[CONNECTED_EQ_CONNECTED_COMPONENT_EQ]);;
7868
7869 let COMPONENTS_EQ_SING,COMPONENTS_EQ_SING_EXISTS = (CONJ_PAIR o prove)
7870  (`(!s:real^N->bool. components s = {s} <=> connected s /\ ~(s = {})) /\
7871    (!s:real^N->bool. (?a. components s = {a}) <=> connected s /\ ~(s = {}))`,
7872   REWRITE_TAC[AND_FORALL_THM] THEN X_GEN_TAC `s:real^N->bool` THEN
7873   MATCH_MP_TAC(TAUT `(p ==> q) /\ (q ==> r) /\ (r ==> p)
7874                      ==> (p <=> r) /\ (q <=> r)`) THEN
7875   REPEAT CONJ_TAC THENL
7876    [MESON_TAC[];
7877     STRIP_TAC THEN ASM_REWRITE_TAC[CONNECTED_EQ_CONNECTED_COMPONENTS_EQ] THEN
7878     ASM_MESON_TAC[IN_SING; COMPONENTS_EQ_EMPTY; NOT_INSERT_EMPTY];
7879     STRIP_TAC THEN ONCE_REWRITE_TAC[EXTENSION] THEN
7880     REWRITE_TAC[IN_SING] THEN
7881     REWRITE_TAC[components; IN_ELIM_THM] THEN
7882     ASM_MESON_TAC[CONNECTED_CONNECTED_COMPONENT_SET; MEMBER_NOT_EMPTY]]);;
7883
7884 let IN_COMPONENTS_SELF = prove
7885  (`!s:real^N->bool. s IN components s <=> connected s /\ ~(s = {})`,
7886   GEN_TAC THEN EQ_TAC THENL
7887    [MESON_TAC[IN_COMPONENTS_NONEMPTY; IN_COMPONENTS_CONNECTED];
7888     SIMP_TAC[GSYM COMPONENTS_EQ_SING; IN_SING]]);;
7889
7890 let COMPONENTS_MAXIMAL = prove
7891  (`!s t c:real^N->bool.
7892      c IN components s /\ connected t /\ t SUBSET s /\ ~(c INTER t = {})
7893      ==> t SUBSET c`,
7894   REWRITE_TAC[IMP_CONJ; components; FORALL_IN_GSPEC] THEN
7895   REPEAT STRIP_TAC THEN
7896   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
7897   REWRITE_TAC[IN_INTER; LEFT_IMP_EXISTS_THM] THEN
7898   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
7899   FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP CONNECTED_COMPONENT_EQ) THEN
7900   MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[]);;
7901
7902 let COMPONENTS_UNIQUE = prove
7903  (`!s:real^N->bool k.
7904         UNIONS k = s /\
7905         (!c. c IN k
7906              ==> connected c /\ ~(c = {}) /\
7907                  !c'. connected c' /\ c SUBSET c' /\ c' SUBSET s ==> c' = c)
7908         ==> components s = k`,
7909   REPEAT STRIP_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
7910   X_GEN_TAC `c:real^N->bool` THEN REWRITE_TAC[IN_COMPONENTS] THEN
7911   EQ_TAC THENL
7912    [DISCH_THEN(X_CHOOSE_THEN `x:real^N`
7913      (CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC)) THEN
7914     FIRST_ASSUM(MP_TAC o SPEC `x:real^N` o GEN_REWRITE_RULE I [EXTENSION]) THEN
7915     REWRITE_TAC[IN_UNIONS] THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
7916     X_GEN_TAC `c:real^N->bool` THEN STRIP_TAC THEN
7917     SUBGOAL_THEN `connected_component s (x:real^N) = c`
7918      (fun th -> ASM_REWRITE_TAC[th]) THEN
7919     MATCH_MP_TAC CONNECTED_COMPONENT_UNIQUE THEN
7920     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN
7921     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
7922     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
7923     X_GEN_TAC `c':real^N->bool` THEN STRIP_TAC THEN
7924     REWRITE_TAC[SET_RULE `c' SUBSET c <=> c' UNION c = c`] THEN
7925     FIRST_X_ASSUM MATCH_MP_TAC THEN CONJ_TAC THENL
7926      [MATCH_MP_TAC CONNECTED_UNION; ASM SET_TAC[]] THEN
7927     ASM SET_TAC[];
7928     DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN
7929     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
7930     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
7931     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
7932     CONJ_TAC THENL [ASM SET_TAC[]; CONV_TAC SYM_CONV] THEN
7933     FIRST_X_ASSUM MATCH_MP_TAC THEN
7934     REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT; CONNECTED_COMPONENT_SUBSET] THEN
7935     MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
7936     ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;
7937
7938 let COMPONENTS_UNIQUE_EQ = prove
7939  (`!s:real^N->bool k.
7940         components s = k <=>
7941         UNIONS k = s /\
7942         (!c. c IN k
7943              ==> connected c /\ ~(c = {}) /\
7944                  !c'. connected c' /\ c SUBSET c' /\ c' SUBSET s ==> c' = c)`,
7945   REPEAT GEN_TAC THEN EQ_TAC THENL
7946    [DISCH_THEN(SUBST1_TAC o SYM); REWRITE_TAC[COMPONENTS_UNIQUE]] THEN
7947   REWRITE_TAC[GSYM UNIONS_COMPONENTS] THEN
7948   X_GEN_TAC `c:real^N->bool` THEN DISCH_TAC THEN REPEAT CONJ_TAC THENL
7949    [ASM_MESON_TAC[IN_COMPONENTS_CONNECTED];
7950     ASM_MESON_TAC[IN_COMPONENTS_NONEMPTY];
7951     RULE_ASSUM_TAC(REWRITE_RULE[IN_COMPONENTS_MAXIMAL]) THEN
7952     ASM_MESON_TAC[SUBSET_EMPTY]]);;
7953
7954 (* ------------------------------------------------------------------------- *)
7955 (* Continuity implies uniform continuity on a compact domain.                *)
7956 (* ------------------------------------------------------------------------- *)
7957
7958 let COMPACT_UNIFORMLY_EQUICONTINUOUS = prove
7959  (`!(fs:(real^M->real^N)->bool) s.
7960      (!x e. x IN s /\ &0 < e
7961             ==> ?d. &0 < d /\
7962                     (!f x'. f IN fs /\ x' IN s /\ dist (x',x) < d
7963                             ==> dist (f x',f x) < e)) /\
7964      compact s
7965      ==> !e. &0 < e
7966              ==> ?d. &0 < d /\
7967                      !f x x'. f IN fs /\ x IN s /\ x' IN s /\ dist (x',x) < d
7968                               ==> dist(f x',f x) < e`,
7969   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
7970   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
7971   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
7972   X_GEN_TAC `d:real^M->real->real` THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN
7973   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP HEINE_BOREL_LEMMA) THEN
7974   DISCH_THEN(MP_TAC o SPEC
7975     `{ ball(x:real^M,d x (e / &2)) | x IN s}`) THEN
7976   SIMP_TAC[FORALL_IN_GSPEC; OPEN_BALL; UNIONS_GSPEC; SUBSET; IN_ELIM_THM] THEN
7977   ANTS_TAC THENL [ASM_MESON_TAC[CENTRE_IN_BALL; REAL_HALF]; ALL_TAC] THEN
7978   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `k:real` THEN STRIP_TAC THEN
7979   ASM_REWRITE_TAC[] THEN
7980   MAP_EVERY X_GEN_TAC [`f:real^M->real^N`; `u:real^M`; `v:real^M`] THEN
7981   STRIP_TAC THEN FIRST_X_ASSUM(fun th -> MP_TAC(SPEC `v:real^M` th) THEN
7982     ASM_REWRITE_TAC[] THEN DISCH_THEN(CHOOSE_THEN MP_TAC)) THEN
7983   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
7984   DISCH_THEN(fun th ->
7985     MP_TAC(SPEC `u:real^M` th) THEN MP_TAC(SPEC `v:real^M` th)) THEN
7986   ASM_REWRITE_TAC[DIST_REFL] THEN
7987   FIRST_X_ASSUM(X_CHOOSE_THEN `w:real^M` (CONJUNCTS_THEN2 ASSUME_TAC
7988     SUBST_ALL_TAC)) THEN
7989   ASM_REWRITE_TAC[CENTRE_IN_BALL] THEN ASM_REWRITE_TAC[IN_BALL] THEN
7990   ONCE_REWRITE_TAC[DIST_SYM] THEN REPEAT STRIP_TAC THEN
7991   FIRST_X_ASSUM(MP_TAC o SPECL [`w:real^M`; `e / &2`]) THEN
7992   ASM_REWRITE_TAC[REAL_HALF] THEN
7993   DISCH_THEN(MP_TAC o SPEC `f:real^M->real^N` o CONJUNCT2) THEN
7994   DISCH_THEN(fun th -> MP_TAC(SPEC `u:real^M` th) THEN
7995                         MP_TAC(SPEC `v:real^M` th)) THEN
7996   ASM_REWRITE_TAC[] THEN CONV_TAC NORM_ARITH);;
7997
7998 let COMPACT_UNIFORMLY_CONTINUOUS = prove
7999  (`!f:real^M->real^N s.
8000         f continuous_on s /\ compact s ==> f uniformly_continuous_on s`,
8001   REPEAT GEN_TAC THEN REWRITE_TAC[continuous_on; uniformly_continuous_on] THEN
8002   STRIP_TAC THEN
8003   MP_TAC(ISPECL [`{f:real^M->real^N}`; `s:real^M->bool`]
8004         COMPACT_UNIFORMLY_EQUICONTINUOUS) THEN
8005   REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ; IN_SING; FORALL_UNWIND_THM2] THEN
8006   ASM_MESON_TAC[]);;
8007
8008 (* ------------------------------------------------------------------------- *)
8009 (* A uniformly convergent limit of continuous functions is continuous.       *)
8010 (* ------------------------------------------------------------------------- *)
8011
8012 let CONTINUOUS_UNIFORM_LIMIT = prove
8013  (`!net f:A->real^M->real^N g s.
8014         ~(trivial_limit net) /\
8015         eventually (\n. (f n) continuous_on s) net /\
8016         (!e. &0 < e
8017              ==> eventually (\n. !x. x IN s ==> norm(f n x - g x) < e) net)
8018         ==> g continuous_on s`,
8019   REWRITE_TAC[continuous_on] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
8020   X_GEN_TAC `x:real^M` THEN STRIP_TAC THEN
8021   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8022   FIRST_X_ASSUM(MP_TAC o SPEC `e / &3`) THEN
8023   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
8024   FIRST_X_ASSUM(fun th -> MP_TAC th THEN REWRITE_TAC[IMP_IMP] THEN
8025         GEN_REWRITE_TAC LAND_CONV [GSYM EVENTUALLY_AND]) THEN
8026   DISCH_THEN(MP_TAC o MATCH_MP EVENTUALLY_HAPPENS) THEN
8027   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `a:A` THEN
8028   DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o SPEC `x:real^M`) ASSUME_TAC) THEN
8029   ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
8030   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
8031   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN
8032   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
8033   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `y:real^M` THEN
8034   DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
8035   FIRST_X_ASSUM(fun th ->
8036    MP_TAC(SPEC `x:real^M` th) THEN MP_TAC(SPEC `y:real^M` th)) THEN
8037   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(REAL_ARITH
8038    `w <= x + y + z
8039     ==> x < e / &3 ==> y < e / &3 ==> z < e / &3 ==> w < e`) THEN
8040   REWRITE_TAC[dist] THEN
8041   SUBST1_TAC(VECTOR_ARITH
8042    `(g:real^M->real^N) y - g x =
8043     --(f (a:A) y - g y) + (f a x - g x) + (f a y - f a x)`) THEN
8044   MATCH_MP_TAC NORM_TRIANGLE_LE THEN REWRITE_TAC[NORM_NEG; REAL_LE_LADD] THEN
8045   MATCH_MP_TAC NORM_TRIANGLE_LE THEN REWRITE_TAC[NORM_NEG; REAL_LE_REFL]);;
8046
8047 (* ------------------------------------------------------------------------- *)
8048 (* Topological stuff lifted from and dropped to R                            *)
8049 (* ------------------------------------------------------------------------- *)
8050
8051 let OPEN_LIFT = prove
8052  (`!s. open(IMAGE lift s) <=>
8053         !x. x IN s ==> ?e. &0 < e /\ !x'. abs(x' - x) < e ==> x' IN s`,
8054   REWRITE_TAC[open_def; FORALL_LIFT; LIFT_IN_IMAGE_LIFT; DIST_LIFT]);;
8055
8056 let LIMPT_APPROACHABLE_LIFT = prove
8057  (`!x s. (lift x) limit_point_of (IMAGE lift s) <=>
8058          !e. &0 < e ==> ?x'. x' IN s /\ ~(x' = x) /\ abs(x' - x) < e`,
8059   REWRITE_TAC[LIMPT_APPROACHABLE; EXISTS_LIFT; LIFT_IN_IMAGE_LIFT;
8060               LIFT_EQ; DIST_LIFT]);;
8061
8062 let CLOSED_LIFT = prove
8063  (`!s. closed (IMAGE lift s) <=>
8064         !x. (!e. &0 < e ==> ?x'. x' IN s /\ ~(x' = x) /\ abs(x' - x) < e)
8065             ==> x IN s`,
8066   GEN_TAC THEN REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE] THEN
8067   ONCE_REWRITE_TAC[FORALL_LIFT] THEN
8068   REWRITE_TAC[LIMPT_APPROACHABLE_LIFT; LIFT_EQ; DIST_LIFT;
8069               EXISTS_LIFT; LIFT_IN_IMAGE_LIFT]);;
8070
8071 let CONTINUOUS_AT_LIFT_RANGE = prove
8072  (`!f x. (lift o f) continuous (at x) <=>
8073                 !e. &0 < e
8074                     ==> ?d. &0 < d /\
8075                             (!x'. norm(x' - x) < d
8076                                   ==> abs(f x' - f x) < e)`,
8077   REWRITE_TAC[continuous_at; o_THM; DIST_LIFT] THEN REWRITE_TAC[dist]);;
8078
8079 let CONTINUOUS_ON_LIFT_RANGE = prove
8080  (`!f s. (lift o f) continuous_on s <=>
8081          !x. x IN s
8082              ==> !e. &0 < e
8083                      ==> ?d. &0 < d /\
8084                              (!x'. x' IN s /\ norm(x' - x) < d
8085                                    ==> abs(f x' - f x) < e)`,
8086   REWRITE_TAC[continuous_on; o_THM; DIST_LIFT] THEN REWRITE_TAC[dist]);;
8087
8088 let CONTINUOUS_LIFT_NORM_COMPOSE = prove
8089  (`!net f:A->real^N.
8090         f continuous net
8091         ==> (\x. lift(norm(f x))) continuous net`,
8092   REPEAT GEN_TAC THEN REWRITE_TAC[continuous; tendsto] THEN
8093   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MATCH_MP_TAC MONO_IMP THEN
8094   REWRITE_TAC[] THEN
8095   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
8096   REWRITE_TAC[DIST_REAL; GSYM drop; LIFT_DROP] THEN
8097   NORM_ARITH_TAC);;
8098
8099 let CONTINUOUS_ON_LIFT_NORM_COMPOSE = prove
8100  (`!f:real^M->real^N s.
8101         f continuous_on s
8102         ==> (\x. lift(norm(f x))) continuous_on s`,
8103   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_LIFT_NORM_COMPOSE]);;
8104
8105 let CONTINUOUS_AT_LIFT_NORM = prove
8106  (`!x. (lift o norm) continuous (at x)`,
8107   REWRITE_TAC[CONTINUOUS_AT_LIFT_RANGE; NORM_LIFT] THEN
8108   MESON_TAC[REAL_ABS_SUB_NORM; REAL_LET_TRANS]);;
8109
8110 let CONTINUOUS_ON_LIFT_NORM = prove
8111  (`!s. (lift o norm) continuous_on s`,
8112   REWRITE_TAC[CONTINUOUS_ON_LIFT_RANGE; NORM_LIFT] THEN
8113   MESON_TAC[REAL_ABS_SUB_NORM; REAL_LET_TRANS]);;
8114
8115 let CONTINUOUS_AT_LIFT_COMPONENT = prove
8116  (`!i a. 1 <= i /\ i <= dimindex(:N)
8117          ==> (\x:real^N. lift(x$i)) continuous (at a)`,
8118   SIMP_TAC[continuous_at; DIST_LIFT; GSYM VECTOR_SUB_COMPONENT] THEN
8119   MESON_TAC[dist; REAL_LET_TRANS; COMPONENT_LE_NORM]);;
8120
8121 let CONTINUOUS_ON_LIFT_COMPONENT = prove
8122  (`!i s. 1 <= i /\ i <= dimindex(:N)
8123          ==> (\x:real^N. lift(x$i)) continuous_on s`,
8124   SIMP_TAC[continuous_on; DIST_LIFT; GSYM VECTOR_SUB_COMPONENT] THEN
8125   MESON_TAC[dist; REAL_LET_TRANS; COMPONENT_LE_NORM]);;
8126
8127 let CONTINUOUS_AT_LIFT_INFNORM = prove
8128  (`!x:real^N. (lift o infnorm) continuous (at x)`,
8129   REWRITE_TAC[CONTINUOUS_AT; LIM_AT; o_THM; DIST_LIFT] THEN
8130   MESON_TAC[REAL_LET_TRANS; dist; REAL_ABS_SUB_INFNORM; INFNORM_LE_NORM]);;
8131
8132 let CONTINUOUS_AT_LIFT_DIST = prove
8133  (`!a:real^N x. (lift o (\x. dist(a,x))) continuous (at x)`,
8134   REWRITE_TAC[CONTINUOUS_AT_LIFT_RANGE] THEN
8135   MESON_TAC[NORM_ARITH `abs(dist(a:real^N,x) - dist(a,y)) <= norm(x - y)`;
8136             REAL_LET_TRANS]);;
8137
8138 let CONTINUOUS_ON_LIFT_DIST = prove
8139  (`!a s. (lift o (\x. dist(a,x))) continuous_on s`,
8140   REWRITE_TAC[CONTINUOUS_ON_LIFT_RANGE] THEN
8141   MESON_TAC[NORM_ARITH `abs(dist(a:real^N,x) - dist(a,y)) <= norm(x - y)`;
8142             REAL_LET_TRANS]);;
8143
8144 (* ------------------------------------------------------------------------- *)
8145 (* Hence some handy theorems on distance, diameter etc. of/from a set.       *)
8146 (* ------------------------------------------------------------------------- *)
8147
8148 let COMPACT_ATTAINS_SUP = prove
8149  (`!s. compact (IMAGE lift s) /\ ~(s = {})
8150        ==> ?x. x IN s /\ !y. y IN s ==> y <= x`,
8151   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN REPEAT STRIP_TAC THEN
8152   MP_TAC(SPEC `s:real->bool` BOUNDED_HAS_SUP) THEN ASM_REWRITE_TAC[] THEN
8153   STRIP_TAC THEN EXISTS_TAC `sup s` THEN ASM_REWRITE_TAC[] THEN
8154   ASM_MESON_TAC[CLOSED_LIFT; REAL_ARITH `s <= s - e <=> ~(&0 < e)`;
8155                 REAL_ARITH `x <= s /\ ~(x <= s - e) ==> abs(x - s) < e`]);;
8156
8157 let COMPACT_ATTAINS_INF = prove
8158  (`!s. compact (IMAGE lift s) /\ ~(s = {})
8159        ==> ?x. x IN s /\ !y. y IN s ==> x <= y`,
8160   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN REPEAT STRIP_TAC THEN
8161   MP_TAC(SPEC `s:real->bool` BOUNDED_HAS_INF) THEN ASM_REWRITE_TAC[] THEN
8162   STRIP_TAC THEN EXISTS_TAC `inf s` THEN ASM_REWRITE_TAC[] THEN
8163   ASM_MESON_TAC[CLOSED_LIFT; REAL_ARITH `s + e <= s <=> ~(&0 < e)`;
8164                 REAL_ARITH `s <= x /\ ~(s + e <= x) ==> abs(x - s) < e`]);;
8165
8166 let CONTINUOUS_ATTAINS_SUP = prove
8167  (`!f:real^N->real s.
8168         compact s /\ ~(s = {}) /\ (lift o f) continuous_on s
8169         ==> ?x. x IN s /\ !y. y IN s ==> f(y) <= f(x)`,
8170   REPEAT STRIP_TAC THEN
8171   MP_TAC(SPEC `IMAGE (f:real^N->real) s` COMPACT_ATTAINS_SUP) THEN
8172   ASM_SIMP_TAC[GSYM IMAGE_o; COMPACT_CONTINUOUS_IMAGE; IMAGE_EQ_EMPTY] THEN
8173   MESON_TAC[IN_IMAGE]);;
8174
8175 let CONTINUOUS_ATTAINS_INF = prove
8176  (`!f:real^N->real s.
8177         compact s /\ ~(s = {}) /\ (lift o f) continuous_on s
8178         ==> ?x. x IN s /\ !y. y IN s ==> f(x) <= f(y)`,
8179   REPEAT STRIP_TAC THEN
8180   MP_TAC(SPEC `IMAGE (f:real^N->real) s` COMPACT_ATTAINS_INF) THEN
8181   ASM_SIMP_TAC[GSYM IMAGE_o; COMPACT_CONTINUOUS_IMAGE; IMAGE_EQ_EMPTY] THEN
8182   MESON_TAC[IN_IMAGE]);;
8183
8184 let DISTANCE_ATTAINS_SUP = prove
8185  (`!s a. compact s /\ ~(s = {})
8186          ==> ?x. x IN s /\ !y. y IN s ==> dist(a,y) <= dist(a,x)`,
8187   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ATTAINS_SUP THEN
8188   ASM_REWRITE_TAC[CONTINUOUS_ON_LIFT_RANGE] THEN REWRITE_TAC[dist] THEN
8189   ASM_MESON_TAC[REAL_LET_TRANS; REAL_ABS_SUB_NORM; NORM_NEG;
8190                 VECTOR_ARITH `(a - x) - (a - y) = --(x - y):real^N`]);;
8191
8192 (* ------------------------------------------------------------------------- *)
8193 (* For *minimal* distance, we only need closure, not compactness.            *)
8194 (* ------------------------------------------------------------------------- *)
8195
8196 let DISTANCE_ATTAINS_INF = prove
8197  (`!s a:real^N.
8198         closed s /\ ~(s = {})
8199         ==> ?x. x IN s /\ !y. y IN s ==> dist(a,x) <= dist(a,y)`,
8200   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
8201   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
8202   DISCH_THEN(X_CHOOSE_TAC `b:real^N`) THEN
8203   MP_TAC(ISPECL [`\x:real^N. dist(a,x)`; `cball(a:real^N,dist(b,a)) INTER s`]
8204                 CONTINUOUS_ATTAINS_INF) THEN
8205   ANTS_TAC THENL
8206    [ASM_SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_INTER; BOUNDED_INTER;
8207                  BOUNDED_CBALL; CLOSED_CBALL; GSYM MEMBER_NOT_EMPTY] THEN
8208     REWRITE_TAC[dist; CONTINUOUS_ON_LIFT_RANGE; IN_INTER; IN_CBALL] THEN
8209     ASM_MESON_TAC[REAL_LET_TRANS; REAL_ABS_SUB_NORM; NORM_NEG; REAL_LE_REFL;
8210             NORM_SUB; VECTOR_ARITH `(a - x) - (a - y) = --(x - y):real^N`];
8211     MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[IN_INTER; IN_CBALL] THEN
8212     ASM_MESON_TAC[DIST_SYM; REAL_LE_TOTAL; REAL_LE_TRANS]]);;
8213
8214 (* ------------------------------------------------------------------------- *)
8215 (* We can now extend limit compositions to consider the scalar multiplier.   *)
8216 (* ------------------------------------------------------------------------- *)
8217
8218 let LIM_MUL = prove
8219  (`!net:(A)net f l:real^N c d.
8220         ((lift o c) --> lift d) net /\ (f --> l) net
8221         ==> ((\x. c(x) % f(x)) --> (d % l)) net`,
8222   REPEAT STRIP_TAC THEN
8223   MP_TAC(ISPECL [`net:(A)net`; `\x (y:real^N). drop x % y`;
8224   `lift o (c:A->real)`; `f:A->real^N`; `lift d`; `l:real^N`] LIM_BILINEAR) THEN
8225   ASM_REWRITE_TAC[LIFT_DROP; o_THM] THEN DISCH_THEN MATCH_MP_TAC THEN
8226   REWRITE_TAC[bilinear; linear; DROP_ADD; DROP_CMUL] THEN
8227   REPEAT STRIP_TAC THEN VECTOR_ARITH_TAC);;
8228
8229 let LIM_VMUL = prove
8230  (`!net:(A)net c d v:real^N.
8231         ((lift o c) --> lift d) net ==> ((\x. c(x) % v) --> d % v) net`,
8232   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_MUL THEN ASM_REWRITE_TAC[LIM_CONST]);;
8233
8234 let CONTINUOUS_VMUL = prove
8235  (`!net c v. (lift o c) continuous net ==> (\x. c(x) % v) continuous net`,
8236   REWRITE_TAC[continuous; LIM_VMUL; o_THM]);;
8237
8238 let CONTINUOUS_MUL = prove
8239  (`!net f c. (lift o c) continuous net /\ f continuous net
8240              ==> (\x. c(x) % f(x)) continuous net`,
8241   REWRITE_TAC[continuous; LIM_MUL; o_THM]);;
8242
8243 let CONTINUOUS_ON_VMUL = prove
8244  (`!s c v. (lift o c) continuous_on s ==> (\x. c(x) % v) continuous_on s`,
8245   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
8246   SIMP_TAC[CONTINUOUS_VMUL]);;
8247
8248 let CONTINUOUS_ON_MUL = prove
8249  (`!s c f. (lift o c) continuous_on s /\ f continuous_on s
8250            ==> (\x. c(x) % f(x)) continuous_on s`,
8251   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
8252   SIMP_TAC[CONTINUOUS_MUL]);;
8253
8254 let CONTINUOUS_LIFT_POW = prove
8255  (`!net f:A->real n.
8256         (\x. lift(f x)) continuous net
8257         ==> (\x. lift(f x pow n)) continuous net`,
8258   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN
8259   INDUCT_TAC THEN ASM_REWRITE_TAC[LIFT_CMUL; real_pow; CONTINUOUS_CONST] THEN
8260   MATCH_MP_TAC CONTINUOUS_MUL THEN ASM_REWRITE_TAC[o_DEF]);;
8261
8262 let CONTINUOUS_ON_LIFT_POW = prove
8263  (`!f:real^N->real s n.
8264         (\x. lift(f x)) continuous_on s
8265         ==> (\x. lift(f x pow n)) continuous_on s`,
8266   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN REPEAT GEN_TAC THEN
8267   DISCH_TAC THEN INDUCT_TAC THEN
8268   ASM_REWRITE_TAC[LIFT_CMUL; real_pow; CONTINUOUS_ON_CONST] THEN
8269   MATCH_MP_TAC CONTINUOUS_ON_MUL THEN ASM_REWRITE_TAC[o_DEF]);;
8270
8271 let CONTINUOUS_LIFT_PRODUCT = prove
8272  (`!net:(A)net f (t:B->bool).
8273         FINITE t /\
8274         (!i. i IN t ==> (\x. lift(f x i)) continuous net)
8275         ==> (\x. lift(product t (f x))) continuous net`,
8276   GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
8277   MATCH_MP_TAC FINITE_INDUCT_STRONG THEN SIMP_TAC[PRODUCT_CLAUSES] THEN
8278   REWRITE_TAC[CONTINUOUS_CONST; LIFT_CMUL; FORALL_IN_INSERT] THEN
8279   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
8280   ASM_SIMP_TAC[o_DEF]);;
8281
8282 let CONTINUOUS_ON_LIFT_PRODUCT = prove
8283  (`!f:real^N->A->real s t.
8284         FINITE t /\
8285
8286         (!i. i IN t ==> (\x. lift(f x i)) continuous_on s)
8287         ==> (\x. lift(product t (f x))) continuous_on s`,
8288   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_LIFT_PRODUCT]);;
8289
8290 (* ------------------------------------------------------------------------- *)
8291 (* And so we have continuity of inverse.                                     *)
8292 (* ------------------------------------------------------------------------- *)
8293
8294 let LIM_INV = prove
8295  (`!net:(A)net f l.
8296         ((lift o f) --> lift l) net /\ ~(l = &0)
8297         ==> ((lift o inv o f) --> lift(inv l)) net`,
8298   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
8299   ASM_CASES_TAC `trivial_limit(net:(A)net)` THEN ASM_REWRITE_TAC[] THEN
8300   REWRITE_TAC[o_THM; DIST_LIFT] THEN STRIP_TAC THEN
8301   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8302   FIRST_X_ASSUM(MP_TAC o SPEC `min (abs(l) / &2) ((l pow 2 * e) / &2)`) THEN
8303   REWRITE_TAC[REAL_LT_MIN] THEN ANTS_TAC THENL
8304    [ASM_SIMP_TAC[GSYM REAL_ABS_NZ; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
8305     MATCH_MP_TAC REAL_LT_DIV THEN REWRITE_TAC[REAL_OF_NUM_LT; ARITH] THEN
8306     ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN
8307     ASM_SIMP_TAC[REAL_LT_MUL; GSYM REAL_ABS_NZ; REAL_POW_LT];
8308     ALL_TAC] THEN
8309   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:A` THEN
8310   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
8311   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `b:A` THEN
8312   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
8313   SIMP_TAC[REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN STRIP_TAC THEN
8314   FIRST_ASSUM(ASSUME_TAC o MATCH_MP (REAL_ARITH
8315    `abs(x - l) * &2 < abs l ==> ~(x = &0)`)) THEN
8316   ASM_SIMP_TAC[REAL_SUB_INV; REAL_ABS_DIV; REAL_LT_LDIV_EQ;
8317                GSYM REAL_ABS_NZ; REAL_ENTIRE] THEN
8318   FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
8319    `abs(x - y) * &2 < b * c ==> c * b <= d * &2 ==> abs(y - x) < d`)) THEN
8320   ASM_SIMP_TAC[GSYM REAL_MUL_ASSOC; REAL_LE_LMUL_EQ] THEN
8321   ONCE_REWRITE_TAC[GSYM REAL_POW2_ABS] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
8322   ASM_SIMP_TAC[REAL_ABS_MUL; REAL_POW_2; REAL_MUL_ASSOC; GSYM REAL_ABS_NZ;
8323                REAL_LE_RMUL_EQ] THEN
8324   ASM_SIMP_TAC[REAL_ARITH `abs(x - y) * &2 < abs y ==> abs y <= &2 * abs x`]);;
8325
8326 let CONTINUOUS_INV = prove
8327  (`!net f. (lift o f) continuous net /\ ~(f(netlimit net) = &0)
8328            ==> (lift o inv o f) continuous net`,
8329   REWRITE_TAC[continuous; LIM_INV; o_THM]);;
8330
8331 let CONTINUOUS_AT_WITHIN_INV = prove
8332  (`!f s a:real^N.
8333         (lift o f) continuous (at a within s) /\ ~(f a = &0)
8334         ==> (lift o inv o f) continuous (at a within s)`,
8335   REPEAT GEN_TAC THEN
8336   ASM_CASES_TAC `trivial_limit (at (a:real^N) within s)` THENL
8337    [ASM_REWRITE_TAC[continuous; LIM];
8338     ASM_SIMP_TAC[NETLIMIT_WITHIN; CONTINUOUS_INV]]);;
8339
8340 let CONTINUOUS_AT_INV = prove
8341  (`!f a. (lift o f) continuous at a /\ ~(f a = &0)
8342          ==> (lift o inv o f) continuous at a`,
8343   ONCE_REWRITE_TAC[GSYM WITHIN_UNIV] THEN
8344   REWRITE_TAC[CONTINUOUS_AT_WITHIN_INV]);;
8345
8346 let CONTINUOUS_ON_INV = prove
8347  (`!f s. (lift o f) continuous_on s /\ (!x. x IN s ==> ~(f x = &0))
8348          ==> (lift o inv o f) continuous_on s`,
8349   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_AT_WITHIN_INV]);;
8350
8351 (* ------------------------------------------------------------------------- *)
8352 (* Preservation properties for pasted sets (Cartesian products).             *)
8353 (* ------------------------------------------------------------------------- *)
8354
8355 let BOUNDED_PCROSS_EQ = prove
8356  (`!s:real^M->bool t:real^N->bool.
8357         bounded (s PCROSS t) <=>
8358         s = {} \/ t = {} \/ bounded s /\ bounded t`,
8359   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN
8360   ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
8361   ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
8362   REWRITE_TAC[SET_RULE `{f x y |x,y| F} = {}`; BOUNDED_EMPTY] THEN
8363   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
8364   REWRITE_TAC[bounded; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
8365   ASM_MESON_TAC[NORM_LE_PASTECART; REAL_LE_TRANS; NORM_PASTECART_LE;
8366                 REAL_LE_ADD2]);;
8367
8368 let BOUNDED_PCROSS = prove
8369  (`!s:real^M->bool t:real^N->bool.
8370      bounded s /\ bounded t ==> bounded (s PCROSS t)`,
8371   SIMP_TAC[BOUNDED_PCROSS_EQ]);;
8372
8373 let CLOSED_PCROSS_EQ = prove
8374  (`!s:real^M->bool t:real^N->bool.
8375         closed (s PCROSS t) <=>
8376         s = {} \/ t = {} \/ closed s /\ closed t`,
8377   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN MAP_EVERY ASM_CASES_TAC
8378    [`s:real^M->bool = {}`; `t:real^N->bool = {}`] THEN
8379   ASM_REWRITE_TAC[NOT_IN_EMPTY; CLOSED_EMPTY; SET_RULE
8380    `{f x y |x,y| F} = {}`] THEN
8381   REWRITE_TAC[CLOSED_SEQUENTIAL_LIMITS; LIM_SEQUENTIALLY] THEN
8382   REWRITE_TAC[FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
8383   REWRITE_TAC[IN_ELIM_THM; SKOLEM_THM; FORALL_AND_THM] THEN
8384   ONCE_REWRITE_TAC[GSYM FUN_EQ_THM] THEN
8385   REWRITE_TAC[LEFT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM] THEN
8386   SIMP_TAC[TAUT `((p /\ q) /\ r) /\ s ==> t <=> r ==> p /\ q /\ s ==> t`] THEN
8387   ONCE_REWRITE_TAC[MESON[]
8388    `(!a b c d e. P a b c d e) <=> (!d e b c a. P a b c d e)`] THEN
8389   REWRITE_TAC[FORALL_UNWIND_THM2] THEN
8390   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN EQ_TAC THENL
8391    [GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
8392      [TAUT `p ==> q /\ r <=> (p ==> q) /\ (p ==> r)`; FORALL_AND_THM] THEN
8393     MATCH_MP_TAC MONO_AND THEN CONJ_TAC THENL
8394      [ALL_TAC; GEN_REWRITE_TAC LAND_CONV [SWAP_FORALL_THM]] THEN
8395     MATCH_MP_TAC MONO_FORALL THEN REPEAT STRIP_TAC THEN
8396     FIRST_X_ASSUM MATCH_MP_TAC THEN MATCH_MP_TAC(MESON[]
8397      `(?x. P x (\n. x)) ==> (?s x. P x s)`) THEN
8398     ASM_MESON_TAC[DIST_PASTECART_CANCEL];
8399     ONCE_REWRITE_TAC[MESON[]
8400      `(!x l. P x l) /\ (!y m. Q y m) <=> (!x y l m. P x l /\ Q y m)`] THEN
8401     REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
8402     REWRITE_TAC[dist; PASTECART_SUB] THEN
8403     ASM_MESON_TAC[NORM_LE_PASTECART; REAL_LET_TRANS]]);;
8404
8405 let CLOSED_PCROSS = prove
8406  (`!s:real^M->bool t:real^N->bool.
8407      closed s /\ closed t ==> closed (s PCROSS t)`,
8408   SIMP_TAC[CLOSED_PCROSS_EQ]);;
8409
8410 let COMPACT_PCROSS_EQ = prove
8411  (`!s:real^M->bool t:real^N->bool.
8412         compact (s PCROSS t) <=>
8413         s = {} \/ t = {} \/ compact s /\ compact t`,
8414   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_PCROSS_EQ;
8415               BOUNDED_PCROSS_EQ] THEN
8416   MESON_TAC[]);;
8417
8418 let COMPACT_PCROSS = prove
8419  (`!s:real^M->bool t:real^N->bool.
8420      compact s /\ compact t ==> compact (s PCROSS t)`,
8421   SIMP_TAC[COMPACT_PCROSS_EQ]);;
8422
8423 let OPEN_PCROSS_EQ = prove
8424  (`!s:real^M->bool t:real^N->bool.
8425         open (s PCROSS t) <=>
8426         s = {} \/ t = {} \/ open s /\ open t`,
8427   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN
8428   ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
8429   ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
8430   REWRITE_TAC[SET_RULE `{f x y |x,y| F} = {}`; OPEN_EMPTY] THEN
8431   RULE_ASSUM_TAC(REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
8432   EQ_TAC THENL
8433    [REWRITE_TAC[open_def; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
8434     ASM_MESON_TAC[DIST_PASTECART_CANCEL];
8435     REWRITE_TAC[OPEN_CLOSED] THEN STRIP_TAC THEN
8436     SUBGOAL_THEN
8437      `UNIV DIFF {pastecart x y | x IN s /\ y IN t} =
8438       {pastecart x y | x IN ((:real^M) DIFF s) /\ y IN (:real^N)} UNION
8439       {pastecart x y | x IN (:real^M) /\ y IN ((:real^N) DIFF t)}`
8440     SUBST1_TAC THENL
8441      [REWRITE_TAC[EXTENSION; IN_DIFF; IN_UNION; FORALL_PASTECART; IN_UNIV] THEN
8442       REWRITE_TAC[IN_ELIM_THM; PASTECART_EQ; FSTCART_PASTECART;
8443                   SNDCART_PASTECART] THEN MESON_TAC[];
8444       SIMP_TAC[GSYM PCROSS] THEN MATCH_MP_TAC CLOSED_UNION THEN CONJ_TAC THEN
8445       MATCH_MP_TAC CLOSED_PCROSS THEN ASM_REWRITE_TAC[CLOSED_UNIV]]]);;
8446
8447 let OPEN_PCROSS = prove
8448  (`!s:real^M->bool t:real^N->bool.
8449         open s /\ open t ==> open (s PCROSS t)`,
8450   SIMP_TAC[OPEN_PCROSS_EQ]);;
8451
8452 let OPEN_IN_PCROSS = prove
8453  (`!s s':real^M->bool t t':real^N->bool.
8454         open_in (subtopology euclidean s) s' /\
8455         open_in (subtopology euclidean t) t'
8456         ==> open_in (subtopology euclidean (s PCROSS t)) (s' PCROSS t')`,
8457   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN] THEN DISCH_THEN(CONJUNCTS_THEN2
8458    (X_CHOOSE_THEN `s'':real^M->bool` STRIP_ASSUME_TAC)
8459    (X_CHOOSE_THEN `t'':real^N->bool` STRIP_ASSUME_TAC)) THEN
8460   EXISTS_TAC `(s'':real^M->bool) PCROSS (t'':real^N->bool)` THEN
8461   ASM_SIMP_TAC[OPEN_PCROSS; EXTENSION; FORALL_PASTECART] THEN
8462   REWRITE_TAC[IN_INTER; PASTECART_IN_PCROSS] THEN ASM SET_TAC[]);;
8463
8464 let PASTECART_IN_INTERIOR_SUBTOPOLOGY = prove
8465  (`!s t u x:real^M y:real^N.
8466      pastecart x y IN u /\ open_in (subtopology euclidean (s PCROSS t)) u
8467      ==> ?v w. open_in (subtopology euclidean s) v /\ x IN v /\
8468                open_in (subtopology euclidean t) w /\ y IN w /\
8469                (v PCROSS w) SUBSET u`,
8470   REWRITE_TAC[open_in; FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
8471   REPEAT STRIP_TAC THEN
8472   FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^M`; `y:real^N`]) THEN
8473   ASM_REWRITE_TAC[] THEN
8474   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
8475   EXISTS_TAC `ball(x:real^M,e / &2) INTER s` THEN
8476   EXISTS_TAC `ball(y:real^N,e / &2) INTER t` THEN
8477   SUBGOAL_THEN `(x:real^M) IN s /\ (y:real^N) IN t` STRIP_ASSUME_TAC THENL
8478    [ASM_MESON_TAC[SUBSET; PASTECART_IN_PCROSS]; ALL_TAC] THEN
8479   ASM_SIMP_TAC[INTER_SUBSET; IN_INTER; CENTRE_IN_BALL; REAL_HALF] THEN
8480   REWRITE_TAC[IN_BALL] THEN REPEAT(CONJ_TAC THENL
8481    [MESON_TAC[REAL_SUB_LT; NORM_ARITH
8482      `dist(x,y) < e /\ dist(z,y) < e - dist(x,y)
8483       ==> dist(x:real^N,z) < e`];
8484     ALL_TAC]) THEN
8485   REWRITE_TAC[SUBSET; FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
8486   REWRITE_TAC[IN_BALL; IN_INTER] THEN REPEAT STRIP_TAC THEN
8487   FIRST_X_ASSUM MATCH_MP_TAC THEN
8488   ASM_REWRITE_TAC[dist; PASTECART_SUB] THEN
8489   W(MP_TAC o PART_MATCH lhand NORM_PASTECART_LE o lhand o snd) THEN
8490   REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[DIST_SYM] dist)] THEN
8491   ASM_REAL_ARITH_TAC);;
8492
8493 let OPEN_IN_PCROSS_EQ = prove
8494  (`!s s':real^M->bool t t':real^N->bool.
8495         open_in (subtopology euclidean (s PCROSS t)) (s' PCROSS t') <=>
8496         s' = {} \/ t' = {} \/
8497         open_in (subtopology euclidean s) s' /\
8498         open_in (subtopology euclidean t) t'`,
8499   REPEAT GEN_TAC THEN
8500   ASM_CASES_TAC `s':real^M->bool = {}` THEN
8501   ASM_REWRITE_TAC[PCROSS_EMPTY; OPEN_IN_EMPTY] THEN
8502   ASM_CASES_TAC `t':real^N->bool = {}` THEN
8503   ASM_REWRITE_TAC[PCROSS_EMPTY; OPEN_IN_EMPTY] THEN
8504   EQ_TAC THEN REWRITE_TAC[OPEN_IN_PCROSS] THEN REPEAT STRIP_TAC THENL
8505    [ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN
8506     X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
8507     UNDISCH_TAC `~(t':real^N->bool = {})` THEN
8508     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
8509     DISCH_THEN(X_CHOOSE_TAC `y:real^N`);
8510     ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN
8511     X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
8512     UNDISCH_TAC `~(s':real^M->bool = {})` THEN
8513     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
8514     DISCH_THEN(X_CHOOSE_TAC `x:real^M`)] THEN
8515    MP_TAC(ISPECL
8516      [`s:real^M->bool`; `t:real^N->bool`;
8517       `(s':real^M->bool) PCROSS (t':real^N->bool)`;
8518       `x:real^M`; `y:real^N`] PASTECART_IN_INTERIOR_SUBTOPOLOGY) THEN
8519   ASM_REWRITE_TAC[SUBSET; FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
8520   MESON_TAC[]);;
8521
8522 let INTERIOR_PCROSS = prove
8523  (`!s:real^M->bool t:real^N->bool.
8524         interior (s PCROSS t) = (interior s) PCROSS (interior t)`,
8525   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
8526    [REWRITE_TAC[SUBSET; FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
8527     MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^N`] THEN DISCH_TAC THEN
8528     MP_TAC(ISPECL [`(:real^M)`; `(:real^N)`;
8529          `interior((s:real^M->bool) PCROSS (t:real^N->bool))`;
8530          `x:real^M`; `y:real^N`] PASTECART_IN_INTERIOR_SUBTOPOLOGY) THEN
8531     REWRITE_TAC[UNIV_PCROSS_UNIV; SUBTOPOLOGY_UNIV; GSYM OPEN_IN] THEN
8532     ASM_REWRITE_TAC[OPEN_INTERIOR] THEN STRIP_TAC THEN
8533     FIRST_ASSUM(MP_TAC o MATCH_MP (MESON[INTERIOR_SUBSET; SUBSET_TRANS]
8534       `s SUBSET interior t ==> s SUBSET t`)) THEN
8535     REWRITE_TAC[SUBSET_PCROSS] THEN
8536     ASM_MESON_TAC[NOT_IN_EMPTY; INTERIOR_MAXIMAL; SUBSET];
8537     MATCH_MP_TAC INTERIOR_MAXIMAL THEN
8538     SIMP_TAC[OPEN_PCROSS; OPEN_INTERIOR; PCROSS_MONO; INTERIOR_SUBSET]]);;
8539
8540 let LIM_PASTECART = prove
8541  (`!net f:A->real^M g:A->real^N.
8542         (f --> a) net /\ (g --> b) net
8543         ==> ((\x. pastecart (f x) (g x)) --> pastecart a b) net`,
8544   REPEAT GEN_TAC THEN REWRITE_TAC[LIM] THEN
8545   ASM_CASES_TAC `trivial_limit(net:(A)net)` THEN ASM_REWRITE_TAC[] THEN
8546   REWRITE_TAC[AND_FORALL_THM] THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN
8547   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
8548   ASM_REWRITE_TAC[REAL_HALF] THEN
8549   DISCH_THEN(MP_TAC o MATCH_MP NET_DILEMMA) THEN
8550   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN MATCH_MP_TAC MONO_AND THEN
8551   REWRITE_TAC[] THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
8552   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
8553   REWRITE_TAC[dist; PASTECART_SUB] THEN
8554   MATCH_MP_TAC(REAL_ARITH
8555     `z <= x + y ==> x < e / &2 /\ y < e / &2 ==> z < e`) THEN
8556   REWRITE_TAC[NORM_PASTECART_LE]);;
8557
8558 let LIM_PASTECART_EQ = prove
8559  (`!net f:A->real^M g:A->real^N.
8560         ((\x. pastecart (f x) (g x)) --> pastecart a b) net <=>
8561         (f --> a) net /\ (g --> b) net`,
8562   REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[LIM_PASTECART] THEN
8563   REPEAT STRIP_TAC THENL
8564    [FIRST_ASSUM(MP_TAC o ISPEC `fstcart:real^(M,N)finite_sum->real^M` o
8565         MATCH_MP (REWRITE_RULE[IMP_CONJ] LIM_LINEAR)) THEN
8566     REWRITE_TAC[LINEAR_FSTCART; FSTCART_PASTECART; ETA_AX];
8567     FIRST_ASSUM(MP_TAC o ISPEC `sndcart:real^(M,N)finite_sum->real^N` o
8568         MATCH_MP (REWRITE_RULE[IMP_CONJ] LIM_LINEAR)) THEN
8569     REWRITE_TAC[LINEAR_SNDCART; SNDCART_PASTECART; ETA_AX]]);;
8570
8571 let CONTINUOUS_PASTECART = prove
8572  (`!net f:A->real^M g:A->real^N.
8573         f continuous net /\ g continuous net
8574         ==> (\x. pastecart (f x) (g x)) continuous net`,
8575   REWRITE_TAC[continuous; LIM_PASTECART]);;
8576
8577 let CONTINUOUS_ON_PASTECART = prove
8578  (`!f:real^M->real^N g:real^M->real^P s.
8579         f continuous_on s /\ g continuous_on s
8580         ==> (\x. pastecart (f x) (g x)) continuous_on s`,
8581   SIMP_TAC[CONTINUOUS_ON; LIM_PASTECART]);;
8582
8583 let CONNECTED_PCROSS = prove
8584  (`!s:real^M->bool t:real^N->bool.
8585         connected s /\ connected t
8586         ==> connected (s PCROSS t)`,
8587   REPEAT GEN_TAC THEN
8588   REWRITE_TAC[PCROSS; CONNECTED_IFF_CONNECTED_COMPONENT] THEN
8589   DISCH_TAC THEN REWRITE_TAC[FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
8590   MAP_EVERY X_GEN_TAC [`x1:real^M`; `y1:real^N`; `x2:real^M`; `y2:real^N`] THEN
8591   STRIP_TAC THEN FIRST_X_ASSUM(CONJUNCTS_THEN2
8592    (MP_TAC o SPECL [`x1:real^M`; `x2:real^M`])
8593    (MP_TAC o SPECL [`y1:real^N`; `y2:real^N`])) THEN
8594   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; connected_component] THEN
8595   X_GEN_TAC `c2:real^N->bool` THEN STRIP_TAC THEN
8596   X_GEN_TAC `c1:real^M->bool` THEN STRIP_TAC THEN
8597   EXISTS_TAC
8598    `IMAGE (\x:real^M. pastecart x y1) c1 UNION
8599     IMAGE (\y:real^N. pastecart x2 y) c2` THEN
8600   REWRITE_TAC[IN_UNION] THEN REPEAT CONJ_TAC THENL
8601    [MATCH_MP_TAC CONNECTED_UNION THEN
8602     ASM_SIMP_TAC[CONNECTED_CONTINUOUS_IMAGE; CONTINUOUS_ON_PASTECART;
8603                  CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN
8604     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER; EXISTS_IN_IMAGE] THEN
8605     EXISTS_TAC `x2:real^M` THEN ASM SET_TAC[];
8606     REWRITE_TAC[SUBSET; IN_UNION; FORALL_AND_THM; FORALL_IN_IMAGE;
8607                 TAUT `a \/ b ==> c <=> (a ==> c) /\ (b ==> c)`] THEN
8608     ASM SET_TAC[];
8609     ASM SET_TAC[];
8610     ASM SET_TAC[]]);;
8611
8612 let CONNECTED_PCROSS_EQ = prove
8613  (`!s:real^M->bool t:real^N->bool.
8614         connected (s PCROSS t) <=>
8615         s = {} \/ t = {} \/ connected s /\ connected t`,
8616   REPEAT GEN_TAC THEN
8617   ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
8618   ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
8619   REWRITE_TAC[PCROSS_EMPTY; CONNECTED_EMPTY] THEN
8620   EQ_TAC THEN SIMP_TAC[CONNECTED_PCROSS] THEN
8621   REWRITE_TAC[PCROSS] THEN REPEAT STRIP_TAC THENL
8622    [SUBGOAL_THEN `connected (IMAGE fstcart
8623                      {pastecart (x:real^M) (y:real^N) | x IN s /\ y IN t})`
8624     MP_TAC THENL [MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE; ALL_TAC];
8625     SUBGOAL_THEN `connected (IMAGE sndcart
8626                      {pastecart (x:real^M) (y:real^N) | x IN s /\ y IN t})`
8627     MP_TAC THENL [MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE; ALL_TAC]] THEN
8628   ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART; LINEAR_SNDCART] THEN
8629   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
8630   REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; IN_ELIM_PASTECART_THM;
8631               FSTCART_PASTECART; SNDCART_PASTECART] THEN
8632   ASM SET_TAC[]);;
8633
8634 let CLOSURE_PCROSS = prove
8635  (`!s:real^M->bool t:real^N->bool.
8636         closure (s PCROSS t) = (closure s) PCROSS (closure t)`,
8637   REWRITE_TAC[EXTENSION; PCROSS; FORALL_PASTECART] THEN REPEAT GEN_TAC THEN
8638   REWRITE_TAC[CLOSURE_APPROACHABLE; EXISTS_PASTECART; FORALL_PASTECART] THEN
8639   REWRITE_TAC[IN_ELIM_PASTECART_THM; PASTECART_INJ] THEN
8640   REWRITE_TAC[FSTCART_PASTECART; SNDCART_PASTECART] THEN
8641   REWRITE_TAC[dist; PASTECART_SUB] THEN EQ_TAC THENL
8642    [MESON_TAC[NORM_LE_PASTECART; REAL_LET_TRANS]; DISCH_TAC] THEN
8643   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8644   FIRST_X_ASSUM(CONJUNCTS_THEN (MP_TAC o SPEC `e / &2`)) THEN
8645   ASM_MESON_TAC[REAL_HALF; NORM_PASTECART_LE; REAL_ARITH
8646     `z <= x + y /\ x < e / &2 /\ y < e / &2 ==> z < e`]);;
8647
8648 let LIMPT_PCROSS = prove
8649  (`!s:real^M->bool t:real^N->bool x y.
8650         x limit_point_of s /\ y limit_point_of t
8651         ==> (pastecart x y) limit_point_of (s PCROSS t)`,
8652   REPEAT GEN_TAC THEN
8653   REWRITE_TAC[PCROSS; LIMPT_APPROACHABLE; EXISTS_PASTECART] THEN
8654   REWRITE_TAC[IN_ELIM_PASTECART_THM; PASTECART_INJ; dist; PASTECART_SUB] THEN
8655   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
8656   FIRST_X_ASSUM(CONJUNCTS_THEN (MP_TAC o SPEC `e / &2`)) THEN
8657   ASM_MESON_TAC[REAL_HALF; NORM_PASTECART_LE; REAL_ARITH
8658     `z <= x + y /\ x < e / &2 /\ y < e / &2 ==> z < e`]);;
8659
8660 (* ------------------------------------------------------------------------- *)
8661 (* Hence some useful properties follow quite easily.                         *)
8662 (* ------------------------------------------------------------------------- *)
8663
8664 let CONNECTED_SCALING = prove
8665  (`!s:real^N->bool c. connected s ==> connected (IMAGE (\x. c % x) s)`,
8666   REPEAT STRIP_TAC THEN
8667   MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
8668   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
8669   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
8670   REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
8671
8672 let CONNECTED_NEGATIONS = prove
8673  (`!s:real^N->bool. connected s ==> connected (IMAGE (--) s)`,
8674   REPEAT STRIP_TAC THEN
8675   MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
8676   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
8677   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
8678   REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
8679
8680 let CONNECTED_SUMS = prove
8681  (`!s t:real^N->bool.
8682         connected s /\ connected t ==> connected {x + y | x IN s /\ y IN t}`,
8683   REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CONNECTED_PCROSS) THEN
8684   DISCH_THEN(MP_TAC o ISPEC
8685    `\z. (fstcart z + sndcart z:real^N)` o
8686     MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT] CONNECTED_CONTINUOUS_IMAGE)) THEN
8687   SIMP_TAC[CONTINUOUS_ON_ADD; LINEAR_CONTINUOUS_ON; LINEAR_FSTCART;
8688            LINEAR_SNDCART; PCROSS] THEN
8689   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
8690   REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM; EXISTS_PASTECART] THEN
8691   REWRITE_TAC[PASTECART_INJ; FSTCART_PASTECART; SNDCART_PASTECART] THEN
8692   MESON_TAC[]);;
8693
8694 let COMPACT_SCALING = prove
8695  (`!s:real^N->bool c. compact s ==> compact (IMAGE (\x. c % x) s)`,
8696   REPEAT STRIP_TAC THEN
8697   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
8698   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
8699   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
8700   REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
8701
8702 let COMPACT_NEGATIONS = prove
8703  (`!s:real^N->bool. compact s ==> compact (IMAGE (--) s)`,
8704   REPEAT STRIP_TAC THEN
8705   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
8706   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
8707   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
8708   REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
8709
8710 let COMPACT_SUMS = prove
8711  (`!s:real^N->bool t.
8712         compact s /\ compact t ==> compact {x + y | x IN s /\ y IN t}`,
8713   REPEAT STRIP_TAC THEN
8714   SUBGOAL_THEN `{x + y | x IN s /\ y IN t} =
8715                 IMAGE (\z. fstcart z + sndcart z :real^N) (s PCROSS t)`
8716   SUBST1_TAC THENL
8717    [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE; PCROSS] THEN
8718     GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
8719     ASM_MESON_TAC[FSTCART_PASTECART; SNDCART_PASTECART; PASTECART_FST_SND];
8720     ALL_TAC] THEN
8721   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
8722   ASM_SIMP_TAC[COMPACT_PCROSS] THEN
8723   MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
8724   REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN
8725   REWRITE_TAC[linear; FSTCART_ADD; FSTCART_CMUL; SNDCART_ADD;
8726               SNDCART_CMUL] THEN
8727   CONJ_TAC THEN VECTOR_ARITH_TAC);;
8728
8729 let COMPACT_DIFFERENCES = prove
8730  (`!s:real^N->bool t.
8731         compact s /\ compact t ==> compact {x - y | x IN s /\ y IN t}`,
8732   REPEAT STRIP_TAC THEN
8733   SUBGOAL_THEN `{x - y | x:real^N IN s /\ y IN t} =
8734                 {x + y | x IN s /\ y IN (IMAGE (--) t)}`
8735     (fun th -> ASM_SIMP_TAC[th; COMPACT_SUMS; COMPACT_NEGATIONS]) THEN
8736   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE] THEN
8737   ONCE_REWRITE_TAC[VECTOR_ARITH `(x:real^N = --y) <=> (y = --x)`] THEN
8738   SIMP_TAC[VECTOR_SUB; GSYM CONJ_ASSOC; UNWIND_THM2] THEN
8739   MESON_TAC[VECTOR_NEG_NEG]);;
8740
8741 let COMPACT_TRANSLATION_EQ = prove
8742  (`!a s. compact (IMAGE (\x:real^N. a + x) s) <=> compact s`,
8743   REWRITE_TAC[COMPACT_EQ_HEINE_BOREL] THEN GEOM_TRANSLATE_TAC[]);;
8744
8745 let COMPACT_TRANSLATION = prove
8746  (`!s a:real^N. compact s ==> compact (IMAGE (\x. a + x) s)`,
8747   REWRITE_TAC[COMPACT_TRANSLATION_EQ]);;
8748
8749 add_translation_invariants [COMPACT_TRANSLATION_EQ];;
8750
8751 let COMPACT_AFFINITY = prove
8752  (`!s a:real^N c.
8753         compact s ==> compact (IMAGE (\x. a + c % x) s)`,
8754   REPEAT STRIP_TAC THEN
8755   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
8756   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
8757   ASM_SIMP_TAC[IMAGE_o; COMPACT_TRANSLATION; COMPACT_SCALING]);;
8758
8759 (* ------------------------------------------------------------------------- *)
8760 (* Hence we get the following.                                               *)
8761 (* ------------------------------------------------------------------------- *)
8762
8763 let COMPACT_SUP_MAXDISTANCE = prove
8764  (`!s:real^N->bool.
8765         compact s /\ ~(s = {})
8766         ==> ?x y. x IN s /\ y IN s /\
8767                   !u v. u IN s /\ v IN s ==> norm(u - v) <= norm(x - y)`,
8768   REPEAT STRIP_TAC THEN
8769   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN s}`; `vec 0:real^N`]
8770                 DISTANCE_ATTAINS_SUP) THEN
8771   ANTS_TAC THENL
8772    [ASM_SIMP_TAC[COMPACT_DIFFERENCES] THEN
8773     REWRITE_TAC[EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY] THEN
8774     ASM_MESON_TAC[MEMBER_NOT_EMPTY];
8775     REWRITE_TAC[IN_ELIM_THM; dist; VECTOR_SUB_RZERO; VECTOR_SUB_LZERO;
8776                 NORM_NEG] THEN
8777     MESON_TAC[]]);;
8778
8779 (* ------------------------------------------------------------------------- *)
8780 (* We can state this in terms of diameter of a set.                          *)
8781 (* ------------------------------------------------------------------------- *)
8782
8783 let diameter = new_definition
8784   `diameter s =
8785         if s = {} then &0
8786         else sup {norm(x - y) | x IN s /\ y IN s}`;;
8787
8788 let DIAMETER_BOUNDED = prove
8789  (`!s. bounded s
8790        ==> (!x:real^N y. x IN s /\ y IN s ==> norm(x - y) <= diameter s) /\
8791            (!d. &0 <= d /\ d < diameter s
8792                 ==> ?x y. x IN s /\ y IN s /\ norm(x - y) > d)`,
8793   GEN_TAC THEN DISCH_TAC THEN
8794   ASM_CASES_TAC `s:real^N->bool = {}` THEN
8795   ASM_REWRITE_TAC[diameter; NOT_IN_EMPTY; REAL_LET_ANTISYM] THEN
8796   MP_TAC(SPEC `{norm(x - y:real^N) | x IN s /\ y IN s}` SUP) THEN
8797   ABBREV_TAC `b = sup {norm(x - y:real^N) | x IN s /\ y IN s}` THEN
8798   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
8799   REWRITE_TAC[NOT_IN_EMPTY; real_gt] THEN ANTS_TAC THENL
8800    [CONJ_TAC THENL [ASM_MESON_TAC[MEMBER_NOT_EMPTY]; ALL_TAC];
8801     MESON_TAC[REAL_NOT_LE]] THEN
8802   SIMP_TAC[VECTOR_SUB; LEFT_IMP_EXISTS_THM] THEN
8803   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [bounded]) THEN
8804   MESON_TAC[REAL_ARITH `x <= y + z /\ y <= b /\ z<= b ==> x <= b + b`;
8805             NORM_TRIANGLE; NORM_NEG]);;
8806
8807 let DIAMETER_BOUNDED_BOUND = prove
8808  (`!s x y. bounded s /\ x IN s /\ y IN s ==> norm(x - y) <= diameter s`,
8809   MESON_TAC[DIAMETER_BOUNDED]);;
8810
8811 let DIAMETER_COMPACT_ATTAINED = prove
8812  (`!s:real^N->bool.
8813         compact s /\ ~(s = {})
8814         ==> ?x y. x IN s /\ y IN s /\ (norm(x - y) = diameter s)`,
8815   GEN_TAC THEN DISCH_TAC THEN
8816   FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_SUP_MAXDISTANCE) THEN
8817   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
8818   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
8819   MP_TAC(SPEC `s:real^N->bool` DIAMETER_BOUNDED) THEN
8820   RULE_ASSUM_TAC(REWRITE_RULE[COMPACT_EQ_BOUNDED_CLOSED]) THEN
8821   ASM_REWRITE_TAC[real_gt] THEN STRIP_TAC THEN
8822   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
8823   ASM_MESON_TAC[NORM_POS_LE; REAL_NOT_LT]);;
8824
8825 let DIAMETER_TRANSLATION = prove
8826  (`!a s. diameter (IMAGE (\x. a + x) s) = diameter s`,
8827   REWRITE_TAC[diameter] THEN GEOM_TRANSLATE_TAC[]);;
8828
8829 add_translation_invariants [DIAMETER_TRANSLATION];;
8830
8831 let DIAMETER_LINEAR_IMAGE = prove
8832  (`!f:real^M->real^N s.
8833         linear f /\ (!x. norm(f x) = norm x)
8834         ==> diameter(IMAGE f s) = diameter s`,
8835   REWRITE_TAC[diameter] THEN
8836   REPEAT STRIP_TAC THEN REWRITE_TAC[diameter; IMAGE_EQ_EMPTY] THEN
8837   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN
8838   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
8839   REWRITE_TAC[GSYM CONJ_ASSOC; RIGHT_EXISTS_AND_THM; EXISTS_IN_IMAGE] THEN
8840   ASM_MESON_TAC[LINEAR_SUB]);;
8841
8842 add_linear_invariants [DIAMETER_LINEAR_IMAGE];;
8843
8844 let DIAMETER_EMPTY = prove
8845  (`diameter {} = &0`,
8846   REWRITE_TAC[diameter]);;
8847
8848 let DIAMETER_SING = prove
8849  (`!a. diameter {a} = &0`,
8850   REWRITE_TAC[diameter; NOT_INSERT_EMPTY; IN_SING] THEN
8851   REWRITE_TAC[SET_RULE `{f x y | x = a /\ y = a} = {f a a }`] THEN
8852   REWRITE_TAC[SUP_SING; VECTOR_SUB_REFL; NORM_0]);;
8853
8854 let DIAMETER_POS_LE = prove
8855  (`!s:real^N->bool. bounded s ==> &0 <= diameter s`,
8856   REPEAT STRIP_TAC THEN REWRITE_TAC[diameter] THEN
8857   COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_LE_REFL] THEN
8858   MP_TAC(SPEC `{norm(x - y:real^N) | x IN s /\ y IN s}` SUP) THEN
8859   REWRITE_TAC[FORALL_IN_GSPEC] THEN ANTS_TAC THENL
8860    [CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
8861     FIRST_X_ASSUM(X_CHOOSE_TAC `B:real` o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
8862     EXISTS_TAC `&2 * B` THEN
8863     ASM_SIMP_TAC[NORM_ARITH
8864       `norm x <= B /\ norm y <= B ==> norm(x - y) <= &2 * B`];
8865     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
8866     DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN
8867     DISCH_THEN(MP_TAC o SPECL [`a:real^N`; `a:real^N`] o CONJUNCT1) THEN
8868     ASM_REWRITE_TAC[VECTOR_SUB_REFL; NORM_0]]);;
8869
8870 let DIAMETER_SUBSET = prove
8871  (`!s t:real^N->bool. s SUBSET t /\ bounded t ==> diameter s <= diameter t`,
8872   REPEAT STRIP_TAC THEN
8873   ASM_CASES_TAC `s:real^N->bool = {}` THEN
8874   ASM_SIMP_TAC[DIAMETER_EMPTY; DIAMETER_POS_LE] THEN
8875   ASM_REWRITE_TAC[diameter] THEN
8876   COND_CASES_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
8877   MATCH_MP_TAC REAL_SUP_LE_SUBSET THEN
8878   REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
8879   REWRITE_TAC[FORALL_IN_GSPEC] THEN
8880   FIRST_X_ASSUM(X_CHOOSE_TAC `B:real` o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
8881   EXISTS_TAC `&2 * B` THEN
8882   ASM_SIMP_TAC[NORM_ARITH
8883     `norm x <= B /\ norm y <= B ==> norm(x - y) <= &2 * B`]);;
8884
8885 let DIAMETER_CLOSURE = prove
8886  (`!s:real^N->bool. bounded s ==> diameter(closure s) = diameter s`,
8887   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN REPEAT STRIP_TAC THEN
8888   ASM_SIMP_TAC[DIAMETER_SUBSET; BOUNDED_CLOSURE; CLOSURE_SUBSET] THEN
8889   REWRITE_TAC[GSYM REAL_NOT_LT] THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN
8890   DISCH_TAC THEN MP_TAC(ISPEC `closure s:real^N->bool` DIAMETER_BOUNDED) THEN
8891   ABBREV_TAC `d = diameter(closure s) - diameter(s:real^N->bool)` THEN
8892   ASM_SIMP_TAC[BOUNDED_CLOSURE] THEN DISCH_THEN(MP_TAC o
8893     SPEC `diameter(closure(s:real^N->bool)) - d / &2` o CONJUNCT2) THEN
8894   REWRITE_TAC[NOT_IMP; GSYM CONJ_ASSOC; NOT_EXISTS_THM] THEN
8895   FIRST_ASSUM(ASSUME_TAC o MATCH_MP DIAMETER_POS_LE) THEN
8896   REPEAT(CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
8897   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
8898   REWRITE_TAC[CLOSURE_APPROACHABLE; CONJ_ASSOC; AND_FORALL_THM] THEN
8899   DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o SPEC `d / &4`) ASSUME_TAC) THEN
8900   ASM_REWRITE_TAC[REAL_ARITH `&0 < d / &4 <=> &0 < d`] THEN
8901   DISCH_THEN(CONJUNCTS_THEN2
8902    (X_CHOOSE_THEN `u:real^N` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC))
8903    (X_CHOOSE_THEN `v:real^N` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC))) THEN
8904   FIRST_ASSUM(MP_TAC o MATCH_MP DIAMETER_BOUNDED) THEN
8905   DISCH_THEN(MP_TAC o SPECL [`u:real^N`; `v:real^N`] o CONJUNCT1) THEN
8906   ASM_REWRITE_TAC[] THEN REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
8907
8908 let DIAMETER_SUBSET_CBALL_NONEMPTY = prove
8909  (`!s:real^N->bool.
8910        bounded s /\ ~(s = {}) ==> ?z. z IN s /\ s SUBSET cball(z,diameter s)`,
8911    REPEAT STRIP_TAC THEN
8912    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
8913    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
8914    DISCH_TAC THEN ASM_REWRITE_TAC[SUBSET] THEN X_GEN_TAC `b:real^N` THEN
8915    DISCH_TAC THEN REWRITE_TAC[IN_CBALL; dist] THEN
8916    ASM_MESON_TAC[DIAMETER_BOUNDED]);;
8917
8918 let DIAMETER_SUBSET_CBALL = prove
8919  (`!s:real^N->bool. bounded s ==> ?z. s SUBSET cball(z,diameter s)`,
8920   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
8921   ASM_MESON_TAC[DIAMETER_SUBSET_CBALL_NONEMPTY; EMPTY_SUBSET]);;
8922
8923 let DIAMETER_EQ_0 = prove
8924  (`!s:real^N->bool.
8925         bounded s ==> (diameter s = &0 <=> s = {} \/ ?a. s = {a})`,
8926   REPEAT STRIP_TAC THEN EQ_TAC THEN STRIP_TAC THEN
8927   ASM_REWRITE_TAC[DIAMETER_EMPTY; DIAMETER_SING] THEN
8928   REWRITE_TAC[SET_RULE
8929    `s = {} \/ (?a. s = {a}) <=> !a b. a IN s /\ b IN s ==> a = b`] THEN
8930   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN
8931   MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`; `b:real^N`]
8932         DIAMETER_BOUNDED_BOUND) THEN
8933   ASM_REWRITE_TAC[] THEN NORM_ARITH_TAC);;
8934
8935 let DIAMETER_LE = prove
8936  (`!s:real^N->bool.
8937         (~(s = {}) \/ &0 <= d) /\
8938         (!x y. x IN s /\ y IN s ==> norm(x - y) <= d) ==> diameter s <= d`,
8939   GEN_TAC THEN REWRITE_TAC[diameter] THEN
8940   COND_CASES_TAC THEN ASM_SIMP_TAC[] THEN
8941   STRIP_TAC THEN MATCH_MP_TAC REAL_SUP_LE THEN
8942   CONJ_TAC THENL [ASM SET_TAC[]; ASM_SIMP_TAC[FORALL_IN_GSPEC]]);;
8943
8944 let DIAMETER_CBALL = prove
8945  (`!a:real^N r. diameter(cball(a,r)) = if r < &0 then &0 else &2 * r`,
8946   REPEAT GEN_TAC THEN COND_CASES_TAC THENL
8947    [ASM_MESON_TAC[CBALL_EQ_EMPTY; DIAMETER_EMPTY]; ALL_TAC] THEN
8948   RULE_ASSUM_TAC(REWRITE_RULE[REAL_NOT_LT]) THEN
8949   REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN CONJ_TAC THENL
8950    [MATCH_MP_TAC DIAMETER_LE THEN
8951     ASM_SIMP_TAC[CBALL_EQ_EMPTY; REAL_LE_MUL; REAL_POS; REAL_NOT_LT] THEN
8952     REWRITE_TAC[IN_CBALL] THEN NORM_ARITH_TAC;
8953     MATCH_MP_TAC REAL_LE_TRANS THEN
8954     EXISTS_TAC `norm((a + r % basis 1) - (a - r % basis 1):real^N)` THEN
8955     CONJ_TAC THENL
8956      [REWRITE_TAC[VECTOR_ARITH `(a + r % b) - (a - r % b:real^N) =
8957                                 (&2 * r) % b`] THEN
8958       SIMP_TAC[NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
8959       ASM_REAL_ARITH_TAC;
8960       MATCH_MP_TAC DIAMETER_BOUNDED_BOUND THEN
8961       REWRITE_TAC[BOUNDED_CBALL; IN_CBALL] THEN
8962       REWRITE_TAC[NORM_ARITH
8963        `dist(a:real^N,a + b) = norm b /\ dist(a,a - b) = norm b`] THEN
8964       SIMP_TAC[NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
8965       ASM_REAL_ARITH_TAC]]);;
8966
8967 let DIAMETER_BALL = prove
8968  (`!a:real^N r. diameter(ball(a,r)) = if r < &0 then &0 else &2 * r`,
8969   REPEAT GEN_TAC THEN COND_CASES_TAC THENL
8970    [ASM_SIMP_TAC[BALL_EMPTY; REAL_LT_IMP_LE; DIAMETER_EMPTY]; ALL_TAC] THEN
8971   ASM_CASES_TAC `r = &0` THEN
8972   ASM_SIMP_TAC[BALL_EMPTY; REAL_LE_REFL; DIAMETER_EMPTY; REAL_MUL_RZERO] THEN
8973   MATCH_MP_TAC EQ_TRANS THEN
8974   EXISTS_TAC `diameter(cball(a:real^N,r))` THEN CONJ_TAC THENL
8975    [SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
8976     ASM_SIMP_TAC[GSYM CLOSURE_BALL; DIAMETER_CLOSURE; BOUNDED_BALL];
8977     ASM_SIMP_TAC[DIAMETER_CBALL]]);;
8978
8979 let LEBESGUE_COVERING_LEMMA = prove
8980  (`!s:real^N->bool c.
8981         compact s /\ ~(c = {}) /\ s SUBSET UNIONS c /\ (!b. b IN c ==> open b)
8982         ==> ?d. &0 < d /\
8983                 !t. t SUBSET s /\ diameter t <= d
8984                     ==> ?b. b IN c /\ t SUBSET b`,
8985   REPEAT STRIP_TAC THEN
8986   FIRST_ASSUM(MP_TAC o MATCH_MP HEINE_BOREL_LEMMA) THEN
8987   DISCH_THEN(MP_TAC o SPEC `c:(real^N->bool)->bool`) THEN ASM_SIMP_TAC[] THEN
8988   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `e:real` THEN
8989   STRIP_TAC THEN EXISTS_TAC `e / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN
8990   X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
8991   ASM_CASES_TAC `t:real^N->bool = {}` THENL [ASM SET_TAC[]; ALL_TAC] THEN
8992   MP_TAC(ISPEC `t:real^N->bool` DIAMETER_SUBSET_CBALL_NONEMPTY) THEN
8993   ANTS_TAC THENL
8994    [ASM_MESON_TAC[BOUNDED_SUBSET; COMPACT_IMP_BOUNDED]; ALL_TAC] THEN
8995   DISCH_THEN(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
8996   FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
8997   ANTS_TAC THENL [ASM SET_TAC[]; MATCH_MP_TAC MONO_EXISTS] THEN
8998   X_GEN_TAC `b:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
8999   MATCH_MP_TAC SUBSET_TRANS THEN
9000   EXISTS_TAC `cball(x:real^N,diameter(t:real^N->bool))` THEN
9001   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUBSET_TRANS THEN
9002   EXISTS_TAC `ball(x:real^N,e)` THEN ASM_REWRITE_TAC[] THEN
9003   REWRITE_TAC[SUBSET; IN_CBALL; IN_BALL] THEN
9004   MAP_EVERY UNDISCH_TAC [`&0 < e`; `diameter(t:real^N->bool) <= e / &2`] THEN
9005   NORM_ARITH_TAC);;
9006
9007 (* ------------------------------------------------------------------------- *)
9008 (* Related results with closure as the conclusion.                           *)
9009 (* ------------------------------------------------------------------------- *)
9010
9011 let CLOSED_SCALING = prove
9012  (`!s:real^N->bool c. closed s ==> closed (IMAGE (\x. c % x) s)`,
9013   REPEAT GEN_TAC THEN
9014   ASM_CASES_TAC `s :real^N->bool = {}` THEN
9015   ASM_REWRITE_TAC[CLOSED_EMPTY; IMAGE_CLAUSES] THEN
9016   ASM_CASES_TAC `c = &0` THENL
9017    [SUBGOAL_THEN `IMAGE (\x:real^N. c % x) s = {(vec 0)}`
9018      (fun th -> REWRITE_TAC[th; CLOSED_SING]) THEN
9019     ASM_REWRITE_TAC[EXTENSION; IN_IMAGE; IN_SING; VECTOR_MUL_LZERO] THEN
9020     ASM_MESON_TAC[MEMBER_NOT_EMPTY];
9021     ALL_TAC] THEN
9022   REWRITE_TAC[CLOSED_SEQUENTIAL_LIMITS; IN_IMAGE; SKOLEM_THM] THEN
9023   STRIP_TAC THEN X_GEN_TAC `x:num->real^N` THEN X_GEN_TAC `l:real^N` THEN
9024   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
9025   DISCH_THEN(X_CHOOSE_THEN `y:num->real^N` MP_TAC) THEN
9026   REWRITE_TAC[FORALL_AND_THM] THEN STRIP_TAC THEN
9027   EXISTS_TAC `inv(c) % l :real^N` THEN
9028   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; VECTOR_MUL_LID] THEN
9029   FIRST_X_ASSUM MATCH_MP_TAC THEN EXISTS_TAC `\n:num. inv(c) % x n:real^N` THEN
9030   ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
9031    [ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; VECTOR_MUL_LID];
9032     MATCH_MP_TAC LIM_CMUL THEN
9033     FIRST_ASSUM(fun th -> REWRITE_TAC[SYM(SPEC_ALL th)]) THEN
9034     ASM_REWRITE_TAC[ETA_AX]]);;
9035
9036 let CLOSED_NEGATIONS = prove
9037  (`!s:real^N->bool. closed s ==> closed (IMAGE (--) s)`,
9038   REPEAT GEN_TAC THEN
9039   SUBGOAL_THEN `IMAGE (--) s = IMAGE (\x:real^N. --(&1) % x) s`
9040   SUBST1_TAC THEN SIMP_TAC[CLOSED_SCALING] THEN
9041   REWRITE_TAC[VECTOR_ARITH `--(&1) % x = --x`] THEN REWRITE_TAC[ETA_AX]);;
9042
9043 let COMPACT_CLOSED_SUMS = prove
9044  (`!s:real^N->bool t.
9045         compact s /\ closed t ==> closed {x + y | x IN s /\ y IN t}`,
9046   REPEAT GEN_TAC THEN
9047   REWRITE_TAC[compact; IN_ELIM_THM; CLOSED_SEQUENTIAL_LIMITS] THEN
9048   STRIP_TAC THEN X_GEN_TAC `f:num->real^N` THEN X_GEN_TAC `l:real^N` THEN
9049   REWRITE_TAC[SKOLEM_THM; FORALL_AND_THM] THEN
9050   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
9051   DISCH_THEN(X_CHOOSE_THEN `a:num->real^N` MP_TAC) THEN
9052   DISCH_THEN(X_CHOOSE_THEN `b:num->real^N` STRIP_ASSUME_TAC) THEN
9053   FIRST_X_ASSUM(MP_TAC o check(is_imp o concl) o SPEC `a:num->real^N`) THEN
9054   ASM_REWRITE_TAC[] THEN
9055   DISCH_THEN(X_CHOOSE_THEN `la:real^N` (X_CHOOSE_THEN `sub:num->num`
9056         STRIP_ASSUME_TAC)) THEN
9057   MAP_EVERY EXISTS_TAC [`la:real^N`; `l - la:real^N`] THEN
9058   ASM_REWRITE_TAC[VECTOR_ARITH `a + (b - a) = b:real^N`] THEN
9059   FIRST_X_ASSUM MATCH_MP_TAC THEN
9060   EXISTS_TAC `\n. (f o (sub:num->num)) n - (a o sub) n:real^N` THEN
9061   CONJ_TAC THENL [ASM_REWRITE_TAC[VECTOR_ADD_SUB; o_THM]; ALL_TAC] THEN
9062   MATCH_MP_TAC LIM_SUB THEN ASM_SIMP_TAC[LIM_SUBSEQUENCE; ETA_AX]);;
9063
9064 let CLOSED_COMPACT_SUMS = prove
9065  (`!s:real^N->bool t.
9066         closed s /\ compact t ==> closed {x + y | x IN s /\ y IN t}`,
9067   REPEAT GEN_TAC THEN
9068   SUBGOAL_THEN `{x + y:real^N | x IN s /\ y IN t} = {y + x | y IN t /\ x IN s}`
9069   SUBST1_TAC THEN  SIMP_TAC[COMPACT_CLOSED_SUMS] THEN
9070   REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN MESON_TAC[VECTOR_ADD_SYM]);;
9071
9072 let COMPACT_CLOSED_DIFFERENCES = prove
9073  (`!s:real^N->bool t.
9074         compact s /\ closed t ==> closed {x - y | x IN s /\ y IN t}`,
9075   REPEAT STRIP_TAC THEN
9076   SUBGOAL_THEN `{x - y | x:real^N IN s /\ y IN t} =
9077                 {x + y | x IN s /\ y IN (IMAGE (--) t)}`
9078     (fun th -> ASM_SIMP_TAC[th; COMPACT_CLOSED_SUMS; CLOSED_NEGATIONS]) THEN
9079   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE] THEN
9080   ONCE_REWRITE_TAC[VECTOR_ARITH `(x:real^N = --y) <=> (y = --x)`] THEN
9081   SIMP_TAC[VECTOR_SUB; GSYM CONJ_ASSOC; UNWIND_THM2] THEN
9082   MESON_TAC[VECTOR_NEG_NEG]);;
9083
9084 let CLOSED_COMPACT_DIFFERENCES = prove
9085  (`!s:real^N->bool t.
9086         closed s /\ compact t ==> closed {x - y | x IN s /\ y IN t}`,
9087   REPEAT STRIP_TAC THEN
9088   SUBGOAL_THEN `{x - y | x:real^N IN s /\ y IN t} =
9089                 {x + y | x IN s /\ y IN (IMAGE (--) t)}`
9090     (fun th -> ASM_SIMP_TAC[th; CLOSED_COMPACT_SUMS; COMPACT_NEGATIONS]) THEN
9091   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_IMAGE] THEN
9092   ONCE_REWRITE_TAC[VECTOR_ARITH `(x:real^N = --y) <=> (y = --x)`] THEN
9093   SIMP_TAC[VECTOR_SUB; GSYM CONJ_ASSOC; UNWIND_THM2] THEN
9094   MESON_TAC[VECTOR_NEG_NEG]);;
9095
9096 let CLOSED_TRANSLATION_EQ = prove
9097  (`!a s. closed (IMAGE (\x:real^N. a + x) s) <=> closed s`,
9098   REWRITE_TAC[closed] THEN GEOM_TRANSLATE_TAC[]);;
9099
9100 let CLOSED_TRANSLATION = prove
9101  (`!s a:real^N. closed s ==> closed (IMAGE (\x. a + x) s)`,
9102   REWRITE_TAC[CLOSED_TRANSLATION_EQ]);;
9103
9104 add_translation_invariants [CLOSED_TRANSLATION_EQ];;
9105
9106 let COMPLETE_TRANSLATION_EQ = prove
9107  (`!a s. complete(IMAGE (\x:real^N. a + x) s) <=> complete s`,
9108   REWRITE_TAC[COMPLETE_EQ_CLOSED; CLOSED_TRANSLATION_EQ]);;
9109
9110 add_translation_invariants [COMPLETE_TRANSLATION_EQ];;
9111
9112 let TRANSLATION_UNIV = prove
9113  (`!a. IMAGE (\x. a + x) (:real^N) = (:real^N)`,
9114   CONV_TAC(ONCE_DEPTH_CONV SYM_CONV) THEN GEOM_TRANSLATE_TAC[]);;
9115
9116 let TRANSLATION_DIFF = prove
9117  (`!s t:real^N->bool.
9118         IMAGE (\x. a + x) (s DIFF t) =
9119         (IMAGE (\x. a + x) s) DIFF (IMAGE (\x. a + x) t)`,
9120   REWRITE_TAC[EXTENSION; IN_DIFF; IN_IMAGE] THEN
9121   ONCE_REWRITE_TAC[VECTOR_ARITH `x:real^N = a + y <=> y = x - a`] THEN
9122   REWRITE_TAC[UNWIND_THM2]);;
9123
9124 let CLOSURE_TRANSLATION = prove
9125  (`!a s. closure(IMAGE (\x:real^N. a + x) s) = IMAGE (\x. a + x) (closure s)`,
9126   REWRITE_TAC[CLOSURE_INTERIOR] THEN GEOM_TRANSLATE_TAC[]);;
9127
9128 add_translation_invariants [CLOSURE_TRANSLATION];;
9129
9130 let FRONTIER_TRANSLATION = prove
9131  (`!a s. frontier(IMAGE (\x:real^N. a + x) s) = IMAGE (\x. a + x) (frontier s)`,
9132   REWRITE_TAC[frontier] THEN GEOM_TRANSLATE_TAC[]);;
9133
9134 add_translation_invariants [FRONTIER_TRANSLATION];;
9135
9136 (* ------------------------------------------------------------------------- *)
9137 (* Separation between points and sets.                                       *)
9138 (* ------------------------------------------------------------------------- *)
9139
9140 let SEPARATE_POINT_CLOSED = prove
9141  (`!s a:real^N.
9142         closed s /\ ~(a IN s)
9143         ==> ?d. &0 < d /\ !x. x IN s ==> d <= dist(a,x)`,
9144   REPEAT STRIP_TAC THEN
9145   ASM_CASES_TAC `s:real^N->bool = {}` THENL
9146    [EXISTS_TAC `&1` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY; REAL_LT_01];
9147     ALL_TAC] THEN
9148   MP_TAC(ISPECL [`s:real^N->bool`; `a:real^N`] DISTANCE_ATTAINS_INF) THEN
9149   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `b:real^N` THEN
9150   STRIP_TAC THEN EXISTS_TAC `dist(a:real^N,b)` THEN
9151   ASM_MESON_TAC[DIST_POS_LT]);;
9152
9153 let SEPARATE_COMPACT_CLOSED = prove
9154  (`!s t:real^N->bool.
9155         compact s /\ closed t /\ s INTER t = {}
9156         ==> ?d. &0 < d /\ !x y. x IN s /\ y IN t ==> d <= dist(x,y)`,
9157   REPEAT STRIP_TAC THEN
9158   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN t}`; `vec 0:real^N`]
9159                 SEPARATE_POINT_CLOSED) THEN
9160   ASM_SIMP_TAC[COMPACT_CLOSED_DIFFERENCES; IN_ELIM_THM] THEN
9161   REWRITE_TAC[VECTOR_ARITH `vec 0 = x - y <=> x = y`] THEN
9162   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
9163   MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN
9164   MESON_TAC[NORM_ARITH `dist(vec 0,x - y) = dist(x,y)`]);;
9165
9166 let SEPARATE_CLOSED_COMPACT = prove
9167  (`!s t:real^N->bool.
9168         closed s /\ compact t /\ s INTER t = {}
9169         ==> ?d. &0 < d /\ !x y. x IN s /\ y IN t ==> d <= dist(x,y)`,
9170   ONCE_REWRITE_TAC[DIST_SYM; INTER_COMM] THEN
9171   MESON_TAC[SEPARATE_COMPACT_CLOSED]);;
9172
9173 (* ------------------------------------------------------------------------- *)
9174 (* Representing sets as the union of a chain of compact sets.                *)
9175 (* ------------------------------------------------------------------------- *)
9176
9177 let CLOSED_UNION_COMPACT_SUBSETS = prove
9178  (`!s. closed s
9179        ==> ?f:num->real^N->bool.
9180                 (!n. compact(f n)) /\
9181                 (!n. (f n) SUBSET s) /\
9182                 (!n. (f n) SUBSET f(n + 1)) /\
9183                 UNIONS {f n | n IN (:num)} = s /\
9184                 (!k. compact k /\ k SUBSET s
9185                      ==> ?N. !n. n >= N ==> k SUBSET (f n))`,
9186   REPEAT STRIP_TAC THEN
9187   EXISTS_TAC `\n. s INTER cball(vec 0:real^N,&n)` THEN
9188   ASM_SIMP_TAC[INTER_SUBSET; COMPACT_CBALL; CLOSED_INTER_COMPACT] THEN
9189   REPEAT CONJ_TAC THENL
9190    [GEN_TAC THEN MATCH_MP_TAC(SET_RULE
9191      `t SUBSET u ==> s INTER t SUBSET s INTER u`) THEN
9192     REWRITE_TAC[SUBSET_BALLS; DIST_REFL; GSYM REAL_OF_NUM_ADD] THEN
9193     REAL_ARITH_TAC;
9194     REWRITE_TAC[EXTENSION; UNIONS_GSPEC; IN_ELIM_THM; IN_UNIV; IN_INTER] THEN
9195     X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_CBALL_0] THEN
9196     MESON_TAC[REAL_ARCH_SIMPLE];
9197     X_GEN_TAC `k:real^N->bool` THEN SIMP_TAC[SUBSET_INTER] THEN
9198     REPEAT STRIP_TAC THEN
9199     FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN DISCH_THEN
9200      (MP_TAC o SPEC `vec 0:real^N` o MATCH_MP BOUNDED_SUBSET_CBALL) THEN
9201     DISCH_THEN(X_CHOOSE_THEN `r:real` STRIP_ASSUME_TAC) THEN
9202     MP_TAC(ISPEC `r:real` REAL_ARCH_SIMPLE) THEN MATCH_MP_TAC MONO_EXISTS THEN
9203     X_GEN_TAC `N:num` THEN REWRITE_TAC[GSYM REAL_OF_NUM_GE] THEN
9204
9205     REPEAT STRIP_TAC THEN
9206     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
9207         SUBSET_TRANS)) THEN
9208     REWRITE_TAC[SUBSET_BALLS; DIST_REFL] THEN ASM_REAL_ARITH_TAC]);;
9209
9210 let OPEN_UNION_COMPACT_SUBSETS = prove
9211  (`!s. open s
9212        ==> ?f:num->real^N->bool.
9213                 (!n. compact(f n)) /\
9214                 (!n. (f n) SUBSET s) /\
9215                 (!n. (f n) SUBSET interior(f(n + 1))) /\
9216                 UNIONS {f n | n IN (:num)} = s /\
9217                 (!k. compact k /\ k SUBSET s
9218                      ==> ?N. !n. n >= N ==> k SUBSET (f n))`,
9219   GEN_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THENL
9220    [DISCH_TAC THEN EXISTS_TAC `(\n. {}):num->real^N->bool` THEN
9221     ASM_SIMP_TAC[EMPTY_SUBSET; SUBSET_EMPTY; COMPACT_EMPTY] THEN
9222     REWRITE_TAC[EXTENSION; UNIONS_GSPEC; IN_ELIM_THM; NOT_IN_EMPTY];
9223     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
9224     DISCH_THEN(X_CHOOSE_TAC `a:real^N`) THEN STRIP_TAC] THEN
9225   MATCH_MP_TAC(MESON[]
9226    `(!f. p1 f /\ p3 f /\ p4 f ==> p5 f) /\
9227     (?f. p1 f /\ p2 f /\ p3 f /\ (p2 f ==> p4 f))
9228     ==> ?f. p1 f /\ p2 f /\ p3 f /\ p4 f /\ p5 f`) THEN
9229   CONJ_TAC THENL
9230    [X_GEN_TAC `f:num->real^N->bool` THEN STRIP_TAC THEN
9231     FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
9232     X_GEN_TAC `k:real^N->bool` THEN STRIP_TAC THEN
9233     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL]) THEN
9234     DISCH_THEN(MP_TAC o SPEC `{interior(f n):real^N->bool | n IN (:num)}`) THEN
9235     REWRITE_TAC[FORALL_IN_GSPEC; OPEN_INTERIOR] THEN ANTS_TAC THENL
9236      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
9237         SUBSET_TRANS)) THEN
9238       REWRITE_TAC[SUBSET; UNIONS_GSPEC; IN_ELIM_THM] THEN ASM SET_TAC[];
9239       ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN
9240       REWRITE_TAC[SIMPLE_IMAGE; EXISTS_FINITE_SUBSET_IMAGE] THEN
9241       REWRITE_TAC[SUBSET_UNIV] THEN
9242       DISCH_THEN(X_CHOOSE_THEN `i:num->bool` STRIP_ASSUME_TAC) THEN
9243       FIRST_ASSUM(MP_TAC o SPEC `\n:num. n` o
9244         MATCH_MP UPPER_BOUND_FINITE_SET) THEN
9245       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
9246       REWRITE_TAC[GE] THEN DISCH_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
9247       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
9248         SUBSET_TRANS)) THEN
9249       REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_IMAGE] THEN
9250       X_GEN_TAC `m:num` THEN DISCH_TAC THEN MATCH_MP_TAC SUBSET_TRANS THEN
9251       EXISTS_TAC `(f:num->real^N->bool) m` THEN
9252       REWRITE_TAC[INTERIOR_SUBSET] THEN
9253       SUBGOAL_THEN `!m n. m <= n ==> (f:num->real^N->bool) m SUBSET f n`
9254        (fun th -> ASM_MESON_TAC[th; LE_TRANS]) THEN
9255       MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
9256       ASM_MESON_TAC[SUBSET; ADD1; INTERIOR_SUBSET]];
9257     EXISTS_TAC
9258      `\n. cball(a,&n) DIFF
9259          {x + e | x IN (:real^N) DIFF s /\ e IN ball(vec 0,inv(&n + &1))}` THEN
9260     REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
9261      [X_GEN_TAC `n:num` THEN MATCH_MP_TAC COMPACT_DIFF THEN
9262       SIMP_TAC[COMPACT_CBALL; OPEN_SUMS; OPEN_BALL];
9263       GEN_TAC THEN MATCH_MP_TAC(SET_RULE
9264        `(UNIV DIFF s) SUBSET t ==> c DIFF t SUBSET s`) THEN
9265       REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
9266       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
9267       MAP_EVERY EXISTS_TAC [`x:real^N`; `vec 0:real^N`] THEN
9268       ASM_REWRITE_TAC[VECTOR_ADD_RID; CENTRE_IN_BALL; REAL_LT_INV_EQ] THEN
9269       REAL_ARITH_TAC;
9270       GEN_TAC THEN REWRITE_TAC[INTERIOR_DIFF] THEN MATCH_MP_TAC(SET_RULE
9271        `s SUBSET s' /\ t' SUBSET t ==> (s DIFF t) SUBSET (s' DIFF t')`) THEN
9272       CONJ_TAC THENL
9273        [REWRITE_TAC[INTERIOR_CBALL; SUBSET; IN_BALL; IN_CBALL] THEN
9274         REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN REAL_ARITH_TAC;
9275         MATCH_MP_TAC SUBSET_TRANS THEN
9276         EXISTS_TAC `{x + e | x IN (:real^N) DIFF s /\
9277                              e IN cball(vec 0,inv(&n + &2))}` THEN
9278         CONJ_TAC THENL
9279          [MATCH_MP_TAC CLOSURE_MINIMAL THEN
9280           ASM_SIMP_TAC[CLOSED_COMPACT_SUMS; COMPACT_CBALL;
9281                        GSYM OPEN_CLOSED] THEN
9282           MATCH_MP_TAC(SET_RULE
9283            `t SUBSET t'
9284             ==> {f x y | x IN s /\ y IN t} SUBSET
9285                 {f x y | x IN s /\ y IN t'}`) THEN
9286           REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL; GSYM REAL_OF_NUM_ADD] THEN
9287           REAL_ARITH_TAC;
9288           MATCH_MP_TAC(SET_RULE
9289            `t SUBSET t'
9290             ==> {f x y | x IN s /\ y IN t} SUBSET
9291                 {f x y | x IN s /\ y IN t'}`) THEN
9292           REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL; GSYM REAL_OF_NUM_ADD] THEN
9293           GEN_TAC THEN MATCH_MP_TAC(REAL_ARITH
9294            `a < b ==> x <= a ==> x < b`) THEN
9295           MATCH_MP_TAC REAL_LT_INV2 THEN REAL_ARITH_TAC]];
9296       DISCH_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
9297       ASM_REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC] THEN
9298       REWRITE_TAC[SUBSET; UNIONS_GSPEC; IN_UNIV; IN_ELIM_THM] THEN
9299       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_DIFF] THEN
9300       REWRITE_TAC[IN_ELIM_THM; IN_UNIV; IN_BALL_0] THEN
9301       REWRITE_TAC[VECTOR_ARITH `x:real^N = y + e <=> e = x - y`] THEN
9302       REWRITE_TAC[TAUT `(p /\ q) /\ r <=> r /\ p /\ q`; UNWIND_THM2] THEN
9303       REWRITE_TAC[MESON[] `~(?x. ~P x /\ Q x) <=> !x. Q x ==> P x`] THEN
9304       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
9305       DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
9306       ASM_REWRITE_TAC[SUBSET; IN_BALL; dist] THEN
9307       DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
9308       FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [REAL_ARCH_INV]) THEN
9309       DISCH_THEN(X_CHOOSE_THEN `N1:num` STRIP_ASSUME_TAC) THEN
9310       MP_TAC(ISPEC `norm(x - a:real^N)` REAL_ARCH_SIMPLE) THEN
9311       DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN EXISTS_TAC `N1 + N2:num` THEN
9312       CONJ_TAC THENL
9313        [REWRITE_TAC[IN_CBALL] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
9314         UNDISCH_TAC `norm(x - a:real^N) <= &N2` THEN
9315         REWRITE_TAC[dist; GSYM REAL_OF_NUM_ADD] THEN REAL_ARITH_TAC;
9316         REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
9317         SUBGOAL_THEN `inv(&(N1 + N2) + &1) <= inv(&N1)` MP_TAC THENL
9318          [MATCH_MP_TAC REAL_LE_INV2 THEN
9319           ASM_SIMP_TAC[REAL_OF_NUM_LT; LE_1] THEN
9320           REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN REAL_ARITH_TAC;
9321           ASM_REAL_ARITH_TAC]]]]);;
9322
9323 (* ------------------------------------------------------------------------- *)
9324 (* A cute way of denoting open and closed intervals using overloading.       *)
9325 (* ------------------------------------------------------------------------- *)
9326
9327 let open_interval = new_definition
9328   `open_interval(a:real^N,b:real^N) =
9329         {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
9330                         ==> a$i < x$i /\ x$i < b$i}`;;
9331
9332 let closed_interval = new_definition
9333   `closed_interval(l:(real^N#real^N)list) =
9334          {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
9335                          ==> FST(HD l)$i <= x$i /\ x$i <= SND(HD l)$i}`;;
9336
9337 make_overloadable "interval" `:A`;;
9338
9339 overload_interface("interval",`open_interval`);;
9340 overload_interface("interval",`closed_interval`);;
9341
9342 let interval = prove
9343  (`(interval (a,b) = {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
9344                                      ==> a$i < x$i /\ x$i < b$i}) /\
9345    (interval [a,b] = {x:real^N | !i. 1 <= i /\ i <= dimindex(:N)
9346                                      ==> a$i <= x$i /\ x$i <= b$i})`,
9347   REWRITE_TAC[open_interval; closed_interval; HD; FST; SND]);;
9348
9349 let IN_INTERVAL = prove
9350  (`(!x:real^N.
9351         x IN interval (a,b) <=>
9352                 !i. 1 <= i /\ i <= dimindex(:N)
9353                     ==> a$i < x$i /\ x$i < b$i) /\
9354    (!x:real^N.
9355         x IN interval [a,b] <=>
9356                 !i. 1 <= i /\ i <= dimindex(:N)
9357                     ==> a$i <= x$i /\ x$i <= b$i)`,
9358   REWRITE_TAC[interval; IN_ELIM_THM]);;
9359
9360 let IN_INTERVAL_REFLECT = prove
9361  (`(!a b x. (--x) IN interval[--b,--a] <=> x IN interval[a,b]) /\
9362    (!a b x. (--x) IN interval(--b,--a) <=> x IN interval(a,b))`,
9363   SIMP_TAC[IN_INTERVAL; REAL_LT_NEG2; REAL_LE_NEG2; VECTOR_NEG_COMPONENT] THEN
9364   MESON_TAC[]);;
9365
9366 let REFLECT_INTERVAL = prove
9367  (`(!a b:real^N. IMAGE (--) (interval[a,b]) = interval[--b,--a]) /\
9368    (!a b:real^N. IMAGE (--) (interval(a,b)) = interval(--b,--a))`,
9369   REPEAT STRIP_TAC THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
9370   REWRITE_TAC[IN_INTERVAL_REFLECT] THEN MESON_TAC[VECTOR_NEG_NEG]);;
9371
9372 let INTERVAL_EQ_EMPTY = prove
9373  (`((interval [a:real^N,b] = {}) <=>
9374     ?i. 1 <= i /\ i <= dimindex(:N) /\ b$i < a$i) /\
9375    ((interval (a:real^N,b) = {}) <=>
9376     ?i. 1 <= i /\ i <= dimindex(:N) /\ b$i <= a$i)`,
9377   REWRITE_TAC[EXTENSION; IN_INTERVAL; NOT_IN_EMPTY] THEN
9378   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; GSYM CONJ_ASSOC] THEN
9379   CONJ_TAC THEN EQ_TAC THENL
9380    [MESON_TAC[REAL_LE_REFL; REAL_NOT_LE];
9381     MESON_TAC[REAL_LE_TRANS; REAL_NOT_LE];
9382     ALL_TAC;
9383     MESON_TAC[REAL_LT_TRANS; REAL_NOT_LT]] THEN
9384   SUBGOAL_THEN `!a b. ?c. a < b ==> a < c /\ c < b`
9385   (MP_TAC o REWRITE_RULE[SKOLEM_THM]) THENL
9386    [MESON_TAC[REAL_LT_BETWEEN]; ALL_TAC] THEN
9387   DISCH_THEN(X_CHOOSE_TAC `mid:real->real->real`) THEN
9388   DISCH_THEN(MP_TAC o SPEC
9389    `(lambda i. mid ((a:real^N)$i) ((b:real^N)$i)):real^N`) THEN
9390   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> ~(a /\ b ==> ~c)`] THEN
9391   SIMP_TAC[LAMBDA_BETA] THEN ASM_MESON_TAC[REAL_NOT_LT]);;
9392
9393 let INTERVAL_NE_EMPTY = prove
9394  (`(~(interval [a:real^N,b] = {}) <=>
9395     !i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= b$i) /\
9396    (~(interval (a:real^N,b) = {}) <=>
9397     !i. 1 <= i /\ i <= dimindex(:N) ==> a$i < b$i)`,
9398   REWRITE_TAC[INTERVAL_EQ_EMPTY] THEN MESON_TAC[REAL_NOT_LE]);;
9399
9400 let SUBSET_INTERVAL_IMP = prove
9401  (`((!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)
9402     ==> interval[c,d] SUBSET interval[a:real^N,b]) /\
9403    ((!i. 1 <= i /\ i <= dimindex(:N) ==> a$i < c$i /\ d$i < b$i)
9404     ==> interval[c,d] SUBSET interval(a:real^N,b)) /\
9405    ((!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)
9406     ==> interval(c,d) SUBSET interval[a:real^N,b]) /\
9407    ((!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)
9408     ==> interval(c,d) SUBSET interval(a:real^N,b))`,
9409   REWRITE_TAC[SUBSET; IN_INTERVAL] THEN REPEAT CONJ_TAC THEN
9410   DISCH_TAC THEN GEN_TAC THEN POP_ASSUM MP_TAC THEN
9411   REWRITE_TAC[IMP_IMP; AND_FORALL_THM] THEN MATCH_MP_TAC MONO_FORALL THEN
9412   GEN_TAC THEN DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
9413   ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
9414
9415 let INTERVAL_SING = prove
9416  (`interval[a,a] = {a} /\ interval(a,a) = {}`,
9417   REWRITE_TAC[EXTENSION; IN_SING; NOT_IN_EMPTY; IN_INTERVAL] THEN
9418   REWRITE_TAC[REAL_LE_ANTISYM; REAL_LT_ANTISYM; CART_EQ; EQ_SYM_EQ] THEN
9419   MESON_TAC[DIMINDEX_GE_1; LE_REFL]);;
9420
9421 let SUBSET_INTERVAL = prove
9422  (`(interval[c,d] SUBSET interval[a:real^N,b] <=>
9423         (!i. 1 <= i /\ i <= dimindex(:N) ==> c$i <= d$i)
9424         ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)) /\
9425    (interval[c,d] SUBSET interval(a:real^N,b) <=>
9426         (!i. 1 <= i /\ i <= dimindex(:N) ==> c$i <= d$i)
9427         ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> a$i < c$i /\ d$i < b$i)) /\
9428    (interval(c,d) SUBSET interval[a:real^N,b] <=>
9429         (!i. 1 <= i /\ i <= dimindex(:N) ==> c$i < d$i)
9430         ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i)) /\
9431    (interval(c,d) SUBSET interval(a:real^N,b) <=>
9432         (!i. 1 <= i /\ i <= dimindex(:N) ==> c$i < d$i)
9433         ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> a$i <= c$i /\ d$i <= b$i))`,
9434   let lemma = prove
9435    (`(!x:real^N. (!i. 1 <= i /\ i <= dimindex(:N) ==> Q i (x$i))
9436                  ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> R i (x$i)))
9437      ==> (!i. 1 <= i /\ i <= dimindex(:N) ==> ?y. Q i y)
9438          ==> !i y. 1 <= i /\ i <= dimindex(:N) /\ Q i y ==> R i y`,
9439     DISCH_TAC THEN REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM] THEN
9440     DISCH_THEN(X_CHOOSE_THEN `f:num->real` STRIP_ASSUME_TAC) THEN
9441     REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o
9442      SPEC `(lambda j. if j = i then y else f j):real^N`) THEN
9443     SIMP_TAC[LAMBDA_BETA] THEN ASM_MESON_TAC[]) in
9444   REPEAT STRIP_TAC THEN
9445   (MATCH_MP_TAC(TAUT
9446     `(~q ==> p) /\ (q ==> (p <=> r)) ==> (p <=> q ==> r)`) THEN
9447    CONJ_TAC THENL
9448     [DISCH_TAC THEN MATCH_MP_TAC(SET_RULE `s = {} ==> s SUBSET t`) THEN
9449      REWRITE_TAC[INTERVAL_EQ_EMPTY] THEN ASM_MESON_TAC[REAL_NOT_LT];
9450      ALL_TAC] THEN
9451    DISCH_TAC THEN EQ_TAC THEN REWRITE_TAC[SUBSET_INTERVAL_IMP] THEN
9452    REWRITE_TAC[SUBSET; IN_INTERVAL] THEN
9453    DISCH_THEN(MP_TAC o MATCH_MP lemma) THEN ANTS_TAC THENL
9454     [ASM_MESON_TAC[REAL_LT_BETWEEN; REAL_LE_BETWEEN]; ALL_TAC] THEN
9455    MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `i:num` THEN
9456    DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
9457    FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN
9458    ASM_REWRITE_TAC[] THEN POP_ASSUM_LIST(K ALL_TAC) THEN STRIP_TAC)
9459   THENL
9460    [ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_REFL];
9461     ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_REFL];
9462     ALL_TAC; ALL_TAC] THEN
9463   (REPEAT STRIP_TAC THENL
9464     [FIRST_X_ASSUM(MP_TAC o SPEC
9465       `((c:real^N)$i + min ((a:real^N)$i) ((d:real^N)$i)) / &2`) THEN
9466      POP_ASSUM MP_TAC THEN REAL_ARITH_TAC;
9467      FIRST_X_ASSUM(MP_TAC o SPEC
9468       `(max ((b:real^N)$i) ((c:real^N)$i) + (d:real^N)$i) / &2`) THEN
9469      POP_ASSUM MP_TAC THEN REAL_ARITH_TAC]));;
9470
9471 let DISJOINT_INTERVAL = prove
9472  (`!a b c d:real^N.
9473         (interval[a,b] INTER interval[c,d] = {} <=>
9474           ?i. 1 <= i /\ i <= dimindex(:N) /\
9475               (b$i < a$i \/ d$i < c$i \/ b$i < c$i \/ d$i < a$i)) /\
9476         (interval[a,b] INTER interval(c,d) = {} <=>
9477           ?i. 1 <= i /\ i <= dimindex(:N) /\
9478               (b$i < a$i \/ d$i <= c$i \/ b$i <= c$i \/ d$i <= a$i)) /\
9479         (interval(a,b) INTER interval[c,d] = {} <=>
9480           ?i. 1 <= i /\ i <= dimindex(:N) /\
9481               (b$i <= a$i \/ d$i < c$i \/ b$i <= c$i \/ d$i <= a$i)) /\
9482         (interval(a,b) INTER interval(c,d) = {} <=>
9483           ?i. 1 <= i /\ i <= dimindex(:N) /\
9484               (b$i <= a$i \/ d$i <= c$i \/ b$i <= c$i \/ d$i <= a$i))`,
9485   REWRITE_TAC[EXTENSION; IN_INTER; IN_INTERVAL; NOT_IN_EMPTY] THEN
9486   REWRITE_TAC[AND_FORALL_THM; NOT_FORALL_THM] THEN
9487   REWRITE_TAC[TAUT `~((p ==> q) /\ (p ==> r)) <=> p /\ (~q \/ ~r)`] THEN
9488   REWRITE_TAC[DE_MORGAN_THM] THEN REPEAT STRIP_TAC THEN
9489   (EQ_TAC THENL
9490     [DISCH_THEN(MP_TAC o SPEC
9491       `(lambda i. (max ((a:real^N)$i) ((c:real^N)$i) +
9492                    min ((b:real^N)$i) ((d:real^N)$i)) / &2):real^N`) THEN
9493      MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
9494      DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN
9495      ASM_SIMP_TAC[LAMBDA_BETA] THEN REAL_ARITH_TAC;
9496      DISCH_THEN(fun th -> GEN_TAC THEN MP_TAC th) THEN
9497      MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN SIMP_TAC[] THEN
9498      REAL_ARITH_TAC]));;
9499
9500 let ENDS_IN_INTERVAL = prove
9501  (`(!a b. a IN interval[a,b] <=> ~(interval[a,b] = {})) /\
9502    (!a b. b IN interval[a,b] <=> ~(interval[a,b] = {})) /\
9503    (!a b. ~(a IN interval(a,b))) /\
9504    (!a b. ~(b IN interval(a,b)))`,
9505   REWRITE_TAC[IN_INTERVAL; INTERVAL_NE_EMPTY] THEN
9506   REWRITE_TAC[REAL_LE_REFL; REAL_LT_REFL] THEN
9507   MESON_TAC[DIMINDEX_GE_1; LE_REFL]);;
9508
9509 let ENDS_IN_UNIT_INTERVAL = prove
9510  (`vec 0 IN interval[vec 0,vec 1] /\
9511    vec 1 IN interval[vec 0,vec 1] /\
9512    ~(vec 0 IN interval(vec 0,vec 1)) /\
9513    ~(vec 1 IN interval(vec 0,vec 1))`,
9514   REWRITE_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY; VEC_COMPONENT] THEN
9515   REWRITE_TAC[REAL_POS]);;
9516
9517 let INTER_INTERVAL = prove
9518  (`interval[a,b] INTER interval[c,d] =
9519         interval[(lambda i. max (a$i) (c$i)),(lambda i. min (b$i) (d$i))]`,
9520   REWRITE_TAC[EXTENSION; IN_INTER; IN_INTERVAL] THEN
9521   SIMP_TAC[LAMBDA_BETA; REAL_MAX_LE; REAL_LE_MIN] THEN MESON_TAC[]);;
9522
9523 let INTERVAL_OPEN_SUBSET_CLOSED = prove
9524  (`!a b. interval(a,b) SUBSET interval[a,b]`,
9525   REWRITE_TAC[SUBSET; IN_INTERVAL] THEN MESON_TAC[REAL_LT_IMP_LE]);;
9526
9527 let OPEN_INTERVAL_LEMMA = prove
9528  (`!a b x. a < x /\ x < b
9529            ==> ?d. &0 < d /\ !x'. abs(x' - x) < d ==> a < x' /\ x' < b`,
9530   REPEAT STRIP_TAC THEN
9531   EXISTS_TAC `min (x - a) (b - x)` THEN REWRITE_TAC[REAL_LT_MIN] THEN
9532   ASM_REAL_ARITH_TAC);;
9533
9534 let OPEN_INTERVAL = prove
9535  (`!a:real^N b. open(interval (a,b))`,
9536   REPEAT GEN_TAC THEN REWRITE_TAC[open_def; interval; IN_ELIM_THM] THEN
9537   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
9538   SUBGOAL_THEN `!i. 1 <= i /\ i <= dimindex(:N)
9539                     ==> ?d. &0 < d /\
9540                             !x'. abs(x' - (x:real^N)$i) < d
9541                                  ==> (a:real^N)$i < x' /\ x' < (b:real^N)$i`
9542   MP_TAC THENL [ASM_SIMP_TAC[OPEN_INTERVAL_LEMMA]; ALL_TAC] THEN
9543   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
9544   REWRITE_TAC[SKOLEM_THM] THEN
9545   DISCH_THEN(X_CHOOSE_THEN `d:num->real` STRIP_ASSUME_TAC) THEN
9546   EXISTS_TAC `inf (IMAGE d (1..dimindex(:N)))` THEN
9547   SIMP_TAC[REAL_LT_INF_FINITE; FINITE_IMAGE; FINITE_NUMSEG;
9548            IMAGE_EQ_EMPTY; NOT_INSERT_EMPTY; NUMSEG_EMPTY;
9549            ARITH_RULE `n < 1 <=> (n = 0)`; DIMINDEX_NONZERO] THEN
9550   REWRITE_TAC[FORALL_IN_IMAGE; IN_NUMSEG; dist] THEN
9551   ASM_MESON_TAC[COMPONENT_LE_NORM; REAL_LET_TRANS; VECTOR_SUB_COMPONENT]);;
9552
9553 let CLOSED_INTERVAL = prove
9554  (`!a:real^N b. closed(interval [a,b])`,
9555   REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE; IN_INTERVAL] THEN
9556   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THENL
9557    [FIRST_X_ASSUM(MP_TAC o SPEC `(a:real^N)$i - (x:real^N)$i`);
9558     FIRST_X_ASSUM(MP_TAC o SPEC `(x:real^N)$i - (b:real^N)$i`)] THEN
9559   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
9560   DISCH_THEN(X_CHOOSE_THEN `z:real^N` MP_TAC) THEN
9561   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
9562   REWRITE_TAC[dist; REAL_NOT_LT] THEN
9563   MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `abs((z - x :real^N)$i)` THEN
9564   ASM_SIMP_TAC[COMPONENT_LE_NORM] THEN
9565   ASM_SIMP_TAC[VECTOR_SUB_COMPONENT] THEN
9566   ASM_SIMP_TAC[REAL_ARITH `x < a /\ a <= z ==> a - x <= abs(z - x)`;
9567                REAL_ARITH `z <= b /\ b < x ==> x - b <= abs(z - x)`]);;
9568
9569 let INTERIOR_CLOSED_INTERVAL = prove
9570  (`!a:real^N b. interior(interval [a,b]) = interval (a,b)`,
9571   REPEAT GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
9572    [ALL_TAC;
9573     MATCH_MP_TAC INTERIOR_MAXIMAL THEN
9574     REWRITE_TAC[INTERVAL_OPEN_SUBSET_CLOSED; OPEN_INTERVAL]] THEN
9575   REWRITE_TAC[interior; SUBSET; IN_INTERVAL; IN_ELIM_THM] THEN
9576   X_GEN_TAC `x:real^N` THEN
9577   DISCH_THEN(X_CHOOSE_THEN `s:real^N->bool` STRIP_ASSUME_TAC) THEN
9578   X_GEN_TAC `i:num` THEN STRIP_TAC THEN
9579   ASM_SIMP_TAC[REAL_LT_LE] THEN REPEAT STRIP_TAC THEN
9580   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [open_def]) THEN
9581   DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
9582   DISCH_THEN(X_CHOOSE_THEN `e:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THENL
9583    [(let t = `x - (e / &2) % basis i :real^N` in
9584      DISCH_THEN(MP_TAC o SPEC t) THEN FIRST_X_ASSUM(MP_TAC o SPEC t));
9585     (let t = `x + (e / &2) % basis i :real^N` in
9586      DISCH_THEN(MP_TAC o SPEC t) THEN FIRST_X_ASSUM(MP_TAC o SPEC t))] THEN
9587   REWRITE_TAC[dist; VECTOR_ADD_SUB; VECTOR_ARITH `x - y - x = --y:real^N`] THEN
9588   ASM_SIMP_TAC[NORM_MUL; NORM_BASIS; NORM_NEG; REAL_MUL_RID;
9589                REAL_ARITH `&0 < e ==> abs(e / &2) < e`] THEN
9590   MATCH_MP_TAC(TAUT `~b ==> (a ==> b) ==> ~a`) THEN
9591   REWRITE_TAC[NOT_FORALL_THM] THEN EXISTS_TAC `i:num` THEN
9592   ASM_SIMP_TAC[DE_MORGAN_THM; VECTOR_SUB_COMPONENT; VECTOR_ADD_COMPONENT] THENL
9593    [DISJ1_TAC THEN REWRITE_TAC[REAL_ARITH `a <= a - b <=> ~(&0 < b)`];
9594     DISJ2_TAC THEN REWRITE_TAC[REAL_ARITH `a + b <= a <=> ~(&0 < b)`]] THEN
9595   ASM_SIMP_TAC[VECTOR_MUL_COMPONENT; basis; LAMBDA_BETA; REAL_MUL_RID] THEN
9596   ASM_REWRITE_TAC[REAL_HALF]);;
9597
9598 let INTERIOR_INTERVAL = prove
9599  (`(!a b. interior(interval[a,b]) = interval(a,b)) /\
9600    (!a b. interior(interval(a,b)) = interval(a,b))`,
9601   SIMP_TAC[INTERIOR_CLOSED_INTERVAL; INTERIOR_OPEN; OPEN_INTERVAL]);;
9602
9603 let BOUNDED_CLOSED_INTERVAL = prove
9604  (`!a b:real^N. bounded (interval [a,b])`,
9605   REPEAT STRIP_TAC THEN REWRITE_TAC[bounded; interval] THEN
9606   EXISTS_TAC `sum(1..dimindex(:N))
9607                  (\i. abs((a:real^N)$i) + abs((b:real^N)$i))` THEN
9608   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN
9609   STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN
9610   EXISTS_TAC `sum(1..dimindex(:N)) (\i. abs((x:real^N)$i))` THEN
9611   REWRITE_TAC[NORM_LE_L1] THEN MATCH_MP_TAC SUM_LE THEN
9612   ASM_SIMP_TAC[FINITE_NUMSEG; IN_NUMSEG; REAL_ARITH
9613    `a <= x /\ x <= b ==> abs(x) <= abs(a) + abs(b)`]);;
9614
9615 let BOUNDED_INTERVAL = prove
9616  (`(!a b. bounded (interval [a,b])) /\ (!a b. bounded (interval (a,b)))`,
9617   MESON_TAC[BOUNDED_CLOSED_INTERVAL; BOUNDED_SUBSET;
9618             INTERVAL_OPEN_SUBSET_CLOSED]);;
9619
9620 let NOT_INTERVAL_UNIV = prove
9621  (`(!a b. ~(interval[a,b] = UNIV)) /\
9622    (!a b. ~(interval(a,b) = UNIV))`,
9623   MESON_TAC[BOUNDED_INTERVAL; NOT_BOUNDED_UNIV]);;
9624
9625 let COMPACT_INTERVAL = prove
9626  (`!a b. compact (interval [a,b])`,
9627   SIMP_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_INTERVAL; CLOSED_INTERVAL]);;
9628
9629 let OPEN_INTERVAL_MIDPOINT = prove
9630  (`!a b:real^N.
9631         ~(interval(a,b) = {}) ==> (inv(&2) % (a + b)) IN interval(a,b)`,
9632   REWRITE_TAC[INTERVAL_NE_EMPTY; IN_INTERVAL] THEN
9633   SIMP_TAC[VECTOR_MUL_COMPONENT; VECTOR_ADD_COMPONENT] THEN
9634   REPEAT GEN_TAC THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
9635   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN REAL_ARITH_TAC);;
9636
9637 let OPEN_CLOSED_INTERVAL_CONVEX = prove
9638  (`!a b x y:real^N e.
9639         x IN interval(a,b) /\ y IN interval[a,b] /\ &0 < e /\ e <= &1
9640         ==> (e % x + (&1 - e) % y) IN interval(a,b)`,
9641   REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT
9642    `(c /\ d ==> a /\ b ==> e) ==> a /\ b /\ c /\ d ==> e`) THEN
9643   STRIP_TAC THEN REWRITE_TAC[IN_INTERVAL; AND_FORALL_THM] THEN
9644   SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN
9645   MATCH_MP_TAC MONO_FORALL THEN
9646   GEN_TAC THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
9647   ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
9648   SUBST1_TAC(REAL_ARITH `(a:real^N)$i = e * a$i + (&1 - e) * a$i`) THEN
9649   SUBST1_TAC(REAL_ARITH `(b:real^N)$i = e * b$i + (&1 - e) * b$i`) THEN
9650   CONJ_TAC THEN MATCH_MP_TAC REAL_LTE_ADD2 THEN
9651   ASM_SIMP_TAC[REAL_LT_LMUL_EQ; REAL_LE_LMUL; REAL_SUB_LE]);;
9652
9653 let CLOSURE_OPEN_INTERVAL = prove
9654  (`!a b:real^N.
9655      ~(interval(a,b) = {}) ==> closure(interval(a,b)) = interval[a,b]`,
9656   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
9657    [MATCH_MP_TAC CLOSURE_MINIMAL THEN
9658     REWRITE_TAC[INTERVAL_OPEN_SUBSET_CLOSED; CLOSED_INTERVAL];
9659     ALL_TAC] THEN
9660   REWRITE_TAC[SUBSET; closure; IN_UNION] THEN X_GEN_TAC `x:real^N` THEN
9661   DISCH_TAC THEN MATCH_MP_TAC(TAUT `(~b ==> c) ==> b \/ c`) THEN DISCH_TAC THEN
9662   REWRITE_TAC[IN_ELIM_THM; LIMPT_SEQUENTIAL] THEN
9663   ABBREV_TAC `(c:real^N) = inv(&2) % (a + b)` THEN
9664   EXISTS_TAC `\n. (x:real^N) + inv(&n + &1) % (c - x)` THEN CONJ_TAC THENL
9665    [X_GEN_TAC `n:num` THEN REWRITE_TAC[IN_DELETE] THEN
9666     REWRITE_TAC[VECTOR_ARITH `x + a = x <=> a = vec 0`] THEN
9667     REWRITE_TAC[VECTOR_MUL_EQ_0; REAL_INV_EQ_0] THEN
9668     REWRITE_TAC[VECTOR_SUB_EQ; REAL_ARITH `~(&n + &1 = &0)`] THEN
9669     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[OPEN_INTERVAL_MIDPOINT]] THEN
9670     REWRITE_TAC[VECTOR_ARITH `x + a % (y - x) = a % y + (&1 - a) % x`] THEN
9671     MATCH_MP_TAC OPEN_CLOSED_INTERVAL_CONVEX THEN
9672     CONJ_TAC THENL [ASM_MESON_TAC[OPEN_INTERVAL_MIDPOINT]; ALL_TAC] THEN
9673     ASM_REWRITE_TAC[REAL_LT_INV_EQ; REAL_ARITH `&0 < &n + &1`] THEN
9674     MATCH_MP_TAC REAL_INV_LE_1 THEN REAL_ARITH_TAC;
9675     ALL_TAC] THEN
9676   GEN_REWRITE_TAC LAND_CONV [VECTOR_ARITH `x:real^N = x + &0 % (c - x)`] THEN
9677   MATCH_MP_TAC LIM_ADD THEN REWRITE_TAC[LIM_CONST] THEN
9678   MATCH_MP_TAC LIM_VMUL THEN REWRITE_TAC[LIM_CONST] THEN
9679   REWRITE_TAC[LIM_SEQUENTIALLY; o_THM; DIST_LIFT; REAL_SUB_RZERO] THEN
9680   X_GEN_TAC `e:real` THEN GEN_REWRITE_TAC LAND_CONV [REAL_ARCH_INV] THEN
9681   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
9682   STRIP_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
9683   REWRITE_TAC[REAL_ABS_INV] THEN MATCH_MP_TAC REAL_LET_TRANS THEN
9684   EXISTS_TAC `inv(&N)` THEN ASM_REWRITE_TAC[] THEN
9685   MATCH_MP_TAC REAL_LE_INV2 THEN UNDISCH_TAC `N:num <= n` THEN
9686   UNDISCH_TAC `~(N = 0)` THEN
9687   REWRITE_TAC[GSYM LT_NZ; GSYM REAL_OF_NUM_LE; GSYM REAL_OF_NUM_LT] THEN
9688   REAL_ARITH_TAC);;
9689
9690 let CLOSURE_INTERVAL = prove
9691  (`(!a b. closure(interval[a,b]) = interval[a,b]) /\
9692    (!a b. closure(interval(a,b)) =
9693           if interval(a,b) = {} then {} else interval[a,b])`,
9694   SIMP_TAC[CLOSURE_CLOSED; CLOSED_INTERVAL] THEN REPEAT GEN_TAC THEN
9695   COND_CASES_TAC THEN ASM_SIMP_TAC[CLOSURE_OPEN_INTERVAL; CLOSURE_EMPTY]);;
9696
9697 let BOUNDED_SUBSET_OPEN_INTERVAL_SYMMETRIC = prove
9698  (`!s:real^N->bool. bounded s ==> ?a. s SUBSET interval(--a,a)`,
9699   REWRITE_TAC[BOUNDED_POS; LEFT_IMP_EXISTS_THM] THEN
9700   MAP_EVERY X_GEN_TAC [`s:real^N->bool`; `B:real`] THEN STRIP_TAC THEN
9701   EXISTS_TAC `(lambda i. B + &1):real^N` THEN
9702   REWRITE_TAC[SUBSET] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
9703   SIMP_TAC[IN_INTERVAL; LAMBDA_BETA; REAL_BOUNDS_LT; VECTOR_NEG_COMPONENT] THEN
9704   ASM_MESON_TAC[COMPONENT_LE_NORM;
9705                 REAL_ARITH `x <= y ==> a <= x ==> a < y + &1`]);;
9706
9707 let BOUNDED_SUBSET_OPEN_INTERVAL = prove
9708  (`!s:real^N->bool. bounded s ==> ?a b. s SUBSET interval(a,b)`,
9709   MESON_TAC[BOUNDED_SUBSET_OPEN_INTERVAL_SYMMETRIC]);;
9710
9711 let BOUNDED_SUBSET_CLOSED_INTERVAL_SYMMETRIC = prove
9712  (`!s:real^N->bool. bounded s ==> ?a. s SUBSET interval[--a,a]`,
9713   GEN_TAC THEN
9714   DISCH_THEN(MP_TAC o MATCH_MP BOUNDED_SUBSET_OPEN_INTERVAL_SYMMETRIC) THEN
9715   MATCH_MP_TAC MONO_EXISTS THEN
9716   SIMP_TAC[IN_BALL; IN_INTERVAL; SUBSET; REAL_LT_IMP_LE]);;
9717
9718 let BOUNDED_SUBSET_CLOSED_INTERVAL = prove
9719  (`!s:real^N->bool. bounded s ==> ?a b. s SUBSET interval[a,b]`,
9720   MESON_TAC[BOUNDED_SUBSET_CLOSED_INTERVAL_SYMMETRIC]);;
9721
9722 let FRONTIER_CLOSED_INTERVAL = prove
9723  (`!a b. frontier(interval[a,b]) = interval[a,b] DIFF interval(a,b)`,
9724   SIMP_TAC[frontier; INTERIOR_CLOSED_INTERVAL; CLOSURE_CLOSED;
9725            CLOSED_INTERVAL]);;
9726
9727 let FRONTIER_OPEN_INTERVAL = prove
9728  (`!a b. frontier(interval(a,b)) =
9729                 if interval(a,b) = {} then {}
9730                 else interval[a,b] DIFF interval(a,b)`,
9731   REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[FRONTIER_EMPTY] THEN
9732   ASM_SIMP_TAC[frontier; CLOSURE_OPEN_INTERVAL; INTERIOR_OPEN;
9733                OPEN_INTERVAL]);;
9734
9735 let INTER_INTERVAL_MIXED_EQ_EMPTY = prove
9736  (`!a b c d:real^N.
9737         ~(interval(c,d) = {})
9738         ==> (interval(a,b) INTER interval[c,d] = {} <=>
9739              interval(a,b) INTER interval(c,d) = {})`,
9740   SIMP_TAC[GSYM CLOSURE_OPEN_INTERVAL; OPEN_INTER_CLOSURE_EQ_EMPTY;
9741            OPEN_INTERVAL]);;
9742
9743 let INTERVAL_TRANSLATION = prove
9744  (`(!c a b. interval[c + a,c + b] = IMAGE (\x. c + x) (interval[a,b])) /\
9745    (!c a b. interval(c + a,c + b) = IMAGE (\x. c + x) (interval(a,b)))`,
9746   REWRITE_TAC[interval] THEN CONJ_TAC THEN GEOM_TRANSLATE_TAC[] THEN
9747   REWRITE_TAC[VECTOR_ADD_COMPONENT; REAL_LT_LADD; REAL_LE_LADD]);;
9748
9749 add_translation_invariants
9750  [CONJUNCT1 INTERVAL_TRANSLATION; CONJUNCT2 INTERVAL_TRANSLATION];;
9751
9752 let EMPTY_AS_INTERVAL = prove
9753  (`{} = interval[vec 1,vec 0]`,
9754   SIMP_TAC[EXTENSION; NOT_IN_EMPTY; IN_INTERVAL; VEC_COMPONENT] THEN
9755   GEN_TAC THEN DISCH_THEN(MP_TAC o SPEC `1`) THEN
9756   REWRITE_TAC[LE_REFL; DIMINDEX_GE_1] THEN REAL_ARITH_TAC);;
9757
9758 let UNIT_INTERVAL_NONEMPTY = prove
9759  (`~(interval[vec 0:real^N,vec 1] = {}) /\
9760    ~(interval(vec 0:real^N,vec 1) = {})`,
9761   SIMP_TAC[INTERVAL_NE_EMPTY; VEC_COMPONENT; REAL_LT_01; REAL_POS]);;
9762
9763 let IMAGE_STRETCH_INTERVAL = prove
9764  (`!a b:real^N m.
9765     IMAGE (\x. lambda k. m(k) * x$k) (interval[a,b]) =
9766         if interval[a,b] = {} then {}
9767         else interval[(lambda k. min (m(k) * a$k) (m(k) * b$k)):real^N,
9768                       (lambda k. max (m(k) * a$k) (m(k) * b$k))]`,
9769   REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_SIMP_TAC[IMAGE_CLAUSES] THEN
9770   ASM_SIMP_TAC[EXTENSION; IN_IMAGE; CART_EQ; IN_INTERVAL; AND_FORALL_THM;
9771                TAUT `(a ==> b) /\ (a ==> c) <=> a ==> b /\ c`;
9772                 LAMBDA_BETA; GSYM LAMBDA_SKOLEM] THEN
9773   X_GEN_TAC `x:real^N` THEN MATCH_MP_TAC(MESON[]
9774    `(!x. p x ==> (q x <=> r x))
9775     ==> ((!x. p x ==> q x) <=> (!x. p x ==> r x))`) THEN
9776   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INTERVAL_NE_EMPTY]) THEN
9777   MATCH_MP_TAC MONO_FORALL THEN
9778   X_GEN_TAC `k:num` THEN ASM_CASES_TAC `1 <= k /\ k <= dimindex(:N)` THEN
9779   ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `(m:num->real) k = &0` THENL
9780    [ASM_REWRITE_TAC[REAL_MUL_LZERO; REAL_MAX_ACI; REAL_MIN_ACI] THEN
9781     ASM_MESON_TAC[REAL_LE_ANTISYM; REAL_LE_REFL];
9782     ALL_TAC] THEN
9783   ASM_SIMP_TAC[REAL_FIELD `~(m = &0) ==> (x = m * y <=> y = x / m)`] THEN
9784   REWRITE_TAC[UNWIND_THM2] THEN FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP
9785    (REAL_ARITH `~(z = &0) ==> &0 < z \/ &0 < --z`))
9786   THENL
9787    [ALL_TAC;
9788     ONCE_REWRITE_TAC[GSYM REAL_LE_NEG2] THEN
9789     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
9790     REWRITE_TAC[REAL_ARITH `--(max a b) = min (--a) (--b)`;
9791                 REAL_ARITH `--(min a b) = max (--a) (--b)`; real_div;
9792                 GSYM REAL_MUL_RNEG; GSYM REAL_INV_NEG] THEN
9793     REWRITE_TAC[GSYM real_div]] THEN
9794   ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ] THEN
9795   ASM_SIMP_TAC[real_min; real_max; REAL_LE_LMUL_EQ; REAL_LE_RMUL_EQ] THEN
9796   REAL_ARITH_TAC);;
9797
9798 let INTERVAL_IMAGE_STRETCH_INTERVAL = prove
9799  (`!a b:real^N m. ?u v:real^N.
9800      IMAGE (\x. lambda k. m k * x$k) (interval[a,b]) = interval[u,v]`,
9801   REWRITE_TAC[IMAGE_STRETCH_INTERVAL] THEN MESON_TAC[EMPTY_AS_INTERVAL]);;
9802
9803 let CLOSED_INTERVAL_IMAGE_UNIT_INTERVAL = prove
9804  (`!a b:real^N.
9805         ~(interval[a,b] = {})
9806         ==> interval[a,b] = IMAGE (\x:real^N. a + x)
9807                                   (IMAGE (\x. (lambda i. (b$i - a$i) * x$i))
9808                                          (interval[vec 0:real^N,vec 1]))`,
9809   REWRITE_TAC[INTERVAL_NE_EMPTY] THEN REPEAT STRIP_TAC THEN
9810   REWRITE_TAC[IMAGE_STRETCH_INTERVAL; UNIT_INTERVAL_NONEMPTY] THEN
9811   REWRITE_TAC[GSYM INTERVAL_TRANSLATION] THEN
9812   REWRITE_TAC[EXTENSION; IN_INTERVAL] THEN
9813   SIMP_TAC[LAMBDA_BETA; VECTOR_ADD_COMPONENT; VEC_COMPONENT] THEN
9814   GEN_TAC THEN REWRITE_TAC[REAL_MUL_RZERO; REAL_MUL_RID] THEN
9815   MATCH_MP_TAC(MESON[] `(!x. P x <=> Q x) ==> ((!x. P x) <=> (!x. Q x))`) THEN
9816   POP_ASSUM MP_TAC THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `i:num` THEN
9817   ASM_CASES_TAC `1 <= i /\ i <= dimindex(:N)` THEN ASM_REWRITE_TAC[] THEN
9818   REAL_ARITH_TAC);;
9819
9820 let SUMS_INTERVALS = prove
9821  (`(!a b c d:real^N.
9822         ~(interval[a,b] = {}) /\ ~(interval[c,d] = {})
9823         ==> {x + y | x IN interval[a,b] /\ y IN interval[c,d]} =
9824             interval[a+c,b+d]) /\
9825    (!a b c d:real^N.
9826         ~(interval(a,b) = {}) /\ ~(interval(c,d) = {})
9827         ==> {x + y | x IN interval(a,b) /\ y IN interval(c,d)} =
9828             interval(a+c,b+d))`,
9829   CONJ_TAC THEN REPEAT GEN_TAC THEN REWRITE_TAC[INTERVAL_NE_EMPTY] THEN
9830   STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_INTERVAL; IN_ELIM_THM] THEN
9831   REWRITE_TAC[TAUT `(a /\ b) /\ c <=> c /\ a /\ b`] THEN
9832   REWRITE_TAC[VECTOR_ARITH `x:real^N = y + z <=> z = x - y`] THEN
9833   REWRITE_TAC[UNWIND_THM2; VECTOR_ADD_COMPONENT; VECTOR_SUB_COMPONENT] THEN
9834   (X_GEN_TAC `x:real^N` THEN EQ_TAC THENL
9835    [DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC);
9836     DISCH_TAC THEN
9837     REWRITE_TAC[AND_FORALL_THM; GSYM LAMBDA_SKOLEM;
9838                 TAUT `(p ==> q) /\ (p ==> r) <=> p ==> q /\ r`] THEN
9839     REWRITE_TAC[REAL_ARITH
9840      `((a <= y /\ y <= b) /\ c <= x - y /\ x - y <= d <=>
9841        max a (x - d) <= y /\ y <= min b (x - c)) /\
9842       ((a < y /\ y < b) /\ c < x - y /\ x - y < d <=>
9843        max a (x - d) < y /\ y < min b (x - c))`] THEN
9844     REWRITE_TAC[GSYM REAL_LE_BETWEEN; GSYM REAL_LT_BETWEEN]] THEN
9845   X_GEN_TAC `i:num` THEN STRIP_TAC THEN
9846   REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `i:num`)) THEN
9847   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC));;
9848
9849 let PCROSS_INTERVAL = prove
9850  (`!a b:real^M c d:real^N.
9851         interval[a,b] PCROSS interval[c,d] =
9852         interval[pastecart a c,pastecart b d]`,
9853   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN
9854   REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN
9855   SIMP_TAC[IN_INTERVAL; pastecart; LAMBDA_BETA; DIMINDEX_FINITE_SUM] THEN
9856   MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^N`] THEN EQ_TAC THEN STRIP_TAC THENL
9857    [X_GEN_TAC `i:num` THEN STRIP_TAC THEN
9858     COND_CASES_TAC THEN ASM_SIMP_TAC[] THEN
9859     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC;
9860     CONJ_TAC THEN X_GEN_TAC `i:num` THEN STRIP_TAC THENL
9861      [FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN ASM_REWRITE_TAC[] THEN
9862       DISCH_THEN MATCH_MP_TAC THEN ASM_ARITH_TAC;
9863       FIRST_X_ASSUM(MP_TAC o SPEC `i + dimindex(:M)`) THEN
9864       COND_CASES_TAC THEN ASM_REWRITE_TAC[ADD_SUB] THENL
9865        [ASM_ARITH_TAC;
9866         DISCH_THEN MATCH_MP_TAC THEN ASM_ARITH_TAC]]]);;
9867
9868 let OPEN_CONTAINS_INTERVAL,OPEN_CONTAINS_OPEN_INTERVAL = (CONJ_PAIR o prove)
9869  (`(!s:real^N->bool.
9870         open s <=>
9871         !x. x IN s ==> ?a b. x IN interval(a,b) /\ interval[a,b] SUBSET s) /\
9872    (!s:real^N->bool.
9873         open s <=>
9874         !x. x IN s ==> ?a b. x IN interval(a,b) /\ interval(a,b) SUBSET s)`,
9875   REWRITE_TAC[AND_FORALL_THM] THEN GEN_TAC THEN
9876   MATCH_MP_TAC(TAUT
9877    `(q ==> r) /\ (r ==> p) /\ (p ==> q) ==> (p <=> q) /\ (p <=> r)`) THEN
9878   REPEAT CONJ_TAC THENL
9879    [MESON_TAC[SUBSET_TRANS; INTERVAL_OPEN_SUBSET_CLOSED];
9880     DISCH_TAC THEN REWRITE_TAC[OPEN_CONTAINS_BALL] THEN
9881     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
9882     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
9883     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
9884     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN
9885     MP_TAC(ISPEC `interval(a:real^N,b)` OPEN_CONTAINS_BALL) THEN
9886     REWRITE_TAC[OPEN_INTERVAL] THEN
9887     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
9888     MATCH_MP_TAC MONO_EXISTS THEN
9889     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
9890     ASM_MESON_TAC[SUBSET_TRANS; INTERVAL_OPEN_SUBSET_CLOSED];
9891     DISCH_TAC THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
9892     FIRST_ASSUM(MP_TAC o SPEC `x:real^N` o
9893       GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN
9894     ASM_REWRITE_TAC[] THEN
9895     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
9896     EXISTS_TAC `x - e / &(dimindex(:N)) % vec 1:real^N` THEN
9897     EXISTS_TAC `x + e / &(dimindex(:N)) % vec 1:real^N` THEN
9898     FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
9899      `b SUBSET s ==> x IN i /\ j SUBSET b ==> x IN i /\ j SUBSET s`)) THEN
9900     SIMP_TAC[IN_INTERVAL; VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT; IN_CBALL;
9901              VEC_COMPONENT; VECTOR_ADD_COMPONENT; SUBSET; REAL_MUL_RID] THEN
9902     REWRITE_TAC[REAL_ARITH `x - e < x /\ x < x + e <=> &0 < e`;
9903                 REAL_ARITH `x - e <= y /\ y <= x + e <=> abs(x - y) <= e`] THEN
9904     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1] THEN
9905     X_GEN_TAC `y:real^N` THEN REWRITE_TAC[GSYM VECTOR_SUB_COMPONENT] THEN
9906     DISCH_TAC THEN REWRITE_TAC[dist] THEN
9907     MATCH_MP_TAC REAL_LE_TRANS THEN
9908     EXISTS_TAC `sum(1..dimindex(:N)) (\i. abs((x - y:real^N)$i))` THEN
9909     REWRITE_TAC[NORM_LE_L1] THEN MATCH_MP_TAC SUM_BOUND_GEN THEN
9910     ASM_SIMP_TAC[CARD_NUMSEG_1; IN_NUMSEG; FINITE_NUMSEG] THEN
9911     REWRITE_TAC[NUMSEG_EMPTY; NOT_LT; DIMINDEX_GE_1]]);;
9912
9913 let DIAMETER_INTERVAL = prove
9914  (`(!a b:real^N.
9915         diameter(interval[a,b]) =
9916         if interval[a,b] = {} then &0 else norm(b - a)) /\
9917    (!a b:real^N.
9918         diameter(interval(a,b)) =
9919         if interval(a,b) = {} then &0 else norm(b - a))`,
9920   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN
9921   ASM_CASES_TAC `interval[a:real^N,b] = {}` THENL
9922    [ASM_MESON_TAC[INTERVAL_OPEN_SUBSET_CLOSED; SUBSET_EMPTY; DIAMETER_EMPTY];
9923     ASM_REWRITE_TAC[]] THEN
9924   MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
9925    [REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
9926     ASM_SIMP_TAC[DIAMETER_BOUNDED_BOUND;
9927                  ENDS_IN_INTERVAL; BOUNDED_INTERVAL] THEN
9928     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
9929      `diameter(cball(inv(&2) % (a + b):real^N,norm(b - a) / &2))` THEN
9930     CONJ_TAC THENL
9931      [MATCH_MP_TAC DIAMETER_SUBSET THEN REWRITE_TAC[BOUNDED_CBALL] THEN
9932       REWRITE_TAC[SUBSET; IN_INTERVAL; IN_CBALL] THEN
9933       GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[dist] THEN
9934       REWRITE_TAC[GSYM NORM_MUL; REAL_ARITH `x / &2 = abs(inv(&2)) * x`] THEN
9935       MATCH_MP_TAC NORM_LE_COMPONENTWISE THEN
9936       X_GEN_TAC `i:num` THEN DISCH_TAC THEN
9937       FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN
9938       ASM_REWRITE_TAC[VECTOR_ADD_COMPONENT; VECTOR_SUB_COMPONENT;
9939                       VECTOR_MUL_COMPONENT] THEN
9940       REAL_ARITH_TAC;
9941       REWRITE_TAC[DIAMETER_CBALL] THEN NORM_ARITH_TAC];
9942     DISCH_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[DIAMETER_EMPTY] THEN
9943     SUBGOAL_THEN `interval[a:real^N,b] = closure(interval(a,b))`
9944     SUBST_ALL_TAC THEN ASM_REWRITE_TAC[CLOSURE_INTERVAL] THEN
9945     ASM_MESON_TAC[DIAMETER_CLOSURE; BOUNDED_INTERVAL]]);;
9946
9947 (* ------------------------------------------------------------------------- *)
9948 (* Some special cases for intervals in R^1.                                  *)
9949 (* ------------------------------------------------------------------------- *)
9950
9951 let INTERVAL_CASES_1 = prove
9952  (`!x:real^1. x IN interval[a,b] ==> x IN interval(a,b) \/ (x = a) \/ (x = b)`,
9953   REWRITE_TAC[CART_EQ; IN_INTERVAL; FORALL_DIMINDEX_1] THEN REAL_ARITH_TAC);;
9954
9955 let IN_INTERVAL_1 = prove
9956  (`!a b x:real^1.
9957         (x IN interval[a,b] <=> drop a <= drop x /\ drop x <= drop b) /\
9958         (x IN interval(a,b) <=> drop a < drop x /\ drop x < drop b)`,
9959   REWRITE_TAC[IN_INTERVAL; drop; CONJ_ASSOC; DIMINDEX_1; LE_ANTISYM] THEN
9960   MESON_TAC[]);;
9961
9962 let INTERVAL_EQ_EMPTY_1 = prove
9963  (`!a b:real^1.
9964         (interval[a,b] = {} <=> drop b < drop a) /\
9965         (interval(a,b) = {} <=> drop b <= drop a)`,
9966   REWRITE_TAC[INTERVAL_EQ_EMPTY; drop; CONJ_ASSOC; DIMINDEX_1; LE_ANTISYM] THEN
9967   MESON_TAC[]);;
9968
9969 let INTERVAL_NE_EMPTY_1 = prove
9970  (`(!a b:real^1. ~(interval[a,b] = {}) <=> drop a <= drop b) /\
9971    (!a b:real^1. ~(interval(a,b) = {}) <=> drop a < drop b)`,
9972   REWRITE_TAC[INTERVAL_EQ_EMPTY_1] THEN REAL_ARITH_TAC);;
9973
9974 let SUBSET_INTERVAL_1 = prove
9975  (`!a b c d.
9976         (interval[a,b] SUBSET interval[c,d] <=>
9977                 drop b < drop a \/
9978                 drop c <= drop a /\ drop a <= drop b /\ drop b <= drop d) /\
9979         (interval[a,b] SUBSET interval(c,d) <=>
9980                 drop b < drop a \/
9981                 drop c < drop a /\ drop a <= drop b /\ drop b < drop d) /\
9982         (interval(a,b) SUBSET interval[c,d] <=>
9983                 drop b <= drop a \/
9984                 drop c <= drop a /\ drop a < drop b /\ drop b <= drop d) /\
9985         (interval(a,b) SUBSET interval(c,d) <=>
9986                 drop b <= drop a \/
9987                 drop c <= drop a /\ drop a < drop b /\ drop b <= drop d)`,
9988   REWRITE_TAC[SUBSET_INTERVAL; FORALL_1; DIMINDEX_1; drop] THEN
9989   REAL_ARITH_TAC);;
9990
9991 let EQ_INTERVAL_1 = prove
9992  (`!a b c d:real^1.
9993        (interval[a,b] = interval[c,d] <=>
9994           drop b < drop a /\ drop d < drop c \/
9995           drop a = drop c /\ drop b = drop d)`,
9996   REWRITE_TAC[SET_RULE `s = t <=> s SUBSET t /\ t SUBSET s`] THEN
9997   REWRITE_TAC[SUBSET_INTERVAL_1] THEN REAL_ARITH_TAC);;
9998
9999 let DISJOINT_INTERVAL_1 = prove
10000  (`!a b c d:real^1.
10001         (interval[a,b] INTER interval[c,d] = {} <=>
10002           drop b < drop a \/ drop d < drop c \/
10003           drop b < drop c \/ drop d < drop a) /\
10004         (interval[a,b] INTER interval(c,d) = {} <=>
10005           drop b < drop a \/ drop d <= drop c \/
10006           drop b <= drop c \/ drop d <= drop a) /\
10007         (interval(a,b) INTER interval[c,d] = {} <=>
10008           drop b <= drop a \/ drop d < drop c \/
10009           drop b <= drop c \/ drop d <= drop a) /\
10010         (interval(a,b) INTER interval(c,d) = {} <=>
10011           drop b <= drop a \/ drop d <= drop c \/
10012           drop b <= drop c \/ drop d <= drop a)`,
10013   REWRITE_TAC[DISJOINT_INTERVAL; CONJ_ASSOC; DIMINDEX_1; LE_ANTISYM;
10014               UNWIND_THM1; drop]);;
10015
10016 let OPEN_CLOSED_INTERVAL_1 = prove
10017  (`!a b:real^1. interval(a,b) = interval[a,b] DIFF {a,b}`,
10018   REWRITE_TAC[EXTENSION; IN_INTERVAL_1; IN_DIFF; IN_INSERT; NOT_IN_EMPTY] THEN
10019   REWRITE_TAC[GSYM DROP_EQ] THEN REAL_ARITH_TAC);;
10020
10021 let CLOSED_OPEN_INTERVAL_1 = prove
10022  (`!a b:real^1. drop a <= drop b ==> interval[a,b] = interval(a,b) UNION {a,b}`,
10023   REWRITE_TAC[EXTENSION; IN_INTERVAL_1; IN_UNION; IN_INSERT; NOT_IN_EMPTY] THEN
10024   REWRITE_TAC[GSYM DROP_EQ] THEN REAL_ARITH_TAC);;
10025
10026 let BALL_1 = prove
10027  (`!x:real^1 r. cball(x,r) = interval[x - lift r,x + lift r] /\
10028                 ball(x,r) = interval(x - lift r,x + lift r)`,
10029   REWRITE_TAC[EXTENSION; IN_BALL; IN_CBALL; IN_INTERVAL_1] THEN
10030   REWRITE_TAC[dist; NORM_REAL; GSYM drop; DROP_SUB; LIFT_DROP; DROP_ADD] THEN
10031   REAL_ARITH_TAC);;
10032
10033 let SPHERE_1 = prove
10034  (`!a:real^1 r. sphere(a,r) = if r < &0 then {} else {a - lift r,a + lift r}`,
10035   REPEAT GEN_TAC THEN REWRITE_TAC[sphere] THEN COND_CASES_TAC THEN
10036   REWRITE_TAC[DIST_REAL; GSYM drop; FORALL_DROP] THEN
10037   REWRITE_TAC[EXTENSION; IN_INSERT; NOT_IN_EMPTY; IN_ELIM_THM] THEN
10038   REWRITE_TAC[GSYM DROP_EQ; DROP_ADD; DROP_SUB; LIFT_DROP] THEN
10039   ASM_REAL_ARITH_TAC);;
10040
10041 let FINITE_SPHERE_1 = prove
10042  (`!a:real^1 r. FINITE(sphere(a,r))`,
10043   REPEAT GEN_TAC THEN REWRITE_TAC[SPHERE_1] THEN
10044   MESON_TAC[FINITE_INSERT; FINITE_EMPTY]);;
10045
10046 let FINITE_INTERVAL_1 = prove
10047  (`(!a b. FINITE(interval[a,b]) <=> drop b <= drop a) /\
10048    (!a b. FINITE(interval(a,b)) <=> drop b <= drop a)`,
10049   REWRITE_TAC[OPEN_CLOSED_INTERVAL_1] THEN
10050   REWRITE_TAC[SET_RULE `s DIFF {a,b} = s DELETE a DELETE b`] THEN
10051   REWRITE_TAC[FINITE_DELETE] THEN REPEAT GEN_TAC THEN
10052   SUBGOAL_THEN `interval[a,b] = IMAGE lift {x | drop a <= x /\ x <= drop b}`
10053   SUBST1_TAC THENL
10054    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
10055     CONJ_TAC THENL [MESON_TAC[LIFT_DROP]; ALL_TAC] THEN
10056     REWRITE_TAC[IN_INTERVAL_1; IN_ELIM_THM; LIFT_DROP];
10057     SIMP_TAC[FINITE_IMAGE_INJ_EQ; LIFT_EQ; FINITE_REAL_INTERVAL]]);;
10058
10059 let BALL_INTERVAL = prove
10060  (`!x:real^1 e. ball(x,e) = interval(x - lift e,x + lift e)`,
10061   REWRITE_TAC[EXTENSION; IN_BALL; IN_INTERVAL_1; DIST_REAL] THEN
10062   REWRITE_TAC[GSYM drop; DROP_SUB; DROP_ADD; LIFT_DROP] THEN REAL_ARITH_TAC);;
10063
10064 let CBALL_INTERVAL = prove
10065  (`!x:real^1 e. cball(x,e) = interval[x - lift e,x + lift e]`,
10066   REWRITE_TAC[EXTENSION; IN_CBALL; IN_INTERVAL_1; DIST_REAL] THEN
10067   REWRITE_TAC[GSYM drop; DROP_SUB; DROP_ADD; LIFT_DROP] THEN REAL_ARITH_TAC);;
10068
10069 let BALL_INTERVAL_0 = prove
10070  (`!e. ball(vec 0:real^1,e) = interval(--lift e,lift e)`,
10071   GEN_TAC THEN REWRITE_TAC[BALL_INTERVAL] THEN AP_TERM_TAC THEN
10072   BINOP_TAC THEN VECTOR_ARITH_TAC);;
10073
10074 let CBALL_INTERVAL_0 = prove
10075  (`!e. cball(vec 0:real^1,e) = interval[--lift e,lift e]`,
10076   GEN_TAC THEN REWRITE_TAC[CBALL_INTERVAL] THEN AP_TERM_TAC THEN
10077   AP_THM_TAC THEN AP_TERM_TAC THEN BINOP_TAC THEN VECTOR_ARITH_TAC);;
10078
10079 let INTER_INTERVAL_1 = prove
10080  (`!a b c d:real^1.
10081         interval[a,b] INTER interval[c,d] =
10082         interval[lift(max (drop a) (drop c)),lift(min (drop b) (drop d))]`,
10083   REWRITE_TAC[EXTENSION; IN_INTER; IN_INTERVAL_1; real_max; real_min] THEN
10084   REPEAT GEN_TAC THEN
10085   REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[LIFT_DROP]) THEN
10086   ASM_REAL_ARITH_TAC);;
10087
10088 let CLOSED_DIFF_OPEN_INTERVAL_1 = prove
10089  (`!a b:real^1.
10090         interval[a,b] DIFF interval(a,b) =
10091         if interval[a,b] = {} then {} else {a,b}`,
10092   REWRITE_TAC[EXTENSION; IN_DIFF; INTERVAL_EQ_EMPTY_1; IN_INTERVAL_1] THEN
10093   REPEAT GEN_TAC THEN COND_CASES_TAC THEN
10094   ASM_REWRITE_TAC[NOT_IN_EMPTY; IN_INSERT; NOT_IN_EMPTY] THEN
10095   REWRITE_TAC[GSYM DROP_EQ] THEN ASM_REAL_ARITH_TAC);;
10096
10097 (* ------------------------------------------------------------------------- *)
10098 (* Intervals in general, including infinite and mixtures of open and closed. *)
10099 (* ------------------------------------------------------------------------- *)
10100
10101 let is_interval = new_definition
10102   `is_interval(s:real^N->bool) <=>
10103         !a b x. a IN s /\ b IN s /\
10104                 (!i. 1 <= i /\ i <= dimindex(:N)
10105                      ==> (a$i <= x$i /\ x$i <= b$i) \/
10106                          (b$i <= x$i /\ x$i <= a$i))
10107                 ==> x IN s`;;
10108
10109 let IS_INTERVAL_INTERVAL = prove
10110  (`!a:real^N b. is_interval(interval (a,b)) /\ is_interval(interval [a,b])`,
10111   REWRITE_TAC[is_interval; IN_INTERVAL] THEN
10112   MESON_TAC[REAL_LT_TRANS; REAL_LE_TRANS; REAL_LET_TRANS; REAL_LTE_TRANS]);;
10113
10114 let IS_INTERVAL_EMPTY = prove
10115  (`is_interval {}`,
10116   REWRITE_TAC[is_interval; NOT_IN_EMPTY]);;
10117
10118 let IS_INTERVAL_UNIV = prove
10119  (`is_interval(UNIV:real^N->bool)`,
10120   REWRITE_TAC[is_interval; IN_UNIV]);;
10121
10122 let IS_INTERVAL_TRANSLATION_EQ = prove
10123  (`!a:real^N s. is_interval(IMAGE (\x. a + x) s) <=> is_interval s`,
10124   REWRITE_TAC[is_interval] THEN GEOM_TRANSLATE_TAC[] THEN
10125   REWRITE_TAC[VECTOR_ADD_COMPONENT; REAL_LT_LADD; REAL_LE_LADD]);;
10126
10127 add_translation_invariants [IS_INTERVAL_TRANSLATION_EQ];;
10128
10129 let IS_INTERVAL_TRANSLATION = prove
10130  (`!s a:real^N. is_interval s ==> is_interval(IMAGE (\x. a + x) s)`,
10131   REWRITE_TAC[IS_INTERVAL_TRANSLATION_EQ]);;
10132
10133 let IS_INTERVAL_POINTWISE = prove
10134  (`!s:real^N->bool x.
10135         is_interval s /\
10136         (!i. 1 <= i /\ i <= dimindex(:N) ==> ?a. a IN s /\ a$i = x$i)
10137         ==> x IN s`,
10138   REWRITE_TAC[is_interval] THEN REPEAT STRIP_TAC THEN
10139   SUBGOAL_THEN
10140     `!n. ?y:real^N. (!i. 1 <= i /\ i <= n ==> y$i = (x:real^N)$i) /\ y IN s`
10141   MP_TAC THENL
10142    [INDUCT_TAC THEN REWRITE_TAC[ARITH_RULE `~(1 <= i /\ i <= 0)`] THENL
10143      [ASM_MESON_TAC[DIMINDEX_GE_1; LE_REFL]; ALL_TAC] THEN
10144     FIRST_X_ASSUM(X_CHOOSE_TAC `y:real^N`) THEN
10145     ASM_CASES_TAC `SUC n <= dimindex(:N)` THENL
10146      [FIRST_X_ASSUM(MP_TAC o SPEC `SUC n`) THEN
10147       ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
10148       DISCH_THEN(X_CHOOSE_THEN `z:real^N` STRIP_ASSUME_TAC) THEN
10149       EXISTS_TAC
10150        `(lambda i. if i <= n then (y:real^N)$i else (z:real^N)$i):real^N` THEN
10151       CONJ_TAC THENL
10152        [X_GEN_TAC `i:num` THEN STRIP_TAC THEN
10153         SUBGOAL_THEN `i <= dimindex(:N)` ASSUME_TAC THENL
10154          [ASM_ARITH_TAC; ASM_SIMP_TAC[LAMBDA_BETA]] THEN
10155         COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
10156         SUBGOAL_THEN `i = SUC n` (fun th -> ASM_REWRITE_TAC[th]) THEN
10157         ASM_ARITH_TAC;
10158         FIRST_X_ASSUM(ASSUME_TAC o CONJUNCT2) THEN
10159         FIRST_X_ASSUM MATCH_MP_TAC THEN
10160         MAP_EVERY EXISTS_TAC [`y:real^N`; `z:real^N`] THEN
10161         ASM_SIMP_TAC[LAMBDA_BETA] THEN REAL_ARITH_TAC];
10162       EXISTS_TAC `y:real^N` THEN ASM_REWRITE_TAC[] THEN
10163       SUBGOAL_THEN `y:real^N = x` (fun th -> REWRITE_TAC[th]) THEN
10164       REWRITE_TAC[CART_EQ] THEN
10165       ASM_MESON_TAC[ARITH_RULE `i <= N /\ ~(SUC n <= N) ==> i <= n`]];
10166     DISCH_THEN(MP_TAC o SPEC `dimindex(:N)`) THEN
10167     REWRITE_TAC[GSYM CART_EQ] THEN MESON_TAC[]]);;
10168
10169 let IS_INTERVAL_COMPACT = prove
10170  (`!s:real^N->bool. is_interval s /\ compact s <=> ?a b. s = interval[a,b]`,
10171   GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
10172   ASM_SIMP_TAC[IS_INTERVAL_INTERVAL; COMPACT_INTERVAL] THEN
10173   ASM_CASES_TAC `s:real^N->bool = {}` THENL
10174    [ASM_MESON_TAC[EMPTY_AS_INTERVAL]; ALL_TAC] THEN
10175   EXISTS_TAC `(lambda i. inf { (x:real^N)$i | x IN s}):real^N` THEN
10176   EXISTS_TAC `(lambda i. sup { (x:real^N)$i | x IN s}):real^N` THEN
10177   SIMP_TAC[EXTENSION; IN_INTERVAL; LAMBDA_BETA] THEN X_GEN_TAC `x:real^N` THEN
10178   EQ_TAC THENL
10179    [DISCH_TAC THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
10180     MP_TAC(ISPEC `{ (x:real^N)$i | x IN s}` INF) THEN
10181     MP_TAC(ISPEC `{ (x:real^N)$i | x IN s}` SUP) THEN
10182     ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN
10183     ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
10184     FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_IMP_BOUNDED) THEN
10185     REWRITE_TAC[bounded] THEN
10186     ASM_MESON_TAC[COMPONENT_LE_NORM; REAL_LE_TRANS; MEMBER_NOT_EMPTY;
10187                   REAL_ARITH `abs(x) <= B ==> --B <= x /\ x <= B`];
10188     DISCH_TAC THEN MATCH_MP_TAC IS_INTERVAL_POINTWISE THEN
10189     ASM_REWRITE_TAC[] THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
10190     SUBGOAL_THEN
10191      `?a b:real^N. a IN s /\ b IN s /\ a$i <= (x:real^N)$i /\ x$i <= b$i`
10192     STRIP_ASSUME_TAC THENL
10193      [MP_TAC(ISPECL [`\x:real^N. x$i`; `s:real^N->bool`]
10194         CONTINUOUS_ATTAINS_INF) THEN
10195       ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT; o_DEF] THEN
10196       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN STRIP_TAC THEN
10197       MP_TAC(ISPECL [`\x:real^N. x$i`; `s:real^N->bool`]
10198         CONTINUOUS_ATTAINS_SUP) THEN
10199       ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT; o_DEF] THEN
10200       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
10201       ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THENL
10202        [EXISTS_TAC `inf {(x:real^N)$i | x IN s}` THEN ASM_SIMP_TAC[] THEN
10203         MATCH_MP_TAC REAL_LE_INF THEN ASM SET_TAC[];
10204         EXISTS_TAC `sup {(x:real^N)$i | x IN s}` THEN ASM_SIMP_TAC[] THEN
10205         MATCH_MP_TAC REAL_SUP_LE THEN ASM SET_TAC[]];
10206       EXISTS_TAC
10207        `(lambda j. if j = i then (x:real^N)$i else (a:real^N)$j):real^N` THEN
10208       ASM_SIMP_TAC[LAMBDA_BETA] THEN
10209       FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[is_interval]) THEN
10210       MAP_EVERY EXISTS_TAC
10211        [`a:real^N`;
10212         `(lambda j. if j = i then (b:real^N)$i else (a:real^N)$j):real^N`] THEN
10213       ASM_SIMP_TAC[LAMBDA_BETA] THEN CONJ_TAC THENL
10214        [FIRST_X_ASSUM(MATCH_MP_TAC o REWRITE_RULE[is_interval]) THEN
10215         MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real^N`] THEN
10216         ASM_SIMP_TAC[LAMBDA_BETA];
10217         ALL_TAC] THEN
10218       GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
10219       ASM_REAL_ARITH_TAC]]);;
10220
10221 let IS_INTERVAL_1 = prove
10222  (`!s:real^1->bool.
10223         is_interval s <=>
10224           !a b x. a IN s /\ b IN s /\ drop a <= drop x /\ drop x <= drop b
10225                   ==> x IN s`,
10226   REWRITE_TAC[is_interval; DIMINDEX_1; FORALL_1; GSYM drop] THEN
10227   REWRITE_TAC[FORALL_LIFT; LIFT_DROP] THEN MESON_TAC[]);;
10228
10229 let IS_INTERVAL_1_CASES = prove
10230  (`!s:real^1->bool.
10231         is_interval s <=>
10232         s = {} \/
10233         s = (:real^1) \/
10234         (?a. s = {x | a < drop x}) \/
10235         (?a. s = {x | a <= drop x}) \/
10236         (?b. s = {x | drop x <= b}) \/
10237         (?b. s = {x | drop x < b}) \/
10238         (?a b. s = {x | a < drop x /\ drop x < b}) \/
10239         (?a b. s = {x | a < drop x /\ drop x <= b}) \/
10240         (?a b. s = {x | a <= drop x /\ drop x < b}) \/
10241         (?a b. s = {x | a <= drop x /\ drop x <= b})`,
10242   GEN_TAC THEN REWRITE_TAC[IS_INTERVAL_1] THEN EQ_TAC THENL
10243    [DISCH_TAC;
10244     STRIP_TAC THEN ASM_REWRITE_TAC[IN_ELIM_THM; IN_UNIV; NOT_IN_EMPTY] THEN
10245     REAL_ARITH_TAC] THEN
10246   ASM_CASES_TAC `s:real^1->bool = {}` THEN ASM_REWRITE_TAC[] THEN
10247   MP_TAC(ISPEC `IMAGE drop s` SUP) THEN
10248   MP_TAC(ISPEC `IMAGE drop s` INF) THEN
10249   ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; FORALL_IN_IMAGE] THEN
10250   ASM_CASES_TAC `?a. !x. x IN s ==> a <= drop x` THEN
10251   ASM_CASES_TAC `?b. !x. x IN s ==> drop x <= b` THEN
10252   ASM_REWRITE_TAC[] THENL
10253    [STRIP_TAC THEN STRIP_TAC THEN
10254     MAP_EVERY ASM_CASES_TAC
10255      [`inf(IMAGE drop s) IN IMAGE drop s`; `sup(IMAGE drop s) IN IMAGE drop s`]
10256     THENL
10257      [REPLICATE_TAC 8 DISJ2_TAC;
10258       REPLICATE_TAC 7 DISJ2_TAC THEN DISJ1_TAC;
10259       REPLICATE_TAC 6 DISJ2_TAC THEN DISJ1_TAC;
10260       REPLICATE_TAC 5 DISJ2_TAC THEN DISJ1_TAC] THEN
10261     MAP_EVERY EXISTS_TAC [`inf(IMAGE drop s)`; `sup(IMAGE drop s)`];
10262     STRIP_TAC THEN ASM_CASES_TAC `inf(IMAGE drop s) IN IMAGE drop s` THENL
10263      [REPLICATE_TAC 2 DISJ2_TAC THEN DISJ1_TAC;
10264       DISJ2_TAC THEN DISJ1_TAC] THEN
10265     EXISTS_TAC `inf(IMAGE drop s)`;
10266     STRIP_TAC THEN ASM_CASES_TAC `sup(IMAGE drop s) IN IMAGE drop s` THENL
10267      [REPLICATE_TAC 3 DISJ2_TAC THEN DISJ1_TAC;
10268       REPLICATE_TAC 4 DISJ2_TAC THEN DISJ1_TAC] THEN
10269     EXISTS_TAC `sup(IMAGE drop s)`;
10270     DISJ1_TAC] THEN
10271   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_UNIV] THEN
10272   RULE_ASSUM_TAC(REWRITE_RULE[IN_IMAGE]) THEN
10273   REWRITE_TAC[GSYM REAL_NOT_LE] THEN
10274   ASM_MESON_TAC[REAL_LE_TRANS; REAL_LE_TOTAL; REAL_LE_ANTISYM]);;
10275
10276 let IS_INTERVAL_PCROSS = prove
10277  (`!s:real^M->bool t:real^N->bool.
10278         is_interval s /\ is_interval t ==> is_interval(s PCROSS t)`,
10279   REWRITE_TAC[is_interval; DIMINDEX_FINITE_SUM] THEN
10280   REWRITE_TAC[FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
10281   REPEAT GEN_TAC THEN
10282   MATCH_MP_TAC(MESON[]
10283    `(!a b a' b' x x'. P a b x /\ Q a' b' x' ==> R a b x a' b' x')
10284     ==> (!a b x. P a b x) /\ (!a' b' x'. Q a' b' x')
10285         ==> (!a a' b b' x x'. R a b x a' b' x')`) THEN
10286   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
10287   ASM_REWRITE_TAC[] THEN X_GEN_TAC `i:num` THEN STRIP_TAC THENL
10288    [FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN
10289     ASM_SIMP_TAC[pastecart; LAMBDA_BETA; DIMINDEX_FINITE_SUM;
10290                  ARITH_RULE `x:num <= m ==> x <= m + n`];
10291     FIRST_X_ASSUM(MP_TAC o SPEC `dimindex(:M) + i`) THEN
10292     ASM_SIMP_TAC[pastecart; LAMBDA_BETA; DIMINDEX_FINITE_SUM;
10293                  ARITH_RULE `x:num <= n ==> m + x <= m + n`;
10294                  ARITH_RULE `1 <= x ==> 1 <= m + x`] THEN
10295     COND_CASES_TAC THEN ASM_REWRITE_TAC[ADD_SUB2] THEN ASM_ARITH_TAC]);;
10296
10297 let IS_INTERVAL_PCROSS_EQ = prove
10298  (`!s:real^M->bool t:real^N->bool.
10299         is_interval(s PCROSS t) <=>
10300         s = {} \/ t = {} \/ is_interval s /\ is_interval t`,
10301   REPEAT GEN_TAC THEN
10302   ASM_CASES_TAC `s:real^M->bool = {}` THEN
10303   ASM_REWRITE_TAC[PCROSS_EMPTY; IS_INTERVAL_EMPTY] THEN
10304   ASM_CASES_TAC `t:real^N->bool = {}` THEN
10305   ASM_REWRITE_TAC[PCROSS_EMPTY; IS_INTERVAL_EMPTY] THEN
10306   EQ_TAC THEN REWRITE_TAC[IS_INTERVAL_PCROSS] THEN
10307   REWRITE_TAC[is_interval] THEN
10308   REWRITE_TAC[FORALL_PASTECART; PASTECART_IN_PCROSS] THEN
10309   STRIP_TAC THEN CONJ_TAC THENL
10310    [MAP_EVERY X_GEN_TAC [`a:real^M`; `b:real^M`; `x:real^M`] THEN
10311     STRIP_TAC THEN UNDISCH_TAC `~(t:real^N->bool = {})` THEN
10312     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
10313     DISCH_THEN(X_CHOOSE_TAC `y:real^N`) THEN
10314     FIRST_X_ASSUM(MP_TAC o SPECL
10315      [`a:real^M`; `y:real^N`; `b:real^M`;
10316       `y:real^N`; `x:real^M`; `y:real^N`]);
10317     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`; `x:real^N`] THEN
10318     STRIP_TAC THEN UNDISCH_TAC `~(s:real^M->bool = {})` THEN
10319     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN
10320     DISCH_THEN(X_CHOOSE_TAC `w:real^M`) THEN
10321     FIRST_X_ASSUM(MP_TAC o SPECL
10322      [`w:real^M`; `a:real^N`; `w:real^M`;
10323       `b:real^N`; `w:real^M`; `x:real^N`])] THEN
10324   ASM_REWRITE_TAC[] THEN DISCH_THEN MATCH_MP_TAC THEN
10325   SIMP_TAC[pastecart; LAMBDA_BETA] THEN
10326   REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_LE_REFL] THEN
10327   ASM_MESON_TAC[DIMINDEX_FINITE_SUM; ARITH_RULE
10328       `1 <= i /\ i <= m + n /\ ~(i <= m) ==> 1 <= i - m /\ i - m <= n`]);;
10329
10330 let IS_INTERVAL_INTER = prove
10331  (`!s t:real^N->bool.
10332         is_interval s /\ is_interval t ==> is_interval(s INTER t)`,
10333   REWRITE_TAC[is_interval; IN_INTER] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
10334   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`; `x:real^N`] THEN
10335   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
10336   MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real^N`] THEN ASM_REWRITE_TAC[]);;
10337
10338 let INTERVAL_SUBSET_IS_INTERVAL = prove
10339  (`!s a b:real^N.
10340      is_interval s
10341      ==> (interval[a,b] SUBSET s <=> interval[a,b] = {} \/ a IN s /\ b IN s)`,
10342   REWRITE_TAC[is_interval] THEN REPEAT STRIP_TAC THEN
10343   ASM_CASES_TAC `interval[a:real^N,b] = {}` THEN
10344   ASM_REWRITE_TAC[EMPTY_SUBSET] THEN
10345   EQ_TAC THENL [ASM_MESON_TAC[ENDS_IN_INTERVAL; SUBSET]; ALL_TAC] THEN
10346   REWRITE_TAC[SUBSET; IN_INTERVAL] THEN ASM_MESON_TAC[]);;
10347
10348 let INTERVAL_CONTAINS_COMPACT_NEIGHBOURHOOD = prove
10349  (`!s x:real^N.
10350         is_interval s /\ x IN s
10351         ==> ?a b d. &0 < d /\ x IN interval[a,b] /\
10352                     interval[a,b] SUBSET s /\
10353                     ball(x,d) INTER s SUBSET interval[a,b]`,
10354   REPEAT STRIP_TAC THEN ASM_SIMP_TAC[INTERVAL_SUBSET_IS_INTERVAL] THEN
10355   SUBGOAL_THEN
10356    `!i. 1 <= i /\ i <= dimindex(:N)
10357         ==> ?a. (?y. y IN s /\ y$i = a) /\
10358                 (a < x$i \/ a = (x:real^N)$i /\
10359                             !y:real^N. y IN s ==> a <= y$i)`
10360   MP_TAC THENL [ASM_MESON_TAC[REAL_NOT_LT]; REWRITE_TAC[LAMBDA_SKOLEM]] THEN
10361   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN STRIP_TAC THEN
10362   SUBGOAL_THEN
10363    `!i. 1 <= i /\ i <= dimindex(:N)
10364         ==> ?b. (?y. y IN s /\ y$i = b) /\
10365                 (x$i < b \/ b = (x:real^N)$i /\
10366                             !y:real^N. y IN s ==> y$i <= b)`
10367   MP_TAC THENL [ASM_MESON_TAC[REAL_NOT_LT]; REWRITE_TAC[LAMBDA_SKOLEM]] THEN
10368   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN STRIP_TAC THEN
10369   EXISTS_TAC `min (inf (IMAGE (\i. if a$i < x$i
10370                                    then (x:real^N)$i - (a:real^N)$i else &1)
10371                               (1..dimindex(:N))))
10372                   (inf (IMAGE (\i. if x$i < b$i
10373                                    then (b:real^N)$i - x$i else &1)
10374                               (1..dimindex(:N))))` THEN
10375   REWRITE_TAC[REAL_LT_MIN; SUBSET; IN_BALL; IN_INTER] THEN
10376   SIMP_TAC[REAL_LT_INF_FINITE; IMAGE_EQ_EMPTY; FINITE_IMAGE;
10377            FINITE_NUMSEG; NUMSEG_EMPTY; GSYM NOT_LE; DIMINDEX_GE_1] THEN
10378   REWRITE_TAC[FORALL_IN_IMAGE; IN_INTERVAL] THEN REPEAT CONJ_TAC THENL
10379    [MESON_TAC[REAL_SUB_LT; REAL_LT_01];
10380     MESON_TAC[REAL_SUB_LT; REAL_LT_01];
10381     ASM_MESON_TAC[REAL_LE_LT];
10382     DISJ2_TAC THEN CONJ_TAC THEN MATCH_MP_TAC IS_INTERVAL_POINTWISE THEN
10383     ASM_MESON_TAC[];
10384     X_GEN_TAC `y:real^N` THEN
10385     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
10386     REWRITE_TAC[AND_FORALL_THM] THEN MATCH_MP_TAC MONO_FORALL THEN
10387     X_GEN_TAC `i:num` THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
10388     ASM_REWRITE_TAC[IN_NUMSEG] THEN MATCH_MP_TAC MONO_AND THEN CONJ_TAC THEN
10389     (COND_CASES_TAC THENL [REWRITE_TAC[dist]; ASM_MESON_TAC[]]) THEN
10390     DISCH_TAC THEN MP_TAC(ISPECL [`x - y:real^N`; `i:num`]
10391       COMPONENT_LE_NORM) THEN
10392     ASM_REWRITE_TAC[VECTOR_SUB_COMPONENT] THEN ASM_REAL_ARITH_TAC]);;
10393
10394 let IS_INTERVAL_SUMS = prove
10395  (`!s t:real^N->bool.
10396         is_interval s /\ is_interval t
10397         ==> is_interval {x + y | x IN s /\ y IN t}`,
10398   REPEAT GEN_TAC THEN REWRITE_TAC[is_interval] THEN
10399   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
10400   REWRITE_TAC[FORALL_IN_GSPEC] THEN
10401   REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN
10402   REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC] THEN
10403   MAP_EVERY X_GEN_TAC
10404    [`a:real^N`; `a':real^N`; `b:real^N`; `b':real^N`; `y:real^N`] THEN
10405   DISCH_THEN(CONJUNCTS_THEN2
10406    (MP_TAC o SPECL [`a:real^N`; `b:real^N`]) MP_TAC) THEN
10407   DISCH_THEN(CONJUNCTS_THEN2
10408    (MP_TAC o SPECL [`a':real^N`; `b':real^N`]) STRIP_ASSUME_TAC) THEN
10409   ASM_REWRITE_TAC[IMP_IMP; IN_ELIM_THM] THEN  ONCE_REWRITE_TAC[CONJ_SYM] THEN
10410   ONCE_REWRITE_TAC[VECTOR_ARITH `z:real^N = x + y <=> y = z - x`] THEN
10411   REWRITE_TAC[UNWIND_THM2] THEN MATCH_MP_TAC(MESON[]
10412    `(?x. P x /\ Q(f x))
10413     ==> (!x. P x ==> x IN s) /\ (!x. Q x ==> x IN t)
10414         ==> ?x. x IN s /\ f x IN t`) THEN
10415   REWRITE_TAC[VECTOR_SUB_COMPONENT; AND_FORALL_THM;
10416               TAUT `(p ==> q) /\ (p ==> r) <=> p ==> q /\ r`] THEN
10417   REWRITE_TAC[GSYM LAMBDA_SKOLEM] THEN
10418   X_GEN_TAC `i:num` THEN STRIP_TAC THEN
10419   FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN
10420   ASM_REWRITE_TAC[VECTOR_ADD_COMPONENT] THEN
10421   REWRITE_TAC[REAL_ARITH
10422    `c <= y - x /\ y - x <= d <=> y - d <= x /\ x <= y - c`] THEN
10423   REWRITE_TAC[REAL_ARITH
10424   `a <= x /\ x <= b \/ b <= x /\ x <= a <=> min a b <= x /\ x <= max a b`] THEN
10425   ONCE_REWRITE_TAC[TAUT `(p /\ q) /\ (r /\ s) <=> (p /\ r) /\ (q /\ s)`] THEN
10426   REWRITE_TAC[GSYM REAL_LE_MIN; GSYM REAL_MAX_LE] THEN
10427   REWRITE_TAC[GSYM REAL_LE_BETWEEN] THEN REAL_ARITH_TAC);;
10428
10429 let IS_INTERVAL_SING = prove
10430  (`!a:real^N. is_interval {a}`,
10431   SIMP_TAC[is_interval; IN_SING; IMP_CONJ; CART_EQ; REAL_LE_ANTISYM]);;
10432
10433 let IS_INTERVAL_SCALING = prove
10434  (`!s:real^N->bool c. is_interval s ==> is_interval(IMAGE (\x. c % x) s)`,
10435   REPEAT GEN_TAC THEN ASM_CASES_TAC `c = &0` THENL
10436    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO] THEN
10437     SUBGOAL_THEN `IMAGE ((\x. vec 0):real^N->real^N) s = {} \/
10438                   IMAGE ((\x. vec 0):real^N->real^N) s = {vec 0}`
10439     STRIP_ASSUME_TAC THENL
10440      [SET_TAC[];
10441       ASM_REWRITE_TAC[IS_INTERVAL_EMPTY];
10442       ASM_REWRITE_TAC[IS_INTERVAL_SING]];
10443     REWRITE_TAC[is_interval; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
10444     REWRITE_TAC[FORALL_IN_IMAGE] THEN
10445     GEN_REWRITE_TAC (BINOP_CONV o REDEPTH_CONV) [RIGHT_IMP_FORALL_THM] THEN
10446     REWRITE_TAC[IMP_IMP; VECTOR_MUL_COMPONENT] THEN
10447     MAP_EVERY (fun t -> MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC t)
10448      [`a:real^N`; `b:real^N`] THEN
10449     DISCH_THEN(fun th -> X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
10450                          MP_TAC(SPEC `inv(c) % x:real^N` th)) THEN
10451     ASM_REWRITE_TAC[VECTOR_MUL_COMPONENT; IN_IMAGE] THEN ANTS_TAC THENL
10452      [X_GEN_TAC `i:num` THEN STRIP_TAC THEN
10453       FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN ASM_REWRITE_TAC[] THEN
10454       ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN REWRITE_TAC[GSYM real_div] THEN
10455       FIRST_X_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
10456        `~(c = &0) ==> &0 < c \/ &0 < --c`)) THEN
10457       ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ] THEN
10458       GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM REAL_LE_NEG2] THEN
10459       ASM_SIMP_TAC[GSYM REAL_MUL_RNEG; GSYM REAL_LE_RDIV_EQ; GSYM
10460                    REAL_LE_LDIV_EQ] THEN
10461       REWRITE_TAC[real_div; REAL_INV_NEG] THEN REAL_ARITH_TAC;
10462       DISCH_TAC THEN EXISTS_TAC `inv c % x:real^N` THEN
10463       ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RINV; VECTOR_MUL_LID]]]);;
10464
10465 let IS_INTERVAL_SCALING_EQ = prove
10466  (`!s:real^N->bool c.
10467         is_interval(IMAGE (\x. c % x) s) <=> c = &0 \/ is_interval s`,
10468   REPEAT GEN_TAC THEN ASM_CASES_TAC `c = &0` THENL
10469    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO] THEN
10470     SUBGOAL_THEN `IMAGE ((\x. vec 0):real^N->real^N) s = {} \/
10471                   IMAGE ((\x. vec 0):real^N->real^N) s = {vec 0}`
10472     STRIP_ASSUME_TAC THENL
10473      [SET_TAC[];
10474       ASM_REWRITE_TAC[IS_INTERVAL_EMPTY];
10475       ASM_REWRITE_TAC[IS_INTERVAL_SING]];
10476     ASM_REWRITE_TAC[] THEN EQ_TAC THEN REWRITE_TAC[IS_INTERVAL_SCALING] THEN
10477     DISCH_THEN(MP_TAC o SPEC `inv c:real` o MATCH_MP IS_INTERVAL_SCALING) THEN
10478     ASM_SIMP_TAC[GSYM IMAGE_o; VECTOR_MUL_ASSOC; o_DEF; REAL_MUL_LINV;
10479                  VECTOR_MUL_LID; IMAGE_ID]]);;
10480
10481 let lemma = prove
10482  (`!c. &0 < c
10483        ==> !s:real^N->bool. is_interval(IMAGE (\x. c % x) s) <=>
10484                             is_interval s`,
10485   SIMP_TAC[IS_INTERVAL_SCALING_EQ; REAL_LT_IMP_NZ]) in
10486 add_scaling_theorems [lemma];;
10487
10488 (* ------------------------------------------------------------------------- *)
10489 (* Line segments, with same open/closed overloading as for intervals.        *)
10490 (* ------------------------------------------------------------------------- *)
10491
10492 let closed_segment = define
10493  `closed_segment[a,b] = {(&1 - u) % a + u % b | &0 <= u /\ u <= &1}`;;
10494
10495 let open_segment = new_definition
10496  `open_segment(a,b) = closed_segment[a,b] DIFF {a,b}`;;
10497
10498 let OPEN_SEGMENT_ALT = prove
10499  (`!a b:real^N.
10500         ~(a = b)
10501         ==> open_segment(a,b) = {(&1 - u) % a + u % b | &0 < u /\ u < &1}`,
10502   REPEAT STRIP_TAC THEN REWRITE_TAC[open_segment; closed_segment] THEN
10503   REWRITE_TAC[EXTENSION; IN_DIFF; IN_INSERT; NOT_IN_EMPTY; IN_ELIM_THM] THEN
10504   X_GEN_TAC `x:real^N` THEN REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN
10505   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN
10506   X_GEN_TAC `u:real` THEN ASM_CASES_TAC `x:real^N = (&1 - u) % a + u % b` THEN
10507   ASM_REWRITE_TAC[REAL_LE_LT;
10508     VECTOR_ARITH `(&1 - u) % a + u % b = a <=> u % (b - a) = vec 0`;
10509     VECTOR_ARITH `(&1 - u) % a + u % b = b <=> (&1 - u) % (b - a) = vec 0`;
10510     VECTOR_MUL_EQ_0; REAL_SUB_0; VECTOR_SUB_EQ] THEN
10511   REAL_ARITH_TAC);;
10512
10513 make_overloadable "segment" `:A`;;
10514
10515 overload_interface("segment",`open_segment`);;
10516 overload_interface("segment",`closed_segment`);;
10517
10518 let segment = prove
10519  (`segment[a,b] = {(&1 - u) % a + u % b | &0 <= u /\ u <= &1} /\
10520    segment(a,b) = segment[a,b] DIFF {a,b}`,
10521   REWRITE_TAC[open_segment; closed_segment]);;
10522
10523 let SEGMENT_REFL = prove
10524  (`(!a. segment[a,a] = {a}) /\
10525    (!a. segment(a,a) = {})`,
10526   REWRITE_TAC[segment; VECTOR_ARITH `(&1 - u) % a + u % a = a`] THEN
10527   SET_TAC[REAL_POS]);;
10528
10529 let IN_SEGMENT = prove
10530  (`!a b x:real^N.
10531         (x IN segment[a,b] <=>
10532          ?u. &0 <= u /\ u <= &1 /\ x = (&1 - u) % a + u % b) /\
10533         (x IN segment(a,b) <=>
10534          ~(a = b) /\ ?u. &0 < u /\ u < &1 /\ x = (&1 - u) % a + u % b)`,
10535   REPEAT STRIP_TAC THENL
10536    [REWRITE_TAC[segment; IN_ELIM_THM; CONJ_ASSOC]; ALL_TAC] THEN
10537   ASM_CASES_TAC `a:real^N = b` THEN
10538   ASM_REWRITE_TAC[SEGMENT_REFL; NOT_IN_EMPTY] THEN
10539   ASM_SIMP_TAC[OPEN_SEGMENT_ALT; IN_ELIM_THM; CONJ_ASSOC]);;
10540
10541 let SEGMENT_SYM = prove
10542  (`(!a b:real^N. segment[a,b] = segment[b,a]) /\
10543    (!a b:real^N. segment(a,b) = segment(b,a))`,
10544   MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN
10545   SIMP_TAC[open_segment] THEN
10546   CONJ_TAC THENL [ALL_TAC; SIMP_TAC[INSERT_AC]] THEN
10547   REWRITE_TAC[EXTENSION; IN_SEGMENT] THEN REPEAT GEN_TAC THEN EQ_TAC THEN
10548   DISCH_THEN(X_CHOOSE_TAC `u:real`) THEN EXISTS_TAC `&1 - u` THEN
10549   ASM_REWRITE_TAC[] THEN
10550   REPEAT CONJ_TAC THEN TRY ASM_ARITH_TAC THEN VECTOR_ARITH_TAC);;
10551
10552 let ENDS_IN_SEGMENT = prove
10553  (`!a b. a IN segment[a,b] /\ b IN segment[a,b]`,
10554   REPEAT STRIP_TAC THEN REWRITE_TAC[segment; IN_ELIM_THM] THENL
10555    [EXISTS_TAC `&0`; EXISTS_TAC `&1`] THEN
10556   (CONJ_TAC THENL [REAL_ARITH_TAC; VECTOR_ARITH_TAC]));;
10557
10558 let ENDS_NOT_IN_SEGMENT = prove
10559  (`!a b. ~(a IN segment(a,b)) /\ ~(b IN segment(a,b))`,
10560   REWRITE_TAC[open_segment] THEN SET_TAC[]);;
10561
10562 let SEGMENT_CLOSED_OPEN = prove
10563  (`!a b. segment[a,b] = segment(a,b) UNION {a,b}`,
10564   REPEAT GEN_TAC THEN REWRITE_TAC[open_segment] THEN MATCH_MP_TAC(SET_RULE
10565    `a IN s /\ b IN s ==> s = (s DIFF {a,b}) UNION {a,b}`) THEN
10566   REWRITE_TAC[ENDS_IN_SEGMENT]);;
10567
10568 let MIDPOINT_IN_SEGMENT = prove
10569  (`(!a b:real^N. midpoint(a,b) IN segment[a,b]) /\
10570    (!a b:real^N. midpoint(a,b) IN segment(a,b) <=> ~(a = b))`,
10571   REWRITE_TAC[IN_SEGMENT] THEN REPEAT STRIP_TAC THENL
10572    [ALL_TAC; ASM_CASES_TAC `a:real^N = b` THEN ASM_REWRITE_TAC[]] THEN
10573   EXISTS_TAC `&1 / &2` THEN REWRITE_TAC[midpoint] THEN
10574   CONV_TAC REAL_RAT_REDUCE_CONV THEN VECTOR_ARITH_TAC);;
10575
10576 let BETWEEN_IN_SEGMENT = prove
10577  (`!x a b:real^N. between x (a,b) <=> x IN segment[a,b]`,
10578   REPEAT GEN_TAC THEN REWRITE_TAC[between] THEN
10579   ASM_CASES_TAC `a:real^N = b` THEN
10580   ASM_REWRITE_TAC[SEGMENT_REFL; IN_SING] THENL [NORM_ARITH_TAC; ALL_TAC] THEN
10581   REWRITE_TAC[segment; IN_ELIM_THM] THEN EQ_TAC THENL
10582    [DISCH_THEN(ASSUME_TAC o SYM) THEN
10583     EXISTS_TAC `dist(a:real^N,x) / dist(a,b)` THEN
10584     ASM_SIMP_TAC[REAL_LE_LDIV_EQ; REAL_LE_RDIV_EQ; DIST_POS_LT] THEN CONJ_TAC
10585     THENL [FIRST_ASSUM(SUBST1_TAC o SYM) THEN NORM_ARITH_TAC; ALL_TAC] THEN
10586     MATCH_MP_TAC VECTOR_MUL_LCANCEL_IMP THEN EXISTS_TAC `dist(a:real^N,b)` THEN
10587     ASM_SIMP_TAC[VECTOR_MUL_ASSOC; VECTOR_ADD_LDISTRIB; REAL_SUB_LDISTRIB;
10588                  REAL_DIV_LMUL; DIST_EQ_0] THEN
10589     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [DIST_TRIANGLE_EQ] o SYM) THEN
10590     FIRST_ASSUM(SUBST1_TAC o SYM) THEN
10591     REWRITE_TAC[dist; REAL_ARITH `(a + b) * &1 - a = b`] THEN
10592     VECTOR_ARITH_TAC;
10593     STRIP_TAC THEN ASM_REWRITE_TAC[dist] THEN
10594     REWRITE_TAC[VECTOR_ARITH `a - ((&1 - u) % a + u % b) = u % (a - b)`;
10595                 VECTOR_ARITH `((&1 - u) % a + u % b) - b = (&1 - u) % (a - b)`;
10596                 NORM_MUL; GSYM REAL_ADD_LDISTRIB] THEN
10597     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD]);;
10598
10599 let IN_SEGMENT_COMPONENT = prove
10600  (`!a b x:real^N i.
10601         x IN segment[a,b] /\ 1 <= i /\ i <= dimindex(:N)
10602         ==> min (a$i) (b$i) <= x$i /\ x$i <= max (a$i) (b$i)`,
10603   REPEAT STRIP_TAC THEN
10604   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT]) THEN
10605   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
10606   FIRST_X_ASSUM(X_CHOOSE_THEN `t:real` STRIP_ASSUME_TAC) THEN
10607   ASM_REWRITE_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN
10608   SIMP_TAC[REAL_ARITH `c <= u * a + t * b <=> u * --a + t * --b <= --c`] THEN
10609   MATCH_MP_TAC REAL_CONVEX_BOUND_LE THEN ASM_REAL_ARITH_TAC);;
10610
10611 let SEGMENT_1 = prove
10612  (`(!a b. segment[a,b] =
10613           if drop a <= drop b then interval[a,b] else interval[b,a]) /\
10614    (!a b. segment(a,b) =
10615           if drop a <= drop b then interval(a,b) else interval(b,a))`,
10616   CONJ_TAC THEN REPEAT GEN_TAC THEN REWRITE_TAC[open_segment] THEN
10617   COND_CASES_TAC THEN
10618   REWRITE_TAC[IN_DIFF; IN_INSERT; NOT_IN_EMPTY;
10619               EXTENSION; GSYM BETWEEN_IN_SEGMENT; between; IN_INTERVAL_1] THEN
10620   REWRITE_TAC[GSYM DROP_EQ; DIST_REAL; GSYM drop] THEN ASM_REAL_ARITH_TAC);;
10621
10622 let OPEN_SEGMENT_1 = prove
10623  (`!a b:real^1. open(segment(a,b))`,
10624   REPEAT GEN_TAC THEN REWRITE_TAC[SEGMENT_1] THEN
10625   COND_CASES_TAC THEN REWRITE_TAC[OPEN_INTERVAL]);;
10626
10627 let SEGMENT_TRANSLATION = prove
10628  (`(!c a b. segment[c + a,c + b] = IMAGE (\x. c + x) (segment[a,b])) /\
10629    (!c a b. segment(c + a,c + b) = IMAGE (\x. c + x) (segment(a,b)))`,
10630   REWRITE_TAC[EXTENSION; IN_SEGMENT; IN_IMAGE] THEN
10631   REWRITE_TAC[VECTOR_ARITH `(&1 - u) % (c + a) + u % (c + b) =
10632                             c + (&1 - u) % a + u % b`] THEN
10633   REWRITE_TAC[VECTOR_ARITH `c + a:real^N = c + b <=> a = b`] THEN
10634   MESON_TAC[]);;
10635
10636 add_translation_invariants
10637  [CONJUNCT1 SEGMENT_TRANSLATION; CONJUNCT2 SEGMENT_TRANSLATION];;
10638
10639 let CLOSED_SEGMENT_LINEAR_IMAGE = prove
10640  (`!f a b. linear f
10641            ==> segment[f a,f b] = IMAGE f (segment[a,b])`,
10642   REPEAT STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_SEGMENT] THEN
10643   FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_CMUL th)]) THEN
10644   FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_ADD th)]) THEN
10645   MESON_TAC[]);;
10646
10647 add_linear_invariants [CLOSED_SEGMENT_LINEAR_IMAGE];;
10648
10649 let OPEN_SEGMENT_LINEAR_IMAGE = prove
10650  (`!f:real^M->real^N a b.
10651         linear f /\ (!x y. f x = f y ==> x = y)
10652         ==> segment(f a,f b) = IMAGE f (segment(a,b))`,
10653   REWRITE_TAC[open_segment] THEN GEOM_TRANSFORM_TAC[]);;
10654
10655 add_linear_invariants [OPEN_SEGMENT_LINEAR_IMAGE];;
10656
10657 let IN_OPEN_SEGMENT = prove
10658  (`!a b x:real^N.
10659         x IN segment(a,b) <=> x IN segment[a,b] /\ ~(x = a) /\ ~(x = b)`,
10660   REPEAT GEN_TAC THEN REWRITE_TAC[open_segment; IN_DIFF] THEN SET_TAC[]);;
10661
10662 let IN_OPEN_SEGMENT_ALT = prove
10663  (`!a b x:real^N.
10664         x IN segment(a,b) <=>
10665         x IN segment[a,b] /\ ~(x = a) /\ ~(x = b) /\ ~(a = b)`,
10666   REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = b` THEN
10667   ASM_REWRITE_TAC[SEGMENT_REFL; IN_SING; NOT_IN_EMPTY] THEN
10668   ASM_MESON_TAC[IN_OPEN_SEGMENT]);;
10669
10670 let COLLINEAR_DIST_IN_CLOSED_SEGMENT = prove
10671  (`!a b x. collinear {x,a,b} /\
10672            dist(x,a) <= dist(a,b) /\ dist(x,b) <= dist(a,b)
10673            ==> x IN segment[a,b]`,
10674   REWRITE_TAC[GSYM BETWEEN_IN_SEGMENT; COLLINEAR_DIST_BETWEEN]);;
10675
10676 let COLLINEAR_DIST_IN_OPEN_SEGMENT = prove
10677  (`!a b x. collinear {x,a,b} /\
10678            dist(x,a) < dist(a,b) /\ dist(x,b) < dist(a,b)
10679            ==> x IN segment(a,b)`,
10680   REWRITE_TAC[IN_OPEN_SEGMENT] THEN
10681   MESON_TAC[COLLINEAR_DIST_IN_CLOSED_SEGMENT; REAL_LT_LE; DIST_SYM]);;
10682
10683 let SEGMENT_SCALAR_MULTIPLE = prove
10684  (`(!a b v. segment[a % v,b % v] =
10685             {x % v:real^N | a <= x /\ x <= b \/ b <= x /\ x <= a}) /\
10686    (!a b v. ~(v = vec 0)
10687             ==> segment(a % v,b % v) =
10688                 {x % v:real^N | a < x /\ x < b \/ b < x /\ x < a})`,
10689   MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN REPEAT STRIP_TAC THENL
10690    [REPEAT GEN_TAC THEN
10691     MP_TAC(SPECL [`a % basis 1:real^1`; `b % basis 1:real^1`]
10692      (CONJUNCT1 SEGMENT_1)) THEN
10693     REWRITE_TAC[segment; VECTOR_MUL_ASSOC; GSYM VECTOR_ADD_RDISTRIB] THEN
10694     REWRITE_TAC[SET_RULE `{f x % b | p x} = IMAGE (\a. a % b) {f x | p x}`] THEN
10695     DISCH_TAC THEN AP_TERM_TAC THEN
10696     FIRST_X_ASSUM(MP_TAC o AP_TERM `IMAGE drop`) THEN
10697     REWRITE_TAC[GSYM IMAGE_o; o_DEF; DROP_CMUL] THEN
10698     SIMP_TAC[drop; BASIS_COMPONENT; DIMINDEX_GE_1; LE_REFL] THEN
10699     REWRITE_TAC[REAL_MUL_RID; IMAGE_ID] THEN DISCH_THEN SUBST1_TAC THEN
10700     MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
10701     CONJ_TAC THENL [MESON_TAC[LIFT_DROP]; ALL_TAC] THEN
10702     REWRITE_TAC[FORALL_LIFT; LIFT_DROP] THEN GEN_TAC THEN
10703     COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP] THEN
10704     SIMP_TAC[drop; VECTOR_MUL_COMPONENT; BASIS_COMPONENT; DIMINDEX_GE_1;
10705              LE_REFL; IN_ELIM_THM] THEN ASM_REAL_ARITH_TAC;
10706     ASM_REWRITE_TAC[open_segment] THEN
10707     ASM_SIMP_TAC[VECTOR_MUL_RCANCEL; SET_RULE
10708      `(!x y. x % v = y % v <=> x = y)
10709       ==> {x % v | P x} DIFF {a % v,b % v} =
10710           {x % v | P x /\ ~(x = a) /\ ~(x = b)}`] THEN
10711     ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN AP_TERM_TAC THEN
10712     REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REAL_ARITH_TAC]);;
10713
10714 let FINITE_INTER_COLLINEAR_OPEN_SEGMENTS = prove
10715  (`!a b c d:real^N.
10716         collinear{a,b,c}
10717         ==> (FINITE(segment(a,b) INTER segment(c,d)) <=>
10718              segment(a,b) INTER segment(c,d) = {})`,
10719   REPEAT GEN_TAC THEN ABBREV_TAC `m:real^N = b - a` THEN POP_ASSUM MP_TAC THEN
10720   GEOM_NORMALIZE_TAC `m:real^N` THEN
10721   SIMP_TAC[VECTOR_SUB_EQ; SEGMENT_REFL; INTER_EMPTY; FINITE_EMPTY] THEN
10722   X_GEN_TAC `m:real^N` THEN DISCH_TAC THEN REPEAT GEN_TAC THEN
10723   DISCH_THEN(SUBST_ALL_TAC o SYM) THEN POP_ASSUM MP_TAC THEN
10724   GEOM_ORIGIN_TAC `a:real^N` THEN GEOM_BASIS_MULTIPLE_TAC 1 `b:real^N` THEN
10725   X_GEN_TAC `b:real` THEN DISCH_TAC THEN
10726   MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN
10727   SIMP_TAC[VECTOR_SUB_RZERO; NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN
10728   ASM_REWRITE_TAC[real_abs; REAL_MUL_RID] THEN DISCH_THEN SUBST_ALL_TAC THEN
10729   POP_ASSUM(K ALL_TAC) THEN
10730   ASM_CASES_TAC `collinear{vec 0:real^N,&1 % basis 1,y}` THENL
10731    [POP_ASSUM MP_TAC THEN
10732     SIMP_TAC[COLLINEAR_LEMMA_ALT; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL] THEN
10733     MATCH_MP_TAC(TAUT
10734      `~a /\ (b ==> c ==> d) ==> a \/ b ==> a \/ c ==> d`) THEN
10735     CONJ_TAC THENL
10736      [SIMP_TAC[VECTOR_MUL_LID; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL];
10737       REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN
10738     X_GEN_TAC `b:real` THEN DISCH_THEN SUBST_ALL_TAC THEN
10739     X_GEN_TAC `a:real` THEN DISCH_THEN SUBST_ALL_TAC THEN
10740     REWRITE_TAC[VECTOR_MUL_ASSOC; REAL_MUL_RID] THEN
10741     SUBST1_TAC(VECTOR_ARITH `vec 0:real^N = &0 % basis 1`) THEN
10742     SIMP_TAC[SEGMENT_SCALAR_MULTIPLE; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL;
10743      VECTOR_MUL_RCANCEL; IMAGE_EQ_EMPTY; FINITE_IMAGE_INJ_EQ; SET_RULE
10744      `(!x y. x % v = y % v <=> x = y)
10745       ==> {x % v | P x} INTER {x % v | Q x} =
10746           IMAGE (\x. x % v) {x | P x /\ Q x}`] THEN
10747     REWRITE_TAC[REAL_ARITH `(&0 < x /\ x < &1 \/ &1 < x /\ x < &0) /\
10748                             (b < x /\ x < a \/ a < x /\ x < b) <=>
10749                        max (&0) (min a b) < x /\ x < min (&1) (max a b)`] THEN
10750     SIMP_TAC[FINITE_REAL_INTERVAL; EXTENSION; NOT_IN_EMPTY; IN_ELIM_THM] THEN
10751     SIMP_TAC[GSYM REAL_LT_BETWEEN; GSYM NOT_EXISTS_THM] THEN REAL_ARITH_TAC;
10752     DISCH_TAC THEN ASM_CASES_TAC
10753      `segment(vec 0:real^N,&1 % basis 1) INTER segment (x,y) = {}` THEN
10754     ASM_REWRITE_TAC[FINITE_EMPTY] THEN DISCH_THEN(K ALL_TAC) THEN
10755     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
10756     REWRITE_TAC[open_segment; IN_DIFF; NOT_IN_EMPTY;
10757                 DE_MORGAN_THM; IN_INTER; IN_INSERT] THEN
10758     DISCH_THEN(X_CHOOSE_THEN `p:real^N` STRIP_ASSUME_TAC) THEN
10759     UNDISCH_TAC `~collinear{vec 0:real^N,&1 % basis 1, y}` THEN
10760     RULE_ASSUM_TAC(REWRITE_RULE[VECTOR_MUL_LID]) THEN
10761     REWRITE_TAC[VECTOR_MUL_LID] THEN
10762     MATCH_MP_TAC COLLINEAR_SUBSET THEN
10763     EXISTS_TAC `{p,x:real^N, y, vec 0, basis 1}` THEN
10764     CONJ_TAC THENL [ALL_TAC; SET_TAC[]] THEN
10765     MP_TAC(ISPECL [`{y:real^N,vec 0,basis 1}`; `p:real^N`; `x:real^N`]
10766         COLLINEAR_TRIPLES) THEN
10767     ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST1_TAC THEN
10768     REWRITE_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY] THEN CONJ_TAC THENL
10769      [ONCE_REWRITE_TAC[SET_RULE `{p,x,y} = {x,p,y}`] THEN
10770       MATCH_MP_TAC BETWEEN_IMP_COLLINEAR THEN
10771       ASM_REWRITE_TAC[BETWEEN_IN_SEGMENT];
10772       ALL_TAC] THEN
10773     ASM_SIMP_TAC[GSYM COLLINEAR_4_3] THEN
10774     ONCE_REWRITE_TAC[SET_RULE `{p,x,z,w} = {w,z,p,x}`] THEN
10775     SIMP_TAC[COLLINEAR_4_3; BASIS_NONZERO; DIMINDEX_GE_1; ARITH] THEN
10776     REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP BETWEEN_IMP_COLLINEAR o
10777         GEN_REWRITE_RULE I [GSYM BETWEEN_IN_SEGMENT])) THEN
10778     REPEAT(POP_ASSUM MP_TAC) THEN SIMP_TAC[INSERT_AC]]);;
10779
10780 let DIST_IN_CLOSED_SEGMENT,DIST_IN_OPEN_SEGMENT = (CONJ_PAIR o prove)
10781  (`(!a b x:real^N.
10782     x IN segment[a,b] ==> dist(x,a) <= dist(a,b) /\ dist(x,b) <= dist(a,b)) /\
10783    (!a b x:real^N.
10784     x IN segment(a,b) ==> dist(x,a) < dist(a,b) /\ dist(x,b) < dist(a,b))`,
10785   SIMP_TAC[IN_SEGMENT; RIGHT_AND_EXISTS_THM; LEFT_IMP_EXISTS_THM; dist;
10786            VECTOR_ARITH
10787     `((&1 - u) % a + u % b) - a:real^N = u % (b - a) /\
10788      ((&1 - u) % a + u % b) - b = --(&1 - u) % (b - a)`] THEN
10789   REWRITE_TAC[NORM_MUL; REAL_ABS_NEG; NORM_SUB] THEN CONJ_TAC THEN
10790   REPEAT GEN_TAC THEN STRIP_TAC THENL
10791    [REWRITE_TAC[REAL_ARITH `x * y <= y <=> x * y <= &1 * y`] THEN
10792     CONJ_TAC THEN MATCH_MP_TAC REAL_LE_RMUL THEN
10793     REWRITE_TAC[NORM_POS_LE] THEN ASM_REAL_ARITH_TAC;
10794     REWRITE_TAC[REAL_ARITH `x * y < y <=> x * y < &1 * y`] THEN
10795     ASM_SIMP_TAC[REAL_LT_RMUL_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
10796     ASM_REAL_ARITH_TAC]);;
10797
10798 (* ------------------------------------------------------------------------- *)
10799 (* Limit component bounds.                                                   *)
10800 (* ------------------------------------------------------------------------- *)
10801
10802 let LIM_COMPONENT_UBOUND = prove
10803  (`!net:(A)net f (l:real^N) b k.
10804         ~(trivial_limit net) /\ (f --> l) net /\
10805         eventually (\x. (f x)$k <= b) net /\
10806         1 <= k /\ k <= dimindex(:N)
10807         ==> l$k <= b`,
10808   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
10809    [`net:(A)net`; `f:A->real^N`; `{y:real^N | basis k dot y <= b}`; `l:real^N`]
10810    LIM_IN_CLOSED_SET) THEN
10811   ASM_SIMP_TAC[CLOSED_HALFSPACE_LE; IN_ELIM_THM; DOT_BASIS]);;
10812
10813 let LIM_COMPONENT_LBOUND = prove
10814  (`!net:(A)net f (l:real^N) b k.
10815         ~(trivial_limit net) /\ (f --> l) net /\
10816         eventually (\x. b <= (f x)$k) net /\
10817         1 <= k /\ k <= dimindex(:N)
10818         ==> b <= l$k`,
10819   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
10820    [`net:(A)net`; `f:A->real^N`; `{y:real^N | b <= basis k dot y}`; `l:real^N`]
10821    LIM_IN_CLOSED_SET) THEN
10822   ASM_SIMP_TAC[REWRITE_RULE[real_ge] CLOSED_HALFSPACE_GE;
10823                IN_ELIM_THM; DOT_BASIS]);;
10824
10825 let LIM_COMPONENT_EQ = prove
10826  (`!net f:A->real^N i l b.
10827         (f --> l) net /\ 1 <= i /\ i <= dimindex(:N) /\
10828         ~(trivial_limit net) /\ eventually (\x. f(x)$i = b) net
10829         ==> l$i = b`,
10830   REWRITE_TAC[GSYM REAL_LE_ANTISYM; EVENTUALLY_AND] THEN
10831   MESON_TAC[LIM_COMPONENT_UBOUND; LIM_COMPONENT_LBOUND]);;
10832
10833 let LIM_COMPONENT_LE = prove
10834  (`!net:(A)net f:A->real^N g:A->real^N k l m.
10835          ~(trivial_limit net) /\ (f --> l) net /\ (g --> m) net /\
10836         eventually (\x. (f x)$k <= (g x)$k) net /\
10837         1 <= k /\ k <= dimindex(:N)
10838         ==> l$k <= m$k`,
10839   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[GSYM REAL_SUB_LE] THEN
10840   REWRITE_TAC[GSYM VECTOR_SUB_COMPONENT; LIM_COMPONENT_LBOUND] THEN
10841   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
10842   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> b /\ a ==> c ==> d`] THEN
10843   DISCH_THEN(MP_TAC o MATCH_MP LIM_SUB) THEN POP_ASSUM MP_TAC THEN
10844   REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC; LIM_COMPONENT_LBOUND]);;
10845
10846 let LIM_DROP_LE = prove
10847  (`!net:(A)net f g l m.
10848          ~(trivial_limit net) /\ (f --> l) net /\ (g --> m) net /\
10849         eventually (\x. drop(f x) <= drop(g x)) net
10850         ==> drop l <= drop m`,
10851   REWRITE_TAC[drop] THEN REPEAT STRIP_TAC THEN
10852   MATCH_MP_TAC(ISPEC `net:(A)net` LIM_COMPONENT_LE) THEN
10853   MAP_EVERY EXISTS_TAC [`f:A->real^1`; `g:A->real^1`] THEN
10854   ASM_REWRITE_TAC[DIMINDEX_1; LE_REFL]);;
10855
10856 let LIM_DROP_UBOUND = prove
10857  (`!net f:A->real^1 l b.
10858         (f --> l) net /\
10859         ~(trivial_limit net) /\ eventually (\x. drop(f x) <= b) net
10860         ==> drop l <= b`,
10861   SIMP_TAC[drop] THEN REPEAT STRIP_TAC THEN
10862   MATCH_MP_TAC LIM_COMPONENT_UBOUND THEN
10863   REWRITE_TAC[LE_REFL; DIMINDEX_1] THEN ASM_MESON_TAC[]);;
10864
10865 let LIM_DROP_LBOUND = prove
10866  (`!net f:A->real^1 l b.
10867         (f --> l) net /\
10868         ~(trivial_limit net) /\ eventually (\x. b <= drop(f x)) net
10869         ==> b <= drop l`,
10870   SIMP_TAC[drop] THEN REPEAT STRIP_TAC THEN
10871   MATCH_MP_TAC LIM_COMPONENT_LBOUND THEN
10872   REWRITE_TAC[LE_REFL; DIMINDEX_1] THEN ASM_MESON_TAC[]);;
10873
10874 (* ------------------------------------------------------------------------- *)
10875 (* Also extending closed bounds to closures.                                 *)
10876 (* ------------------------------------------------------------------------- *)
10877
10878 let IMAGE_CLOSURE_SUBSET = prove
10879  (`!f (s:real^N->bool) (t:real^M->bool).
10880       f continuous_on closure s /\ closed t /\ IMAGE f s SUBSET t
10881       ==> IMAGE f (closure s) SUBSET t`,
10882   REPEAT STRIP_TAC THEN
10883   SUBGOAL_THEN `closure s SUBSET {x | (f:real^N->real^M) x IN t}` MP_TAC
10884   THENL [MATCH_MP_TAC SUBSET_TRANS; SET_TAC []]  THEN
10885   EXISTS_TAC `{x | x IN closure s /\ (f:real^N->real^M) x IN t}` THEN
10886   CONJ_TAC THENL
10887   [MATCH_MP_TAC CLOSURE_MINIMAL; SET_TAC[]] THEN
10888   ASM_SIMP_TAC[CONTINUOUS_CLOSED_PREIMAGE; CLOSED_CLOSURE] THEN
10889   MP_TAC (ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[]);;
10890
10891 let CLOSURE_IMAGE_CLOSURE = prove
10892  (`!f:real^M->real^N s.
10893         f continuous_on closure s
10894         ==> closure(IMAGE f (closure s)) = closure(IMAGE f s)`,
10895   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
10896   SIMP_TAC[SUBSET_CLOSURE; IMAGE_SUBSET; CLOSURE_SUBSET] THEN
10897   SIMP_TAC[CLOSURE_MINIMAL_EQ; CLOSED_CLOSURE] THEN
10898   MATCH_MP_TAC IMAGE_CLOSURE_SUBSET THEN
10899   ASM_REWRITE_TAC[CLOSED_CLOSURE; CLOSURE_SUBSET]);;
10900
10901 let CONTINUOUS_ON_CLOSURE_NORM_LE = prove
10902  (`!f:real^N->real^M s x b.
10903       f continuous_on (closure s) /\
10904       (!y. y IN s ==> norm(f y) <= b) /\
10905       x IN (closure s)
10906       ==> norm(f x) <= b`,
10907   REWRITE_TAC [GSYM IN_CBALL_0] THEN REPEAT STRIP_TAC THEN
10908   SUBGOAL_THEN `IMAGE (f:real^N->real^M) (closure s) SUBSET cball(vec 0,b)`
10909     MP_TAC THENL
10910   [MATCH_MP_TAC IMAGE_CLOSURE_SUBSET; ASM SET_TAC []] THEN
10911   ASM_REWRITE_TAC [CLOSED_CBALL] THEN ASM SET_TAC []);;
10912
10913 let CONTINUOUS_ON_CLOSURE_COMPONENT_LE = prove
10914  (`!f:real^N->real^M s x b k.
10915       f continuous_on (closure s) /\
10916       (!y. y IN s ==> (f y)$k <= b) /\
10917       x IN (closure s)
10918       ==> (f x)$k <= b`,
10919   REWRITE_TAC [GSYM IN_CBALL_0] THEN REPEAT STRIP_TAC THEN
10920   SUBGOAL_THEN `IMAGE (f:real^N->real^M) (closure s) SUBSET {x | x$k <= b}`
10921   MP_TAC THENL
10922    [MATCH_MP_TAC IMAGE_CLOSURE_SUBSET; ASM SET_TAC []] THEN
10923   ASM_REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_LE] THEN ASM SET_TAC[]);;
10924
10925 let CONTINUOUS_ON_CLOSURE_COMPONENT_GE = prove
10926  (`!f:real^N->real^M s x b k.
10927       f continuous_on (closure s) /\
10928       (!y. y IN s ==> b <= (f y)$k) /\
10929       x IN (closure s)
10930       ==> b <= (f x)$k`,
10931   REWRITE_TAC [GSYM IN_CBALL_0] THEN REPEAT STRIP_TAC THEN
10932   SUBGOAL_THEN `IMAGE (f:real^N->real^M) (closure s) SUBSET {x | x$k >= b}`
10933   MP_TAC THENL
10934    [MATCH_MP_TAC IMAGE_CLOSURE_SUBSET; ASM SET_TAC [real_ge]] THEN
10935   ASM_REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_GE] THEN ASM SET_TAC[real_ge]);;
10936
10937 (* ------------------------------------------------------------------------- *)
10938 (* Limits relative to a union.                                               *)
10939 (* ------------------------------------------------------------------------- *)
10940
10941 let LIM_WITHIN_UNION = prove
10942  (`(f --> l) (at x within (s UNION t)) <=>
10943    (f --> l) (at x within s) /\ (f --> l) (at x within t)`,
10944   REWRITE_TAC[LIM_WITHIN; IN_UNION; AND_FORALL_THM] THEN
10945   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN
10946   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
10947   EQ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN DISCH_THEN
10948    (CONJUNCTS_THEN2 (X_CHOOSE_TAC `d:real`) (X_CHOOSE_TAC `k:real`)) THEN
10949   EXISTS_TAC `min d k` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN
10950   ASM_MESON_TAC[]);;
10951
10952 let CONTINUOUS_ON_UNION = prove
10953  (`!f s t. closed s /\ closed t /\ f continuous_on s /\ f continuous_on t
10954            ==> f continuous_on (s UNION t)`,
10955   REWRITE_TAC[CONTINUOUS_ON; CLOSED_LIMPT; IN_UNION; LIM_WITHIN_UNION] THEN
10956   MESON_TAC[LIM; TRIVIAL_LIMIT_WITHIN]);;
10957
10958 let CONTINUOUS_ON_CASES = prove
10959  (`!P f g:real^M->real^N s t.
10960         closed s /\ closed t /\ f continuous_on s /\ g continuous_on t /\
10961         (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x)
10962         ==> (\x. if P x then f x else g x) continuous_on (s UNION t)`,
10963   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_UNION THEN
10964   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THENL
10965    [EXISTS_TAC `f:real^M->real^N`; EXISTS_TAC `g:real^M->real^N`] THEN
10966   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
10967
10968 let CONTINUOUS_ON_UNION_LOCAL = prove
10969  (`!f:real^M->real^N s.
10970         closed_in (subtopology euclidean (s UNION t)) s /\
10971         closed_in (subtopology euclidean (s UNION t)) t /\
10972         f continuous_on s /\ f continuous_on t
10973         ==> f continuous_on (s UNION t)`,
10974   REWRITE_TAC[CONTINUOUS_ON; CLOSED_IN_LIMPT; IN_UNION; LIM_WITHIN_UNION] THEN
10975   MESON_TAC[LIM; TRIVIAL_LIMIT_WITHIN]);;
10976
10977 let CONTINUOUS_ON_CASES_LOCAL = prove
10978  (`!P f g:real^M->real^N s t.
10979         closed_in (subtopology euclidean (s UNION t)) s /\
10980         closed_in (subtopology euclidean (s UNION t)) t /\
10981         f continuous_on s /\ g continuous_on t /\
10982         (!x. x IN s /\ ~P x \/ x IN t /\ P x ==> f x = g x)
10983         ==> (\x. if P x then f x else g x) continuous_on (s UNION t)`,
10984   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_UNION_LOCAL THEN
10985   ASM_REWRITE_TAC[] THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THENL
10986    [EXISTS_TAC `f:real^M->real^N`; EXISTS_TAC `g:real^M->real^N`] THEN
10987   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
10988
10989 let CONTINUOUS_ON_CASES_LE = prove
10990  (`!f g:real^M->real^N h s a.
10991         f continuous_on {t | t IN s /\ h t <= a} /\
10992         g continuous_on {t | t IN s /\ a <= h t} /\
10993         (lift o h) continuous_on s /\
10994         (!t. t IN s /\ h t = a ==> f t = g t)
10995         ==> (\t. if h t <= a then f(t) else g(t)) continuous_on s`,
10996   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC
10997    `{t | t IN s /\ (h:real^M->real) t <= a} UNION
10998     {t | t IN s /\ a <= h t}` THEN
10999   CONJ_TAC THENL
11000    [ALL_TAC; SIMP_TAC[SUBSET; IN_UNION; IN_ELIM_THM; REAL_LE_TOTAL]] THEN
11001   MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL THEN ASM_REWRITE_TAC[] THEN
11002   REWRITE_TAC[IN_ELIM_THM; GSYM CONJ_ASSOC; REAL_LE_ANTISYM] THEN
11003   REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL
11004    [ALL_TAC; ASM_MESON_TAC[]] THEN
11005   CONJ_TAC THENL
11006    [SUBGOAL_THEN
11007      `{t | t IN s /\ (h:real^M->real) t <= a} =
11008       {t | t IN ({t | t IN s /\ h t <= a} UNION {t | t IN s /\ a <= h t}) /\
11009            (lift o h) t IN {x | x$1 <= a}}`
11010      (fun th -> GEN_REWRITE_TAC RAND_CONV [th])
11011     THENL
11012      [REWRITE_TAC[GSYM drop; o_THM; IN_ELIM_THM; LIFT_DROP; EXTENSION;
11013                   IN_UNION] THEN
11014       GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
11015       ASM_REAL_ARITH_TAC;
11016       MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
11017       ASM_REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_LE; ETA_AX] THEN
11018       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
11019         CONTINUOUS_ON_SUBSET)) THEN
11020       SET_TAC[]];
11021     SUBGOAL_THEN
11022      `{t | t IN s /\ a <= (h:real^M->real) t} =
11023       {t | t IN ({t | t IN s /\ h t <= a} UNION {t | t IN s /\ a <= h t}) /\
11024            (lift o h) t IN {x | x$1 >= a}}`
11025      (fun th -> GEN_REWRITE_TAC RAND_CONV [th])
11026     THENL
11027      [REWRITE_TAC[GSYM drop; o_THM; IN_ELIM_THM; LIFT_DROP; EXTENSION;
11028                   IN_UNION] THEN
11029       GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
11030       ASM_REAL_ARITH_TAC;
11031       MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
11032       ASM_REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_GE; ETA_AX] THEN
11033       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
11034         CONTINUOUS_ON_SUBSET)) THEN
11035       SET_TAC[]]]);;
11036
11037 let CONTINUOUS_ON_CASES_1 = prove
11038  (`!f g:real^1->real^N s a.
11039         f continuous_on {t | t IN s /\ drop t <= a} /\
11040         g continuous_on {t | t IN s /\ a <= drop t} /\
11041         (lift a IN s ==> f(lift a) = g(lift a))
11042         ==> (\t. if drop t <= a then f(t) else g(t)) continuous_on s`,
11043   REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_CASES_LE THEN
11044   ASM_REWRITE_TAC[o_DEF; LIFT_DROP; CONTINUOUS_ON_ID] THEN
11045   REWRITE_TAC[GSYM LIFT_EQ; LIFT_DROP] THEN ASM_MESON_TAC[]);;
11046
11047 (* ------------------------------------------------------------------------- *)
11048 (* Componentwise limits and continuity.                                      *)
11049 (* ------------------------------------------------------------------------- *)
11050
11051 let LIM_COMPONENTWISE_LIFT = prove
11052  (`!net f:A->real^N.
11053         (f --> l) net <=>
11054         !i. 1 <= i /\ i <= dimindex(:N)
11055             ==> ((\x. lift((f x)$i)) --> lift(l$i)) net`,
11056   REPEAT GEN_TAC THEN REWRITE_TAC[tendsto] THEN EQ_TAC THENL
11057    [DISCH_TAC THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
11058     X_GEN_TAC `e:real` THEN
11059     DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN
11060     ASM_SIMP_TAC[GSYM VECTOR_SUB_COMPONENT] THEN
11061     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
11062     GEN_TAC THEN REWRITE_TAC[dist] THEN MATCH_MP_TAC(REAL_ARITH
11063      `y <= x ==> x < e ==> y < e`) THEN
11064     ASM_SIMP_TAC[COMPONENT_LE_NORM; GSYM LIFT_SUB; NORM_LIFT;
11065                  GSYM VECTOR_SUB_COMPONENT];
11066     GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [RIGHT_IMP_FORALL_THM] THEN
11067     ONCE_REWRITE_TAC[IMP_IMP] THEN ONCE_REWRITE_TAC[IMP_CONJ_ALT] THEN
11068     ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
11069     REWRITE_TAC[GSYM IN_NUMSEG; RIGHT_FORALL_IMP_THM] THEN
11070     SIMP_TAC[FORALL_EVENTUALLY; FINITE_NUMSEG; NUMSEG_EMPTY;
11071              GSYM NOT_LE; DIMINDEX_GE_1] THEN
11072     REWRITE_TAC[DIST_LIFT; GSYM VECTOR_SUB_COMPONENT] THEN
11073     DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
11074     FIRST_X_ASSUM(MP_TAC o SPEC `e / &(dimindex(:N))`) THEN
11075     ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1] THEN
11076     MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] EVENTUALLY_MONO) THEN
11077     X_GEN_TAC `x:A` THEN SIMP_TAC[GSYM VECTOR_SUB_COMPONENT; dist] THEN
11078     DISCH_TAC THEN W(MP_TAC o PART_MATCH lhand NORM_LE_L1 o lhand o snd) THEN
11079     MATCH_MP_TAC(REAL_ARITH `s < e ==> n <= s ==> n < e`) THEN
11080     MATCH_MP_TAC SUM_BOUND_LT_GEN THEN
11081     ASM_SIMP_TAC[FINITE_NUMSEG; NUMSEG_EMPTY; GSYM NOT_LE; DIMINDEX_GE_1;
11082                  CARD_NUMSEG_1; GSYM IN_NUMSEG]]);;
11083
11084 let CONTINUOUS_COMPONENTWISE_LIFT = prove
11085  (`!net f:A->real^N.
11086         f continuous net <=>
11087         !i. 1 <= i /\ i <= dimindex(:N)
11088             ==> (\x. lift((f x)$i)) continuous net`,
11089   REWRITE_TAC[continuous; GSYM LIM_COMPONENTWISE_LIFT]);;
11090
11091 let CONTINUOUS_ON_COMPONENTWISE_LIFT = prove
11092  (`!f:real^M->real^N s.
11093         f continuous_on s <=>
11094         !i. 1 <= i /\ i <= dimindex(:N)
11095             ==> (\x. lift((f x)$i)) continuous_on s`,
11096   REPEAT GEN_TAC THEN
11097   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
11098   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV)
11099    [CONTINUOUS_COMPONENTWISE_LIFT] THEN
11100   MESON_TAC[]);;
11101
11102 (* ------------------------------------------------------------------------- *)
11103 (* Some more convenient intermediate-value theorem formulations.             *)
11104 (* ------------------------------------------------------------------------- *)
11105
11106 let CONNECTED_IVT_HYPERPLANE = prove
11107  (`!s x y:real^N a b.
11108         connected s /\
11109         x IN s /\ y IN s /\ a dot x <= b /\ b <= a dot y
11110         ==> ?z. z IN s /\ a dot z = b`,
11111   REPEAT STRIP_TAC THEN
11112   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [connected]) THEN
11113   REWRITE_TAC[NOT_EXISTS_THM] THEN DISCH_THEN(MP_TAC o SPECL
11114    [`{x:real^N | a dot x < b}`; `{x:real^N | a dot x > b}`]) THEN
11115   REWRITE_TAC[OPEN_HALFSPACE_LT; OPEN_HALFSPACE_GT] THEN
11116   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN STRIP_TAC THEN
11117   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_INTER; NOT_IN_EMPTY; SUBSET;
11118               IN_UNION; REAL_LT_LE; real_gt] THEN
11119   ASM_MESON_TAC[REAL_LE_TOTAL; REAL_LE_ANTISYM]);;
11120
11121 let CONNECTED_IVT_COMPONENT = prove
11122  (`!s x y:real^N a k.
11123         connected s /\ x IN s /\ y IN s /\
11124         1 <= k /\ k <= dimindex(:N) /\ x$k <= a /\ a <= y$k
11125         ==> ?z. z IN s /\ z$k = a`,
11126   REPEAT STRIP_TAC THEN MP_TAC(ISPECL
11127    [`s:real^N->bool`; `x:real^N`; `y:real^N`; `(basis k):real^N`;
11128     `a:real`] CONNECTED_IVT_HYPERPLANE) THEN
11129   ASM_SIMP_TAC[DOT_BASIS]);;
11130
11131 (* ------------------------------------------------------------------------- *)
11132 (* Also more convenient formulations of monotone convergence.                *)
11133 (* ------------------------------------------------------------------------- *)
11134
11135 let BOUNDED_INCREASING_CONVERGENT = prove
11136  (`!s:num->real^1.
11137         bounded {s n | n IN (:num)} /\ (!n. drop(s n) <= drop(s(SUC n)))
11138         ==> ?l. (s --> l) sequentially`,
11139   GEN_TAC THEN
11140   REWRITE_TAC[bounded; IN_ELIM_THM; ABS_DROP; LIM_SEQUENTIALLY; dist;
11141               DROP_SUB; IN_UNIV; GSYM EXISTS_DROP] THEN
11142   DISCH_TAC THEN MATCH_MP_TAC CONVERGENT_BOUNDED_MONOTONE THEN
11143   REWRITE_TAC[LEFT_EXISTS_AND_THM] THEN
11144   CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
11145   DISJ1_TAC THEN MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
11146   ASM_REWRITE_TAC[REAL_LE_TRANS; REAL_LE_REFL]);;
11147
11148 let BOUNDED_DECREASING_CONVERGENT = prove
11149  (`!s:num->real^1.
11150         bounded {s n | n IN (:num)} /\ (!n. drop(s(SUC n)) <= drop(s(n)))
11151         ==> ?l. (s --> l) sequentially`,
11152   GEN_TAC THEN REWRITE_TAC[bounded; FORALL_IN_GSPEC] THEN
11153   DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
11154   MP_TAC(ISPEC `\n. --((s:num->real^1) n)` BOUNDED_INCREASING_CONVERGENT) THEN
11155   ASM_SIMP_TAC[bounded; FORALL_IN_GSPEC; NORM_NEG; DROP_NEG; REAL_LE_NEG2] THEN
11156   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [GSYM LIM_NEG_EQ] THEN
11157   REWRITE_TAC[VECTOR_NEG_NEG; ETA_AX] THEN MESON_TAC[]);;
11158
11159 (* ------------------------------------------------------------------------- *)
11160 (* Since we'll use some cardinality reasoning, add invariance theorems.      *)
11161 (* ------------------------------------------------------------------------- *)
11162
11163 let card_translation_invariants = (CONJUNCTS o prove)
11164  (`(!a (s:real^N->bool) (t:A->bool).
11165      IMAGE (\x. a + x) s =_c t <=> s =_c t) /\
11166    (!a (s:A->bool) (t:real^N->bool).
11167      s =_c IMAGE (\x. a + x) t <=> s =_c t) /\
11168    (!a (s:real^N->bool) (t:A->bool).
11169      IMAGE (\x. a + x) s <_c t <=> s <_c t) /\
11170    (!a (s:A->bool) (t:real^N->bool).
11171      s <_c IMAGE (\x. a + x) t <=> s <_c t) /\
11172    (!a (s:real^N->bool) (t:A->bool).
11173      IMAGE (\x. a + x) s <=_c t <=> s <=_c t) /\
11174    (!a (s:A->bool) (t:real^N->bool).
11175      s <=_c IMAGE (\x. a + x) t <=> s <=_c t) /\
11176    (!a (s:real^N->bool) (t:A->bool).
11177      IMAGE (\x. a + x) s >_c t <=> s >_c t) /\
11178    (!a (s:A->bool) (t:real^N->bool).
11179      s >_c IMAGE (\x. a + x) t <=> s >_c t) /\
11180    (!a (s:real^N->bool) (t:A->bool).
11181      IMAGE (\x. a + x) s >=_c t <=> s >=_c t) /\
11182    (!a (s:A->bool) (t:real^N->bool).
11183      s >=_c IMAGE (\x. a + x) t <=> s >=_c t)`,
11184   REWRITE_TAC[gt_c; ge_c] THEN REPEAT STRIP_TAC THENL
11185    [MATCH_MP_TAC CARD_EQ_CONG;
11186     MATCH_MP_TAC CARD_EQ_CONG;
11187     MATCH_MP_TAC CARD_LT_CONG;
11188     MATCH_MP_TAC CARD_LT_CONG;
11189     MATCH_MP_TAC CARD_LE_CONG;
11190     MATCH_MP_TAC CARD_LE_CONG;
11191     MATCH_MP_TAC CARD_LT_CONG;
11192     MATCH_MP_TAC CARD_LT_CONG;
11193     MATCH_MP_TAC CARD_LE_CONG;
11194     MATCH_MP_TAC CARD_LE_CONG] THEN
11195   REWRITE_TAC[CARD_EQ_REFL] THEN MATCH_MP_TAC CARD_EQ_IMAGE THEN
11196   SIMP_TAC[VECTOR_ARITH `a + x:real^N = a + y <=> x = y`]) in
11197 add_translation_invariants card_translation_invariants;;
11198
11199 let card_linear_invariants = (CONJUNCTS o prove)
11200  (`(!(f:real^M->real^N) s (t:A->bool).
11201      linear f /\ (!x y. f x = f y ==> x = y)
11202      ==> (IMAGE f s =_c t <=> s =_c t)) /\
11203    (!(f:real^M->real^N) (s:A->bool) t.
11204      linear f /\ (!x y. f x = f y ==> x = y)
11205      ==> (s =_c IMAGE f t <=> s =_c t)) /\
11206    (!(f:real^M->real^N) s (t:A->bool).
11207      linear f /\ (!x y. f x = f y ==> x = y)
11208      ==> (IMAGE f s <_c t <=> s <_c t)) /\
11209    (!(f:real^M->real^N) (s:A->bool) t.
11210      linear f /\ (!x y. f x = f y ==> x = y)
11211      ==> (s <_c IMAGE f t <=> s <_c t)) /\
11212    (!(f:real^M->real^N) s (t:A->bool).
11213      linear f /\ (!x y. f x = f y ==> x = y)
11214      ==> (IMAGE f s <=_c t <=> s <=_c t)) /\
11215    (!(f:real^M->real^N) (s:A->bool) t.
11216      linear f /\ (!x y. f x = f y ==> x = y)
11217      ==> (s <=_c IMAGE f t <=> s <=_c t)) /\
11218    (!(f:real^M->real^N) s (t:A->bool).
11219      linear f /\ (!x y. f x = f y ==> x = y)
11220      ==> (IMAGE f s >_c t <=> s >_c t)) /\
11221    (!(f:real^M->real^N) (s:A->bool) t.
11222      linear f /\ (!x y. f x = f y ==> x = y)
11223      ==> (s >_c IMAGE f t <=> s >_c t)) /\
11224    (!(f:real^M->real^N) s (t:A->bool).
11225      linear f /\ (!x y. f x = f y ==> x = y)
11226      ==> (IMAGE f s >=_c t <=> s >=_c t)) /\
11227    (!(f:real^M->real^N) (s:A->bool) t.
11228      linear f /\ (!x y. f x = f y ==> x = y)
11229      ==> (s >=_c IMAGE f t <=> s >=_c t))`,
11230   REWRITE_TAC[gt_c; ge_c] THEN REPEAT STRIP_TAC THENL
11231    [MATCH_MP_TAC CARD_EQ_CONG;
11232     MATCH_MP_TAC CARD_EQ_CONG;
11233     MATCH_MP_TAC CARD_LT_CONG;
11234     MATCH_MP_TAC CARD_LT_CONG;
11235     MATCH_MP_TAC CARD_LE_CONG;
11236     MATCH_MP_TAC CARD_LE_CONG;
11237     MATCH_MP_TAC CARD_LT_CONG;
11238     MATCH_MP_TAC CARD_LT_CONG;
11239     MATCH_MP_TAC CARD_LE_CONG;
11240     MATCH_MP_TAC CARD_LE_CONG] THEN
11241   REWRITE_TAC[CARD_EQ_REFL] THEN MATCH_MP_TAC CARD_EQ_IMAGE THEN
11242   ASM_MESON_TAC[]) in
11243 add_linear_invariants card_linear_invariants;;
11244
11245 (* ------------------------------------------------------------------------- *)
11246 (* Basic homeomorphism definitions.                                          *)
11247 (* ------------------------------------------------------------------------- *)
11248
11249 let homeomorphism = new_definition
11250   `homeomorphism (s,t) (f,g) <=>
11251      (!x. x IN s ==> (g(f(x)) = x)) /\ (IMAGE f s = t) /\ f continuous_on s /\
11252      (!y. y IN t ==> (f(g(y)) = y)) /\ (IMAGE g t = s) /\ g continuous_on t`;;
11253
11254 parse_as_infix("homeomorphic",(12,"right"));;
11255
11256 let homeomorphic = new_definition
11257   `s homeomorphic t <=> ?f g. homeomorphism (s,t) (f,g)`;;
11258
11259 let HOMEOMORPHISM = prove
11260  (`!s:real^M->bool t:real^N->bool f g.
11261         homeomorphism (s,t) (f,g) <=>
11262          f continuous_on s /\ IMAGE f s SUBSET t /\
11263          g continuous_on t /\ IMAGE g t SUBSET s /\
11264          (!x. x IN s ==> g (f x) = x) /\
11265          (!y. y IN t ==> f (g y) = y)`,
11266   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphism] THEN
11267   EQ_TAC THEN SIMP_TAC[] THEN SET_TAC[]);;
11268
11269 let HOMEOMORPHISM_OF_SUBSETS = prove
11270  (`!f g s t s' t'.
11271     homeomorphism (s,t) (f,g) /\ s' SUBSET s /\ t' SUBSET t /\ IMAGE f s' = t'
11272     ==> homeomorphism (s',t') (f,g)`,
11273   REWRITE_TAC[homeomorphism] THEN
11274   REPEAT STRIP_TAC THEN
11275   TRY(MATCH_MP_TAC CONTINUOUS_ON_SUBSET) THEN ASM SET_TAC[]);;
11276
11277 let HOMEOMORPHISM_ID = prove
11278  (`!s:real^N->bool. homeomorphism (s,s) ((\x. x),(\x. x))`,
11279   REWRITE_TAC[homeomorphism; IMAGE_ID; CONTINUOUS_ON_ID]);;
11280
11281 let HOMEOMORPHISM_I = prove
11282  (`!s:real^N->bool. homeomorphism (s,s) (I,I)`,
11283   REWRITE_TAC[I_DEF; HOMEOMORPHISM_ID]);;
11284
11285 let HOMEOMORPHIC_REFL = prove
11286  (`!s:real^N->bool. s homeomorphic s`,
11287   REWRITE_TAC[homeomorphic] THEN MESON_TAC[HOMEOMORPHISM_I]);;
11288
11289 let HOMEOMORPHISM_SYM = prove
11290  (`!f:real^M->real^N g s t.
11291         homeomorphism (s,t) (f,g) <=> homeomorphism (t,s) (g,f)`,
11292   REWRITE_TAC[homeomorphism] THEN MESON_TAC[]);;
11293
11294 let HOMEOMORPHIC_SYM = prove
11295  (`!s t. s homeomorphic t <=> t homeomorphic s`,
11296   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; homeomorphism] THEN
11297   GEN_REWRITE_TAC RAND_CONV [SWAP_EXISTS_THM] THEN
11298   REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN CONV_TAC TAUT);;
11299
11300 let HOMEOMORPHISM_COMPOSE = prove
11301  (`!f:real^M->real^N g h:real^N->real^P k s t u.
11302         homeomorphism (s,t) (f,g) /\ homeomorphism (t,u) (h,k)
11303         ==> homeomorphism (s,u) (h o f,g o k)`,
11304   SIMP_TAC[homeomorphism; CONTINUOUS_ON_COMPOSE; IMAGE_o; o_THM] THEN
11305   SET_TAC[]);;
11306
11307 let HOMEOMORPHIC_TRANS = prove
11308  (`!s:real^M->bool t:real^N->bool u:real^P->bool.
11309         s homeomorphic t /\ t homeomorphic u ==> s homeomorphic u`,
11310   REWRITE_TAC[homeomorphic] THEN MESON_TAC[HOMEOMORPHISM_COMPOSE]);;
11311
11312 let HOMEOMORPHIC_IMP_CARD_EQ = prove
11313  (`!s:real^M->bool t:real^N->bool. s homeomorphic t ==> s =_c t`,
11314   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; homeomorphism; eq_c] THEN
11315   MATCH_MP_TAC MONO_EXISTS THEN SET_TAC[]);;
11316
11317 let HOMEOMORPHIC_EMPTY = prove
11318  (`(!s. (s:real^N->bool) homeomorphic ({}:real^M->bool) <=> s = {}) /\
11319    (!s. ({}:real^M->bool) homeomorphic (s:real^N->bool) <=> s = {})`,
11320   REWRITE_TAC[homeomorphic; homeomorphism; IMAGE_CLAUSES; IMAGE_EQ_EMPTY] THEN
11321   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
11322   ASM_REWRITE_TAC[continuous_on; NOT_IN_EMPTY]);;
11323
11324 let HOMEOMORPHIC_MINIMAL = prove
11325  (`!s t. s homeomorphic t <=>
11326             ?f g. (!x. x IN s ==> f(x) IN t /\ (g(f(x)) = x)) /\
11327                   (!y. y IN t ==> g(y) IN s /\ (f(g(y)) = y)) /\
11328                   f continuous_on s /\ g continuous_on t`,
11329   REWRITE_TAC[homeomorphic; homeomorphism; EXTENSION; IN_IMAGE] THEN
11330   REPEAT GEN_TAC THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN MESON_TAC[]);;
11331
11332 let HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_SELF = prove
11333  (`!f:real^M->real^N s.
11334         linear f /\ (!x y. f x = f y ==> x = y)
11335         ==> (IMAGE f s) homeomorphic s`,
11336   REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
11337   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_LEFT_INVERSE]) THEN
11338   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN DISCH_TAC THEN
11339   EXISTS_TAC `f:real^M->real^N` THEN
11340   ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON; FORALL_IN_IMAGE; FUN_IN_IMAGE] THEN
11341   ASM_SIMP_TAC[continuous_on; IMP_CONJ; FORALL_IN_IMAGE] THEN
11342   X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
11343   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
11344   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_BOUNDED_BELOW_POS) THEN
11345   ASM_REWRITE_TAC[] THEN
11346   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
11347   EXISTS_TAC `e * B:real` THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
11348   X_GEN_TAC `y:real^M` THEN ASM_SIMP_TAC[dist; GSYM LINEAR_SUB] THEN
11349   DISCH_TAC THEN ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ] THEN
11350   MATCH_MP_TAC(REAL_ARITH `a <= b ==> b < x ==> a < x`) THEN
11351   ASM_SIMP_TAC[REAL_LE_RDIV_EQ]);;
11352
11353 let HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_LEFT_EQ = prove
11354  (`!f:real^M->real^N s t.
11355         linear f /\ (!x y. f x = f y ==> x = y)
11356         ==> ((IMAGE f s) homeomorphic t <=> s homeomorphic t)`,
11357   REPEAT GEN_TAC THEN DISCH_THEN(ASSUME_TAC o SPEC `s:real^M->bool` o
11358     MATCH_MP HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_SELF) THEN
11359   EQ_TAC THENL
11360    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [HOMEOMORPHIC_SYM]);
11361     POP_ASSUM MP_TAC] THEN
11362   REWRITE_TAC[IMP_IMP; HOMEOMORPHIC_TRANS]);;
11363
11364 let HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_RIGHT_EQ = prove
11365  (`!f:real^M->real^N s t.
11366         linear f /\ (!x y. f x = f y ==> x = y)
11367         ==> (s homeomorphic (IMAGE f t) <=> s homeomorphic t)`,
11368   ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
11369   REWRITE_TAC[HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_LEFT_EQ]);;
11370
11371 add_linear_invariants
11372   [HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_LEFT_EQ;
11373    HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_RIGHT_EQ];;
11374
11375 let HOMEOMORPHIC_TRANSLATION_SELF = prove
11376  (`!a:real^N s. (IMAGE (\x. a + x) s) homeomorphic s`,
11377   REPEAT GEN_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
11378   EXISTS_TAC `\x:real^N. x - a` THEN
11379   EXISTS_TAC `\x:real^N. a + x` THEN
11380   SIMP_TAC[FORALL_IN_IMAGE; CONTINUOUS_ON_SUB; CONTINUOUS_ON_ID;
11381            CONTINUOUS_ON_CONST; CONTINUOUS_ON_ADD; VECTOR_ADD_SUB] THEN
11382   REWRITE_TAC[IN_IMAGE] THEN MESON_TAC[]);;
11383
11384 let HOMEOMORPHIC_TRANSLATION_LEFT_EQ = prove
11385  (`!a:real^N s t.
11386       (IMAGE (\x. a + x) s) homeomorphic t <=> s homeomorphic t`,
11387   MESON_TAC[HOMEOMORPHIC_TRANSLATION_SELF;
11388             HOMEOMORPHIC_SYM; HOMEOMORPHIC_TRANS]);;
11389
11390 let HOMEOMORPHIC_TRANSLATION_RIGHT_EQ = prove
11391  (`!a:real^N s t.
11392       s homeomorphic (IMAGE (\x. a + x) t) <=> s homeomorphic t`,
11393   ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
11394   REWRITE_TAC[HOMEOMORPHIC_TRANSLATION_LEFT_EQ]);;
11395
11396 add_translation_invariants
11397   [HOMEOMORPHIC_TRANSLATION_LEFT_EQ;
11398    HOMEOMORPHIC_TRANSLATION_RIGHT_EQ];;
11399
11400 let HOMEOMORPHISM_IMP_QUOTIENT_MAP = prove
11401  (`!f:real^M->real^N g s t.
11402     homeomorphism (s,t) (f,g)
11403     ==> !u. u SUBSET t
11404             ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN u} <=>
11405                  open_in (subtopology euclidean t) u)`,
11406   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphism] THEN
11407   STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_RIGHT_INVERSE_IMP_QUOTIENT_MAP THEN
11408   EXISTS_TAC `g:real^N->real^M` THEN ASM_REWRITE_TAC[SUBSET_REFL]);;
11409
11410 let HOMEOMORPHIC_PCROSS = prove
11411  (`!s:real^M->bool t:real^N->bool s':real^P->bool t':real^Q->bool.
11412         s homeomorphic s' /\ t homeomorphic t'
11413         ==> (s PCROSS t) homeomorphic (s' PCROSS t')`,
11414   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
11415   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
11416   DISCH_THEN(CONJUNCTS_THEN2
11417    (X_CHOOSE_THEN `f:real^M->real^P`
11418      (X_CHOOSE_THEN `f':real^P->real^M` STRIP_ASSUME_TAC))
11419    (X_CHOOSE_THEN `g:real^N->real^Q`
11420      (X_CHOOSE_THEN `g':real^Q->real^N` STRIP_ASSUME_TAC))) THEN
11421   MAP_EVERY EXISTS_TAC
11422    [`(\z. pastecart (f(fstcart z)) (g(sndcart z)))
11423      :real^(M,N)finite_sum->real^(P,Q)finite_sum`;
11424     `(\z. pastecart (f'(fstcart z)) (g'(sndcart z)))
11425      :real^(P,Q)finite_sum->real^(M,N)finite_sum`] THEN
11426   ASM_SIMP_TAC[FORALL_IN_PCROSS; FSTCART_PASTECART; SNDCART_PASTECART;
11427                SUBSET; FORALL_IN_IMAGE; PASTECART_IN_PCROSS] THEN
11428   CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN
11429   CONJ_TAC THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN
11430   MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
11431   SIMP_TAC[LINEAR_FSTCART; LINEAR_SNDCART; LINEAR_CONTINUOUS_ON] THEN
11432   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
11433           CONTINUOUS_ON_SUBSET)) THEN
11434   REWRITE_TAC[FORALL_IN_IMAGE; FORALL_IN_PCROSS; SUBSET] THEN
11435   SIMP_TAC[FSTCART_PASTECART; SNDCART_PASTECART]);;
11436
11437 let HOMEOMORPHIC_PCROSS_SYM = prove
11438  (`!s:real^M->bool t:real^N->bool. (s PCROSS t) homeomorphic (t PCROSS s)`,
11439   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; homeomorphism] THEN
11440   EXISTS_TAC `(\z. pastecart (sndcart z) (fstcart z))
11441               :real^(M,N)finite_sum->real^(N,M)finite_sum` THEN
11442   EXISTS_TAC `(\z. pastecart (sndcart z) (fstcart z))
11443               :real^(N,M)finite_sum->real^(M,N)finite_sum` THEN
11444   REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; SUBSET; FORALL_IN_IMAGE] THEN
11445   SIMP_TAC[CONTINUOUS_ON_PASTECART; LINEAR_CONTINUOUS_ON;
11446            LINEAR_FSTCART; LINEAR_SNDCART] THEN
11447   REWRITE_TAC[FORALL_IN_PCROSS; FSTCART_PASTECART; SNDCART_PASTECART;
11448     IN_IMAGE; EXISTS_PASTECART; PASTECART_INJ; PASTECART_IN_PCROSS] THEN
11449   MESON_TAC[]);;
11450
11451 let HOMEOMORPHIC_PCROSS_ASSOC = prove
11452  (`!s:real^M->bool t:real^N->bool u:real^P->bool.
11453         (s PCROSS (t PCROSS u)) homeomorphic ((s PCROSS t) PCROSS u)`,
11454   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
11455   MAP_EVERY EXISTS_TAC
11456    [`\z:real^(M,(N,P)finite_sum)finite_sum.
11457         pastecart (pastecart (fstcart z) (fstcart(sndcart z)))
11458                   (sndcart(sndcart z))`;
11459     `\z:real^((M,N)finite_sum,P)finite_sum.
11460         pastecart (fstcart(fstcart z))
11461                   (pastecart (sndcart(fstcart z)) (sndcart z))`] THEN
11462   REWRITE_TAC[FORALL_IN_PCROSS; SUBSET; FORALL_IN_IMAGE;
11463               RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
11464   SIMP_TAC[FSTCART_PASTECART; SNDCART_PASTECART; PASTECART_IN_PCROSS] THEN
11465   CONJ_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
11466   REPEAT(MATCH_MP_TAC LINEAR_PASTECART THEN CONJ_TAC) THEN
11467   TRY(GEN_REWRITE_TAC RAND_CONV [GSYM o_DEF] THEN
11468       MATCH_MP_TAC LINEAR_COMPOSE) THEN
11469   REWRITE_TAC[LINEAR_FSTCART; LINEAR_SNDCART]);;
11470
11471 let HOMEOMORPHIC_SCALING_LEFT = prove
11472  (`!c. &0 < c
11473        ==> !s t. (IMAGE (\x. c % x) s) homeomorphic t <=> s homeomorphic t`,
11474   REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN
11475   MATCH_MP_TAC HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_LEFT_EQ THEN
11476   ASM_SIMP_TAC[VECTOR_MUL_LCANCEL; REAL_LT_IMP_NZ; LINEAR_SCALING]);;
11477
11478 let HOMEOMORPHIC_SCALING_RIGHT = prove
11479  (`!c. &0 < c
11480        ==> !s t. s homeomorphic (IMAGE (\x. c % x) t) <=> s homeomorphic t`,
11481   REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN
11482   MATCH_MP_TAC HOMEOMORPHIC_INJECTIVE_LINEAR_IMAGE_RIGHT_EQ THEN
11483   ASM_SIMP_TAC[VECTOR_MUL_LCANCEL; REAL_LT_IMP_NZ; LINEAR_SCALING]);;
11484
11485 let HOMEOMORPHIC_SUBSPACES = prove
11486  (`!s:real^M->bool t:real^N->bool.
11487         subspace s /\ subspace t /\ dim s = dim t ==> s homeomorphic t`,
11488   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
11489   DISCH_THEN(MP_TAC o MATCH_MP ISOMETRIES_SUBSPACES) THEN
11490   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^M->real^N` THEN
11491   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^M` THEN
11492   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTER; IN_CBALL_0] THEN
11493   SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN ASM SET_TAC[]);;
11494
11495 let HOMEOMORPHIC_FINITE = prove
11496  (`!s:real^M->bool t:real^N->bool.
11497         FINITE s /\ FINITE t ==> (s homeomorphic t <=> CARD s = CARD t)`,
11498   REPEAT STRIP_TAC THEN EQ_TAC THENL
11499    [DISCH_THEN(MP_TAC o MATCH_MP HOMEOMORPHIC_IMP_CARD_EQ) THEN
11500     ASM_SIMP_TAC[CARD_EQ_CARD];
11501     STRIP_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
11502     MP_TAC(ISPECL [`s:real^M->bool`; `t:real^N->bool`]
11503         CARD_EQ_BIJECTIONS) THEN
11504     ASM_REWRITE_TAC[] THEN
11505     REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
11506     ASM_SIMP_TAC[CONTINUOUS_ON_FINITE] THEN ASM SET_TAC[]]);;
11507
11508 let HOMEOMORPHIC_FINITE_STRONG = prove
11509  (`!s:real^M->bool t:real^N->bool.
11510         FINITE s \/ FINITE t
11511         ==> (s homeomorphic t <=> FINITE s /\ FINITE t /\ CARD s = CARD t)`,
11512   REPEAT GEN_TAC THEN DISCH_TAC THEN EQ_TAC THEN
11513   SIMP_TAC[HOMEOMORPHIC_FINITE] THEN DISCH_TAC THEN
11514   FIRST_ASSUM(MP_TAC o MATCH_MP CARD_FINITE_CONG o MATCH_MP
11515     HOMEOMORPHIC_IMP_CARD_EQ) THEN
11516   FIRST_X_ASSUM DISJ_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
11517   ASM_MESON_TAC[HOMEOMORPHIC_FINITE]);;
11518
11519 let HOMEOMORPHIC_SING = prove
11520  (`!a:real^M b:real^N. {a} homeomorphic {b}`,
11521   SIMP_TAC[HOMEOMORPHIC_FINITE; FINITE_SING; CARD_SING]);;
11522
11523 let HOMEOMORPHIC_PCROSS_SING = prove
11524  (`(!s:real^M->bool a:real^N. s homeomorphic (s PCROSS {a})) /\
11525    (!s:real^M->bool a:real^N. s homeomorphic ({a} PCROSS s))`,
11526   MATCH_MP_TAC(TAUT `(p ==> q) /\ p ==> p /\ q`) THEN CONJ_TAC THENL
11527    [MESON_TAC[HOMEOMORPHIC_PCROSS_SYM; HOMEOMORPHIC_TRANS]; ALL_TAC] THEN
11528   REPEAT GEN_TAC THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
11529   EXISTS_TAC `\x. (pastecart x a:real^(M,N)finite_sum)` THEN
11530   EXISTS_TAC `fstcart:real^(M,N)finite_sum->real^M` THEN
11531   SIMP_TAC[CONTINUOUS_ON_PASTECART; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN
11532   SIMP_TAC[LINEAR_FSTCART; LINEAR_CONTINUOUS_ON; SUBSET; FORALL_IN_IMAGE] THEN
11533   REWRITE_TAC[FORALL_IN_PCROSS; PASTECART_IN_PCROSS; IN_SING] THEN
11534   SIMP_TAC[FSTCART_PASTECART]);;
11535
11536 (* ------------------------------------------------------------------------- *)
11537 (* Inverse function property for open/closed maps.                           *)
11538 (* ------------------------------------------------------------------------- *)
11539
11540 let CONTINUOUS_ON_INVERSE_OPEN_MAP = prove
11541  (`!f:real^M->real^N g s t.
11542         f continuous_on s /\ IMAGE f s = t /\ (!x. x IN s ==> g(f x) = x) /\
11543         (!u. open_in (subtopology euclidean s) u
11544              ==> open_in (subtopology euclidean t) (IMAGE f u))
11545         ==> g continuous_on t`,
11546   REPEAT STRIP_TAC THEN
11547   MP_TAC(ISPECL [`g:real^N->real^M`; `t:real^N->bool`; `s:real^M->bool`]
11548         CONTINUOUS_ON_OPEN_GEN) THEN
11549   ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN SUBST1_TAC] THEN
11550   X_GEN_TAC `u:real^M->bool` THEN DISCH_TAC THEN
11551   FIRST_X_ASSUM(MP_TAC o SPEC `u:real^M->bool`) THEN ASM_REWRITE_TAC[] THEN
11552   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
11553   FIRST_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN
11554   ASM SET_TAC[]);;
11555
11556 let CONTINUOUS_ON_INVERSE_CLOSED_MAP = prove
11557  (`!f:real^M->real^N g s t.
11558         f continuous_on s /\ IMAGE f s = t /\ (!x. x IN s ==> g(f x) = x) /\
11559         (!u. closed_in (subtopology euclidean s) u
11560              ==> closed_in (subtopology euclidean t) (IMAGE f u))
11561         ==> g continuous_on t`,
11562   REPEAT STRIP_TAC THEN
11563   MP_TAC(ISPECL [`g:real^N->real^M`; `t:real^N->bool`; `s:real^M->bool`]
11564         CONTINUOUS_ON_CLOSED_GEN) THEN
11565   ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN SUBST1_TAC] THEN
11566   X_GEN_TAC `u:real^M->bool` THEN DISCH_TAC THEN
11567   FIRST_X_ASSUM(MP_TAC o SPEC `u:real^M->bool`) THEN ASM_REWRITE_TAC[] THEN
11568   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
11569   FIRST_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [closed_in]) THEN
11570   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN ASM SET_TAC[]);;
11571
11572 let HOMEOMORPHISM_INJECTIVE_OPEN_MAP = prove
11573  (`!f:real^M->real^N s t.
11574         f continuous_on s /\ IMAGE f s = t /\
11575         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) /\
11576         (!u. open_in (subtopology euclidean s) u
11577              ==> open_in (subtopology euclidean t) (IMAGE f u))
11578         ==> ?g. homeomorphism (s,t) (f,g)`,
11579   REPEAT STRIP_TAC THEN
11580   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
11581   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^M` THEN
11582   DISCH_TAC THEN ASM_SIMP_TAC[homeomorphism] THEN
11583   REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
11584   MATCH_MP_TAC CONTINUOUS_ON_INVERSE_OPEN_MAP THEN ASM_MESON_TAC[]);;
11585
11586 let HOMEOMORPHISM_INJECTIVE_CLOSED_MAP = prove
11587  (`!f:real^M->real^N s t.
11588         f continuous_on s /\ IMAGE f s = t /\
11589         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) /\
11590         (!u. closed_in (subtopology euclidean s) u
11591              ==> closed_in (subtopology euclidean t) (IMAGE f u))
11592         ==> ?g. homeomorphism (s,t) (f,g)`,
11593   REPEAT STRIP_TAC THEN
11594   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
11595   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^M` THEN
11596   DISCH_TAC THEN ASM_SIMP_TAC[homeomorphism] THEN
11597   REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
11598   MATCH_MP_TAC CONTINUOUS_ON_INVERSE_CLOSED_MAP THEN ASM_MESON_TAC[]);;
11599
11600 let HOMEOMORPHISM_IMP_OPEN_MAP = prove
11601  (`!f:real^M->real^N g s t u.
11602         homeomorphism (s,t) (f,g) /\ open_in (subtopology euclidean s) u
11603         ==> open_in (subtopology euclidean t) (IMAGE f u)`,
11604   REWRITE_TAC[homeomorphism] THEN REPEAT STRIP_TAC THEN
11605   SUBGOAL_THEN `IMAGE (f:real^M->real^N) u =
11606                  {y | y IN t /\ g(y) IN u}`
11607   SUBST1_TAC THENL
11608    [FIRST_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN
11609     ASM SET_TAC[];
11610     MATCH_MP_TAC CONTINUOUS_ON_IMP_OPEN_IN THEN ASM_REWRITE_TAC[]]);;
11611
11612 let HOMEOMORPHISM_IMP_CLOSED_MAP = prove
11613  (`!f:real^M->real^N g s t u.
11614         homeomorphism (s,t) (f,g) /\ closed_in (subtopology euclidean s) u
11615         ==> closed_in (subtopology euclidean t) (IMAGE f u)`,
11616   REWRITE_TAC[homeomorphism] THEN REPEAT STRIP_TAC THEN
11617   SUBGOAL_THEN `IMAGE (f:real^M->real^N) u =
11618                  {y | y IN t /\ g(y) IN u}`
11619   SUBST1_TAC THENL
11620    [FIRST_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [closed_in]) THEN
11621     REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN ASM SET_TAC[];
11622     MATCH_MP_TAC CONTINUOUS_ON_IMP_CLOSED_IN THEN ASM_REWRITE_TAC[]]);;
11623
11624 let HOMEOMORPHISM_INJECTIVE_OPEN_MAP_EQ = prove
11625  (`!f:real^M->real^N s t.
11626         f continuous_on s /\ IMAGE f s = t /\
11627         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
11628         ==> ((?g. homeomorphism (s,t) (f,g)) <=>
11629              !u. open_in (subtopology euclidean s) u
11630                  ==> open_in (subtopology euclidean t) (IMAGE f u))`,
11631   REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL
11632    [MATCH_MP_TAC HOMEOMORPHISM_IMP_OPEN_MAP THEN ASM_MESON_TAC[];
11633     MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP THEN
11634     ASM_REWRITE_TAC[]]);;
11635
11636 let HOMEOMORPHISM_INJECTIVE_CLOSED_MAP_EQ = prove
11637  (`!f:real^M->real^N s t.
11638         f continuous_on s /\ IMAGE f s = t /\
11639         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
11640         ==> ((?g. homeomorphism (s,t) (f,g)) <=>
11641              !u. closed_in (subtopology euclidean s) u
11642                  ==> closed_in (subtopology euclidean t) (IMAGE f u))`,
11643   REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL
11644    [MATCH_MP_TAC HOMEOMORPHISM_IMP_CLOSED_MAP THEN ASM_MESON_TAC[];
11645     MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_CLOSED_MAP THEN
11646     ASM_REWRITE_TAC[]]);;
11647
11648 let INJECTIVE_MAP_OPEN_IFF_CLOSED = prove
11649  (`!f:real^M->real^N s t.
11650         f continuous_on s /\ IMAGE f s = t /\
11651         (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
11652         ==> ((!u. open_in (subtopology euclidean s) u
11653                   ==> open_in (subtopology euclidean t) (IMAGE f u)) <=>
11654              (!u. closed_in (subtopology euclidean s) u
11655                   ==> closed_in (subtopology euclidean t) (IMAGE f u)))`,
11656   REPEAT STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
11657   EXISTS_TAC `?g:real^N->real^M. homeomorphism (s,t) (f,g)` THEN
11658   CONJ_TAC THENL
11659    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP_EQ;
11660     MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_CLOSED_MAP_EQ] THEN
11661   ASM_REWRITE_TAC[]);;
11662
11663 (* ------------------------------------------------------------------------- *)
11664 (* Relatively weak hypotheses if the domain of the function is compact.      *)
11665 (* ------------------------------------------------------------------------- *)
11666
11667 let CONTINUOUS_IMP_CLOSED_MAP = prove
11668  (`!f:real^M->real^N s t.
11669         f continuous_on s /\ IMAGE f s = t /\ compact s
11670         ==> !u. closed_in (subtopology euclidean s) u
11671                 ==> closed_in (subtopology euclidean t) (IMAGE f u)`,
11672   SIMP_TAC[CLOSED_IN_CLOSED_EQ; COMPACT_IMP_CLOSED] THEN
11673   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSED_CLOSED_IN_TRANS THEN
11674   EXPAND_TAC "t" THEN REWRITE_TAC[CONJ_ASSOC] THEN
11675   CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
11676   CONJ_TAC THEN MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
11677   MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN
11678   ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_IN_CLOSED_TRANS;
11679                 BOUNDED_SUBSET; CONTINUOUS_ON_SUBSET]);;
11680
11681 let CONTINUOUS_ON_INVERSE = prove
11682  (`!f:real^M->real^N g s.
11683         f continuous_on s /\ compact s /\ (!x. x IN s ==> (g(f(x)) = x))
11684         ==> g continuous_on (IMAGE f s)`,
11685   REPEAT STRIP_TAC THEN REWRITE_TAC[CONTINUOUS_ON_CLOSED] THEN
11686   SUBGOAL_THEN `IMAGE g (IMAGE (f:real^M->real^N) s) = s` SUBST1_TAC THENL
11687    [REWRITE_TAC[EXTENSION; IN_IMAGE] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
11688   X_GEN_TAC `t:real^M->bool` THEN DISCH_TAC THEN
11689   REWRITE_TAC[CLOSED_IN_CLOSED] THEN
11690   EXISTS_TAC `IMAGE (f:real^M->real^N) t` THEN CONJ_TAC THENL
11691    [MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
11692     MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
11693     FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET) THEN
11694     REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
11695     ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_IN_CLOSED_TRANS;
11696                   BOUNDED_SUBSET; CONTINUOUS_ON_SUBSET];
11697     REWRITE_TAC[EXTENSION; IN_INTER; IN_ELIM_THM; IN_IMAGE] THEN
11698     ASM_MESON_TAC[CLOSED_IN_SUBSET; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY; SUBSET]]);;
11699
11700 let HOMEOMORPHISM_COMPACT = prove
11701  (`!s f t. compact s /\ f continuous_on s /\ (IMAGE f s = t) /\
11702            (!x y. x IN s /\ y IN s /\ (f x = f y) ==> (x = y))
11703            ==> ?g. homeomorphism(s,t) (f,g)`,
11704   REWRITE_TAC[INJECTIVE_ON_LEFT_INVERSE] THEN REPEAT GEN_TAC THEN
11705   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
11706   MATCH_MP_TAC MONO_EXISTS THEN ASM_SIMP_TAC[EXTENSION; homeomorphism] THEN
11707   FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN
11708   ASM_MESON_TAC[CONTINUOUS_ON_INVERSE; IN_IMAGE]);;
11709
11710 let HOMEOMORPHIC_COMPACT = prove
11711  (`!s f t. compact s /\ f continuous_on s /\ (IMAGE f s = t) /\
11712            (!x y. x IN s /\ y IN s /\ (f x = f y) ==> (x = y))
11713            ==> s homeomorphic t`,
11714   REWRITE_TAC[homeomorphic] THEN MESON_TAC[HOMEOMORPHISM_COMPACT]);;
11715
11716 (* ------------------------------------------------------------------------- *)
11717 (* Lemmas about composition of homeomorphisms.                               *)
11718 (* ------------------------------------------------------------------------- *)
11719
11720 let HOMEOMORPHISM_FROM_COMPOSITION_SURJECTIVE = prove
11721  (`!f:real^M->real^N g:real^N->real^P s t u.
11722         f continuous_on s /\ IMAGE f s = t /\
11723         g continuous_on t /\ IMAGE g t SUBSET u /\
11724         (?h. homeomorphism (s,u) (g o f,h))
11725         ==> (?f'. homeomorphism (s,t) (f,f')) /\
11726             (?g'. homeomorphism (t,u) (g,g'))`,
11727   REPEAT GEN_TAC THEN STRIP_TAC THEN
11728   RULE_ASSUM_TAC(REWRITE_RULE[homeomorphism; o_THM]) THEN
11729   MATCH_MP_TAC(TAUT `q /\ (q ==> p) ==> p /\ q`) THEN CONJ_TAC THENL
11730    [MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP THEN
11731     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
11732     MATCH_MP_TAC OPEN_MAP_FROM_COMPOSITION_SURJECTIVE THEN
11733     MAP_EVERY EXISTS_TAC [`f:real^M->real^N`; `s:real^M->bool`] THEN
11734     ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
11735     MATCH_MP_TAC HOMEOMORPHISM_IMP_OPEN_MAP THEN
11736     MAP_EVERY EXISTS_TAC [`h:real^P->real^M`; `s:real^M->bool`] THEN
11737     ASM_REWRITE_TAC[homeomorphism; o_THM];
11738     REWRITE_TAC[homeomorphism; o_THM] THEN
11739     DISCH_THEN(X_CHOOSE_THEN `g':real^P->real^N` STRIP_ASSUME_TAC) THEN
11740     EXISTS_TAC `(h:real^P->real^M) o (g:real^N->real^P)` THEN
11741     ASM_SIMP_TAC[o_THM; IMAGE_o] THEN
11742     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
11743     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
11744     ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]]);;
11745
11746 let HOMEOMORPHISM_FROM_COMPOSITION_INJECTIVE = prove
11747  (`!f:real^M->real^N g:real^N->real^P s t u.
11748         f continuous_on s /\ IMAGE f s SUBSET t /\
11749         g continuous_on t /\ IMAGE g t SUBSET u /\
11750         (!x y. x IN t /\ y IN t /\ g x = g y ==> x = y) /\
11751         (?h. homeomorphism (s,u) (g o f,h))
11752         ==> (?f'. homeomorphism (s,t) (f,f')) /\
11753             (?g'. homeomorphism (t,u) (g,g'))`,
11754   REPEAT GEN_TAC THEN STRIP_TAC THEN
11755   RULE_ASSUM_TAC(REWRITE_RULE[homeomorphism; o_THM]) THEN
11756   MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
11757    [MATCH_MP_TAC HOMEOMORPHISM_INJECTIVE_OPEN_MAP THEN
11758     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
11759     MATCH_MP_TAC OPEN_MAP_FROM_COMPOSITION_INJECTIVE THEN
11760     MAP_EVERY EXISTS_TAC [`g:real^N->real^P`; `u:real^P->bool`] THEN
11761     ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THEN
11762     MATCH_MP_TAC HOMEOMORPHISM_IMP_OPEN_MAP THEN
11763     MAP_EVERY EXISTS_TAC [`h:real^P->real^M`; `s:real^M->bool`] THEN
11764     ASM_REWRITE_TAC[homeomorphism; o_THM];
11765     REWRITE_TAC[homeomorphism; o_THM] THEN
11766     DISCH_THEN(X_CHOOSE_THEN `f':real^N->real^M` STRIP_ASSUME_TAC) THEN
11767     EXISTS_TAC `(f:real^M->real^N) o (h:real^P->real^M)` THEN
11768     ASM_SIMP_TAC[o_THM; IMAGE_o] THEN
11769     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
11770     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
11771     ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]]);;
11772
11773 (* ------------------------------------------------------------------------- *)
11774 (* Preservation of topological properties.                                   *)
11775 (* ------------------------------------------------------------------------- *)
11776
11777 let HOMEOMORPHIC_COMPACTNESS = prove
11778  (`!s t. s homeomorphic t ==> (compact s <=> compact t)`,
11779   REWRITE_TAC[homeomorphic; homeomorphism] THEN
11780   MESON_TAC[COMPACT_CONTINUOUS_IMAGE]);;
11781
11782 let HOMEOMORPHIC_CONNECTEDNESS = prove
11783  (`!s t. s homeomorphic t ==> (connected s <=> connected t)`,
11784   REWRITE_TAC[homeomorphic; homeomorphism] THEN
11785   MESON_TAC[CONNECTED_CONTINUOUS_IMAGE]);;
11786
11787 (* ------------------------------------------------------------------------- *)
11788 (* Results on translation, scaling etc.                                      *)
11789 (* ------------------------------------------------------------------------- *)
11790
11791 let HOMEOMORPHIC_SCALING = prove
11792  (`!s:real^N->bool c. ~(c = &0) ==> s homeomorphic (IMAGE (\x. c % x) s)`,
11793   REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
11794   MAP_EVERY EXISTS_TAC [`\x:real^N. c % x`; `\x:real^N. inv(c) % x`] THEN
11795   ASM_SIMP_TAC[CONTINUOUS_ON_CMUL; CONTINUOUS_ON_ID; FORALL_IN_IMAGE] THEN
11796   ASM_SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_MUL_RINV] THEN
11797   SIMP_TAC[VECTOR_MUL_LID; IN_IMAGE; REAL_MUL_LID] THEN MESON_TAC[]);;
11798
11799 let HOMEOMORPHIC_TRANSLATION = prove
11800  (`!s a:real^N. s homeomorphic (IMAGE (\x. a + x) s)`,
11801   REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
11802   MAP_EVERY EXISTS_TAC [`\x:real^N. a +  x`; `\x:real^N. --a + x`] THEN
11803   ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN
11804   SIMP_TAC[VECTOR_ADD_ASSOC; VECTOR_ADD_LINV; VECTOR_ADD_RINV;
11805            FORALL_IN_IMAGE; VECTOR_ADD_LID] THEN
11806   REWRITE_TAC[IN_IMAGE] THEN MESON_TAC[]);;
11807
11808 let HOMEOMORPHIC_AFFINITY = prove
11809  (`!s a:real^N c. ~(c = &0) ==> s homeomorphic (IMAGE (\x. a + c % x) s)`,
11810   REPEAT STRIP_TAC THEN
11811   MATCH_MP_TAC HOMEOMORPHIC_TRANS THEN
11812   EXISTS_TAC `IMAGE (\x:real^N. c % x) s` THEN
11813   ASM_SIMP_TAC[HOMEOMORPHIC_SCALING] THEN
11814   SUBGOAL_THEN `(\x:real^N. a + c % x) = (\x. a + x) o (\x. c % x)`
11815   SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
11816   REWRITE_TAC[IMAGE_o; HOMEOMORPHIC_TRANSLATION]);;
11817
11818 let [HOMEOMORPHIC_BALLS; HOMEOMORPHIC_CBALLS; HOMEOMORPHIC_SPHERES] =
11819   (CONJUNCTS o prove)
11820  (`(!a:real^N b:real^N d e.
11821       &0 < d /\ &0 < e ==> ball(a,d) homeomorphic ball(b,e)) /\
11822    (!a:real^N b:real^N d e.
11823       &0 < d /\ &0 < e ==> cball(a,d) homeomorphic cball(b,e)) /\
11824    (!a:real^N b:real^N d e.
11825       &0 < d /\ &0 < e ==> sphere(a,d) homeomorphic sphere(b,e))`,
11826   REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
11827   EXISTS_TAC `\x:real^N. b + (e / d) % (x - a)` THEN
11828   EXISTS_TAC `\x:real^N. a + (d / e) % (x - b)` THEN
11829   ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_SUB; CONTINUOUS_ON_CMUL;
11830     CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID; IN_BALL; IN_CBALL; IN_SPHERE] THEN
11831   REWRITE_TAC[dist; VECTOR_ARITH `a - (a + b) = --b:real^N`; NORM_NEG] THEN
11832   REWRITE_TAC[real_div; VECTOR_ARITH
11833    `a + d % ((b + e % (x - a)) - b) = (&1 - d * e) % a + (d * e) % x`] THEN
11834   ONCE_REWRITE_TAC[REAL_ARITH
11835     `(e * d') * (d * e') = (d * d') * (e * e')`] THEN
11836   ASM_SIMP_TAC[REAL_MUL_RINV; REAL_LT_IMP_NZ; REAL_MUL_LID; REAL_SUB_REFL] THEN
11837   REWRITE_TAC[NORM_MUL; VECTOR_MUL_LZERO; VECTOR_MUL_LID; VECTOR_ADD_LID] THEN
11838   ASM_SIMP_TAC[REAL_ABS_MUL; REAL_ABS_INV; REAL_ARITH
11839    `&0 < x ==> (abs x = x)`] THEN
11840   GEN_REWRITE_TAC(BINOP_CONV o BINDER_CONV o funpow 2 RAND_CONV)
11841         [GSYM REAL_MUL_RID] THEN
11842   ONCE_REWRITE_TAC[AC REAL_MUL_AC `(a * b) * c = (a * c) * b`] THEN
11843   ASM_SIMP_TAC[REAL_LE_LMUL_EQ; GSYM real_div; REAL_LE_LDIV_EQ; REAL_MUL_LID;
11844     GSYM REAL_MUL_ASSOC; REAL_LT_LMUL_EQ; REAL_LT_LDIV_EQ; NORM_SUB] THEN
11845   ASM_SIMP_TAC[REAL_DIV_REFL; REAL_LT_IMP_NZ; REAL_MUL_RID]);;
11846
11847 (* ------------------------------------------------------------------------- *)
11848 (* Homeomorphism of one-point compactifications.                             *)
11849 (* ------------------------------------------------------------------------- *)
11850
11851 let HOMEOMORPHIC_ONE_POINT_COMPACTIFICATIONS = prove
11852  (`!s:real^M->bool t:real^N->bool a b.
11853         compact s /\ compact t /\ a IN s /\ b IN t /\
11854         (s DELETE a) homeomorphic (t DELETE b)
11855         ==> s homeomorphic t`,
11856   REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHIC_COMPACT THEN
11857   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [homeomorphic]) THEN
11858   REWRITE_TAC[HOMEOMORPHISM; LEFT_IMP_EXISTS_THM] THEN
11859   MAP_EVERY X_GEN_TAC [`f:real^M->real^N`; `g:real^N->real^M`] THEN
11860   STRIP_TAC THEN
11861   EXISTS_TAC `\x. if x = a then b else (f:real^M->real^N) x` THEN
11862   ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
11863   REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
11864   X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
11865   ASM_CASES_TAC `x:real^M = a` THEN ASM_REWRITE_TAC[] THENL
11866    [REWRITE_TAC[continuous_within] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
11867     MP_TAC(ISPECL [`b:real^N`; `e:real`] CENTRE_IN_BALL) THEN
11868     ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
11869     SUBGOAL_THEN
11870       `closed_in (subtopology euclidean s)
11871                  { x | x IN (s DELETE a) /\
11872                        (f:real^M->real^N)(x) IN t DIFF ball(b,e)}`
11873     MP_TAC THENL
11874      [MATCH_MP_TAC CLOSED_SUBSET THEN CONJ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
11875       MATCH_MP_TAC COMPACT_IMP_CLOSED THEN SUBGOAL_THEN
11876        `{x | x IN s DELETE a /\ f x IN t DIFF ball(b,e)} =
11877         IMAGE (g:real^N->real^M) (t DIFF ball (b,e))`
11878       SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
11879       MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
11880       ASM_SIMP_TAC[COMPACT_DIFF; OPEN_BALL] THEN
11881       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
11882         CONTINUOUS_ON_SUBSET)) THEN ASM SET_TAC[];
11883       REWRITE_TAC[closed_in; open_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
11884       DISCH_THEN(MP_TAC o SPEC `a:real^M` o last o CONJUNCTS) THEN
11885       ASM_REWRITE_TAC[IN_ELIM_THM; IN_DIFF; IN_DELETE] THEN
11886       SIMP_TAC[IMP_CONJ; DE_MORGAN_THM] THEN
11887       MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN
11888       ASM_REWRITE_TAC[] THEN COND_CASES_TAC THEN
11889       ASM_REWRITE_TAC[DIST_REFL] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
11890       RULE_ASSUM_TAC(REWRITE_RULE[IN_BALL]) THEN ASM SET_TAC[]];
11891     UNDISCH_TAC `(f:real^M->real^N) continuous_on (s DELETE a)` THEN
11892     REWRITE_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN
11893     DISCH_THEN(MP_TAC o SPEC `x:real^M`) THEN ASM_REWRITE_TAC[IN_DELETE] THEN
11894     REWRITE_TAC[continuous_within] THEN
11895     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
11896     ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[IN_DELETE] THEN
11897     DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
11898     EXISTS_TAC `min d (dist(a:real^M,x))` THEN
11899     ASM_REWRITE_TAC[REAL_LT_MIN; GSYM DIST_NZ] THEN
11900     ASM_MESON_TAC[REAL_LT_REFL]]);;
11901
11902 (* ------------------------------------------------------------------------- *)
11903 (* Homeomorphisms between open intervals in real^1 and then in real^N.       *)
11904 (* Could prove similar things for closed intervals, but they drop out of     *)
11905 (* later stuff in "convex.ml" even more easily.                              *)
11906 (* ------------------------------------------------------------------------- *)
11907
11908 let HOMEOMORPHIC_OPEN_INTERVALS_1 = prove
11909  (`!a b c d.
11910         drop a < drop b /\ drop c < drop d
11911         ==> interval(a,b) homeomorphic interval(c,d)`,
11912   SUBGOAL_THEN
11913    `!a b. drop a < drop b
11914           ==> interval(vec 0:real^1,vec 1) homeomorphic interval(a,b)`
11915   ASSUME_TAC THENL
11916    [REPEAT STRIP_TAC THEN REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
11917     EXISTS_TAC `(\x. a + drop x % (b - a)):real^1->real^1` THEN
11918     EXISTS_TAC `(\x. inv(drop b - drop a) % (x - a)):real^1->real^1` THEN
11919     ASM_REWRITE_TAC[IN_INTERVAL_1; GSYM DROP_EQ] THEN
11920     REWRITE_TAC[DROP_ADD; DROP_CMUL; DROP_NEG; DROP_VEC; DROP_SUB] THEN
11921     REWRITE_TAC[REAL_ARITH `inv b * a:real = a / b`] THEN
11922     ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ; REAL_SUB_LT;
11923        REAL_LT_ADDR; REAL_EQ_LDIV_EQ; REAL_DIV_RMUL; REAL_LT_IMP_NZ;
11924        REAL_LT_MUL; REAL_MUL_LZERO; REAL_ADD_SUB; REAL_LT_RMUL_EQ;
11925        REAL_ARITH `a + x < b <=> x < &1 * (b - a)`] THEN
11926     REPEAT CONJ_TAC THENL
11927      [REAL_ARITH_TAC;
11928       MATCH_MP_TAC CONTINUOUS_ON_ADD THEN REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
11929       MATCH_MP_TAC CONTINUOUS_ON_VMUL THEN
11930       REWRITE_TAC[o_DEF; LIFT_DROP; CONTINUOUS_ON_ID];
11931       MATCH_MP_TAC CONTINUOUS_ON_CMUL THEN
11932       ASM_SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID]];
11933     REPEAT STRIP_TAC THEN
11934     FIRST_ASSUM(MP_TAC o SPECL [`a:real^1`; `b:real^1`]) THEN
11935     FIRST_X_ASSUM(MP_TAC o SPECL [`c:real^1`; `d:real^1`]) THEN
11936     ASM_REWRITE_TAC[GSYM IMP_CONJ_ALT] THEN
11937     GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [HOMEOMORPHIC_SYM] THEN
11938     REWRITE_TAC[HOMEOMORPHIC_TRANS]]);;
11939
11940 let HOMEOMORPHIC_OPEN_INTERVAL_UNIV_1 = prove
11941  (`!a b. drop a < drop b ==> interval(a,b) homeomorphic (:real^1)`,
11942   REPEAT STRIP_TAC THEN
11943   MP_TAC(SPECL [`a:real^1`; `b:real^1`; `--vec 1:real^1`; `vec 1:real^1`]
11944         HOMEOMORPHIC_OPEN_INTERVALS_1) THEN
11945   ASM_REWRITE_TAC[DROP_VEC; DROP_NEG] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
11946   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] HOMEOMORPHIC_TRANS) THEN
11947   POP_ASSUM_LIST(K ALL_TAC) THEN
11948   REWRITE_TAC[HOMEOMORPHIC_MINIMAL; IN_UNIV] THEN
11949   EXISTS_TAC `\x:real^1. inv(&1 - norm x) % x` THEN
11950   EXISTS_TAC `\y. if &0 <= drop y then inv(&1 + drop y) % y
11951                   else inv(&1 - drop y) % y` THEN
11952   REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
11953    [X_GEN_TAC `x:real^1` THEN REWRITE_TAC[IN_INTERVAL_1] THEN
11954     REWRITE_TAC[DROP_NEG; DROP_VEC; DROP_CMUL; NORM_REAL; GSYM drop] THEN
11955     SIMP_TAC[REAL_LE_MUL_EQ; REAL_LT_INV_EQ; REAL_LE_MUL_EQ; REAL_ARITH
11956      `--a < x /\ x < a ==> &0 < a - abs x`] THEN
11957     SIMP_TAC[real_abs; VECTOR_MUL_ASSOC] THEN
11958     COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
11959     GEN_REWRITE_TAC RAND_CONV [GSYM VECTOR_MUL_LID] THEN
11960     AP_THM_TAC THEN AP_TERM_TAC THEN
11961     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD;
11962     X_GEN_TAC `y:real^1` THEN COND_CASES_TAC THEN
11963     ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_NEG; DROP_VEC; REAL_BOUNDS_LT] THEN
11964     REWRITE_TAC[DROP_CMUL; REAL_ABS_MUL; REAL_ABS_INV] THEN
11965     REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_MUL_SYM] real_div)] THEN
11966     ASM_SIMP_TAC[REAL_LT_LDIV_EQ; REAL_ARITH `&0 <= x ==> &0 < abs(&1 + x)`;
11967                  REAL_ARITH `~(&0 <= x) ==> &0 < abs(&1 - x)`] THEN
11968     (CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
11969     REWRITE_TAC[NORM_REAL; VECTOR_MUL_ASSOC] THEN
11970     REWRITE_TAC[GSYM drop; DROP_CMUL; REAL_ABS_MUL] THEN
11971     ASM_REWRITE_TAC[real_abs; REAL_LE_INV_EQ] THEN
11972     ASM_SIMP_TAC[REAL_ARITH `&0 <= x ==> &0 <= &1 + x`;
11973                  REAL_ARITH `~(&0 <= x) ==> &0 <= &1 - x`] THEN
11974     GEN_REWRITE_TAC RAND_CONV [GSYM VECTOR_MUL_LID] THEN
11975     AP_THM_TAC THEN AP_TERM_TAC THEN
11976     REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD;
11977     MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
11978     X_GEN_TAC `x:real^1` THEN
11979     REWRITE_TAC[IN_INTERVAL_1; DROP_NEG; DROP_VEC] THEN
11980     DISCH_TAC THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
11981     REWRITE_TAC[CONTINUOUS_AT_ID] THEN
11982     ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_INV THEN
11983     REWRITE_TAC[NETLIMIT_AT; o_DEF; LIFT_SUB; LIFT_DROP] THEN
11984     CONJ_TAC THENL
11985      [MATCH_MP_TAC CONTINUOUS_SUB THEN
11986       SIMP_TAC[CONTINUOUS_CONST; REWRITE_RULE[o_DEF] CONTINUOUS_AT_LIFT_NORM];
11987       REWRITE_TAC[NORM_REAL; GSYM drop] THEN ASM_REAL_ARITH_TAC];
11988     SUBGOAL_THEN `(:real^1) = {x | x$1 >= &0} UNION {x | x$1 <= &0}`
11989     SUBST1_TAC THENL
11990      [REWRITE_TAC[EXTENSION; IN_UNION; IN_UNION; IN_ELIM_THM; IN_UNIV] THEN
11991       REAL_ARITH_TAC;
11992       MATCH_MP_TAC CONTINUOUS_ON_CASES THEN
11993       REWRITE_TAC[CLOSED_HALFSPACE_COMPONENT_LE; CLOSED_HALFSPACE_COMPONENT_GE;
11994                   IN_ELIM_THM] THEN
11995       REWRITE_TAC[GSYM drop; REAL_NOT_LE; real_ge; REAL_LET_ANTISYM] THEN
11996       SIMP_TAC[REAL_LE_ANTISYM; REAL_SUB_RZERO; REAL_ADD_RID] THEN
11997       CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN
11998       X_GEN_TAC `y:real^1` THEN REWRITE_TAC[IN_ELIM_THM; real_ge] THEN
11999       DISCH_TAC THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
12000       REWRITE_TAC[CONTINUOUS_AT_ID] THEN
12001       ONCE_REWRITE_TAC[GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_INV THEN
12002       REWRITE_TAC[NETLIMIT_AT; o_DEF; LIFT_ADD; LIFT_SUB; LIFT_DROP] THEN
12003       ASM_SIMP_TAC[CONTINUOUS_ADD; CONTINUOUS_AT_ID; CONTINUOUS_SUB;
12004                    CONTINUOUS_CONST] THEN
12005       ASM_REAL_ARITH_TAC]]);;
12006
12007 let HOMEOMORPHIC_OPEN_INTERVALS = prove
12008  (`!a b:real^N c d:real^N.
12009         (interval(a,b) = {} <=> interval(c,d) = {})
12010         ==> interval(a,b) homeomorphic interval(c,d)`,
12011   REPEAT GEN_TAC THEN ASM_CASES_TAC `interval(c:real^N,d) = {}` THEN
12012   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN ASM_REWRITE_TAC[HOMEOMORPHIC_REFL] THEN
12013   SUBGOAL_THEN
12014    `!i. 1 <= i /\ i <= dimindex(:N)
12015         ==> interval(lift((a:real^N)$i),lift((b:real^N)$i)) homeomorphic
12016             interval(lift((c:real^N)$i),lift((d:real^N)$i))`
12017   MP_TAC THENL
12018    [RULE_ASSUM_TAC(REWRITE_RULE[INTERVAL_NE_EMPTY]) THEN
12019     ASM_SIMP_TAC[HOMEOMORPHIC_OPEN_INTERVALS_1; LIFT_DROP];
12020     ALL_TAC] THEN
12021   REWRITE_TAC[HOMEOMORPHIC_MINIMAL; IN_INTERVAL_1; LIFT_DROP] THEN
12022   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
12023   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
12024   MAP_EVERY X_GEN_TAC [`f:num->real^1->real^1`; `g:num->real^1->real^1`] THEN
12025   DISCH_TAC THEN
12026   EXISTS_TAC
12027    `(\x. lambda i.
12028        drop((f:num->real^1->real^1) i (lift(x$i)))):real^N->real^N` THEN
12029   EXISTS_TAC
12030    `(\x. lambda i.
12031        drop((g:num->real^1->real^1) i (lift(x$i)))):real^N->real^N` THEN
12032   ASM_SIMP_TAC[IN_INTERVAL; LAMBDA_BETA; CART_EQ; LIFT_DROP] THEN
12033   ONCE_REWRITE_TAC[CONTINUOUS_ON_COMPONENTWISE_LIFT] THEN
12034   SIMP_TAC[LAMBDA_BETA; LIFT_DROP] THEN CONJ_TAC THEN REPEAT STRIP_TAC THEN
12035   ONCE_REWRITE_TAC[GSYM o_DEF] THEN
12036   MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
12037   ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT] THEN
12038   MATCH_MP_TAC CONTINUOUS_ON_SUBSET THENL
12039    [EXISTS_TAC `interval(lift((a:real^N)$i),lift((b:real^N)$i))`;
12040     EXISTS_TAC `interval(lift((c:real^N)$i),lift((d:real^N)$i))`] THEN
12041   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1] THEN
12042   ASM_SIMP_TAC[LIFT_DROP; IN_INTERVAL]);;
12043
12044 let HOMEOMORPHIC_OPEN_INTERVAL_UNIV = prove
12045  (`!a b:real^N.
12046         ~(interval(a,b) = {})
12047         ==> interval(a,b) homeomorphic (:real^N)`,
12048   REPEAT STRIP_TAC THEN
12049   SUBGOAL_THEN
12050    `!i. 1 <= i /\ i <= dimindex(:N)
12051         ==> interval(lift((a:real^N)$i),lift((b:real^N)$i)) homeomorphic
12052             (:real^1)`
12053   MP_TAC THENL
12054    [RULE_ASSUM_TAC(REWRITE_RULE[INTERVAL_NE_EMPTY]) THEN
12055     ASM_SIMP_TAC[HOMEOMORPHIC_OPEN_INTERVAL_UNIV_1; LIFT_DROP];
12056     ALL_TAC] THEN
12057   REWRITE_TAC[HOMEOMORPHIC_MINIMAL; IN_INTERVAL_1; LIFT_DROP] THEN
12058   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
12059   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM; IN_UNIV] THEN
12060   MAP_EVERY X_GEN_TAC [`f:num->real^1->real^1`; `g:num->real^1->real^1`] THEN
12061   DISCH_TAC THEN
12062   EXISTS_TAC
12063    `(\x. lambda i.
12064        drop((f:num->real^1->real^1) i (lift(x$i)))):real^N->real^N` THEN
12065   EXISTS_TAC
12066    `(\x. lambda i.
12067        drop((g:num->real^1->real^1) i (lift(x$i)))):real^N->real^N` THEN
12068   ASM_SIMP_TAC[IN_INTERVAL; LAMBDA_BETA; CART_EQ; LIFT_DROP; IN_UNIV] THEN
12069   ONCE_REWRITE_TAC[CONTINUOUS_ON_COMPONENTWISE_LIFT] THEN
12070   SIMP_TAC[LAMBDA_BETA; LIFT_DROP] THEN CONJ_TAC THEN REPEAT STRIP_TAC THEN
12071   ONCE_REWRITE_TAC[GSYM o_DEF] THEN
12072   MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
12073   ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT] THEN
12074   MATCH_MP_TAC CONTINUOUS_ON_SUBSET THENL
12075    [EXISTS_TAC `interval(lift((a:real^N)$i),lift((b:real^N)$i))`;
12076     EXISTS_TAC `(:real^1)`] THEN
12077   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1; IN_UNIV] THEN
12078   ASM_SIMP_TAC[LIFT_DROP; IN_INTERVAL]);;
12079
12080 let HOMEOMORPHIC_BALL_UNIV = prove
12081  (`!a:real^N r. &0 < r ==> ball(a,r) homeomorphic (:real^N)`,
12082   REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN REPEAT STRIP_TAC THEN
12083   SUBGOAL_THEN `?y:real^N. r = norm(y)` (CHOOSE_THEN SUBST_ALL_TAC) THENL
12084    [ASM_MESON_TAC[VECTOR_CHOOSE_SIZE; REAL_LT_IMP_LE]; POP_ASSUM MP_TAC] THEN
12085   REWRITE_TAC[NORM_POS_LT] THEN GEOM_NORMALIZE_TAC `y:real^N` THEN
12086   SIMP_TAC[] THEN GEN_TAC THEN REPEAT(DISCH_THEN(K ALL_TAC)) THEN
12087   REWRITE_TAC[HOMEOMORPHIC_MINIMAL] THEN
12088   EXISTS_TAC `\z:real^N. inv(&1 - norm(z)) % z` THEN
12089   EXISTS_TAC `\z:real^N. inv(&1 + norm(z)) % z` THEN
12090   REWRITE_TAC[IN_BALL; IN_UNIV; DIST_0; VECTOR_MUL_ASSOC; VECTOR_MUL_EQ_0;
12091               VECTOR_ARITH `a % x:real^N = x <=> (a - &1) % x = vec 0`] THEN
12092   REPEAT CONJ_TAC THENL
12093    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN DISJ1_TAC THEN
12094     REWRITE_TAC[GSYM REAL_INV_MUL; REAL_SUB_0; REAL_INV_EQ_1] THEN
12095     REWRITE_TAC[NORM_MUL; REAL_ABS_INV] THEN
12096     ASM_SIMP_TAC[REAL_ARITH `x < &1 ==> abs(&1 - x) = &1 - x`] THEN
12097     POP_ASSUM MP_TAC THEN CONV_TAC REAL_FIELD;
12098     X_GEN_TAC `y:real^N` THEN REWRITE_TAC[NORM_MUL; REAL_ABS_INV] THEN
12099     ASM_SIMP_TAC[NORM_POS_LE; REAL_ARITH
12100      `&0 <= y ==> inv(abs(&1 + y)) * z = z / (&1 + y)`] THEN
12101     ASM_SIMP_TAC[NORM_POS_LE; REAL_LT_LDIV_EQ; REAL_ARITH
12102       `&0 <= y ==> &0 < &1 + y`] THEN
12103     CONJ_TAC THENL [REAL_ARITH_TAC; DISJ1_TAC] THEN
12104     REWRITE_TAC[GSYM REAL_INV_MUL; REAL_SUB_0; REAL_INV_EQ_1] THEN
12105     MP_TAC(ISPEC `y:real^N` NORM_POS_LE) THEN CONV_TAC REAL_FIELD;
12106     MATCH_MP_TAC CONTINUOUS_ON_MUL THEN REWRITE_TAC[CONTINUOUS_ON_ID] THEN
12107     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
12108     MATCH_MP_TAC CONTINUOUS_ON_INV THEN
12109     SIMP_TAC[IN_BALL_0; REAL_SUB_0; REAL_ARITH `x < &1 ==> ~(&1 = x)`] THEN
12110     REWRITE_TAC[o_DEF; LIFT_SUB] THEN MATCH_MP_TAC CONTINUOUS_ON_SUB THEN
12111     REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
12112     MATCH_MP_TAC CONTINUOUS_ON_LIFT_NORM_COMPOSE THEN
12113     REWRITE_TAC[CONTINUOUS_ON_ID];
12114     MATCH_MP_TAC CONTINUOUS_ON_MUL THEN REWRITE_TAC[CONTINUOUS_ON_ID] THEN
12115     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
12116     MATCH_MP_TAC CONTINUOUS_ON_INV THEN
12117     SIMP_TAC[NORM_POS_LE; REAL_ARITH `&0 <= x ==> ~(&1 + x = &0)`] THEN
12118     REWRITE_TAC[o_DEF; LIFT_ADD] THEN MATCH_MP_TAC CONTINUOUS_ON_ADD THEN
12119     REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
12120     MATCH_MP_TAC CONTINUOUS_ON_LIFT_NORM_COMPOSE THEN
12121     REWRITE_TAC[CONTINUOUS_ON_ID]]);;
12122
12123 (* ------------------------------------------------------------------------- *)
12124 (* Cardinalities of various useful sets.                                     *)
12125 (* ------------------------------------------------------------------------- *)
12126
12127 let CARD_EQ_EUCLIDEAN = prove
12128  (`(:real^N) =_c (:real)`,
12129   MATCH_MP_TAC CARD_EQ_CART THEN REWRITE_TAC[real_INFINITE]);;
12130
12131 let UNCOUNTABLE_EUCLIDEAN = prove
12132  (`~COUNTABLE(:real^N)`,
12133   MATCH_MP_TAC CARD_EQ_REAL_IMP_UNCOUNTABLE THEN
12134   REWRITE_TAC[CARD_EQ_EUCLIDEAN]);;
12135
12136 let CARD_EQ_INTERVAL = prove
12137  (`(!a b:real^N. ~(interval(a,b) = {}) ==> interval[a,b] =_c (:real)) /\
12138    (!a b:real^N. ~(interval(a,b) = {}) ==> interval(a,b) =_c (:real))`,
12139   REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN
12140   ASM_CASES_TAC `interval(a:real^N,b) = {}` THEN ASM_REWRITE_TAC[] THEN
12141   CONJ_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
12142    [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
12143     REWRITE_TAC[CARD_LE_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
12144     REWRITE_TAC[CARD_EQ_EUCLIDEAN];
12145     TRANS_TAC CARD_LE_TRANS `interval(a:real^N,b)` THEN
12146     SIMP_TAC[CARD_LE_SUBSET; INTERVAL_OPEN_SUBSET_CLOSED];
12147     TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
12148     REWRITE_TAC[CARD_LE_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
12149     REWRITE_TAC[CARD_EQ_EUCLIDEAN];
12150     ALL_TAC] THEN
12151   TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
12152   SIMP_TAC[ONCE_REWRITE_RULE[CARD_EQ_SYM] CARD_EQ_IMP_LE;
12153            CARD_EQ_EUCLIDEAN] THEN
12154   FIRST_X_ASSUM(MP_TAC o MATCH_MP HOMEOMORPHIC_OPEN_INTERVAL_UNIV) THEN
12155   DISCH_THEN(MP_TAC o MATCH_MP HOMEOMORPHIC_IMP_CARD_EQ) THEN
12156   MESON_TAC[CARD_EQ_IMP_LE; CARD_EQ_SYM]);;
12157
12158 let UNCOUNTABLE_INTERVAL = prove
12159  (`(!a b. ~(interval(a,b) = {}) ==> ~COUNTABLE(interval[a,b])) /\
12160    (!a b. ~(interval(a,b) = {}) ==> ~COUNTABLE(interval(a,b)))`,
12161   SIMP_TAC[CARD_EQ_REAL_IMP_UNCOUNTABLE; CARD_EQ_INTERVAL]);;
12162
12163 let COUNTABLE_OPEN_INTERVAL = prove
12164  (`!a b. COUNTABLE(interval(a,b)) <=> interval(a,b) = {}`,
12165   MESON_TAC[COUNTABLE_EMPTY; UNCOUNTABLE_INTERVAL]);;
12166
12167 let CARD_EQ_OPEN = prove
12168  (`!s:real^N->bool. open s /\ ~(s = {}) ==> s =_c (:real)`,
12169   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
12170    [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
12171     REWRITE_TAC[CARD_LE_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
12172     REWRITE_TAC[CARD_EQ_EUCLIDEAN];
12173     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_INTERVAL]) THEN
12174     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
12175     DISCH_THEN(X_CHOOSE_TAC `c:real^N`) THEN
12176     DISCH_THEN(MP_TAC o SPEC `c:real^N`) THEN
12177     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
12178     MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN
12179     ASM_CASES_TAC `interval(a:real^N,b) = {}` THEN
12180     ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN STRIP_TAC THEN
12181     TRANS_TAC CARD_LE_TRANS `interval[a:real^N,b]` THEN
12182     ASM_SIMP_TAC[CARD_LE_SUBSET] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
12183     ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN ASM_SIMP_TAC[CARD_EQ_INTERVAL]]);;
12184
12185 let UNCOUNTABLE_OPEN = prove
12186  (`!s:real^N->bool. open s /\ ~(s = {}) ==> ~(COUNTABLE s)`,
12187   SIMP_TAC[CARD_EQ_OPEN; CARD_EQ_REAL_IMP_UNCOUNTABLE]);;
12188
12189 let CARD_EQ_BALL = prove
12190  (`!a:real^N r. &0 < r ==> ball(a,r) =_c (:real)`,
12191   SIMP_TAC[CARD_EQ_OPEN; OPEN_BALL; BALL_EQ_EMPTY; GSYM REAL_NOT_LT]);;
12192
12193 let CARD_EQ_CBALL = prove
12194  (`!a:real^N r. &0 < r ==> cball(a,r) =_c (:real)`,
12195   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
12196    [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
12197     REWRITE_TAC[CARD_LE_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN
12198     REWRITE_TAC[CARD_EQ_EUCLIDEAN];
12199     TRANS_TAC CARD_LE_TRANS `ball(a:real^N,r)` THEN
12200     SIMP_TAC[CARD_LE_SUBSET; BALL_SUBSET_CBALL] THEN
12201     MATCH_MP_TAC CARD_EQ_IMP_LE THEN
12202     ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN ASM_SIMP_TAC[CARD_EQ_BALL]]);;
12203
12204 let FINITE_IMP_NOT_OPEN = prove
12205  (`!s:real^N->bool. FINITE s /\ ~(s = {}) ==> ~(open s)`,
12206   MESON_TAC[UNCOUNTABLE_OPEN; FINITE_IMP_COUNTABLE]);;
12207
12208 let OPEN_IMP_INFINITE = prove
12209  (`!s. open s ==> s = {} \/ INFINITE s`,
12210   MESON_TAC[FINITE_IMP_NOT_OPEN; INFINITE]);;
12211
12212 let EMPTY_INTERIOR_FINITE = prove
12213  (`!s:real^N->bool. FINITE s ==> interior s = {}`,
12214   REPEAT STRIP_TAC THEN MP_TAC(ISPEC `s:real^N->bool` OPEN_INTERIOR) THEN
12215   ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
12216   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] FINITE_IMP_NOT_OPEN) THEN
12217   MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `s:real^N->bool` THEN
12218   ASM_REWRITE_TAC[INTERIOR_SUBSET]);;
12219
12220 let CARD_EQ_CONNECTED = prove
12221  (`!s a b:real^N.
12222         connected s /\ a IN s /\ b IN s /\ ~(a = b) ==> s =_c (:real)`,
12223   GEOM_ORIGIN_TAC `b:real^N` THEN GEOM_NORMALIZE_TAC `a:real^N` THEN
12224   REWRITE_TAC[NORM_EQ_SQUARE; REAL_POS; REAL_POW_ONE] THEN
12225   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
12226    [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
12227     SIMP_TAC[CARD_LE_UNIV; CARD_EQ_EUCLIDEAN; CARD_EQ_IMP_LE];
12228     TRANS_TAC CARD_LE_TRANS `interval[vec 0:real^1,vec 1]` THEN CONJ_TAC THENL
12229      [MATCH_MP_TAC(ONCE_REWRITE_RULE[CARD_EQ_SYM] CARD_EQ_IMP_LE) THEN
12230       SIMP_TAC[UNIT_INTERVAL_NONEMPTY; CARD_EQ_INTERVAL];
12231       REWRITE_TAC[LE_C] THEN EXISTS_TAC `\x:real^N. lift(a dot x)` THEN
12232       SIMP_TAC[FORALL_LIFT; LIFT_EQ; IN_INTERVAL_1; LIFT_DROP; DROP_VEC] THEN
12233       X_GEN_TAC `t:real` THEN STRIP_TAC THEN
12234       MATCH_MP_TAC CONNECTED_IVT_HYPERPLANE THEN
12235       MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `a:real^N`] THEN
12236       ASM_REWRITE_TAC[DOT_RZERO]]]);;
12237
12238 let UNCOUNTABLE_CONNECTED = prove
12239  (`!s a b:real^N.
12240         connected s /\ a IN s /\ b IN s /\ ~(a = b) ==> ~COUNTABLE s`,
12241   REPEAT GEN_TAC THEN STRIP_TAC THEN
12242   MATCH_MP_TAC CARD_EQ_REAL_IMP_UNCOUNTABLE THEN
12243   MATCH_MP_TAC CARD_EQ_CONNECTED THEN
12244   ASM_MESON_TAC[]);;
12245
12246 let CARD_LT_IMP_DISCONNECTED = prove
12247  (`!s x:real^N. s <_c (:real) /\ x IN s ==> connected_component s x = {x}`,
12248   REPEAT STRIP_TAC THEN REWRITE_TAC[SET_RULE
12249    `s = {a} <=> a IN s /\ !a b. a IN s /\ b IN s /\ ~(a = b) ==> F`] THEN
12250   REPEAT STRIP_TAC THEN REWRITE_TAC[IN] THEN
12251   ASM_REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ] THEN
12252   MP_TAC(ISPECL [`connected_component s (x:real^N)`; `a:real^N`; `b:real^N`]
12253         CARD_EQ_CONNECTED) THEN
12254   ASM_REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT] THEN
12255   DISCH_TAC THEN UNDISCH_TAC `(s:real^N->bool) <_c (:real)` THEN
12256   REWRITE_TAC[CARD_NOT_LT] THEN
12257   TRANS_TAC CARD_LE_TRANS `connected_component s (x:real^N)` THEN
12258   ASM_SIMP_TAC[ONCE_REWRITE_RULE[CARD_EQ_SYM] CARD_EQ_IMP_LE] THEN
12259   MATCH_MP_TAC CARD_LE_SUBSET THEN REWRITE_TAC[CONNECTED_COMPONENT_SUBSET]);;
12260
12261 let COUNTABLE_IMP_DISCONNECTED = prove
12262  (`!s x:real^N. COUNTABLE s /\ x IN s ==> connected_component s x = {x}`,
12263   SIMP_TAC[CARD_LT_IMP_DISCONNECTED; COUNTABLE_IMP_CARD_LT_REAL]);;
12264
12265 let CONNECTED_CARD_EQ_IFF_NONTRIVIAL = prove
12266  (`!s:real^N->bool.
12267         connected s ==> (s =_c (:real) <=> ~(?a. s SUBSET {a}))`,
12268   REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL
12269    [ALL_TAC; MATCH_MP_TAC CARD_EQ_CONNECTED THEN ASM SET_TAC[]] THEN
12270   FIRST_ASSUM(MP_TAC o MATCH_MP(REWRITE_RULE[IMP_CONJ_ALT] FINITE_SUBSET)) THEN
12271   REWRITE_TAC[FINITE_SING] THEN
12272   ASM_MESON_TAC[CARD_EQ_REAL_IMP_UNCOUNTABLE; FINITE_IMP_COUNTABLE]);;
12273
12274 (* ------------------------------------------------------------------------- *)
12275 (* "Iff" forms of constancy of function from connected set into a set that   *)
12276 (* is smaller than R, or countable, or finite, or disconnected, or discrete. *)
12277 (* ------------------------------------------------------------------------- *)
12278
12279 let [CONTINUOUS_DISCONNECTED_RANGE_CONSTANT_EQ;
12280      CONTINUOUS_DISCRETE_RANGE_CONSTANT_EQ;
12281      CONTINUOUS_FINITE_RANGE_CONSTANT_EQ] = (CONJUNCTS o prove)
12282   (`(!s. connected s <=>
12283          !f:real^M->real^N t.
12284             f continuous_on s /\ IMAGE f s SUBSET t /\
12285             (!y. y IN t ==> connected_component t y = {y})
12286             ==> ?a. !x. x IN s ==> f x = a) /\
12287     (!s. connected s <=>
12288          !f:real^M->real^N.
12289             f continuous_on s /\
12290             (!x. x IN s
12291                  ==> ?e. &0 < e /\
12292                          !y. y IN s /\ ~(f y = f x) ==> e <= norm(f y - f x))
12293             ==> ?a. !x. x IN s ==> f x = a) /\
12294     (!s. connected s <=>
12295          !f:real^M->real^N.
12296             f continuous_on s /\ FINITE(IMAGE f s)
12297             ==> ?a. !x. x IN s ==> f x = a)`,
12298   REWRITE_TAC[AND_FORALL_THM] THEN X_GEN_TAC `s:real^M->bool` THEN
12299   MATCH_MP_TAC(TAUT
12300    `(s ==> t) /\ (t ==> u) /\ (u ==> v) /\ (v ==> s)
12301     ==> (s <=> t) /\ (s <=> u) /\ (s <=> v)`) THEN
12302   REPEAT CONJ_TAC THENL
12303    [REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^M->bool = {}` THEN
12304     ASM_REWRITE_TAC[NOT_IN_EMPTY] THEN
12305     FIRST_X_ASSUM(X_CHOOSE_TAC `x:real^M` o
12306         GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
12307     EXISTS_TAC `(f:real^M->real^N) x` THEN
12308     MATCH_MP_TAC(SET_RULE
12309      `IMAGE f s SUBSET {a} ==> !y. y IN s ==> f y = a`) THEN
12310     FIRST_X_ASSUM(MP_TAC o SPEC `(f:real^M->real^N) x`) THEN
12311     ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN(SUBST1_TAC o SYM)] THEN
12312     MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN
12313     ASM_SIMP_TAC[CONNECTED_CONTINUOUS_IMAGE] THEN ASM SET_TAC[];
12314     REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
12315     EXISTS_TAC `IMAGE (f:real^M->real^N) s` THEN
12316     ASM_REWRITE_TAC[FORALL_IN_IMAGE; SUBSET_REFL] THEN
12317     X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
12318     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^M`) THEN ASM_REWRITE_TAC[] THEN
12319     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
12320     MATCH_MP_TAC(SET_RULE
12321      `(!y. y IN s /\ f y IN connected_component (IMAGE f s) a ==> f y = a) /\
12322       connected_component (IMAGE f s) a SUBSET (IMAGE f s) /\
12323       connected_component (IMAGE f s) a a
12324       ==> connected_component (IMAGE f s) a = {a}`) THEN
12325     REWRITE_TAC[CONNECTED_COMPONENT_SUBSET; CONNECTED_COMPONENT_REFL_EQ] THEN
12326     ASM_SIMP_TAC[FUN_IN_IMAGE] THEN X_GEN_TAC `y:real^M` THEN STRIP_TAC THEN
12327     MP_TAC(ISPEC `connected_component (IMAGE (f:real^M->real^N) s) (f x)`
12328         CONNECTED_CLOSED) THEN
12329     REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT] THEN
12330     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
12331     ASM_REWRITE_TAC[] THEN MAP_EVERY EXISTS_TAC
12332      [`cball((f:real^M->real^N) x,e / &2)`;
12333       `(:real^N) DIFF ball((f:real^M->real^N) x,e)`] THEN
12334     REWRITE_TAC[GSYM OPEN_CLOSED; OPEN_BALL; CLOSED_CBALL] THEN
12335     REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN REPEAT CONJ_TAC THENL
12336      [REWRITE_TAC[SUBSET; IN_CBALL; IN_UNION; IN_DIFF; IN_BALL; IN_UNIV] THEN
12337       MATCH_MP_TAC(MESON[SUBSET; CONNECTED_COMPONENT_SUBSET]
12338        `(!x. x IN s ==> P x)
12339         ==> (!x. x IN connected_component s y ==> P x)`) THEN
12340       REWRITE_TAC[FORALL_IN_IMAGE] THEN X_GEN_TAC `z:real^M` THEN
12341       DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `z:real^M`) THEN
12342       ASM_REWRITE_TAC[] THEN CONV_TAC NORM_ARITH;
12343       MATCH_MP_TAC(SET_RULE
12344        `(!x. x IN s /\ x IN t ==> F) ==> s INTER t INTER u = {}`) THEN
12345       REWRITE_TAC[IN_BALL; IN_CBALL; IN_DIFF; IN_UNIV] THEN
12346       UNDISCH_TAC `&0 < e` THEN CONV_TAC NORM_ARITH;
12347       EXISTS_TAC `(f:real^M->real^N) x` THEN
12348       ASM_SIMP_TAC[CENTRE_IN_CBALL; REAL_HALF; REAL_LT_IMP_LE; IN_INTER] THEN
12349       REWRITE_TAC[IN] THEN
12350       ASM_SIMP_TAC[CONNECTED_COMPONENT_REFL_EQ; FUN_IN_IMAGE];
12351       EXISTS_TAC `(f:real^M->real^N) y` THEN
12352       ASM_REWRITE_TAC[IN_INTER; IN_DIFF; IN_UNIV; IN_BALL; REAL_NOT_LT] THEN
12353       ASM_SIMP_TAC[ONCE_REWRITE_RULE[DIST_SYM] dist]];
12354     MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `f:real^M->real^N` THEN
12355     DISCH_THEN(fun th -> STRIP_TAC THEN MATCH_MP_TAC th) THEN
12356     ASM_REWRITE_TAC[] THEN X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
12357     ASM_CASES_TAC `IMAGE (f:real^M->real^N) s DELETE (f x) = {}` THENL
12358      [EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN ASM SET_TAC[];
12359       ALL_TAC] THEN
12360     EXISTS_TAC
12361      `inf{norm(z - f x) |z| z IN IMAGE (f:real^M->real^N) s DELETE (f x)}` THEN
12362     REWRITE_TAC[SIMPLE_IMAGE] THEN
12363     ASM_SIMP_TAC[REAL_LT_INF_FINITE; REAL_INF_LE_FINITE; FINITE_DELETE;
12364                  FINITE_IMAGE; IMAGE_EQ_EMPTY] THEN
12365     REWRITE_TAC[FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
12366     REWRITE_TAC[IN_DELETE; NORM_POS_LT; VECTOR_SUB_EQ; IN_IMAGE] THEN
12367     MESON_TAC[REAL_LE_REFL];
12368     REWRITE_TAC[CONNECTED_CLOSED_IN_EQ] THEN
12369     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
12370     REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
12371     MAP_EVERY X_GEN_TAC [`t:real^M->bool`; `u:real^M->bool`] THEN
12372     STRIP_TAC THEN DISCH_THEN(MP_TAC o SPEC
12373      `(\x. if x IN t then vec 0 else basis 1):real^M->real^N`) THEN
12374     REWRITE_TAC[NOT_IMP] THEN REPEAT CONJ_TAC THENL
12375      [EXPAND_TAC "s" THEN MATCH_MP_TAC CONTINUOUS_ON_CASES_LOCAL THEN
12376       ASM_REWRITE_TAC[CONTINUOUS_ON_CONST] THEN ASM SET_TAC[];
12377       MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `{vec 0:real^N,basis 1}` THEN
12378       REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY] THEN SET_TAC[];
12379       SUBGOAL_THEN `?a b:real^M. a IN s /\ a IN t /\ b IN s /\ ~(b IN t)`
12380       STRIP_ASSUME_TAC THENL
12381        [ASM SET_TAC[]; DISCH_THEN(CHOOSE_THEN MP_TAC)] THEN
12382       DISCH_THEN(fun th -> MP_TAC(SPEC `a:real^M` th) THEN
12383                            MP_TAC(SPEC `b:real^M` th)) THEN
12384       ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
12385       CONV_TAC(RAND_CONV SYM_CONV) THEN
12386       SIMP_TAC[BASIS_NONZERO; LE_REFL; DIMINDEX_GE_1; REAL_LE_REFL]]]);;
12387
12388 let CONTINUOUS_DISCONNECTED_RANGE_CONSTANT = prove
12389  (`!f:real^M->real^N s.
12390         connected s /\
12391         f continuous_on s /\ IMAGE f s SUBSET t /\
12392         (!y. y IN t ==> connected_component t y = {y})
12393         ==> ?a. !x. x IN s ==> f x = a`,
12394   MESON_TAC[CONTINUOUS_DISCONNECTED_RANGE_CONSTANT_EQ]);;
12395
12396 let CONTINUOUS_DISCRETE_RANGE_CONSTANT = prove
12397  (`!f:real^M->real^N s.
12398         connected s /\
12399         f continuous_on s /\
12400         (!x. x IN s
12401              ==> ?e. &0 < e /\
12402                      !y. y IN s /\ ~(f y = f x) ==> e <= norm(f y - f x))
12403         ==> ?a. !x. x IN s ==> f x = a`,
12404   ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
12405   REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
12406   REWRITE_TAC[IMP_IMP; GSYM CONTINUOUS_DISCRETE_RANGE_CONSTANT_EQ]);;
12407
12408 let CONTINUOUS_FINITE_RANGE_CONSTANT = prove
12409  (`!f:real^M->real^N s.
12410         connected s /\
12411         f continuous_on s /\
12412         FINITE(IMAGE f s)
12413         ==> ?a. !x. x IN s ==> f x = a`,
12414   MESON_TAC[CONTINUOUS_FINITE_RANGE_CONSTANT_EQ]);;
12415
12416 let CONTINUOUS_COUNTABLE_RANGE_CONSTANT_EQ = prove
12417  (`!s. connected s <=>
12418          !f:real^M->real^N.
12419             f continuous_on s /\ COUNTABLE(IMAGE f s)
12420             ==> ?a. !x. x IN s ==> f x = a`,
12421   GEN_TAC THEN EQ_TAC THENL
12422    [REWRITE_TAC[CONTINUOUS_DISCONNECTED_RANGE_CONSTANT_EQ];
12423     REWRITE_TAC[CONTINUOUS_FINITE_RANGE_CONSTANT_EQ]] THEN
12424   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
12425   ASM_SIMP_TAC[FINITE_IMP_COUNTABLE] THEN
12426   EXISTS_TAC `IMAGE (f:real^M->real^N) s` THEN
12427   ASM_SIMP_TAC[COUNTABLE_IMP_DISCONNECTED; SUBSET_REFL]);;
12428
12429 let CONTINUOUS_CARD_LT_RANGE_CONSTANT_EQ = prove
12430  (`!s. connected s <=>
12431          !f:real^M->real^N.
12432             f continuous_on s /\ (IMAGE f s) <_c (:real)
12433             ==> ?a. !x. x IN s ==> f x = a`,
12434   GEN_TAC THEN EQ_TAC THENL
12435    [REWRITE_TAC[CONTINUOUS_DISCONNECTED_RANGE_CONSTANT_EQ];
12436     REWRITE_TAC[CONTINUOUS_COUNTABLE_RANGE_CONSTANT_EQ]] THEN
12437   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
12438   ASM_SIMP_TAC[COUNTABLE_IMP_CARD_LT_REAL] THEN
12439   EXISTS_TAC `IMAGE (f:real^M->real^N) s` THEN
12440   ASM_SIMP_TAC[CARD_LT_IMP_DISCONNECTED; SUBSET_REFL]);;
12441
12442 let CONTINUOUS_COUNTABLE_RANGE_CONSTANT = prove
12443  (`!f:real^M->real^N s.
12444         connected s /\ f continuous_on s /\ COUNTABLE(IMAGE f s)
12445         ==> ?a. !x. x IN s ==> f x = a`,
12446   MESON_TAC[CONTINUOUS_COUNTABLE_RANGE_CONSTANT_EQ]);;
12447
12448 let CONTINUOUS_CARD_LT_RANGE_CONSTANT = prove
12449  (`!f:real^M->real^N s.
12450         connected s /\ f continuous_on s /\ (IMAGE f s) <_c (:real)
12451         ==> ?a. !x. x IN s ==> f x = a`,
12452   MESON_TAC[CONTINUOUS_CARD_LT_RANGE_CONSTANT_EQ]);;
12453
12454 (* ------------------------------------------------------------------------- *)
12455 (* Homeomorphism of hyperplanes.                                             *)
12456 (* ------------------------------------------------------------------------- *)
12457
12458 let HOMEOMORPHIC_HYPERPLANES = prove
12459  (`!a:real^N b c:real^N d.
12460         ~(a = vec 0) /\ ~(c = vec 0)
12461         ==> {x | a dot x = b} homeomorphic {x | c dot x = d}`,
12462   let lemma = prove
12463    (`~(a = vec 0)
12464      ==> {x:real^N | a dot x = b} homeomorphic {x:real^N | x$1 = &0}`,
12465     REPEAT STRIP_TAC THEN SUBGOAL_THEN `?c:real^N. a dot c = b`
12466     STRIP_ASSUME_TAC THENL
12467      [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [CART_EQ]) THEN
12468       REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; VEC_COMPONENT] THEN
12469       DISCH_THEN(X_CHOOSE_THEN `k:num` STRIP_ASSUME_TAC) THEN
12470       EXISTS_TAC `b / (a:real^N)$k % basis k:real^N` THEN
12471       ASM_SIMP_TAC[DOT_RMUL; DOT_BASIS; REAL_DIV_RMUL];
12472       FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
12473       ABBREV_TAC `p = {x:real^N | x$1 = &0}` THEN
12474       GEOM_ORIGIN_TAC `c:real^N` THEN
12475       REWRITE_TAC[VECTOR_ADD_RID; DOT_RADD; DOT_RZERO; REAL_EQ_ADD_LCANCEL_0;
12476                   REAL_ADD_RID] THEN
12477       REPEAT STRIP_TAC THEN UNDISCH_TAC `~(a:real^N = vec 0)` THEN
12478       GEOM_BASIS_MULTIPLE_TAC 1 `a:real^N` THEN
12479       SIMP_TAC[VECTOR_MUL_EQ_0; DE_MORGAN_THM; DOT_LMUL; REAL_ENTIRE] THEN
12480       SIMP_TAC[DOT_BASIS; LE_REFL; DIMINDEX_GE_1] THEN
12481       EXPAND_TAC "p" THEN REWRITE_TAC[HOMEOMORPHIC_REFL]]) in
12482   REPEAT STRIP_TAC THEN
12483   TRANS_TAC HOMEOMORPHIC_TRANS `{x:real^N | x$1 = &0}` THEN
12484   ASM_SIMP_TAC[lemma] THEN ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
12485   ASM_SIMP_TAC[lemma]);;
12486
12487 let HOMEOMORPHIC_HYPERPLANE_STANDARD_HYPERPLANE = prove
12488  (`!a:real^N b k c.
12489         ~(a = vec 0) /\ 1 <= k /\ k <= dimindex(:N)
12490         ==> {x | a dot x = b} homeomorphic {x:real^N | x$k = c}`,
12491   REPEAT STRIP_TAC THEN
12492   SUBGOAL_THEN `{x:real^N | x$k = c} = {x | basis k dot x = c}` SUBST1_TAC
12493   THENL [ASM_SIMP_TAC[DOT_BASIS]; MATCH_MP_TAC HOMEOMORPHIC_HYPERPLANES] THEN
12494   ASM_SIMP_TAC[BASIS_NONZERO]);;
12495
12496 let HOMEOMORPHIC_STANDARD_HYPERPLANE_HYPERPLANE = prove
12497  (`!a:real^N b k c.
12498         ~(a = vec 0) /\ 1 <= k /\ k <= dimindex(:N)
12499         ==> {x:real^N | x$k = c} homeomorphic {x | a dot x = b}`,
12500   ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
12501   REWRITE_TAC[HOMEOMORPHIC_HYPERPLANE_STANDARD_HYPERPLANE]);;
12502
12503 let HOMEOMORPHIC_HYPERPLANE_UNIV = prove
12504  (`!a b. ~(a = vec 0) /\ dimindex(:N) = dimindex(:M) + 1
12505          ==> {x:real^N | a dot x = b} homeomorphic (:real^M)`,
12506   REPEAT STRIP_TAC THEN TRANS_TAC HOMEOMORPHIC_TRANS
12507    `{x:real^N | basis(dimindex(:N)) dot x = &0}` THEN
12508   ASM_SIMP_TAC[HOMEOMORPHIC_HYPERPLANES; BASIS_NONZERO;
12509                LE_REFL; DIMINDEX_GE_1] THEN
12510   REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN
12511   EXISTS_TAC `(\x. lambda i. x$i):real^N->real^M` THEN
12512   EXISTS_TAC `(\x. lambda i. if i <= dimindex(:M) then x$i else &0)
12513               :real^M->real^N` THEN
12514   REPEAT CONJ_TAC THENL
12515    [MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
12516     SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
12517              VECTOR_MUL_COMPONENT];
12518     REWRITE_TAC[SUBSET_UNIV];
12519     MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
12520     SIMP_TAC[linear; CART_EQ; LAMBDA_BETA; VECTOR_ADD_COMPONENT;
12521              VECTOR_MUL_COMPONENT] THEN
12522     REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
12523     REAL_ARITH_TAC;
12524     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM; IN_UNIV] THEN
12525     ASM_SIMP_TAC[DOT_BASIS; LAMBDA_BETA; LE_REFL; ARITH_RULE `1 <= n + 1`;
12526                  ARITH_RULE `~(m + 1 <= m)`];
12527     ASM_SIMP_TAC[IN_ELIM_THM; LAMBDA_BETA; DOT_BASIS; LE_REFL; CART_EQ;
12528                  ARITH_RULE `1 <= n + 1`] THEN
12529     GEN_TAC THEN DISCH_TAC THEN X_GEN_TAC `i:num` THEN
12530     ASM_CASES_TAC `i = dimindex(:M) + 1` THEN ASM_REWRITE_TAC[COND_ID] THEN
12531     COND_CASES_TAC THEN REWRITE_TAC[] THEN ASM_ARITH_TAC;
12532     ASM_SIMP_TAC[LAMBDA_BETA; CART_EQ; IN_UNIV; LE_REFL;
12533                  ARITH_RULE `i <= n ==> i <= n + 1`]]);;
12534
12535 (* ------------------------------------------------------------------------- *)
12536 (* "Isometry" (up to constant bounds) of injective linear map etc.           *)
12537 (* ------------------------------------------------------------------------- *)
12538
12539 let CAUCHY_ISOMETRIC = prove
12540  (`!f s e x.
12541         &0 < e /\ subspace s /\
12542         linear f /\ (!x. x IN s ==> norm(f x) >= e * norm(x)) /\
12543         (!n. x(n) IN s) /\ cauchy(f o x)
12544         ==> cauchy x`,
12545   REPEAT GEN_TAC THEN REWRITE_TAC[real_ge] THEN
12546   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
12547   REWRITE_TAC[CAUCHY; dist; o_THM] THEN
12548   FIRST_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_SUB th)]) THEN
12549   DISCH_THEN(fun th -> X_GEN_TAC `d:real` THEN DISCH_TAC THEN MP_TAC th) THEN
12550   DISCH_THEN(MP_TAC o SPEC `d * e`) THEN ASM_SIMP_TAC[REAL_LT_MUL] THEN
12551   ASM_MESON_TAC[REAL_LE_RDIV_EQ; REAL_MUL_SYM; REAL_LET_TRANS; SUBSPACE_SUB;
12552                 REAL_LT_LDIV_EQ]);;
12553
12554 let COMPLETE_ISOMETRIC_IMAGE = prove
12555  (`!f:real^M->real^N s e.
12556         &0 < e /\ subspace s /\
12557         linear f /\ (!x. x IN s ==> norm(f x) >= e * norm(x)) /\
12558         complete s
12559         ==> complete(IMAGE f s)`,
12560   REPEAT GEN_TAC THEN REWRITE_TAC[complete; EXISTS_IN_IMAGE] THEN
12561   STRIP_TAC THEN X_GEN_TAC `g:num->real^N` THEN
12562   REWRITE_TAC[IN_IMAGE; SKOLEM_THM; FORALL_AND_THM] THEN
12563   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
12564   DISCH_THEN(X_CHOOSE_THEN `x:num->real^M` MP_TAC) THEN
12565   GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [GSYM FUN_EQ_THM] THEN
12566   REWRITE_TAC[GSYM o_DEF] THEN
12567   DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
12568   FIRST_X_ASSUM(MP_TAC o SPEC `x:num->real^M`) THEN
12569   ASM_MESON_TAC[CAUCHY_ISOMETRIC; LINEAR_CONTINUOUS_AT;
12570                 CONTINUOUS_AT_SEQUENTIALLY]);;
12571
12572 let INJECTIVE_IMP_ISOMETRIC = prove
12573  (`!f:real^M->real^N s.
12574         closed s /\ subspace s /\
12575         linear f /\ (!x. x IN s /\ (f x = vec 0) ==> (x = vec 0))
12576         ==> ?e. &0 < e /\ !x. x IN s ==> norm(f x) >= e * norm(x)`,
12577   REPEAT STRIP_TAC THEN
12578   ASM_CASES_TAC `s SUBSET {vec 0 :real^M}` THENL
12579    [EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01; REAL_MUL_LID; real_ge] THEN
12580     ASM_MESON_TAC[SUBSET; IN_SING; NORM_0; LINEAR_0; REAL_LE_REFL];
12581     ALL_TAC] THEN
12582   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [SUBSET]) THEN
12583   REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; IN_SING] THEN
12584   DISCH_THEN(X_CHOOSE_THEN `a:real^M` STRIP_ASSUME_TAC) THEN
12585   MP_TAC(ISPECL
12586    [`{(f:real^M->real^N) x | x IN s /\ norm(x) = norm(a:real^M)}`;
12587     `vec 0:real^N`] DISTANCE_ATTAINS_INF) THEN
12588   ANTS_TAC THENL
12589    [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN
12590     CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
12591     MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
12592     SUBST1_TAC(SET_RULE
12593      `{f x | x IN s /\ norm(x) = norm(a:real^M)} =
12594       IMAGE (f:real^M->real^N) (s INTER {x | norm x = norm a})`) THEN
12595     MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
12596     ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN
12597     MATCH_MP_TAC CLOSED_INTER_COMPACT THEN ASM_REWRITE_TAC[] THEN
12598     SUBGOAL_THEN
12599      `{x:real^M | norm x = norm(a:real^M)} = frontier(cball(vec 0,norm a))`
12600     SUBST1_TAC THENL
12601      [ASM_SIMP_TAC[FRONTIER_CBALL; NORM_POS_LT; dist; VECTOR_SUB_LZERO;
12602                    NORM_NEG; sphere];
12603       ASM_SIMP_TAC[COMPACT_FRONTIER; COMPACT_CBALL]];
12604     ALL_TAC] THEN
12605   ONCE_REWRITE_TAC[SET_RULE `{f x | P x} = IMAGE f {x | P x}`] THEN
12606   REWRITE_TAC[FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
12607   DISCH_THEN(X_CHOOSE_THEN `b:real^M` MP_TAC) THEN
12608   REWRITE_TAC[IN_ELIM_THM; dist; VECTOR_SUB_LZERO; NORM_NEG] THEN
12609   STRIP_TAC THEN REWRITE_TAC[CLOSED_LIMPT; LIMPT_APPROACHABLE] THEN
12610   EXISTS_TAC `norm((f:real^M->real^N) b) / norm(b)` THEN CONJ_TAC THENL
12611    [ASM_MESON_TAC[REAL_LT_DIV; NORM_POS_LT; NORM_EQ_0]; ALL_TAC] THEN
12612   X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN
12613   ASM_CASES_TAC `x:real^M = vec 0` THENL
12614    [FIRST_ASSUM(fun th -> ASM_REWRITE_TAC[MATCH_MP LINEAR_0 th]) THEN
12615     REWRITE_TAC[NORM_0; REAL_MUL_RZERO; real_ge; REAL_LE_REFL];
12616     ALL_TAC] THEN
12617   FIRST_X_ASSUM(MP_TAC o SPEC `(norm(a:real^M) / norm(x)) % x:real^M`) THEN
12618   ANTS_TAC THENL
12619    [ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
12620     ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0] THEN ASM_MESON_TAC[subspace];
12621     ALL_TAC] THEN
12622   FIRST_ASSUM(fun th -> REWRITE_TAC[MATCH_MP LINEAR_CMUL th]) THEN
12623   ASM_REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; real_ge] THEN
12624   ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; REAL_LE_LDIV_EQ; NORM_POS_LT] THEN
12625   REWRITE_TAC[real_div; REAL_MUL_AC]);;
12626
12627 let CLOSED_INJECTIVE_IMAGE_SUBSPACE = prove
12628  (`!f s. subspace s /\
12629          linear f /\
12630          (!x. x IN s /\ f(x) = vec 0 ==> x = vec 0) /\
12631          closed s
12632          ==> closed(IMAGE f s)`,
12633   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM COMPLETE_EQ_CLOSED] THEN
12634   MATCH_MP_TAC COMPLETE_ISOMETRIC_IMAGE THEN
12635   ASM_REWRITE_TAC[COMPLETE_EQ_CLOSED] THEN
12636   MATCH_MP_TAC INJECTIVE_IMP_ISOMETRIC THEN
12637   ASM_REWRITE_TAC[]);;
12638
12639 (* ------------------------------------------------------------------------- *)
12640 (* Relating linear images to open/closed/interior/closure.                   *)
12641 (* ------------------------------------------------------------------------- *)
12642
12643 let OPEN_SURJECTIVE_LINEAR_IMAGE = prove
12644  (`!f:real^M->real^N.
12645         linear f /\ (!y. ?x. f x = y)
12646         ==> !s. open s ==> open(IMAGE f s)`,
12647   GEN_TAC THEN STRIP_TAC THEN
12648   REWRITE_TAC[open_def; FORALL_IN_IMAGE] THEN
12649   FIRST_ASSUM(MP_TAC o GEN `k:num` o SPEC `basis k:real^N`) THEN
12650   REWRITE_TAC[SKOLEM_THM] THEN
12651   DISCH_THEN(X_CHOOSE_THEN `b:num->real^M` STRIP_ASSUME_TAC) THEN
12652   SUBGOAL_THEN `bounded(IMAGE (b:num->real^M) (1..dimindex(:N)))` MP_TAC THENL
12653    [SIMP_TAC[FINITE_IMP_BOUNDED; FINITE_IMAGE; FINITE_NUMSEG]; ALL_TAC] THEN
12654   REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE; IN_NUMSEG] THEN
12655   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
12656   X_GEN_TAC `s:real^M->bool` THEN MATCH_MP_TAC MONO_FORALL THEN
12657   X_GEN_TAC `x:real^M` THEN ASM_CASES_TAC `(x:real^M) IN s` THEN
12658   ASM_REWRITE_TAC[] THEN
12659   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
12660   EXISTS_TAC `e / B / &(dimindex(:N))` THEN
12661   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; DIMINDEX_GE_1; LE_1] THEN
12662   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN REWRITE_TAC[IN_IMAGE] THEN
12663   ABBREV_TAC `u = y - (f:real^M->real^N) x` THEN
12664   EXISTS_TAC `x + vsum(1..dimindex(:N)) (\i. (u:real^N)$i % b i):real^M` THEN
12665   ASM_SIMP_TAC[LINEAR_ADD; LINEAR_VSUM; FINITE_NUMSEG; o_DEF;
12666                LINEAR_CMUL; BASIS_EXPANSION] THEN
12667   CONJ_TAC THENL [EXPAND_TAC "u" THEN VECTOR_ARITH_TAC; ALL_TAC] THEN
12668   FIRST_X_ASSUM MATCH_MP_TAC THEN
12669   REWRITE_TAC[NORM_ARITH `dist(x + y,x) = norm y`] THEN
12670   MATCH_MP_TAC REAL_LET_TRANS THEN
12671   EXISTS_TAC `(dist(y,(f:real^M->real^N) x) * &(dimindex(:N))) * B` THEN
12672   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_OF_NUM_LT; DIMINDEX_GE_1; LE_1] THEN
12673   MATCH_MP_TAC VSUM_NORM_TRIANGLE THEN REWRITE_TAC[FINITE_NUMSEG] THEN
12674   ONCE_REWRITE_TAC[REAL_ARITH `(a * b) * c:real = b * a * c`] THEN
12675   GEN_REWRITE_TAC(RAND_CONV o LAND_CONV o RAND_CONV) [GSYM CARD_NUMSEG_1] THEN
12676   MATCH_MP_TAC SUM_BOUND THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
12677   X_GEN_TAC `k:num` THEN STRIP_TAC THEN REWRITE_TAC[NORM_MUL; dist] THEN
12678   MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS; NORM_POS_LE] THEN
12679   ASM_SIMP_TAC[COMPONENT_LE_NORM]);;
12680
12681 let OPEN_BIJECTIVE_LINEAR_IMAGE_EQ = prove
12682  (`!f:real^M->real^N s.
12683         linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
12684         ==> (open(IMAGE f s) <=> open s)`,
12685   REPEAT STRIP_TAC THEN EQ_TAC THENL
12686    [DISCH_TAC; ASM_MESON_TAC[OPEN_SURJECTIVE_LINEAR_IMAGE]] THEN
12687   SUBGOAL_THEN `s = {x | (f:real^M->real^N) x IN IMAGE f s}`
12688   SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
12689   MATCH_MP_TAC CONTINUOUS_OPEN_PREIMAGE_UNIV THEN
12690   ASM_SIMP_TAC[LINEAR_CONTINUOUS_AT]);;
12691
12692 add_linear_invariants [OPEN_BIJECTIVE_LINEAR_IMAGE_EQ];;
12693
12694 let CLOSED_INJECTIVE_LINEAR_IMAGE = prove
12695  (`!f:real^M->real^N.
12696         linear f /\ (!x y. f x = f y ==> x = y)
12697         ==> !s. closed s ==> closed(IMAGE f s)`,
12698   REPEAT STRIP_TAC THEN
12699   MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_LEFT_INVERSE) THEN
12700   ASM_REWRITE_TAC[] THEN
12701   DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^M` STRIP_ASSUME_TAC) THEN
12702   MATCH_MP_TAC CLOSED_IN_CLOSED_TRANS THEN
12703   EXISTS_TAC `IMAGE (f:real^M->real^N) (:real^M)` THEN
12704   CONJ_TAC THENL
12705    [MP_TAC(ISPECL [`g:real^N->real^M`; `IMAGE (f:real^M->real^N) (:real^M)`;
12706                    `IMAGE (g:real^N->real^M) (IMAGE (f:real^M->real^N) s)`]
12707         CONTINUOUS_CLOSED_IN_PREIMAGE) THEN
12708     ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN ANTS_TAC THENL
12709      [ASM_REWRITE_TAC[GSYM IMAGE_o; IMAGE_I]; ALL_TAC] THEN
12710     MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
12711     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [FUN_EQ_THM]) THEN
12712     REWRITE_TAC[EXTENSION; o_THM; I_THM] THEN SET_TAC[];
12713     MATCH_MP_TAC CLOSED_INJECTIVE_IMAGE_SUBSPACE THEN
12714     ASM_REWRITE_TAC[IN_UNIV; SUBSPACE_UNIV; CLOSED_UNIV] THEN
12715     X_GEN_TAC `x:real^M` THEN
12716     DISCH_THEN(MP_TAC o AP_TERM `g:real^N->real^M`) THEN
12717     RULE_ASSUM_TAC(REWRITE_RULE[FUN_EQ_THM; I_THM; o_THM]) THEN
12718     ASM_MESON_TAC[LINEAR_0]]);;
12719
12720 let CLOSED_INJECTIVE_LINEAR_IMAGE_EQ = prove
12721  (`!f:real^M->real^N s.
12722         linear f /\ (!x y. f x = f y ==> x = y)
12723         ==> (closed(IMAGE f s) <=> closed s)`,
12724   REPEAT STRIP_TAC THEN EQ_TAC THENL
12725    [DISCH_TAC; ASM_MESON_TAC[CLOSED_INJECTIVE_LINEAR_IMAGE]] THEN
12726   SUBGOAL_THEN `s = {x | (f:real^M->real^N) x IN IMAGE f s}`
12727   SUBST1_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
12728   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
12729   ASM_SIMP_TAC[LINEAR_CONTINUOUS_AT]);;
12730
12731 add_linear_invariants [CLOSED_INJECTIVE_LINEAR_IMAGE_EQ];;
12732
12733 let CLOSURE_LINEAR_IMAGE_SUBSET = prove
12734  (`!f:real^M->real^N s.
12735         linear f ==> IMAGE f (closure s) SUBSET closure(IMAGE f s)`,
12736   REPEAT STRIP_TAC THEN
12737   MATCH_MP_TAC IMAGE_CLOSURE_SUBSET THEN
12738   ASM_SIMP_TAC[CLOSED_CLOSURE; CLOSURE_SUBSET; LINEAR_CONTINUOUS_ON]);;
12739
12740 let CLOSURE_INJECTIVE_LINEAR_IMAGE  = prove
12741  (`!f:real^M->real^N s.
12742         linear f /\ (!x y. f x = f y ==> x = y)
12743         ==> closure(IMAGE f s) = IMAGE f (closure s)`,
12744   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
12745   ASM_SIMP_TAC[CLOSURE_LINEAR_IMAGE_SUBSET] THEN
12746   MATCH_MP_TAC CLOSURE_MINIMAL THEN
12747   SIMP_TAC[CLOSURE_SUBSET; IMAGE_SUBSET] THEN
12748   ASM_MESON_TAC[CLOSED_INJECTIVE_LINEAR_IMAGE; CLOSED_CLOSURE]);;
12749
12750 add_linear_invariants [CLOSURE_INJECTIVE_LINEAR_IMAGE];;
12751
12752 let CLOSURE_BOUNDED_LINEAR_IMAGE = prove
12753  (`!f:real^M->real^N s.
12754         linear f /\ bounded s
12755         ==> closure(IMAGE f s) = IMAGE f (closure s)`,
12756   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN
12757   ASM_SIMP_TAC[CLOSURE_LINEAR_IMAGE_SUBSET] THEN
12758   MATCH_MP_TAC CLOSURE_MINIMAL THEN
12759   SIMP_TAC[CLOSURE_SUBSET; IMAGE_SUBSET] THEN
12760   MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
12761   MATCH_MP_TAC COMPACT_LINEAR_IMAGE THEN
12762   ASM_REWRITE_TAC[COMPACT_CLOSURE]);;
12763
12764 let LINEAR_INTERIOR_IMAGE_SUBSET = prove
12765  (`!f:real^M->real^N s.
12766         linear f /\ (!x y. f x = f y ==> x = y)
12767        ==> interior(IMAGE f s) SUBSET IMAGE f (interior s)`,
12768   MESON_TAC[INTERIOR_IMAGE_SUBSET; LINEAR_CONTINUOUS_AT]);;
12769
12770 let LINEAR_IMAGE_SUBSET_INTERIOR = prove
12771  (`!f:real^M->real^N s.
12772         linear f /\ (!y. ?x. f x = y)
12773         ==> IMAGE f (interior s) SUBSET interior(IMAGE f s)`,
12774   REPEAT STRIP_TAC THEN MATCH_MP_TAC INTERIOR_MAXIMAL THEN
12775   ASM_SIMP_TAC[OPEN_SURJECTIVE_LINEAR_IMAGE; OPEN_INTERIOR;
12776                IMAGE_SUBSET; INTERIOR_SUBSET]);;
12777
12778 let INTERIOR_BIJECTIVE_LINEAR_IMAGE = prove
12779  (`!f:real^M->real^N s.
12780         linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
12781         ==> interior(IMAGE f s) = IMAGE f (interior s)`,
12782   REWRITE_TAC[interior] THEN GEOM_TRANSFORM_TAC[]);;
12783
12784 add_linear_invariants [INTERIOR_BIJECTIVE_LINEAR_IMAGE];;
12785
12786 let FRONTIER_BIJECTIVE_LINEAR_IMAGE = prove
12787  (`!f:real^M->real^N s.
12788         linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
12789         ==> frontier(IMAGE f s) = IMAGE f (frontier s)`,
12790   REWRITE_TAC[frontier] THEN GEOM_TRANSFORM_TAC[]);;
12791
12792 add_linear_invariants [FRONTIER_BIJECTIVE_LINEAR_IMAGE];;
12793
12794 (* ------------------------------------------------------------------------- *)
12795 (* Corollaries, reformulations and special cases for M = N.                  *)
12796 (* ------------------------------------------------------------------------- *)
12797
12798 let IN_INTERIOR_LINEAR_IMAGE = prove
12799  (`!f:real^M->real^N g s x.
12800         linear f /\ linear g /\ (f o g = I) /\ x IN interior s
12801         ==> (f x) IN interior (IMAGE f s)`,
12802   REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN REPEAT STRIP_TAC THEN
12803   MP_TAC(ISPECL [`f:real^M->real^N`; `s:real^M->bool`]
12804     LINEAR_IMAGE_SUBSET_INTERIOR) THEN
12805   ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
12806   ASM_MESON_TAC[]);;
12807
12808 let LINEAR_OPEN_MAPPING = prove
12809  (`!f:real^M->real^N g.
12810         linear f /\ linear g /\ (f o g = I)
12811         ==> !s. open s ==> open(IMAGE f s)`,
12812   REPEAT GEN_TAC THEN REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN DISCH_TAC THEN
12813   MATCH_MP_TAC OPEN_SURJECTIVE_LINEAR_IMAGE THEN
12814   ASM_MESON_TAC[]);;
12815
12816 let INTERIOR_INJECTIVE_LINEAR_IMAGE = prove
12817  (`!f:real^N->real^N s.
12818         linear f /\ (!x y. f x = f y ==> x = y)
12819         ==> interior(IMAGE f s) = IMAGE f (interior s)`,
12820   REPEAT STRIP_TAC THEN MATCH_MP_TAC INTERIOR_BIJECTIVE_LINEAR_IMAGE THEN
12821   ASM_MESON_TAC[LINEAR_INJECTIVE_IMP_SURJECTIVE]);;
12822
12823 let INTERIOR_SURJECTIVE_LINEAR_IMAGE = prove
12824  (`!f:real^N->real^N s.
12825         linear f /\ (!y. ?x. f x = y)
12826         ==> interior(IMAGE f s) = IMAGE f (interior s)`,
12827   REPEAT STRIP_TAC THEN MATCH_MP_TAC INTERIOR_BIJECTIVE_LINEAR_IMAGE THEN
12828   ASM_MESON_TAC[LINEAR_SURJECTIVE_IMP_INJECTIVE]);;
12829
12830 let CLOSURE_SURJECTIVE_LINEAR_IMAGE = prove
12831  (`!f:real^N->real^N s.
12832         linear f /\ (!y. ?x. f x = y)
12833         ==> closure(IMAGE f s) = IMAGE f (closure s)`,
12834   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_INJECTIVE_LINEAR_IMAGE THEN
12835   ASM_MESON_TAC[LINEAR_SURJECTIVE_IMP_INJECTIVE]);;
12836
12837 let FRONTIER_INJECTIVE_LINEAR_IMAGE = prove
12838  (`!f:real^N->real^N s.
12839         linear f /\ (!x y. f x = f y ==> x = y)
12840         ==> frontier(IMAGE f s) = IMAGE f (frontier s)`,
12841   REPEAT STRIP_TAC THEN MATCH_MP_TAC FRONTIER_BIJECTIVE_LINEAR_IMAGE THEN
12842   ASM_MESON_TAC[LINEAR_INJECTIVE_IMP_SURJECTIVE]);;
12843
12844 let FRONTIER_SURJECTIVE_LINEAR_IMAGE = prove
12845  (`!f:real^N->real^N.
12846         linear f /\ (!y. ?x. f x = y)
12847         ==> frontier(IMAGE f s) = IMAGE f (frontier s)`,
12848   REPEAT STRIP_TAC THEN MATCH_MP_TAC FRONTIER_BIJECTIVE_LINEAR_IMAGE THEN
12849   ASM_MESON_TAC[LINEAR_SURJECTIVE_IMP_INJECTIVE]);;
12850
12851 let COMPLETE_INJECTIVE_LINEAR_IMAGE = prove
12852  (`!f:real^M->real^N.
12853         linear f /\ (!x y. f x = f y ==> x = y)
12854         ==> !s. complete s ==> complete(IMAGE f s)`,
12855   REWRITE_TAC[COMPLETE_EQ_CLOSED; CLOSED_INJECTIVE_LINEAR_IMAGE]);;
12856
12857 let COMPLETE_INJECTIVE_LINEAR_IMAGE_EQ = prove
12858  (`!f:real^M->real^N s.
12859         linear f /\ (!x y. f x = f y ==> x = y)
12860         ==> (complete(IMAGE f s) <=> complete s)`,
12861   REWRITE_TAC[COMPLETE_EQ_CLOSED; CLOSED_INJECTIVE_LINEAR_IMAGE_EQ]);;
12862
12863 add_linear_invariants [COMPLETE_INJECTIVE_LINEAR_IMAGE_EQ];;
12864
12865 let LIMPT_INJECTIVE_LINEAR_IMAGE_EQ = prove
12866  (`!f:real^M->real^N s.
12867         linear f /\ (!x y. f x = f y ==> x = y)
12868         ==> ((f x) limit_point_of (IMAGE f s) <=> x limit_point_of s)`,
12869   REWRITE_TAC[LIMPT_APPROACHABLE; EXISTS_IN_IMAGE] THEN
12870   REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN
12871   DISCH_TAC THENL
12872    [MP_TAC(ISPEC `f:real^M->real^N` LINEAR_INJECTIVE_BOUNDED_BELOW_POS);
12873     MP_TAC(ISPEC `f:real^M->real^N` LINEAR_BOUNDED_POS)] THEN
12874   ASM_REWRITE_TAC[] THEN
12875   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THENL
12876    [FIRST_X_ASSUM(MP_TAC o SPEC `e * B:real`);
12877     FIRST_X_ASSUM(MP_TAC o SPEC `e / B:real`)] THEN
12878   ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_MUL; dist; GSYM LINEAR_SUB] THEN
12879   MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
12880   REPEAT(MATCH_MP_TAC MONO_AND THEN
12881          CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC]) THEN
12882   ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ; REAL_LT_RDIV_EQ] THEN
12883   MATCH_MP_TAC(REAL_ARITH `a <= b ==> b < x ==> a < x`) THEN
12884   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN ASM_SIMP_TAC[REAL_LE_RDIV_EQ]);;
12885
12886 add_linear_invariants [LIMPT_INJECTIVE_LINEAR_IMAGE_EQ];;
12887
12888 let LIMPT_TRANSLATION_EQ = prove
12889  (`!a s x. (a + x) limit_point_of (IMAGE (\y. a + y) s) <=> x limit_point_of s`,
12890   REWRITE_TAC[limit_point_of] THEN GEOM_TRANSLATE_TAC[]);;
12891
12892 add_translation_invariants [LIMPT_TRANSLATION_EQ];;
12893
12894 let OPEN_OPEN_LEFT_PROJECTION = prove
12895  (`!s t:real^(M,N)finite_sum->bool.
12896         open s /\ open t ==> open {x | x IN s /\ ?y. pastecart x y IN t}`,
12897   REPEAT STRIP_TAC THEN
12898   SUBGOAL_THEN
12899    `{x | x IN s /\ ?y. (pastecart x y:real^(M,N)finite_sum) IN t} =
12900     s INTER IMAGE fstcart t`
12901   SUBST1_TAC THENL
12902    [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_INTER; IN_IMAGE] THEN
12903     MESON_TAC[FSTCART_PASTECART; PASTECART_FST_SND];
12904     MATCH_MP_TAC OPEN_INTER THEN ASM_REWRITE_TAC[] THEN
12905     MATCH_MP_TAC(REWRITE_RULE[IMP_IMP; RIGHT_IMP_FORALL_THM]
12906       OPEN_SURJECTIVE_LINEAR_IMAGE) THEN
12907     ASM_REWRITE_TAC[LINEAR_FSTCART] THEN MESON_TAC[FSTCART_PASTECART]]);;
12908
12909 let OPEN_OPEN_RIGHT_PROJECTION = prove
12910  (`!s t:real^(M,N)finite_sum->bool.
12911         open s /\ open t ==> open {y | y IN s /\ ?x. pastecart x y IN t}`,
12912   REPEAT STRIP_TAC THEN
12913   SUBGOAL_THEN
12914    `{y | y IN s /\ ?x. (pastecart x y:real^(M,N)finite_sum) IN t} =
12915     s INTER IMAGE sndcart t`
12916   SUBST1_TAC THENL
12917    [REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_INTER; IN_IMAGE] THEN
12918     MESON_TAC[SNDCART_PASTECART; PASTECART_FST_SND];
12919     MATCH_MP_TAC OPEN_INTER THEN ASM_REWRITE_TAC[] THEN
12920     MATCH_MP_TAC(REWRITE_RULE[IMP_IMP; RIGHT_IMP_FORALL_THM]
12921       OPEN_SURJECTIVE_LINEAR_IMAGE) THEN
12922     ASM_REWRITE_TAC[LINEAR_SNDCART] THEN MESON_TAC[SNDCART_PASTECART]]);;
12923
12924 (* ------------------------------------------------------------------------- *)
12925 (* Even more special cases.                                                  *)
12926 (* ------------------------------------------------------------------------- *)
12927
12928 let INTERIOR_NEGATIONS = prove
12929  (`!s. interior(IMAGE (--) s) = IMAGE (--) (interior s)`,
12930   GEN_TAC THEN MATCH_MP_TAC INTERIOR_INJECTIVE_LINEAR_IMAGE THEN
12931   REWRITE_TAC[linear] THEN REPEAT CONJ_TAC THEN VECTOR_ARITH_TAC);;
12932
12933 let SYMMETRIC_INTERIOR = prove
12934  (`!s:real^N->bool.
12935         (!x. x IN s ==> --x IN s)
12936         ==> !x. x IN interior s ==> (--x) IN interior s`,
12937   REPEAT GEN_TAC THEN DISCH_TAC THEN GEN_TAC THEN
12938   DISCH_THEN(MP_TAC o MATCH_MP(ISPEC `(--):real^N->real^N` FUN_IN_IMAGE)) THEN
12939   REWRITE_TAC[GSYM INTERIOR_NEGATIONS] THEN
12940   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
12941   REWRITE_TAC[EXTENSION; IN_IMAGE] THEN ASM_MESON_TAC[VECTOR_NEG_NEG]);;
12942
12943 let CLOSURE_NEGATIONS = prove
12944  (`!s. closure(IMAGE (--) s) = IMAGE (--) (closure s)`,
12945   GEN_TAC THEN MATCH_MP_TAC CLOSURE_INJECTIVE_LINEAR_IMAGE THEN
12946   REWRITE_TAC[linear] THEN REPEAT CONJ_TAC THEN VECTOR_ARITH_TAC);;
12947
12948 let SYMMETRIC_CLOSURE = prove
12949  (`!s:real^N->bool.
12950         (!x. x IN s ==> --x IN s)
12951         ==> !x. x IN closure s ==> (--x) IN closure s`,
12952   REPEAT GEN_TAC THEN DISCH_TAC THEN GEN_TAC THEN
12953   DISCH_THEN(MP_TAC o MATCH_MP(ISPEC `(--):real^N->real^N` FUN_IN_IMAGE)) THEN
12954   REWRITE_TAC[GSYM CLOSURE_NEGATIONS] THEN
12955   MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
12956   REWRITE_TAC[EXTENSION; IN_IMAGE] THEN ASM_MESON_TAC[VECTOR_NEG_NEG]);;
12957
12958 (* ------------------------------------------------------------------------- *)
12959 (* Some properties of a canonical subspace.                                  *)
12960 (* ------------------------------------------------------------------------- *)
12961
12962 let SUBSPACE_SUBSTANDARD = prove
12963  (`!d. subspace
12964          {x:real^N | !i. d < i /\ i <= dimindex(:N) ==> x$i = &0}`,
12965   GEN_TAC THEN ASM_CASES_TAC `d <= dimindex(:N)` THENL
12966    [MP_TAC(ARITH_RULE `!i. d < i ==> 1 <= i`) THEN
12967     SIMP_TAC[subspace; IN_ELIM_THM; REAL_MUL_RZERO; REAL_ADD_LID;
12968              VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT; VEC_COMPONENT];
12969     ASM_SIMP_TAC[ARITH_RULE `~(d:num <= e) ==> (d < i /\ i <= e <=> F)`] THEN
12970     REWRITE_TAC[SET_RULE `{x | T} = UNIV`; SUBSPACE_UNIV]]);;
12971
12972 let CLOSED_SUBSTANDARD = prove
12973  (`!d. closed
12974         {x:real^N | !i. d < i /\ i <= dimindex(:N) ==> x$i = &0}`,
12975   GEN_TAC THEN
12976   SUBGOAL_THEN
12977    `{x:real^N | !i. d < i /\ i <= dimindex(:N) ==> x$i = &0} =
12978     INTERS {{x | basis i dot x = &0} | d < i /\ i <= dimindex(:N)}`
12979   SUBST1_TAC THENL
12980    [ALL_TAC;
12981     SIMP_TAC[CLOSED_INTERS; CLOSED_HYPERPLANE; IN_ELIM_THM;
12982              LEFT_IMP_EXISTS_THM]] THEN
12983   GEN_REWRITE_TAC I [EXTENSION] THEN REWRITE_TAC[IN_INTERS; IN_ELIM_THM] THEN
12984   SIMP_TAC[LEFT_IMP_EXISTS_THM; IN_ELIM_THM] THEN
12985   MP_TAC(ARITH_RULE `!i. d < i ==> 1 <= i`) THEN
12986   SIMP_TAC[DOT_BASIS] THEN MESON_TAC[]);;
12987
12988 let DIM_SUBSTANDARD = prove
12989  (`!d. d <= dimindex(:N)
12990        ==> (dim {x:real^N | !i. d < i /\ i <= dimindex(:N)
12991                                 ==> x$i = &0} =
12992             d)`,
12993   REPEAT STRIP_TAC THEN MATCH_MP_TAC DIM_UNIQUE THEN
12994   EXISTS_TAC `IMAGE (basis:num->real^N) (1..d)` THEN REPEAT CONJ_TAC THENL
12995    [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM; IN_NUMSEG] THEN
12996     MESON_TAC[BASIS_COMPONENT; ARITH_RULE `d < i ==> 1 <= i`; NOT_LT];
12997     ALL_TAC;
12998     MATCH_MP_TAC INDEPENDENT_MONO THEN
12999     EXISTS_TAC `{basis i :real^N | 1 <= i /\ i <= dimindex(:N)}` THEN
13000     REWRITE_TAC[INDEPENDENT_STDBASIS]THEN
13001     REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_ELIM_THM; IN_NUMSEG] THEN
13002     ASM_MESON_TAC[LE_TRANS];
13003     MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN REWRITE_TAC[HAS_SIZE_NUMSEG_1] THEN
13004     REWRITE_TAC[IN_NUMSEG] THEN ASM_MESON_TAC[LE_TRANS; BASIS_INJ]] THEN
13005   POP_ASSUM MP_TAC THEN SPEC_TAC(`d:num`,`d:num`) THEN
13006   INDUCT_TAC THENL
13007    [REWRITE_TAC[ARITH_RULE `0 < i <=> 1 <= i`; SPAN_STDBASIS] THEN
13008     SUBGOAL_THEN `IMAGE basis (1 .. 0) :real^N->bool = {}` SUBST1_TAC THENL
13009      [REWRITE_TAC[IMAGE_EQ_EMPTY; NUMSEG_EMPTY; ARITH]; ALL_TAC] THEN
13010     DISCH_TAC THEN REWRITE_TAC[SPAN_EMPTY; SUBSET; IN_ELIM_THM; IN_SING] THEN
13011     SIMP_TAC[CART_EQ; VEC_COMPONENT];
13012     ALL_TAC] THEN
13013   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o check (is_imp o concl)) THEN
13014   ASM_SIMP_TAC[ARITH_RULE `SUC d <= n ==> d <= n`] THEN
13015   REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN DISCH_TAC THEN
13016   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
13017   FIRST_X_ASSUM(MP_TAC o SPEC `x - (x$(SUC d)) % basis(SUC d) :real^N`) THEN
13018   ANTS_TAC THENL
13019    [X_GEN_TAC `i:num` THEN STRIP_TAC THEN
13020     FIRST_ASSUM(ASSUME_TAC o MATCH_MP(ARITH_RULE `d < i ==> 1 <= i`)) THEN
13021     ASM_SIMP_TAC[VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT] THEN
13022     ASM_SIMP_TAC[BASIS_COMPONENT] THEN COND_CASES_TAC THEN
13023     ASM_REWRITE_TAC[REAL_MUL_RID; REAL_SUB_REFL] THEN
13024     ASM_REWRITE_TAC[REAL_MUL_RZERO; REAL_SUB_RZERO] THEN
13025     ASM_MESON_TAC[ARITH_RULE `d < i /\ ~(i = SUC d) ==> SUC d < i`];
13026     ALL_TAC] THEN
13027   DISCH_TAC THEN
13028   SUBST1_TAC(VECTOR_ARITH
13029    `x = (x - (x$(SUC d)) % basis(SUC d)) +
13030         x$(SUC d) % basis(SUC d) :real^N`) THEN
13031   MATCH_MP_TAC SPAN_ADD THEN CONJ_TAC THENL
13032    [ASM_MESON_TAC[SPAN_MONO; SUBSET_IMAGE; SUBSET; SUBSET_NUMSEG; LE_REFL; LE];
13033     MATCH_MP_TAC SPAN_MUL THEN MATCH_MP_TAC SPAN_SUPERSET THEN
13034     REWRITE_TAC[IN_IMAGE; IN_NUMSEG] THEN
13035     MESON_TAC[LE_REFL; ARITH_RULE `1 <= SUC d`]]);;
13036
13037 (* ------------------------------------------------------------------------- *)
13038 (* Hence closure and completeness of all subspaces.                          *)
13039 (* ------------------------------------------------------------------------- *)
13040
13041 let CLOSED_SUBSPACE = prove
13042  (`!s:real^N->bool. subspace s ==> closed s`,
13043   REPEAT STRIP_TAC THEN ABBREV_TAC `d = dim(s:real^N->bool)` THEN
13044   MP_TAC(MATCH_MP DIM_SUBSTANDARD
13045     (ISPEC `s:real^N->bool` DIM_SUBSET_UNIV)) THEN
13046   ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
13047   MP_TAC(ISPECL
13048    [`{x:real^N | !i. d < i /\ i <= dimindex(:N)
13049                                 ==> x$i = &0}`;
13050     `s:real^N->bool`] SUBSPACE_ISOMORPHISM) THEN
13051   ASM_REWRITE_TAC[SUBSPACE_SUBSTANDARD] THEN
13052   DISCH_THEN(X_CHOOSE_THEN `f:real^N->real^N` MP_TAC) THEN
13053   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
13054   DISCH_THEN(CONJUNCTS_THEN2 (SUBST_ALL_TAC o SYM) STRIP_ASSUME_TAC) THEN
13055   MATCH_MP_TAC(ISPEC `f:real^N->real^N` CLOSED_INJECTIVE_IMAGE_SUBSPACE) THEN
13056   ASM_REWRITE_TAC[SUBSPACE_SUBSTANDARD; CLOSED_SUBSTANDARD] THEN
13057   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
13058   ASM_REWRITE_TAC[] THEN
13059   CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[LINEAR_0]] THEN
13060   REWRITE_TAC[IN_ELIM_THM] THEN
13061   ASM_MESON_TAC[VEC_COMPONENT; ARITH_RULE `d < i ==> 1 <= i`]);;
13062
13063 let COMPLETE_SUBSPACE = prove
13064  (`!s:real^N->bool. subspace s ==> complete s`,
13065   REWRITE_TAC[COMPLETE_EQ_CLOSED; CLOSED_SUBSPACE]);;
13066
13067 let CLOSED_SPAN = prove
13068  (`!s. closed(span s)`,
13069   SIMP_TAC[CLOSED_SUBSPACE; SUBSPACE_SPAN]);;
13070
13071 let DIM_CLOSURE = prove
13072  (`!s:real^N->bool. dim(closure s) = dim s`,
13073   GEN_TAC THEN REWRITE_TAC[GSYM LE_ANTISYM] THEN CONJ_TAC THENL
13074    [GEN_REWRITE_TAC RAND_CONV [GSYM DIM_SPAN]; ALL_TAC] THEN
13075   MATCH_MP_TAC DIM_SUBSET THEN REWRITE_TAC[CLOSURE_SUBSET] THEN
13076   MATCH_MP_TAC CLOSURE_MINIMAL THEN
13077   SIMP_TAC[CLOSED_SUBSPACE; SUBSPACE_SPAN; SPAN_INC]);;
13078
13079 let CLOSED_BOUNDEDPREIM_CONTINUOUS_IMAGE = prove
13080  (`!f:real^M->real^N s.
13081       closed s /\ f continuous_on s /\
13082       (!e. bounded {x | x IN s /\ norm(f x) <= e})
13083       ==> closed(IMAGE f s)`,
13084   REPEAT STRIP_TAC THEN REWRITE_TAC[CLOSED_INTERS_COMPACT] THEN
13085   REWRITE_TAC[SET_RULE
13086    `cball(vec 0,e) INTER IMAGE (f:real^M->real^N) s =
13087     IMAGE f (s INTER {x | x IN s /\ f x IN cball(vec 0,e)})`] THEN
13088   X_GEN_TAC `e:real` THEN MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
13089   CONJ_TAC THENL
13090    [MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:real^M->bool` THEN
13091     ASM_REWRITE_TAC[] THEN SET_TAC[];
13092     MATCH_MP_TAC CLOSED_INTER_COMPACT THEN ASM_REWRITE_TAC[] THEN
13093     REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN CONJ_TAC THENL
13094      [ASM_REWRITE_TAC[IN_CBALL_0];
13095       ASM_SIMP_TAC[CONTINUOUS_CLOSED_PREIMAGE; CLOSED_CBALL]]]);;
13096
13097 let CLOSED_INJECTIVE_IMAGE_SUBSET_SUBSPACE = prove
13098  (`!f:real^M->real^N s t.
13099         closed s /\ s SUBSET t /\ subspace t /\
13100         linear f /\
13101         (!x. x IN t /\ f(x) = vec 0 ==> x = vec 0)
13102         ==> closed(IMAGE f s)`,
13103   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSED_BOUNDEDPREIM_CONTINUOUS_IMAGE THEN
13104   ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN
13105   MP_TAC(ISPECL [`f:real^M->real^N`; `t:real^M->bool`]
13106     INJECTIVE_IMP_ISOMETRIC) THEN
13107   ASM_SIMP_TAC[CLOSED_SUBSPACE; real_ge] THEN
13108   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
13109   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
13110   X_GEN_TAC `e:real` THEN MATCH_MP_TAC BOUNDED_SUBSET THEN
13111   EXISTS_TAC `cball(vec 0:real^M,e / B)` THEN
13112   REWRITE_TAC[BOUNDED_CBALL] THEN
13113   ASM_SIMP_TAC[SUBSET; IN_ELIM_THM; IN_CBALL_0; REAL_LE_RDIV_EQ] THEN
13114   ASM_MESON_TAC[SUBSET; REAL_LE_TRANS]);;
13115
13116 let BASIS_COORDINATES_LIPSCHITZ = prove
13117  (`!b:real^N->bool.
13118         independent b
13119         ==> ?B. &0 < B /\
13120                 !c v. v IN b
13121                       ==> abs(c v) <= B * norm(vsum b (\v. c(v) % v))`,
13122   X_GEN_TAC `k:real^N->bool` THEN DISCH_TAC THEN
13123   FIRST_ASSUM(STRIP_ASSUME_TAC o MATCH_MP INDEPENDENT_BOUND) THEN
13124   FIRST_ASSUM(X_CHOOSE_THEN `b:num->real^N` STRIP_ASSUME_TAC o
13125         GEN_REWRITE_RULE I [FINITE_INDEX_NUMSEG]) THEN
13126   ABBREV_TAC `n = CARD(k:real^N->bool)` THEN
13127   MP_TAC(ISPECL
13128    [`(\x. vsum(1..n) (\i. x$i % b i)):real^N->real^N`;
13129     `span(IMAGE basis (1..n)):real^N->bool`]
13130         INJECTIVE_IMP_ISOMETRIC) THEN
13131   REWRITE_TAC[SUBSPACE_SPAN] THEN ANTS_TAC THENL
13132    [CONJ_TAC THENL [SIMP_TAC[CLOSED_SUBSPACE; SUBSPACE_SPAN]; ALL_TAC] THEN
13133     CONJ_TAC THENL
13134      [MATCH_MP_TAC LINEAR_COMPOSE_VSUM THEN
13135       REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN REPEAT STRIP_TAC THEN
13136       MATCH_MP_TAC LINEAR_VMUL_COMPONENT THEN
13137       SIMP_TAC[LINEAR_ID] THEN ASM_ARITH_TAC;
13138       ALL_TAC] THEN
13139     X_GEN_TAC `x:real^N` THEN
13140     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
13141     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SPAN_IMAGE_BASIS]) THEN
13142     REWRITE_TAC[IN_NUMSEG] THEN DISCH_TAC THEN
13143     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
13144     DISCH_THEN(X_CHOOSE_TAC `c:real^N->num`) THEN
13145     SUBGOAL_THEN
13146      `vsum(1..n) (\i. (x:real^N)$i % b i:real^N) = vsum k (\v. x$(c v) % v)`
13147     SUBST1_TAC THENL
13148      [MATCH_MP_TAC VSUM_EQ_GENERAL_INVERSES THEN
13149       MAP_EVERY EXISTS_TAC [`b:num->real^N`; `c:real^N->num`] THEN
13150       ASM SET_TAC[];
13151       ALL_TAC] THEN
13152     DISCH_TAC THEN
13153     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INDEPENDENT_EXPLICIT]) THEN
13154     DISCH_THEN(MP_TAC o SPEC `\v:real^N. (x:real^N)$(c v)` o CONJUNCT2) THEN
13155     ASM_REWRITE_TAC[] THEN ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
13156     REWRITE_TAC[CART_EQ; FORALL_IN_IMAGE; VEC_COMPONENT] THEN
13157     ASM_MESON_TAC[IN_NUMSEG];
13158     ALL_TAC] THEN
13159   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
13160   EXISTS_TAC `inv(B:real)` THEN ASM_REWRITE_TAC[REAL_LT_INV_EQ] THEN
13161   ASM_REWRITE_TAC[FORALL_IN_IMAGE; IN_NUMSEG] THEN
13162   MAP_EVERY X_GEN_TAC [`c:real^N->real`; `j:num`] THEN STRIP_TAC THEN
13163   ONCE_REWRITE_TAC[REAL_ARITH `inv B * x = x / B`] THEN
13164   ASM_SIMP_TAC[REAL_LE_RDIV_EQ] THEN
13165   W(MP_TAC o PART_MATCH (lhs o rand) VSUM_IMAGE o rand o rand o snd) THEN
13166   ASM_REWRITE_TAC[FINITE_NUMSEG] THEN DISCH_THEN SUBST1_TAC THEN
13167   FIRST_X_ASSUM(MP_TAC o SPEC
13168    `(lambda i. if 1 <= i /\ i <= n then c(b i:real^N) else &0):real^N`) THEN
13169   SIMP_TAC[IN_SPAN_IMAGE_BASIS; LAMBDA_BETA] THEN
13170   ANTS_TAC THENL [MESON_TAC[IN_NUMSEG]; ALL_TAC] THEN
13171   MATCH_MP_TAC(REAL_ARITH `x = v /\ u <= y ==> x >= y ==> u <= v`) THEN
13172   CONJ_TAC THENL
13173    [AP_TERM_TAC THEN MATCH_MP_TAC VSUM_EQ_NUMSEG THEN
13174     SUBGOAL_THEN `!i. i <= n ==> i <= dimindex(:N)` MP_TAC THENL
13175      [ASM_ARITH_TAC; SIMP_TAC[LAMBDA_BETA] THEN DISCH_THEN(K ALL_TAC)] THEN
13176     REWRITE_TAC[o_THM];
13177     GEN_REWRITE_TAC RAND_CONV [REAL_MUL_SYM] THEN
13178     ASM_SIMP_TAC[REAL_LE_RMUL_EQ] THEN
13179     MP_TAC(ISPECL
13180      [`(lambda i. if 1 <= i /\ i <= n then c(b i:real^N) else &0):real^N`;
13181       `j:num`] COMPONENT_LE_NORM) THEN
13182     SIMP_TAC[LAMBDA_BETA] THEN ASM_REWRITE_TAC[] THEN
13183     DISCH_THEN MATCH_MP_TAC THEN ASM_ARITH_TAC]);;
13184
13185 let BASIS_COORDINATES_CONTINUOUS = prove
13186  (`!b:real^N->bool e.
13187         independent b /\ &0 < e
13188         ==> ?d. &0 < d /\
13189                 !c. norm(vsum b (\v. c(v) % v)) < d
13190                     ==> !v. v IN b ==> abs(c v) < e`,
13191   REPEAT STRIP_TAC THEN
13192   FIRST_X_ASSUM(MP_TAC o MATCH_MP BASIS_COORDINATES_LIPSCHITZ) THEN
13193   DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
13194   EXISTS_TAC `e / B:real` THEN ASM_SIMP_TAC[REAL_LT_DIV] THEN
13195   X_GEN_TAC `c:real^N->real` THEN DISCH_TAC THEN
13196   X_GEN_TAC `v:real^N` THEN DISCH_TAC THEN
13197   MATCH_MP_TAC REAL_LET_TRANS THEN
13198   EXISTS_TAC `B * norm(vsum b (\v:real^N. c v % v))` THEN
13199   ASM_SIMP_TAC[] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
13200   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ]);;
13201
13202 (* ------------------------------------------------------------------------- *)
13203 (* Affine transformations of intervals.                                      *)
13204 (* ------------------------------------------------------------------------- *)
13205
13206 let AFFINITY_INVERSES = prove
13207  (`!m c. ~(m = &0)
13208          ==> (\x. m % x + c) o (\x. inv(m) % x + (--(inv(m) % c))) = I /\
13209              (\x. inv(m) % x + (--(inv(m) % c))) o (\x. m % x + c) = I`,
13210   REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN
13211   REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_RNEG] THEN
13212   SIMP_TAC[VECTOR_MUL_ASSOC; REAL_MUL_LINV; REAL_MUL_RINV] THEN
13213   REPEAT STRIP_TAC THEN VECTOR_ARITH_TAC);;
13214
13215 let REAL_AFFINITY_LE = prove
13216  (`!m c x y. &0 < m ==> (m * x + c <= y <=> x <= inv(m) * y + --(c / m))`,
13217   REWRITE_TAC[REAL_ARITH `m * x + c <= y <=> x * m <= y - c`] THEN
13218   SIMP_TAC[GSYM REAL_LE_RDIV_EQ] THEN REAL_ARITH_TAC);;
13219
13220 let REAL_LE_AFFINITY = prove
13221  (`!m c x y. &0 < m ==> (y <= m * x + c <=> inv(m) * y + --(c / m) <= x)`,
13222   REWRITE_TAC[REAL_ARITH `y <= m * x + c <=> y - c <= x * m`] THEN
13223   SIMP_TAC[GSYM REAL_LE_LDIV_EQ] THEN REAL_ARITH_TAC);;
13224
13225 let REAL_AFFINITY_LT = prove
13226  (`!m c x y. &0 < m ==> (m * x + c < y <=> x < inv(m) * y + --(c / m))`,
13227   SIMP_TAC[REAL_LE_AFFINITY; GSYM REAL_NOT_LE]);;
13228
13229 let REAL_LT_AFFINITY = prove
13230  (`!m c x y. &0 < m ==> (y < m * x + c <=> inv(m) * y + --(c / m) < x)`,
13231   SIMP_TAC[REAL_AFFINITY_LE; GSYM REAL_NOT_LE]);;
13232
13233 let REAL_AFFINITY_EQ = prove
13234  (`!m c x y. ~(m = &0) ==> (m * x + c = y <=> x = inv(m) * y + --(c / m))`,
13235   CONV_TAC REAL_FIELD);;
13236
13237 let REAL_EQ_AFFINITY = prove
13238  (`!m c x y. ~(m = &0) ==> (y = m * x + c  <=> inv(m) * y + --(c / m) = x)`,
13239   CONV_TAC REAL_FIELD);;
13240
13241 let VECTOR_AFFINITY_EQ = prove
13242  (`!m c x y. ~(m = &0)
13243              ==> (m % x + c = y <=> x = inv(m) % y + --(inv(m) % c))`,
13244   SIMP_TAC[CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
13245            real_div; VECTOR_NEG_COMPONENT; REAL_AFFINITY_EQ] THEN
13246   REWRITE_TAC[REAL_MUL_AC]);;
13247
13248 let VECTOR_EQ_AFFINITY = prove
13249  (`!m c x y. ~(m = &0)
13250              ==> (y = m % x + c <=> inv(m) % y + --(inv(m) % c) = x)`,
13251   SIMP_TAC[CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
13252            real_div; VECTOR_NEG_COMPONENT; REAL_EQ_AFFINITY] THEN
13253   REWRITE_TAC[REAL_MUL_AC]);;
13254
13255 let IMAGE_AFFINITY_INTERVAL = prove
13256  (`!a b:real^N m c.
13257         IMAGE (\x. m % x + c) (interval[a,b]) =
13258             if interval[a,b] = {} then {}
13259             else if &0 <= m then interval[m % a + c,m % b + c]
13260             else interval[m % b + c,m % a + c]`,
13261   REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[IMAGE_CLAUSES] THEN
13262   ASM_CASES_TAC `m = &0` THEN ASM_REWRITE_TAC[REAL_LE_LT] THENL
13263    [ASM_REWRITE_TAC[VECTOR_MUL_LZERO; VECTOR_ADD_LID; COND_ID] THEN
13264     REWRITE_TAC[INTERVAL_SING] THEN ASM SET_TAC[];
13265     ALL_TAC] THEN
13266   FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP (REAL_ARITH
13267    `~(x = &0) ==> &0 < x \/ &0 < --x`)) THEN
13268   ASM_SIMP_TAC[EXTENSION; IN_IMAGE; REAL_ARITH `&0 < --x ==> ~(&0 < x)`] THENL
13269    [ALL_TAC;
13270     ONCE_REWRITE_TAC[VECTOR_ARITH `x = m % y + c <=> c = (--m) % y + x`]] THEN
13271   ASM_SIMP_TAC[VECTOR_EQ_AFFINITY; REAL_LT_IMP_NZ; UNWIND_THM1] THEN
13272   SIMP_TAC[IN_INTERVAL; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT;
13273            VECTOR_NEG_COMPONENT] THEN
13274   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM REAL_LT_INV_EQ]) THEN
13275   SIMP_TAC[REAL_AFFINITY_LE; REAL_LE_AFFINITY; real_div] THEN
13276   DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[REAL_INV_INV] THEN
13277   REWRITE_TAC[REAL_MUL_LNEG; REAL_NEGNEG] THEN
13278   ASM_SIMP_TAC[REAL_FIELD `&0 < m ==> (inv m * x) * m = x`] THEN
13279   GEN_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN AP_TERM_TAC THEN REAL_ARITH_TAC);;
13280
13281 (* ------------------------------------------------------------------------- *)
13282 (* Existence of eigenvectors. The proof is only in this file because it uses *)
13283 (* a few simple results about continuous functions (at least                 *)
13284 (* CONTINUOUS_ON_LIFT_DOT2, CONTINUOUS_ATTAINS_SUP and CLOSED_SUBSPACE).     *)
13285 (* ------------------------------------------------------------------------- *)
13286
13287 let SELF_ADJOINT_HAS_EIGENVECTOR_IN_SUBSPACE = prove
13288  (`!f:real^N->real^N s.
13289         linear f /\ adjoint f = f /\
13290         subspace s /\ ~(s = {vec 0}) /\ (!x. x IN s ==> f x IN s)
13291         ==> ?v c. v IN s /\ norm(v) = &1 /\ f(v) = c % v`,
13292   let lemma = prove
13293    (`!a b. (!x. a * x <= b * x pow 2) ==> &0 <= b ==> a = &0`,
13294     REPEAT GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[REAL_LE_LT] THEN
13295     ASM_CASES_TAC `b = &0` THEN ASM_REWRITE_TAC[] THENL
13296      [FIRST_X_ASSUM(fun t -> MP_TAC(SPEC `&1` t) THEN
13297         MP_TAC(SPEC `-- &1` t)) THEN ASM_REAL_ARITH_TAC;
13298       DISCH_TAC THEN  FIRST_X_ASSUM(MP_TAC o SPEC `a / &2 / b`) THEN
13299       ASM_SIMP_TAC[REAL_FIELD
13300        `&0 < b ==> (b * (a / b) pow 2) = a pow 2 / b`] THEN
13301       REWRITE_TAC[real_div; REAL_MUL_ASSOC] THEN SIMP_TAC[GSYM real_div] THEN
13302       ASM_SIMP_TAC[REAL_LE_DIV2_EQ] THEN
13303       REWRITE_TAC[REAL_LT_SQUARE; REAL_ARITH
13304         `(a * a) / &2 <= (a / &2) pow 2 <=> ~(&0 < a * a)`]]) in
13305   REPEAT STRIP_TAC THEN
13306   MP_TAC(ISPECL [`\x:real^N. (f x) dot x`;
13307                  `s INTER sphere(vec 0:real^N,&1)`]
13308         CONTINUOUS_ATTAINS_SUP) THEN
13309   REWRITE_TAC[EXISTS_IN_GSPEC; FORALL_IN_GSPEC; o_DEF] THEN ANTS_TAC THENL
13310    [ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_DOT2; LINEAR_CONTINUOUS_ON;
13311                    CONTINUOUS_ON_ID] THEN
13312     ASM_SIMP_TAC[COMPACT_SPHERE; CLOSED_INTER_COMPACT; CLOSED_SUBSPACE] THEN
13313     FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE
13314       `~(s = {a}) ==> a IN s ==> ?b. ~(b = a) /\ b IN s`)) THEN
13315     ASM_SIMP_TAC[SUBSPACE_0; IN_SPHERE_0; GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN
13316     DISCH_THEN(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
13317     EXISTS_TAC `inv(norm x) % x:real^N` THEN
13318     ASM_REWRITE_TAC[IN_ELIM_THM; VECTOR_SUB_RZERO; NORM_MUL] THEN
13319     ASM_SIMP_TAC[SUBSPACE_MUL; REAL_ABS_INV; REAL_ABS_NORM] THEN
13320     ASM_SIMP_TAC[REAL_MUL_LINV; NORM_EQ_0];
13321     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v:real^N` THEN
13322     REWRITE_TAC[IN_INTER; IN_SPHERE_0] THEN STRIP_TAC THEN
13323     ABBREV_TAC `c = (f:real^N->real^N) v dot v` THEN
13324     EXISTS_TAC `c:real` THEN ASM_REWRITE_TAC[]] THEN
13325   ABBREV_TAC `p = \x y:real^N. c * (x dot y) - (f x) dot y` THEN
13326   SUBGOAL_THEN `!x:real^N. x IN s ==> &0 <= p x x` (LABEL_TAC "POSDEF") THENL
13327    [X_GEN_TAC `x:real^N` THEN EXPAND_TAC "p" THEN REWRITE_TAC[] THEN
13328     ASM_CASES_TAC `x:real^N = vec 0` THEN DISCH_TAC THEN
13329     ASM_REWRITE_TAC[DOT_RZERO; REAL_MUL_RZERO; REAL_SUB_LE; REAL_LE_REFL] THEN
13330     FIRST_X_ASSUM(MP_TAC o SPEC `inv(norm x) % x:real^N`) THEN
13331     ASM_SIMP_TAC[SUBSPACE_MUL] THEN
13332     ASM_SIMP_TAC[LINEAR_CMUL; NORM_MUL; REAL_ABS_INV; DOT_RMUL] THEN
13333     ASM_SIMP_TAC[REAL_ABS_NORM; REAL_MUL_LINV; NORM_EQ_0; DOT_LMUL] THEN
13334     ASM_SIMP_TAC[GSYM REAL_LE_LDIV_EQ; DOT_POS_LT] THEN
13335     REWRITE_TAC[GSYM NORM_POW_2; real_div; REAL_INV_POW] THEN REAL_ARITH_TAC;
13336     ALL_TAC] THEN
13337   SUBGOAL_THEN `!y:real^N. y IN s ==> !a. p v y * a <= p y y * a pow 2`
13338   MP_TAC THENL
13339    [REPEAT STRIP_TAC THEN
13340     REMOVE_THEN "POSDEF" (MP_TAC o SPEC `v - (&2 * a) % y:real^N`) THEN
13341     EXPAND_TAC "p" THEN ASM_SIMP_TAC[SUBSPACE_SUB; SUBSPACE_MUL] THEN
13342     ASM_SIMP_TAC[LINEAR_SUB; LINEAR_CMUL] THEN
13343     REWRITE_TAC[DOT_LSUB; DOT_LMUL] THEN
13344     REWRITE_TAC[DOT_RSUB; DOT_RMUL] THEN
13345     SUBGOAL_THEN `f y dot (v:real^N) = f v dot y` SUBST1_TAC THENL
13346      [ASM_MESON_TAC[ADJOINT_CLAUSES; DOT_SYM]; ALL_TAC] THEN
13347     ASM_REWRITE_TAC[GSYM NORM_POW_2] THEN REWRITE_TAC[NORM_POW_2] THEN
13348     MATCH_MP_TAC(REAL_ARITH
13349         `&4 * (z - y) = x ==> &0 <= x ==> y <= z`) THEN
13350     REWRITE_TAC[DOT_SYM] THEN CONV_TAC REAL_RING;
13351     DISCH_THEN(MP_TAC o GEN `y:real^N` o DISCH `(y:real^N) IN s` o
13352       MATCH_MP lemma o C MP (ASSUME `(y:real^N) IN s`) o SPEC `y:real^N`) THEN
13353     ASM_SIMP_TAC[] THEN EXPAND_TAC "p" THEN
13354     REWRITE_TAC[GSYM DOT_LMUL; GSYM DOT_LSUB] THEN
13355     DISCH_THEN(MP_TAC o SPEC `c % v - f v:real^N`) THEN
13356     ASM_SIMP_TAC[SUBSPACE_MUL; SUBSPACE_SUB; DOT_EQ_0; VECTOR_SUB_EQ]]);;
13357
13358 let SELF_ADJOINT_HAS_EIGENVECTOR = prove
13359  (`!f:real^N->real^N.
13360         linear f /\ adjoint f = f ==> ?v c. norm(v) = &1 /\ f(v) = c % v`,
13361   REPEAT STRIP_TAC THEN
13362   MP_TAC(ISPECL [`f:real^N->real^N`; `(:real^N)`]
13363         SELF_ADJOINT_HAS_EIGENVECTOR_IN_SUBSPACE) THEN
13364   ASM_REWRITE_TAC[SUBSPACE_UNIV; IN_UNIV] THEN DISCH_THEN MATCH_MP_TAC THEN
13365   MATCH_MP_TAC(SET_RULE `!a. ~(a IN s) ==> ~(UNIV = s)`) THEN
13366   EXISTS_TAC `vec 1:real^N` THEN
13367   REWRITE_TAC[IN_SING; VEC_EQ; ARITH_EQ]);;
13368
13369 let SELF_ADJOINT_HAS_EIGENVECTOR_BASIS_OF_SUBSPACE = prove
13370  (`!f:real^N->real^N s.
13371         linear f /\ adjoint f = f /\
13372         subspace s /\ (!x. x IN s ==> f x IN s)
13373         ==> ?b. b SUBSET s /\
13374                 pairwise orthogonal b /\
13375                 (!x. x IN b ==> norm x = &1 /\ ?c. f(x) = c % x) /\
13376                 independent b /\
13377                 span b = s /\
13378                 b HAS_SIZE dim s`,
13379   let lemma = prove
13380    (`!f:real^N->real^N s.
13381           linear f /\ adjoint f = f /\ subspace s /\ (!x. x IN s ==> f x IN s)
13382           ==> ?b. b SUBSET s /\ b HAS_SIZE dim s /\
13383                   pairwise orthogonal b /\
13384                   (!x. x IN b ==> norm x = &1 /\ ?c. f(x) = c % x)`,
13385     REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN REWRITE_TAC[IMP_IMP] THEN
13386     GEN_TAC THEN STRIP_TAC THEN GEN_TAC THEN
13387     WF_INDUCT_TAC `dim(s:real^N->bool)` THEN STRIP_TAC THEN
13388     ASM_CASES_TAC `dim(s:real^N->bool) = 0` THENL
13389      [EXISTS_TAC `{}:real^N->bool` THEN
13390       ASM_SIMP_TAC[HAS_SIZE_CLAUSES; NOT_IN_EMPTY;
13391                    PAIRWISE_EMPTY; EMPTY_SUBSET];
13392       ALL_TAC] THEN
13393     FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [DIM_EQ_0]) THEN
13394     DISCH_THEN(ASSUME_TAC o MATCH_MP (SET_RULE
13395      `~(s SUBSET {a}) ==> ~(s = {a})`)) THEN
13396     MP_TAC(ISPECL [`f:real^N->real^N`; `s:real^N->bool`]
13397       SELF_ADJOINT_HAS_EIGENVECTOR_IN_SUBSPACE) THEN
13398     ASM_REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN
13399     DISCH_THEN(X_CHOOSE_THEN `v:real^N` MP_TAC) THEN
13400     ASM_CASES_TAC `v:real^N = vec 0` THEN ASM_REWRITE_TAC[NORM_0] THEN
13401     CONV_TAC REAL_RAT_REDUCE_CONV THEN
13402     DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN
13403     FIRST_X_ASSUM(MP_TAC o SPEC `{y:real^N | y IN s /\ orthogonal v y}`) THEN
13404     REWRITE_TAC[SUBSPACE_ORTHOGONAL_TO_VECTOR; IN_ELIM_THM] THEN
13405     MP_TAC(ISPECL [`span {v:real^N}`; `s:real^N->bool`]
13406           DIM_SUBSPACE_ORTHOGONAL_TO_VECTORS) THEN
13407     REWRITE_TAC[ONCE_REWRITE_RULE[ORTHOGONAL_SYM] ORTHOGONAL_TO_SPAN_EQ] THEN
13408     ASM_REWRITE_TAC[SUBSPACE_SPAN; IN_SING; FORALL_UNWIND_THM2] THEN
13409     ANTS_TAC THENL
13410      [MATCH_MP_TAC SPAN_SUBSET_SUBSPACE THEN ASM SET_TAC[];
13411       DISCH_THEN(SUBST1_TAC o SYM)] THEN
13412     ASM_REWRITE_TAC[DIM_SPAN; DIM_SING; ARITH_RULE `n < n + 1`] THEN
13413     ANTS_TAC THENL
13414      [REWRITE_TAC[SET_RULE `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
13415       ASM_SIMP_TAC[SUBSPACE_INTER; SUBSPACE_ORTHOGONAL_TO_VECTOR] THEN
13416       REWRITE_TAC[orthogonal] THEN X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN
13417       MATCH_MP_TAC EQ_TRANS THEN
13418       EXISTS_TAC `(f:real^N->real^N) v dot x` THEN CONJ_TAC THENL
13419        [ASM_MESON_TAC[ADJOINT_CLAUSES];
13420         ASM_MESON_TAC[DOT_LMUL; REAL_MUL_RZERO]];
13421       DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` STRIP_ASSUME_TAC) THEN
13422       EXISTS_TAC `(v:real^N) INSERT b` THEN
13423       ASM_REWRITE_TAC[FORALL_IN_INSERT] THEN
13424       CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
13425       ASM_REWRITE_TAC[PAIRWISE_INSERT] THEN
13426       RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE; SUBSET; IN_ELIM_THM]) THEN
13427       CONJ_TAC THENL
13428        [ASM_SIMP_TAC[HAS_SIZE; FINITE_INSERT; CARD_CLAUSES] THEN
13429         COND_CASES_TAC THEN ASM_REWRITE_TAC[ADD1] THEN
13430         ASM_MESON_TAC[ORTHOGONAL_REFL];
13431         RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; IN_ELIM_THM]) THEN
13432         ASM_MESON_TAC[ORTHOGONAL_SYM]]]) in
13433   REPEAT STRIP_TAC THEN
13434   MP_TAC(ISPECL [`f:real^N->real^N`; `s:real^N->bool`] lemma) THEN
13435   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN
13436   X_GEN_TAC `b:real^N->bool` THEN
13437   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
13438   MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
13439    [MATCH_MP_TAC PAIRWISE_ORTHOGONAL_INDEPENDENT THEN
13440     ASM_MESON_TAC[NORM_ARITH `~(norm(vec 0:real^N) = &1)`];
13441     DISCH_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
13442      [ASM_MESON_TAC[SPAN_SUBSET_SUBSPACE];
13443       MATCH_MP_TAC CARD_GE_DIM_INDEPENDENT THEN
13444       RULE_ASSUM_TAC(REWRITE_RULE[HAS_SIZE]) THEN
13445       ASM_REWRITE_TAC[LE_REFL]]]);;
13446
13447 let SELF_ADJOINT_HAS_EIGENVECTOR_BASIS = prove
13448  (`!f:real^N->real^N.
13449         linear f /\ adjoint f = f
13450         ==> ?b. pairwise orthogonal b /\
13451                 (!x. x IN b ==> norm x = &1 /\ ?c. f(x) = c % x) /\
13452                 independent b /\
13453                 span b = (:real^N) /\
13454                 b HAS_SIZE (dimindex(:N))`,
13455   REPEAT STRIP_TAC THEN
13456   MP_TAC(ISPECL [`f:real^N->real^N`; `(:real^N)`]
13457         SELF_ADJOINT_HAS_EIGENVECTOR_BASIS_OF_SUBSPACE) THEN
13458   ASM_REWRITE_TAC[SUBSPACE_UNIV; IN_UNIV; DIM_UNIV; SUBSET_UNIV]);;
13459
13460 (* ------------------------------------------------------------------------- *)
13461 (* Diagonalization of symmetric matrix.                                      *)
13462 (* ------------------------------------------------------------------------- *)
13463
13464 let SYMMETRIC_MATRIX_DIAGONALIZABLE_EXPLICIT = prove
13465  (`!A:real^N^N.
13466     transp A = A
13467     ==> ?P d. orthogonal_matrix P /\
13468               transp P ** A ** P = (lambda i j. if i = j then d i else &0)`,
13469   let lemma1 = prove
13470    (`!A:real^N^N P:real^N^N d.
13471        A ** P = P ** (lambda i j. if i = j then d i else &0) <=>
13472        !i. 1 <= i /\ i <= dimindex(:N)
13473            ==> A ** column i P = d i % column i P`,
13474     SIMP_TAC[CART_EQ; matrix_mul; matrix_vector_mul; LAMBDA_BETA;
13475              column; VECTOR_MUL_COMPONENT] THEN
13476     REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[COND_RAND] THEN
13477     SIMP_TAC[REAL_MUL_RZERO; SUM_DELTA; IN_NUMSEG] THEN
13478     EQ_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[] THEN
13479     REWRITE_TAC[REAL_MUL_SYM]) in
13480   let lemma2 = prove
13481    (`!A:real^N^N P:real^N^N d.
13482           orthogonal_matrix P /\
13483           transp P ** A ** P = (lambda i j. if i = j then d i else &0) <=>
13484           orthogonal_matrix P /\
13485           !i. 1 <= i /\ i <= dimindex(:N)
13486               ==> A ** column i P = d i % column i P`,
13487     REPEAT GEN_TAC THEN REWRITE_TAC[GSYM lemma1; orthogonal_matrix] THEN
13488     ABBREV_TAC `D:real^N^N = lambda i j. if i = j then d i else &0` THEN
13489     MESON_TAC[MATRIX_MUL_ASSOC; MATRIX_MUL_LID]) in
13490   REPEAT STRIP_TAC THEN
13491   REWRITE_TAC[lemma2] THEN REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN
13492   REWRITE_TAC[GSYM SKOLEM_THM] THEN
13493   MP_TAC(ISPEC `\x:real^N. (A:real^N^N) ** x`
13494     SELF_ADJOINT_HAS_EIGENVECTOR_BASIS) THEN
13495   ASM_SIMP_TAC[MATRIX_SELF_ADJOINT; MATRIX_VECTOR_MUL_LINEAR;
13496                MATRIX_OF_MATRIX_VECTOR_MUL] THEN
13497   DISCH_THEN(X_CHOOSE_THEN `b:real^N->bool` MP_TAC) THEN
13498   REWRITE_TAC[CONJ_ASSOC] THEN ONCE_REWRITE_TAC[IMP_CONJ_ALT] THEN
13499   REWRITE_TAC[HAS_SIZE] THEN STRIP_TAC THEN
13500   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [FINITE_INDEX_NUMSEG]) THEN
13501   ASM_REWRITE_TAC[IN_NUMSEG; TAUT
13502    `p /\ q /\ x = y ==> a = b <=> p /\ q /\ ~(a = b) ==> ~(x = y)`] THEN
13503   DISCH_THEN(X_CHOOSE_THEN `f:num->real^N` STRIP_ASSUME_TAC) THEN
13504   ASM_REWRITE_TAC[PAIRWISE_IMAGE; FORALL_IN_IMAGE] THEN
13505   ASM_SIMP_TAC[pairwise; IN_NUMSEG] THEN STRIP_TAC THEN
13506   EXISTS_TAC `transp(lambda i. f i):real^N^N` THEN
13507   SIMP_TAC[COLUMN_TRANSP; ORTHOGONAL_MATRIX_TRANSP] THEN
13508   SIMP_TAC[ORTHOGONAL_MATRIX_ORTHONORMAL_ROWS_INDEXED; row] THEN
13509   SIMP_TAC[LAMBDA_ETA; LAMBDA_BETA; pairwise; IN_NUMSEG] THEN
13510   ASM_MESON_TAC[]);;
13511
13512 let SYMMETRIC_MATRIX_IMP_DIAGONALIZABLE = prove
13513  (`!A:real^N^N.
13514      transp A = A
13515      ==> ?P. orthogonal_matrix P /\ diagonal_matrix(transp P ** A ** P)`,
13516   GEN_TAC THEN
13517   DISCH_THEN(MP_TAC o MATCH_MP SYMMETRIC_MATRIX_DIAGONALIZABLE_EXPLICIT) THEN
13518   MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
13519   SIMP_TAC[diagonal_matrix; LAMBDA_BETA]);;
13520
13521 let SYMMETRIC_MATRIX_EQ_DIAGONALIZABLE = prove
13522  (`!A:real^N^N.
13523      transp A = A <=>
13524      ?P. orthogonal_matrix P /\ diagonal_matrix(transp P ** A ** P)`,
13525   GEN_TAC THEN EQ_TAC THEN
13526   REWRITE_TAC[SYMMETRIC_MATRIX_IMP_DIAGONALIZABLE] THEN
13527   REWRITE_TAC[orthogonal_matrix] THEN
13528   DISCH_THEN(X_CHOOSE_THEN `P:real^N^N` STRIP_ASSUME_TAC) THEN
13529   ABBREV_TAC `D:real^N^N = transp P ** (A:real^N^N) ** P` THEN
13530   SUBGOAL_THEN `A:real^N^N = P ** (D:real^N^N) ** transp P` SUBST1_TAC THENL
13531    [EXPAND_TAC "D" THEN REWRITE_TAC[MATRIX_MUL_ASSOC] THEN
13532     ASM_REWRITE_TAC[MATRIX_MUL_LID] THEN
13533     ASM_REWRITE_TAC[GSYM MATRIX_MUL_ASSOC; MATRIX_MUL_RID];
13534     REWRITE_TAC[MATRIX_TRANSP_MUL; TRANSP_TRANSP; MATRIX_MUL_ASSOC] THEN
13535     ASM_MESON_TAC[TRANSP_DIAGONAL_MATRIX]]);;
13536
13537 (* ------------------------------------------------------------------------- *)
13538 (* Some matrix identities are easier to deduce for invertible matrices. We   *)
13539 (* can then extend by continuity, which is why this material needs to be     *)
13540 (* here after basic topological notions have been defined.                   *)
13541 (* ------------------------------------------------------------------------- *)
13542
13543 let CONTINUOUS_LIFT_DET = prove
13544  (`!(A:A->real^N^N) net.
13545         (!i j. 1 <= i /\ i <= dimindex(:N) /\
13546                1 <= j /\ j <= dimindex(:N)
13547                ==> (\x. lift(A x$i$j)) continuous net)
13548         ==> (\x. lift(det(A x))) continuous net`,
13549   REPEAT STRIP_TAC THEN REWRITE_TAC[det] THEN
13550   SIMP_TAC[LIFT_SUM; FINITE_PERMUTATIONS; FINITE_NUMSEG; o_DEF] THEN
13551   MATCH_MP_TAC CONTINUOUS_VSUM THEN
13552   SIMP_TAC[FINITE_PERMUTATIONS; FINITE_NUMSEG; LIFT_CMUL; IN_ELIM_THM] THEN
13553   X_GEN_TAC `p:num->num` THEN DISCH_TAC THEN
13554   MATCH_MP_TAC CONTINUOUS_CMUL THEN
13555   MATCH_MP_TAC CONTINUOUS_LIFT_PRODUCT THEN
13556   REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
13557   REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
13558   FIRST_ASSUM(MP_TAC o MATCH_MP PERMUTES_IMAGE) THEN
13559   DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE `s = t ==> s SUBSET t`)) THEN
13560   ASM_SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_NUMSEG]);;
13561
13562 let CONTINUOUS_ON_LIFT_DET = prove
13563  (`!A:real^M->real^N^N s.
13564         (!i j. 1 <= i /\ i <= dimindex(:N) /\
13565                1 <= j /\ j <= dimindex(:N)
13566                ==> (\x. lift(A x$i$j)) continuous_on s)
13567         ==> (\x. lift(det(A x))) continuous_on s`,
13568   SIMP_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN; CONTINUOUS_LIFT_DET]);;
13569
13570 let NEARBY_INVERTIBLE_MATRIX = prove
13571  (`!A:real^N^N.
13572      ?e. &0 < e /\ !x. ~(x = &0) /\ abs x < e ==> invertible(A + x %% mat 1)`,
13573   GEN_TAC THEN MP_TAC(ISPEC `A:real^N^N` CHARACTERISTIC_POLYNOMIAL) THEN
13574   DISCH_THEN(X_CHOOSE_THEN `a:num->real` STRIP_ASSUME_TAC) THEN
13575   MP_TAC(ISPECL [`dimindex(:N)`; `a:num->real`] REAL_POLYFUN_FINITE_ROOTS) THEN
13576   MATCH_MP_TAC(TAUT `q /\ (p ==> r) ==> (p <=> q) ==> r`) THEN CONJ_TAC THENL
13577    [EXISTS_TAC `dimindex(:N)` THEN ASM_REWRITE_TAC[IN_NUMSEG] THEN ARITH_TAC;
13578     ALL_TAC] THEN
13579   DISCH_THEN(MP_TAC o ISPEC `lift` o MATCH_MP FINITE_IMAGE) THEN
13580   DISCH_THEN(MP_TAC o MATCH_MP LIMIT_POINT_FINITE) THEN
13581   DISCH_THEN(MP_TAC o SPEC `lift(&0)`) THEN
13582   REWRITE_TAC[LIMPT_APPROACHABLE; EXISTS_IN_IMAGE; EXISTS_IN_GSPEC] THEN
13583   REWRITE_TAC[DIST_LIFT; LIFT_EQ; REAL_SUB_RZERO; NOT_FORALL_THM; NOT_IMP] THEN
13584   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN
13585   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[NOT_EXISTS_THM] THEN
13586   DISCH_THEN(fun th -> X_GEN_TAC `x:real` THEN STRIP_TAC THEN
13587                 MP_TAC(SPEC `--x:real` th)) THEN
13588   FIRST_X_ASSUM(SUBST1_TAC o SYM o SPEC `--x:real`) THEN
13589   ASM_REWRITE_TAC[REAL_NEG_EQ_0; REAL_ABS_NEG] THEN
13590   ONCE_REWRITE_TAC[GSYM INVERTIBLE_NEG] THEN
13591   REWRITE_TAC[INVERTIBLE_DET_NZ; CONTRAPOS_THM] THEN
13592   REWRITE_TAC[MATRIX_SUB; MATRIX_NEG_MINUS1] THEN
13593   ONCE_REWRITE_TAC[REAL_ARITH `--x = -- &1 * x`] THEN
13594   REWRITE_TAC[GSYM MATRIX_CMUL_ADD_LDISTRIB; GSYM MATRIX_CMUL_ASSOC] THEN
13595   REWRITE_TAC[MATRIX_CMUL_LID; MATRIX_ADD_SYM]);;
13596
13597 let MATRIX_WLOG_INVERTIBLE = prove
13598  (`!P. (!A:real^N^N. invertible A ==> P A) /\
13599        (!A:real^N^N. ?d. &0 < d /\
13600                          closed {x | x IN cball(vec 0,d) /\
13601                                      P(A + drop x %% mat 1)})
13602        ==> !A:real^N^N. P A`,
13603   REPEAT GEN_TAC THEN
13604   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
13605   MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
13606   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
13607   FIRST_ASSUM(MP_TAC o SPEC `vec 0:real^1` o
13608     GEN_REWRITE_RULE I [CLOSED_LIMPT]) THEN
13609   ASM_SIMP_TAC[IN_ELIM_THM; DROP_VEC; MATRIX_CMUL_LZERO; MATRIX_ADD_RID] THEN
13610   ANTS_TAC THENL [ALL_TAC; CONV_TAC TAUT] THEN
13611   MP_TAC(ISPEC `A:real^N^N` NEARBY_INVERTIBLE_MATRIX) THEN
13612   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
13613   REWRITE_TAC[LIMPT_APPROACHABLE] THEN X_GEN_TAC `k:real` THEN
13614   DISCH_TAC THEN REWRITE_TAC[EXISTS_LIFT; IN_ELIM_THM] THEN
13615   REWRITE_TAC[GSYM LIFT_NUM; IN_CBALL_0; NORM_LIFT; DIST_LIFT] THEN
13616   REWRITE_TAC[REAL_SUB_RZERO; LIFT_EQ; LIFT_DROP] THEN
13617   EXISTS_TAC `min d ((min e k) / &2)` THEN
13618   CONJ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
13619   CONJ_TAC THENL [ASM_REAL_ARITH_TAC; FIRST_X_ASSUM MATCH_MP_TAC] THEN
13620   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REAL_ARITH_TAC);;
13621
13622 let SYLVESTER_DETERMINANT_IDENTITY = prove
13623  (`!A:real^N^M B:real^M^N. det(mat 1 + A ** B) = det(mat 1 + B ** A)`,
13624   let lemma1 = prove
13625    (`!A:real^N^N B:real^N^N. det(mat 1 + A ** B) = det(mat 1 + B ** A)`,
13626     ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN GEN_TAC THEN
13627     MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN CONJ_TAC THENL
13628      [REPEAT STRIP_TAC THEN
13629       SUBGOAL_THEN `det((mat 1 + A ** B) ** A:real^N^N) =
13630                     det(A ** (mat 1 + B ** A))`
13631       MP_TAC THENL
13632        [REWRITE_TAC[MATRIX_ADD_RDISTRIB; MATRIX_ADD_LDISTRIB] THEN
13633         REWRITE_TAC[MATRIX_MUL_LID; MATRIX_MUL_RID; MATRIX_MUL_ASSOC];
13634         REWRITE_TAC[DET_MUL] THEN
13635         FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INVERTIBLE_DET_NZ]) THEN
13636         CONV_TAC REAL_RING];
13637       X_GEN_TAC `A:real^N^N` THEN EXISTS_TAC `&1` THEN
13638       REWRITE_TAC[REAL_LT_01; SET_RULE
13639        `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
13640       MATCH_MP_TAC CLOSED_INTER THEN REWRITE_TAC[CLOSED_CBALL] THEN
13641       ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN
13642       REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM] THEN
13643       REWRITE_TAC[SET_RULE `{x | f x = a} = {x | f x IN {a}}`] THEN
13644       MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
13645       REWRITE_TAC[CLOSED_SING; LIFT_SUB] THEN X_GEN_TAC `x:real^1` THEN
13646       REWRITE_TAC[o_DEF; LIFT_SUB] THEN MATCH_MP_TAC CONTINUOUS_SUB THEN
13647       CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN
13648       MAP_EVERY X_GEN_TAC [`i:num`; `j:num`] THEN STRIP_TAC THEN
13649       ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; LIFT_ADD] THEN
13650       MATCH_MP_TAC CONTINUOUS_ADD THEN
13651       ASM_SIMP_TAC[matrix_mul; LAMBDA_BETA; CONTINUOUS_CONST] THEN
13652       SIMP_TAC[LIFT_SUM; FINITE_NUMSEG; o_DEF] THEN
13653       MATCH_MP_TAC CONTINUOUS_VSUM THEN
13654       REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN X_GEN_TAC `k:num` THEN
13655       DISCH_TAC THENL [ONCE_REWRITE_TAC[REAL_MUL_SYM]; ALL_TAC] THEN
13656       REWRITE_TAC[LIFT_CMUL] THEN MATCH_MP_TAC CONTINUOUS_CMUL THEN
13657       REWRITE_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT; LIFT_ADD] THEN
13658       MATCH_MP_TAC CONTINUOUS_ADD THEN REWRITE_TAC[CONTINUOUS_CONST] THEN
13659       REWRITE_TAC[ONCE_REWRITE_RULE[REAL_MUL_SYM] LIFT_CMUL] THEN
13660       MATCH_MP_TAC CONTINUOUS_CMUL THEN
13661       REWRITE_TAC[LIFT_DROP; CONTINUOUS_AT_ID]]) in
13662   let lemma2 = prove
13663    (`!A:real^N^M B:real^M^N.
13664           dimindex(:M) <= dimindex(:N)
13665           ==> det(mat 1 + A ** B) = det(mat 1 + B ** A)`,
13666     REPEAT STRIP_TAC THEN
13667     MAP_EVERY ABBREV_TAC
13668      [`A':real^N^N =
13669           lambda i j. if i <= dimindex(:M) then (A:real^N^M)$i$j
13670                       else &0`;
13671       `B':real^N^N =
13672           lambda i j. if j <= dimindex(:M) then (B:real^M^N)$i$j
13673                       else &0`] THEN
13674     MP_TAC(ISPECL [`A':real^N^N`; `B':real^N^N`] lemma1) THEN
13675     SUBGOAL_THEN
13676      `(B':real^N^N) ** (A':real^N^N) = (B:real^M^N) ** (A:real^N^M)`
13677     SUBST1_TAC THENL
13678      [MAP_EVERY EXPAND_TAC ["A'"; "B'"] THEN
13679       SIMP_TAC[CART_EQ; LAMBDA_BETA; matrix_mul] THEN REPEAT STRIP_TAC THEN
13680       MATCH_MP_TAC SUM_EQ_SUPERSET THEN
13681       ASM_SIMP_TAC[IN_NUMSEG; REAL_MUL_LZERO; FINITE_NUMSEG; SUBSET_NUMSEG;
13682                    LE_REFL; TAUT `(p /\ q) /\ ~(p /\ r) <=> p /\ q /\ ~r`];
13683       DISCH_THEN(SUBST1_TAC o SYM)] THEN
13684     REWRITE_TAC[det] THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC
13685      `sum {p | p permutes 1..dimindex(:N) /\ !i. dimindex(:M) < i ==> p i = i}
13686           (\p. sign p * product (1..dimindex(:N))
13687                      (\i. (mat 1 + (A':real^N^N) ** (B':real^N^N))$i$p i))` THEN
13688     CONJ_TAC THENL
13689      [ALL_TAC;
13690       CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_SUPERSET THEN
13691       CONJ_TAC THENL [SET_TAC[]; SIMP_TAC[IN_ELIM_THM; IMP_CONJ]] THEN
13692       X_GEN_TAC `p:num->num` THEN REPEAT STRIP_TAC THEN
13693       REWRITE_TAC[REAL_ENTIRE; PRODUCT_EQ_0_NUMSEG] THEN DISJ2_TAC THEN
13694       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_FORALL_THM]) THEN
13695       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `k:num` THEN
13696       REWRITE_TAC[NOT_IMP] THEN STRIP_TAC THEN
13697       FIRST_ASSUM(MP_TAC o SPEC `k:num` o CONJUNCT1 o
13698         GEN_REWRITE_RULE I [permutes]) THEN
13699       ASM_REWRITE_TAC[IN_NUMSEG] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
13700       FIRST_ASSUM(MP_TAC o MATCH_MP PERMUTES_IMAGE) THEN
13701       DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE `s = t ==> s SUBSET t`)) THEN
13702       ASM_SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_NUMSEG] THEN
13703       DISCH_THEN(MP_TAC o SPEC `k:num`) THEN ASM_SIMP_TAC[] THEN STRIP_TAC THEN
13704       ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MAT_COMPONENT; REAL_ADD_LID] THEN
13705       ASM_SIMP_TAC[matrix_mul; LAMBDA_BETA] THEN
13706       MATCH_MP_TAC SUM_EQ_0_NUMSEG THEN REPEAT STRIP_TAC THEN
13707       REWRITE_TAC[REAL_ENTIRE] THEN DISJ1_TAC THEN EXPAND_TAC "A'" THEN
13708       ASM_SIMP_TAC[LAMBDA_BETA; GSYM NOT_LT]] THEN
13709     CONV_TAC SYM_CONV THEN MATCH_MP_TAC SUM_EQ_GENERAL THEN
13710     EXISTS_TAC `\f:num->num. f` THEN REWRITE_TAC[IN_ELIM_THM] THEN
13711     CONJ_TAC THEN X_GEN_TAC `p:num->num` THEN STRIP_TAC THENL
13712      [REWRITE_TAC[MESON[] `(?!x. P x /\ x = y) <=> P y`] THEN CONJ_TAC THENL
13713        [MATCH_MP_TAC PERMUTES_SUBSET THEN
13714         EXISTS_TAC `1..dimindex(:M)` THEN
13715         ASM_REWRITE_TAC[SUBSET_NUMSEG; LE_REFL];
13716         X_GEN_TAC `k:num` THEN DISCH_TAC THEN
13717         FIRST_X_ASSUM(MATCH_MP_TAC o CONJUNCT1 o
13718           GEN_REWRITE_RULE I [permutes]) THEN
13719         ASM_REWRITE_TAC[IN_NUMSEG; DE_MORGAN_THM; NOT_LE]];
13720       MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
13721        [MATCH_MP_TAC PERMUTES_SUPERSET THEN
13722         EXISTS_TAC `1..dimindex(:N)` THEN
13723         ASM_REWRITE_TAC[IN_DIFF; IN_NUMSEG] THEN ASM_MESON_TAC[NOT_LE];
13724         DISCH_TAC] THEN
13725       AP_TERM_TAC THEN FIRST_ASSUM(SUBST1_TAC o MATCH_MP (ARITH_RULE
13726        `m:num <= n ==> n = m + (n - m)`)) THEN
13727       SIMP_TAC[PRODUCT_ADD_SPLIT; ARITH_RULE `1 <= n + 1`] THEN
13728       MATCH_MP_TAC(REAL_RING `x = y /\ z = &1 ==> x = y * z`) THEN
13729       CONJ_TAC THENL
13730        [MATCH_MP_TAC PRODUCT_EQ_NUMSEG THEN
13731         X_GEN_TAC `i:num` THEN STRIP_TAC THEN
13732         SUBGOAL_THEN `i <= dimindex(:N)` ASSUME_TAC THENL
13733          [ASM_ARITH_TAC; ALL_TAC] THEN
13734         MP_TAC(ISPECL [`p:num->num`; `1..dimindex(:M)`] PERMUTES_IMAGE) THEN
13735         ASM_REWRITE_TAC[] THEN
13736         DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE `s = t ==> s SUBSET t`)) THEN
13737         ASM_SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_NUMSEG] THEN
13738         DISCH_THEN(MP_TAC o SPEC `i:num`) THEN
13739         ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
13740         SUBGOAL_THEN `(p:num->num) i <= dimindex(:N)` ASSUME_TAC THENL
13741          [ASM_ARITH_TAC; ALL_TAC] THEN
13742         ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MAT_COMPONENT] THEN
13743         AP_TERM_TAC THEN ASM_SIMP_TAC[matrix_mul; LAMBDA_BETA] THEN
13744         MATCH_MP_TAC SUM_EQ_NUMSEG THEN REPEAT STRIP_TAC THEN
13745         MAP_EVERY EXPAND_TAC ["A'"; "B'"] THEN
13746         ASM_SIMP_TAC[LAMBDA_BETA];
13747         MATCH_MP_TAC PRODUCT_EQ_1_NUMSEG THEN
13748         ASM_SIMP_TAC[ARITH_RULE `n + 1 <= i ==> n < i`] THEN
13749         ASM_SIMP_TAC[ARITH_RULE `m:num <= n ==> m + (n - m) = n`] THEN
13750         X_GEN_TAC `i:num` THEN STRIP_TAC THEN
13751         SUBGOAL_THEN `1 <= i` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
13752         ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MAT_COMPONENT] THEN
13753         ASM_SIMP_TAC[REAL_EQ_ADD_LCANCEL_0; matrix_mul; LAMBDA_BETA] THEN
13754         MATCH_MP_TAC SUM_EQ_0_NUMSEG THEN REPEAT STRIP_TAC THEN
13755         REWRITE_TAC[REAL_ENTIRE] THEN DISJ1_TAC THEN EXPAND_TAC "A'" THEN
13756         ASM_SIMP_TAC[LAMBDA_BETA; ARITH_RULE `m + 1 <= i ==> ~(i <= m)`]]]) in
13757   REPEAT GEN_TAC THEN DISJ_CASES_TAC (ARITH_RULE
13758    `dimindex(:M) <= dimindex(:N) \/ dimindex(:N) <= dimindex(:M)`)
13759   THENL [ALL_TAC; CONV_TAC SYM_CONV] THEN
13760   MATCH_MP_TAC lemma2 THEN ASM_REWRITE_TAC[]);;
13761
13762 let COFACTOR_MATRIX_MUL = prove
13763  (`!A B:real^N^N. cofactor(A ** B) = cofactor(A) ** cofactor(B)`,
13764   MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN CONJ_TAC THENL
13765    [GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN
13766     CONJ_TAC THENL
13767      [ASM_SIMP_TAC[COFACTOR_MATRIX_INV; GSYM INVERTIBLE_DET_NZ;
13768                    INVERTIBLE_MATRIX_MUL] THEN
13769       REWRITE_TAC[DET_MUL; MATRIX_MUL_LMUL] THEN
13770       REWRITE_TAC[MATRIX_MUL_RMUL; MATRIX_CMUL_ASSOC;
13771                   GSYM MATRIX_TRANSP_MUL] THEN
13772       ASM_SIMP_TAC[MATRIX_INV_MUL];
13773       GEN_TAC THEN EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01]];
13774     X_GEN_TAC `A:real^N^N` THEN EXISTS_TAC `&1` THEN
13775     REWRITE_TAC[REAL_LT_01] THEN REWRITE_TAC[RIGHT_AND_FORALL_THM] THEN
13776     MATCH_MP_TAC CLOSED_FORALL THEN GEN_TAC] THEN
13777   REWRITE_TAC[SET_RULE
13778    `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
13779   MATCH_MP_TAC CLOSED_INTER THEN REWRITE_TAC[CLOSED_CBALL] THEN
13780   REWRITE_TAC[CART_EQ] THEN
13781   MATCH_MP_TAC CLOSED_FORALL_IN THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
13782   MATCH_MP_TAC CLOSED_FORALL_IN THEN X_GEN_TAC `j:num` THEN STRIP_TAC THEN
13783   ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN
13784   REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM] THEN
13785   REWRITE_TAC[SET_RULE `{x | f x = a} = {x | f x IN {a}}`] THEN
13786   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
13787   REWRITE_TAC[CLOSED_SING; LIFT_SUB] THEN X_GEN_TAC `x:real^1` THEN
13788   ASM_SIMP_TAC[matrix_mul; LAMBDA_BETA; cofactor; LIFT_SUM;
13789                FINITE_NUMSEG; o_DEF] THEN
13790   (MATCH_MP_TAC CONTINUOUS_SUB THEN CONJ_TAC THENL
13791     [ALL_TAC;
13792      MATCH_MP_TAC CONTINUOUS_VSUM THEN
13793      REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
13794      X_GEN_TAC `k:num` THEN STRIP_TAC THEN
13795      REWRITE_TAC[LIFT_CMUL] THEN MATCH_MP_TAC CONTINUOUS_MUL THEN
13796      REWRITE_TAC[o_DEF] THEN CONJ_TAC]) THEN
13797   MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN
13798   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
13799   ASM_SIMP_TAC[LAMBDA_BETA; CONTINUOUS_CONST] THEN
13800   REPEAT(W(fun (asl,w) ->
13801    let t = find_term is_cond w in
13802    ASM_CASES_TAC (lhand(rator t)) THEN ASM_REWRITE_TAC[CONTINUOUS_CONST])) THEN
13803   SIMP_TAC[LIFT_SUM; FINITE_NUMSEG; o_DEF] THEN
13804   TRY(MATCH_MP_TAC CONTINUOUS_VSUM THEN REWRITE_TAC[FINITE_NUMSEG] THEN
13805       REWRITE_TAC[IN_NUMSEG] THEN X_GEN_TAC `p:num` THEN STRIP_TAC) THEN
13806   REWRITE_TAC[LIFT_CMUL] THEN
13807   TRY(MATCH_MP_TAC CONTINUOUS_MUL THEN
13808       REWRITE_TAC[o_DEF; CONTINUOUS_CONST]) THEN
13809   REWRITE_TAC[MATRIX_ADD_COMPONENT; LIFT_ADD] THEN
13810   MATCH_MP_TAC CONTINUOUS_ADD THEN REWRITE_TAC[CONTINUOUS_CONST] THEN
13811   REWRITE_TAC[MATRIX_CMUL_COMPONENT; LIFT_CMUL; o_DEF] THEN
13812   MATCH_MP_TAC CONTINUOUS_MUL THEN
13813   REWRITE_TAC[CONTINUOUS_CONST; o_DEF; LIFT_DROP; CONTINUOUS_AT_ID]);;
13814
13815 let DET_COFACTOR = prove
13816  (`!A:real^N^N. det(cofactor A) = det(A) pow (dimindex(:N) - 1)`,
13817   MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN CONJ_TAC THEN
13818   X_GEN_TAC `A:real^N^N` THENL
13819    [REWRITE_TAC[INVERTIBLE_DET_NZ] THEN STRIP_TAC THEN
13820     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_FIELD
13821      `~(a = &0) ==> a * x = a * y ==> x = y`)) THEN
13822     GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM DET_TRANSP] THEN
13823     REWRITE_TAC[GSYM DET_MUL; MATRIX_MUL_RIGHT_COFACTOR] THEN
13824     REWRITE_TAC[DET_CMUL; GSYM(CONJUNCT2 real_pow); DET_I; REAL_MUL_RID] THEN
13825     SIMP_TAC[DIMINDEX_GE_1; ARITH_RULE `1 <= n ==> SUC(n - 1) = n`];
13826     ALL_TAC] THEN
13827   EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN
13828   REWRITE_TAC[SET_RULE
13829    `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
13830   MATCH_MP_TAC CLOSED_INTER THEN REWRITE_TAC[CLOSED_CBALL] THEN
13831   ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN
13832   REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM] THEN
13833   REWRITE_TAC[SET_RULE `{x | f x = a} = {x | f x IN {a}}`] THEN
13834   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
13835   REWRITE_TAC[CLOSED_SING; LIFT_SUB] THEN X_GEN_TAC `x:real^1` THEN
13836   MATCH_MP_TAC CONTINUOUS_SUB THEN
13837   CONJ_TAC THENL [ALL_TAC; MATCH_MP_TAC CONTINUOUS_LIFT_POW] THEN
13838   MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN
13839   MAP_EVERY X_GEN_TAC [`i:num`; `j:num`] THEN STRIP_TAC THEN
13840   ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT; LIFT_ADD;
13841                LIFT_CMUL; LIFT_DROP; CONTINUOUS_ADD; CONTINUOUS_CONST;
13842                CONTINUOUS_MUL; o_DEF; LIFT_DROP; CONTINUOUS_AT_ID] THEN
13843   ASM_SIMP_TAC[cofactor; LAMBDA_BETA] THEN
13844   MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN
13845   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
13846   ASM_SIMP_TAC[LAMBDA_BETA] THEN
13847   REPEAT(W(fun (asl,w) ->
13848    let t = find_term is_cond w in
13849    ASM_CASES_TAC (lhand(rator t)) THEN ASM_REWRITE_TAC[CONTINUOUS_CONST])) THEN
13850   ASM_SIMP_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT; LIFT_ADD;
13851                LIFT_CMUL; LIFT_DROP; CONTINUOUS_ADD; CONTINUOUS_CONST;
13852                CONTINUOUS_MUL; o_DEF; LIFT_DROP; CONTINUOUS_AT_ID]);;
13853
13854 let INVERTIBLE_COFACTOR = prove
13855  (`!A:real^N^N. invertible(cofactor A) <=> dimindex(:N) = 1 \/ invertible A`,
13856   SIMP_TAC[DET_COFACTOR; INVERTIBLE_DET_NZ; REAL_POW_EQ_0; DE_MORGAN_THM;
13857            DIMINDEX_GE_1; ARITH_RULE `1 <= n ==> (n - 1 = 0 <=> n = 1)`;
13858            DISJ_ACI]);;
13859
13860 let COFACTOR_COFACTOR = prove
13861  (`!A:real^N^N.
13862      2 <= dimindex(:N)
13863      ==> cofactor(cofactor A) = (det(A) pow (dimindex(:N) - 2)) %% A`,
13864   REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
13865   MATCH_MP_TAC MATRIX_WLOG_INVERTIBLE THEN CONJ_TAC THEN
13866   X_GEN_TAC `A:real^N^N` THENL
13867    [REWRITE_TAC[INVERTIBLE_DET_NZ] THEN DISCH_TAC THEN
13868     MP_TAC(ISPECL [`A:real^N^N`; `transp(cofactor A):real^N^N`]
13869         COFACTOR_MATRIX_MUL) THEN
13870     REWRITE_TAC[MATRIX_MUL_RIGHT_COFACTOR; COFACTOR_CMUL; COFACTOR_I] THEN
13871     REWRITE_TAC[COFACTOR_TRANSP] THEN
13872     DISCH_THEN(MP_TAC o AP_TERM `transp:real^N^N->real^N^N`) THEN
13873     REWRITE_TAC[MATRIX_TRANSP_MUL; TRANSP_TRANSP; TRANSP_MATRIX_CMUL] THEN
13874     REWRITE_TAC[TRANSP_MAT] THEN
13875     DISCH_THEN(MP_TAC o AP_TERM `(\x. x ** A):real^N^N->real^N^N`) THEN
13876     REWRITE_TAC[GSYM MATRIX_MUL_ASSOC; MATRIX_MUL_LEFT_COFACTOR] THEN
13877     REWRITE_TAC[MATRIX_MUL_LMUL; MATRIX_MUL_RMUL] THEN
13878     REWRITE_TAC[MATRIX_MUL_LID; MATRIX_MUL_RID] THEN
13879     DISCH_THEN(MP_TAC o AP_TERM `\x:real^N^N. inv(det(A:real^N^N)) %% x`) THEN
13880     ASM_SIMP_TAC[MATRIX_CMUL_ASSOC; REAL_MUL_LINV; MATRIX_CMUL_LID] THEN
13881     DISCH_THEN(SUBST1_TAC o SYM) THEN AP_THM_TAC THEN AP_TERM_TAC THEN
13882     ASM_SIMP_TAC[REAL_POW_SUB; ARITH_RULE `2 <= n ==> 1 <= n`] THEN
13883     REWRITE_TAC[REAL_POW_2; real_div; REAL_INV_POW] THEN REAL_ARITH_TAC;
13884     POP_ASSUM(K ALL_TAC)] THEN
13885   EXISTS_TAC `&1` THEN REWRITE_TAC[REAL_LT_01] THEN
13886   REWRITE_TAC[SET_RULE
13887    `{x | x IN s /\ P x} = s INTER {x | P x}`] THEN
13888   MATCH_MP_TAC CLOSED_INTER THEN REWRITE_TAC[CLOSED_CBALL] THEN
13889   REWRITE_TAC[CART_EQ] THEN
13890   MATCH_MP_TAC CLOSED_FORALL_IN THEN X_GEN_TAC `i:num` THEN STRIP_TAC THEN
13891   MATCH_MP_TAC CLOSED_FORALL_IN THEN X_GEN_TAC `j:num` THEN STRIP_TAC THEN
13892   ONCE_REWRITE_TAC[GSYM REAL_SUB_0] THEN
13893   REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM] THEN
13894   REWRITE_TAC[SET_RULE `{x | f x = a} = {x | f x IN {a}}`] THEN
13895   MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN
13896   REWRITE_TAC[CLOSED_SING; LIFT_SUB] THEN X_GEN_TAC `x:real^1` THEN
13897   MATCH_MP_TAC CONTINUOUS_SUB THEN CONJ_TAC THENL
13898    [REPLICATE_TAC 2
13899      (ONCE_REWRITE_TAC[cofactor] THEN ASM_SIMP_TAC[LAMBDA_BETA] THEN
13900       MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN REPEAT STRIP_TAC THEN
13901       ASM_SIMP_TAC[LAMBDA_BETA] THEN
13902       REPEAT(W(fun (asl,w) ->
13903        let t = find_term is_cond w in
13904        ASM_CASES_TAC (lhand(rator t)) THEN
13905        ASM_REWRITE_TAC[CONTINUOUS_CONST])));
13906     REWRITE_TAC[MATRIX_CMUL_COMPONENT; LIFT_CMUL] THEN
13907     MATCH_MP_TAC CONTINUOUS_MUL THEN REWRITE_TAC[o_DEF] THEN CONJ_TAC THENL
13908      [MATCH_MP_TAC CONTINUOUS_LIFT_POW THEN
13909       MATCH_MP_TAC CONTINUOUS_LIFT_DET THEN REPEAT STRIP_TAC;
13910       ALL_TAC]] THEN
13911   REWRITE_TAC[MATRIX_ADD_COMPONENT; MATRIX_CMUL_COMPONENT] THEN
13912   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
13913   REWRITE_TAC[LIFT_ADD; LIFT_CMUL; LIFT_DROP] THEN
13914   SIMP_TAC[CONTINUOUS_ADD; CONTINUOUS_CONST; CONTINUOUS_CMUL;
13915            CONTINUOUS_AT_ID]);;
13916
13917 (* ------------------------------------------------------------------------- *)
13918 (* Infinite sums of vectors. Allow general starting point (and more).        *)
13919 (* ------------------------------------------------------------------------- *)
13920
13921 parse_as_infix("sums",(12,"right"));;
13922
13923 let sums = new_definition
13924   `(f sums l) s = ((\n. vsum(s INTER (0..n)) f) --> l) sequentially`;;
13925
13926 let infsum = new_definition
13927  `infsum s f = @l. (f sums l) s`;;
13928
13929 let summable = new_definition
13930  `summable s f = ?l. (f sums l) s`;;
13931
13932 let SUMS_SUMMABLE = prove
13933  (`!f l s. (f sums l) s ==> summable s f`,
13934   REWRITE_TAC[summable] THEN MESON_TAC[]);;
13935
13936 let SUMS_INFSUM = prove
13937  (`!f s. (f sums (infsum s f)) s <=> summable s f`,
13938   REWRITE_TAC[infsum; summable] THEN MESON_TAC[]);;
13939
13940 let SUMS_LIM = prove
13941  (`!f:num->real^N s.
13942       (f sums lim sequentially (\n. vsum (s INTER (0..n)) f)) s
13943       <=> summable s f`,
13944   GEN_TAC THEN GEN_TAC THEN EQ_TAC THENL [MESON_TAC[summable];
13945   REWRITE_TAC[summable; sums] THEN STRIP_TAC THEN REWRITE_TAC[lim] THEN
13946   ASM_MESON_TAC[]]);;
13947
13948 let FINITE_INTER_NUMSEG = prove
13949  (`!s m n. FINITE(s INTER (m..n))`,
13950   MESON_TAC[FINITE_SUBSET; FINITE_NUMSEG; INTER_SUBSET]);;
13951
13952 let SERIES_FROM = prove
13953  (`!f l k. (f sums l) (from k) = ((\n. vsum(k..n) f) --> l) sequentially`,
13954   REPEAT GEN_TAC THEN REWRITE_TAC[sums] THEN
13955   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN
13956   AP_THM_TAC THEN AP_TERM_TAC THEN
13957   REWRITE_TAC[EXTENSION; numseg; from; IN_ELIM_THM; IN_INTER] THEN ARITH_TAC);;
13958
13959 let SERIES_UNIQUE = prove
13960  (`!f:num->real^N l l' s. (f sums l) s /\ (f sums l') s ==> (l = l')`,
13961   REWRITE_TAC[sums] THEN MESON_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; LIM_UNIQUE]);;
13962
13963 let INFSUM_UNIQUE = prove
13964  (`!f:num->real^N l s. (f sums l) s ==> infsum s f = l`,
13965   MESON_TAC[SERIES_UNIQUE; SUMS_INFSUM; summable]);;
13966
13967 let SERIES_FINITE = prove
13968  (`!f s. FINITE s ==> (f sums (vsum s f)) s`,
13969   REPEAT GEN_TAC THEN REWRITE_TAC[num_FINITE; LEFT_IMP_EXISTS_THM] THEN
13970   X_GEN_TAC `n:num` THEN REWRITE_TAC[sums; LIM_SEQUENTIALLY] THEN
13971   DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN EXISTS_TAC `n:num` THEN
13972   X_GEN_TAC `m:num` THEN DISCH_TAC THEN
13973   SUBGOAL_THEN `s INTER (0..m) = s`
13974    (fun th -> ASM_REWRITE_TAC[th; DIST_REFL]) THEN
13975   REWRITE_TAC[EXTENSION; IN_INTER; IN_NUMSEG; LE_0] THEN
13976   ASM_MESON_TAC[LE_TRANS]);;
13977
13978 let SERIES_LINEAR = prove
13979  (`!f h l s. (f sums l) s /\ linear h ==> ((\n. h(f n)) sums h l) s`,
13980   SIMP_TAC[sums; LIM_LINEAR; FINITE_INTER; FINITE_NUMSEG;
13981            GSYM(REWRITE_RULE[o_DEF] LINEAR_VSUM)]);;
13982
13983 let SERIES_0 = prove
13984  (`!s. ((\n. vec 0) sums (vec 0)) s`,
13985   REWRITE_TAC[sums; VSUM_0; LIM_CONST]);;
13986
13987 let SERIES_ADD = prove
13988  (`!x x0 y y0 s.
13989      (x sums x0) s /\ (y sums y0) s ==> ((\n. x n + y n) sums (x0 + y0)) s`,
13990   SIMP_TAC[sums; FINITE_INTER_NUMSEG; VSUM_ADD; LIM_ADD]);;
13991
13992 let SERIES_SUB = prove
13993  (`!x x0 y y0 s.
13994      (x sums x0) s /\ (y sums y0) s ==> ((\n. x n - y n) sums (x0 - y0)) s`,
13995   SIMP_TAC[sums; FINITE_INTER_NUMSEG; VSUM_SUB; LIM_SUB]);;
13996
13997 let SERIES_CMUL = prove
13998  (`!x x0 c s. (x sums x0) s ==> ((\n. c % x n) sums (c % x0)) s`,
13999   SIMP_TAC[sums; FINITE_INTER_NUMSEG; VSUM_LMUL; LIM_CMUL]);;
14000
14001 let SERIES_NEG = prove
14002  (`!x x0 s. (x sums x0) s ==> ((\n. --(x n)) sums (--x0)) s`,
14003   SIMP_TAC[sums; FINITE_INTER_NUMSEG; VSUM_NEG; LIM_NEG]);;
14004
14005 let SUMS_IFF = prove
14006  (`!f g k. (!x. x IN k ==> f x = g x) ==> ((f sums l) k <=> (g sums l) k)`,
14007   REPEAT STRIP_TAC THEN REWRITE_TAC[sums] THEN
14008   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN
14009   MATCH_MP_TAC VSUM_EQ THEN ASM_SIMP_TAC[IN_INTER]);;
14010
14011 let SUMS_EQ = prove
14012  (`!f g k. (!x. x IN k ==> f x = g x) /\ (f sums l) k ==> (g sums l) k`,
14013   MESON_TAC[SUMS_IFF]);;
14014
14015 let SUMS_0 = prove
14016  (`!f:num->real^N s. (!n. n IN s ==> f n = vec 0) ==> (f sums vec 0) s`,
14017   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUMS_EQ THEN
14018   EXISTS_TAC `\n:num. vec 0:real^N` THEN ASM_SIMP_TAC[SERIES_0]);;
14019
14020 let SERIES_FINITE_SUPPORT = prove
14021  (`!f:num->real^N s k.
14022      FINITE (s INTER k) /\ (!x. ~(x IN s INTER k) ==> f x = vec 0)
14023      ==> (f sums vsum (s INTER k) f) k`,
14024   REWRITE_TAC[sums; LIM_SEQUENTIALLY] THEN REPEAT STRIP_TAC THEN
14025   FIRST_ASSUM(MP_TAC o ISPEC `\x:num. x` o MATCH_MP UPPER_BOUND_FINITE_SET) THEN
14026   REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
14027   STRIP_TAC THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
14028   SUBGOAL_THEN `vsum (k INTER (0..n)) (f:num->real^N) = vsum(s INTER k) f`
14029    (fun th -> ASM_REWRITE_TAC[DIST_REFL; th]) THEN
14030   MATCH_MP_TAC VSUM_SUPERSET THEN
14031   ASM_SIMP_TAC[SUBSET; IN_INTER; IN_NUMSEG; LE_0] THEN
14032   ASM_MESON_TAC[IN_INTER; LE_TRANS]);;
14033
14034 let SERIES_COMPONENT = prove
14035  (`!f s l:real^N k. (f sums l) s /\ 1 <= k /\ k <= dimindex(:N)
14036                     ==> ((\i. lift(f(i)$k)) sums lift(l$k)) s`,
14037   REPEAT GEN_TAC THEN REWRITE_TAC[sums] THEN STRIP_TAC THEN
14038   ONCE_REWRITE_TAC[GSYM o_DEF] THEN
14039   ASM_SIMP_TAC[GSYM LIFT_SUM; GSYM VSUM_COMPONENT;
14040                FINITE_INTER; FINITE_NUMSEG] THEN
14041   ASM_SIMP_TAC[o_DEF; LIM_COMPONENT]);;
14042
14043 let SERIES_DIFFS = prove
14044  (`!f:num->real^N k.
14045         (f --> vec 0) sequentially
14046         ==> ((\n. f(n) - f(n + 1)) sums f(k)) (from k)`,
14047   REWRITE_TAC[sums; FROM_INTER_NUMSEG; VSUM_DIFFS] THEN
14048   REPEAT STRIP_TAC THEN MATCH_MP_TAC LIM_TRANSFORM_EVENTUALLY THEN
14049   EXISTS_TAC `\n. (f:num->real^N) k - f(n + 1)` THEN CONJ_TAC THENL
14050    [REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN EXISTS_TAC `k:num` THEN
14051     SIMP_TAC[];
14052     GEN_REWRITE_TAC LAND_CONV [GSYM VECTOR_SUB_RZERO] THEN
14053     MATCH_MP_TAC LIM_SUB THEN REWRITE_TAC[LIM_CONST] THEN
14054     MATCH_MP_TAC SEQ_OFFSET THEN ASM_REWRITE_TAC[]]);;
14055
14056 let SERIES_TRIVIAL = prove
14057  (`!f. (f sums vec 0) {}`,
14058   REWRITE_TAC[sums; INTER_EMPTY; VSUM_CLAUSES; LIM_CONST]);;
14059
14060 let SERIES_RESTRICT = prove
14061  (`!f k l:real^N.
14062         ((\n. if n IN k then f(n) else vec 0) sums l) (:num) <=>
14063         (f sums l) k`,
14064   REPEAT GEN_TAC THEN REWRITE_TAC[sums] THEN
14065   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
14066   REWRITE_TAC[FUN_EQ_THM; INTER_UNIV] THEN GEN_TAC THEN
14067   MATCH_MP_TAC(MESON[] `vsum s f = vsum t f /\ vsum t f = vsum t g
14068                         ==> vsum s f = vsum t g`) THEN
14069   CONJ_TAC THENL
14070    [MATCH_MP_TAC VSUM_SUPERSET THEN SET_TAC[];
14071     MATCH_MP_TAC VSUM_EQ THEN SIMP_TAC[IN_INTER]]);;
14072
14073 let SERIES_VSUM = prove
14074  (`!f l k s. FINITE s /\ s SUBSET k /\ (!x. ~(x IN s) ==> f x = vec 0) /\
14075              vsum s f = l ==> (f sums l) k`,
14076   REPEAT STRIP_TAC THEN EXPAND_TAC "l" THEN
14077   SUBGOAL_THEN `s INTER k = s:num->bool` ASSUME_TAC THENL
14078    [ASM SET_TAC []; ASM_MESON_TAC [SERIES_FINITE_SUPPORT]]);;
14079
14080 let SUMS_REINDEX = prove
14081  (`!k a l n. ((\x. a(x + k)) sums l) (from n) <=> (a sums l) (from(n + k))`,
14082   REPEAT GEN_TAC THEN REWRITE_TAC[sums; FROM_INTER_NUMSEG] THEN
14083   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM VSUM_OFFSET] THEN
14084   REWRITE_TAC[LIM_SEQUENTIALLY] THEN
14085   ASM_MESON_TAC[ARITH_RULE `N + k:num <= n ==> n = (n - k) + k /\ N <= n - k`;
14086                 ARITH_RULE `N + k:num <= n ==> N <= n + k`]);;
14087
14088 (* ------------------------------------------------------------------------- *)
14089 (* Similar combining theorems just for summability.                          *)
14090 (* ------------------------------------------------------------------------- *)
14091
14092 let SUMMABLE_LINEAR = prove
14093  (`!f h s. summable s f /\ linear h ==> summable s (\n. h(f n))`,
14094   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_LINEAR]);;
14095
14096 let SUMMABLE_0 = prove
14097  (`!s. summable s (\n. vec 0)`,
14098   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_0]);;
14099
14100 let SUMMABLE_ADD = prove
14101  (`!x y s. summable s x /\ summable s y ==> summable s (\n. x n + y n)`,
14102   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_ADD]);;
14103
14104 let SUMMABLE_SUB = prove
14105  (`!x y s. summable s x /\ summable s y ==> summable s (\n. x n - y n)`,
14106   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_SUB]);;
14107
14108 let SUMMABLE_CMUL = prove
14109  (`!s x c. summable s x ==> summable s (\n. c % x n)`,
14110   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_CMUL]);;
14111
14112 let SUMMABLE_NEG = prove
14113  (`!x s. summable s x ==> summable s (\n. --(x n))`,
14114   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_NEG]);;
14115
14116 let SUMMABLE_IFF = prove
14117  (`!f g k. (!x. x IN k ==> f x = g x) ==> (summable k f <=> summable k g)`,
14118   REWRITE_TAC[summable] THEN MESON_TAC[SUMS_IFF]);;
14119
14120 let SUMMABLE_EQ = prove
14121  (`!f g k. (!x. x IN k ==> f x = g x) /\ summable k f ==> summable k g`,
14122   REWRITE_TAC[summable] THEN MESON_TAC[SUMS_EQ]);;
14123
14124 let SUMMABLE_COMPONENT = prove
14125  (`!f:num->real^N s k.
14126         summable s f /\ 1 <= k /\ k <= dimindex(:N)
14127         ==> summable s (\i. lift(f(i)$k))`,
14128   REPEAT STRIP_TAC THEN
14129   FIRST_X_ASSUM(X_CHOOSE_TAC `l:real^N` o REWRITE_RULE[summable]) THEN
14130   REWRITE_TAC[summable] THEN EXISTS_TAC `lift((l:real^N)$k)` THEN
14131   ASM_SIMP_TAC[SERIES_COMPONENT]);;
14132
14133 let SERIES_SUBSET = prove
14134  (`!x s t l.
14135         s SUBSET t /\
14136         ((\i. if i IN s then x i else vec 0) sums l) t
14137         ==> (x sums l) s`,
14138   REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
14139   REWRITE_TAC[sums] THEN MATCH_MP_TAC EQ_IMP THEN
14140   AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN
14141   ASM_SIMP_TAC[GSYM VSUM_RESTRICT_SET; FINITE_INTER_NUMSEG] THEN
14142   AP_THM_TAC THEN AP_TERM_TAC THEN POP_ASSUM MP_TAC THEN SET_TAC[]);;
14143
14144 let SUMMABLE_SUBSET = prove
14145  (`!x s t.
14146         s SUBSET t /\
14147         summable t (\i. if i IN s then x i else vec 0)
14148         ==> summable s x`,
14149   REWRITE_TAC[summable] THEN MESON_TAC[SERIES_SUBSET]);;
14150
14151 let SUMMABLE_TRIVIAL = prove
14152  (`!f:num->real^N. summable {} f`,
14153   GEN_TAC THEN REWRITE_TAC[summable] THEN EXISTS_TAC `vec 0:real^N` THEN
14154   REWRITE_TAC[SERIES_TRIVIAL]);;
14155
14156 let SUMMABLE_RESTRICT = prove
14157  (`!f:num->real^N k.
14158         summable (:num) (\n. if n IN k then f(n) else vec 0) <=>
14159         summable k f`,
14160   REWRITE_TAC[summable; SERIES_RESTRICT]);;
14161
14162 let SUMS_FINITE_DIFF = prove
14163  (`!f:num->real^N t s l.
14164         t SUBSET s /\ FINITE t /\ (f sums l) s
14165         ==> (f sums (l - vsum t f)) (s DIFF t)`,
14166   REPEAT GEN_TAC THEN
14167   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
14168   FIRST_ASSUM(MP_TAC o ISPEC `f:num->real^N` o MATCH_MP SERIES_FINITE) THEN
14169   ONCE_REWRITE_TAC[GSYM SERIES_RESTRICT] THEN
14170   REWRITE_TAC[IMP_IMP] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
14171   DISCH_THEN(MP_TAC o MATCH_MP SERIES_SUB) THEN
14172   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
14173   REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `x:num` THEN REWRITE_TAC[IN_DIFF] THEN
14174   FIRST_ASSUM(MP_TAC o SPEC `x:num` o GEN_REWRITE_RULE I [SUBSET]) THEN
14175   MAP_EVERY ASM_CASES_TAC [`(x:num) IN s`; `(x:num) IN t`] THEN
14176   ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC);;
14177
14178 let SUMS_FINITE_UNION = prove
14179  (`!f:num->real^N s t l.
14180         FINITE t /\ (f sums l) s
14181         ==> (f sums (l + vsum (t DIFF s) f)) (s UNION t)`,
14182   REPEAT GEN_TAC THEN
14183   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
14184   FIRST_ASSUM(MP_TAC o SPEC `s:num->bool` o MATCH_MP FINITE_DIFF) THEN
14185   DISCH_THEN(MP_TAC o ISPEC `f:num->real^N` o MATCH_MP SERIES_FINITE) THEN
14186   ONCE_REWRITE_TAC[GSYM SERIES_RESTRICT] THEN
14187   REWRITE_TAC[IMP_IMP] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
14188   DISCH_THEN(MP_TAC o MATCH_MP SERIES_ADD) THEN
14189   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
14190   REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `x:num` THEN
14191   REWRITE_TAC[IN_DIFF; IN_UNION] THEN
14192   MAP_EVERY ASM_CASES_TAC [`(x:num) IN s`; `(x:num) IN t`] THEN
14193   ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC);;
14194
14195 let SUMS_OFFSET = prove
14196  (`!f:num->real^N l m n.
14197         (f sums l) (from m) /\ m < n
14198         ==> (f sums (l - vsum(m..(n-1)) f)) (from n)`,
14199   REPEAT STRIP_TAC THEN
14200   SUBGOAL_THEN `from n = from m DIFF (m..(n-1))` SUBST1_TAC THENL
14201    [REWRITE_TAC[EXTENSION; IN_FROM; IN_DIFF; IN_NUMSEG] THEN ASM_ARITH_TAC;
14202     MATCH_MP_TAC SUMS_FINITE_DIFF THEN ASM_REWRITE_TAC[FINITE_NUMSEG] THEN
14203     SIMP_TAC[SUBSET; IN_FROM; IN_NUMSEG]]);;
14204
14205 let SUMS_OFFSET_REV = prove
14206  (`!f:num->real^N l m n.
14207         (f sums l) (from m) /\ n < m
14208         ==> (f sums (l + vsum(n..m-1) f)) (from n)`,
14209   REPEAT STRIP_TAC THEN
14210   MP_TAC(ISPECL [`f:num->real^N`; `from m`; `n..m-1`; `l:real^N`]
14211                 SUMS_FINITE_UNION) THEN
14212   ASM_REWRITE_TAC[FINITE_NUMSEG] THEN MATCH_MP_TAC EQ_IMP THEN
14213   BINOP_TAC THENL [AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC; ALL_TAC] THEN
14214   REWRITE_TAC[EXTENSION; IN_DIFF; IN_UNION; IN_FROM; IN_NUMSEG] THEN
14215   ASM_ARITH_TAC);;
14216
14217 let SUMMABLE_REINDEX = prove
14218  (`!k a n. summable (from n) (\x. a (x + k)) <=> summable (from(n + k)) a`,
14219   REWRITE_TAC[summable; GSYM SUMS_REINDEX]);;
14220
14221 (* ------------------------------------------------------------------------- *)
14222 (* Similar combining theorems for infsum.                                    *)
14223 (* ------------------------------------------------------------------------- *)
14224
14225 let INFSUM_LINEAR = prove
14226  (`!f h s. summable s f /\ linear h
14227            ==> infsum s (\n. h(f n)) = h(infsum s f)`,
14228   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
14229   MATCH_MP_TAC SERIES_LINEAR THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
14230
14231 let INFSUM_0 = prove
14232  (`infsum s (\i. vec 0) = vec 0`,
14233   MATCH_MP_TAC INFSUM_UNIQUE THEN REWRITE_TAC[SERIES_0]);;
14234
14235 let INFSUM_ADD = prove
14236  (`!x y s. summable s x /\ summable s y
14237            ==> infsum s (\i. x i + y i) = infsum s x + infsum s y`,
14238   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
14239   MATCH_MP_TAC SERIES_ADD THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
14240
14241 let INFSUM_SUB = prove
14242  (`!x y s. summable s x /\ summable s y
14243            ==> infsum s (\i. x i - y i) = infsum s x - infsum s y`,
14244   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
14245   MATCH_MP_TAC SERIES_SUB THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
14246
14247 let INFSUM_CMUL = prove
14248  (`!s x c. summable s x ==> infsum s (\n. c % x n) = c % infsum s x`,
14249   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
14250   MATCH_MP_TAC SERIES_CMUL THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
14251
14252 let INFSUM_NEG = prove
14253  (`!s x. summable s x ==> infsum s (\n. --(x n)) = --(infsum s x)`,
14254   REPEAT STRIP_TAC THEN MATCH_MP_TAC INFSUM_UNIQUE THEN
14255   MATCH_MP_TAC SERIES_NEG THEN ASM_REWRITE_TAC[SUMS_INFSUM]);;
14256
14257 let INFSUM_EQ = prove
14258  (`!f g k. summable k f /\ summable k g /\ (!x. x IN k ==> f x = g x)
14259            ==> infsum k f = infsum k g`,
14260   REPEAT STRIP_TAC THEN REWRITE_TAC[infsum] THEN
14261   AP_TERM_TAC THEN ABS_TAC THEN ASM_MESON_TAC[SUMS_EQ; SUMS_INFSUM]);;
14262
14263 let INFSUM_RESTRICT = prove
14264  (`!k a:num->real^N.
14265         infsum (:num) (\n. if n IN k then a n else vec 0) = infsum k a`,
14266   REPEAT GEN_TAC THEN
14267   MP_TAC(ISPECL [`a:num->real^N`; `k:num->bool`] SUMMABLE_RESTRICT) THEN
14268   ASM_CASES_TAC `summable k (a:num->real^N)` THEN ASM_REWRITE_TAC[] THEN
14269   STRIP_TAC THENL
14270    [MATCH_MP_TAC INFSUM_UNIQUE THEN
14271     ASM_REWRITE_TAC[SERIES_RESTRICT; SUMS_INFSUM];
14272     RULE_ASSUM_TAC(REWRITE_RULE[summable; NOT_EXISTS_THM]) THEN
14273     ASM_REWRITE_TAC[infsum]]);;
14274
14275 let PARTIAL_SUMS_COMPONENT_LE_INFSUM = prove
14276  (`!f:num->real^N s k n.
14277         1 <= k /\ k <= dimindex(:N) /\
14278         (!i. i IN s ==> &0 <= (f i)$k) /\
14279         summable s f
14280         ==> (vsum (s INTER (0..n)) f)$k <= (infsum s f)$k`,
14281   REPEAT GEN_TAC THEN REWRITE_TAC[GSYM SUMS_INFSUM] THEN
14282   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
14283   REWRITE_TAC[sums; LIM_SEQUENTIALLY] THEN DISCH_TAC THEN
14284   REWRITE_TAC[GSYM REAL_NOT_LT] THEN DISCH_TAC THEN
14285   FIRST_X_ASSUM(MP_TAC o SPEC
14286    `vsum (s INTER (0..n)) (f:num->real^N)$k - (infsum s f)$k`) THEN
14287   ASM_REWRITE_TAC[REAL_SUB_LT] THEN
14288   DISCH_THEN(X_CHOOSE_THEN `N:num` (MP_TAC o SPEC `N + n:num`)) THEN
14289   REWRITE_TAC[LE_ADD; REAL_NOT_LT; dist] THEN
14290   MATCH_MP_TAC REAL_LE_TRANS THEN
14291   EXISTS_TAC `abs((vsum (s INTER (0..N + n)) f - infsum s f:real^N)$k)` THEN
14292   ASM_SIMP_TAC[COMPONENT_LE_NORM] THEN REWRITE_TAC[VECTOR_SUB_COMPONENT] THEN
14293   MATCH_MP_TAC(REAL_ARITH `s < a /\ a <= b ==> a - s <= abs(b - s)`) THEN
14294   ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[ADD_SYM] THEN
14295   SIMP_TAC[NUMSEG_ADD_SPLIT; LE_0; UNION_OVER_INTER] THEN
14296   W(MP_TAC o PART_MATCH (lhs o rand) VSUM_UNION o lhand o rand o snd) THEN
14297   ANTS_TAC THENL
14298    [SIMP_TAC[FINITE_INTER; FINITE_NUMSEG; DISJOINT; EXTENSION] THEN
14299     REWRITE_TAC[IN_INTER; NOT_IN_EMPTY; IN_NUMSEG] THEN ARITH_TAC;
14300     DISCH_THEN SUBST1_TAC THEN
14301     REWRITE_TAC[REAL_LE_ADDR; VECTOR_ADD_COMPONENT] THEN
14302     ASM_SIMP_TAC[VSUM_COMPONENT] THEN MATCH_MP_TAC SUM_POS_LE THEN
14303     ASM_SIMP_TAC[FINITE_INTER; IN_INTER; FINITE_NUMSEG]]);;
14304
14305 let PARTIAL_SUMS_DROP_LE_INFSUM = prove
14306  (`!f s n.
14307         (!i. i IN s ==> &0 <= drop(f i)) /\
14308         summable s f
14309         ==> drop(vsum (s INTER (0..n)) f) <= drop(infsum s f)`,
14310   REPEAT STRIP_TAC THEN REWRITE_TAC[drop] THEN
14311   MATCH_MP_TAC PARTIAL_SUMS_COMPONENT_LE_INFSUM THEN
14312   ASM_REWRITE_TAC[DIMINDEX_1; LE_REFL; GSYM drop]);;
14313
14314 (* ------------------------------------------------------------------------- *)
14315 (* Cauchy criterion for series.                                              *)
14316 (* ------------------------------------------------------------------------- *)
14317
14318 let SEQUENCE_CAUCHY_WLOG = prove
14319  (`!P s. (!m n:num. P m /\ P n ==> dist(s m,s n) < e) <=>
14320          (!m n. P m /\ P n /\ m <= n ==> dist(s m,s n) < e)`,
14321   MESON_TAC[DIST_SYM; LE_CASES]);;
14322
14323 let VSUM_DIFF_LEMMA = prove
14324  (`!f:num->real^N k m n.
14325         m <= n
14326         ==> vsum(k INTER (0..n)) f - vsum(k INTER (0..m)) f =
14327             vsum(k INTER (m+1..n)) f`,
14328   REPEAT STRIP_TAC THEN
14329   MP_TAC(ISPECL [`f:num->real^N`; `k INTER (0..n)`; `k INTER (0..m)`]
14330     VSUM_DIFF) THEN
14331   ANTS_TAC THENL
14332    [SIMP_TAC[FINITE_INTER; FINITE_NUMSEG] THEN MATCH_MP_TAC
14333      (SET_RULE `s SUBSET t ==> (u INTER s SUBSET u INTER t)`) THEN
14334     REWRITE_TAC[SUBSET; IN_NUMSEG] THEN POP_ASSUM MP_TAC THEN ARITH_TAC;
14335     DISCH_THEN(SUBST1_TAC o SYM) THEN AP_THM_TAC THEN AP_TERM_TAC THEN
14336     REWRITE_TAC[SET_RULE
14337      `(k INTER s) DIFF (k INTER t) = k INTER (s DIFF t)`] THEN
14338     AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_DIFF; IN_NUMSEG] THEN
14339     POP_ASSUM MP_TAC THEN ARITH_TAC]);;
14340
14341 let NORM_VSUM_TRIVIAL_LEMMA = prove
14342  (`!e. &0 < e ==> (P ==> norm(vsum(s INTER (m..n)) f) < e <=>
14343                    P ==> n < m \/ norm(vsum(s INTER (m..n)) f) < e)`,
14344   REPEAT STRIP_TAC THEN ASM_CASES_TAC `n:num < m` THEN ASM_REWRITE_TAC[] THEN
14345   FIRST_X_ASSUM(SUBST1_TAC o GEN_REWRITE_RULE I [GSYM NUMSEG_EMPTY]) THEN
14346   ASM_REWRITE_TAC[VSUM_CLAUSES; NORM_0; INTER_EMPTY]);;
14347
14348 let SERIES_CAUCHY = prove
14349  (`!f s. (?l. (f sums l) s) =
14350          !e. &0 < e
14351              ==> ?N. !m n. m >= N
14352                            ==> norm(vsum(s INTER (m..n)) f) < e`,
14353   REPEAT GEN_TAC THEN REWRITE_TAC[sums; CONVERGENT_EQ_CAUCHY; cauchy] THEN
14354   REWRITE_TAC[SEQUENCE_CAUCHY_WLOG] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
14355   SIMP_TAC[dist; VSUM_DIFF_LEMMA; NORM_VSUM_TRIVIAL_LEMMA] THEN
14356   REWRITE_TAC[GE; TAUT `a ==> b \/ c <=> a /\ ~b ==> c`] THEN
14357   REWRITE_TAC[NOT_LT; ARITH_RULE
14358    `(N <= m /\ N <= n /\ m <= n) /\ m + 1 <= n <=>
14359     N + 1 <= m + 1 /\ m + 1 <= n`] THEN
14360   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN
14361   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
14362   EQ_TAC THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THENL
14363    [EXISTS_TAC `N + 1`; EXISTS_TAC `N:num`] THEN
14364   REPEAT STRIP_TAC THEN
14365   ASM_SIMP_TAC[ARITH_RULE `N + 1 <= m + 1 ==> N <= m + 1`] THEN
14366   FIRST_X_ASSUM(MP_TAC o SPECL [`m - 1`; `n:num`]) THEN
14367   SUBGOAL_THEN `m - 1 + 1 = m` SUBST_ALL_TAC THENL
14368    [ALL_TAC; ANTS_TAC THEN SIMP_TAC[]] THEN
14369   ASM_ARITH_TAC);;
14370
14371 let SUMMABLE_CAUCHY = prove
14372  (`!f s. summable s f <=>
14373          !e. &0 < e
14374              ==> ?N. !m n. m >= N ==> norm(vsum(s INTER (m..n)) f) < e`,
14375   REWRITE_TAC[summable; GSYM SERIES_CAUCHY]);;
14376
14377 let SUMMABLE_IFF_EVENTUALLY = prove
14378  (`!f g k. (?N. !n. N <= n /\ n IN k ==> f n = g n)
14379            ==> (summable k f <=> summable k g)`,
14380   REWRITE_TAC[summable; SERIES_CAUCHY] THEN REPEAT GEN_TAC THEN
14381   DISCH_THEN(X_CHOOSE_THEN `N0:num` STRIP_ASSUME_TAC) THEN
14382   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN
14383   AP_TERM_TAC THEN EQ_TAC THEN
14384   DISCH_THEN(X_CHOOSE_THEN `N1:num`
14385    (fun th -> EXISTS_TAC `N0 + N1:num` THEN MP_TAC th)) THEN
14386   REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
14387   DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
14388   (ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC]) THEN
14389   MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
14390   MATCH_MP_TAC VSUM_EQ THEN ASM_SIMP_TAC[IN_INTER; IN_NUMSEG] THEN
14391   REPEAT STRIP_TAC THENL [ALL_TAC; CONV_TAC SYM_CONV] THEN
14392   FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
14393   ASM_ARITH_TAC);;
14394
14395 let SUMMABLE_EQ_EVENTUALLY = prove
14396  (`!f g k. (?N. !n. N <= n /\ n IN k ==> f n = g n) /\ summable k f
14397            ==> summable k g`,
14398   MESON_TAC[SUMMABLE_IFF_EVENTUALLY]);;
14399
14400 let SUMMABLE_IFF_COFINITE = prove
14401  (`!f s t. FINITE((s DIFF t) UNION (t DIFF s))
14402            ==> (summable s f <=> summable t f)`,
14403   REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[GSYM SUMMABLE_RESTRICT] THEN
14404   MATCH_MP_TAC SUMMABLE_IFF_EVENTUALLY THEN
14405   FIRST_ASSUM(MP_TAC o ISPEC `\x:num.x` o MATCH_MP UPPER_BOUND_FINITE_SET) THEN
14406   DISCH_THEN(X_CHOOSE_THEN `N:num` MP_TAC) THEN REWRITE_TAC[IN_UNIV] THEN
14407   DISCH_TAC THEN EXISTS_TAC `N + 1` THEN
14408   REWRITE_TAC[ARITH_RULE `N + 1 <= n <=> ~(n <= N)`] THEN ASM SET_TAC[]);;
14409
14410 let SUMMABLE_EQ_COFINITE = prove
14411  (`!f s t. FINITE((s DIFF t) UNION (t DIFF s)) /\ summable s f
14412            ==> summable t f`,
14413   MESON_TAC[SUMMABLE_IFF_COFINITE]);;
14414
14415 let SUMMABLE_FROM_ELSEWHERE = prove
14416  (`!f m n. summable (from m) f ==> summable (from n) f`,
14417   REPEAT GEN_TAC THEN
14418   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] SUMMABLE_EQ_COFINITE) THEN
14419   MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `0..(m+n)` THEN
14420   SIMP_TAC[FINITE_NUMSEG; SUBSET; IN_NUMSEG; IN_UNION; IN_DIFF; IN_FROM] THEN
14421   ARITH_TAC);;
14422
14423 (* ------------------------------------------------------------------------- *)
14424 (* Uniform vesion of Cauchy criterion.                                       *)
14425 (* ------------------------------------------------------------------------- *)
14426
14427 let SERIES_CAUCHY_UNIFORM = prove
14428  (`!P f:A->num->real^N k.
14429         (?l. !e. &0 < e
14430                  ==> ?N. !n x. N <= n /\ P x
14431                                ==> dist(vsum(k INTER (0..n)) (f x),
14432                                         l x) < e) <=>
14433         (!e. &0 < e ==> ?N. !m n x. N <= m /\ P x
14434                                     ==> norm(vsum(k INTER (m..n)) (f x)) < e)`,
14435   REPEAT GEN_TAC THEN
14436   REWRITE_TAC[sums; UNIFORMLY_CONVERGENT_EQ_CAUCHY; cauchy] THEN
14437   ONCE_REWRITE_TAC[MESON[]
14438    `(!m n:num y. N <= m /\ N <= n /\ P y ==> Q m n y) <=>
14439     (!y. P y ==> !m n. N <= m /\ N <= n ==> Q m n y)`] THEN
14440   REWRITE_TAC[SEQUENCE_CAUCHY_WLOG] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN
14441   SIMP_TAC[dist; VSUM_DIFF_LEMMA; NORM_VSUM_TRIVIAL_LEMMA] THEN
14442   REWRITE_TAC[GE; TAUT `a ==> b \/ c <=> a /\ ~b ==> c`] THEN
14443   REWRITE_TAC[NOT_LT; ARITH_RULE
14444    `(N <= m /\ N <= n /\ m <= n) /\ m + 1 <= n <=>
14445     N + 1 <= m + 1 /\ m + 1 <= n`] THEN
14446   AP_TERM_TAC THEN REWRITE_TAC[FUN_EQ_THM] THEN X_GEN_TAC `e:real` THEN
14447   ASM_CASES_TAC `&0 < e` THEN ASM_REWRITE_TAC[] THEN
14448   EQ_TAC THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THENL
14449    [EXISTS_TAC `N + 1`; EXISTS_TAC `N:num`] THEN
14450   REPEAT STRIP_TAC THEN
14451   ASM_SIMP_TAC[ARITH_RULE `N + 1 <= m + 1 ==> N <= m + 1`] THEN
14452   FIRST_X_ASSUM(MP_TAC o SPEC `x:A`) THEN ASM_REWRITE_TAC[] THEN
14453   DISCH_THEN(MP_TAC o SPECL [`m - 1`; `n:num`]) THEN
14454   SUBGOAL_THEN `m - 1 + 1 = m` SUBST_ALL_TAC THENL
14455    [ALL_TAC; ANTS_TAC THEN SIMP_TAC[]] THEN
14456   ASM_ARITH_TAC);;
14457
14458 (* ------------------------------------------------------------------------- *)
14459 (* So trivially, terms of a convergent series go to zero.                    *)
14460 (* ------------------------------------------------------------------------- *)
14461
14462 let SERIES_GOESTOZERO = prove
14463  (`!s x. summable s x
14464          ==> !e. &0 < e
14465                  ==> eventually (\n. n IN s ==> norm(x n) < e) sequentially`,
14466   REPEAT GEN_TAC THEN REWRITE_TAC[summable; SERIES_CAUCHY] THEN
14467   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
14468   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
14469   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN DISCH_TAC THEN
14470   X_GEN_TAC `n:num` THEN REPEAT STRIP_TAC THEN
14471   FIRST_X_ASSUM(MP_TAC o SPECL [`n:num`; `n:num`]) THEN
14472   ASM_SIMP_TAC[NUMSEG_SING; GE; SET_RULE `n IN s ==> s INTER {n} = {n}`] THEN
14473   REWRITE_TAC[VSUM_SING]);;
14474
14475 let SUMMABLE_IMP_TOZERO = prove
14476  (`!f:num->real^N k.
14477        summable k f
14478        ==> ((\n. if n IN k then f(n) else vec 0) --> vec 0) sequentially`,
14479   REPEAT GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM SUMMABLE_RESTRICT] THEN
14480   REWRITE_TAC[summable; LIM_SEQUENTIALLY; INTER_UNIV; sums] THEN
14481   DISCH_THEN(X_CHOOSE_TAC `l:real^N`) THEN X_GEN_TAC `e:real` THEN
14482   DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e / &2`) THEN
14483   ASM_REWRITE_TAC[REAL_HALF; LEFT_IMP_EXISTS_THM] THEN
14484   X_GEN_TAC `N:num` THEN DISCH_TAC THEN EXISTS_TAC `N + 1` THEN
14485   X_GEN_TAC `n:num` THEN DISCH_TAC THEN
14486   FIRST_X_ASSUM(fun th ->
14487     MP_TAC(SPEC `n - 1` th) THEN MP_TAC(SPEC `n:num` th)) THEN
14488   ASM_SIMP_TAC[ARITH_RULE `N + 1 <= n ==> N <= n /\ N <= n - 1`] THEN
14489   ABBREV_TAC `m = n - 1` THEN
14490   SUBGOAL_THEN `n = SUC m` SUBST1_TAC THENL
14491    [ASM_ARITH_TAC; ALL_TAC] THEN
14492   REWRITE_TAC[VSUM_CLAUSES_NUMSEG; LE_0] THEN
14493   REWRITE_TAC[NORM_ARITH `dist(x,vec 0) = norm x`] THEN
14494   COND_CASES_TAC THEN ASM_REWRITE_TAC[NORM_0] THEN CONV_TAC NORM_ARITH);;
14495
14496 let SUMMABLE_IMP_BOUNDED = prove
14497  (`!f:num->real^N k. summable k f ==> bounded (IMAGE f k)`,
14498   REPEAT GEN_TAC THEN
14499   DISCH_THEN(MP_TAC o MATCH_MP SUMMABLE_IMP_TOZERO) THEN
14500   DISCH_THEN(MP_TAC o MATCH_MP CONVERGENT_IMP_BOUNDED) THEN
14501   REWRITE_TAC[BOUNDED_POS; FORALL_IN_IMAGE; IN_UNIV] THEN
14502   MATCH_MP_TAC MONO_EXISTS THEN MESON_TAC[REAL_LT_IMP_LE; NORM_0]);;
14503
14504 let SUMMABLE_IMP_SUMS_BOUNDED = prove
14505  (`!f:num->real^N k.
14506        summable (from k) f ==> bounded { vsum(k..n) f | n IN (:num) }`,
14507   REWRITE_TAC[summable; sums; LEFT_IMP_EXISTS_THM] THEN REPEAT GEN_TAC THEN
14508   DISCH_THEN(MP_TAC o MATCH_MP CONVERGENT_IMP_BOUNDED) THEN
14509   REWRITE_TAC[FROM_INTER_NUMSEG; SIMPLE_IMAGE]);;
14510
14511 (* ------------------------------------------------------------------------- *)
14512 (* Comparison test.                                                          *)
14513 (* ------------------------------------------------------------------------- *)
14514
14515 let SERIES_COMPARISON = prove
14516  (`!f g s. (?l. ((lift o g) sums l) s) /\
14517            (?N. !n. n >= N /\ n IN s ==> norm(f n) <= g n)
14518            ==> ?l:real^N. (f sums l) s`,
14519   REPEAT GEN_TAC THEN REWRITE_TAC[SERIES_CAUCHY] THEN
14520   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC (X_CHOOSE_TAC `N1:num`)) THEN
14521   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
14522   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
14523   DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN
14524   EXISTS_TAC `N1 + N2:num` THEN
14525   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN DISCH_TAC THEN
14526   MATCH_MP_TAC REAL_LET_TRANS THEN
14527   EXISTS_TAC `norm (vsum (s INTER (m .. n)) (lift o g))` THEN CONJ_TAC THENL
14528    [SIMP_TAC[GSYM LIFT_SUM; FINITE_INTER_NUMSEG; NORM_LIFT] THEN
14529     MATCH_MP_TAC(REAL_ARITH `x <= a ==> x <= abs(a)`) THEN
14530     MATCH_MP_TAC VSUM_NORM_LE THEN
14531     REWRITE_TAC[FINITE_INTER_NUMSEG; IN_INTER; IN_NUMSEG] THEN
14532     ASM_MESON_TAC[ARITH_RULE `m >= N1 + N2:num /\ m <= x ==> x >= N1`];
14533     ASM_MESON_TAC[ARITH_RULE `m >= N1 + N2:num ==> m >= N2`]]);;
14534
14535 let SUMMABLE_COMPARISON = prove
14536  (`!f g s. summable s (lift o g) /\
14537            (?N. !n. n >= N /\ n IN s ==> norm(f n) <= g n)
14538            ==> summable s f`,
14539   REWRITE_TAC[summable; SERIES_COMPARISON]);;
14540
14541 let SERIES_LIFT_ABSCONV_IMP_CONV = prove
14542  (`!x:num->real^N k. summable k (\n. lift(norm(x n))) ==> summable k x`,
14543   REWRITE_TAC[summable] THEN REPEAT STRIP_TAC THEN
14544   MATCH_MP_TAC SERIES_COMPARISON THEN
14545   EXISTS_TAC `\n:num. norm(x n:real^N)` THEN
14546   ASM_REWRITE_TAC[o_DEF; REAL_LE_REFL] THEN ASM_MESON_TAC[]);;
14547
14548 let SUMMABLE_SUBSET_ABSCONV = prove
14549  (`!x:num->real^N s t.
14550         summable s (\n. lift(norm(x n))) /\ t SUBSET s
14551         ==> summable t (\n. lift(norm(x n)))`,
14552   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUMMABLE_SUBSET THEN
14553   EXISTS_TAC `s:num->bool` THEN ASM_REWRITE_TAC[] THEN
14554   REWRITE_TAC[summable] THEN MATCH_MP_TAC SERIES_COMPARISON THEN
14555   EXISTS_TAC `\n:num. norm(x n:real^N)` THEN
14556   ASM_REWRITE_TAC[o_DEF; GSYM summable] THEN
14557   EXISTS_TAC `0` THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
14558   REWRITE_TAC[REAL_LE_REFL; NORM_LIFT; REAL_ABS_NORM; NORM_0; NORM_POS_LE]);;
14559
14560 (* ------------------------------------------------------------------------- *)
14561 (* Uniform version of comparison test.                                       *)
14562 (* ------------------------------------------------------------------------- *)
14563
14564 let SERIES_COMPARISON_UNIFORM = prove
14565  (`!f g P s. (?l. ((lift o g) sums l) s) /\
14566              (?N. !n x. N <= n /\ n IN s /\ P x ==> norm(f x n) <= g n)
14567              ==> ?l:A->real^N.
14568                     !e. &0 < e
14569                         ==> ?N. !n x. N <= n /\ P x
14570                                       ==> dist(vsum(s INTER (0..n)) (f x),
14571                                                l x) < e`,
14572   REPEAT GEN_TAC THEN SIMP_TAC[GE; SERIES_CAUCHY; SERIES_CAUCHY_UNIFORM] THEN
14573   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC (X_CHOOSE_TAC `N1:num`)) THEN
14574   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `e:real` THEN
14575   MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
14576   DISCH_THEN(X_CHOOSE_TAC `N2:num`) THEN
14577   EXISTS_TAC `N1 + N2:num` THEN
14578   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`; `x:A`] THEN DISCH_TAC THEN
14579   MATCH_MP_TAC REAL_LET_TRANS THEN
14580   EXISTS_TAC `norm (vsum (s INTER (m .. n)) (lift o g))` THEN CONJ_TAC THENL
14581    [SIMP_TAC[GSYM LIFT_SUM; FINITE_INTER_NUMSEG; NORM_LIFT] THEN
14582     MATCH_MP_TAC(REAL_ARITH `x <= a ==> x <= abs(a)`) THEN
14583     MATCH_MP_TAC VSUM_NORM_LE THEN
14584     REWRITE_TAC[FINITE_INTER_NUMSEG; IN_INTER; IN_NUMSEG] THEN
14585     ASM_MESON_TAC[ARITH_RULE `N1 + N2:num <= m /\ m <= x ==> N1 <= x`];
14586     ASM_MESON_TAC[ARITH_RULE `N1 + N2:num <= m ==> N2 <= m`]]);;
14587
14588 (* ------------------------------------------------------------------------- *)
14589 (* Ratio test.                                                               *)
14590 (* ------------------------------------------------------------------------- *)
14591
14592 let SERIES_RATIO = prove
14593  (`!c a s N.
14594       c < &1 /\
14595       (!n. n >= N ==> norm(a(SUC n)) <= c * norm(a(n)))
14596       ==> ?l:real^N. (a sums l) s`,
14597   REWRITE_TAC[GE] THEN REPEAT STRIP_TAC THEN
14598   MATCH_MP_TAC SERIES_COMPARISON THEN
14599   DISJ_CASES_TAC(REAL_ARITH `c <= &0 \/ &0 < c`) THENL
14600    [EXISTS_TAC `\n:num. &0` THEN REWRITE_TAC[o_DEF; LIFT_NUM] THEN
14601     CONJ_TAC THENL [MESON_TAC[SERIES_0]; ALL_TAC] THEN
14602     EXISTS_TAC `N + 1` THEN REWRITE_TAC[GE] THEN REPEAT STRIP_TAC THEN
14603     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `c * norm(a(n - 1):real^N)` THEN
14604     CONJ_TAC THENL
14605      [ASM_MESON_TAC[ARITH_RULE `N + 1 <= n ==> SUC(n - 1) = n /\ N <= n - 1`];
14606       ALL_TAC] THEN
14607     MATCH_MP_TAC(REAL_ARITH `&0 <= --c * x ==> c * x <= &0`) THEN
14608     MATCH_MP_TAC REAL_LE_MUL THEN REWRITE_TAC[NORM_POS_LE] THEN
14609     UNDISCH_TAC `c <= &0` THEN REAL_ARITH_TAC;
14610     ASSUME_TAC(MATCH_MP REAL_LT_IMP_LE (ASSUME `&0 < c`))] THEN
14611   EXISTS_TAC `\n. norm(a(N):real^N) * c pow (n - N)` THEN
14612   REWRITE_TAC[] THEN CONJ_TAC THENL
14613    [ALL_TAC;
14614     EXISTS_TAC `N:num` THEN
14615     SIMP_TAC[GE; LE_EXISTS; IMP_CONJ; ADD_SUB2; LEFT_IMP_EXISTS_THM] THEN
14616     SUBGOAL_THEN `!d:num. norm(a(N + d):real^N) <= norm(a N) * c pow d`
14617      (fun th -> MESON_TAC[th]) THEN INDUCT_TAC THEN
14618     REWRITE_TAC[ADD_CLAUSES; real_pow; REAL_MUL_RID; REAL_LE_REFL] THEN
14619     MATCH_MP_TAC REAL_LE_TRANS THEN
14620     EXISTS_TAC `c * norm((a:num->real^N) (N + d))` THEN
14621     ASM_SIMP_TAC[LE_ADD] THEN ASM_MESON_TAC[REAL_LE_LMUL; REAL_MUL_AC]] THEN
14622   GEN_REWRITE_TAC I [SERIES_CAUCHY] THEN X_GEN_TAC `e:real` THEN
14623   SIMP_TAC[GSYM LIFT_SUM; FINITE_INTER; NORM_LIFT; FINITE_NUMSEG] THEN
14624   DISCH_TAC THEN SIMP_TAC[SUM_LMUL; FINITE_INTER; FINITE_NUMSEG] THEN
14625   ASM_CASES_TAC `(a:num->real^N) N = vec 0` THENL
14626    [ASM_REWRITE_TAC[NORM_0; REAL_MUL_LZERO; REAL_ABS_NUM]; ALL_TAC] THEN
14627   MP_TAC(SPECL [`c:real`; `((&1 - c) * e) / norm((a:num->real^N) N)`]
14628                REAL_ARCH_POW_INV) THEN
14629   ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_MUL; REAL_SUB_LT; NORM_POS_LT; GE] THEN
14630   DISCH_THEN(X_CHOOSE_TAC `M:num`) THEN EXISTS_TAC `N + M:num` THEN
14631   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN DISCH_TAC THEN
14632   MATCH_MP_TAC REAL_LET_TRANS THEN
14633   EXISTS_TAC `abs(norm((a:num->real^N) N) *
14634                   sum(m..n) (\i. c pow (i - N)))` THEN
14635   CONJ_TAC THENL
14636    [REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC REAL_LE_LMUL THEN
14637     REWRITE_TAC[REAL_ABS_POS] THEN
14638     MATCH_MP_TAC(REAL_ARITH `&0 <= x /\ x <= y ==> abs x <= abs y`) THEN
14639     ASM_SIMP_TAC[SUM_POS_LE; FINITE_INTER_NUMSEG; REAL_POW_LE] THEN
14640     MATCH_MP_TAC SUM_SUBSET THEN ASM_SIMP_TAC[REAL_POW_LE] THEN
14641     REWRITE_TAC[FINITE_INTER_NUMSEG; FINITE_NUMSEG] THEN
14642     REWRITE_TAC[IN_INTER; IN_DIFF] THEN MESON_TAC[];
14643     ALL_TAC] THEN
14644   REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_NORM] THEN
14645   DISJ_CASES_TAC(ARITH_RULE `n:num < m \/ m <= n`) THENL
14646    [ASM_SIMP_TAC[SUM_TRIV_NUMSEG; REAL_ABS_NUM; REAL_MUL_RZERO]; ALL_TAC] THEN
14647   SUBGOAL_THEN `m = 0 + m /\ n = (n - m) + m` (CONJUNCTS_THEN SUBST1_TAC) THENL
14648    [UNDISCH_TAC `m:num <= n` THEN ARITH_TAC; ALL_TAC] THEN
14649   REWRITE_TAC[SUM_OFFSET] THEN UNDISCH_TAC `N + M:num <= m` THEN
14650   SIMP_TAC[LE_EXISTS] THEN DISCH_THEN(X_CHOOSE_THEN `d:num` SUBST_ALL_TAC) THEN
14651   REWRITE_TAC[ARITH_RULE `(i + (N + M) + d) - N:num = (M + d) + i`] THEN
14652   ONCE_REWRITE_TAC[REAL_POW_ADD] THEN REWRITE_TAC[SUM_LMUL; SUM_GP] THEN
14653   ASM_SIMP_TAC[LT; REAL_LT_IMP_NE] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
14654   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; NORM_POS_LT; REAL_ABS_MUL] THEN
14655   REWRITE_TAC[REAL_ABS_POW] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
14656   ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_ABS_DIV; REAL_POW_LT; REAL_ARITH
14657    `&0 < c /\ c < &1 ==> &0 < abs c /\ &0 < abs(&1 - c)`; REAL_LT_LDIV_EQ] THEN
14658   MATCH_MP_TAC(REAL_ARITH
14659    `&0 < x /\ x <= &1 /\ &1 <= e ==> abs(c pow 0 - x) < e`) THEN
14660   ASM_SIMP_TAC[REAL_POW_LT; REAL_POW_1_LE; REAL_LT_IMP_LE] THEN
14661   ASM_SIMP_TAC[REAL_ARITH `c < &1 ==> x * abs(&1 - c) = (&1 - c) * x`] THEN
14662   REWRITE_TAC[real_div; REAL_INV_MUL; REAL_POW_ADD; REAL_MUL_ASSOC] THEN
14663   REWRITE_TAC[REAL_ARITH
14664    `(((a * b) * c) * d) * e = (e * ((a * b) * c)) * d`] THEN
14665   ASM_SIMP_TAC[GSYM real_div; REAL_LE_RDIV_EQ; REAL_POW_LT; REAL_MUL_LID;
14666                REAL_ARITH `&0 < c ==> abs c = c`] THEN
14667   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
14668    `xm < e ==> &0 <= (d - &1) * e ==> xm <= d * e`)) THEN
14669   MATCH_MP_TAC REAL_LE_MUL THEN CONJ_TAC THENL
14670    [REWRITE_TAC[REAL_SUB_LE; GSYM REAL_POW_INV] THEN
14671     MATCH_MP_TAC REAL_POW_LE_1 THEN
14672     MATCH_MP_TAC REAL_INV_1_LE THEN ASM_SIMP_TAC[REAL_LT_IMP_LE];
14673     MATCH_MP_TAC REAL_LT_IMP_LE THEN
14674     ASM_SIMP_TAC[REAL_SUB_LT; REAL_LT_MUL; REAL_LT_DIV; NORM_POS_LT]]);;
14675
14676 (* ------------------------------------------------------------------------- *)
14677 (* Ostensibly weaker versions of the boundedness of partial sums.            *)
14678 (* ------------------------------------------------------------------------- *)
14679
14680 let BOUNDED_PARTIAL_SUMS = prove
14681  (`!f:num->real^N k.
14682         bounded { vsum(k..n) f | n IN (:num) }
14683         ==> bounded { vsum(m..n) f | m IN (:num) /\ n IN (:num) }`,
14684   REPEAT STRIP_TAC THEN
14685   SUBGOAL_THEN `bounded { vsum(0..n) f:real^N | n IN (:num) }` MP_TAC THENL
14686    [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
14687     REWRITE_TAC[bounded] THEN
14688     REWRITE_TAC[SIMPLE_IMAGE; FORALL_IN_IMAGE; IN_UNIV] THEN
14689     DISCH_THEN(X_CHOOSE_THEN `B:real` STRIP_ASSUME_TAC) THEN
14690     EXISTS_TAC `sum { i:num | i < k} (\i. norm(f i:real^N)) + B` THEN
14691     X_GEN_TAC `i:num` THEN ASM_CASES_TAC `i:num < k` THENL
14692      [MATCH_MP_TAC(REAL_ARITH
14693        `!y. x <= y /\ y <= a /\ &0 < b ==> x <= a + b`) THEN
14694       EXISTS_TAC `sum (0..i) (\i. norm(f i:real^N))` THEN
14695       ASM_SIMP_TAC[VSUM_NORM; FINITE_NUMSEG] THEN
14696       MATCH_MP_TAC SUM_SUBSET THEN
14697       REWRITE_TAC[FINITE_NUMSEG; FINITE_NUMSEG_LT; NORM_POS_LE] THEN
14698       REWRITE_TAC[IN_DIFF; IN_NUMSEG; IN_ELIM_THM] THEN ASM_ARITH_TAC;
14699       ALL_TAC] THEN
14700     ASM_CASES_TAC `k = 0` THENL
14701      [FIRST_X_ASSUM SUBST_ALL_TAC THEN MATCH_MP_TAC(REAL_ARITH
14702        `x <= B /\ &0 <= b ==> x <= b + B`) THEN
14703       ASM_SIMP_TAC[SUM_POS_LE; FINITE_NUMSEG_LT; NORM_POS_LE];
14704       ALL_TAC] THEN
14705     MP_TAC(ISPECL [`f:num->real^N`; `0`; `k:num`; `i:num`]
14706       VSUM_COMBINE_L) THEN
14707     ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
14708     DISCH_THEN(SUBST1_TAC o SYM) THEN ASM_REWRITE_TAC[NUMSEG_LT] THEN
14709     MATCH_MP_TAC(NORM_ARITH
14710      `norm(x) <= a /\ norm(y) <= b ==> norm(x + y) <= a + b`) THEN
14711     ASM_SIMP_TAC[VSUM_NORM; FINITE_NUMSEG];
14712     ALL_TAC] THEN
14713   DISCH_THEN(fun th ->
14714     MP_TAC(MATCH_MP BOUNDED_DIFFS (W CONJ th)) THEN MP_TAC th) THEN
14715   REWRITE_TAC[IMP_IMP; GSYM BOUNDED_UNION] THEN
14716   MATCH_MP_TAC(REWRITE_RULE[TAUT `a /\ b ==> c <=> b ==> a ==> c`]
14717         BOUNDED_SUBSET) THEN
14718   REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNION; LEFT_IMP_EXISTS_THM; IN_UNIV] THEN
14719   MAP_EVERY X_GEN_TAC [`x:real^N`; `m:num`; `n:num`] THEN
14720   DISCH_THEN SUBST1_TAC THEN
14721   ASM_CASES_TAC `m = 0` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
14722   ASM_CASES_TAC `n:num < m` THENL
14723    [DISJ2_TAC THEN REPEAT(EXISTS_TAC `vsum(0..0) (f:num->real^N)`) THEN
14724     ASM_SIMP_TAC[VSUM_TRIV_NUMSEG; VECTOR_SUB_REFL] THEN MESON_TAC[];
14725     ALL_TAC] THEN
14726   DISJ2_TAC THEN MAP_EVERY EXISTS_TAC
14727    [`vsum(0..n) (f:num->real^N)`; `vsum(0..(m-1)) (f:num->real^N)`] THEN
14728   CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
14729   MP_TAC(ISPECL [`f:num->real^N`; `0`; `m:num`; `n:num`]
14730       VSUM_COMBINE_L) THEN
14731   ANTS_TAC THENL [ASM_ARITH_TAC; VECTOR_ARITH_TAC]);;
14732
14733 (* ------------------------------------------------------------------------- *)
14734 (* General Dirichlet convergence test (could make this uniform on a set).    *)
14735 (* ------------------------------------------------------------------------- *)
14736
14737 let SUMMABLE_BILINEAR_PARTIAL_PRE = prove
14738  (`!f g h:real^M->real^N->real^P l k.
14739         bilinear h /\
14740         ((\n. h (f(n + 1)) (g(n))) --> l) sequentially /\
14741         summable (from k) (\n. h (f(n + 1) - f(n)) (g(n)))
14742         ==> summable (from k) (\n. h (f n) (g(n) - g(n - 1)))`,
14743   REPEAT GEN_TAC THEN
14744   REWRITE_TAC[summable; sums; FROM_INTER_NUMSEG] THEN
14745   REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
14746   FIRST_ASSUM(fun th ->
14747    REWRITE_TAC[MATCH_MP BILINEAR_VSUM_PARTIAL_PRE th]) THEN
14748   DISCH_THEN(X_CHOOSE_TAC `l':real^P`) THEN
14749   EXISTS_TAC `l - (h:real^M->real^N->real^P) (f k) (g(k - 1)) - l'` THEN
14750   REWRITE_TAC[LIM_CASES_SEQUENTIALLY] THEN
14751   REPEAT(MATCH_MP_TAC LIM_SUB THEN ASM_REWRITE_TAC[LIM_CONST]));;
14752
14753 let SERIES_DIRICHLET_BILINEAR = prove
14754  (`!f g h:real^M->real^N->real^P k m p l.
14755         bilinear h /\
14756         bounded { vsum (m..n) f | n IN (:num)} /\
14757         summable (from p) (\n. lift(norm(g(n + 1) - g(n)))) /\
14758         ((\n. h (g(n + 1)) (vsum(1..n) f)) --> l) sequentially
14759         ==> summable (from k) (\n. h (g n) (f n))`,
14760   REPEAT STRIP_TAC THEN MATCH_MP_TAC SUMMABLE_FROM_ELSEWHERE THEN
14761   EXISTS_TAC `1` THEN
14762   FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP BOUNDED_PARTIAL_SUMS) THEN
14763   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
14764   SIMP_TAC[IN_ELIM_THM; IN_UNIV; LEFT_IMP_EXISTS_THM] THEN
14765   REWRITE_TAC[MESON[] `(!x a b. x = f a b ==> p a b) <=> (!a b. p a b)`] THEN
14766   X_GEN_TAC `B:real` THEN STRIP_TAC THEN
14767   FIRST_ASSUM(MP_TAC o MATCH_MP BILINEAR_BOUNDED_POS) THEN
14768   DISCH_THEN(X_CHOOSE_THEN `C:real` STRIP_ASSUME_TAC) THEN
14769   MATCH_MP_TAC SUMMABLE_EQ THEN
14770   EXISTS_TAC `\n. (h:real^M->real^N->real^P)
14771                   (g n) (vsum (1..n) f - vsum (1..n-1) f)` THEN
14772   SIMP_TAC[IN_FROM; GSYM NUMSEG_RREC] THEN
14773   SIMP_TAC[VSUM_CLAUSES; FINITE_NUMSEG; IN_NUMSEG;
14774            ARITH_RULE `1 <= n ==> ~(n <= n - 1)`] THEN
14775   CONJ_TAC THENL
14776    [REPEAT STRIP_TAC THEN ASM_SIMP_TAC[BILINEAR_RADD; BILINEAR_RSUB] THEN
14777     VECTOR_ARITH_TAC;
14778     ALL_TAC] THEN
14779   MATCH_MP_TAC SUMMABLE_FROM_ELSEWHERE THEN EXISTS_TAC `p:num` THEN
14780   MP_TAC(ISPECL [`g:num->real^M`; `\n. vsum(1..n) f:real^N`;
14781                  `h:real^M->real^N->real^P`; `l:real^P`; `p:num`]
14782          SUMMABLE_BILINEAR_PARTIAL_PRE) THEN
14783   REWRITE_TAC[] THEN DISCH_THEN MATCH_MP_TAC THEN
14784   ASM_REWRITE_TAC[] THEN
14785   SUBGOAL_THEN
14786     `summable (from p) (lift o (\n. C * B * norm(g(n + 1) - g(n):real^M)))`
14787   MP_TAC THENL [ASM_SIMP_TAC[o_DEF; LIFT_CMUL; SUMMABLE_CMUL]; ALL_TAC] THEN
14788   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] SUMMABLE_COMPARISON) THEN
14789   EXISTS_TAC `0` THEN REWRITE_TAC[IN_FROM; GE; LE_0] THEN
14790   REPEAT STRIP_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
14791    `C * norm(g(n + 1) - g(n):real^M) * norm(vsum (1..n) f:real^N)` THEN
14792   ASM_SIMP_TAC[REAL_LE_LMUL_EQ] THEN
14793   GEN_REWRITE_TAC RAND_CONV [REAL_MUL_SYM] THEN
14794   ASM_SIMP_TAC[REAL_LE_LMUL; NORM_POS_LE]);;
14795
14796 let SERIES_DIRICHLET = prove
14797  (`!f:num->real^N g N k m.
14798         bounded { vsum (m..n) f | n IN (:num)} /\
14799         (!n. N <= n ==> g(n + 1) <= g(n)) /\
14800         ((lift o g) --> vec 0) sequentially
14801         ==> summable (from k) (\n. g(n) % f(n))`,
14802   REPEAT STRIP_TAC THEN
14803   MP_TAC(ISPECL [`f:num->real^N`; `lift o (g:num->real)`;
14804                  `\x y:real^N. drop x % y`] SERIES_DIRICHLET_BILINEAR) THEN
14805   REWRITE_TAC[o_THM; LIFT_DROP] THEN DISCH_THEN MATCH_MP_TAC THEN
14806   MAP_EVERY EXISTS_TAC [`m:num`; `N:num`; `vec 0:real^N`] THEN CONJ_TAC THENL
14807    [REWRITE_TAC[bilinear; linear; DROP_ADD; DROP_CMUL] THEN
14808     REPEAT STRIP_TAC THEN VECTOR_ARITH_TAC;
14809     ALL_TAC] THEN
14810   ASM_REWRITE_TAC[GSYM LIFT_SUB; NORM_LIFT] THEN
14811   FIRST_ASSUM(MP_TAC o SPEC `1` o MATCH_MP SEQ_OFFSET) THEN
14812   REWRITE_TAC[o_THM] THEN DISCH_TAC THEN CONJ_TAC THENL
14813    [MATCH_MP_TAC SUMMABLE_EQ_EVENTUALLY THEN
14814     EXISTS_TAC `\n. lift(g(n) - g(n + 1))` THEN REWRITE_TAC[] THEN
14815     CONJ_TAC THENL
14816      [ASM_MESON_TAC[REAL_ARITH `b <= a ==> abs(b - a) = a - b`];
14817       REWRITE_TAC[summable; sums; FROM_INTER_NUMSEG; VSUM_DIFFS; LIFT_SUB] THEN
14818       REWRITE_TAC[LIM_CASES_SEQUENTIALLY] THEN
14819       EXISTS_TAC `lift(g(N:num)) - vec 0` THEN
14820       MATCH_MP_TAC LIM_SUB THEN ASM_REWRITE_TAC[LIM_CONST]];
14821     MATCH_MP_TAC LIM_NULL_VMUL_BOUNDED THEN ASM_REWRITE_TAC[o_DEF] THEN
14822     REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN
14823     FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP BOUNDED_PARTIAL_SUMS) THEN
14824     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [BOUNDED_POS]) THEN
14825     SIMP_TAC[IN_ELIM_THM; IN_UNIV] THEN MESON_TAC[]]);;
14826
14827 (* ------------------------------------------------------------------------- *)
14828 (* Rearranging absolutely convergent series.                                 *)
14829 (* ------------------------------------------------------------------------- *)
14830
14831 let SERIES_INJECTIVE_IMAGE_STRONG = prove
14832  (`!x:num->real^N s f.
14833         summable (IMAGE f s) (\n. lift(norm(x n))) /\
14834         (!m n. m IN s /\ n IN s /\ f m = f n ==> m = n)
14835         ==> ((\n. vsum (IMAGE f s INTER (0..n)) x -
14836                   vsum (s INTER (0..n)) (x o f)) --> vec 0)
14837             sequentially`,
14838   let lemma = prove
14839    (`!f:A->real^N s t.
14840           FINITE s /\ FINITE t
14841           ==> vsum s f - vsum t f = vsum (s DIFF t) f - vsum (t DIFF s) f`,
14842     REPEAT STRIP_TAC THEN
14843     ONCE_REWRITE_TAC[SET_RULE `s DIFF t = s DIFF (s INTER t)`] THEN
14844     ASM_SIMP_TAC[VSUM_DIFF; INTER_SUBSET] THEN
14845     REWRITE_TAC[INTER_COMM] THEN VECTOR_ARITH_TAC) in
14846   REPEAT STRIP_TAC THEN REWRITE_TAC[LIM_SEQUENTIALLY] THEN
14847   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
14848   FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUMMABLE_CAUCHY]) THEN
14849   SIMP_TAC[VSUM_REAL; FINITE_INTER; FINITE_NUMSEG] THEN
14850   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [o_DEF] THEN
14851   REWRITE_TAC[NORM_LIFT; LIFT_DROP] THEN
14852   SIMP_TAC[real_abs; SUM_POS_LE; NORM_POS_LE; FINITE_INTER; FINITE_NUMSEG] THEN
14853   DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN
14854   ASM_REWRITE_TAC[dist; GE; VECTOR_SUB_RZERO; REAL_HALF] THEN
14855   DISCH_THEN(X_CHOOSE_THEN `N:num` STRIP_ASSUME_TAC) THEN
14856   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [INJECTIVE_ON_LEFT_INVERSE]) THEN
14857   DISCH_THEN(X_CHOOSE_TAC `g:num->num`) THEN
14858   MP_TAC(ISPECL [`g:num->num`; `0..N`] UPPER_BOUND_FINITE_SET) THEN
14859   REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG; LE_0] THEN
14860   DISCH_THEN(X_CHOOSE_TAC `P:num`) THEN
14861   EXISTS_TAC `MAX N P` THEN X_GEN_TAC `n:num` THEN
14862   SIMP_TAC[ARITH_RULE `MAX a b <= c <=> a <= c /\ b <= c`] THEN DISCH_TAC THEN
14863   W(MP_TAC o PART_MATCH (rand o rand) VSUM_IMAGE o rand o
14864     rand o lhand o snd) THEN
14865   ANTS_TAC THENL
14866    [ASM_MESON_TAC[FINITE_INTER; FINITE_NUMSEG; IN_INTER];
14867     DISCH_THEN(SUBST1_TAC o SYM)] THEN
14868   W(MP_TAC o PART_MATCH (lhand o rand) lemma o rand o lhand o snd) THEN
14869   SIMP_TAC[FINITE_INTER; FINITE_IMAGE; FINITE_NUMSEG] THEN
14870   DISCH_THEN SUBST1_TAC THEN MATCH_MP_TAC(NORM_ARITH
14871    `norm a < e / &2 /\ norm b < e / &2 ==> norm(a - b:real^N) < e`) THEN
14872   CONJ_TAC THEN
14873   W(MP_TAC o PART_MATCH (lhand o rand) VSUM_NORM o lhand o snd) THEN
14874   SIMP_TAC[FINITE_DIFF; FINITE_IMAGE; FINITE_INTER; FINITE_NUMSEG] THEN
14875   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LET_TRANS) THEN
14876   MATCH_MP_TAC REAL_LET_TRANS THENL
14877    [EXISTS_TAC
14878      `sum(IMAGE (f:num->num) s INTER (N..n)) (\i. norm(x i :real^N))` THEN
14879     ASM_SIMP_TAC[LE_REFL] THEN MATCH_MP_TAC SUM_SUBSET_SIMPLE THEN
14880     SIMP_TAC[NORM_POS_LE; FINITE_INTER; FINITE_NUMSEG] THEN
14881     MATCH_MP_TAC(SET_RULE
14882      `(!x. x IN s /\ f(x) IN n /\ ~(x IN m) ==> f x IN t)
14883       ==> (IMAGE f s INTER n) DIFF (IMAGE f (s INTER m)) SUBSET
14884           IMAGE f s INTER t`) THEN
14885     ASM_SIMP_TAC[IN_NUMSEG; LE_0; NOT_LE] THEN
14886     X_GEN_TAC `i:num` THEN STRIP_TAC THEN
14887     MATCH_MP_TAC LT_IMP_LE THEN ONCE_REWRITE_TAC[GSYM NOT_LE] THEN
14888     FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE BINDER_CONV
14889      [GSYM CONTRAPOS_THM]) THEN
14890     ASM_SIMP_TAC[] THEN ASM_ARITH_TAC;
14891     MP_TAC(ISPECL [`f:num->num`; `0..n`] UPPER_BOUND_FINITE_SET) THEN
14892     REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG; LE_0] THEN
14893     DISCH_THEN(X_CHOOSE_TAC `p:num`) THEN
14894     EXISTS_TAC
14895      `sum(IMAGE (f:num->num) s INTER (N..p)) (\i. norm(x i :real^N))` THEN
14896     ASM_SIMP_TAC[LE_REFL] THEN MATCH_MP_TAC SUM_SUBSET_SIMPLE THEN
14897     SIMP_TAC[NORM_POS_LE; FINITE_INTER; FINITE_NUMSEG] THEN
14898     MATCH_MP_TAC(SET_RULE
14899      `(!x. x IN s /\ x IN n /\ ~(f x IN m) ==> f x IN t)
14900       ==> (IMAGE f (s INTER n) DIFF (IMAGE f s) INTER m) SUBSET
14901           (IMAGE f s INTER t)`) THEN
14902     ASM_SIMP_TAC[IN_NUMSEG; LE_0] THEN ASM_ARITH_TAC]);;
14903
14904 let SERIES_INJECTIVE_IMAGE = prove
14905  (`!x:num->real^N s f l.
14906         summable (IMAGE f s) (\n. lift(norm(x n))) /\
14907         (!m n. m IN s /\ n IN s /\ f m = f n ==> m = n)
14908         ==> (((x o f) sums l) s <=> (x sums l) (IMAGE f s))`,
14909   REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN REWRITE_TAC[sums] THEN
14910   MATCH_MP_TAC LIM_TRANSFORM_EQ THEN REWRITE_TAC[] THEN
14911   MATCH_MP_TAC SERIES_INJECTIVE_IMAGE_STRONG THEN
14912   ASM_REWRITE_TAC[]);;
14913
14914 let SERIES_REARRANGE_EQ = prove
14915  (`!x:num->real^N s p l.
14916         summable s (\n. lift(norm(x n))) /\ p permutes s
14917         ==> (((x o p) sums l) s <=> (x sums l) s)`,
14918   REPEAT STRIP_TAC THEN
14919   MP_TAC(ISPECL [`x:num->real^N`; `s:num->bool`; `p:num->num`; `l:real^N`]
14920         SERIES_INJECTIVE_IMAGE) THEN
14921   ASM_SIMP_TAC[PERMUTES_IMAGE] THEN
14922   ASM_MESON_TAC[PERMUTES_INJECTIVE]);;
14923
14924 let SERIES_REARRANGE = prove
14925  (`!x:num->real^N s p l.
14926         summable s (\n. lift(norm(x n))) /\ p permutes s /\ (x sums l) s
14927         ==> ((x o p) sums l) s`,
14928   MESON_TAC[SERIES_REARRANGE_EQ]);;
14929
14930 let SUMMABLE_REARRANGE = prove
14931  (`!x s p.
14932         summable s (\n. lift(norm(x n))) /\ p permutes s
14933         ==> summable s (x o p)`,
14934   MESON_TAC[SERIES_LIFT_ABSCONV_IMP_CONV; summable; SERIES_REARRANGE]);;
14935
14936 (* ------------------------------------------------------------------------- *)
14937 (* Banach fixed point theorem (not really topological...)                    *)
14938 (* ------------------------------------------------------------------------- *)
14939
14940 let BANACH_FIX = prove
14941  (`!f s c. complete s /\ ~(s = {}) /\
14942            &0 <= c /\ c < &1 /\
14943            (IMAGE f s) SUBSET s /\
14944            (!x y. x IN s /\ y IN s ==> dist(f(x),f(y)) <= c * dist(x,y))
14945            ==> ?!x:real^N. x IN s /\ (f x = x)`,
14946   REPEAT STRIP_TAC THEN REWRITE_TAC[EXISTS_UNIQUE_THM] THEN CONJ_TAC THENL
14947    [ALL_TAC;
14948     MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN
14949     SUBGOAL_THEN `dist((f:real^N->real^N) x,f y) <= c * dist(x,y)` MP_TAC THENL
14950      [ASM_MESON_TAC[]; ALL_TAC] THEN
14951     ASM_REWRITE_TAC[REAL_ARITH `a <= c * a <=> &0 <= --a * (&1 - c)`] THEN
14952     ASM_SIMP_TAC[GSYM REAL_LE_LDIV_EQ; REAL_SUB_LT; real_div] THEN
14953     REWRITE_TAC[REAL_MUL_LZERO; REAL_ARITH `&0 <= --x <=> ~(&0 < x)`] THEN
14954     MESON_TAC[DIST_POS_LT]] THEN
14955   STRIP_ASSUME_TAC(prove_recursive_functions_exist num_RECURSION
14956     `(z 0 = @x:real^N. x IN s) /\ (!n. z(SUC n) = f(z n))`) THEN
14957   SUBGOAL_THEN `!n. (z:num->real^N) n IN s` ASSUME_TAC THENL
14958    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN
14959     ASM_MESON_TAC[MEMBER_NOT_EMPTY; SUBSET; IN_IMAGE];
14960     ALL_TAC] THEN
14961   UNDISCH_THEN `z 0 = @x:real^N. x IN s` (K ALL_TAC) THEN
14962   SUBGOAL_THEN `?x:real^N. x IN s /\ (z --> x) sequentially` MP_TAC THENL
14963    [ALL_TAC;
14964     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
14965     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
14966     ABBREV_TAC `e = dist(f(a:real^N),a)` THEN
14967     SUBGOAL_THEN `~(&0 < e)` (fun th -> ASM_MESON_TAC[th; DIST_POS_LT]) THEN
14968     DISCH_TAC THEN
14969     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIM_SEQUENTIALLY]) THEN
14970     DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN
14971     ASM_REWRITE_TAC[REAL_HALF] THEN DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN
14972     SUBGOAL_THEN
14973      `dist(f(z N),a:real^N) < e / &2 /\ dist(f(z(N:num)),f(a)) < e / &2`
14974      (fun th -> ASM_MESON_TAC[th; DIST_TRIANGLE_HALF_R; REAL_LT_REFL]) THEN
14975     CONJ_TAC THENL [ASM_MESON_TAC[ARITH_RULE `N <= SUC N`]; ALL_TAC] THEN
14976     MATCH_MP_TAC REAL_LET_TRANS THEN
14977     EXISTS_TAC `c * dist((z:num->real^N) N,a)` THEN ASM_SIMP_TAC[] THEN
14978     MATCH_MP_TAC(REAL_ARITH `x < y /\ c * x <= &1 * x ==> c * x < y`) THEN
14979     ASM_SIMP_TAC[LE_REFL; REAL_LE_RMUL; DIST_POS_LE; REAL_LT_IMP_LE]] THEN
14980   FIRST_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [complete]) THEN
14981   ASM_REWRITE_TAC[CAUCHY] THEN
14982   SUBGOAL_THEN `!n. dist(z(n):real^N,z(SUC n)) <= c pow n * dist(z(0),z(1))`
14983   ASSUME_TAC THENL
14984    [INDUCT_TAC THEN
14985     REWRITE_TAC[real_pow; ARITH; REAL_MUL_LID; REAL_LE_REFL] THEN
14986     MATCH_MP_TAC REAL_LE_TRANS THEN
14987     EXISTS_TAC `c * dist(z(n):real^N,z(SUC n))` THEN
14988     CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
14989     REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN ASM_SIMP_TAC[REAL_LE_LMUL];
14990     ALL_TAC] THEN
14991   SUBGOAL_THEN
14992    `!m n:num. (&1 - c) * dist(z(m):real^N,z(m+n))
14993                 <= c pow m * dist(z(0),z(1)) * (&1 - c pow n)`
14994   ASSUME_TAC THENL
14995    [GEN_TAC THEN INDUCT_TAC THENL
14996      [REWRITE_TAC[ADD_CLAUSES; DIST_REFL; REAL_MUL_RZERO] THEN
14997       MATCH_MP_TAC REAL_LE_MUL THEN
14998       ASM_SIMP_TAC[REAL_LE_MUL; REAL_POW_LE; DIST_POS_LE; REAL_SUB_LE;
14999                    REAL_POW_1_LE; REAL_LT_IMP_LE];
15000       ALL_TAC] THEN
15001     MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC
15002     `(&1 - c) * (dist(z m:real^N,z(m + n)) + dist(z(m + n),z(m + SUC n)))` THEN
15003     ASM_SIMP_TAC[REAL_LE_LMUL; REAL_SUB_LE; REAL_LT_IMP_LE; DIST_TRIANGLE] THEN
15004     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
15005       `c * x <= y ==> c * x' + y <= y' ==> c * (x + x') <= y'`)) THEN
15006     REWRITE_TAC[REAL_ARITH
15007      `q + a * b * (&1 - x) <= a * b * (&1 - y) <=> q <= a * b * (x - y)`] THEN
15008     REWRITE_TAC[ADD_CLAUSES; real_pow] THEN
15009     REWRITE_TAC[REAL_ARITH `a * b * (d - c * d) = (&1 - c) * a * d * b`] THEN
15010     MATCH_MP_TAC REAL_LE_LMUL THEN
15011     ASM_SIMP_TAC[REAL_SUB_LE; REAL_LT_IMP_LE] THEN
15012     REWRITE_TAC[GSYM REAL_POW_ADD; REAL_MUL_ASSOC] THEN ASM_MESON_TAC[];
15013     ALL_TAC] THEN
15014   X_GEN_TAC `e:real` THEN DISCH_TAC THEN
15015   ASM_CASES_TAC `(z:num->real^N) 0 = z 1` THENL
15016    [FIRST_X_ASSUM SUBST_ALL_TAC THEN EXISTS_TAC `0` THEN
15017     REWRITE_TAC[GE; LE_0] THEN X_GEN_TAC `n:num` THEN
15018     FIRST_X_ASSUM(MP_TAC o SPECL [`0`; `n:num`]) THEN
15019     REWRITE_TAC[ADD_CLAUSES; DIST_REFL; REAL_MUL_LZERO; REAL_MUL_RZERO] THEN
15020     ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
15021     ASM_CASES_TAC `(z:num->real^N) 0 = z n` THEN
15022     ASM_REWRITE_TAC[DIST_REFL; REAL_NOT_LE] THEN
15023     ASM_SIMP_TAC[REAL_LT_MUL; DIST_POS_LT; REAL_SUB_LT];
15024     ALL_TAC] THEN
15025   MP_TAC(SPECL [`c:real`; `e * (&1 - c) / dist((z:num->real^N) 0,z 1)`]
15026    REAL_ARCH_POW_INV) THEN
15027   ASM_SIMP_TAC[REAL_LT_MUL; REAL_LT_DIV; REAL_SUB_LT; DIST_POS_LT] THEN
15028   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
15029   REWRITE_TAC[real_div; GE; REAL_MUL_ASSOC] THEN
15030   ASM_SIMP_TAC[REAL_LT_RDIV_EQ; GSYM real_div; DIST_POS_LT] THEN
15031   ASM_SIMP_TAC[GSYM REAL_LT_LDIV_EQ; REAL_SUB_LT] THEN DISCH_TAC THEN
15032   REWRITE_TAC[LE_EXISTS; LEFT_IMP_EXISTS_THM] THEN
15033   GEN_TAC THEN X_GEN_TAC `d:num` THEN DISCH_THEN SUBST_ALL_TAC THEN
15034   ONCE_REWRITE_TAC[DIST_SYM] THEN
15035   FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP(REAL_ARITH
15036     `d < e ==> x <= d ==> x < e`)) THEN
15037   ASM_SIMP_TAC[REAL_LE_RDIV_EQ; REAL_SUB_LT] THEN
15038   FIRST_X_ASSUM(MP_TAC o SPECL [`N:num`; `d:num`]) THEN
15039   MATCH_MP_TAC(REAL_ARITH
15040   `(c * d) * e <= (c * d) * &1 ==> x * y <= c * d * e ==> y * x <= c * d`) THEN
15041   MATCH_MP_TAC REAL_LE_LMUL THEN
15042   ASM_SIMP_TAC[REAL_LE_MUL; REAL_POW_LE; DIST_POS_LE; REAL_ARITH
15043    `&0 <= x ==> &1 - x <= &1`]);;
15044
15045 (* ------------------------------------------------------------------------- *)
15046 (* Edelstein fixed point theorem.                                            *)
15047 (* ------------------------------------------------------------------------- *)
15048
15049 let EDELSTEIN_FIX = prove
15050  (`!f s. compact s /\ ~(s = {}) /\ (IMAGE f s) SUBSET s /\
15051          (!x y. x IN s /\ y IN s /\ ~(x = y) ==> dist(f(x),f(y)) < dist(x,y))
15052          ==> ?!x:real^N. x IN s /\ f x = x`,
15053   MAP_EVERY X_GEN_TAC [`g:real^N->real^N`; `s:real^N->bool`] THEN
15054   REPEAT STRIP_TAC THEN REWRITE_TAC[EXISTS_UNIQUE_THM] THEN CONJ_TAC THENL
15055    [ALL_TAC; ASM_MESON_TAC[REAL_LT_REFL]] THEN
15056   SUBGOAL_THEN
15057    `!x y. x IN s /\ y IN s ==> dist((g:real^N->real^N)(x),g(y)) <= dist(x,y)`
15058   ASSUME_TAC THENL
15059    [REPEAT STRIP_TAC THEN ASM_CASES_TAC `x:real^N = y` THEN
15060     ASM_SIMP_TAC[DIST_REFL; REAL_LE_LT];
15061     ALL_TAC] THEN
15062   ASM_CASES_TAC `?x:real^N. x IN s /\ ~(g x = x)` THENL
15063    [ALL_TAC; ASM SET_TAC[]] THEN
15064   FIRST_X_ASSUM(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
15065   ABBREV_TAC `y = (g:real^N->real^N) x` THEN
15066   SUBGOAL_THEN `(y:real^N) IN s` ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
15067   FIRST_ASSUM(MP_TAC o MATCH_MP COMPACT_PCROSS o W CONJ) THEN
15068   REWRITE_TAC[compact; PCROSS] THEN
15069   (STRIP_ASSUME_TAC o prove_general_recursive_function_exists)
15070     `?f:num->real^N->real^N.
15071         (!z. f 0 z = z) /\ (!z n. f (SUC n) z = g(f n z))` THEN
15072   SUBGOAL_THEN `!n z. z IN s ==> (f:num->real^N->real^N) n z IN s`
15073   STRIP_ASSUME_TAC THENL [INDUCT_TAC THEN ASM SET_TAC[]; ALL_TAC] THEN
15074   SUBGOAL_THEN
15075    `!m n w z. m <= n /\ w IN s /\ z IN s
15076               ==> dist((f:num->real^N->real^N) n w,f n z) <= dist(f m w,f m z)`
15077   ASSUME_TAC THENL
15078    [REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
15079     MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
15080     RULE_ASSUM_TAC(REWRITE_RULE[SUBSET; FORALL_IN_IMAGE]) THEN
15081     ASM_SIMP_TAC[REAL_LE_REFL] THEN MESON_TAC[REAL_LE_TRANS];
15082     ALL_TAC] THEN
15083   DISCH_THEN(MP_TAC o SPEC
15084    `\n:num. pastecart (f n (x:real^N)) (f n y:real^N)`) THEN
15085   ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN
15086   MAP_EVERY X_GEN_TAC [`l:real^(N,N)finite_sum`; `s:num->num`] THEN
15087   REWRITE_TAC[o_DEF; IN_ELIM_THM] THEN
15088   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
15089   REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
15090   MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN
15091   DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC SUBST_ALL_TAC) THEN
15092   SUBGOAL_THEN
15093    `(\x:real^(N,N)finite_sum. fstcart x) continuous_on UNIV /\
15094     (\x:real^(N,N)finite_sum. sndcart x) continuous_on UNIV`
15095   MP_TAC THENL
15096    [CONJ_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_ON THEN
15097     REWRITE_TAC[ETA_AX; LINEAR_FSTCART; LINEAR_SNDCART];
15098     ALL_TAC] THEN
15099   REWRITE_TAC[CONTINUOUS_ON_SEQUENTIALLY; IN_UNIV] THEN
15100   DISCH_THEN(CONJUNCTS_THEN(fun th -> FIRST_ASSUM(MP_TAC o MATCH_MP th))) THEN
15101   REWRITE_TAC[o_DEF; FSTCART_PASTECART; SNDCART_PASTECART; IMP_IMP] THEN
15102   ONCE_REWRITE_TAC[CONJ_SYM] THEN
15103   DISCH_THEN(fun th -> CONJUNCTS_THEN2 (LABEL_TAC "A") (LABEL_TAC "B") th THEN
15104     MP_TAC(MATCH_MP LIM_SUB th)) THEN
15105   REWRITE_TAC[] THEN DISCH_THEN(LABEL_TAC "AB") THEN
15106   SUBGOAL_THEN
15107    `!n. dist(a:real^N,b) <= dist((f:num->real^N->real^N) n x,f n y)`
15108   STRIP_ASSUME_TAC THENL
15109    [X_GEN_TAC `N:num` THEN REWRITE_TAC[GSYM REAL_NOT_LT] THEN
15110     ONCE_REWRITE_TAC[GSYM REAL_SUB_LT] THEN DISCH_TAC THEN
15111     USE_THEN "AB" (MP_TAC o REWRITE_RULE[LIM_SEQUENTIALLY]) THEN
15112     DISCH_THEN(fun th -> FIRST_X_ASSUM(MP_TAC o MATCH_MP th)) THEN
15113     REWRITE_TAC[NOT_EXISTS_THM] THEN X_GEN_TAC `M:num` THEN
15114     DISCH_THEN(MP_TAC o SPEC `M + N:num`) THEN REWRITE_TAC[LE_ADD] THEN
15115     MATCH_MP_TAC(NORM_ARITH
15116      `dist(fx,fy) <= dist(x,y)
15117       ==> ~(dist(fx - fy,a - b) < dist(a,b) - dist(x,y))`) THEN
15118     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
15119     FIRST_X_ASSUM(MP_TAC o SPEC `M + N:num` o MATCH_MP MONOTONE_BIGGER) THEN
15120     ARITH_TAC;
15121     ALL_TAC] THEN
15122   SUBGOAL_THEN `b:real^N = a` SUBST_ALL_TAC THENL
15123    [MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN
15124     ABBREV_TAC `e = dist(a,b) - dist((g:real^N->real^N) a,g b)` THEN
15125     SUBGOAL_THEN `&0 < e` ASSUME_TAC THENL
15126      [ASM_MESON_TAC[REAL_SUB_LT]; ALL_TAC] THEN
15127     SUBGOAL_THEN
15128      `?n. dist((f:num->real^N->real^N) n x,a) < e / &2 /\
15129           dist(f n y,b) < e / &2`
15130     STRIP_ASSUME_TAC THENL
15131      [MAP_EVERY (fun s -> USE_THEN s (MP_TAC o SPEC `e / &2` o
15132         REWRITE_RULE[LIM_SEQUENTIALLY])) ["A"; "B"] THEN
15133       ASM_REWRITE_TAC[REAL_HALF] THEN
15134       DISCH_THEN(X_CHOOSE_TAC `M:num`) THEN
15135       DISCH_THEN(X_CHOOSE_TAC `N:num`) THEN
15136       EXISTS_TAC `(s:num->num) (M + N)` THEN
15137       CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ARITH_TAC;
15138       ALL_TAC] THEN
15139     SUBGOAL_THEN `dist(f (SUC n) x,(g:real^N->real^N) a) +
15140                   dist((f:num->real^N->real^N) (SUC n) y,g b) < e`
15141     MP_TAC THENL
15142      [ASM_REWRITE_TAC[] THEN
15143       MATCH_MP_TAC(REAL_ARITH `x < e / &2 /\ y < e / &2 ==> x + y < e`) THEN
15144       CONJ_TAC THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
15145        `dist(x,y) < e
15146         ==> dist(g x,g y) <= dist(x,y) ==> dist(g x,g y) < e`)) THEN
15147       ASM_SIMP_TAC[];
15148       ALL_TAC] THEN
15149     MP_TAC(SPEC `SUC n` (ASSUME
15150     `!n. dist (a:real^N,b) <=
15151          dist ((f:num->real^N->real^N) n x,f n y)`)) THEN
15152     EXPAND_TAC "e" THEN NORM_ARITH_TAC;
15153     ALL_TAC] THEN
15154   EXISTS_TAC `a:real^N` THEN ASM_REWRITE_TAC[] THEN
15155   MATCH_MP_TAC(ISPEC `sequentially` LIM_UNIQUE) THEN
15156   EXISTS_TAC `\n:num. (f:num->real^N->real^N) (SUC(s n)) x` THEN
15157   REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY] THEN CONJ_TAC THENL
15158    [ASM_REWRITE_TAC[] THEN
15159     SUBGOAL_THEN `(g:real^N->real^N) continuous_on s` MP_TAC THENL
15160      [REWRITE_TAC[continuous_on] THEN ASM_MESON_TAC[REAL_LET_TRANS];
15161       ALL_TAC] THEN
15162     REWRITE_TAC[CONTINUOUS_ON_SEQUENTIALLY; o_DEF] THEN
15163     DISCH_THEN MATCH_MP_TAC THEN ASM_SIMP_TAC[];
15164     SUBGOAL_THEN `!n. (f:num->real^N->real^N) (SUC n) x = f n y`
15165      (fun th -> ASM_SIMP_TAC[th]) THEN
15166     INDUCT_TAC THEN ASM_REWRITE_TAC[]]);;
15167
15168 (* ------------------------------------------------------------------------- *)
15169 (* Dini's theorem.                                                           *)
15170 (* ------------------------------------------------------------------------- *)
15171
15172 let DINI = prove
15173  (`!f:num->real^N->real^1 g s.
15174         compact s /\ (!n. (f n) continuous_on s) /\ g continuous_on s /\
15175         (!x. x IN s ==> ((\n. (f n x)) --> g x) sequentially) /\
15176         (!n x. x IN s ==> drop(f n x) <= drop(f (n + 1) x))
15177         ==> !e. &0 < e
15178                 ==> eventually (\n. !x. x IN s ==> norm(f n x - g x) < e)
15179                                sequentially`,
15180   REPEAT STRIP_TAC THEN
15181   SUBGOAL_THEN
15182    `!x:real^N m n:num. x IN s /\ m <= n ==> drop(f m x) <= drop(f n x)`
15183   ASSUME_TAC THENL
15184    [GEN_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THEN ASM_REWRITE_TAC[] THEN
15185     MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN ASM_SIMP_TAC[ADD1] THEN
15186     REAL_ARITH_TAC;
15187     ALL_TAC] THEN
15188   SUBGOAL_THEN `!n:num x:real^N. x IN s ==> drop(f n x) <= drop(g x)`
15189   ASSUME_TAC THENL
15190    [REPEAT STRIP_TAC THEN
15191     MATCH_MP_TAC(ISPEC `sequentially` LIM_DROP_LE) THEN
15192     EXISTS_TAC `\m:num. (f:num->real^N->real^1) n x` THEN
15193     EXISTS_TAC `\m:num. (f:num->real^N->real^1) m x` THEN
15194     ASM_SIMP_TAC[LIM_CONST; TRIVIAL_LIMIT_SEQUENTIALLY] THEN
15195     REWRITE_TAC[EVENTUALLY_SEQUENTIALLY] THEN ASM_MESON_TAC[];
15196     ALL_TAC] THEN
15197   RULE_ASSUM_TAC(REWRITE_RULE[LIM_SEQUENTIALLY; dist]) THEN
15198   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I
15199    [COMPACT_EQ_HEINE_BOREL_SUBTOPOLOGY]) THEN
15200   DISCH_THEN(MP_TAC o SPEC
15201    `IMAGE (\n. { x | x IN s /\ norm((f:num->real^N->real^1) n x - g x) < e})
15202           (:num)`) THEN
15203   REWRITE_TAC[FORALL_IN_IMAGE; IN_UNIV] THEN
15204   ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN
15205   REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE; SUBSET_UNION; UNIONS_IMAGE] THEN
15206   REWRITE_TAC[IN_UNIV; IN_ELIM_THM; EVENTUALLY_SEQUENTIALLY] THEN
15207   SIMP_TAC[SUBSET; IN_UNIV; IN_ELIM_THM] THEN ANTS_TAC THENL
15208    [CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[LE_REFL]] THEN
15209     X_GEN_TAC `n:num` THEN REWRITE_TAC[GSYM IN_BALL_0] THEN
15210     MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE THEN
15211     ASM_SIMP_TAC[OPEN_BALL; CONTINUOUS_ON_SUB; ETA_AX];
15212
15213     DISCH_THEN(X_CHOOSE_THEN `k:num->bool` (CONJUNCTS_THEN2
15214      (MP_TAC o SPEC `\n:num. n` o MATCH_MP UPPER_BOUND_FINITE_SET)
15215      (LABEL_TAC "*"))) THEN
15216     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
15217     REWRITE_TAC[] THEN STRIP_TAC THEN X_GEN_TAC `n:num` THEN
15218     DISCH_TAC THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
15219     REMOVE_THEN "*" (MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
15220     DISCH_THEN(X_CHOOSE_THEN `m:num` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
15221     REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB] THEN MATCH_MP_TAC(REAL_ARITH
15222      `m <= n /\ n <= g ==> abs(m - g) < e ==> abs(n - g) < e`) THEN
15223     ASM_MESON_TAC[LE_TRANS]]);;
15224
15225 (* ------------------------------------------------------------------------- *)
15226 (* Closest point of a (closed) set to a point.                               *)
15227 (* ------------------------------------------------------------------------- *)
15228
15229 let closest_point = new_definition
15230  `closest_point s a = @x. x IN s /\ !y. y IN s ==> dist(a,x) <= dist(a,y)`;;
15231
15232 let CLOSEST_POINT_EXISTS = prove
15233  (`!s a. closed s /\ ~(s = {})
15234          ==> (closest_point s a) IN s /\
15235              !y. y IN s ==> dist(a,closest_point s a) <= dist(a,y)`,
15236   REWRITE_TAC[closest_point] THEN CONV_TAC(ONCE_DEPTH_CONV SELECT_CONV) THEN
15237   REWRITE_TAC[DISTANCE_ATTAINS_INF]);;
15238
15239 let CLOSEST_POINT_IN_SET = prove
15240  (`!s a. closed s /\ ~(s = {}) ==> (closest_point s a) IN s`,
15241   MESON_TAC[CLOSEST_POINT_EXISTS]);;
15242
15243 let CLOSEST_POINT_LE = prove
15244  (`!s a x. closed s /\ x IN s ==> dist(a,closest_point s a) <= dist(a,x)`,
15245   MESON_TAC[CLOSEST_POINT_EXISTS; MEMBER_NOT_EMPTY]);;
15246
15247 let CLOSEST_POINT_SELF = prove
15248  (`!s x:real^N. x IN s ==> closest_point s x = x`,
15249   REPEAT STRIP_TAC THEN REWRITE_TAC[closest_point] THEN
15250   MATCH_MP_TAC SELECT_UNIQUE THEN REWRITE_TAC[] THEN GEN_TAC THEN EQ_TAC THENL
15251    [STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN
15252     ASM_SIMP_TAC[DIST_LE_0; DIST_REFL];
15253     STRIP_TAC THEN ASM_REWRITE_TAC[DIST_REFL; DIST_POS_LE]]);;
15254
15255 let CLOSEST_POINT_REFL = prove
15256  (`!s x:real^N. closed s /\ ~(s = {}) ==> (closest_point s x = x <=> x IN s)`,
15257   MESON_TAC[CLOSEST_POINT_IN_SET; CLOSEST_POINT_SELF]);;
15258
15259 let DIST_CLOSEST_POINT_LIPSCHITZ = prove
15260  (`!s x y:real^N.
15261         closed s /\ ~(s = {})
15262         ==> abs(dist(x,closest_point s x) - dist(y,closest_point s y))
15263             <= dist(x,y)`,
15264   REPEAT GEN_TAC THEN DISCH_TAC THEN
15265   FIRST_ASSUM(MP_TAC o MATCH_MP CLOSEST_POINT_EXISTS) THEN
15266   DISCH_THEN(fun th ->
15267     CONJUNCTS_THEN2 ASSUME_TAC
15268      (MP_TAC o SPEC `closest_point s (y:real^N)`) (SPEC `x:real^N` th) THEN
15269     CONJUNCTS_THEN2 ASSUME_TAC
15270      (MP_TAC o SPEC `closest_point s (x:real^N)`) (SPEC `y:real^N` th)) THEN
15271   ASM_REWRITE_TAC[] THEN NORM_ARITH_TAC);;
15272
15273 let CONTINUOUS_AT_DIST_CLOSEST_POINT = prove
15274  (`!s x:real^N.
15275         closed s /\ ~(s = {})
15276         ==> (\x. lift(dist(x,closest_point s x))) continuous (at x)`,
15277   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_at; DIST_LIFT] THEN
15278   ASM_MESON_TAC[DIST_CLOSEST_POINT_LIPSCHITZ; REAL_LET_TRANS]);;
15279
15280 let CONTINUOUS_ON_DIST_CLOSEST_POINT = prove
15281  (`!s t. closed s /\ ~(s = {})
15282          ==> (\x. lift(dist(x,closest_point s x))) continuous_on t`,
15283   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON;
15284             CONTINUOUS_AT_DIST_CLOSEST_POINT]);;
15285
15286 let UNIFORMLY_CONTINUOUS_ON_DIST_CLOSEST_POINT = prove
15287  (`!s t:real^N->bool.
15288         closed s /\ ~(s = {})
15289         ==> (\x. lift(dist(x,closest_point s x))) uniformly_continuous_on t`,
15290   REPEAT STRIP_TAC THEN REWRITE_TAC[uniformly_continuous_on; DIST_LIFT] THEN
15291   ASM_MESON_TAC[DIST_CLOSEST_POINT_LIPSCHITZ; REAL_LET_TRANS]);;
15292
15293 let SEGMENT_TO_CLOSEST_POINT = prove
15294  (`!s a:real^N.
15295         closed s /\ ~(s = {})
15296         ==> segment(a,closest_point s a) INTER s = {}`,
15297   REPEAT STRIP_TAC THEN
15298   REWRITE_TAC[SET_RULE `s INTER t = {} <=> !x. x IN s ==> ~(x IN t)`] THEN
15299   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP DIST_IN_OPEN_SEGMENT) THEN
15300   MATCH_MP_TAC(TAUT `(r ==> ~p) ==> p /\ q ==> ~r`) THEN
15301   ASM_MESON_TAC[CLOSEST_POINT_EXISTS; REAL_NOT_LT; DIST_SYM]);;
15302
15303 let SEGMENT_TO_POINT_EXISTS = prove
15304  (`!s a:real^N.
15305         closed s /\ ~(s = {}) ==> ?b. b IN s /\ segment(a,b) INTER s = {}`,
15306   MESON_TAC[SEGMENT_TO_CLOSEST_POINT; CLOSEST_POINT_EXISTS]);;
15307
15308 let CLOSEST_POINT_IN_INTERIOR = prove
15309  (`!s x:real^N.
15310         closed s /\ ~(s = {})
15311         ==> ((closest_point s x) IN interior s <=> x IN interior s)`,
15312   REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THEN
15313   ASM_SIMP_TAC[CLOSEST_POINT_SELF] THEN
15314   MATCH_MP_TAC(TAUT `~q /\ ~p ==> (p <=> q)`) THEN
15315   CONJ_TAC THENL [ASM_MESON_TAC[INTERIOR_SUBSET; SUBSET]; STRIP_TAC] THEN
15316   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERIOR_CBALL]) THEN
15317   DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
15318   SUBGOAL_THEN `closest_point s (x:real^N) IN s` ASSUME_TAC THENL
15319    [ASM_MESON_TAC[INTERIOR_SUBSET; SUBSET]; ALL_TAC] THEN
15320   SUBGOAL_THEN `~(closest_point s (x:real^N) = x)` ASSUME_TAC THENL
15321    [ASM_MESON_TAC[]; ALL_TAC] THEN
15322   MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`;
15323    `closest_point s x -
15324     (min (&1) (e / norm(closest_point s x - x))) %
15325     (closest_point s x - x):real^N`]
15326     CLOSEST_POINT_LE) THEN
15327   ASM_REWRITE_TAC[dist; NOT_IMP; VECTOR_ARITH
15328    `x - (y - e % (y - x)):real^N = (&1 - e) % (x - y)`] THEN
15329   CONJ_TAC THENL
15330    [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN
15331     REWRITE_TAC[IN_CBALL; NORM_ARITH `dist(a:real^N,a - x) = norm x`] THEN
15332     REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM] THEN
15333     ASM_SIMP_TAC[GSYM REAL_LE_RDIV_EQ; NORM_POS_LT; VECTOR_SUB_EQ] THEN
15334     MATCH_MP_TAC(REAL_ARITH `&0 <= a ==> abs(min (&1) a) <= a`) THEN
15335     ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LE_DIV; NORM_POS_LE];
15336     REWRITE_TAC[NORM_MUL; REAL_ARITH
15337      `~(n <= a * n) <=> &0 < (&1 - a) * n`] THEN
15338     MATCH_MP_TAC REAL_LT_MUL THEN
15339     ASM_SIMP_TAC[NORM_POS_LT; VECTOR_SUB_EQ] THEN
15340     MATCH_MP_TAC(REAL_ARITH
15341      `&0 < e /\ e <= &1 ==> &0 < &1 - abs(&1 - e)`) THEN
15342     REWRITE_TAC[REAL_MIN_LE; REAL_LT_MIN; REAL_LT_01; REAL_LE_REFL] THEN
15343     ASM_SIMP_TAC[REAL_LT_DIV; NORM_POS_LT; VECTOR_SUB_EQ]]);;
15344
15345 let CLOSEST_POINT_IN_FRONTIER = prove
15346  (`!s x:real^N.
15347         closed s /\ ~(s = {}) /\ ~(x IN interior s)
15348         ==> (closest_point s x) IN frontier s`,
15349   SIMP_TAC[frontier; IN_DIFF; CLOSEST_POINT_IN_INTERIOR] THEN
15350   SIMP_TAC[CLOSEST_POINT_IN_SET; CLOSURE_CLOSED]);;
15351
15352 (* ------------------------------------------------------------------------- *)
15353 (* More general infimum of distance between two sets.                        *)
15354 (* ------------------------------------------------------------------------- *)
15355
15356 let setdist = new_definition
15357  `setdist(s,t) =
15358         if s = {} \/ t = {} then &0
15359         else inf {dist(x,y) | x IN s /\ y IN t}`;;
15360
15361 let SETDIST_EMPTY = prove
15362  (`(!t. setdist({},t) = &0) /\ (!s. setdist(s,{}) = &0)`,
15363   REWRITE_TAC[setdist]);;
15364
15365 let SETDIST_POS_LE = prove
15366  (`!s t. &0 <= setdist(s,t)`,
15367   REPEAT GEN_TAC THEN REWRITE_TAC[setdist] THEN
15368   COND_CASES_TAC THEN REWRITE_TAC[REAL_LE_REFL] THEN
15369   MATCH_MP_TAC REAL_LE_INF THEN
15370   REWRITE_TAC[FORALL_IN_GSPEC; DIST_POS_LE] THEN ASM SET_TAC[]);;
15371
15372 let REAL_LE_SETDIST = prove
15373   (`!s t:real^N->bool d.
15374         ~(s = {}) /\ ~(t = {}) /\
15375         (!x y. x IN s /\ y IN t ==> d <= dist(x,y))
15376         ==> d <= setdist(s,t)`,
15377   REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[setdist] THEN
15378   MP_TAC(ISPEC `{dist(x:real^N,y) | x IN s /\ y IN t}` INF) THEN
15379   REWRITE_TAC[FORALL_IN_GSPEC] THEN ANTS_TAC THENL
15380    [CONJ_TAC THENL [ASM SET_TAC[]; MESON_TAC[DIST_POS_LE]]; ALL_TAC] THEN
15381   ASM_MESON_TAC[]);;
15382
15383 let SETDIST_LE_DIST = prove
15384  (`!s t x y:real^N. x IN s /\ y IN t ==> setdist(s,t) <= dist(x,y)`,
15385   REPEAT GEN_TAC THEN REWRITE_TAC[setdist] THEN
15386   COND_CASES_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
15387   MP_TAC(ISPEC `{dist(x:real^N,y) | x IN s /\ y IN t}` INF) THEN
15388   REWRITE_TAC[FORALL_IN_GSPEC] THEN ANTS_TAC THENL
15389    [CONJ_TAC THENL [ASM SET_TAC[]; MESON_TAC[DIST_POS_LE]]; ALL_TAC] THEN
15390   ASM_MESON_TAC[]);;
15391
15392 let REAL_LE_SETDIST_EQ = prove
15393  (`!d s t:real^N->bool.
15394         d <= setdist(s,t) <=>
15395         (!x y. x IN s /\ y IN t ==> d <= dist(x,y)) /\
15396         (s = {} \/ t = {} ==> d <= &0)`,
15397   REPEAT GEN_TAC THEN MAP_EVERY ASM_CASES_TAC
15398    [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
15399   ASM_REWRITE_TAC[SETDIST_EMPTY; NOT_IN_EMPTY] THEN
15400   ASM_MESON_TAC[REAL_LE_SETDIST; SETDIST_LE_DIST; REAL_LE_TRANS]);;
15401
15402 let SETDIST_REFL = prove
15403  (`!s:real^N->bool. setdist(s,s) = &0`,
15404   GEN_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM; SETDIST_POS_LE] THEN
15405   ASM_CASES_TAC `s:real^N->bool = {}` THENL
15406    [ASM_REWRITE_TAC[setdist; REAL_LE_REFL]; ALL_TAC] THEN
15407   ASM_MESON_TAC[SETDIST_LE_DIST; MEMBER_NOT_EMPTY; DIST_REFL]);;
15408
15409 let SETDIST_SYM = prove
15410  (`!s t. setdist(s,t) = setdist(t,s)`,
15411   REPEAT GEN_TAC THEN REWRITE_TAC[setdist; DISJ_SYM] THEN
15412   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
15413   AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
15414   MESON_TAC[DIST_SYM]);;
15415
15416 let SETDIST_TRIANGLE = prove
15417  (`!s a t:real^N->bool.
15418         setdist(s,t) <= setdist(s,{a}) + setdist({a},t)`,
15419   REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN
15420   ASM_REWRITE_TAC[SETDIST_EMPTY; REAL_ADD_LID; SETDIST_POS_LE] THEN
15421   ASM_CASES_TAC `t:real^N->bool = {}` THEN
15422   ASM_REWRITE_TAC[SETDIST_EMPTY; REAL_ADD_RID; SETDIST_POS_LE] THEN
15423   ONCE_REWRITE_TAC[GSYM REAL_LE_SUB_RADD] THEN
15424   MATCH_MP_TAC REAL_LE_SETDIST THEN
15425   ASM_REWRITE_TAC[NOT_INSERT_EMPTY; IN_SING; IMP_CONJ;
15426                   RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2] THEN
15427   X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
15428   ONCE_REWRITE_TAC[REAL_ARITH `x - y <= z <=> x - z <= y`] THEN
15429   MATCH_MP_TAC REAL_LE_SETDIST THEN
15430   ASM_REWRITE_TAC[NOT_INSERT_EMPTY; IN_SING; IMP_CONJ;
15431                   RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2] THEN
15432   X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
15433   REWRITE_TAC[REAL_LE_SUB_RADD] THEN MATCH_MP_TAC REAL_LE_TRANS THEN
15434   EXISTS_TAC `dist(x:real^N,y)` THEN
15435   ASM_SIMP_TAC[SETDIST_LE_DIST] THEN CONV_TAC NORM_ARITH);;
15436
15437 let SETDIST_SINGS = prove
15438  (`!x y. setdist({x},{y}) = dist(x,y)`,
15439   REWRITE_TAC[setdist; NOT_INSERT_EMPTY] THEN
15440   REWRITE_TAC[SET_RULE `{f x y | x IN {a} /\ y IN {b}} = {f a b}`] THEN
15441   SIMP_TAC[INF_INSERT_FINITE; FINITE_EMPTY]);;
15442
15443 let SETDIST_LIPSCHITZ = prove
15444  (`!s t x y:real^N. abs(setdist({x},s) - setdist({y},s)) <= dist(x,y)`,
15445   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM SETDIST_SINGS] THEN
15446   REWRITE_TAC[REAL_ARITH
15447    `abs(x - y) <= z <=> x <= z + y /\ y <= z + x`] THEN
15448   MESON_TAC[SETDIST_TRIANGLE; SETDIST_SYM]);;
15449
15450 let CONTINUOUS_AT_LIFT_SETDIST = prove
15451  (`!s x:real^N. (\y. lift(setdist({y},s))) continuous (at x)`,
15452   REPEAT STRIP_TAC THEN REWRITE_TAC[continuous_at; DIST_LIFT] THEN
15453   ASM_MESON_TAC[SETDIST_LIPSCHITZ; REAL_LET_TRANS]);;
15454
15455 let CONTINUOUS_ON_LIFT_SETDIST = prove
15456  (`!s t:real^N->bool. (\y. lift(setdist({y},s))) continuous_on t`,
15457   MESON_TAC[CONTINUOUS_AT_IMP_CONTINUOUS_ON;
15458             CONTINUOUS_AT_LIFT_SETDIST]);;
15459
15460 let UNIFORMLY_CONTINUOUS_ON_LIFT_SETDIST = prove
15461  (`!s t:real^N->bool.
15462          (\y. lift(setdist({y},s))) uniformly_continuous_on t`,
15463   REPEAT GEN_TAC THEN REWRITE_TAC[uniformly_continuous_on; DIST_LIFT] THEN
15464   ASM_MESON_TAC[SETDIST_LIPSCHITZ; REAL_LET_TRANS]);;
15465
15466 let SETDIST_DIFFERENCES = prove
15467  (`!s t. setdist(s,t) = setdist({vec 0},{x - y:real^N | x IN s /\ y IN t})`,
15468   REPEAT GEN_TAC THEN REWRITE_TAC[setdist; NOT_INSERT_EMPTY;
15469      SET_RULE `{f x y | x IN s /\ y IN t} = {} <=> s = {} \/ t = {}`] THEN
15470   COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN
15471   REWRITE_TAC[EXTENSION; IN_ELIM_THM; IN_SING] THEN
15472   REWRITE_TAC[GSYM CONJ_ASSOC; RIGHT_EXISTS_AND_THM; UNWIND_THM2; DIST_0] THEN
15473   REWRITE_TAC[dist] THEN MESON_TAC[]);;
15474
15475 let SETDIST_SUBSET_RIGHT = prove
15476  (`!s t u:real^N->bool.
15477     ~(t = {}) /\ t SUBSET u ==> setdist(s,u) <= setdist(s,t)`,
15478   REPEAT STRIP_TAC THEN
15479   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `u:real^N->bool = {}`] THEN
15480   ASM_REWRITE_TAC[SETDIST_EMPTY; SETDIST_POS_LE; REAL_LE_REFL] THEN
15481   ASM_REWRITE_TAC[setdist] THEN MATCH_MP_TAC REAL_LE_INF_SUBSET THEN
15482   ASM_REWRITE_TAC[FORALL_IN_GSPEC; SUBSET] THEN
15483   REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
15484   MESON_TAC[DIST_POS_LE]);;
15485
15486 let SETDIST_SUBSET_LEFT = prove
15487  (`!s t u:real^N->bool.
15488     ~(s = {}) /\ s SUBSET t ==> setdist(t,u) <= setdist(s,u)`,
15489   MESON_TAC[SETDIST_SUBSET_RIGHT; SETDIST_SYM]);;
15490
15491 let SETDIST_CLOSURE = prove
15492  (`(!s t:real^N->bool. setdist(closure s,t) = setdist(s,t)) /\
15493    (!s t:real^N->bool. setdist(s,closure t) = setdist(s,t))`,
15494   GEN_REWRITE_TAC RAND_CONV [SWAP_FORALL_THM] THEN
15495   GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [SETDIST_SYM] THEN
15496   REWRITE_TAC[] THEN
15497   REWRITE_TAC[MESON[REAL_LE_ANTISYM]
15498    `x:real = y <=> !d. d <= x <=> d <= y`] THEN
15499   REPEAT GEN_TAC THEN REWRITE_TAC[REAL_LE_SETDIST_EQ] THEN
15500   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
15501   ASM_REWRITE_TAC[CLOSURE_EQ_EMPTY; CLOSURE_EMPTY; NOT_IN_EMPTY] THEN
15502   MATCH_MP_TAC(SET_RULE
15503    `s SUBSET c /\
15504     (!y. Q y /\ (!x. x IN s ==> P x y) ==> (!x. x IN c ==> P x y))
15505    ==> ((!x y. x IN c /\ Q y ==> P x y) <=>
15506         (!x y. x IN s /\ Q y ==> P x y))`) THEN
15507   REWRITE_TAC[CLOSURE_SUBSET] THEN GEN_TAC THEN STRIP_TAC THEN
15508   MATCH_MP_TAC CONTINUOUS_GE_ON_CLOSURE THEN
15509   ASM_REWRITE_TAC[o_DEF; dist] THEN
15510   MATCH_MP_TAC CONTINUOUS_ON_LIFT_NORM_COMPOSE THEN
15511   SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID]);;
15512
15513 let SETDIST_COMPACT_CLOSED = prove
15514  (`!s t:real^N->bool.
15515         compact s /\ closed t /\ ~(s = {}) /\ ~(t = {})
15516         ==> ?x y. x IN s /\ y IN t /\ dist(x,y) = setdist(s,t)`,
15517   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
15518   MATCH_MP_TAC(MESON[]
15519    `(!x y. P x /\ Q y ==> S x y) /\ (?x y. P x /\ Q y /\ R x y)
15520     ==> ?x y. P x /\ Q y /\ R x y /\ S x y`) THEN
15521   SIMP_TAC[SETDIST_LE_DIST] THEN
15522   ASM_REWRITE_TAC[REAL_LE_SETDIST_EQ] THEN
15523   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN t}`; `vec 0:real^N`]
15524         DISTANCE_ATTAINS_INF) THEN
15525   ASM_SIMP_TAC[COMPACT_CLOSED_DIFFERENCES; EXISTS_IN_GSPEC; FORALL_IN_GSPEC;
15526                DIST_0; GSYM CONJ_ASSOC] THEN
15527   REWRITE_TAC[dist] THEN DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]);;
15528
15529 let SETDIST_CLOSED_COMPACT = prove
15530  (`!s t:real^N->bool.
15531         closed s /\ compact t /\ ~(s = {}) /\ ~(t = {})
15532         ==> ?x y. x IN s /\ y IN t /\ dist(x,y) = setdist(s,t)`,
15533   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN
15534   MATCH_MP_TAC(MESON[]
15535    `(!x y. P x /\ Q y ==> S x y) /\ (?x y. P x /\ Q y /\ R x y)
15536     ==> ?x y. P x /\ Q y /\ R x y /\ S x y`) THEN
15537   SIMP_TAC[SETDIST_LE_DIST] THEN
15538   ASM_REWRITE_TAC[REAL_LE_SETDIST_EQ] THEN
15539   MP_TAC(ISPECL [`{x - y:real^N | x IN s /\ y IN t}`; `vec 0:real^N`]
15540         DISTANCE_ATTAINS_INF) THEN
15541   ASM_SIMP_TAC[CLOSED_COMPACT_DIFFERENCES; EXISTS_IN_GSPEC; FORALL_IN_GSPEC;
15542                DIST_0; GSYM CONJ_ASSOC] THEN
15543   REWRITE_TAC[dist] THEN DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]);;
15544
15545 let SETDIST_EQ_0_COMPACT_CLOSED = prove
15546  (`!s t:real^N->bool.
15547         compact s /\ closed t
15548         ==> (setdist(s,t) = &0 <=> s = {} \/ t = {} \/ ~(s INTER t = {}))`,
15549   REPEAT STRIP_TAC THEN
15550   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
15551   ASM_REWRITE_TAC[SETDIST_EMPTY] THEN EQ_TAC THENL
15552    [MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`]
15553       SETDIST_COMPACT_CLOSED) THEN ASM_REWRITE_TAC[] THEN
15554     REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN MESON_TAC[DIST_EQ_0];
15555     REWRITE_TAC[GSYM REAL_LE_ANTISYM; SETDIST_POS_LE] THEN
15556     REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN
15557     MESON_TAC[SETDIST_LE_DIST; DIST_EQ_0]]);;
15558
15559 let SETDIST_EQ_0_CLOSED_COMPACT = prove
15560  (`!s t:real^N->bool.
15561         closed s /\ compact t
15562         ==> (setdist(s,t) = &0 <=> s = {} \/ t = {} \/ ~(s INTER t = {}))`,
15563   ONCE_REWRITE_TAC[SETDIST_SYM] THEN
15564   SIMP_TAC[SETDIST_EQ_0_COMPACT_CLOSED] THEN SET_TAC[]);;
15565
15566 let SETDIST_EQ_0_BOUNDED = prove
15567  (`!s t:real^N->bool.
15568         (bounded s \/ bounded t)
15569         ==> (setdist(s,t) = &0 <=>
15570              s = {} \/ t = {} \/ ~(closure(s) INTER closure(t) = {}))`,
15571   REPEAT GEN_TAC THEN
15572   MAP_EVERY ASM_CASES_TAC [`s:real^N->bool = {}`; `t:real^N->bool = {}`] THEN
15573   ASM_REWRITE_TAC[SETDIST_EMPTY] THEN STRIP_TAC THEN
15574   ONCE_REWRITE_TAC[MESON[SETDIST_CLOSURE]
15575    `setdist(s,t) = setdist(closure s,closure t)`] THEN
15576   ASM_SIMP_TAC[SETDIST_EQ_0_COMPACT_CLOSED; SETDIST_EQ_0_CLOSED_COMPACT;
15577                COMPACT_CLOSURE; CLOSED_CLOSURE; CLOSURE_EQ_EMPTY]);;
15578
15579
15580 let SETDIST_TRANSLATION = prove
15581  (`!a:real^N s t.
15582         setdist(IMAGE (\x. a + x) s,IMAGE (\x. a + x) t) = setdist(s,t)`,
15583   REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[SETDIST_DIFFERENCES] THEN
15584   AP_TERM_TAC THEN AP_TERM_TAC THEN
15585   REWRITE_TAC[SET_RULE
15586    `{f x y | x IN IMAGE g s /\ y IN IMAGE g t} =
15587     {f (g x) (g y) | x IN s /\ y IN t}`] THEN
15588   REWRITE_TAC[VECTOR_ARITH `(a + x) - (a + y):real^N = x - y`]);;
15589
15590 add_translation_invariants [SETDIST_TRANSLATION];;
15591
15592 let SETDIST_LINEAR_IMAGE = prove
15593  (`!f:real^M->real^N s t.
15594         linear f /\ (!x. norm(f x) = norm x)
15595         ==> setdist(IMAGE f s,IMAGE f t) = setdist(s,t)`,
15596   REPEAT STRIP_TAC THEN REWRITE_TAC[setdist; IMAGE_EQ_EMPTY] THEN
15597   COND_CASES_TAC THEN ASM_REWRITE_TAC[dist] THEN AP_TERM_TAC THEN
15598   REWRITE_TAC[SET_RULE
15599    `{f x y | x IN IMAGE g s /\ y IN IMAGE g t} =
15600     {f (g x) (g y) | x IN s /\ y IN t}`] THEN
15601   FIRST_X_ASSUM(fun th -> REWRITE_TAC[GSYM(MATCH_MP LINEAR_SUB th)]) THEN
15602   ASM_REWRITE_TAC[]);;
15603
15604 add_linear_invariants [SETDIST_LINEAR_IMAGE];;
15605
15606 let SETDIST_UNIQUE = prove
15607  (`!s t a b:real^N d.
15608         a IN s /\ b IN t /\ dist(a,b) = d /\
15609         (!x y. x IN s /\ y IN t ==> dist(a,b) <= dist(x,y))
15610         ==> setdist(s,t) = d`,
15611   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN CONJ_TAC THENL
15612    [ASM_MESON_TAC[SETDIST_LE_DIST];
15613     MATCH_MP_TAC REAL_LE_SETDIST THEN ASM SET_TAC[]]);;
15614
15615 let SETDIST_CLOSEST_POINT = prove
15616  (`!a:real^N s.
15617       closed s /\ ~(s = {}) ==> setdist({a},s) = dist(a,closest_point s a)`,
15618   REPEAT STRIP_TAC THEN MATCH_MP_TAC SETDIST_UNIQUE THEN
15619   REWRITE_TAC[RIGHT_EXISTS_AND_THM; IN_SING; UNWIND_THM2] THEN
15620   EXISTS_TAC `closest_point s (a:real^N)` THEN
15621   ASM_MESON_TAC[CLOSEST_POINT_EXISTS; DIST_SYM]);;
15622
15623 let SETDIST_EQ_0_SING = prove
15624  (`(!s x:real^N. setdist({x},s) = &0 <=> s = {} \/ x IN closure s) /\
15625    (!s x:real^N. setdist(s,{x}) = &0 <=> s = {} \/ x IN closure s)`,
15626   SIMP_TAC[SETDIST_EQ_0_BOUNDED; BOUNDED_SING; CLOSURE_SING] THEN SET_TAC[]);;
15627
15628 (* ------------------------------------------------------------------------- *)
15629 (* Use set distance for an easy proof of separation properties.              *)
15630 (* ------------------------------------------------------------------------- *)
15631
15632 let SEPARATION_CLOSURES = prove
15633  (`!s t:real^N->bool.
15634         s INTER closure(t) = {} /\ t INTER closure(s) = {}
15635         ==> ?u v. DISJOINT u v /\ open u /\ open v /\
15636                   s SUBSET u /\ t SUBSET v`,
15637   REPEAT STRIP_TAC THEN
15638   ASM_CASES_TAC `s:real^N->bool = {}` THENL
15639    [MAP_EVERY EXISTS_TAC [`{}:real^N->bool`; `(:real^N)`] THEN
15640     ASM_REWRITE_TAC[OPEN_EMPTY; OPEN_UNIV] THEN ASM SET_TAC[];
15641     ALL_TAC] THEN
15642   ASM_CASES_TAC `t:real^N->bool = {}` THENL
15643    [MAP_EVERY EXISTS_TAC [`(:real^N)`; `{}:real^N->bool`] THEN
15644     ASM_REWRITE_TAC[OPEN_EMPTY; OPEN_UNIV] THEN ASM SET_TAC[];
15645     ALL_TAC] THEN
15646   EXISTS_TAC `{x | x IN (:real^N) /\
15647                    lift(setdist({x},t) - setdist({x},s)) IN
15648                    {x | &0 < x$1}}` THEN
15649   EXISTS_TAC `{x | x IN (:real^N) /\
15650                    lift(setdist({x},t) - setdist({x},s)) IN
15651                    {x | x$1 < &0}}` THEN
15652   REPEAT CONJ_TAC THENL
15653    [REWRITE_TAC[SET_RULE `DISJOINT s t <=> !x. x IN s /\ x IN t ==> F`] THEN
15654     REWRITE_TAC[IN_ELIM_THM; IN_UNIV] THEN REAL_ARITH_TAC;
15655     MATCH_MP_TAC CONTINUOUS_OPEN_PREIMAGE THEN
15656     SIMP_TAC[REWRITE_RULE[real_gt] OPEN_HALFSPACE_COMPONENT_GT; OPEN_UNIV] THEN
15657     SIMP_TAC[LIFT_SUB; CONTINUOUS_ON_SUB; CONTINUOUS_ON_LIFT_SETDIST];
15658     MATCH_MP_TAC CONTINUOUS_OPEN_PREIMAGE THEN
15659     SIMP_TAC[OPEN_HALFSPACE_COMPONENT_LT; OPEN_UNIV] THEN
15660     SIMP_TAC[LIFT_SUB; CONTINUOUS_ON_SUB; CONTINUOUS_ON_LIFT_SETDIST];
15661     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNIV; GSYM drop; LIFT_DROP] THEN
15662     GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC(REAL_ARITH
15663      `&0 <= x /\ y = &0 /\ ~(x = &0) ==> &0 < x - y`);
15664     REWRITE_TAC[SUBSET; IN_ELIM_THM; IN_UNIV; GSYM drop; LIFT_DROP] THEN
15665     GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC(REAL_ARITH
15666      `&0 <= y /\ x = &0 /\ ~(y = &0) ==> x - y < &0`)] THEN
15667   ASM_SIMP_TAC[SETDIST_POS_LE; SETDIST_EQ_0_BOUNDED; BOUNDED_SING] THEN
15668   ASM_SIMP_TAC[CLOSED_SING; CLOSURE_CLOSED; NOT_INSERT_EMPTY;
15669                REWRITE_RULE[SUBSET] CLOSURE_SUBSET;
15670                SET_RULE `{a} INTER s = {} <=> ~(a IN s)`] THEN
15671   ASM SET_TAC[]);;
15672
15673 let SEPARATION_NORMAL = prove
15674  (`!s t:real^N->bool.
15675         closed s /\ closed t /\ s INTER t = {}
15676         ==> ?u v. open u /\ open v /\
15677                   s SUBSET u /\ t SUBSET v /\ u INTER v = {}`,
15678   REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM DISJOINT] THEN
15679   ONCE_REWRITE_TAC[TAUT
15680     `a /\ b /\ c /\ d /\ e <=> e /\ a /\ b /\ c /\ d`] THEN
15681   MATCH_MP_TAC SEPARATION_CLOSURES THEN
15682   ASM_SIMP_TAC[CLOSURE_CLOSED] THEN ASM SET_TAC[]);;
15683
15684 let SEPARATION_NORMAL_COMPACT = prove
15685  (`!s t:real^N->bool.
15686         compact s /\ closed t /\ s INTER t = {}
15687         ==> ?u v. open u /\ compact(closure u) /\ open v /\
15688                   s SUBSET u /\ t SUBSET v /\ u INTER v = {}`,
15689   REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED; CLOSED_CLOSURE] THEN
15690   REPEAT STRIP_TAC THEN FIRST_ASSUM
15691    (MP_TAC o SPEC `vec 0:real^N` o MATCH_MP BOUNDED_SUBSET_BALL) THEN
15692   DISCH_THEN(X_CHOOSE_THEN `r:real` STRIP_ASSUME_TAC) THEN
15693   MP_TAC(ISPECL [`s:real^N->bool`; `t UNION ((:real^N) DIFF ball(vec 0,r))`]
15694         SEPARATION_NORMAL) THEN
15695   ASM_SIMP_TAC[CLOSED_UNION; GSYM OPEN_CLOSED; OPEN_BALL] THEN
15696   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
15697   REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
15698   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
15699   CONJ_TAC THENL [MATCH_MP_TAC BOUNDED_CLOSURE; ASM SET_TAC[]] THEN
15700   MATCH_MP_TAC BOUNDED_SUBSET THEN EXISTS_TAC `ball(vec 0:real^N,r)` THEN
15701   REWRITE_TAC[BOUNDED_BALL] THEN ASM SET_TAC[]);;
15702
15703 let SEPARATION_HAUSDORFF = prove
15704  (`!x:real^N y.
15705       ~(x = y)
15706       ==> ?u v. open u /\ open v /\ x IN u /\ y IN v /\ (u INTER v = {})`,
15707   REPEAT STRIP_TAC THEN
15708   MP_TAC(SPECL [`{x:real^N}`; `{y:real^N}`] SEPARATION_NORMAL) THEN
15709   REWRITE_TAC[SING_SUBSET; CLOSED_SING] THEN
15710   DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]);;
15711
15712 let SEPARATION_T2 = prove
15713  (`!x:real^N y.
15714         ~(x = y) <=> ?u v. open u /\ open v /\ x IN u /\ y IN v /\
15715                            (u INTER v = {})`,
15716   REPEAT STRIP_TAC THEN EQ_TAC THEN ASM_SIMP_TAC[SEPARATION_HAUSDORFF] THEN
15717   REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN MESON_TAC[]);;
15718
15719 let SEPARATION_T1 = prove
15720  (`!x:real^N y.
15721         ~(x = y) <=> ?u v. open u /\ open v /\ x IN u /\ ~(y IN u) /\
15722                            ~(x IN v) /\ y IN v`,
15723   REPEAT STRIP_TAC THEN EQ_TAC THENL
15724    [ASM_SIMP_TAC[SEPARATION_T2; EXTENSION; NOT_IN_EMPTY; IN_INTER];
15725     ALL_TAC] THEN MESON_TAC[]);;
15726
15727 let SEPARATION_T0 = prove
15728  (`!x:real^N y. ~(x = y) <=> ?u. open u /\ ~(x IN u <=> y IN u)`,
15729   MESON_TAC[SEPARATION_T1]);;
15730
15731 let CLOSED_COMPACT_PROJECTION = prove
15732  (`!s:real^M->bool t:real^(M,N)finite_sum->bool.
15733         compact s /\ closed t
15734         ==> closed {y | ?x. x IN s /\ (pastecart x y) IN t}`,
15735   REPEAT STRIP_TAC THEN
15736   ASM_CASES_TAC `s:real^M->bool = {}` THEN
15737   ASM_CASES_TAC `t:real^(M,N)finite_sum->bool = {}` THEN
15738   ASM_REWRITE_TAC[NOT_IN_EMPTY; EMPTY_GSPEC; CLOSED_EMPTY] THEN
15739   REWRITE_TAC[closed; open_def; IN_DIFF; IN_UNIV; IN_ELIM_THM] THEN
15740   X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN
15741   EXISTS_TAC `setdist({pastecart (x:real^M) (y:real^N) | x IN s},t)` THEN
15742   CONJ_TAC THENL
15743    [REWRITE_TAC[REAL_LT_LE; SETDIST_POS_LE] THEN
15744     ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN
15745     W(MP_TAC o PART_MATCH (lhs o rand) SETDIST_EQ_0_COMPACT_CLOSED o
15746       rand o snd) THEN
15747     ANTS_TAC THENL
15748      [REWRITE_TAC[SET_RULE
15749        `{pastecart x y | P x} = {pastecart x z | P x /\ z IN {y}}`] THEN
15750       REWRITE_TAC[GSYM PCROSS] THEN
15751       ASM_SIMP_TAC[COMPACT_PCROSS; COMPACT_SING];
15752       DISCH_THEN SUBST1_TAC THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[]];
15753     X_GEN_TAC `z:real^N` THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
15754     REWRITE_TAC[REAL_NOT_LT] THEN
15755     DISCH_THEN(X_CHOOSE_THEN `w:real^M` STRIP_ASSUME_TAC) THEN
15756     MATCH_MP_TAC REAL_LE_TRANS THEN
15757     EXISTS_TAC `dist(pastecart (w:real^M) (y:real^N),pastecart w z)` THEN
15758     CONJ_TAC THENL
15759      [MATCH_MP_TAC SETDIST_LE_DIST THEN ASM SET_TAC[];
15760       REWRITE_TAC[DIST_PASTECART_CANCEL; REAL_LE_REFL; DIST_SYM]]]);;
15761
15762 let CLOSED_IN_COMPACT_PROJECTION = prove
15763  (`!s:real^M->bool t:real^N->bool u.
15764     compact s /\
15765     closed_in (subtopology euclidean (s PCROSS t)) u
15766     ==> closed_in (subtopology euclidean t)
15767           {y | ?x. x IN s /\ pastecart x y IN u}`,
15768   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS; CLOSED_IN_CLOSED] THEN
15769   REWRITE_TAC[RIGHT_AND_EXISTS_THM; CONJ_ASSOC] THEN
15770   DISCH_THEN(CHOOSE_THEN(CONJUNCTS_THEN2 MP_TAC SUBST1_TAC)) THEN
15771   DISCH_THEN(MP_TAC o MATCH_MP CLOSED_COMPACT_PROJECTION) THEN
15772   MATCH_MP_TAC(MESON[]
15773    `P p==> (closed p ==> ?t. closed t /\ P t)`) THEN
15774   REWRITE_TAC[IN_ELIM_PASTECART_THM; IN_INTER] THEN SET_TAC[]);;
15775
15776 let TUBE_LEMMA = prove
15777  (`!s:real^M->bool t:real^N->bool u a.
15778         compact s /\ ~(s = {}) /\ {pastecart x a | x IN s} SUBSET u /\
15779         open_in(subtopology euclidean (s PCROSS t)) u
15780         ==> ?v. open_in (subtopology euclidean t) v /\ a IN v /\
15781                 (s PCROSS v) SUBSET u`,
15782   REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS] THEN
15783   REWRITE_TAC[OPEN_IN_CLOSED_IN_EQ] THEN
15784   REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
15785   REPEAT STRIP_TAC THEN
15786   FIRST_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT; PCROSS]
15787         CLOSED_IN_COMPACT_PROJECTION)) THEN
15788   ASM_REWRITE_TAC[IN_ELIM_PASTECART_THM; IN_DIFF] THEN
15789   REWRITE_TAC[GSYM CONJ_ASSOC] THEN MATCH_MP_TAC(MESON[]
15790    `(closed_in top t ==> s DIFF (s DIFF t) = t) /\
15791     s DIFF t SUBSET s /\ P(s DIFF t)
15792     ==> closed_in top t
15793         ==> ?v. v SUBSET s /\ closed_in top (s DIFF v) /\ P v`) THEN
15794   REWRITE_TAC[SET_RULE `s DIFF (s DIFF t) = t <=> t SUBSET s`] THEN
15795   REWRITE_TAC[SUBSET_DIFF] THEN
15796   SIMP_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN
15797   REWRITE_TAC[IN_DIFF; IN_ELIM_THM] THEN
15798   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC] THEN
15799   CONJ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
15800   REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [SUBSET])) THEN
15801   REWRITE_TAC[FORALL_IN_GSPEC; IN_SING; FORALL_PASTECART] THEN
15802   REWRITE_TAC[IN_ELIM_PASTECART_THM] THEN ASM_MESON_TAC[MEMBER_NOT_EMPTY]);;
15803
15804 (* ------------------------------------------------------------------------- *)
15805 (* Urysohn's lemma (for real^N, where the proof is easy using distances).    *)
15806 (* ------------------------------------------------------------------------- *)
15807
15808 let URYSOHN_LOCAL_STRONG = prove
15809  (`!s t u a b.
15810         closed_in (subtopology euclidean u) s /\
15811         closed_in (subtopology euclidean u) t /\
15812         s INTER t = {} /\ ~(a = b)
15813         ==> ?f:real^N->real^M.
15814                f continuous_on u /\
15815                (!x. x IN u ==> f(x) IN segment[a,b]) /\
15816                (!x. x IN u ==> (f x = a <=> x IN s)) /\
15817                (!x. x IN u ==> (f x = b <=> x IN t))`,
15818   let lemma = prove
15819    (`!s t u a b.
15820           closed_in (subtopology euclidean u) s /\
15821           closed_in (subtopology euclidean u) t /\
15822           s INTER t = {} /\ ~(s = {}) /\ ~(t = {}) /\ ~(a = b)
15823           ==> ?f:real^N->real^M.
15824                  f continuous_on u /\
15825                  (!x. x IN u ==> f(x) IN segment[a,b]) /\
15826                  (!x. x IN u ==> (f x = a <=> x IN s)) /\
15827                  (!x. x IN u ==> (f x = b <=> x IN t))`,
15828     REPEAT STRIP_TAC THEN EXISTS_TAC
15829       `\x:real^N. a + setdist({x},s) / (setdist({x},s) + setdist({x},t)) %
15830                       (b - a:real^M)` THEN REWRITE_TAC[] THEN
15831     SUBGOAL_THEN
15832      `(!x:real^N. x IN u ==> (setdist({x},s) = &0 <=> x IN s)) /\
15833       (!x:real^N. x IN u ==> (setdist({x},t) = &0 <=> x IN t))`
15834     STRIP_ASSUME_TAC THENL
15835      [ASM_REWRITE_TAC[SETDIST_EQ_0_SING] THEN CONJ_TAC THENL
15836        [MP_TAC(ISPEC `s:real^N->bool` CLOSED_IN_CLOSED);
15837         MP_TAC(ISPEC `t:real^N->bool` CLOSED_IN_CLOSED)] THEN
15838       DISCH_THEN(MP_TAC o SPEC `u:real^N->bool`) THEN
15839       ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool`
15840        (CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC)) THEN
15841       ASM_MESON_TAC[CLOSURE_CLOSED; INTER_SUBSET; SUBSET_CLOSURE; SUBSET;
15842                     IN_INTER; CLOSURE_SUBSET];
15843       ALL_TAC] THEN
15844     SUBGOAL_THEN `!x:real^N. x IN u ==> &0 < setdist({x},s) + setdist({x},t)`
15845     ASSUME_TAC THENL
15846      [REPEAT STRIP_TAC THEN MATCH_MP_TAC(REAL_ARITH
15847         `&0 <= x /\ &0 <= y /\ ~(x = &0 /\ y = &0) ==> &0 < x + y`) THEN
15848       REWRITE_TAC[SETDIST_POS_LE] THEN ASM SET_TAC[];
15849       ALL_TAC] THEN
15850     REPEAT CONJ_TAC THENL
15851      [MATCH_MP_TAC CONTINUOUS_ON_ADD THEN REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
15852       REWRITE_TAC[real_div; GSYM VECTOR_MUL_ASSOC] THEN
15853       REPEAT(MATCH_MP_TAC CONTINUOUS_ON_MUL THEN CONJ_TAC) THEN
15854       REWRITE_TAC[CONTINUOUS_ON_CONST; o_DEF] THEN
15855       REWRITE_TAC[CONTINUOUS_ON_LIFT_SETDIST] THEN
15856       MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_INV) THEN
15857       ASM_SIMP_TAC[REAL_LT_IMP_NZ] THEN
15858       REWRITE_TAC[LIFT_ADD] THEN MATCH_MP_TAC CONTINUOUS_ON_ADD THEN
15859       REWRITE_TAC[CONTINUOUS_ON_LIFT_SETDIST];
15860       X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
15861       REWRITE_TAC[segment; IN_ELIM_THM] THEN
15862       REWRITE_TAC[VECTOR_MUL_EQ_0; LEFT_OR_DISTRIB; VECTOR_ARITH
15863        `a + x % (b - a):real^N = (&1 - u) % a + u % b <=>
15864         (x - u) % (b - a) = vec 0`;
15865        EXISTS_OR_THM] THEN
15866       DISJ1_TAC THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
15867       REWRITE_TAC[REAL_SUB_0; UNWIND_THM1] THEN
15868       ASM_SIMP_TAC[REAL_LE_DIV; REAL_LE_ADD; SETDIST_POS_LE; REAL_LE_LDIV_EQ;
15869                    REAL_ARITH `a <= &1 * (a + b) <=> &0 <= b`];
15870       REWRITE_TAC[VECTOR_ARITH `a + x:real^N = a <=> x = vec 0`];
15871       REWRITE_TAC[VECTOR_ARITH `a + x % (b - a):real^N = b <=>
15872                                 (x - &1) % (b - a) = vec 0`]] THEN
15873     ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ] THEN
15874     ASM_SIMP_TAC[REAL_SUB_0; REAL_EQ_LDIV_EQ;
15875                  REAL_MUL_LZERO; REAL_MUL_LID] THEN
15876     REWRITE_TAC[REAL_ARITH `x:real = x + y <=> y = &0`] THEN
15877     ASM_REWRITE_TAC[]) in
15878   MATCH_MP_TAC(MESON[]
15879    `(!s t. P s t <=> P t s) /\
15880     (!s t. ~(s = {}) /\ ~(t = {}) ==> P s t) /\
15881     P {} {} /\ (!t. ~(t = {}) ==> P {} t)
15882     ==> !s t. P s t`) THEN
15883   REPEAT CONJ_TAC THENL
15884    [REPEAT GEN_TAC THEN
15885     GEN_REWRITE_TAC (RAND_CONV o BINDER_CONV) [SWAP_FORALL_THM] THEN
15886     REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN
15887     REWRITE_TAC[SEGMENT_SYM; INTER_COMM; CONJ_ACI; EQ_SYM_EQ];
15888     SIMP_TAC[lemma];
15889     REPEAT STRIP_TAC THEN EXISTS_TAC `(\x. midpoint(a,b)):real^N->real^M` THEN
15890     ASM_SIMP_TAC[NOT_IN_EMPTY; CONTINUOUS_ON_CONST; MIDPOINT_IN_SEGMENT] THEN
15891     REWRITE_TAC[midpoint] THEN CONJ_TAC THEN GEN_TAC THEN DISCH_TAC THEN
15892     UNDISCH_TAC `~(a:real^M = b)` THEN REWRITE_TAC[CONTRAPOS_THM] THEN
15893     VECTOR_ARITH_TAC;
15894     REPEAT STRIP_TAC THEN ASM_CASES_TAC `t:real^N->bool = u` THENL
15895      [EXISTS_TAC `(\x. b):real^N->real^M` THEN
15896       ASM_REWRITE_TAC[NOT_IN_EMPTY; ENDS_IN_SEGMENT; IN_UNIV;
15897                       CONTINUOUS_ON_CONST];
15898       SUBGOAL_THEN `?c:real^N. c IN u /\ ~(c IN t)` STRIP_ASSUME_TAC THENL
15899        [REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET)) THEN
15900         REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN ASM SET_TAC[];
15901         ALL_TAC] THEN
15902       MP_TAC(ISPECL [`{c:real^N}`; `t:real^N->bool`; `u:real^N->bool`;
15903                      `midpoint(a,b):real^M`; `b:real^M`] lemma) THEN
15904       ASM_REWRITE_TAC[CLOSED_IN_SING; MIDPOINT_EQ_ENDPOINT] THEN
15905       ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
15906       MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[NOT_IN_EMPTY] THEN
15907       X_GEN_TAC `f:real^N->real^M` THEN STRIP_TAC THEN CONJ_TAC THENL
15908        [SUBGOAL_THEN
15909          `segment[midpoint(a,b):real^M,b] SUBSET segment[a,b]` MP_TAC
15910         THENL
15911          [REWRITE_TAC[SUBSET; IN_SEGMENT; midpoint] THEN GEN_TAC THEN
15912           DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN
15913           EXISTS_TAC `(&1 + u) / &2` THEN ASM_REWRITE_TAC[] THEN
15914           REPEAT(CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN
15915           VECTOR_ARITH_TAC;
15916           ASM SET_TAC[]];
15917         SUBGOAL_THEN `~(a IN segment[midpoint(a,b):real^M,b])` MP_TAC THENL
15918          [ALL_TAC; ASM_MESON_TAC[]] THEN
15919         DISCH_THEN(MP_TAC o CONJUNCT2 o MATCH_MP DIST_IN_CLOSED_SEGMENT) THEN
15920         REWRITE_TAC[DIST_MIDPOINT] THEN
15921         UNDISCH_TAC `~(a:real^M = b)` THEN NORM_ARITH_TAC]]]);;
15922
15923 let URYSOHN_LOCAL = prove
15924  (`!s t u a b.
15925         closed_in (subtopology euclidean u) s /\
15926         closed_in (subtopology euclidean u) t /\
15927         s INTER t = {}
15928         ==> ?f:real^N->real^M.
15929                f continuous_on u /\
15930                (!x. x IN u ==> f(x) IN segment[a,b]) /\
15931                (!x. x IN s ==> f x = a) /\
15932                (!x. x IN t ==> f x = b)`,
15933   REPEAT STRIP_TAC THEN ASM_CASES_TAC `a:real^M = b` THENL
15934    [EXISTS_TAC `(\x. b):real^N->real^M` THEN
15935     ASM_REWRITE_TAC[ENDS_IN_SEGMENT; CONTINUOUS_ON_CONST];
15936     MP_TAC(ISPECL [`s:real^N->bool`; `t:real^N->bool`; `u:real^N->bool`;
15937                    `a:real^M`; `b:real^M`] URYSOHN_LOCAL_STRONG) THEN
15938     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[] THEN
15939     REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_SUBSET)) THEN
15940     REWRITE_TAC[TOPSPACE_EUCLIDEAN_SUBTOPOLOGY] THEN SET_TAC[]]);;
15941
15942 let URYSOHN_STRONG = prove
15943  (`!s t a b.
15944         closed s /\ closed t /\ s INTER t = {} /\ ~(a = b)
15945         ==> ?f:real^N->real^M.
15946                f continuous_on (:real^N) /\ (!x. f(x) IN segment[a,b]) /\
15947                (!x. f x = a <=> x IN s) /\ (!x. f x = b <=> x IN t)`,
15948   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN] THEN
15949   ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_UNIV] THEN
15950   DISCH_THEN(MP_TAC o MATCH_MP URYSOHN_LOCAL_STRONG) THEN
15951   REWRITE_TAC[IN_UNIV]);;
15952
15953 let URYSOHN = prove
15954  (`!s t a b.
15955         closed s /\ closed t /\ s INTER t = {}
15956         ==> ?f:real^N->real^M.
15957                f continuous_on (:real^N) /\ (!x. f(x) IN segment[a,b]) /\
15958                (!x. x IN s ==> f x = a) /\ (!x. x IN t ==> f x = b)`,
15959   REPEAT GEN_TAC THEN REWRITE_TAC[CLOSED_IN] THEN
15960   ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_UNIV] THEN DISCH_THEN
15961    (MP_TAC o ISPECL [`a:real^M`; `b:real^M`] o MATCH_MP URYSOHN_LOCAL) THEN
15962   REWRITE_TAC[IN_UNIV]);;
15963
15964 (* ------------------------------------------------------------------------- *)
15965 (* Tietze extension theorem, likewise just for real^N.                       *)
15966 (* ------------------------------------------------------------------------- *)
15967
15968 let TIETZE_STEP = prove
15969  (`!f:real^N->real^1 u s B.
15970         &0 < B /\ closed_in (subtopology euclidean u) s /\
15971         f continuous_on s /\
15972         (!x. x IN s ==> norm(f x) <= B)
15973         ==> ?g. g continuous_on u /\
15974                 (!x. x IN u ==> norm(g x) <= B / &3) /\
15975                 (!x. x IN s ==> norm(f x - g x) <= &2 / &3 * B)`,
15976   REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB] THEN REPEAT STRIP_TAC THEN
15977   MP_TAC(ISPECL [`{x:real^N | x IN s /\ f x IN {y | drop y <= --(B / &3)}}`;
15978                  `{x:real^N | x IN s /\ f x IN {y | drop y >= B / &3}}`;
15979                  `u:real^N->bool`;
15980                  `lift(--(B / &3))`; `lift(B / &3)`] URYSOHN_LOCAL) THEN
15981   ANTS_TAC THENL
15982    [REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL
15983      [ALL_TAC;
15984       REWRITE_TAC[EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY; IN_INTER] THEN
15985       ASM_REAL_ARITH_TAC] THEN
15986     CONJ_TAC THEN MATCH_MP_TAC CLOSED_IN_TRANS THEN
15987     EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN
15988     MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
15989     ASM_REWRITE_TAC[] THENL
15990      [MP_TAC(ISPECL [`lift(&1)`; `--(B / &3)`] CLOSED_HALFSPACE_LE);
15991       MP_TAC(ISPECL [`lift(&1)`; `B / &3`] CLOSED_HALFSPACE_GE)] THEN
15992     REWRITE_TAC[DOT_1; GSYM drop; LIFT_DROP; REAL_MUL_LID];
15993     ASM_SIMP_TAC[SEGMENT_1; IN_ELIM_THM; LIFT_DROP; IN_INTERVAL_1;
15994                  REAL_ARITH `&0 < B ==> --(B / &3) <= B / &3`] THEN
15995     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^N->real^1` THEN
15996     STRIP_TAC THEN ASM_REWRITE_TAC[NORM_REAL; GSYM drop] THEN
15997     ASM_SIMP_TAC[GSYM REAL_BOUNDS_LE] THEN X_GEN_TAC `x:real^N` THEN
15998     DISCH_TAC THEN REWRITE_TAC[DROP_SUB; REAL_BOUNDS_LE] THEN
15999     FIRST_ASSUM(ASSUME_TAC o REWRITE_RULE[SUBSET] o MATCH_MP
16000       CLOSED_IN_IMP_SUBSET) THEN
16001     REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC
16002      (REAL_ARITH `drop(f x) <= --(B / &3) \/ drop(f x) >= B / &3 \/
16003                   abs(drop(f(x:real^N))) <= B / &3`)
16004     THENL
16005      [UNDISCH_THEN
16006        `!x:real^N. x IN s /\ drop(f x) <= --(B / &3) ==> g x = lift(--(B / &3))`
16007        (MP_TAC o SPEC `x:real^N`);
16008       UNDISCH_THEN
16009        `!x:real^N. x IN s /\ drop(f x) >= B / &3 ==> g x = lift(B / &3)`
16010        (MP_TAC o SPEC `x:real^N`);
16011       MATCH_MP_TAC(REAL_ARITH
16012        `abs(f) <= B / &3 /\ --(B / &3) <= g /\ g <= B / &3
16013         ==> abs(f - g) <= &2 / &3 * B`)] THEN
16014     ASM_SIMP_TAC[] THEN DISCH_THEN SUBST_ALL_TAC THEN
16015     UNDISCH_THEN `!x:real^N. x IN s ==> abs(drop(f x)) <= B`
16016         (MP_TAC o SPEC `x:real^N`) THEN
16017     ASM_REWRITE_TAC[LIFT_DROP] THEN ASM_REAL_ARITH_TAC]);;
16018
16019 let TIETZE = prove
16020  (`!f:real^N->real^1 u s B.
16021         &0 <= B /\
16022         closed_in (subtopology euclidean u) s /\
16023         f continuous_on s /\
16024         (!x. x IN s ==> norm(f x) <= B)
16025         ==> ?g. g continuous_on u /\
16026                 (!x. x IN s ==> g x = f x) /\
16027                 (!x. x IN u ==> norm(g x) <= B)`,
16028   REPEAT STRIP_TAC THEN
16029   FIRST_ASSUM(ASSUME_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
16030   FIRST_X_ASSUM(MP_TAC o MATCH_MP (REAL_ARITH
16031    `&0 <= B ==> B = &0 \/ &0 < B`)) THEN
16032   DISCH_THEN(DISJ_CASES_THEN2 SUBST_ALL_TAC ASSUME_TAC) THENL
16033    [EXISTS_TAC `\x:real^N. (vec 0:real^1)` THEN
16034     ASM_SIMP_TAC[CONTINUOUS_ON_CONST; NORM_0; REAL_LE_REFL] THEN
16035     ASM_MESON_TAC[NORM_LE_0];
16036     ALL_TAC] THEN
16037   MP_TAC(ISPECL [`f:real^N->real^1`; `u:real^N->bool`;
16038        `s:real^N->bool`; `B:real`]
16039         TIETZE_STEP) THEN
16040   ASM_REWRITE_TAC[] THEN
16041   DISCH_THEN(X_CHOOSE_THEN `g0:real^N->real^1` STRIP_ASSUME_TAC) THEN
16042   SUBGOAL_THEN
16043    `?g. (g 0 = (g0:real^N->real^1)) /\
16044         (!n. g(SUC n) =
16045                @h. h continuous_on u /\
16046                    (!x. x IN u ==>
16047                         norm(h x) <= &2 pow SUC n * B / &3 pow (SUC n + 1)) /\
16048                    (!x. x IN s ==> norm(f x - vsum(0..n) (\i. g i x) - h x)
16049                        <= &2 pow (SUC n + 1) * B / &3 pow (SUC n + 1)))`
16050   STRIP_ASSUME_TAC THENL
16051    [SIMP_TAC[VSUM_REAL; FINITE_NUMSEG; o_DEF] THEN
16052     W(ACCEPT_TAC o prove_general_recursive_function_exists o snd);
16053     ALL_TAC] THEN
16054   SUBGOAL_THEN
16055    `!n. (!m. m < n ==> g m continuous_on u) /\
16056         g n continuous_on u /\
16057         (!x. x IN u ==> norm(g n x:real^1) <= &2 pow n * B / &3 pow (n + 1)) /\
16058         (!x:real^N. x IN s ==> norm(f x - vsum(0..n) (\i. g i x))
16059         <= &2 pow (n + 1) * B / &3 pow (n + 1))`
16060   ASSUME_TAC THENL
16061    [INDUCT_TAC THEN ASM_REWRITE_TAC[VSUM_CLAUSES_NUMSEG; LT] THENL
16062      [CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
16063       ASM_REWRITE_TAC[REAL_MUL_LID; REAL_ARITH `&2 * B / &3 = &2 / &3 * B`];
16064       ALL_TAC] THEN
16065     ASM_REWRITE_TAC[MESON[] `(!m:num. m = n \/ m < n ==> P m) <=>
16066                              (!m. m < n ==> P m) /\ P n`] THEN
16067     REWRITE_TAC[LE_0; VECTOR_ARITH `f - (g + h):real^1 = f - g - h`] THEN
16068     CONV_TAC SELECT_CONV THEN
16069     REWRITE_TAC[REAL_POW_ADD; REAL_ARITH
16070      `(&2 pow (SUC n) * &2 pow 1) * B = &2 * &2 pow (SUC n) * B`] THEN
16071     REWRITE_TAC[real_div; REAL_INV_MUL; REAL_POW_1] THEN
16072     REWRITE_TAC[REAL_ARITH `a * b * inv c * inv d = (a * b / c) / d`] THEN
16073     REWRITE_TAC[REAL_ARITH `&2 * x / &3 = &2 / &3 * x`] THEN
16074     MATCH_MP_TAC TIETZE_STEP THEN
16075     ASM_SIMP_TAC[REAL_LT_DIV; ADD1; REAL_LT_MUL; REAL_POW_LT;
16076                  REAL_OF_NUM_LT; ARITH] THEN
16077     MATCH_MP_TAC CONTINUOUS_ON_SUB THEN ASM_REWRITE_TAC[ETA_AX] THEN
16078     MATCH_MP_TAC CONTINUOUS_ON_VSUM THEN
16079     REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG; LE_0] THEN REWRITE_TAC[LE_LT] THEN
16080     GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
16081     EXISTS_TAC `u:real^N->bool` THEN ASM_SIMP_TAC[];
16082     ALL_TAC] THEN
16083   ABBREV_TAC `(h:num->real^N->real^1) = \n x. vsum(0..n) (\i. g i x)` THEN
16084   SUBGOAL_THEN
16085    `?k:real^N->real^1.
16086      !e. &0 < e
16087          ==> ?N:num. !n x.
16088                  N <= n /\ x IN u ==> dist(vsum (from 0 INTER (0..n))
16089                                                   (\i. g i x),k x) < e`
16090   MP_TAC THENL
16091    [REWRITE_TAC[SERIES_CAUCHY_UNIFORM]; ALL_TAC] THEN
16092   REWRITE_TAC[FROM_0; INTER_UNIV; IN_UNIV] THENL
16093    [X_GEN_TAC `e:real` THEN DISCH_TAC THEN
16094     MP_TAC(ISPECL [`&2 / &3`; `e / B`] REAL_ARCH_POW_INV) THEN
16095     ASM_SIMP_TAC[REAL_LT_DIV] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
16096     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN DISCH_TAC THEN
16097     MAP_EVERY X_GEN_TAC [`m:num`; `n:num`; `x:real^N`] THEN DISCH_TAC THEN
16098     MATCH_MP_TAC REAL_LET_TRANS THEN
16099     EXISTS_TAC `sum(m..n) (\i. &2 pow i * B / &3 pow (i + 1))` THEN
16100     ASM_SIMP_TAC[VSUM_NORM_LE; FINITE_NUMSEG] THEN
16101     REWRITE_TAC[REAL_POW_ADD; real_div; REAL_INV_MUL] THEN
16102     REWRITE_TAC[REAL_ARITH `x * B * inv y * inv(&3 pow 1) = B / &3 * x / y`;
16103                 SUM_LMUL; GSYM REAL_POW_DIV] THEN
16104     REWRITE_TAC[SUM_GP] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
16105     COND_CASES_TAC THENL
16106      [ASM_REWRITE_TAC[real_div; REAL_MUL_LZERO; REAL_MUL_RZERO]; ALL_TAC] THEN
16107     REWRITE_TAC[REAL_ARITH `B / &3 * x / (&1 / &3) < e <=> x * B < e`] THEN
16108     ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ] THEN
16109     MATCH_MP_TAC(REAL_ARITH `&0 < y /\ x < e ==> x - y < e`) THEN
16110     ASM_SIMP_TAC[REAL_POW_LT; REAL_LT_DIV; REAL_OF_NUM_LT; ARITH] THEN
16111     MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `(&2 / &3) pow N` THEN
16112     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_POW_MONO_INV THEN
16113     ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV;
16114     ALL_TAC] THEN
16115   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `k:real^N->real^1` THEN
16116   DISCH_TAC THEN REPEAT CONJ_TAC THENL
16117    [MATCH_MP_TAC(ISPEC `sequentially` CONTINUOUS_UNIFORM_LIMIT) THEN
16118     EXISTS_TAC `\n x:real^N. vsum (0..n) (\i. g i x :real^1)` THEN
16119     ASM_REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; EVENTUALLY_SEQUENTIALLY] THEN
16120     ASM_REWRITE_TAC[IN_UNIV; IMP_IMP; RIGHT_IMP_FORALL_THM; GSYM dist] THEN
16121     EXISTS_TAC `0` THEN REPEAT STRIP_TAC THEN
16122     MATCH_MP_TAC CONTINUOUS_ON_VSUM THEN ASM_REWRITE_TAC[FINITE_NUMSEG];
16123     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
16124     MATCH_MP_TAC(NORM_ARITH `~(&0 < norm(x - y)) ==> x = y`) THEN
16125     DISCH_TAC THEN
16126     FIRST_X_ASSUM(MP_TAC o SPEC `norm((k:real^N->real^1) x - f x) / &2`) THEN
16127     ASM_REWRITE_TAC[REAL_HALF; NOT_EXISTS_THM] THEN
16128     X_GEN_TAC `N1:num` THEN DISCH_THEN(LABEL_TAC "*") THEN
16129     MP_TAC(ISPECL [`&2 / &3`; `norm((k:real^N->real^1) x - f x) / &2 / B`]
16130         REAL_ARCH_POW_INV) THEN
16131     ASM_SIMP_TAC[REAL_LT_DIV; REAL_HALF] THEN
16132     CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_SIMP_TAC[REAL_LT_RDIV_EQ] THEN
16133     ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
16134     DISCH_THEN(X_CHOOSE_THEN `N2:num` (LABEL_TAC "+")) THEN
16135     REMOVE_THEN "*" (MP_TAC o SPECL [`N1 + N2:num`; `x:real^N`]) THEN
16136     REWRITE_TAC[LE_ADD; NOT_IMP] THEN
16137     CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN MATCH_MP_TAC(NORM_ARITH
16138      `norm(f - s) < norm(k - f) / &2
16139       ==> ~(dist(s,k) < norm(k - f) / &2)`) THEN
16140     MATCH_MP_TAC REAL_LET_TRANS THEN
16141     EXISTS_TAC `B * (&2 / &3) pow N2` THEN ASM_REWRITE_TAC[] THEN
16142     MATCH_MP_TAC REAL_LE_TRANS THEN
16143     EXISTS_TAC `&2 pow ((N1 + N2) + 1) * B / &3 pow ((N1 + N2) + 1)` THEN
16144     ASM_SIMP_TAC[] THEN
16145     ONCE_REWRITE_TAC[REAL_ARITH `x * B / y = B * x / y`] THEN
16146     ASM_SIMP_TAC[REAL_LE_LMUL_EQ; GSYM REAL_POW_DIV] THEN
16147     MATCH_MP_TAC REAL_POW_MONO_INV THEN
16148     ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ARITH_TAC;
16149     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
16150     MATCH_MP_TAC(ISPEC `sequentially` LIM_NORM_UBOUND) THEN
16151     EXISTS_TAC `\n. vsum(0..n) (\i. (g:num->real^N->real^1) i x)` THEN
16152     REWRITE_TAC[TRIVIAL_LIMIT_SEQUENTIALLY; EVENTUALLY_SEQUENTIALLY] THEN
16153     CONJ_TAC THENL
16154      [REWRITE_TAC[LIM_SEQUENTIALLY] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
16155     EXISTS_TAC `0` THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
16156     MATCH_MP_TAC REAL_LE_TRANS THEN
16157     EXISTS_TAC `sum(0..n) (\i. &2 pow i * B / &3 pow (i + 1))` THEN
16158     ASM_SIMP_TAC[VSUM_NORM_LE; FINITE_NUMSEG] THEN
16159     REWRITE_TAC[REAL_POW_ADD; real_div; REAL_INV_MUL] THEN
16160     REWRITE_TAC[REAL_ARITH `x * B * inv y * inv(&3 pow 1) = B / &3 * x / y`;
16161                 SUM_LMUL; GSYM REAL_POW_DIV] THEN
16162     REWRITE_TAC[REAL_ARITH `B / &3 * x <= B <=> B * x / &3 <= B * &1`] THEN
16163     ASM_SIMP_TAC[REAL_LE_LMUL_EQ; REAL_LE_LDIV_EQ; REAL_OF_NUM_LT; ARITH] THEN
16164     REWRITE_TAC[SUM_GP] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
16165     COND_CASES_TAC THENL
16166      [SIMP_TAC[real_div; REAL_MUL_LZERO; REAL_MUL_RZERO; REAL_POS];
16167       ALL_TAC] THEN
16168     REWRITE_TAC[REAL_ARITH `x / (&1 / &3) <= &3 <=> x <= &1`] THEN
16169     REWRITE_TAC[REAL_ARITH `&1 - x <= &1 <=> &0 <= x`] THEN
16170     MATCH_MP_TAC REAL_POW_LE THEN CONV_TAC REAL_RAT_REDUCE_CONV]);;
16171
16172 (* ------------------------------------------------------------------------- *)
16173 (* The same result for intervals in real^1.                                  *)
16174 (* ------------------------------------------------------------------------- *)
16175
16176 let TIETZE_CLOSED_INTERVAL_1 = prove
16177  (`!f:real^N->real^1 u s a b.
16178         drop a <= drop b /\
16179         closed_in (subtopology euclidean u) s /\
16180         f continuous_on s /\
16181         (!x. x IN s ==> f x IN interval[a,b])
16182         ==> ?g. g continuous_on u /\
16183                 (!x. x IN s ==> g x = f x) /\
16184                 (!x. x IN u ==> g(x) IN interval[a,b])`,
16185   REPEAT STRIP_TAC THEN
16186   MP_TAC(ISPECL [`\x. (f:real^N->real^1)(x) - inv(&2) % (a + b)`;
16187              `u:real^N->bool`; `s:real^N->bool`; `(drop(b) - drop(a)) / &2`]
16188         TIETZE) THEN
16189   ASM_SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST] THEN ANTS_TAC THENL
16190    [CONJ_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
16191     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
16192     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
16193     REWRITE_TAC[IN_INTERVAL_1; NORM_REAL; GSYM drop] THEN
16194     REWRITE_TAC[DROP_ADD; DROP_CMUL; DROP_SUB] THEN REAL_ARITH_TAC;
16195     ALL_TAC] THEN
16196   DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^1` STRIP_ASSUME_TAC) THEN
16197   EXISTS_TAC `\x. (g:real^N->real^1)(x) + inv(&2) % (a + b)` THEN
16198   REPEAT CONJ_TAC THENL
16199    [ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_CONST];
16200     REPEAT STRIP_TAC THEN ASM_SIMP_TAC[] THEN VECTOR_ARITH_TAC;
16201     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN UNDISCH_TAC
16202      `!x. x IN u ==> norm((g:real^N->real^1) x) <= (drop b - drop a) / &2` THEN
16203     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
16204     REWRITE_TAC[IN_INTERVAL_1; NORM_REAL; GSYM drop] THEN
16205     REWRITE_TAC[DROP_ADD; DROP_CMUL; DROP_SUB] THEN REAL_ARITH_TAC]);;
16206
16207 let TIETZE_OPEN_INTERVAL_1 = prove
16208  (`!f:real^N->real^1 u s a b.
16209         drop a < drop b /\
16210         closed_in (subtopology euclidean u) s /\
16211         f continuous_on s /\
16212         (!x. x IN s ==> f x IN interval(a,b))
16213         ==> ?g. g continuous_on u /\
16214                 (!x. x IN s ==> g x = f x) /\
16215                 (!x. x IN u ==> g(x) IN interval(a,b))`,
16216   REWRITE_TAC[IN_INTERVAL_1] THEN REPEAT STRIP_TAC THEN
16217   MP_TAC(ISPECL [`f:real^N->real^1`; `u:real^N->bool`; `s:real^N->bool`;
16218                  `a:real^1`; `b:real^1`] TIETZE_CLOSED_INTERVAL_1) THEN
16219   ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
16220    [ASM_MESON_TAC[IN_INTERVAL_1; REAL_LT_IMP_LE]; ALL_TAC] THEN
16221   DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^1` STRIP_ASSUME_TAC) THEN
16222   MP_TAC(ISPECL [`s:real^N->bool`;
16223                  `{x | x IN u /\ (g:real^N->real^1) x IN {a,b}}`;
16224                  `u:real^N->bool`;
16225                  `vec 1:real^1`; `vec 0:real^1`] URYSOHN_LOCAL) THEN
16226   ASM_REWRITE_TAC[SEGMENT_1; DROP_VEC; REAL_OF_NUM_LE; ARITH] THEN
16227   REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN ANTS_TAC THENL
16228    [CONJ_TAC THENL
16229      [MATCH_MP_TAC CONTINUOUS_CLOSED_IN_PREIMAGE THEN
16230       ASM_SIMP_TAC[FINITE_IMP_CLOSED; FINITE_INSERT; FINITE_EMPTY] THEN
16231       ASM_MESON_TAC[CONTINUOUS_ON_EQ_CONTINUOUS_AT; OPEN_UNIV; IN_UNIV];
16232       RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN
16233       ASM SET_TAC[REAL_LT_REFL]];
16234     REWRITE_TAC[IN_ELIM_THM] THEN
16235     DISCH_THEN(X_CHOOSE_THEN `h:real^N->real^1` STRIP_ASSUME_TAC) THEN
16236     EXISTS_TAC `(\x. &1 / &2 % (a + b) +
16237                     drop(h x) % (g x - &1 / &2 % (a + b))):real^N->real^1` THEN
16238     ASM_SIMP_TAC[DROP_CMUL; DROP_VEC; VECTOR_MUL_LID] THEN
16239     REWRITE_TAC[VECTOR_ARITH `a + x - a:real^N = x`] THEN CONJ_TAC THENL
16240      [MATCH_MP_TAC CONTINUOUS_ON_ADD THEN REWRITE_TAC[CONTINUOUS_ON_CONST] THEN
16241       MATCH_MP_TAC CONTINUOUS_ON_MUL THEN
16242       ASM_SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; ETA_AX] THEN
16243       ASM_REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX];
16244       ALL_TAC] THEN
16245     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
16246     REWRITE_TAC[DROP_ADD; DROP_CMUL; DROP_SUB] THEN
16247     REWRITE_TAC[REAL_ARITH
16248      `a < &1 / &2 * (a + b) + x /\ &1 / &2 * (a + b) + x < b <=>
16249       abs(x) < &1 * (b - a) / &2`] THEN
16250     ASM_CASES_TAC `(g:real^N->real^1) x IN {a,b}` THENL
16251      [ASM_SIMP_TAC[DROP_VEC; REAL_MUL_LZERO] THEN ASM_REAL_ARITH_TAC;
16252       REWRITE_TAC[REAL_ABS_MUL] THEN MATCH_MP_TAC(REAL_ARITH
16253        `y < a /\ abs(x) * y <= &1 * y ==> abs(x) * y < a`) THEN
16254       CONJ_TAC THENL
16255        [REWRITE_TAC[REAL_MUL_LID] THEN MATCH_MP_TAC(REAL_ARITH
16256          `a < x /\ x < b ==> abs(x - &1 / &2 * (a + b)) < (b - a) / &2`) THEN
16257         RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN
16258         ASM_REWRITE_TAC[REAL_LT_LE; DROP_EQ] THEN ASM SET_TAC[];
16259         MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_ABS_POS] THEN
16260         REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`)) THEN
16261         FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN
16262         ASM_SIMP_TAC[SUBSET] THEN REAL_ARITH_TAC]]]);;
16263
16264 let TIETZE_UNBOUNDED_1 = prove
16265  (`!f:real^N->real^1 u s.
16266         closed_in (subtopology euclidean u) s  /\ f continuous_on s
16267         ==> ?g. g continuous_on u /\ (!x. x IN s ==> g x = f x)`,
16268   REPEAT STRIP_TAC THEN
16269   MP_TAC(ISPECL [`vec 0:real^1`; `vec 1:real^1`]
16270     HOMEOMORPHIC_OPEN_INTERVAL_UNIV) THEN
16271   REWRITE_TAC[INTERVAL_NE_EMPTY; VEC_COMPONENT; REAL_LT_01] THEN
16272   REWRITE_TAC[HOMEOMORPHIC_MINIMAL; LEFT_IMP_EXISTS_THM] THEN
16273   MAP_EVERY X_GEN_TAC [`h:real^1->real^1`; `k:real^1->real^1`] THEN
16274   REWRITE_TAC[IN_UNIV] THEN STRIP_TAC THEN
16275   MP_TAC(ISPECL [`(k:real^1->real^1) o (f:real^N->real^1)`; `u:real^N->bool`;
16276                  `s:real^N->bool`; `vec 0:real^1`; `vec 1:real^1`]
16277         TIETZE_OPEN_INTERVAL_1) THEN
16278   REWRITE_TAC[] THEN ANTS_TAC THENL
16279    [ASM_REWRITE_TAC[DROP_VEC; REAL_LT_01; o_THM] THEN
16280     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN
16281     ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
16282     EXISTS_TAC `(:real^1)` THEN ASM_REWRITE_TAC[SUBSET_UNIV];
16283     DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^1` STRIP_ASSUME_TAC) THEN
16284     EXISTS_TAC `(h:real^1->real^1) o (g:real^N->real^1)` THEN
16285     ASM_SIMP_TAC[o_THM] THEN
16286     MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN
16287    MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN
16288    EXISTS_TAC `interval(vec 0:real^1,vec 1)` THEN
16289    ASM_REWRITE_TAC[SUBSET_UNIV] THEN ASM SET_TAC[]]);;
16290
16291 (* ------------------------------------------------------------------------- *)
16292 (* Now for general intervals in real^N by componentwise extension.           *)
16293 (* ------------------------------------------------------------------------- *)
16294
16295 let TIETZE_CLOSED_INTERVAL = prove
16296  (`!f:real^M->real^N u s a b.
16297         ~(interval[a,b] = {}) /\
16298         closed_in (subtopology euclidean u) s /\
16299         f continuous_on s /\
16300         (!x. x IN s ==> f x IN interval[a,b])
16301         ==> ?g. g continuous_on u /\
16302                 (!x. x IN s ==> g x = f x) /\
16303                 (!x. x IN u ==> g(x) IN interval[a,b])`,
16304   REWRITE_TAC[INTERVAL_NE_EMPTY] THEN REPEAT STRIP_TAC THEN
16305   SUBGOAL_THEN
16306    `!i. 1 <= i /\ i <= dimindex(:N)
16307         ==> ?g. g continuous_on u /\
16308                 (!x. x IN s ==> g x = lift((f:real^M->real^N)(x)$i)) /\
16309                 (!x. x IN u ==>
16310                       g(x) IN interval[lift((a:real^N)$i),lift((b:real^N)$i)])`
16311   MP_TAC THENL
16312    [REPEAT STRIP_TAC THEN MATCH_MP_TAC TIETZE_CLOSED_INTERVAL_1 THEN
16313     RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL]) THEN
16314     ASM_SIMP_TAC[IN_INTERVAL_1; LIFT_DROP] THEN
16315     SUBGOAL_THEN `(\x. lift((f:real^M->real^N) x$i)) = (\x. lift(x$i)) o f`
16316     SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
16317     ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT; CONTINUOUS_ON_COMPOSE];
16318     ALL_TAC] THEN
16319   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [RIGHT_IMP_EXISTS_THM] THEN
16320   REWRITE_TAC[SKOLEM_THM; IN_INTERVAL_1; LIFT_DROP] THEN
16321   DISCH_THEN(X_CHOOSE_TAC `g:num->real^M->real^1`) THEN
16322   EXISTS_TAC `(\x. lambda i. drop(g i x)):real^M->real^N` THEN
16323   SIMP_TAC[CART_EQ; IN_INTERVAL; LAMBDA_BETA] THEN CONJ_TAC THENL
16324    [ONCE_REWRITE_TAC[CONTINUOUS_ON_COMPONENTWISE_LIFT] THEN
16325     ASM_SIMP_TAC[LAMBDA_BETA; LIFT_DROP; ETA_AX];
16326     ASM_SIMP_TAC[LIFT_DROP]]);;
16327
16328 let TIETZE_OPEN_INTERVAL = prove
16329  (`!f:real^M->real^N u s a b.
16330         ~(interval(a,b) = {}) /\
16331         closed_in (subtopology euclidean u) s /\
16332         f continuous_on s /\
16333         (!x. x IN s ==> f x IN interval(a,b))
16334         ==> ?g. g continuous_on u /\
16335                 (!x. x IN s ==> g x = f x) /\
16336                 (!x. x IN u ==> g(x) IN interval(a,b))`,
16337   REWRITE_TAC[INTERVAL_NE_EMPTY] THEN REPEAT STRIP_TAC THEN
16338   SUBGOAL_THEN
16339    `!i. 1 <= i /\ i <= dimindex(:N)
16340         ==> ?g. g continuous_on u /\
16341                 (!x. x IN s ==> g x = lift((f:real^M->real^N)(x)$i)) /\
16342                 (!x. x IN u ==>
16343                       g(x) IN interval(lift((a:real^N)$i),lift((b:real^N)$i)))`
16344   MP_TAC THENL
16345    [REPEAT STRIP_TAC THEN MATCH_MP_TAC TIETZE_OPEN_INTERVAL_1 THEN
16346     RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL]) THEN
16347     ASM_SIMP_TAC[IN_INTERVAL_1; LIFT_DROP] THEN
16348     SUBGOAL_THEN `(\x. lift((f:real^M->real^N) x$i)) = (\x. lift(x$i)) o f`
16349     SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
16350     ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT; CONTINUOUS_ON_COMPOSE];
16351     ALL_TAC] THEN
16352   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [RIGHT_IMP_EXISTS_THM] THEN
16353   REWRITE_TAC[SKOLEM_THM; IN_INTERVAL_1; LIFT_DROP] THEN
16354   DISCH_THEN(X_CHOOSE_TAC `g:num->real^M->real^1`) THEN
16355   EXISTS_TAC `(\x. lambda i. drop(g i x)):real^M->real^N` THEN
16356   SIMP_TAC[CART_EQ; IN_INTERVAL; LAMBDA_BETA] THEN CONJ_TAC THENL
16357    [ONCE_REWRITE_TAC[CONTINUOUS_ON_COMPONENTWISE_LIFT] THEN
16358     ASM_SIMP_TAC[LAMBDA_BETA; LIFT_DROP; ETA_AX];
16359     ASM_SIMP_TAC[LIFT_DROP]]);;
16360
16361 let TIETZE_UNBOUNDED = prove
16362  (`!f:real^M->real^N u s.
16363         closed_in (subtopology euclidean u) s /\ f continuous_on s
16364         ==> ?g. g continuous_on u /\
16365                 (!x. x IN s ==> g x = f x)`,
16366   REWRITE_TAC[INTERVAL_NE_EMPTY] THEN REPEAT STRIP_TAC THEN
16367   SUBGOAL_THEN
16368    `!i. 1 <= i /\ i <= dimindex(:N)
16369         ==> ?g. g continuous_on u /\
16370                 (!x. x IN s ==> g x = lift((f:real^M->real^N)(x)$i))`
16371   MP_TAC THENL
16372    [REPEAT STRIP_TAC THEN MATCH_MP_TAC TIETZE_UNBOUNDED_1 THEN
16373     RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL]) THEN
16374     ASM_SIMP_TAC[IN_INTERVAL_1; LIFT_DROP] THEN
16375     SUBGOAL_THEN `(\x. lift((f:real^M->real^N) x$i)) = (\x. lift(x$i)) o f`
16376     SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN
16377     ASM_SIMP_TAC[CONTINUOUS_ON_LIFT_COMPONENT; CONTINUOUS_ON_COMPOSE];
16378     ALL_TAC] THEN
16379   GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [RIGHT_IMP_EXISTS_THM] THEN
16380   REWRITE_TAC[SKOLEM_THM; IN_INTERVAL_1; LIFT_DROP] THEN
16381   DISCH_THEN(X_CHOOSE_TAC `g:num->real^M->real^1`) THEN
16382   EXISTS_TAC `(\x. lambda i. drop(g i x)):real^M->real^N` THEN
16383   SIMP_TAC[CART_EQ; IN_INTERVAL; LAMBDA_BETA] THEN CONJ_TAC THENL
16384    [ONCE_REWRITE_TAC[CONTINUOUS_ON_COMPONENTWISE_LIFT] THEN
16385     ASM_SIMP_TAC[LAMBDA_BETA; LIFT_DROP; ETA_AX];
16386     ASM_SIMP_TAC[LIFT_DROP]]);;
16387
16388 (* ------------------------------------------------------------------------- *)
16389 (* Countability of some relevant sets.                                       *)
16390 (* ------------------------------------------------------------------------- *)
16391
16392 let COUNTABLE_INTEGER = prove
16393  (`COUNTABLE integer`,
16394   MATCH_MP_TAC COUNTABLE_SUBSET THEN EXISTS_TAC
16395    `IMAGE (\n. (&n:real)) (:num) UNION IMAGE (\n. --(&n)) (:num)` THEN
16396   SIMP_TAC[COUNTABLE_IMAGE; COUNTABLE_UNION; NUM_COUNTABLE] THEN
16397   REWRITE_TAC[SUBSET; IN_UNION; IN_IMAGE; IN_UNIV] THEN
16398   REWRITE_TAC[IN; INTEGER_CASES]);;
16399
16400 let CARD_EQ_INTEGER = prove
16401  (`integer =_c (:num)`,
16402   REWRITE_TAC[GSYM CARD_LE_ANTISYM; GSYM COUNTABLE_ALT; COUNTABLE_INTEGER] THEN
16403   REWRITE_TAC[le_c] THEN EXISTS_TAC `real_of_num` THEN
16404   REWRITE_TAC[IN_UNIV; REAL_OF_NUM_EQ] THEN
16405   REWRITE_TAC[IN; INTEGER_CLOSED]);;
16406
16407 let COUNTABLE_RATIONAL = prove
16408  (`COUNTABLE rational`,
16409   MATCH_MP_TAC COUNTABLE_SUBSET THEN
16410   EXISTS_TAC `IMAGE (\(x,y). x / y) (integer CROSS integer)` THEN
16411   SIMP_TAC[COUNTABLE_IMAGE; COUNTABLE_CROSS; COUNTABLE_INTEGER] THEN
16412   REWRITE_TAC[SUBSET; IN_IMAGE; EXISTS_PAIR_THM; IN_CROSS] THEN
16413   REWRITE_TAC[rational; IN] THEN MESON_TAC[]);;
16414
16415 let CARD_EQ_RATIONAL = prove
16416  (`rational =_c (:num)`,
16417   REWRITE_TAC[GSYM CARD_LE_ANTISYM; GSYM COUNTABLE_ALT; COUNTABLE_RATIONAL] THEN
16418   REWRITE_TAC[le_c] THEN EXISTS_TAC `real_of_num` THEN
16419   REWRITE_TAC[IN_UNIV; REAL_OF_NUM_EQ] THEN
16420   REWRITE_TAC[IN; RATIONAL_CLOSED]);;
16421
16422 let COUNTABLE_INTEGER_COORDINATES = prove
16423  (`COUNTABLE { x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }`,
16424   MATCH_MP_TAC COUNTABLE_CART THEN
16425   REWRITE_TAC[SET_RULE `{x | P x} = P`; COUNTABLE_INTEGER]);;
16426
16427 let COUNTABLE_RATIONAL_COORDINATES = prove
16428  (`COUNTABLE { x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) }`,
16429   MATCH_MP_TAC COUNTABLE_CART THEN
16430   REWRITE_TAC[SET_RULE `{x | P x} = P`; COUNTABLE_RATIONAL]);;
16431
16432 (* ------------------------------------------------------------------------- *)
16433 (* Density of points with rational, or just dyadic rational, coordinates.    *)
16434 (* ------------------------------------------------------------------------- *)
16435
16436 let CLOSURE_DYADIC_RATIONALS = prove
16437  (`closure { inv(&2 pow n) % x |n,x|
16438              !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) } = (:real^N)`,
16439   REWRITE_TAC[EXTENSION; CLOSURE_APPROACHABLE; IN_UNIV; EXISTS_IN_GSPEC] THEN
16440   MAP_EVERY X_GEN_TAC [`x:real^N`; `e:real`] THEN DISCH_TAC THEN
16441   MP_TAC(SPECL [`inv(&2)`; `e / &(dimindex(:N))`] REAL_ARCH_POW_INV) THEN
16442   ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1;
16443                REAL_POW_INV; REAL_LT_RDIV_EQ] THEN
16444   CONV_TAC REAL_RAT_REDUCE_CONV THEN MATCH_MP_TAC MONO_EXISTS THEN
16445   ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
16446   EXISTS_TAC `(lambda i. floor(&2 pow n * (x:real^N)$i)):real^N` THEN
16447   ASM_SIMP_TAC[LAMBDA_BETA; FLOOR; dist; NORM_MUL] THEN
16448   MATCH_MP_TAC(MATCH_MP (REWRITE_RULE[IMP_CONJ] REAL_LET_TRANS)
16449    (SPEC_ALL NORM_LE_L1)) THEN
16450   SIMP_TAC[LAMBDA_BETA; VECTOR_SUB_COMPONENT; VECTOR_MUL_COMPONENT] THEN
16451   MATCH_MP_TAC REAL_LET_TRANS THEN
16452   EXISTS_TAC `&(dimindex(:N)) * inv(&2 pow n)` THEN ASM_REWRITE_TAC[] THEN
16453   GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o RAND_CONV) [GSYM CARD_NUMSEG_1] THEN
16454   MATCH_MP_TAC SUM_BOUND THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
16455   X_GEN_TAC `k:num` THEN STRIP_TAC THEN
16456   GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_RID] THEN
16457   SIMP_TAC[REAL_ABS_MUL; REAL_POW_EQ_0; REAL_OF_NUM_EQ; ARITH;
16458     REAL_FIELD `~(a = &0) ==> inv a * b - x = inv a * (b - a * x)`] THEN
16459   MATCH_MP_TAC REAL_LE_MUL2 THEN REWRITE_TAC[REAL_ABS_POS] THEN
16460   REWRITE_TAC[REAL_LE_REFL; REAL_ABS_POW; REAL_ABS_INV; REAL_ABS_NUM] THEN
16461   MP_TAC(SPEC `&2 pow n * (x:real^N)$k` FLOOR) THEN REAL_ARITH_TAC);;
16462
16463 let CLOSURE_RATIONAL_COORDINATES = prove
16464  (`closure { x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) } =
16465    (:real^N)`,
16466   MATCH_MP_TAC(SET_RULE `!s. s SUBSET t /\ s = UNIV ==> t = UNIV`) THEN
16467   EXISTS_TAC
16468    `closure { inv(&2 pow n) % x:real^N |n,x|
16469               !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }` THEN
16470
16471   CONJ_TAC THENL [ALL_TAC; REWRITE_TAC[CLOSURE_DYADIC_RATIONALS]] THEN
16472   MATCH_MP_TAC SUBSET_CLOSURE THEN
16473   REWRITE_TAC[SUBSET; FORALL_IN_GSPEC; IN_ELIM_THM; VECTOR_MUL_COMPONENT] THEN
16474   ASM_SIMP_TAC[RATIONAL_CLOSED]);;
16475
16476 let CLOSURE_DYADIC_RATIONALS_IN_OPEN_SET = prove
16477  (`!s:real^N->bool.
16478         open s
16479         ==> closure(s INTER
16480                     { inv(&2 pow n) % x | n,x |
16481                       !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }) =
16482             closure s`,
16483   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_OPEN_INTER_SUPERSET THEN
16484   ASM_REWRITE_TAC[CLOSURE_DYADIC_RATIONALS; SUBSET_UNIV]);;
16485
16486 let CLOSURE_RATIONALS_IN_OPEN_SET = prove
16487  (`!s:real^N->bool.
16488         open s
16489         ==> closure(s INTER
16490                     { inv(&2 pow n) % x | n,x |
16491                       !i. 1 <= i /\ i <= dimindex(:N) ==> integer(x$i) }) =
16492             closure s`,
16493   REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_OPEN_INTER_SUPERSET THEN
16494   ASM_REWRITE_TAC[CLOSURE_DYADIC_RATIONALS; SUBSET_UNIV]);;
16495
16496 (* ------------------------------------------------------------------------- *)
16497 (* Various separability-type properties.                                     *)
16498 (* ------------------------------------------------------------------------- *)
16499
16500 let UNIV_SECOND_COUNTABLE = prove
16501  (`?b. COUNTABLE b /\ (!c. c IN b ==> open c) /\
16502        !s:real^N->bool. open s ==> ?u. u SUBSET b /\ s = UNIONS u`,
16503   EXISTS_TAC
16504    `IMAGE (\(v:real^N,q). ball(v,q))
16505           ({v | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(v$i)} CROSS
16506            rational)` THEN
16507   REPEAT CONJ_TAC THENL
16508    [MATCH_MP_TAC COUNTABLE_IMAGE THEN MATCH_MP_TAC COUNTABLE_CROSS THEN
16509     REWRITE_TAC[COUNTABLE_RATIONAL] THEN MATCH_MP_TAC COUNTABLE_CART THEN
16510     REWRITE_TAC[COUNTABLE_RATIONAL; SET_RULE `{x | P x} = P`];
16511     REWRITE_TAC[FORALL_IN_IMAGE; CROSS; FORALL_IN_GSPEC; OPEN_BALL];
16512     REPEAT STRIP_TAC THEN
16513     ASM_CASES_TAC `s:real^N->bool = {}` THENL
16514      [EXISTS_TAC `{}:(real^N->bool)->bool` THEN
16515       ASM_REWRITE_TAC[UNIONS_0; EMPTY_SUBSET];
16516       ALL_TAC] THEN
16517     EXISTS_TAC `{c | c IN IMAGE (\(v:real^N,q). ball(v,q))
16518           ({v | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(v$i)} CROSS
16519            rational) /\ c SUBSET s}` THEN
16520     CONJ_TAC THENL [SET_TAC[]; ALL_TAC] THEN
16521     MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL [ALL_TAC; SET_TAC[]] THEN
16522     REWRITE_TAC[SUBSET; IN_UNIONS; IN_ELIM_THM] THEN
16523     REWRITE_TAC[GSYM CONJ_ASSOC; EXISTS_IN_IMAGE] THEN
16524     REWRITE_TAC[CROSS; EXISTS_PAIR_THM; EXISTS_IN_GSPEC] THEN
16525     REWRITE_TAC[IN_ELIM_PAIR_THM] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
16526     FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN
16527     DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
16528     ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM; SUBSET; IN_BALL] THEN
16529     X_GEN_TAC `e:real` THEN STRIP_TAC THEN REWRITE_TAC[IN_ELIM_THM] THEN
16530     MP_TAC(REWRITE_RULE[EXTENSION; IN_UNIV] CLOSURE_RATIONAL_COORDINATES) THEN
16531     REWRITE_TAC[CLOSURE_APPROACHABLE] THEN
16532     DISCH_THEN(MP_TAC o SPECL [`x:real^N`; `e / &4`]) THEN
16533     ANTS_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[IN_ELIM_THM]] THEN
16534     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
16535     SUBGOAL_THEN `?x. rational x /\ e / &3 < x /\ x < e / &2`
16536      (X_CHOOSE_THEN `q:real` STRIP_ASSUME_TAC)
16537     THENL
16538      [MP_TAC(ISPECL [`&5 / &12 * e`; `e / &12`] RATIONAL_APPROXIMATION) THEN
16539       ANTS_TAC THENL [ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS] THEN
16540       SIMP_TAC[] THEN REAL_ARITH_TAC;
16541       EXISTS_TAC `q:real` THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL
16542        [ASM_REWRITE_TAC[IN];
16543         REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
16544         REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC;
16545         ASM_REAL_ARITH_TAC]]]);;
16546
16547 let UNIV_SECOND_COUNTABLE_SEQUENCE = prove
16548  (`?b:num->real^N->bool.
16549         (!m n. b m = b n <=> m = n) /\
16550         (!n. open(b n)) /\
16551         (!s. open s ==> ?k. s = UNIONS {b n | n IN k})`,
16552   X_CHOOSE_THEN `bb:(real^N->bool)->bool` STRIP_ASSUME_TAC
16553     UNIV_SECOND_COUNTABLE THEN
16554   MP_TAC(ISPEC `bb:(real^N->bool)->bool` COUNTABLE_AS_INJECTIVE_IMAGE) THEN
16555   ANTS_TAC THENL
16556    [ASM_REWRITE_TAC[INFINITE] THEN DISCH_TAC THEN
16557     SUBGOAL_THEN
16558      `INFINITE {ball(vec 0:real^N,inv(&n + &1)) | n IN (:num)}`
16559     MP_TAC THENL
16560      [REWRITE_TAC[SIMPLE_IMAGE] THEN MATCH_MP_TAC(REWRITE_RULE
16561        [RIGHT_IMP_FORALL_THM; IMP_IMP] INFINITE_IMAGE_INJ) THEN
16562       REWRITE_TAC[num_INFINITE] THEN MATCH_MP_TAC WLOG_LT THEN SIMP_TAC[] THEN
16563       CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
16564       MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN DISCH_TAC THEN
16565       REWRITE_TAC[EXTENSION] THEN
16566       DISCH_THEN(MP_TAC o SPEC `inv(&n + &1) % basis 1:real^N`) THEN
16567       REWRITE_TAC[IN_BALL; DIST_0; NORM_MUL; REAL_ABS_INV] THEN
16568       SIMP_TAC[NORM_BASIS; DIMINDEX_GE_1; LE_REFL; REAL_MUL_RID] THEN
16569       ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN DISCH_TAC THEN
16570       REWRITE_TAC[REAL_ARITH `abs(&n + &1) = &n + &1`; REAL_LT_REFL] THEN
16571       MATCH_MP_TAC REAL_LT_INV2 THEN
16572       REWRITE_TAC[REAL_OF_NUM_LT; REAL_OF_NUM_ADD] THEN ASM_ARITH_TAC;
16573       REWRITE_TAC[INFINITE; SIMPLE_IMAGE] THEN
16574       MATCH_MP_TAC FINITE_SUBSET THEN
16575       EXISTS_TAC `IMAGE UNIONS {u | u SUBSET bb} :(real^N->bool)->bool` THEN
16576       ASM_SIMP_TAC[FINITE_IMAGE; FINITE_POWERSET] THEN
16577       GEN_REWRITE_TAC I [SUBSET] THEN SIMP_TAC[FORALL_IN_IMAGE; IN_UNIV] THEN
16578       X_GEN_TAC `n:num` THEN REWRITE_TAC[IN_IMAGE; IN_ELIM_THM] THEN
16579       ASM_MESON_TAC[OPEN_BALL]];
16580     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:num->real^N->bool` THEN
16581     DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
16582     RULE_ASSUM_TAC(REWRITE_RULE[FORALL_IN_IMAGE; IN_UNIV]) THEN
16583     REPEAT(CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC]) THEN
16584     X_GEN_TAC `s:real^N->bool` THEN DISCH_TAC THEN
16585     FIRST_X_ASSUM(MP_TAC o SPEC `s:real^N->bool`) THEN
16586     ASM_REWRITE_TAC[SUBSET_IMAGE; LEFT_AND_EXISTS_THM; SUBSET_UNIV] THEN
16587     ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
16588     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[SIMPLE_IMAGE]]);;
16589
16590 let SUBSET_SECOND_COUNTABLE = prove
16591  (`!s:real^N->bool.
16592        ?b. COUNTABLE b /\
16593            (!c. c IN b ==> ~(c = {}) /\ open_in(subtopology euclidean s) c) /\
16594            !t. open_in(subtopology euclidean s) t
16595                ==> ?u. u SUBSET b /\ t = UNIONS u`,
16596   GEN_TAC THEN
16597   SUBGOAL_THEN
16598    `?b. COUNTABLE b /\
16599            (!c:real^N->bool. c IN b ==> open_in(subtopology euclidean s) c) /\
16600            !t. open_in(subtopology euclidean s) t
16601                ==> ?u. u SUBSET b /\ t = UNIONS u`
16602   STRIP_ASSUME_TAC THENL
16603    [X_CHOOSE_THEN `B:(real^N->bool)->bool` STRIP_ASSUME_TAC
16604       UNIV_SECOND_COUNTABLE THEN
16605     EXISTS_TAC `{s INTER c :real^N->bool | c IN B}` THEN
16606     ASM_SIMP_TAC[SIMPLE_IMAGE; COUNTABLE_IMAGE] THEN
16607     ASM_SIMP_TAC[FORALL_IN_IMAGE; EXISTS_SUBSET_IMAGE; OPEN_IN_OPEN_INTER] THEN
16608     REWRITE_TAC[OPEN_IN_OPEN] THEN
16609     X_GEN_TAC `t:real^N->bool` THEN
16610     DISCH_THEN(X_CHOOSE_THEN `u:real^N->bool` STRIP_ASSUME_TAC) THEN
16611     FIRST_X_ASSUM SUBST_ALL_TAC THEN
16612     SUBGOAL_THEN `?b. b SUBSET B /\ u:real^N->bool = UNIONS b`
16613     STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
16614     FIRST_X_ASSUM SUBST_ALL_TAC THEN
16615     EXISTS_TAC `b:(real^N->bool)->bool` THEN ASM_REWRITE_TAC[] THEN
16616     REWRITE_TAC[INTER_UNIONS] THEN AP_TERM_TAC THEN SET_TAC[];
16617     EXISTS_TAC `b DELETE ({}:real^N->bool)` THEN
16618     ASM_SIMP_TAC[COUNTABLE_DELETE; IN_DELETE; SUBSET_DELETE] THEN
16619     X_GEN_TAC `t:real^N->bool` THEN DISCH_THEN(ANTE_RES_THEN MP_TAC) THEN
16620     DISCH_THEN(X_CHOOSE_THEN `u:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
16621     EXISTS_TAC `u DELETE ({}:real^N->bool)` THEN
16622     REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
16623     FIRST_X_ASSUM SUBST_ALL_TAC THEN
16624     REWRITE_TAC[EXTENSION; IN_UNIONS] THEN
16625     GEN_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN
16626     REWRITE_TAC[IN_DELETE] THEN SET_TAC[]]);;
16627
16628 let SEPARABLE = prove
16629  (`!s:real^N->bool.
16630         ?t. COUNTABLE t /\ t SUBSET s /\ s SUBSET closure t`,
16631   MP_TAC SUBSET_SECOND_COUNTABLE THEN
16632   MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `s:real^N->bool` THEN
16633   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_AND_EXISTS_THM] THEN
16634   DISCH_THEN(X_CHOOSE_THEN `B:(real^N->bool)->bool`
16635    (CONJUNCTS_THEN2 ASSUME_TAC (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC))) THEN
16636   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
16637   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
16638   X_GEN_TAC `f:(real^N->bool)->real^N` THEN DISCH_TAC THEN
16639   EXISTS_TAC `IMAGE (f:(real^N->bool)->real^N) B` THEN
16640   ASM_SIMP_TAC[COUNTABLE_IMAGE] THEN CONJ_TAC THENL
16641    [REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
16642     X_GEN_TAC `c:real^N->bool` THEN DISCH_TAC THEN
16643     FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN
16644     ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
16645     FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_SUBSET) THEN
16646     REWRITE_TAC[TOPSPACE_SUBTOPOLOGY; TOPSPACE_EUCLIDEAN] THEN ASM SET_TAC[];
16647     REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE; EXISTS_IN_IMAGE] THEN
16648     X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
16649     X_GEN_TAC `e:real` THEN DISCH_TAC THEN
16650     UNDISCH_THEN
16651      `!t:real^N->bool.
16652         open_in (subtopology euclidean s) t
16653         ==> (?u. u SUBSET B /\ t = UNIONS u)`
16654      (MP_TAC o SPEC `s INTER ball(x:real^N,e)`) THEN
16655     SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_BALL; LEFT_IMP_EXISTS_THM] THEN
16656     X_GEN_TAC `b:(real^N->bool)->bool` THEN
16657     ASM_CASES_TAC `b:(real^N->bool)->bool = {}` THENL
16658      [MATCH_MP_TAC(TAUT `~b ==> a /\ b ==> c`) THEN
16659       ASM_REWRITE_TAC[EXTENSION; IN_INTER; NOT_IN_EMPTY; UNIONS_0] THEN
16660       ASM_MESON_TAC[CENTRE_IN_BALL];
16661       STRIP_TAC THEN
16662       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
16663       MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `c:real^N->bool` THEN
16664       DISCH_TAC THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
16665       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EXTENSION]) THEN
16666       DISCH_THEN(MP_TAC o SPEC `(f:(real^N->bool)->real^N) c`) THEN
16667       ONCE_REWRITE_TAC[DIST_SYM] THEN REWRITE_TAC[IN_INTER; IN_BALL] THEN
16668       MATCH_MP_TAC(TAUT `a /\ c ==> (a /\ b <=> c) ==> b`) THEN
16669       CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
16670       FIRST_X_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN
16671       ANTS_TAC THENL [ASM SET_TAC[]; STRIP_TAC] THEN
16672       FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_SUBSET) THEN
16673       REWRITE_TAC[TOPSPACE_SUBTOPOLOGY; TOPSPACE_EUCLIDEAN] THEN
16674       ASM SET_TAC[]]]);;
16675
16676 let OPEN_SET_RATIONAL_COORDINATES = prove
16677  (`!s. open s /\ ~(s = {})
16678        ==> ?x:real^N. x IN s /\
16679                       !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)`,
16680   REPEAT STRIP_TAC THEN
16681   SUBGOAL_THEN
16682    `~(closure { x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) } INTER
16683     (s:real^N->bool) = {})`
16684   MP_TAC THENL
16685    [ASM_REWRITE_TAC[CLOSURE_RATIONAL_COORDINATES; INTER_UNIV]; ALL_TAC] THEN
16686   REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; CLOSURE_APPROACHABLE; IN_INTER;
16687               IN_ELIM_THM] THEN
16688   DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN
16689   FIRST_X_ASSUM(MP_TAC o SPEC `a:real^N` o REWRITE_RULE[open_def]) THEN
16690   ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;
16691
16692 let OPEN_COUNTABLE_UNION_OPEN_INTERVALS,
16693     OPEN_COUNTABLE_UNION_CLOSED_INTERVALS = (CONJ_PAIR o prove)
16694  (`(!s:real^N->bool.
16695         open s
16696         ==> ?D. COUNTABLE D /\
16697                 (!i. i IN D ==> i SUBSET s /\ ?a b. i = interval(a,b)) /\
16698                 UNIONS D = s) /\
16699    (!s:real^N->bool.
16700         open s
16701         ==> ?D. COUNTABLE D /\
16702                 (!i. i IN D ==> i SUBSET s /\ ?a b. i = interval[a,b]) /\
16703                 UNIONS D = s)`,
16704   REPEAT STRIP_TAC THENL
16705    [EXISTS_TAC
16706      `{i | i IN IMAGE (\(a:real^N,b). interval(a,b))
16707             ({x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)} CROSS
16708              {x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)}) /\
16709            i SUBSET s}`;
16710     EXISTS_TAC
16711      `{i | i IN IMAGE (\(a:real^N,b). interval[a,b])
16712             ({x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)} CROSS
16713              {x | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i)}) /\
16714            i SUBSET s}`] THEN
16715   (SIMP_TAC[COUNTABLE_RESTRICT; COUNTABLE_IMAGE; COUNTABLE_CROSS;
16716            COUNTABLE_RATIONAL_COORDINATES] THEN
16717    REWRITE_TAC[IN_ELIM_THM; UNIONS_GSPEC; IMP_CONJ; GSYM CONJ_ASSOC] THEN
16718    REWRITE_TAC[FORALL_IN_IMAGE; EXISTS_IN_IMAGE] THEN
16719    REWRITE_TAC[FORALL_PAIR_THM; EXISTS_PAIR_THM; IN_CROSS; IN_ELIM_THM] THEN
16720    CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
16721    REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
16722    X_GEN_TAC `x:real^N` THEN EQ_TAC THENL [SET_TAC[]; DISCH_TAC] THEN
16723    FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N` o REWRITE_RULE[open_def]) THEN
16724    ASM_REWRITE_TAC[] THEN
16725    DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
16726    SUBGOAL_THEN
16727     `!i. 1 <= i /\ i <= dimindex(:N)
16728          ==> ?a b. rational a /\ rational b /\
16729                    a < (x:real^N)$i /\ (x:real^N)$i < b /\
16730                    abs(b - a) < e / &(dimindex(:N))`
16731    MP_TAC THENL
16732     [REPEAT STRIP_TAC THEN MATCH_MP_TAC RATIONAL_APPROXIMATION_STRADDLE THEN
16733      ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1];
16734      REWRITE_TAC[LAMBDA_SKOLEM]] THEN
16735    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `a:real^N` THEN
16736    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `b:real^N` THEN
16737    DISCH_TAC THEN ASM_SIMP_TAC[SUBSET; IN_INTERVAL; REAL_LT_IMP_LE] THEN
16738    X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
16739    REWRITE_TAC[dist] THEN MP_TAC(ISPEC `y - x:real^N` NORM_LE_L1) THEN
16740    MATCH_MP_TAC(REAL_ARITH `s < e ==> n <= s ==> n < e`) THEN
16741    MATCH_MP_TAC SUM_BOUND_LT_GEN THEN
16742    REWRITE_TAC[FINITE_NUMSEG; NUMSEG_EMPTY; NOT_LT; CARD_NUMSEG_1] THEN
16743    REWRITE_TAC[DIMINDEX_GE_1; IN_NUMSEG; VECTOR_SUB_COMPONENT] THEN
16744    X_GEN_TAC `k:num` THEN STRIP_TAC THEN
16745    REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `k:num`)) THEN ASM_REWRITE_TAC[] THEN
16746    ASM_REAL_ARITH_TAC));;
16747
16748 let LINDELOF = prove
16749  (`!f:(real^N->bool)->bool.
16750         (!s. s IN f ==> open s)
16751         ==> ?f'. f' SUBSET f /\ COUNTABLE f' /\ UNIONS f' = UNIONS f`,
16752   REPEAT STRIP_TAC THEN
16753   SUBGOAL_THEN
16754    `?b. COUNTABLE b /\
16755         (!c:real^N->bool. c IN b ==> open c) /\
16756         (!s. open s ==> ?u. u SUBSET b /\ s = UNIONS u)`
16757   STRIP_ASSUME_TAC THENL [ASM_REWRITE_TAC[UNIV_SECOND_COUNTABLE]; ALL_TAC] THEN
16758   ABBREV_TAC
16759    `d = {s:real^N->bool | s IN b /\ ?u. u IN f /\ s SUBSET u}` THEN
16760   SUBGOAL_THEN
16761    `COUNTABLE d /\ UNIONS f :real^N->bool = UNIONS d`
16762   STRIP_ASSUME_TAC THENL
16763    [EXPAND_TAC "d" THEN ASM_SIMP_TAC[COUNTABLE_RESTRICT] THEN ASM SET_TAC[];
16764     ALL_TAC] THEN
16765   SUBGOAL_THEN
16766    `!s:real^N->bool. ?u. s IN d ==> u IN f /\ s SUBSET u`
16767   MP_TAC THENL [EXPAND_TAC "d" THEN SET_TAC[]; ALL_TAC] THEN
16768   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
16769   X_GEN_TAC `g:(real^N->bool)->(real^N->bool)` THEN STRIP_TAC THEN
16770   EXISTS_TAC `IMAGE (g:(real^N->bool)->(real^N->bool)) d` THEN
16771   ASM_SIMP_TAC[COUNTABLE_IMAGE; UNIONS_IMAGE] THEN
16772   REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN ASM SET_TAC[]);;
16773
16774 let LINDELOF_OPEN_IN = prove
16775  (`!f u:real^N->bool.
16776         (!s. s IN f ==> open_in (subtopology euclidean u) s)
16777         ==> ?f'. f' SUBSET f /\ COUNTABLE f' /\ UNIONS f' = UNIONS f`,
16778   REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_IN_OPEN] THEN
16779   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
16780   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
16781   X_GEN_TAC `v:(real^N->bool)->real^N->bool` THEN DISCH_TAC THEN
16782   MP_TAC(ISPEC `IMAGE (v:(real^N->bool)->real^N->bool) f` LINDELOF) THEN
16783   ASM_SIMP_TAC[FORALL_IN_IMAGE] THEN
16784   ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN
16785   REWRITE_TAC[EXISTS_COUNTABLE_SUBSET_IMAGE] THEN
16786   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f':(real^N->bool)->bool` THEN
16787   STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
16788   SUBGOAL_THEN
16789   `!f'. f' SUBSET f ==> UNIONS f' = (u:real^N->bool) INTER UNIONS (IMAGE v f')`
16790   MP_TAC THENL [ASM SET_TAC[]; ASM_SIMP_TAC[SUBSET_REFL]]);;
16791
16792 let COUNTABLE_DISJOINT_OPEN_SUBSETS = prove
16793  (`!f. (!s:real^N->bool. s IN f ==> open s) /\ pairwise DISJOINT f
16794        ==> COUNTABLE f`,
16795   REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP LINDELOF) THEN
16796   DISCH_THEN(X_CHOOSE_THEN `g:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN
16797   MATCH_MP_TAC COUNTABLE_SUBSET THEN
16798   EXISTS_TAC `({}:real^N->bool) INSERT g` THEN
16799   ASM_REWRITE_TAC[COUNTABLE_INSERT] THEN
16800   REWRITE_TAC[SUBSET; IN_INSERT] THEN
16801   REPEAT(POP_ASSUM MP_TAC) THEN
16802   REWRITE_TAC[EXTENSION; SUBSET] THEN
16803   REWRITE_TAC[IN_UNIONS; pairwise] THEN
16804   REWRITE_TAC[SET_RULE `DISJOINT s t <=> !x. ~(x IN s /\ x IN t)`] THEN
16805   REWRITE_TAC[NOT_IN_EMPTY] THEN MESON_TAC[]);;
16806
16807 let CARD_EQ_OPEN_SETS = prove
16808  (`{s:real^N->bool | open s} =_c (:real)`,
16809   REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
16810    [X_CHOOSE_THEN `b:(real^N->bool)->bool` STRIP_ASSUME_TAC
16811       UNIV_SECOND_COUNTABLE THEN
16812     TRANS_TAC CARD_LE_TRANS `{s:(real^N->bool)->bool | s SUBSET b}` THEN
16813     CONJ_TAC THENL
16814      [REWRITE_TAC[LE_C] THEN
16815       EXISTS_TAC `UNIONS:((real^N->bool)->bool)->real^N->bool` THEN
16816       REWRITE_TAC[IN_ELIM_THM] THEN ASM_MESON_TAC[];
16817       TRANS_TAC CARD_LE_TRANS `{s | s SUBSET (:num)}` THEN CONJ_TAC THENL
16818        [MATCH_MP_TAC CARD_LE_POWERSET THEN ASM_REWRITE_TAC[GSYM COUNTABLE_ALT];
16819         REWRITE_TAC[SUBSET_UNIV; UNIV_GSPEC] THEN
16820         MESON_TAC[CARD_EQ_IMP_LE; CARD_EQ_SYM; CARD_EQ_REAL]]];
16821     REWRITE_TAC[le_c; IN_UNIV; IN_ELIM_THM] THEN
16822     EXISTS_TAC `\x. ball(x % basis 1:real^N,&1)` THEN
16823     REWRITE_TAC[OPEN_BALL; GSYM SUBSET_ANTISYM_EQ; SUBSET_BALLS] THEN
16824     CONV_TAC REAL_RAT_REDUCE_CONV THEN
16825     REWRITE_TAC[NORM_ARITH `dist(p:real^N,q) + &1 <= &1 <=> p = q`] THEN
16826     REWRITE_TAC[VECTOR_MUL_RCANCEL; EQ_SYM_EQ] THEN
16827     SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; ARITH]]);;
16828
16829 let CARD_EQ_CLOSED_SETS = prove
16830  (`{s:real^N->bool | closed s} =_c (:real)`,
16831   SUBGOAL_THEN
16832    `{s:real^N->bool | closed s} =
16833     IMAGE (\s. (:real^N) DIFF s) {s | open s}`
16834   SUBST1_TAC THENL
16835    [CONV_TAC SYM_CONV THEN MATCH_MP_TAC SURJECTIVE_IMAGE_EQ THEN
16836     REWRITE_TAC[IN_ELIM_THM; GSYM OPEN_CLOSED] THEN
16837     MESON_TAC[SET_RULE `UNIV DIFF (UNIV DIFF s) = s`];
16838     TRANS_TAC CARD_EQ_TRANS `{s:real^N->bool | open s}` THEN
16839     REWRITE_TAC[CARD_EQ_OPEN_SETS] THEN
16840     MATCH_MP_TAC CARD_EQ_IMAGE THEN SET_TAC[]]);;
16841
16842 let CARD_EQ_COMPACT_SETS = prove
16843  (`{s:real^N->bool | compact s} =_c (:real)`,
16844   REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
16845    [TRANS_TAC CARD_LE_TRANS `{s:real^N->bool | closed s}` THEN
16846     SIMP_TAC[CARD_EQ_IMP_LE; CARD_EQ_CLOSED_SETS] THEN
16847     MATCH_MP_TAC CARD_LE_SUBSET THEN
16848     SIMP_TAC[SUBSET; IN_ELIM_THM; COMPACT_IMP_CLOSED];
16849     REWRITE_TAC[le_c; IN_UNIV; IN_ELIM_THM] THEN
16850     EXISTS_TAC `\x. {x % basis 1:real^N}` THEN
16851     REWRITE_TAC[COMPACT_SING; SET_RULE `{x} = {y} <=> x = y`] THEN
16852     SIMP_TAC[VECTOR_MUL_RCANCEL; BASIS_NONZERO; DIMINDEX_GE_1; ARITH]]);;
16853
16854 let COUNTABLE_NON_CONDENSATION_POINTS = prove
16855  (`!s:real^N->bool. COUNTABLE(s DIFF {x | x condensation_point_of s})`,
16856   REPEAT STRIP_TAC THEN REWRITE_TAC[condensation_point_of] THEN
16857   MATCH_MP_TAC COUNTABLE_SUBSET THEN
16858   X_CHOOSE_THEN `b:(real^N->bool)->bool` STRIP_ASSUME_TAC
16859    UNIV_SECOND_COUNTABLE THEN
16860   EXISTS_TAC
16861    `s INTER UNIONS { u:real^N->bool | u IN b /\ COUNTABLE(s INTER u)}` THEN
16862   REWRITE_TAC[INTER_UNIONS; IN_ELIM_THM] THEN CONJ_TAC THENL
16863    [MATCH_MP_TAC COUNTABLE_UNIONS THEN SIMP_TAC[FORALL_IN_GSPEC] THEN
16864     ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN
16865     ASM_SIMP_TAC[COUNTABLE_IMAGE; COUNTABLE_RESTRICT];
16866     SIMP_TAC[SUBSET; UNIONS_GSPEC; IN_ELIM_THM; IN_INTER; IN_DIFF] THEN
16867     X_GEN_TAC `x:real^N` THEN
16868     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
16869     REWRITE_TAC[NOT_FORALL_THM; NOT_IMP; LEFT_IMP_EXISTS_THM] THEN
16870     X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
16871     SUBGOAL_THEN `?u:real^N->bool. x IN u /\ u IN b /\ u SUBSET t` MP_TAC THENL
16872      [ASM SET_TAC[]; MATCH_MP_TAC MONO_EXISTS] THEN
16873     REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
16874     MATCH_MP_TAC COUNTABLE_SUBSET THEN
16875     EXISTS_TAC `s INTER t:real^N->bool` THEN ASM SET_TAC[]]);;
16876
16877 let CARD_EQ_CONDENSATION_POINTS_IN_SET = prove
16878  (`!s:real^N->bool.
16879      ~(COUNTABLE s) ==> {x | x IN s /\ x condensation_point_of s} =_c s`,
16880   REPEAT STRIP_TAC THEN
16881   TRANS_TAC CARD_EQ_TRANS
16882    `(s DIFF {x | x condensation_point_of s}) +_c
16883     {x:real^N | x IN s /\ x condensation_point_of s}` THEN
16884   CONJ_TAC THENL
16885    [ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN MATCH_MP_TAC CARD_ADD_ABSORB THEN
16886     MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
16887      [POP_ASSUM MP_TAC THEN REWRITE_TAC[INFINITE; CONTRAPOS_THM] THEN
16888       DISCH_THEN(MP_TAC o CONJ (SPEC `s:real^N->bool`
16889        COUNTABLE_NON_CONDENSATION_POINTS) o MATCH_MP FINITE_IMP_COUNTABLE) THEN
16890       REWRITE_TAC[GSYM COUNTABLE_UNION] THEN MATCH_MP_TAC EQ_IMP THEN
16891       AP_TERM_TAC THEN SET_TAC[];
16892       REWRITE_TAC[INFINITE_CARD_LE] THEN
16893       MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] CARD_LE_TRANS) THEN
16894       REWRITE_TAC[GSYM COUNTABLE_ALT; COUNTABLE_NON_CONDENSATION_POINTS]];
16895     ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN
16896     W(MP_TAC o PART_MATCH (rand o rand) CARD_DISJOINT_UNION o rand o snd) THEN
16897     ANTS_TAC THENL [SET_TAC[]; ALL_TAC] THEN
16898     MATCH_MP_TAC EQ_IMP THEN AP_THM_TAC THEN AP_TERM_TAC THEN SET_TAC[]]);;
16899
16900 (* ------------------------------------------------------------------------- *)
16901 (* A discrete set is countable, and an uncountable set has a limit point.    *)
16902 (* ------------------------------------------------------------------------- *)
16903
16904 let DISCRETE_IMP_COUNTABLE = prove
16905  (`!s:real^N->bool.
16906         (!x. x IN s ==> ?e. &0 < e /\
16907                             !y. y IN s /\ ~(y = x) ==> e <= norm(y - x))
16908         ==> COUNTABLE s`,
16909   REPEAT STRIP_TAC THEN
16910   SUBGOAL_THEN
16911    `!x. x IN s
16912         ==> ?q. (!i. 1 <= i /\ i <= dimindex(:N) ==> rational(q$i)) /\
16913                 !y:real^N. y IN s /\ ~(y = x) ==> norm(x - q) < norm(y - q)`
16914   MP_TAC THENL
16915    [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN
16916     FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN
16917     DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN
16918     MP_TAC(SET_RULE `x IN (:real^N)`) THEN
16919     REWRITE_TAC[GSYM CLOSURE_RATIONAL_COORDINATES] THEN
16920     REWRITE_TAC[CLOSURE_APPROACHABLE; IN_ELIM_THM] THEN
16921     DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
16922     MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `q:real^N` THEN
16923     STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
16924     X_GEN_TAC `y:real^N` THEN STRIP_TAC THEN
16925     FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THEN
16926     REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC;
16927     POP_ASSUM(K ALL_TAC) THEN
16928     REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
16929     X_GEN_TAC `q:real^N->real^N` THEN DISCH_TAC THEN
16930     MP_TAC(ISPECL
16931      [`s:real^N->bool`;
16932       `{ x:real^N | !i. 1 <= i /\ i <= dimindex(:N) ==> rational(x$i) }`;
16933       `(:num)`] CARD_LE_TRANS) THEN
16934     REWRITE_TAC[COUNTABLE; ge_c] THEN DISCH_THEN MATCH_MP_TAC THEN
16935     SIMP_TAC[REWRITE_RULE[COUNTABLE; ge_c] COUNTABLE_RATIONAL_COORDINATES] THEN
16936     REWRITE_TAC[le_c] THEN EXISTS_TAC `q:real^N->real^N` THEN
16937     ASM_SIMP_TAC[IN_ELIM_THM] THEN ASM_MESON_TAC[REAL_LT_ANTISYM]]);;
16938
16939 let UNCOUNTABLE_CONTAINS_LIMIT_POINT = prove
16940  (`!s. ~(COUNTABLE s) ==> ?x. x IN s /\ x limit_point_of s`,
16941   GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP
16942    (ONCE_REWRITE_RULE[GSYM CONTRAPOS_THM] DISCRETE_IMP_COUNTABLE)) THEN
16943   REWRITE_TAC[LIMPT_APPROACHABLE; GSYM REAL_NOT_LT; dist] THEN
16944   MESON_TAC[]);;
16945
16946 (* ------------------------------------------------------------------------- *)
16947 (* The Brouwer reduction theorem.                                            *)
16948 (* ------------------------------------------------------------------------- *)
16949
16950 let BROUWER_REDUCTION_THEOREM_GEN = prove
16951  (`!P s:real^N->bool.
16952         (!f. (!n. closed(f n) /\ P(f n)) /\ (!n. f(SUC n) SUBSET f(n))
16953               ==> P(INTERS {f n | n IN (:num)})) /\
16954         closed s /\ P s
16955         ==> ?t. t SUBSET s /\ closed t /\ P t /\
16956                 (!u. u SUBSET s /\ closed u /\ P u ==> ~(u PSUBSET t))`,
16957   REPEAT STRIP_TAC THEN
16958   SUBGOAL_THEN
16959    `?b:num->real^N->bool.
16960         (!m n. b m = b n <=> m = n) /\
16961         (!n. open (b n)) /\
16962         (!s. open s ==> (?k. s = UNIONS {b n | n IN k}))`
16963   STRIP_ASSUME_TAC THENL
16964    [REWRITE_TAC[UNIV_SECOND_COUNTABLE_SEQUENCE]; ALL_TAC] THEN
16965   X_CHOOSE_THEN `a:num->real^N->bool` MP_TAC
16966    (prove_recursive_functions_exist num_RECURSION
16967    `a 0 = (s:real^N->bool) /\
16968     (!n. a(SUC n) =
16969          if ?u. u SUBSET a(n) /\ closed u /\ P u /\ u INTER (b n) = {}
16970          then @u. u SUBSET a(n) /\ closed u /\ P u /\ u INTER (b n) = {}
16971          else a(n))`) THEN
16972   DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "base") (LABEL_TAC "step")) THEN
16973   EXISTS_TAC `INTERS {a n :real^N->bool | n IN (:num)}` THEN
16974   SUBGOAL_THEN `!n. (a:num->real^N->bool)(SUC n) SUBSET a(n)` ASSUME_TAC THENL
16975    [GEN_TAC THEN ASM_REWRITE_TAC[] THEN
16976     COND_CASES_TAC THEN REWRITE_TAC[SUBSET_REFL] THEN
16977     FIRST_X_ASSUM(MP_TAC o SELECT_RULE) THEN MESON_TAC[];
16978     ALL_TAC] THEN
16979   SUBGOAL_THEN `!n. (a:num->real^N->bool) n SUBSET s` ASSUME_TAC THENL
16980    [INDUCT_TAC THEN ASM_MESON_TAC[SUBSET_REFL; SUBSET_TRANS]; ALL_TAC] THEN
16981   SUBGOAL_THEN `!n. closed((a:num->real^N->bool) n) /\ P(a n)` ASSUME_TAC THENL
16982    [INDUCT_TAC THEN ASM_REWRITE_TAC[] THEN
16983     COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
16984     FIRST_X_ASSUM(MP_TAC o SELECT_RULE) THEN MESON_TAC[];
16985     ALL_TAC] THEN
16986   REPEAT CONJ_TAC THENL
16987    [ASM SET_TAC[];
16988     MATCH_MP_TAC CLOSED_INTERS THEN
16989     ASM_REWRITE_TAC[FORALL_IN_GSPEC; IN_UNIV] THEN SET_TAC[];
16990     FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[];
16991     X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN
16992     REWRITE_TAC[PSUBSET_ALT] THEN
16993     DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
16994     REWRITE_TAC[INTERS_GSPEC; EXISTS_IN_GSPEC; IN_UNIV] THEN
16995     DISCH_THEN(X_CHOOSE_THEN `x:real^N` STRIP_ASSUME_TAC) THEN
16996     SUBGOAL_THEN
16997      `?n. x IN (b:num->real^N->bool)(n) /\ t INTER b n = {}`
16998     STRIP_ASSUME_TAC THENL
16999      [MP_TAC(ISPEC `(:real^N) DIFF t` OPEN_CONTAINS_BALL) THEN
17000       ASM_REWRITE_TAC[GSYM closed] THEN
17001       DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN
17002       ASM_REWRITE_TAC[IN_DIFF; IN_UNIV; LEFT_IMP_EXISTS_THM] THEN
17003       REWRITE_TAC[SET_RULE `s SUBSET UNIV DIFF t <=> t INTER s = {}`] THEN
17004       X_GEN_TAC `e:real` THEN
17005       DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
17006       MP_TAC(ISPECL [`x:real^N`; `e:real`] CENTRE_IN_BALL) THEN
17007       FIRST_X_ASSUM(MP_TAC o SPEC `ball(x:real^N,e)`) THEN
17008       ASM_REWRITE_TAC[OPEN_BALL; LEFT_IMP_EXISTS_THM] THEN
17009       X_GEN_TAC `k:num->bool` THEN DISCH_THEN SUBST1_TAC THEN
17010       REWRITE_TAC[IN_UNIONS; INTER_UNIONS; EMPTY_UNIONS; FORALL_IN_GSPEC] THEN
17011       SET_TAC[];
17012       REMOVE_THEN "step" (MP_TAC o SPEC `n:num`) THEN
17013       COND_CASES_TAC THENL
17014        [DISCH_THEN(ASSUME_TAC o SYM) THEN
17015         FIRST_X_ASSUM(MP_TAC o SELECT_RULE) THEN ASM_REWRITE_TAC[] THEN
17016         ASM SET_TAC[];
17017         FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [NOT_EXISTS_THM]) THEN
17018         DISCH_THEN(MP_TAC o SPEC `t:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN
17019         ASM SET_TAC[]]]]);;
17020
17021 let BROUWER_REDUCTION_THEOREM = prove
17022  (`!P s:real^N->bool.
17023         (!f. (!n. compact(f n) /\ ~(f n = {}) /\ P(f n)) /\
17024              (!n. f(SUC n) SUBSET f(n))
17025              ==> P(INTERS {f n | n IN (:num)})) /\
17026         compact s /\ ~(s = {}) /\ P s
17027         ==> ?t. t SUBSET s /\ compact t /\ ~(t = {}) /\ P t /\
17028                 (!u. u SUBSET s /\ closed u /\ ~(u = {}) /\ P u
17029                      ==> ~(u PSUBSET t))`,
17030   REPEAT STRIP_TAC THEN
17031   MP_TAC(ISPECL [`\t:real^N->bool. ~(t = {}) /\ t SUBSET s /\ P t`;
17032                  `s:real^N->bool`]
17033         BROUWER_REDUCTION_THEOREM_GEN) THEN
17034   ASM_SIMP_TAC[COMPACT_IMP_CLOSED; SUBSET_REFL] THEN ANTS_TAC THENL
17035    [GEN_TAC THEN STRIP_TAC THEN
17036     SUBGOAL_THEN `!n. compact((f:num->real^N->bool) n)` ASSUME_TAC THENL
17037      [ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_SUBSET]; ALL_TAC] THEN
17038     REPEAT CONJ_TAC THENL
17039      [MATCH_MP_TAC COMPACT_NEST THEN ASM_REWRITE_TAC[] THEN
17040       MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN ASM_SIMP_TAC[] THEN SET_TAC[];
17041       ASM SET_TAC[];
17042       FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[]];
17043     MATCH_MP_TAC MONO_EXISTS THEN ASM_SIMP_TAC[] THEN
17044     ASM_MESON_TAC[COMPACT_EQ_BOUNDED_CLOSED; BOUNDED_SUBSET]]);;
17045
17046 (* ------------------------------------------------------------------------- *)
17047 (* The Arzela-Ascoli theorem.                                                *)
17048 (* ------------------------------------------------------------------------- *)
17049
17050 let SUBSEQUENCE_DIAGONALIZATION_LEMMA = prove
17051  (`!P:num->(num->A)->bool.
17052     (!i r:num->A. ?k. (!m n. m < n ==> k m < k n) /\ P i (r o k)) /\
17053     (!i r:num->A k1 k2 N.
17054         P i (r o k1) /\ (!j. N <= j ==> ?j'. j <= j' /\ k2 j = k1 j')
17055         ==> P i (r o k2))
17056     ==> !r:num->A. ?k. (!m n. m < n ==> k m < k n) /\ (!i. P i (r o k))`,
17057   REPEAT GEN_TAC THEN
17058   DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
17059   GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [SKOLEM_THM] THEN
17060   REWRITE_TAC[FORALL_AND_THM; TAUT
17061    `(p ==> q /\ r) <=> (p ==> q) /\ (p ==> r)`] THEN
17062   DISCH_THEN(X_CHOOSE_THEN
17063    `kk:num->(num->A)->num->num` STRIP_ASSUME_TAC) THEN
17064   X_GEN_TAC `r:num->A` THEN
17065   (STRIP_ASSUME_TAC o prove_recursive_functions_exist num_RECURSION)
17066     `(rr 0 = (kk:num->(num->A)->num->num) 0 r) /\
17067      (!n. rr(SUC n) = rr n o kk (SUC n) (r o rr n))` THEN
17068   EXISTS_TAC `\n. (rr:num->num->num) n n` THEN REWRITE_TAC[ETA_AX] THEN
17069   SUBGOAL_THEN
17070    `(!i. (!m n. m < n ==> (rr:num->num->num) i m < rr i n)) /\
17071     (!i. (P:num->(num->A)->bool) i (r o rr i))`
17072   STRIP_ASSUME_TAC THENL
17073    [REWRITE_TAC[AND_FORALL_THM] THEN
17074     INDUCT_TAC THEN ASM_REWRITE_TAC[o_ASSOC] THEN
17075     REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[];
17076     ALL_TAC] THEN
17077   SUBGOAL_THEN `!i j n. i <= j ==> (rr:num->num->num) i n <= rr j n`
17078   ASSUME_TAC THENL
17079    [REPEAT GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [LE_EXISTS] THEN
17080     SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN SPEC_TAC(`j:num`,`j:num`) THEN
17081     ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN SIMP_TAC[FORALL_UNWIND_THM2] THEN
17082     INDUCT_TAC THEN REWRITE_TAC[ADD_CLAUSES; LE_REFL] THEN
17083     ASM_REWRITE_TAC[] THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP
17084      (REWRITE_RULE[IMP_CONJ] LE_TRANS)) THEN REWRITE_TAC[o_THM] THEN
17085     FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP
17086      (MESON[LE_LT]
17087        `!f:num->num.
17088         (!m n. m < n ==> f m < f n) ==> (!m n. m <= n ==> f m <= f n)`) o
17089        SPEC `i + d:num`) THEN
17090     SPEC_TAC(`n:num`,`n:num`) THEN MATCH_MP_TAC MONOTONE_BIGGER THEN
17091     ASM_SIMP_TAC[];
17092     ALL_TAC] THEN
17093   CONJ_TAC THENL
17094    [MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN DISCH_TAC THEN
17095     MATCH_MP_TAC LET_TRANS THEN
17096     EXISTS_TAC `(rr:num->num->num) n m` THEN
17097     ASM_MESON_TAC[LT_IMP_LE];
17098     ALL_TAC] THEN
17099   SUBGOAL_THEN
17100    `!m n i. n <= m ==> ?j. i <= j /\ (rr:num->num->num) m i = rr n j`
17101   ASSUME_TAC THENL
17102    [ALL_TAC;
17103     X_GEN_TAC `i:num` THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
17104     EXISTS_TAC `(rr:num->num->num) i` THEN ASM_REWRITE_TAC[] THEN
17105     EXISTS_TAC `i:num` THEN ASM_MESON_TAC[]] THEN
17106   SUBGOAL_THEN
17107    `!p d i. ?j. i <= j /\ (rr:num->num->num) (p + d) i = rr p j`
17108    (fun th -> MESON_TAC[LE_EXISTS; th]) THEN
17109   X_GEN_TAC `p:num` THEN  MATCH_MP_TAC num_INDUCTION THEN
17110   ASM_REWRITE_TAC[ADD_CLAUSES] THEN CONJ_TAC THENL
17111    [MESON_TAC[LE_REFL]; ALL_TAC] THEN
17112   X_GEN_TAC `d:num` THEN DISCH_THEN(LABEL_TAC "+") THEN
17113   X_GEN_TAC `i:num` THEN ASM_REWRITE_TAC[o_THM] THEN
17114   REMOVE_THEN "+" (MP_TAC o SPEC
17115    `(kk:num->(num->A)->num->num) (SUC(p + d))
17116         ((r:num->A) o (rr:num->num->num) (p + d)) i`) THEN
17117   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `j:num` THEN
17118   MATCH_MP_TAC MONO_AND THEN REWRITE_TAC[] THEN
17119   MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LE_TRANS) THEN
17120   SPEC_TAC(`i:num`,`i:num`) THEN MATCH_MP_TAC MONOTONE_BIGGER THEN
17121   ASM_REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[]);;
17122
17123 let FUNCTION_CONVERGENT_SUBSEQUENCE = prove
17124  (`!f:num->real^M->real^N s M.
17125         COUNTABLE s /\ (!n x. x IN s ==> norm(f n x) <= M)
17126         ==> ?k. (!m n:num. m < n ==> k m < k n) /\
17127                 !x. x IN s ==> ?l. ((\n. f (k n) x) --> l) sequentially`,
17128   REPEAT STRIP_TAC THEN
17129   ASM_CASES_TAC `s:real^M->bool = {}` THENL
17130    [EXISTS_TAC `\n:num. n` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY];
17131     ALL_TAC] THEN
17132   MP_TAC(ISPEC `s:real^M->bool` COUNTABLE_AS_IMAGE) THEN
17133   ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
17134   X_GEN_TAC `X:num->real^M` THEN DISCH_THEN SUBST_ALL_TAC THEN
17135   MP_TAC(ISPEC
17136     `\i r. ?l. ((\n. ((f:num->real^M->real^N) o (r:num->num)) n
17137                      ((X:num->real^M) i)) --> l) sequentially`
17138    SUBSEQUENCE_DIAGONALIZATION_LEMMA) THEN
17139   REWRITE_TAC[FORALL_IN_IMAGE; o_THM; IN_UNIV] THEN
17140   ANTS_TAC THENL [ALL_TAC; DISCH_THEN MATCH_ACCEPT_TAC] THEN CONJ_TAC THENL
17141    [RULE_ASSUM_TAC(REWRITE_RULE[FORALL_IN_IMAGE; IN_UNIV]) THEN
17142     MAP_EVERY X_GEN_TAC [`i:num`; `r:num->num`] THEN
17143     MP_TAC(ISPEC `cball(vec 0:real^N,M)` compact) THEN
17144     REWRITE_TAC[COMPACT_CBALL] THEN DISCH_THEN(MP_TAC o SPEC
17145      `\n. (f:num->real^M->real^N) ((r:num->num) n) (X(i:num))`) THEN
17146     ASM_REWRITE_TAC[IN_CBALL_0; o_DEF] THEN MESON_TAC[];
17147     REPEAT GEN_TAC THEN REWRITE_TAC[LIM_SEQUENTIALLY; GE] THEN
17148     DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
17149     MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
17150     MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN
17151     MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN
17152     ASM_MESON_TAC[LE_TRANS; ARITH_RULE `MAX a b <= c <=> a <= c /\ b <= c`]]);;
17153
17154 let ARZELA_ASCOLI = prove
17155  (`!f:num->real^M->real^N s M.
17156         compact s /\
17157         (!n x. x IN s ==> norm(f n x) <= M) /\
17158         (!x e. x IN s /\ &0 < e
17159                ==> ?d. &0 < d /\
17160                        !n y. y IN s /\ norm(x - y) < d
17161                              ==> norm(f n x - f n y) < e)
17162         ==> ?g. g continuous_on s /\
17163                 ?r. (!m n:num. m < n ==> r m < r n) /\
17164                     !e. &0 < e
17165                         ==> ?N. !n x. n >= N /\ x IN s
17166                                       ==> norm(f(r n) x - g x) < e`,
17167   REPEAT STRIP_TAC THEN REWRITE_TAC[GE] THEN
17168   MATCH_MP_TAC(MESON[]
17169    `(!k g. V k g ==> N g) /\ (?k. M k /\ ?g. V k g)
17170     ==> ?g. N g /\ ?k. M k /\ V k g`) THEN
17171   CONJ_TAC THENL
17172    [MAP_EVERY X_GEN_TAC [`k:num->num`; `g:real^M->real^N`] THEN
17173     STRIP_TAC THEN MATCH_MP_TAC(ISPEC `sequentially`
17174       CONTINUOUS_UNIFORM_LIMIT) THEN
17175     EXISTS_TAC `(f:num->real^M->real^N) o (k:num->num)` THEN
17176     ASM_SIMP_TAC[EVENTUALLY_SEQUENTIALLY; o_THM; TRIVIAL_LIMIT_SEQUENTIALLY;
17177                  RIGHT_IMP_FORALL_THM; IMP_IMP] THEN
17178     EXISTS_TAC `0` THEN REWRITE_TAC[continuous_on; dist] THEN
17179     ASM_MESON_TAC[NORM_SUB];
17180     ALL_TAC] THEN
17181   MP_TAC(ISPECL
17182    [`IMAGE (f:num->real^M->real^N) (:num)`;
17183     `s:real^M->bool`]
17184    COMPACT_UNIFORMLY_EQUICONTINUOUS) THEN
17185   REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE; IN_UNIV] THEN
17186   ANTS_TAC THENL
17187    [REWRITE_TAC[dist] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN ASM_MESON_TAC[];
17188     ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(K ALL_TAC o SPEC `x:real^M`)] THEN
17189   REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN
17190   REWRITE_TAC[IMP_IMP; GSYM CONJ_ASSOC; dist] THEN
17191   DISCH_THEN(ASSUME_TAC o ONCE_REWRITE_RULE[NORM_SUB]) THEN
17192   REWRITE_TAC[GSYM dist; UNIFORMLY_CONVERGENT_EQ_CAUCHY] THEN
17193   X_CHOOSE_THEN `r:real^M->bool` STRIP_ASSUME_TAC
17194    (ISPEC `s:real^M->bool` SEPARABLE) THEN
17195   MP_TAC(ISPECL [`f:num->real^M->real^N`; `r:real^M->bool`; `M:real`]
17196         FUNCTION_CONVERGENT_SUBSEQUENCE) THEN
17197   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
17198   MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `k:num->num` THEN
17199   REWRITE_TAC[CONVERGENT_EQ_CAUCHY; cauchy] THEN
17200   DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "*")) THEN
17201   ASM_REWRITE_TAC[] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN
17202   FIRST_X_ASSUM(MP_TAC o SPEC `e / &3`) THEN
17203   ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
17204   DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
17205   FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL]) THEN
17206   DISCH_THEN(MP_TAC o SPEC `IMAGE (\x:real^M. ball(x,d)) r`) THEN
17207   REWRITE_TAC[FORALL_IN_IMAGE; OPEN_BALL] THEN
17208   ONCE_REWRITE_TAC[TAUT `a /\ b /\ c <=> b /\ a /\ c`] THEN
17209   REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE] THEN ANTS_TAC THENL
17210    [MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `closure r:real^M->bool` THEN
17211     ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE] THEN
17212     X_GEN_TAC `x:real^M` THEN DISCH_THEN(MP_TAC o SPEC `d:real`) THEN
17213     ASM_REWRITE_TAC[UNIONS_IMAGE; IN_ELIM_THM; IN_BALL];
17214     DISCH_THEN(X_CHOOSE_THEN `t:real^M->bool` STRIP_ASSUME_TAC)] THEN
17215   REMOVE_THEN "*" MP_TAC THEN REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN
17216   GEN_REWRITE_TAC LAND_CONV [SWAP_FORALL_THM] THEN
17217   DISCH_THEN(MP_TAC o SPEC `e / &3`) THEN
17218   ASM_REWRITE_TAC[REAL_ARITH `&0 < e / &3 <=> &0 < e`] THEN
17219   GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN
17220   REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
17221   X_GEN_TAC `M:real^M->num` THEN DISCH_THEN(LABEL_TAC "*") THEN
17222   MP_TAC(ISPECL [`M:real^M->num`; `t:real^M->bool`]
17223     UPPER_BOUND_FINITE_SET) THEN
17224   ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `N:num` THEN
17225   DISCH_TAC THEN
17226   MAP_EVERY X_GEN_TAC [`m:num`; `n:num`; `x:real^M`] THEN STRIP_TAC THEN
17227   UNDISCH_TAC `s SUBSET UNIONS (IMAGE (\x:real^M. ball (x,d)) t)` THEN
17228   REWRITE_TAC[SUBSET; UNIONS_IMAGE; IN_ELIM_THM] THEN
17229   DISCH_THEN(MP_TAC o SPEC `x:real^M`) THEN
17230   ASM_REWRITE_TAC[IN_BALL; LEFT_IMP_EXISTS_THM; dist] THEN
17231   X_GEN_TAC `y:real^M` THEN STRIP_TAC THEN
17232   MATCH_MP_TAC(NORM_ARITH
17233    `norm(f (k(m:num)) y - f (k m) x) < e / &3 /\
17234     norm(f (k n) y - f (k n) x) < e / &3 /\
17235     norm(f (k m) y - f (k n) y) < e / &3
17236     ==> norm(f (k m) x - f (k n) x :real^M) < e`) THEN
17237   ASM_SIMP_TAC[] THEN REMOVE_THEN "*" (MP_TAC o SPEC `y:real^M`) THEN
17238   ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
17239   DISCH_THEN(MP_TAC o SPECL [`m:num`; `n:num`]) THEN
17240   ASM_REWRITE_TAC[dist; GE] THEN ASM_MESON_TAC[SUBSET; LE_TRANS]);;